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 // }