1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: Apache-2.0
16 check "gopkg.in/check.v1"
20 // Importing arvadostest would be an import cycle, so these
21 // fixtures are duplicated here [until fs moves to a separate
23 fixtureActiveToken = "3kg6k6lzmp9kj5cpkcoxie963cmvjahbt2fod9zru30k1jqdmi"
24 fixtureAProjectUUID = "zzzzz-j7d0g-v955i6s2oi1cbso"
25 fixtureThisFilterGroupUUID = "zzzzz-j7d0g-thisfiltergroup"
26 fixtureAFilterGroupTwoUUID = "zzzzz-j7d0g-afiltergrouptwo"
27 fixtureAFilterGroupThreeUUID = "zzzzz-j7d0g-filtergroupthre"
28 fixtureAFilterGroupFourUUID = "zzzzz-j7d0g-filtergroupfour"
29 fixtureAFilterGroupFiveUUID = "zzzzz-j7d0g-filtergroupfive"
30 fixtureFooAndBarFilesInDirUUID = "zzzzz-4zz18-foonbarfilesdir"
31 fixtureFooCollectionName = "zzzzz-4zz18-fy296fx3hot09f7 added sometime"
32 fixtureFooCollectionPDH = "1f4b0bc7583c2a7f9102c395f4ffc5e3+45"
33 fixtureFooCollection = "zzzzz-4zz18-fy296fx3hot09f7"
34 fixtureNonexistentCollection = "zzzzz-4zz18-totallynotexist"
35 fixtureStorageClassesDesiredArchive = "zzzzz-4zz18-3t236wr12769qqa"
36 fixtureBlobSigningKey = "zfhgfenhffzltr9dixws36j1yhksjoll2grmku38mi7yxd66h5j4q9w4jzanezacp8s6q0ro3hxakfye02152hncy6zml2ed0uc"
37 fixtureBlobSigningTTL = 336 * time.Hour
40 var _ = check.Suite(&SiteFSSuite{})
43 // Enable DebugLocksPanicMode sometimes. Don't enable it all
44 // the time, though -- it adds many calls to time.Sleep(),
45 // which could hide different bugs.
46 if time.Now().Second()&1 == 0 {
47 DebugLocksPanicMode = true
51 type SiteFSSuite struct {
57 func (s *SiteFSSuite) SetUpTest(c *check.C) {
59 APIHost: os.Getenv("ARVADOS_API_HOST"),
60 AuthToken: fixtureActiveToken,
63 s.kc = &keepClientStub{
64 blocks: map[string][]byte{
65 "3858f62230ac3c915f300c664312c63f": []byte("foobar"),
67 sigkey: fixtureBlobSigningKey,
68 sigttl: fixtureBlobSigningTTL,
69 authToken: fixtureActiveToken,
71 s.fs = s.client.SiteFileSystem(s.kc)
74 func (s *SiteFSSuite) TestHttpFileSystemInterface(c *check.C) {
75 _, ok := s.fs.(http.FileSystem)
76 c.Check(ok, check.Equals, true)
79 func (s *SiteFSSuite) TestByIDEmpty(c *check.C) {
80 f, err := s.fs.Open("/by_id")
81 c.Assert(err, check.IsNil)
82 fis, err := f.Readdir(-1)
83 c.Check(err, check.IsNil)
84 c.Check(len(fis), check.Equals, 0)
87 func (s *SiteFSSuite) TestUpdateStorageClasses(c *check.C) {
88 f, err := s.fs.OpenFile("/by_id/"+fixtureStorageClassesDesiredArchive+"/newfile", os.O_CREATE|os.O_RDWR, 0777)
89 c.Assert(err, check.IsNil)
90 _, err = f.Write([]byte("nope"))
91 c.Assert(err, check.IsNil)
93 c.Assert(err, check.IsNil)
95 c.Assert(err, check.ErrorMatches, `.*stub does not write storage class "archive"`)
98 func (s *SiteFSSuite) TestByUUIDAndPDH(c *check.C) {
99 f, err := s.fs.Open("/by_id")
100 c.Assert(err, check.IsNil)
101 fis, err := f.Readdir(-1)
102 c.Check(err, check.IsNil)
103 c.Check(len(fis), check.Equals, 0)
105 err = s.fs.Mkdir("/by_id/"+fixtureFooCollection, 0755)
106 c.Check(err, check.Equals, os.ErrExist)
108 f, err = s.fs.Open("/by_id/" + fixtureNonexistentCollection)
109 c.Assert(err, check.Equals, os.ErrNotExist)
111 for _, path := range []string{
112 fixtureFooCollection,
113 fixtureFooCollectionPDH,
114 fixtureAProjectUUID + "/" + fixtureFooCollectionName,
116 f, err = s.fs.Open("/by_id/" + path)
117 c.Assert(err, check.IsNil)
118 fis, err = f.Readdir(-1)
119 c.Assert(err, check.IsNil)
121 for _, fi := range fis {
122 names = append(names, fi.Name())
124 c.Check(names, check.DeepEquals, []string{"foo"})
127 f, err = s.fs.Open("/by_id/" + fixtureAProjectUUID + "/A Subproject/baz_file")
128 c.Assert(err, check.IsNil)
129 fis, err = f.Readdir(-1)
130 c.Assert(err, check.IsNil)
132 for _, fi := range fis {
133 names = append(names, fi.Name())
135 c.Check(names, check.DeepEquals, []string{"baz"})
137 _, err = s.fs.OpenFile("/by_id/"+fixtureNonexistentCollection, os.O_RDWR|os.O_CREATE, 0755)
138 c.Check(err, check.Equals, ErrInvalidArgument)
139 err = s.fs.Rename("/by_id/"+fixtureFooCollection, "/by_id/beep")
140 c.Check(err, check.Equals, ErrInvalidArgument)
141 err = s.fs.Rename("/by_id/"+fixtureFooCollection+"/foo", "/by_id/beep")
142 c.Check(err, check.Equals, ErrInvalidArgument)
143 _, err = s.fs.Stat("/by_id/beep")
144 c.Check(err, check.Equals, os.ErrNotExist)
145 err = s.fs.Rename("/by_id/"+fixtureFooCollection+"/foo", "/by_id/"+fixtureFooCollection+"/bar")
146 c.Check(err, check.IsNil)
148 err = s.fs.Rename("/by_id", "/beep")
149 c.Check(err, check.Equals, ErrInvalidArgument)
152 // Copy subtree from OS src to dst path inside fs. If src is a
153 // directory, dst must exist and be a directory.
154 func copyFromOS(fs FileSystem, dst, src string) error {
155 inf, err := os.Open(src)
160 dirents, err := inf.Readdir(-1)
161 if e, ok := err.(*os.PathError); ok {
162 if e, ok := e.Err.(syscall.Errno); ok {
163 if e == syscall.ENOTDIR {
164 err = syscall.ENOTDIR
168 if err == syscall.ENOTDIR {
169 outf, err := fs.OpenFile(dst, os.O_CREATE|os.O_EXCL|os.O_TRUNC|os.O_WRONLY, 0700)
171 return fmt.Errorf("open %s: %s", dst, err)
174 _, err = io.Copy(outf, inf)
176 return fmt.Errorf("%s: copying data from %s: %s", dst, src, err)
182 } else if err != nil {
183 return fmt.Errorf("%s: readdir: %T %s", src, err, err)
186 d, err := fs.Open(dst)
188 return fmt.Errorf("opendir(%s): %s", dst, err)
192 for _, ent := range dirents {
193 if ent.Name() == "." || ent.Name() == ".." {
196 dstname := dst + "/" + ent.Name()
198 err = fs.Mkdir(dstname, 0700)
200 return fmt.Errorf("mkdir %s: %s", dstname, err)
203 err = copyFromOS(fs, dstname, src+"/"+ent.Name())
212 func (s *SiteFSSuite) TestSnapshotSplice(c *check.C) {
213 s.fs.MountProject("home", "")
216 err := s.client.RequestAndDecode(&src1, "POST", "arvados/v1/collections", nil, map[string]interface{}{
217 "collection": map[string]string{
218 "name": "TestSnapshotSplice src1",
219 "owner_uuid": fixtureAProjectUUID,
222 c.Assert(err, check.IsNil)
223 defer s.client.RequestAndDecode(nil, "DELETE", "arvados/v1/collections/"+src1.UUID, nil, nil)
225 c.Assert(err, check.IsNil)
226 err = copyFromOS(s.fs, "/home/A Project/TestSnapshotSplice src1", "..") // arvados.git/sdk/go
227 c.Assert(err, check.IsNil)
230 err = s.client.RequestAndDecode(&src2, "POST", "arvados/v1/collections", nil, map[string]interface{}{
231 "collection": map[string]string{
232 "name": "TestSnapshotSplice src2",
233 "owner_uuid": fixtureAProjectUUID,
236 c.Assert(err, check.IsNil)
237 defer s.client.RequestAndDecode(nil, "DELETE", "arvados/v1/collections/"+src2.UUID, nil, nil)
239 c.Assert(err, check.IsNil)
240 err = copyFromOS(s.fs, "/home/A Project/TestSnapshotSplice src2", "..") // arvados.git/sdk/go
241 c.Assert(err, check.IsNil)
244 err = s.client.RequestAndDecode(&dst, "POST", "arvados/v1/collections", nil, map[string]interface{}{
245 "collection": map[string]string{
246 "name": "TestSnapshotSplice dst",
247 "owner_uuid": fixtureAProjectUUID,
250 c.Assert(err, check.IsNil)
251 defer s.client.RequestAndDecode(nil, "DELETE", "arvados/v1/collections/"+dst.UUID, nil, nil)
253 c.Assert(err, check.IsNil)
254 err = copyFromOS(s.fs, "/home/A Project/TestSnapshotSplice dst", "..") // arvados.git/sdk/go
255 c.Assert(err, check.IsNil)
257 snap1, err := Snapshot(s.fs, "/home/A Project/TestSnapshotSplice src1/ctxlog")
258 c.Assert(err, check.IsNil)
259 err = Splice(s.fs, "/home/A Project/TestSnapshotSplice dst/ctxlog-copy", snap1)
260 c.Assert(err, check.IsNil)
261 err = Splice(s.fs, "/home/A Project/TestSnapshotSplice dst/ctxlog-copy2", snap1)
262 c.Assert(err, check.IsNil)
264 snap2, err := Snapshot(s.fs, "/home/A Project/TestSnapshotSplice dst/ctxlog-copy")
265 c.Assert(err, check.IsNil)
266 err = Splice(s.fs, "/home/A Project/TestSnapshotSplice dst/ctxlog-copy-copy", snap2)
267 c.Assert(err, check.IsNil)
269 snapDst, err := Snapshot(s.fs, "/home/A Project/TestSnapshotSplice dst")
270 c.Assert(err, check.IsNil)
271 err = Splice(s.fs, "/home/A Project/TestSnapshotSplice dst", snapDst)
272 c.Assert(err, check.IsNil)
273 err = Splice(s.fs, "/home/A Project/TestSnapshotSplice dst/copy1", snapDst)
274 c.Assert(err, check.IsNil)
275 err = Splice(s.fs, "/home/A Project/TestSnapshotSplice dst/copy2", snapDst)
276 c.Assert(err, check.IsNil)
277 err = s.fs.RemoveAll("/home/A Project/TestSnapshotSplice dst/arvados")
278 c.Assert(err, check.IsNil)
279 _, err = s.fs.Open("/home/A Project/TestSnapshotSplice dst/arvados/fs_site_test.go")
280 c.Assert(err, check.Equals, os.ErrNotExist)
281 f, err := s.fs.Open("/home/A Project/TestSnapshotSplice dst/copy2/arvados/fs_site_test.go")
282 c.Assert(err, check.IsNil)
284 buf, err := ioutil.ReadAll(f)
285 c.Check(err, check.IsNil)
286 c.Check(string(buf), check.Not(check.Equals), "")
288 c.Assert(err, check.IsNil)