github.com/hms58/moby@v1.13.1/pkg/integration/utils_test.go (about)

     1  package integration
     2  
     3  import (
     4  	"io"
     5  	"io/ioutil"
     6  	"os"
     7  	"os/exec"
     8  	"path/filepath"
     9  	"runtime"
    10  	"strings"
    11  	"testing"
    12  	"time"
    13  )
    14  
    15  func TestIsKilledFalseWithNonKilledProcess(t *testing.T) {
    16  	var lsCmd *exec.Cmd
    17  	if runtime.GOOS != "windows" {
    18  		lsCmd = exec.Command("ls")
    19  	} else {
    20  		lsCmd = exec.Command("cmd", "/c", "dir")
    21  	}
    22  
    23  	err := lsCmd.Run()
    24  	if IsKilled(err) {
    25  		t.Fatalf("Expected the ls command to not be killed, was.")
    26  	}
    27  }
    28  
    29  func TestIsKilledTrueWithKilledProcess(t *testing.T) {
    30  	var longCmd *exec.Cmd
    31  	if runtime.GOOS != "windows" {
    32  		longCmd = exec.Command("top")
    33  	} else {
    34  		longCmd = exec.Command("powershell", "while ($true) { sleep 1 }")
    35  	}
    36  
    37  	// Start a command
    38  	err := longCmd.Start()
    39  	if err != nil {
    40  		t.Fatal(err)
    41  	}
    42  	// Capture the error when *dying*
    43  	done := make(chan error, 1)
    44  	go func() {
    45  		done <- longCmd.Wait()
    46  	}()
    47  	// Then kill it
    48  	longCmd.Process.Kill()
    49  	// Get the error
    50  	err = <-done
    51  	if !IsKilled(err) {
    52  		t.Fatalf("Expected the command to be killed, was not.")
    53  	}
    54  }
    55  
    56  func TestRunCommandPipelineWithOutputWithNotEnoughCmds(t *testing.T) {
    57  	_, _, err := RunCommandPipelineWithOutput(exec.Command("ls"))
    58  	expectedError := "pipeline does not have multiple cmds"
    59  	if err == nil || err.Error() != expectedError {
    60  		t.Fatalf("Expected an error with %s, got err:%s", expectedError, err)
    61  	}
    62  }
    63  
    64  func TestRunCommandPipelineWithOutputErrors(t *testing.T) {
    65  	p := "$PATH"
    66  	if runtime.GOOS == "windows" {
    67  		p = "%PATH%"
    68  	}
    69  	cmd1 := exec.Command("ls")
    70  	cmd1.Stdout = os.Stdout
    71  	cmd2 := exec.Command("anything really")
    72  	_, _, err := RunCommandPipelineWithOutput(cmd1, cmd2)
    73  	if err == nil || err.Error() != "cannot set stdout pipe for anything really: exec: Stdout already set" {
    74  		t.Fatalf("Expected an error, got %v", err)
    75  	}
    76  
    77  	cmdWithError := exec.Command("doesnotexists")
    78  	cmdCat := exec.Command("cat")
    79  	_, _, err = RunCommandPipelineWithOutput(cmdWithError, cmdCat)
    80  	if err == nil || err.Error() != `starting doesnotexists failed with error: exec: "doesnotexists": executable file not found in `+p {
    81  		t.Fatalf("Expected an error, got %v", err)
    82  	}
    83  }
    84  
    85  func TestRunCommandPipelineWithOutput(t *testing.T) {
    86  	//TODO: Should run on Solaris
    87  	if runtime.GOOS == "solaris" {
    88  		t.Skip()
    89  	}
    90  	cmds := []*exec.Cmd{
    91  		// Print 2 characters
    92  		exec.Command("echo", "-n", "11"),
    93  		// Count the number or char from stdin (previous command)
    94  		exec.Command("wc", "-m"),
    95  	}
    96  	out, exitCode, err := RunCommandPipelineWithOutput(cmds...)
    97  	expectedOutput := "2\n"
    98  	if out != expectedOutput || exitCode != 0 || err != nil {
    99  		t.Fatalf("Expected %s for commands %v, got out:%s, exitCode:%d, err:%v", expectedOutput, cmds, out, exitCode, err)
   100  	}
   101  }
   102  
   103  func TestConvertSliceOfStringsToMap(t *testing.T) {
   104  	input := []string{"a", "b"}
   105  	actual := ConvertSliceOfStringsToMap(input)
   106  	for _, key := range input {
   107  		if _, ok := actual[key]; !ok {
   108  			t.Fatalf("Expected output to contains key %s, did not: %v", key, actual)
   109  		}
   110  	}
   111  }
   112  
   113  func TestCompareDirectoryEntries(t *testing.T) {
   114  	tmpFolder, err := ioutil.TempDir("", "integration-cli-utils-compare-directories")
   115  	if err != nil {
   116  		t.Fatal(err)
   117  	}
   118  	defer os.RemoveAll(tmpFolder)
   119  
   120  	file1 := filepath.Join(tmpFolder, "file1")
   121  	file2 := filepath.Join(tmpFolder, "file2")
   122  	os.Create(file1)
   123  	os.Create(file2)
   124  
   125  	fi1, err := os.Stat(file1)
   126  	if err != nil {
   127  		t.Fatal(err)
   128  	}
   129  	fi1bis, err := os.Stat(file1)
   130  	if err != nil {
   131  		t.Fatal(err)
   132  	}
   133  	fi2, err := os.Stat(file2)
   134  	if err != nil {
   135  		t.Fatal(err)
   136  	}
   137  
   138  	cases := []struct {
   139  		e1          []os.FileInfo
   140  		e2          []os.FileInfo
   141  		shouldError bool
   142  	}{
   143  		// Empty directories
   144  		{
   145  			[]os.FileInfo{},
   146  			[]os.FileInfo{},
   147  			false,
   148  		},
   149  		// Same FileInfos
   150  		{
   151  			[]os.FileInfo{fi1},
   152  			[]os.FileInfo{fi1},
   153  			false,
   154  		},
   155  		// Different FileInfos but same names
   156  		{
   157  			[]os.FileInfo{fi1},
   158  			[]os.FileInfo{fi1bis},
   159  			false,
   160  		},
   161  		// Different FileInfos, different names
   162  		{
   163  			[]os.FileInfo{fi1},
   164  			[]os.FileInfo{fi2},
   165  			true,
   166  		},
   167  	}
   168  	for _, elt := range cases {
   169  		err := CompareDirectoryEntries(elt.e1, elt.e2)
   170  		if elt.shouldError && err == nil {
   171  			t.Fatalf("Should have return an error, did not with %v and %v", elt.e1, elt.e2)
   172  		}
   173  		if !elt.shouldError && err != nil {
   174  			t.Fatalf("Should have not returned an error, but did : %v with %v and %v", err, elt.e1, elt.e2)
   175  		}
   176  	}
   177  }
   178  
   179  // FIXME make an "unhappy path" test for ListTar without "panicking" :-)
   180  func TestListTar(t *testing.T) {
   181  	// TODO Windows: Figure out why this fails. Should be portable.
   182  	if runtime.GOOS == "windows" {
   183  		t.Skip("Failing on Windows - needs further investigation")
   184  	}
   185  	tmpFolder, err := ioutil.TempDir("", "integration-cli-utils-list-tar")
   186  	if err != nil {
   187  		t.Fatal(err)
   188  	}
   189  	defer os.RemoveAll(tmpFolder)
   190  
   191  	// Let's create a Tar file
   192  	srcFile := filepath.Join(tmpFolder, "src")
   193  	tarFile := filepath.Join(tmpFolder, "src.tar")
   194  	os.Create(srcFile)
   195  	cmd := exec.Command("sh", "-c", "tar cf "+tarFile+" "+srcFile)
   196  	_, err = cmd.CombinedOutput()
   197  	if err != nil {
   198  		t.Fatal(err)
   199  	}
   200  
   201  	reader, err := os.Open(tarFile)
   202  	if err != nil {
   203  		t.Fatal(err)
   204  	}
   205  	defer reader.Close()
   206  
   207  	entries, err := ListTar(reader)
   208  	if err != nil {
   209  		t.Fatal(err)
   210  	}
   211  	if len(entries) != 1 && entries[0] != "src" {
   212  		t.Fatalf("Expected a tar file with 1 entry (%s), got %v", srcFile, entries)
   213  	}
   214  }
   215  
   216  func TestRandomTmpDirPath(t *testing.T) {
   217  	path := RandomTmpDirPath("something", runtime.GOOS)
   218  
   219  	prefix := "/tmp/something"
   220  	if runtime.GOOS == "windows" {
   221  		prefix = os.Getenv("TEMP") + `\something`
   222  	}
   223  	expectedSize := len(prefix) + 11
   224  
   225  	if !strings.HasPrefix(path, prefix) {
   226  		t.Fatalf("Expected generated path to have '%s' as prefix, got %s'", prefix, path)
   227  	}
   228  	if len(path) != expectedSize {
   229  		t.Fatalf("Expected generated path to be %d, got %d", expectedSize, len(path))
   230  	}
   231  }
   232  
   233  func TestConsumeWithSpeed(t *testing.T) {
   234  	reader := strings.NewReader("1234567890")
   235  	chunksize := 2
   236  
   237  	bytes1, err := ConsumeWithSpeed(reader, chunksize, 1*time.Second, nil)
   238  	if err != nil {
   239  		t.Fatal(err)
   240  	}
   241  
   242  	if bytes1 != 10 {
   243  		t.Fatalf("Expected to have read 10 bytes, got %d", bytes1)
   244  	}
   245  
   246  }
   247  
   248  func TestConsumeWithSpeedWithStop(t *testing.T) {
   249  	reader := strings.NewReader("1234567890")
   250  	chunksize := 2
   251  
   252  	stopIt := make(chan bool)
   253  
   254  	go func() {
   255  		time.Sleep(1 * time.Millisecond)
   256  		stopIt <- true
   257  	}()
   258  
   259  	bytes1, err := ConsumeWithSpeed(reader, chunksize, 20*time.Millisecond, stopIt)
   260  	if err != nil {
   261  		t.Fatal(err)
   262  	}
   263  
   264  	if bytes1 != 2 {
   265  		t.Fatalf("Expected to have read 2 bytes, got %d", bytes1)
   266  	}
   267  
   268  }
   269  
   270  func TestParseCgroupPathsEmpty(t *testing.T) {
   271  	cgroupMap := ParseCgroupPaths("")
   272  	if len(cgroupMap) != 0 {
   273  		t.Fatalf("Expected an empty map, got %v", cgroupMap)
   274  	}
   275  	cgroupMap = ParseCgroupPaths("\n")
   276  	if len(cgroupMap) != 0 {
   277  		t.Fatalf("Expected an empty map, got %v", cgroupMap)
   278  	}
   279  	cgroupMap = ParseCgroupPaths("something:else\nagain:here")
   280  	if len(cgroupMap) != 0 {
   281  		t.Fatalf("Expected an empty map, got %v", cgroupMap)
   282  	}
   283  }
   284  
   285  func TestParseCgroupPaths(t *testing.T) {
   286  	cgroupMap := ParseCgroupPaths("2:memory:/a\n1:cpuset:/b")
   287  	if len(cgroupMap) != 2 {
   288  		t.Fatalf("Expected a map with 2 entries, got %v", cgroupMap)
   289  	}
   290  	if value, ok := cgroupMap["memory"]; !ok || value != "/a" {
   291  		t.Fatalf("Expected cgroupMap to contains an entry for 'memory' with value '/a', got %v", cgroupMap)
   292  	}
   293  	if value, ok := cgroupMap["cpuset"]; !ok || value != "/b" {
   294  		t.Fatalf("Expected cgroupMap to contains an entry for 'cpuset' with value '/b', got %v", cgroupMap)
   295  	}
   296  }
   297  
   298  func TestChannelBufferTimeout(t *testing.T) {
   299  	expected := "11"
   300  
   301  	buf := &ChannelBuffer{make(chan []byte, 1)}
   302  	defer buf.Close()
   303  
   304  	done := make(chan struct{}, 1)
   305  	go func() {
   306  		time.Sleep(100 * time.Millisecond)
   307  		io.Copy(buf, strings.NewReader(expected))
   308  		done <- struct{}{}
   309  	}()
   310  
   311  	// Wait long enough
   312  	b := make([]byte, 2)
   313  	_, err := buf.ReadTimeout(b, 50*time.Millisecond)
   314  	if err == nil && err.Error() != "timeout reading from channel" {
   315  		t.Fatalf("Expected an error, got %s", err)
   316  	}
   317  	<-done
   318  }
   319  
   320  func TestChannelBuffer(t *testing.T) {
   321  	expected := "11"
   322  
   323  	buf := &ChannelBuffer{make(chan []byte, 1)}
   324  	defer buf.Close()
   325  
   326  	go func() {
   327  		time.Sleep(100 * time.Millisecond)
   328  		io.Copy(buf, strings.NewReader(expected))
   329  	}()
   330  
   331  	// Wait long enough
   332  	b := make([]byte, 2)
   333  	_, err := buf.ReadTimeout(b, 200*time.Millisecond)
   334  	if err != nil {
   335  		t.Fatal(err)
   336  	}
   337  
   338  	if string(b) != expected {
   339  		t.Fatalf("Expected '%s', got '%s'", expected, string(b))
   340  	}
   341  }
   342  
   343  // FIXME doesn't work
   344  // func TestRunAtDifferentDate(t *testing.T) {
   345  // 	var date string
   346  
   347  // 	// Layout for date. MMDDhhmmYYYY
   348  // 	const timeLayout = "20060102"
   349  // 	expectedDate := "20100201"
   350  // 	theDate, err := time.Parse(timeLayout, expectedDate)
   351  // 	if err != nil {
   352  // 		t.Fatal(err)
   353  // 	}
   354  
   355  // 	RunAtDifferentDate(theDate, func() {
   356  // 		cmd := exec.Command("date", "+%Y%M%d")
   357  // 		out, err := cmd.Output()
   358  // 		if err != nil {
   359  // 			t.Fatal(err)
   360  // 		}
   361  // 		date = string(out)
   362  // 	})
   363  // }