github.com/damirazo/docker@v1.9.0/pkg/integration/utils_test.go (about)

     1  package integration
     2  
     3  import (
     4  	"io"
     5  	"io/ioutil"
     6  	"os"
     7  	"os/exec"
     8  	"path"
     9  	"runtime"
    10  	"strings"
    11  	"testing"
    12  	"time"
    13  )
    14  
    15  func TestIsKilledFalseWithNonKilledProcess(t *testing.T) {
    16  	lsCmd := exec.Command("ls")
    17  	lsCmd.Start()
    18  	// Wait for it to finish
    19  	err := lsCmd.Wait()
    20  	if IsKilled(err) {
    21  		t.Fatalf("Expected the ls command to not be killed, was.")
    22  	}
    23  }
    24  
    25  func TestIsKilledTrueWithKilledProcess(t *testing.T) {
    26  	longCmd := exec.Command("top")
    27  	// Start a command
    28  	longCmd.Start()
    29  	// Capture the error when *dying*
    30  	done := make(chan error, 1)
    31  	go func() {
    32  		done <- longCmd.Wait()
    33  	}()
    34  	// Then kill it
    35  	longCmd.Process.Kill()
    36  	// Get the error
    37  	err := <-done
    38  	if !IsKilled(err) {
    39  		t.Fatalf("Expected the command to be killed, was not.")
    40  	}
    41  }
    42  
    43  func TestRunCommandWithOutput(t *testing.T) {
    44  	echoHelloWorldCmd := exec.Command("echo", "hello", "world")
    45  	out, exitCode, err := RunCommandWithOutput(echoHelloWorldCmd)
    46  	expected := "hello world\n"
    47  	if out != expected || exitCode != 0 || err != nil {
    48  		t.Fatalf("Expected command to output %s, got %s, %v with exitCode %v", expected, out, err, exitCode)
    49  	}
    50  }
    51  
    52  func TestRunCommandWithOutputError(t *testing.T) {
    53  	cmd := exec.Command("doesnotexists")
    54  	out, exitCode, err := RunCommandWithOutput(cmd)
    55  	expectedError := `exec: "doesnotexists": executable file not found in $PATH`
    56  	if out != "" || exitCode != 127 || err == nil || err.Error() != expectedError {
    57  		t.Fatalf("Expected command to output %s, got %s, %v with exitCode %v", expectedError, out, err, exitCode)
    58  	}
    59  
    60  	wrongLsCmd := exec.Command("ls", "-z")
    61  	expected := `ls: invalid option -- 'z'
    62  Try 'ls --help' for more information.
    63  `
    64  	out, exitCode, err = RunCommandWithOutput(wrongLsCmd)
    65  
    66  	if out != expected || exitCode != 2 || err == nil || err.Error() != "exit status 2" {
    67  		t.Fatalf("Expected command to output %s, got out:%s, err:%v with exitCode %v", expected, out, err, exitCode)
    68  	}
    69  }
    70  
    71  func TestRunCommandWithStdoutStderr(t *testing.T) {
    72  	echoHelloWorldCmd := exec.Command("echo", "hello", "world")
    73  	stdout, stderr, exitCode, err := RunCommandWithStdoutStderr(echoHelloWorldCmd)
    74  	expected := "hello world\n"
    75  	if stdout != expected || stderr != "" || exitCode != 0 || err != nil {
    76  		t.Fatalf("Expected command to output %s, got stdout:%s, stderr:%s, err:%v with exitCode %v", expected, stdout, stderr, err, exitCode)
    77  	}
    78  }
    79  
    80  func TestRunCommandWithStdoutStderrError(t *testing.T) {
    81  	cmd := exec.Command("doesnotexists")
    82  	stdout, stderr, exitCode, err := RunCommandWithStdoutStderr(cmd)
    83  	expectedError := `exec: "doesnotexists": executable file not found in $PATH`
    84  	if stdout != "" || stderr != "" || exitCode != 127 || err == nil || err.Error() != expectedError {
    85  		t.Fatalf("Expected command to output out:%s, stderr:%s, got stdout:%s, stderr:%s, err:%v with exitCode %v", "", "", stdout, stderr, err, exitCode)
    86  	}
    87  
    88  	wrongLsCmd := exec.Command("ls", "-z")
    89  	expected := `ls: invalid option -- 'z'
    90  Try 'ls --help' for more information.
    91  `
    92  
    93  	stdout, stderr, exitCode, err = RunCommandWithStdoutStderr(wrongLsCmd)
    94  	if stdout != "" && stderr != expected || exitCode != 2 || err == nil || err.Error() != "exit status 2" {
    95  		t.Fatalf("Expected command to output out:%s, stderr:%s, got stdout:%s, stderr:%s, err:%v with exitCode %v", "", expectedError, stdout, stderr, err, exitCode)
    96  	}
    97  }
    98  
    99  func TestRunCommandWithOutputForDurationFinished(t *testing.T) {
   100  	cmd := exec.Command("ls")
   101  	out, exitCode, timedOut, err := RunCommandWithOutputForDuration(cmd, 50*time.Millisecond)
   102  	if out == "" || exitCode != 0 || timedOut || err != nil {
   103  		t.Fatalf("Expected the command to run for less 50 milliseconds and thus not time out, but did not : out:[%s], exitCode:[%d], timedOut:[%v], err:[%v]", out, exitCode, timedOut, err)
   104  	}
   105  }
   106  
   107  func TestRunCommandWithOutputForDurationKilled(t *testing.T) {
   108  	cmd := exec.Command("sh", "-c", "while true ; do echo 1 ; sleep .1 ; done")
   109  	out, exitCode, timedOut, err := RunCommandWithOutputForDuration(cmd, 500*time.Millisecond)
   110  	ones := strings.Split(out, "\n")
   111  	if len(ones) != 6 || exitCode != 0 || !timedOut || err != nil {
   112  		t.Fatalf("Expected the command to run for 500 milliseconds (and thus print six lines (five with 1, one empty) and time out, but did not : out:[%s], exitCode:%d, timedOut:%v, err:%v", out, exitCode, timedOut, err)
   113  	}
   114  }
   115  
   116  func TestRunCommandWithOutputForDurationErrors(t *testing.T) {
   117  	cmd := exec.Command("ls")
   118  	cmd.Stdout = os.Stdout
   119  	if _, _, _, err := RunCommandWithOutputForDuration(cmd, 1*time.Millisecond); err == nil || err.Error() != "cmd.Stdout already set" {
   120  		t.Fatalf("Expected an error as cmd.Stdout was already set, did not (err:%s).", err)
   121  	}
   122  	cmd = exec.Command("ls")
   123  	cmd.Stderr = os.Stderr
   124  	if _, _, _, err := RunCommandWithOutputForDuration(cmd, 1*time.Millisecond); err == nil || err.Error() != "cmd.Stderr already set" {
   125  		t.Fatalf("Expected an error as cmd.Stderr was already set, did not (err:%s).", err)
   126  	}
   127  }
   128  
   129  func TestRunCommandWithOutputAndTimeoutFinished(t *testing.T) {
   130  	cmd := exec.Command("ls")
   131  	out, exitCode, err := RunCommandWithOutputAndTimeout(cmd, 50*time.Millisecond)
   132  	if out == "" || exitCode != 0 || err != nil {
   133  		t.Fatalf("Expected the command to run for less 50 milliseconds and thus not time out, but did not : out:[%s], exitCode:[%d], err:[%v]", out, exitCode, err)
   134  	}
   135  }
   136  
   137  func TestRunCommandWithOutputAndTimeoutKilled(t *testing.T) {
   138  	cmd := exec.Command("sh", "-c", "while true ; do echo 1 ; sleep .1 ; done")
   139  	out, exitCode, err := RunCommandWithOutputAndTimeout(cmd, 500*time.Millisecond)
   140  	ones := strings.Split(out, "\n")
   141  	if len(ones) != 6 || exitCode != 0 || err == nil || err.Error() != "command timed out" {
   142  		t.Fatalf("Expected the command to run for 500 milliseconds (and thus print six lines (five with 1, one empty) and time out with an error 'command timed out', but did not : out:[%s], exitCode:%d, err:%v", out, exitCode, err)
   143  	}
   144  }
   145  
   146  func TestRunCommandWithOutputAndTimeoutErrors(t *testing.T) {
   147  	cmd := exec.Command("ls")
   148  	cmd.Stdout = os.Stdout
   149  	if _, _, err := RunCommandWithOutputAndTimeout(cmd, 1*time.Millisecond); err == nil || err.Error() != "cmd.Stdout already set" {
   150  		t.Fatalf("Expected an error as cmd.Stdout was already set, did not (err:%s).", err)
   151  	}
   152  	cmd = exec.Command("ls")
   153  	cmd.Stderr = os.Stderr
   154  	if _, _, err := RunCommandWithOutputAndTimeout(cmd, 1*time.Millisecond); err == nil || err.Error() != "cmd.Stderr already set" {
   155  		t.Fatalf("Expected an error as cmd.Stderr was already set, did not (err:%s).", err)
   156  	}
   157  }
   158  
   159  func TestRunCommand(t *testing.T) {
   160  	lsCmd := exec.Command("ls")
   161  	exitCode, err := RunCommand(lsCmd)
   162  	if exitCode != 0 || err != nil {
   163  		t.Fatalf("Expected runCommand to run the command successfully, got: exitCode:%d, err:%v", exitCode, err)
   164  	}
   165  
   166  	var expectedError string
   167  
   168  	exitCode, err = RunCommand(exec.Command("doesnotexists"))
   169  	expectedError = `exec: "doesnotexists": executable file not found in $PATH`
   170  	if exitCode != 127 || err == nil || err.Error() != expectedError {
   171  		t.Fatalf("Expected runCommand to run the command successfully, got: exitCode:%d, err:%v", exitCode, err)
   172  	}
   173  	wrongLsCmd := exec.Command("ls", "-z")
   174  	expected := 2
   175  	expectedError = `exit status 2`
   176  	exitCode, err = RunCommand(wrongLsCmd)
   177  	if exitCode != expected || err == nil || err.Error() != expectedError {
   178  		t.Fatalf("Expected runCommand to run the command successfully, got: exitCode:%d, err:%v", exitCode, err)
   179  	}
   180  }
   181  
   182  func TestRunCommandPipelineWithOutputWithNotEnoughCmds(t *testing.T) {
   183  	_, _, err := RunCommandPipelineWithOutput(exec.Command("ls"))
   184  	expectedError := "pipeline does not have multiple cmds"
   185  	if err == nil || err.Error() != expectedError {
   186  		t.Fatalf("Expected an error with %s, got err:%s", expectedError, err)
   187  	}
   188  }
   189  
   190  func TestRunCommandPipelineWithOutputErrors(t *testing.T) {
   191  	cmd1 := exec.Command("ls")
   192  	cmd1.Stdout = os.Stdout
   193  	cmd2 := exec.Command("anything really")
   194  	_, _, err := RunCommandPipelineWithOutput(cmd1, cmd2)
   195  	if err == nil || err.Error() != "cannot set stdout pipe for anything really: exec: Stdout already set" {
   196  		t.Fatalf("Expected an error, got %v", err)
   197  	}
   198  
   199  	cmdWithError := exec.Command("doesnotexists")
   200  	cmdCat := exec.Command("cat")
   201  	_, _, err = RunCommandPipelineWithOutput(cmdWithError, cmdCat)
   202  	if err == nil || err.Error() != `starting doesnotexists failed with error: exec: "doesnotexists": executable file not found in $PATH` {
   203  		t.Fatalf("Expected an error, got %v", err)
   204  	}
   205  }
   206  
   207  func TestRunCommandPipelineWithOutput(t *testing.T) {
   208  	cmds := []*exec.Cmd{
   209  		// Print 2 characters
   210  		exec.Command("echo", "-n", "11"),
   211  		// Count the number or char from stdin (previous command)
   212  		exec.Command("wc", "-m"),
   213  	}
   214  	out, exitCode, err := RunCommandPipelineWithOutput(cmds...)
   215  	expectedOutput := "2\n"
   216  	if out != expectedOutput || exitCode != 0 || err != nil {
   217  		t.Fatalf("Expected %s for commands %v, got out:%s, exitCode:%d, err:%v", expectedOutput, cmds, out, exitCode, err)
   218  	}
   219  }
   220  
   221  // Simple simple test as it is just a passthrough for json.Unmarshal
   222  func TestUnmarshalJSON(t *testing.T) {
   223  	emptyResult := struct{}{}
   224  	if err := UnmarshalJSON([]byte(""), &emptyResult); err == nil {
   225  		t.Fatalf("Expected an error, got nothing")
   226  	}
   227  	result := struct{ Name string }{}
   228  	if err := UnmarshalJSON([]byte(`{"name": "name"}`), &result); err != nil {
   229  		t.Fatal(err)
   230  	}
   231  	if result.Name != "name" {
   232  		t.Fatalf("Expected result.name to be 'name', was '%s'", result.Name)
   233  	}
   234  }
   235  
   236  func TestConvertSliceOfStringsToMap(t *testing.T) {
   237  	input := []string{"a", "b"}
   238  	actual := ConvertSliceOfStringsToMap(input)
   239  	for _, key := range input {
   240  		if _, ok := actual[key]; !ok {
   241  			t.Fatalf("Expected output to contains key %s, did not: %v", key, actual)
   242  		}
   243  	}
   244  }
   245  
   246  func TestCompareDirectoryEntries(t *testing.T) {
   247  	tmpFolder, err := ioutil.TempDir("", "integration-cli-utils-compare-directories")
   248  	if err != nil {
   249  		t.Fatal(err)
   250  	}
   251  	defer os.RemoveAll(tmpFolder)
   252  
   253  	file1 := path.Join(tmpFolder, "file1")
   254  	file2 := path.Join(tmpFolder, "file2")
   255  	os.Create(file1)
   256  	os.Create(file2)
   257  
   258  	fi1, err := os.Stat(file1)
   259  	if err != nil {
   260  		t.Fatal(err)
   261  	}
   262  	fi1bis, err := os.Stat(file1)
   263  	if err != nil {
   264  		t.Fatal(err)
   265  	}
   266  	fi2, err := os.Stat(file2)
   267  	if err != nil {
   268  		t.Fatal(err)
   269  	}
   270  
   271  	cases := []struct {
   272  		e1          []os.FileInfo
   273  		e2          []os.FileInfo
   274  		shouldError bool
   275  	}{
   276  		// Empty directories
   277  		{
   278  			[]os.FileInfo{},
   279  			[]os.FileInfo{},
   280  			false,
   281  		},
   282  		// Same FileInfos
   283  		{
   284  			[]os.FileInfo{fi1},
   285  			[]os.FileInfo{fi1},
   286  			false,
   287  		},
   288  		// Different FileInfos but same names
   289  		{
   290  			[]os.FileInfo{fi1},
   291  			[]os.FileInfo{fi1bis},
   292  			false,
   293  		},
   294  		// Different FileInfos, different names
   295  		{
   296  			[]os.FileInfo{fi1},
   297  			[]os.FileInfo{fi2},
   298  			true,
   299  		},
   300  	}
   301  	for _, elt := range cases {
   302  		err := CompareDirectoryEntries(elt.e1, elt.e2)
   303  		if elt.shouldError && err == nil {
   304  			t.Fatalf("Should have return an error, did not with %v and %v", elt.e1, elt.e2)
   305  		}
   306  		if !elt.shouldError && err != nil {
   307  			t.Fatalf("Should have not returned an error, but did : %v with %v and %v", err, elt.e1, elt.e2)
   308  		}
   309  	}
   310  }
   311  
   312  // FIXME make an "unhappy path" test for ListTar without "panicing" :-)
   313  func TestListTar(t *testing.T) {
   314  	tmpFolder, err := ioutil.TempDir("", "integration-cli-utils-list-tar")
   315  	if err != nil {
   316  		t.Fatal(err)
   317  	}
   318  	defer os.RemoveAll(tmpFolder)
   319  
   320  	// Let's create a Tar file
   321  	srcFile := path.Join(tmpFolder, "src")
   322  	tarFile := path.Join(tmpFolder, "src.tar")
   323  	os.Create(srcFile)
   324  	cmd := exec.Command("/bin/sh", "-c", "tar cf "+tarFile+" "+srcFile)
   325  	_, err = cmd.CombinedOutput()
   326  	if err != nil {
   327  		t.Fatal(err)
   328  	}
   329  
   330  	reader, err := os.Open(tarFile)
   331  	if err != nil {
   332  		t.Fatal(err)
   333  	}
   334  	defer reader.Close()
   335  
   336  	entries, err := ListTar(reader)
   337  	if err != nil {
   338  		t.Fatal(err)
   339  	}
   340  	if len(entries) != 1 && entries[0] != "src" {
   341  		t.Fatalf("Expected a tar file with 1 entry (%s), got %v", srcFile, entries)
   342  	}
   343  }
   344  
   345  func TestRandomTmpDirPath(t *testing.T) {
   346  	path := RandomTmpDirPath("something", runtime.GOOS)
   347  
   348  	prefix := "/tmp/something"
   349  	if runtime.GOOS == "windows" {
   350  		prefix = os.Getenv("TEMP") + `\something`
   351  	}
   352  	expectedSize := len(prefix) + 11
   353  
   354  	if !strings.HasPrefix(path, prefix) {
   355  		t.Fatalf("Expected generated path to have '%s' as prefix, got %s'", prefix, path)
   356  	}
   357  	if len(path) != expectedSize {
   358  		t.Fatalf("Expected generated path to be %d, got %d", expectedSize, len(path))
   359  	}
   360  }
   361  
   362  func TestConsumeWithSpeed(t *testing.T) {
   363  	reader := strings.NewReader("1234567890")
   364  	chunksize := 2
   365  
   366  	bytes1, err := ConsumeWithSpeed(reader, chunksize, 1*time.Millisecond, nil)
   367  	if err != nil {
   368  		t.Fatal(err)
   369  	}
   370  
   371  	if bytes1 != 10 {
   372  		t.Fatalf("Expected to have read 10 bytes, got %d", bytes1)
   373  	}
   374  
   375  }
   376  
   377  func TestConsumeWithSpeedWithStop(t *testing.T) {
   378  	reader := strings.NewReader("1234567890")
   379  	chunksize := 2
   380  
   381  	stopIt := make(chan bool)
   382  
   383  	go func() {
   384  		time.Sleep(1 * time.Millisecond)
   385  		stopIt <- true
   386  	}()
   387  
   388  	bytes1, err := ConsumeWithSpeed(reader, chunksize, 2*time.Millisecond, stopIt)
   389  	if err != nil {
   390  		t.Fatal(err)
   391  	}
   392  
   393  	if bytes1 != 2 {
   394  		t.Fatalf("Expected to have read 2 bytes, got %d", bytes1)
   395  	}
   396  
   397  }
   398  
   399  func TestParseCgroupPathsEmpty(t *testing.T) {
   400  	cgroupMap := ParseCgroupPaths("")
   401  	if len(cgroupMap) != 0 {
   402  		t.Fatalf("Expected an empty map, got %v", cgroupMap)
   403  	}
   404  	cgroupMap = ParseCgroupPaths("\n")
   405  	if len(cgroupMap) != 0 {
   406  		t.Fatalf("Expected an empty map, got %v", cgroupMap)
   407  	}
   408  	cgroupMap = ParseCgroupPaths("something:else\nagain:here")
   409  	if len(cgroupMap) != 0 {
   410  		t.Fatalf("Expected an empty map, got %v", cgroupMap)
   411  	}
   412  }
   413  
   414  func TestParseCgroupPaths(t *testing.T) {
   415  	cgroupMap := ParseCgroupPaths("2:memory:/a\n1:cpuset:/b")
   416  	if len(cgroupMap) != 2 {
   417  		t.Fatalf("Expected a map with 2 entries, got %v", cgroupMap)
   418  	}
   419  	if value, ok := cgroupMap["memory"]; !ok || value != "/a" {
   420  		t.Fatalf("Expected cgroupMap to contains an entry for 'memory' with value '/a', got %v", cgroupMap)
   421  	}
   422  	if value, ok := cgroupMap["cpuset"]; !ok || value != "/b" {
   423  		t.Fatalf("Expected cgroupMap to contains an entry for 'cpuset' with value '/b', got %v", cgroupMap)
   424  	}
   425  }
   426  
   427  func TestChannelBufferTimeout(t *testing.T) {
   428  	expected := "11"
   429  
   430  	buf := &ChannelBuffer{make(chan []byte, 1)}
   431  	defer buf.Close()
   432  
   433  	go func() {
   434  		time.Sleep(100 * time.Millisecond)
   435  		io.Copy(buf, strings.NewReader(expected))
   436  	}()
   437  
   438  	// Wait long enough
   439  	b := make([]byte, 2)
   440  	_, err := buf.ReadTimeout(b, 50*time.Millisecond)
   441  	if err == nil && err.Error() != "timeout reading from channel" {
   442  		t.Fatalf("Expected an error, got %s", err)
   443  	}
   444  
   445  	// Wait for the end :)
   446  	time.Sleep(150 * time.Millisecond)
   447  }
   448  
   449  func TestChannelBuffer(t *testing.T) {
   450  	expected := "11"
   451  
   452  	buf := &ChannelBuffer{make(chan []byte, 1)}
   453  	defer buf.Close()
   454  
   455  	go func() {
   456  		time.Sleep(100 * time.Millisecond)
   457  		io.Copy(buf, strings.NewReader(expected))
   458  	}()
   459  
   460  	// Wait long enough
   461  	b := make([]byte, 2)
   462  	_, err := buf.ReadTimeout(b, 200*time.Millisecond)
   463  	if err != nil {
   464  		t.Fatal(err)
   465  	}
   466  
   467  	if string(b) != expected {
   468  		t.Fatalf("Expected '%s', got '%s'", expected, string(b))
   469  	}
   470  }
   471  
   472  // FIXME doesn't work
   473  // func TestRunAtDifferentDate(t *testing.T) {
   474  // 	var date string
   475  
   476  // 	// Layout for date. MMDDhhmmYYYY
   477  // 	const timeLayout = "20060102"
   478  // 	expectedDate := "20100201"
   479  // 	theDate, err := time.Parse(timeLayout, expectedDate)
   480  // 	if err != nil {
   481  // 		t.Fatal(err)
   482  // 	}
   483  
   484  // 	RunAtDifferentDate(theDate, func() {
   485  // 		cmd := exec.Command("date", "+%Y%M%d")
   486  // 		out, err := cmd.Output()
   487  // 		if err != nil {
   488  // 			t.Fatal(err)
   489  // 		}
   490  // 		date = string(out)
   491  // 	})
   492  // }