github.com/sl1pm4t/consul@v1.4.5-0.20190325224627-74c31c540f9c/command/lock/lock_test.go (about)

     1  package lock
     2  
     3  import (
     4  	"io/ioutil"
     5  	"path/filepath"
     6  	"strings"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/hashicorp/consul/agent"
    11  	"github.com/hashicorp/consul/api"
    12  	"github.com/hashicorp/consul/testrpc"
    13  	"github.com/mitchellh/cli"
    14  )
    15  
    16  func argFail(t *testing.T, args []string, expected string) {
    17  	ui := cli.NewMockUi()
    18  	c := New(ui)
    19  	c.flags.SetOutput(ui.ErrorWriter)
    20  	if code := c.Run(args); code != 1 {
    21  		t.Fatalf("expected return code 1, got %d", code)
    22  	}
    23  	if reason := ui.ErrorWriter.String(); !strings.Contains(reason, expected) {
    24  		t.Fatalf("bad reason: got='%s', expected='%s'", reason, expected)
    25  	}
    26  
    27  }
    28  
    29  func TestLockCommand_noTabs(t *testing.T) {
    30  	t.Parallel()
    31  	if strings.ContainsRune(New(cli.NewMockUi()).Help(), '\t') {
    32  		t.Fatal("help has tabs")
    33  	}
    34  }
    35  
    36  func TestLockCommand_BadArgs(t *testing.T) {
    37  	t.Parallel()
    38  	argFail(t, []string{"-try=blah", "test/prefix", "date"}, "invalid duration")
    39  	argFail(t, []string{"-try=-10s", "test/prefix", "date"}, "Timeout must be positive")
    40  	argFail(t, []string{"-monitor-retry=-5", "test/prefix", "date"}, "must be >= 0")
    41  }
    42  
    43  func TestLockCommand(t *testing.T) {
    44  	t.Parallel()
    45  	a := agent.NewTestAgent(t, t.Name(), ``)
    46  	defer a.Shutdown()
    47  
    48  	testrpc.WaitForLeader(t, a.RPC, "dc1")
    49  
    50  	ui := cli.NewMockUi()
    51  	c := New(ui)
    52  
    53  	filePath := filepath.Join(a.Config.DataDir, "test_touch")
    54  	args := []string{"-http-addr=" + a.HTTPAddr(), "test/prefix", "touch", filePath}
    55  
    56  	code := c.Run(args)
    57  	if code != 0 {
    58  		t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
    59  	}
    60  
    61  	// Check for the file
    62  	_, err := ioutil.ReadFile(filePath)
    63  	if err != nil {
    64  		t.Fatalf("err: %v", err)
    65  	}
    66  }
    67  
    68  func TestLockCommand_NoShell(t *testing.T) {
    69  	t.Parallel()
    70  	a := agent.NewTestAgent(t, t.Name(), ``)
    71  	defer a.Shutdown()
    72  
    73  	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
    74  
    75  	ui := cli.NewMockUi()
    76  	c := New(ui)
    77  
    78  	filePath := filepath.Join(a.Config.DataDir, "test_touch")
    79  	args := []string{"-http-addr=" + a.HTTPAddr(), "-shell=false", "test/prefix", "touch", filePath}
    80  
    81  	code := c.Run(args)
    82  	if code != 0 {
    83  		t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
    84  	}
    85  
    86  	// Check for the file
    87  	_, err := ioutil.ReadFile(filePath)
    88  	if err != nil {
    89  		t.Fatalf("err: %v", err)
    90  	}
    91  }
    92  
    93  func TestLockCommand_TryLock(t *testing.T) {
    94  	t.Parallel()
    95  	a := agent.NewTestAgent(t, t.Name(), ``)
    96  	defer a.Shutdown()
    97  
    98  	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
    99  
   100  	ui := cli.NewMockUi()
   101  	c := New(ui)
   102  
   103  	filePath := filepath.Join(a.Config.DataDir, "test_touch")
   104  	args := []string{"-http-addr=" + a.HTTPAddr(), "-try=10s", "test/prefix", "touch", filePath}
   105  
   106  	// Run the command.
   107  	var lu *LockUnlock
   108  	code := c.run(args, &lu)
   109  	if code != 0 {
   110  		t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
   111  	}
   112  	_, err := ioutil.ReadFile(filePath)
   113  	if err != nil {
   114  		t.Fatalf("err: %v", err)
   115  	}
   116  
   117  	// Make sure the try options were set correctly.
   118  	opts, ok := lu.rawOpts.(*api.LockOptions)
   119  	if !ok {
   120  		t.Fatalf("bad type")
   121  	}
   122  	if !opts.LockTryOnce || opts.LockWaitTime != 10*time.Second {
   123  		t.Fatalf("bad: %#v", opts)
   124  	}
   125  }
   126  
   127  func TestLockCommand_TrySemaphore(t *testing.T) {
   128  	t.Parallel()
   129  	a := agent.NewTestAgent(t, t.Name(), ``)
   130  	defer a.Shutdown()
   131  
   132  	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
   133  
   134  	ui := cli.NewMockUi()
   135  	c := New(ui)
   136  
   137  	filePath := filepath.Join(a.Config.DataDir, "test_touch")
   138  	args := []string{"-http-addr=" + a.HTTPAddr(), "-n=3", "-try=10s", "test/prefix", "touch", filePath}
   139  
   140  	// Run the command.
   141  	var lu *LockUnlock
   142  	code := c.run(args, &lu)
   143  	if code != 0 {
   144  		t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
   145  	}
   146  	_, err := ioutil.ReadFile(filePath)
   147  	if err != nil {
   148  		t.Fatalf("err: %v", err)
   149  	}
   150  
   151  	// Make sure the try options were set correctly.
   152  	opts, ok := lu.rawOpts.(*api.SemaphoreOptions)
   153  	if !ok {
   154  		t.Fatalf("bad type")
   155  	}
   156  	if !opts.SemaphoreTryOnce || opts.SemaphoreWaitTime != 10*time.Second {
   157  		t.Fatalf("bad: %#v", opts)
   158  	}
   159  }
   160  
   161  func TestLockCommand_MonitorRetry_Lock_Default(t *testing.T) {
   162  	t.Parallel()
   163  	a := agent.NewTestAgent(t, t.Name(), ``)
   164  	defer a.Shutdown()
   165  
   166  	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
   167  
   168  	ui := cli.NewMockUi()
   169  	c := New(ui)
   170  
   171  	filePath := filepath.Join(a.Config.DataDir, "test_touch")
   172  	args := []string{"-http-addr=" + a.HTTPAddr(), "test/prefix", "touch", filePath}
   173  
   174  	// Run the command.
   175  	var lu *LockUnlock
   176  	code := c.run(args, &lu)
   177  	if code != 0 {
   178  		t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
   179  	}
   180  	_, err := ioutil.ReadFile(filePath)
   181  	if err != nil {
   182  		t.Fatalf("err: %v", err)
   183  	}
   184  
   185  	// Make sure the monitor options were set correctly.
   186  	opts, ok := lu.rawOpts.(*api.LockOptions)
   187  	if !ok {
   188  		t.Fatalf("bad type")
   189  	}
   190  	if opts.MonitorRetries != defaultMonitorRetry ||
   191  		opts.MonitorRetryTime != defaultMonitorRetryTime {
   192  		t.Fatalf("bad: %#v", opts)
   193  	}
   194  }
   195  
   196  func TestLockCommand_MonitorRetry_Semaphore_Default(t *testing.T) {
   197  	t.Parallel()
   198  	a := agent.NewTestAgent(t, t.Name(), ``)
   199  	defer a.Shutdown()
   200  
   201  	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
   202  
   203  	ui := cli.NewMockUi()
   204  	c := New(ui)
   205  
   206  	filePath := filepath.Join(a.Config.DataDir, "test_touch")
   207  	args := []string{"-http-addr=" + a.HTTPAddr(), "-n=3", "test/prefix", "touch", filePath}
   208  
   209  	// Run the command.
   210  	var lu *LockUnlock
   211  	code := c.run(args, &lu)
   212  	if code != 0 {
   213  		t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
   214  	}
   215  	_, err := ioutil.ReadFile(filePath)
   216  	if err != nil {
   217  		t.Fatalf("err: %v", err)
   218  	}
   219  
   220  	// Make sure the monitor options were set correctly.
   221  	opts, ok := lu.rawOpts.(*api.SemaphoreOptions)
   222  	if !ok {
   223  		t.Fatalf("bad type")
   224  	}
   225  	if opts.MonitorRetries != defaultMonitorRetry ||
   226  		opts.MonitorRetryTime != defaultMonitorRetryTime {
   227  		t.Fatalf("bad: %#v", opts)
   228  	}
   229  }
   230  
   231  func TestLockCommand_MonitorRetry_Lock_Arg(t *testing.T) {
   232  	t.Parallel()
   233  	a := agent.NewTestAgent(t, t.Name(), ``)
   234  	defer a.Shutdown()
   235  
   236  	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
   237  
   238  	ui := cli.NewMockUi()
   239  	c := New(ui)
   240  
   241  	filePath := filepath.Join(a.Config.DataDir, "test_touch")
   242  	args := []string{"-http-addr=" + a.HTTPAddr(), "-monitor-retry=9", "test/prefix", "touch", filePath}
   243  
   244  	// Run the command.
   245  	var lu *LockUnlock
   246  	code := c.run(args, &lu)
   247  	if code != 0 {
   248  		t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
   249  	}
   250  	_, err := ioutil.ReadFile(filePath)
   251  	if err != nil {
   252  		t.Fatalf("err: %v", err)
   253  	}
   254  
   255  	// Make sure the monitor options were set correctly.
   256  	opts, ok := lu.rawOpts.(*api.LockOptions)
   257  	if !ok {
   258  		t.Fatalf("bad type")
   259  	}
   260  	if opts.MonitorRetries != 9 ||
   261  		opts.MonitorRetryTime != defaultMonitorRetryTime {
   262  		t.Fatalf("bad: %#v", opts)
   263  	}
   264  }
   265  
   266  func TestLockCommand_MonitorRetry_Semaphore_Arg(t *testing.T) {
   267  	t.Parallel()
   268  	a := agent.NewTestAgent(t, t.Name(), ``)
   269  	defer a.Shutdown()
   270  
   271  	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
   272  
   273  	ui := cli.NewMockUi()
   274  	c := New(ui)
   275  
   276  	filePath := filepath.Join(a.Config.DataDir, "test_touch")
   277  	args := []string{"-http-addr=" + a.HTTPAddr(), "-n=3", "-monitor-retry=9", "test/prefix", "touch", filePath}
   278  
   279  	// Run the command.
   280  	var lu *LockUnlock
   281  	code := c.run(args, &lu)
   282  	if code != 0 {
   283  		t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
   284  	}
   285  	_, err := ioutil.ReadFile(filePath)
   286  	if err != nil {
   287  		t.Fatalf("err: %v", err)
   288  	}
   289  
   290  	// Make sure the monitor options were set correctly.
   291  	opts, ok := lu.rawOpts.(*api.SemaphoreOptions)
   292  	if !ok {
   293  		t.Fatalf("bad type")
   294  	}
   295  	if opts.MonitorRetries != 9 ||
   296  		opts.MonitorRetryTime != defaultMonitorRetryTime {
   297  		t.Fatalf("bad: %#v", opts)
   298  	}
   299  }
   300  
   301  func TestLockCommand_ChildExitCode(t *testing.T) {
   302  	t.Parallel()
   303  	a := agent.NewTestAgent(t, t.Name(), ``)
   304  	defer a.Shutdown()
   305  
   306  	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
   307  
   308  	tt := []struct {
   309  		name string
   310  		args []string
   311  		want int
   312  	}{
   313  		{
   314  			name: "clean exit",
   315  			args: []string{"-http-addr=" + a.HTTPAddr(), "-child-exit-code", "test/prefix", "sh", "-c", "exit", "0"},
   316  			want: 0,
   317  		},
   318  		{
   319  			name: "error exit",
   320  			args: []string{"-http-addr=" + a.HTTPAddr(), "-child-exit-code", "test/prefix", "exit", "1"},
   321  			want: 2,
   322  		},
   323  		{
   324  			name: "not propagated",
   325  			args: []string{"-http-addr=" + a.HTTPAddr(), "test/prefix", "sh", "-c", "exit", "1"},
   326  			want: 0,
   327  		},
   328  	}
   329  
   330  	for _, tc := range tt {
   331  		t.Run(tc.name, func(t *testing.T) {
   332  			ui := cli.NewMockUi()
   333  			c := New(ui)
   334  
   335  			if got := c.Run(tc.args); got != tc.want {
   336  				t.Fatalf("got %d want %d", got, tc.want)
   337  			}
   338  		})
   339  	}
   340  }