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