github.com/apcera/util@v0.0.0-20180322191801-7a50bc84ee48/tarhelper/untar_test.go (about)

     1  // Copyright 2012-2016 Apcera Inc. All rights reserved.
     2  
     3  package tarhelper
     4  
     5  import (
     6  	"archive/tar"
     7  	"bytes"
     8  	"io"
     9  	"io/ioutil"
    10  	"os"
    11  	"os/user"
    12  	"path"
    13  	"path/filepath"
    14  	"strconv"
    15  	"strings"
    16  	"syscall"
    17  	"testing"
    18  	"time"
    19  
    20  	tt "github.com/apcera/util/testtool"
    21  )
    22  
    23  func TestUntarResolveDestinations(t *testing.T) {
    24  	testHelper := tt.StartTest(t)
    25  	defer testHelper.FinishTest()
    26  
    27  	u := new(Untar)
    28  	u.resolvedLinks = make([]resolvedLink, 0)
    29  
    30  	makeTestDir(t)
    31  
    32  	runTest := func(p, e string) {
    33  		dst, err := u.resolveDestination(p)
    34  		tt.TestExpectSuccess(t, err)
    35  		tt.TestEqual(t, dst, e)
    36  	}
    37  
    38  	runTest("a", "a")
    39  	runTest("a/b", "a/b")
    40  	runTest("a/b/c", "a/b/c")
    41  	runTest("a/b/c/d", "a/b/c/d")
    42  	runTest("a/b/c/d/e", "a/b/c/d/e")
    43  	runTest("a/b/c/f", "a/b/c/f")
    44  	runTest("a/b/c/l", "a/b/i")
    45  	runTest("a/b/c/l/j", "a/b/i/j")
    46  	runTest("a/b/c/l/j/k", "a/b/i/j/k")
    47  	runTest("a/b/c/l/j/l", "a/b/i/j/k")
    48  	runTest("a/b/c/l/j/m", "a/b/g")
    49  	runTest("a/b/g", "a/b/g")
    50  	runTest("a/b/h", "a/b/g")
    51  	runTest("a/b/i", "a/b/i")
    52  	runTest("a/b/i/j", "a/b/i/j")
    53  	runTest("a/b/i/j/k", "a/b/i/j/k")
    54  	runTest("a/b/i/j/l", "a/b/i/j/k")
    55  	runTest("a/b/i/j/m", "a/b/g")
    56  
    57  	// resolve an absolute path symlink relative to the root
    58  	u.AbsoluteRoot = "/"
    59  	runTest("a/b/bash", "/bin/bash")
    60  
    61  	// now resolve it relative to some other arbituary path
    62  	u.AbsoluteRoot = "/some/path/elsewhere"
    63  	runTest("a/b/bash", "/some/path/elsewhere/bin/bash")
    64  }
    65  
    66  func TestUntarExtractFollowingSymlinks(t *testing.T) {
    67  	testHelper := tt.StartTest(t)
    68  	defer testHelper.FinishTest()
    69  
    70  	// create a buffer and tar.Writer
    71  	buffer := bytes.NewBufferString("")
    72  	archive := tar.NewWriter(buffer)
    73  
    74  	writeDirectory := func(name string) {
    75  		header := new(tar.Header)
    76  		header.Name = name + "/"
    77  		header.Typeflag = tar.TypeDir
    78  		header.Mode = 0755
    79  		header.Mode |= c_ISDIR
    80  		header.ModTime = time.Now()
    81  		tt.TestExpectSuccess(t, archive.WriteHeader(header))
    82  	}
    83  
    84  	writeFile := func(name, contents string) {
    85  		b := []byte(contents)
    86  		header := new(tar.Header)
    87  		header.Name = name
    88  		header.Typeflag = tar.TypeReg
    89  		header.Mode = 0644
    90  		header.Mode |= c_ISREG
    91  		header.ModTime = time.Now()
    92  		header.Size = int64(len(b))
    93  
    94  		tt.TestExpectSuccess(t, archive.WriteHeader(header))
    95  		_, err := archive.Write(b)
    96  		tt.TestExpectSuccess(t, err)
    97  		tt.TestExpectSuccess(t, archive.Flush())
    98  	}
    99  
   100  	writeSymlink := func(name, link string) {
   101  		header := new(tar.Header)
   102  		header.Name = name
   103  		header.Linkname = link
   104  		header.Typeflag = tar.TypeSymlink
   105  		header.Mode = 0644
   106  		header.Mode |= c_ISLNK
   107  		header.ModTime = time.Now()
   108  		tt.TestExpectSuccess(t, archive.WriteHeader(header))
   109  	}
   110  
   111  	// generate the mock tar
   112  	writeDirectory(".")
   113  	writeFile("./foo", "foo")
   114  	writeDirectory("./usr")
   115  	writeDirectory("./usr/bin")
   116  	writeFile("./usr/bin/bash", "bash")
   117  	writeSymlink("./usr/bin/sh", "bash")
   118  
   119  	// now write a symlink that is an absolute path and then a file in it
   120  	writeSymlink("./etc", "/realetc")
   121  	writeFile("./etc/zz", "zz")
   122  	archive.Close()
   123  
   124  	// create temp folder to extract to
   125  	tempDir := testHelper.TempDir()
   126  	extractionPath := path.Join(tempDir, "pkg")
   127  	err := os.MkdirAll(extractionPath, 0755)
   128  	tt.TestExpectSuccess(t, err)
   129  	err = os.MkdirAll(path.Join(tempDir, "realetc"), 0755)
   130  	tt.TestExpectSuccess(t, err)
   131  
   132  	// extract
   133  	r := bytes.NewReader(buffer.Bytes())
   134  	u := NewUntar(r, extractionPath)
   135  	u.AbsoluteRoot = tempDir
   136  	tt.TestExpectSuccess(t, u.Extract())
   137  
   138  	fileExists := func(name string) {
   139  		_, err := os.Stat(path.Join(tempDir, name))
   140  		tt.TestExpectSuccess(t, err)
   141  	}
   142  
   143  	fileContents := func(name, contents string) {
   144  		b, err := ioutil.ReadFile(path.Join(tempDir, name))
   145  		tt.TestExpectSuccess(t, err)
   146  		tt.TestEqual(t, string(b), contents)
   147  	}
   148  
   149  	fileSymlinks := func(name, link string) {
   150  		l, err := os.Readlink(path.Join(tempDir, name))
   151  		tt.TestExpectSuccess(t, err)
   152  		tt.TestEqual(t, l, link)
   153  	}
   154  
   155  	fileExists("./pkg/foo")
   156  	fileContents("./pkg/foo", "foo")
   157  	fileExists("./pkg/usr")
   158  	fileExists("./pkg/usr/bin")
   159  	fileExists("./pkg/usr/bin/bash")
   160  	fileContents("./pkg/usr/bin/bash", "bash")
   161  	fileSymlinks("./pkg/usr/bin/sh", "bash")
   162  
   163  	// now validate the symlink and file in the symlinked dir that was outside
   164  	// the symlink should still be absolute to /realetc
   165  	// but the file should be in ./realetc/zz within the tempDir and not the
   166  	// system's root... so Untar follows how it knows it should resolve and not
   167  	// follow the real symlink
   168  	fileSymlinks("./pkg/etc", "/realetc")
   169  	fileExists("./realetc/zz")
   170  	fileContents("./realetc/zz", "zz")
   171  }
   172  
   173  func TestUntarCreatesDeeperPathsIfNotMentioned(t *testing.T) {
   174  	testHelper := tt.StartTest(t)
   175  	defer testHelper.FinishTest()
   176  
   177  	// create a buffer and tar.Writer
   178  	buffer := bytes.NewBufferString("")
   179  	archive := tar.NewWriter(buffer)
   180  
   181  	writeFile := func(name, contents string) {
   182  		b := []byte(contents)
   183  		header := new(tar.Header)
   184  		header.Name = name
   185  		header.Typeflag = tar.TypeReg
   186  		header.Mode = 0644
   187  		header.Mode |= c_ISREG
   188  		header.ModTime = time.Now()
   189  		header.Size = int64(len(b))
   190  
   191  		tt.TestExpectSuccess(t, archive.WriteHeader(header))
   192  		_, err := archive.Write(b)
   193  		tt.TestExpectSuccess(t, err)
   194  		tt.TestExpectSuccess(t, archive.Flush())
   195  	}
   196  
   197  	// generate the mock tar... this will write to a file in a directory that
   198  	// isn't already created within the tar
   199  	writeFile("./a_directory/file", "foo")
   200  	archive.Close()
   201  
   202  	// create temp folder to extract to
   203  	tempDir := testHelper.TempDir()
   204  	extractionPath := path.Join(tempDir, "pkg")
   205  	err := os.MkdirAll(extractionPath, 0755)
   206  	tt.TestExpectSuccess(t, err)
   207  
   208  	// extract
   209  	r := bytes.NewReader(buffer.Bytes())
   210  	u := NewUntar(r, extractionPath)
   211  	u.AbsoluteRoot = tempDir
   212  	tt.TestExpectSuccess(t, u.Extract())
   213  
   214  	fileExists := func(name string) {
   215  		_, err := os.Stat(path.Join(tempDir, name))
   216  		tt.TestExpectSuccess(t, err)
   217  	}
   218  
   219  	fileContents := func(name, contents string) {
   220  		b, err := ioutil.ReadFile(path.Join(tempDir, name))
   221  		tt.TestExpectSuccess(t, err)
   222  		tt.TestEqual(t, string(b), contents)
   223  	}
   224  
   225  	fileExists("./pkg/a_directory/file")
   226  	fileContents("./pkg/a_directory/file", "foo")
   227  }
   228  
   229  func TestUntarExtractOverwriting(t *testing.T) {
   230  	testHelper := tt.StartTest(t)
   231  	defer testHelper.FinishTest()
   232  
   233  	// create a buffer and tar.Writer
   234  	buffer := bytes.NewBufferString("")
   235  	archive := tar.NewWriter(buffer)
   236  
   237  	writeDirectory := func(name string) {
   238  		header := new(tar.Header)
   239  		header.Name = name + "/"
   240  		header.Typeflag = tar.TypeDir
   241  		header.Mode = 0755
   242  		header.Mode |= c_ISDIR
   243  		header.ModTime = time.Now()
   244  		tt.TestExpectSuccess(t, archive.WriteHeader(header))
   245  	}
   246  
   247  	writeFile := func(name, contents string) {
   248  		b := []byte(contents)
   249  		header := new(tar.Header)
   250  		header.Name = name
   251  		header.Typeflag = tar.TypeReg
   252  		header.Mode = 0644
   253  		header.Mode |= c_ISREG
   254  		header.ModTime = time.Now()
   255  		header.Size = int64(len(b))
   256  
   257  		tt.TestExpectSuccess(t, archive.WriteHeader(header))
   258  		_, err := archive.Write(b)
   259  		tt.TestExpectSuccess(t, err)
   260  		tt.TestExpectSuccess(t, archive.Flush())
   261  	}
   262  
   263  	writeSymlink := func(name, link string) {
   264  		header := new(tar.Header)
   265  		header.Name = name
   266  		header.Linkname = link
   267  		header.Typeflag = tar.TypeSymlink
   268  		header.Mode = 0644
   269  		header.Mode |= c_ISLNK
   270  		header.ModTime = time.Now()
   271  		tt.TestExpectSuccess(t, archive.WriteHeader(header))
   272  	}
   273  
   274  	// create temp folder to extract to
   275  	tempDir := testHelper.TempDir()
   276  
   277  	fileExists := func(name string) {
   278  		_, err := os.Stat(path.Join(tempDir, name))
   279  		tt.TestExpectSuccess(t, err)
   280  	}
   281  
   282  	fileContents := func(name, contents string) {
   283  		b, err := ioutil.ReadFile(path.Join(tempDir, name))
   284  		tt.TestExpectSuccess(t, err)
   285  		tt.TestEqual(t, string(b), contents)
   286  	}
   287  
   288  	fileSymlinks := func(name, link string) {
   289  		l, err := os.Readlink(path.Join(tempDir, name))
   290  		tt.TestExpectSuccess(t, err)
   291  		tt.TestEqual(t, l, link)
   292  	}
   293  
   294  	// generate the mock tar
   295  	writeDirectory(".")
   296  	writeFile("./foo", "foo")
   297  	writeDirectory("./usr")
   298  	writeDirectory("./usr/bin")
   299  	writeFile("./usr/bin/bash", "bash")
   300  	writeSymlink("./usr/bin/sh", "bash")
   301  	writeDirectory("./etc")
   302  	writeFile("./etc/awesome", "awesome")
   303  	writeFile("./var", "vvv")
   304  	archive.Close()
   305  
   306  	// extract
   307  	r := bytes.NewReader(buffer.Bytes())
   308  	u := NewUntar(r, tempDir)
   309  	tt.TestExpectSuccess(t, u.Extract())
   310  
   311  	// validate the first tar
   312  	fileExists("./foo")
   313  	fileContents("./foo", "foo")
   314  	fileExists("./usr")
   315  	fileExists("./usr/bin")
   316  	fileExists("./usr/bin/bash")
   317  	fileContents("./usr/bin/bash", "bash")
   318  	fileSymlinks("./usr/bin/sh", "bash")
   319  	fileExists("./etc/awesome")
   320  	fileContents("./etc/awesome", "awesome")
   321  	fileExists("./var")
   322  	fileContents("./var", "vvv")
   323  
   324  	// create another tar and then extract it
   325  	buffer2 := bytes.NewBufferString("")
   326  	archive = tar.NewWriter(buffer2)
   327  
   328  	// write the 2nd tar
   329  	writeDirectory(".")
   330  	writeFile("./foo", "bar")
   331  	writeDirectory("./usr")
   332  	writeDirectory("./usr/bin")
   333  	writeFile("./usr/bin/zsh", "zsh")
   334  	writeSymlink("./usr/bin/sh", "zsh")
   335  	writeFile("./etc", "etc") // replace the directory with a file
   336  	writeDirectory("./var")   // replace the file with a directory
   337  	writeFile("./var/lib", "lll")
   338  	archive.Close()
   339  
   340  	// extract the 2nd tar
   341  	r = bytes.NewReader(buffer2.Bytes())
   342  	u = NewUntar(r, tempDir)
   343  	tt.TestExpectSuccess(t, u.Extract())
   344  
   345  	// verify the contents were overwritten as expected
   346  	fileContents("./foo", "bar")
   347  	fileContents("./usr/bin/zsh", "zsh")
   348  	fileSymlinks("./usr/bin/sh", "zsh")
   349  	fileContents("./etc", "etc")
   350  	fileContents("./var/lib", "lll")
   351  }
   352  
   353  func TestUntarIDMappings(t *testing.T) {
   354  	testHelper := tt.StartTest(t)
   355  	defer testHelper.FinishTest()
   356  
   357  	// create a buffer and tar.Writer
   358  	buffer := bytes.NewBufferString("")
   359  	archive := tar.NewWriter(buffer)
   360  
   361  	writeDirectoryWithOwners := func(name string, uid, gid int) {
   362  		header := new(tar.Header)
   363  		header.Name = name + "/"
   364  		header.Typeflag = tar.TypeDir
   365  		header.Mode = 0755
   366  		header.Mode |= c_ISDIR
   367  		header.ModTime = time.Now()
   368  		header.Uid = uid
   369  		header.Gid = gid
   370  		tt.TestExpectSuccess(t, archive.WriteHeader(header))
   371  	}
   372  
   373  	writeFileWithOwners := func(name, contents string, uid, gid int) {
   374  		b := []byte(contents)
   375  		header := new(tar.Header)
   376  		header.Name = name
   377  		header.Typeflag = tar.TypeReg
   378  		header.Mode = 0644
   379  		header.Mode |= c_ISREG
   380  		header.ModTime = time.Now()
   381  		header.Size = int64(len(b))
   382  		header.Uid = uid
   383  		header.Gid = gid
   384  
   385  		tt.TestExpectSuccess(t, archive.WriteHeader(header))
   386  		_, err := archive.Write(b)
   387  		tt.TestExpectSuccess(t, err)
   388  		tt.TestExpectSuccess(t, archive.Flush())
   389  	}
   390  
   391  	writeDirectoryWithOwners(".", 0, 0)
   392  	writeFileWithOwners("./foo", "foo", 0, 0)
   393  	archive.Close()
   394  
   395  	// setup our mapping func
   396  	usr, err := user.Current()
   397  	tt.TestExpectSuccess(t, err)
   398  	myUid, err := strconv.Atoi(usr.Uid)
   399  	tt.TestExpectSuccess(t, err)
   400  	myGid, err := strconv.Atoi(usr.Gid)
   401  	tt.TestExpectSuccess(t, err)
   402  	uidFuncCalled := false
   403  	gidFuncCalled := false
   404  	uidMappingFunc := func(uid int) (int, error) {
   405  		uidFuncCalled = true
   406  		tt.TestEqual(t, uid, 0)
   407  		return myUid, nil
   408  	}
   409  	gidMappingFunc := func(gid int) (int, error) {
   410  		gidFuncCalled = true
   411  		tt.TestEqual(t, gid, 0)
   412  		return myGid, nil
   413  	}
   414  
   415  	// extract
   416  	tempDir := testHelper.TempDir()
   417  	r := bytes.NewReader(buffer.Bytes())
   418  	u := NewUntar(r, tempDir)
   419  	u.PreserveOwners = true
   420  	u.OwnerMappingFunc = uidMappingFunc
   421  	u.GroupMappingFunc = gidMappingFunc
   422  	tt.TestExpectSuccess(t, u.Extract())
   423  
   424  	// verify it was called
   425  	tt.TestEqual(t, uidFuncCalled, true)
   426  	tt.TestEqual(t, gidFuncCalled, true)
   427  
   428  	// verify the file
   429  	stat, err := os.Stat(path.Join(tempDir, "foo"))
   430  	tt.TestExpectSuccess(t, err)
   431  	sys := stat.Sys().(*syscall.Stat_t)
   432  	tt.TestEqual(t, sys.Uid, uint32(myUid))
   433  	tt.TestEqual(t, sys.Gid, uint32(myGid))
   434  }
   435  
   436  func TestUntarFailures(t *testing.T) {
   437  	testHelper := tt.StartTest(t)
   438  	defer testHelper.FinishTest()
   439  
   440  	// Bad compression type.
   441  	u := NewUntar(strings.NewReader("bad"), "/tmp")
   442  	u.Compression = Compression(-1)
   443  	tt.TestExpectError(t, u.Extract())
   444  
   445  	// FIXME(brady): add more cases here!
   446  }
   447  
   448  func TestCannotDetectCompression(t *testing.T) {
   449  	testHelper := tt.StartTest(t)
   450  	defer testHelper.FinishTest()
   451  
   452  	u := NewUntar(strings.NewReader("bad"), "/tmp")
   453  	u.Compression = DETECT
   454  
   455  	tt.TestExpectError(t, u.Extract())
   456  }
   457  
   458  func TestUntarWhitelist(t *testing.T) {
   459  	testHelper := tt.StartTest(t)
   460  	defer testHelper.FinishTest()
   461  
   462  	// create a buffer and tar.Writer
   463  	buffer := bytes.NewBufferString("")
   464  	archive := tar.NewWriter(buffer)
   465  
   466  	writeDirectory := func(name string) {
   467  		header := new(tar.Header)
   468  		header.Name = name + "/"
   469  		header.Typeflag = tar.TypeDir
   470  		header.Mode = 0755
   471  		header.Mode |= c_ISDIR
   472  		header.ModTime = time.Now()
   473  		tt.TestExpectSuccess(t, archive.WriteHeader(header))
   474  	}
   475  
   476  	writeFile := func(name, contents string) {
   477  		b := []byte(contents)
   478  		header := new(tar.Header)
   479  		header.Name = name
   480  		header.Typeflag = tar.TypeReg
   481  		header.Mode = 0644
   482  		header.Mode |= c_ISREG
   483  		header.ModTime = time.Now()
   484  		header.Size = int64(len(b))
   485  
   486  		tt.TestExpectSuccess(t, archive.WriteHeader(header))
   487  		_, err := archive.Write(b)
   488  		tt.TestExpectSuccess(t, err)
   489  		tt.TestExpectSuccess(t, archive.Flush())
   490  	}
   491  
   492  	writeDirectory(".")
   493  	writeFile("./foo", "foo")
   494  	writeFile("./foobar", "foobar")
   495  	writeFile("./doesntexist", "foo")
   496  	writeDirectory("./usr")
   497  	writeDirectory("./usr/bin")
   498  	writeFile("./usr/bin/bash", "bash")
   499  	writeDirectory("./usr/bin/other")
   500  	writeFile("./usr/bin/other/sh", "sh")
   501  	writeDirectory("./usr/nope")
   502  	writeFile("./usr/nope/not", "notthere")
   503  	writeDirectory("./usr/justdir")
   504  	writeFile("./usr/justdir/not", "notthere")
   505  	writeDirectory("./etc")
   506  	writeFile("./etc/not", "notthere")
   507  
   508  	archive.Close()
   509  
   510  	// create temp folder to extract to
   511  	tempDir := testHelper.TempDir()
   512  
   513  	// extract
   514  	r := bytes.NewReader(buffer.Bytes())
   515  	u := NewUntar(r, tempDir)
   516  	u.PathWhitelist = []string{
   517  		"/foo",
   518  		"/usr/bin/",
   519  		"/usr/justdir",
   520  	}
   521  	tt.TestExpectSuccess(t, u.Extract())
   522  
   523  	fileExists := func(name string) {
   524  		_, err := os.Stat(path.Join(tempDir, name))
   525  		tt.TestExpectSuccess(t, err)
   526  	}
   527  
   528  	fileNotExists := func(name string) {
   529  		_, err := os.Stat(path.Join(tempDir, name))
   530  		tt.TestExpectError(t, err)
   531  	}
   532  
   533  	fileExists("/foo")
   534  	fileExists("/usr/bin/bash")
   535  	fileExists("/usr/bin/other/sh")
   536  	fileExists("/usr/justdir")
   537  	fileNotExists("/foobar")
   538  	fileNotExists("/doesntexist")
   539  	fileNotExists("/usr/nope/not")
   540  	fileNotExists("/usr/justdir/not")
   541  	fileNotExists("/etc/not")
   542  }
   543  
   544  func TestUntarCustomHandler(t *testing.T) {
   545  	testHelper := tt.StartTest(t)
   546  	defer testHelper.FinishTest()
   547  
   548  	// create a buffer and tar.Writer
   549  	buffer := bytes.NewBufferString("")
   550  	archive := tar.NewWriter(buffer)
   551  
   552  	writeDirectory := func(name string) {
   553  		header := new(tar.Header)
   554  		header.Name = name + "/"
   555  		header.Typeflag = tar.TypeDir
   556  		header.Mode = 0755
   557  		header.Mode |= c_ISDIR
   558  		header.ModTime = time.Now()
   559  		tt.TestExpectSuccess(t, archive.WriteHeader(header))
   560  	}
   561  
   562  	writeFile := func(name, contents string) {
   563  		b := []byte(contents)
   564  		header := new(tar.Header)
   565  		header.Name = name
   566  		header.Typeflag = tar.TypeReg
   567  		header.Mode = 0644
   568  		header.Mode |= c_ISREG
   569  		header.ModTime = time.Now()
   570  		header.Size = int64(len(b))
   571  
   572  		tt.TestExpectSuccess(t, archive.WriteHeader(header))
   573  		_, err := archive.Write(b)
   574  		tt.TestExpectSuccess(t, err)
   575  		tt.TestExpectSuccess(t, archive.Flush())
   576  	}
   577  
   578  	writeDirectory(".")
   579  	writeFile("./foo", "foo")
   580  	writeFile("./foobar", "foobar")
   581  
   582  	archive.Close()
   583  
   584  	// create temp folder to extract to
   585  	tempDir := testHelper.TempDir()
   586  
   587  	// extract
   588  	r := bytes.NewReader(buffer.Bytes())
   589  	u := NewUntar(r, tempDir)
   590  	u.CustomHandlers = []UntarCustomHandler{
   591  		func(rootpath string, header *tar.Header, reader io.Reader) (bool, error) {
   592  			if filepath.Clean(header.Name) != "foobar" {
   593  				return false, nil
   594  			}
   595  
   596  			f, err := os.Create(filepath.Join(rootpath, "foobar2"))
   597  			if err != nil {
   598  				return false, err
   599  			}
   600  			defer f.Close()
   601  			if _, err := io.Copy(f, reader); err != nil {
   602  				return false, err
   603  			}
   604  			return true, nil
   605  		},
   606  	}
   607  	tt.TestExpectSuccess(t, u.Extract())
   608  
   609  	fileExists := func(name string) {
   610  		_, err := os.Stat(path.Join(tempDir, name))
   611  		tt.TestExpectSuccess(t, err)
   612  	}
   613  
   614  	fileNotExists := func(name string) {
   615  		_, err := os.Stat(path.Join(tempDir, name))
   616  		tt.TestExpectError(t, err)
   617  	}
   618  
   619  	fileExists("/foo")
   620  	fileNotExists("/foobar")
   621  	fileExists("/foobar2")
   622  }