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