14230: Comment about test coverage, add trailing-** case.
[arvados.git] / lib / crunchrun / copier_test.go
index 07fd795efe45a75c6390520a88de39e479ca1f72..30e13f65033eef8dc2e93d5a0ba3acbd6356b155 100644 (file)
@@ -7,12 +7,13 @@ package crunchrun
 import (
        "bytes"
        "io"
+       "io/fs"
        "io/ioutil"
        "os"
+       "sort"
        "syscall"
 
        "git.arvados.org/arvados.git/sdk/go/arvados"
-       "git.arvados.org/arvados.git/sdk/go/arvadosclient"
        "git.arvados.org/arvados.git/sdk/go/arvadostest"
        "github.com/sirupsen/logrus"
        check "gopkg.in/check.v1"
@@ -27,12 +28,9 @@ type copierSuite struct {
 
 func (s *copierSuite) SetUpTest(c *check.C) {
        tmpdir := c.MkDir()
-       api, err := arvadosclient.MakeArvadosClient()
-       c.Assert(err, check.IsNil)
        s.log = bytes.Buffer{}
        s.cp = copier{
                client:        arvados.NewClientFromEnv(),
-               arvClient:     api,
                hostOutputDir: tmpdir,
                ctrOutputDir:  "/ctr/outdir",
                mounts: map[string]arvados.Mount{
@@ -132,7 +130,9 @@ func (s *copierSuite) TestSymlinkToMountedCollection(c *check.C) {
                PortableDataHash: arvadostest.FooCollectionPDH,
                Writable:         true,
        }
-       s.cp.binds = append(s.cp.binds, bindtmp+":/mnt-w")
+       s.cp.bindmounts = map[string]bindmount{
+               "/mnt-w": bindmount{HostPath: bindtmp, ReadOnly: false},
+       }
 
        c.Assert(os.Symlink("../../mnt", s.cp.hostOutputDir+"/l_dir"), check.IsNil)
        c.Assert(os.Symlink("/mnt/foo", s.cp.hostOutputDir+"/l_file"), check.IsNil)
@@ -224,3 +224,184 @@ func (s *copierSuite) writeFileInOutputDir(c *check.C, path, data string) {
        c.Assert(err, check.IsNil)
        c.Assert(f.Close(), check.IsNil)
 }
+
+// applyGlobsToFilesAndDirs uses the same glob-matching code as
+// applyGlobsToCollectionFS, so we don't need to test all of the same
+// glob-matching behavior covered in TestApplyGlobsToCollectionFS.  We
+// do need to check that (a) the glob is actually being used to filter
+// out files, and (b) non-matching dirs still included if and only if
+// they are ancestors of matching files.
+func (s *copierSuite) TestApplyGlobsToFilesAndDirs(c *check.C) {
+       dirs := []string{"dir1", "dir1/dir11", "dir1/dir12", "dir2"}
+       files := []string{"dir1/file11", "dir1/dir11/file111", "dir2/file2"}
+       for _, trial := range []struct {
+               globs []string
+               dirs  []string
+               files []string
+       }{
+               {
+                       globs: []string{},
+                       dirs:  append([]string{}, dirs...),
+                       files: append([]string{}, files...),
+               },
+               {
+                       globs: []string{"**"},
+                       dirs:  append([]string{}, dirs...),
+                       files: append([]string{}, files...),
+               },
+               {
+                       globs: []string{"**/file111"},
+                       dirs:  []string{"dir1", "dir1/dir11"},
+                       files: []string{"dir1/dir11/file111"},
+               },
+               {
+                       globs: []string{"nothing"},
+                       dirs:  nil,
+                       files: nil,
+               },
+               {
+                       globs: []string{"**/dir12"},
+                       dirs:  []string{"dir1", "dir1/dir12"},
+                       files: nil,
+               },
+               {
+                       globs: []string{"**/file*"},
+                       dirs:  []string{"dir1", "dir1/dir11", "dir2"},
+                       files: append([]string{}, files...),
+               },
+               {
+                       globs: []string{"**/dir1[12]"},
+                       dirs:  []string{"dir1", "dir1/dir11", "dir1/dir12"},
+                       files: nil,
+               },
+               {
+                       globs: []string{"**/dir1[^2]"},
+                       dirs:  []string{"dir1", "dir1/dir11"},
+                       files: nil,
+               },
+               {
+                       globs: []string{"dir1/**"},
+                       dirs:  []string{"dir1", "dir1/dir11", "dir1/dir12"},
+                       files: []string{"dir1/file11", "dir1/dir11/file111"},
+               },
+       } {
+               c.Logf("=== globs: %q", trial.globs)
+               cp := copier{
+                       globs: trial.globs,
+                       dirs:  dirs,
+               }
+               for _, path := range files {
+                       cp.files = append(cp.files, filetodo{dst: path})
+               }
+               cp.applyGlobsToFilesAndDirs()
+               var gotFiles []string
+               for _, file := range cp.files {
+                       gotFiles = append(gotFiles, file.dst)
+               }
+               c.Check(cp.dirs, check.DeepEquals, trial.dirs)
+               c.Check(gotFiles, check.DeepEquals, trial.files)
+       }
+}
+
+func (s *copierSuite) TestApplyGlobsToCollectionFS(c *check.C) {
+       for _, trial := range []struct {
+               globs  []string
+               expect []string
+       }{
+               {
+                       globs:  nil,
+                       expect: []string{"foo", "bar", "baz/quux", "baz/parent1/item1"},
+               },
+               {
+                       globs:  []string{"foo"},
+                       expect: []string{"foo"},
+               },
+               {
+                       globs:  []string{"baz/parent1/item1"},
+                       expect: []string{"baz/parent1/item1"},
+               },
+               {
+                       globs:  []string{"**"},
+                       expect: []string{"foo", "bar", "baz/quux", "baz/parent1/item1"},
+               },
+               {
+                       globs:  []string{"**/*"},
+                       expect: []string{"foo", "bar", "baz/quux", "baz/parent1/item1"},
+               },
+               {
+                       globs:  []string{"*"},
+                       expect: []string{"foo", "bar"},
+               },
+               {
+                       globs:  []string{"baz"},
+                       expect: nil,
+               },
+               {
+                       globs:  []string{"b*/**"},
+                       expect: []string{"baz/quux", "baz/parent1/item1"},
+               },
+               {
+                       globs:  []string{"baz"},
+                       expect: nil,
+               },
+               {
+                       globs:  []string{"baz/**"},
+                       expect: []string{"baz/quux", "baz/parent1/item1"},
+               },
+               {
+                       globs:  []string{"baz/*"},
+                       expect: []string{"baz/quux"},
+               },
+               {
+                       globs:  []string{"baz/**/*uu?"},
+                       expect: []string{"baz/quux"},
+               },
+               {
+                       globs:  []string{"**/*m1"},
+                       expect: []string{"baz/parent1/item1"},
+               },
+               {
+                       globs:  []string{"*/*/*/**/*1"},
+                       expect: nil,
+               },
+               {
+                       globs:  []string{"f*", "**/q*"},
+                       expect: []string{"foo", "baz/quux"},
+               },
+               {
+                       globs:  []string{"\\"}, // invalid pattern matches nothing
+                       expect: nil,
+               },
+               {
+                       globs:  []string{"\\", "foo"},
+                       expect: []string{"foo"},
+               },
+               {
+                       globs:  []string{"foo/**"},
+                       expect: nil,
+               },
+               {
+                       globs:  []string{"foo*/**"},
+                       expect: nil,
+               },
+       } {
+               c.Logf("=== globs: %q", trial.globs)
+               collfs, err := (&arvados.Collection{ManifestText: ". d41d8cd98f00b204e9800998ecf8427e+0 0:0:foo 0:0:bar 0:0:baz/quux 0:0:baz/parent1/item1\n"}).FileSystem(nil, nil)
+               c.Assert(err, check.IsNil)
+               cp := copier{globs: trial.globs}
+               err = cp.applyGlobsToCollectionFS(collfs)
+               if !c.Check(err, check.IsNil) {
+                       continue
+               }
+               var got []string
+               fs.WalkDir(arvados.FS(collfs), "", func(path string, ent fs.DirEntry, err error) error {
+                       if !ent.IsDir() {
+                               got = append(got, path)
+                       }
+                       return nil
+               })
+               sort.Strings(got)
+               sort.Strings(trial.expect)
+               c.Check(got, check.DeepEquals, trial.expect)
+       }
+}