13111: Add tests for /users/ paths.
[arvados.git] / services / keep-web / cadaver_test.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package main
6
7 import (
8         "bytes"
9         "fmt"
10         "io"
11         "io/ioutil"
12         "net/url"
13         "os"
14         "os/exec"
15         "path/filepath"
16         "strings"
17         "time"
18
19         "git.curoverse.com/arvados.git/sdk/go/arvados"
20         "git.curoverse.com/arvados.git/sdk/go/arvadostest"
21         check "gopkg.in/check.v1"
22 )
23
24 func (s *IntegrationSuite) TestCadaverHTTPAuth(c *check.C) {
25         s.testCadaver(c, arvadostest.ActiveToken, func(newCollection arvados.Collection) (string, string, string) {
26                 r := "/c=" + arvadostest.FooAndBarFilesInDirUUID + "/"
27                 w := "/c=" + newCollection.UUID + "/"
28                 pdh := "/c=" + strings.Replace(arvadostest.FooAndBarFilesInDirPDH, "+", "-", -1) + "/"
29                 return r, w, pdh
30         })
31 }
32
33 func (s *IntegrationSuite) TestCadaverPathAuth(c *check.C) {
34         s.testCadaver(c, "", func(newCollection arvados.Collection) (string, string, string) {
35                 r := "/c=" + arvadostest.FooAndBarFilesInDirUUID + "/t=" + arvadostest.ActiveToken + "/"
36                 w := "/c=" + newCollection.UUID + "/t=" + arvadostest.ActiveToken + "/"
37                 pdh := "/c=" + strings.Replace(arvadostest.FooAndBarFilesInDirPDH, "+", "-", -1) + "/t=" + arvadostest.ActiveToken + "/"
38                 return r, w, pdh
39         })
40 }
41
42 func (s *IntegrationSuite) TestCadaverUserProject(c *check.C) {
43         s.testCadaver(c, arvadostest.ActiveToken, func(newCollection arvados.Collection) (string, string, string) {
44                 r := "/users/active/foo_file_in_dir/"
45                 w := "/users/active/" + newCollection.Name
46                 pdh := "/c=" + strings.Replace(arvadostest.FooAndBarFilesInDirPDH, "+", "-", -1) + "/"
47                 return r, w, pdh
48         })
49 }
50
51 func (s *IntegrationSuite) testCadaver(c *check.C, password string, pathFunc func(arvados.Collection) (string, string, string)) {
52         testdata := []byte("the human tragedy consists in the necessity of living with the consequences of actions performed under the pressure of compulsions we do not understand")
53
54         tempdir, err := ioutil.TempDir("", "keep-web-test-")
55         c.Assert(err, check.IsNil)
56         defer os.RemoveAll(tempdir)
57
58         localfile, err := ioutil.TempFile(tempdir, "localfile")
59         c.Assert(err, check.IsNil)
60         localfile.Write(testdata)
61
62         emptyfile, err := ioutil.TempFile(tempdir, "emptyfile")
63         c.Assert(err, check.IsNil)
64
65         checkfile, err := ioutil.TempFile(tempdir, "checkfile")
66         c.Assert(err, check.IsNil)
67
68         var newCollection arvados.Collection
69         arv := arvados.NewClientFromEnv()
70         arv.AuthToken = arvadostest.ActiveToken
71         err = arv.RequestAndDecode(&newCollection, "POST", "/arvados/v1/collections", bytes.NewBufferString(url.Values{"collection": {"{}"}}.Encode()), nil)
72         c.Assert(err, check.IsNil)
73
74         readPath, writePath, pdhPath := pathFunc(newCollection)
75
76         matchToday := time.Now().Format("Jan +2")
77
78         type testcase struct {
79                 path  string
80                 cmd   string
81                 match string
82                 data  []byte
83         }
84         for _, trial := range []testcase{
85                 {
86                         path:  readPath,
87                         cmd:   "ls\n",
88                         match: `(?ms).*dir1 *0 .*`,
89                 },
90                 {
91                         path:  readPath,
92                         cmd:   "ls dir1\n",
93                         match: `(?ms).*bar *3.*foo *3 .*`,
94                 },
95                 {
96                         path:  readPath + "_/dir1",
97                         cmd:   "ls\n",
98                         match: `(?ms).*bar *3.*foo *3 .*`,
99                 },
100                 {
101                         path:  readPath + "dir1/",
102                         cmd:   "ls\n",
103                         match: `(?ms).*bar *3.*foo +3 +Feb +\d+ +2014.*`,
104                 },
105                 {
106                         path:  writePath,
107                         cmd:   "get emptyfile '" + checkfile.Name() + "'\n",
108                         match: `(?ms).*Not Found.*`,
109                 },
110                 {
111                         path:  writePath,
112                         cmd:   "put '" + emptyfile.Name() + "' emptyfile\n",
113                         match: `(?ms).*Uploading .* succeeded.*`,
114                 },
115                 {
116                         path:  writePath,
117                         cmd:   "get emptyfile '" + checkfile.Name() + "'\n",
118                         match: `(?ms).*Downloading .* succeeded.*`,
119                         data:  []byte{},
120                 },
121                 {
122                         path:  writePath,
123                         cmd:   "put '" + localfile.Name() + "' testfile\n",
124                         match: `(?ms).*Uploading .* succeeded.*`,
125                 },
126                 {
127                         path:  writePath,
128                         cmd:   "get testfile '" + checkfile.Name() + "'\n",
129                         match: `(?ms).*succeeded.*`,
130                         data:  testdata,
131                 },
132                 {
133                         path:  writePath,
134                         cmd:   "move testfile newdir0/\n",
135                         match: `(?ms).*Moving .* succeeded.*`,
136                 },
137                 {
138                         path:  writePath,
139                         cmd:   "move testfile newdir0/\n",
140                         match: `(?ms).*Moving .* failed.*`,
141                 },
142                 {
143                         path:  writePath,
144                         cmd:   "ls\n",
145                         match: `(?ms).*newdir0.* 0 +` + matchToday + ` \d+:\d+\n.*`,
146                 },
147                 {
148                         path:  writePath,
149                         cmd:   "move newdir0/testfile emptyfile/bogus/\n",
150                         match: `(?ms).*Moving .* failed.*`,
151                 },
152                 {
153                         path:  writePath,
154                         cmd:   "mkcol newdir1\n",
155                         match: `(?ms).*Creating .* succeeded.*`,
156                 },
157                 {
158                         path:  writePath,
159                         cmd:   "move newdir0/testfile newdir1/\n",
160                         match: `(?ms).*Moving .* succeeded.*`,
161                 },
162                 {
163                         path:  writePath,
164                         cmd:   "move newdir1 newdir1/\n",
165                         match: `(?ms).*Moving .* failed.*`,
166                 },
167                 {
168                         path:  writePath,
169                         cmd:   "get newdir1/testfile '" + checkfile.Name() + "'\n",
170                         match: `(?ms).*succeeded.*`,
171                         data:  testdata,
172                 },
173                 {
174                         path:  writePath,
175                         cmd:   "put '" + localfile.Name() + "' newdir1/testfile1\n",
176                         match: `(?ms).*Uploading .* succeeded.*`,
177                 },
178                 {
179                         path:  writePath,
180                         cmd:   "mkcol newdir2\n",
181                         match: `(?ms).*Creating .* succeeded.*`,
182                 },
183                 {
184                         path:  writePath,
185                         cmd:   "put '" + localfile.Name() + "' newdir2/testfile2\n",
186                         match: `(?ms).*Uploading .* succeeded.*`,
187                 },
188                 {
189                         path:  writePath,
190                         cmd:   "copy newdir2/testfile2 testfile3\n",
191                         match: `(?ms).*succeeded.*`,
192                 },
193                 {
194                         path:  writePath,
195                         cmd:   "get testfile3 '" + checkfile.Name() + "'\n",
196                         match: `(?ms).*succeeded.*`,
197                         data:  testdata,
198                 },
199                 {
200                         path:  writePath,
201                         cmd:   "get newdir2/testfile2 '" + checkfile.Name() + "'\n",
202                         match: `(?ms).*succeeded.*`,
203                         data:  testdata,
204                 },
205                 {
206                         path:  writePath,
207                         cmd:   "rmcol newdir2\n",
208                         match: `(?ms).*Deleting collection .* succeeded.*`,
209                 },
210                 {
211                         path:  writePath,
212                         cmd:   "get newdir2/testfile2 '" + checkfile.Name() + "'\n",
213                         match: `(?ms).*Downloading .* failed.*`,
214                 },
215                 {
216                         path:  "/c=" + arvadostest.UserAgreementCollection + "/t=" + arv.AuthToken + "/",
217                         cmd:   "put '" + localfile.Name() + "' foo\n",
218                         match: `(?ms).*Uploading .* failed:.*403 Forbidden.*`,
219                 },
220                 {
221                         path:  pdhPath,
222                         cmd:   "put '" + localfile.Name() + "' foo\n",
223                         match: `(?ms).*Uploading .* failed:.*405 Method Not Allowed.*`,
224                 },
225                 {
226                         path:  pdhPath,
227                         cmd:   "move foo bar\n",
228                         match: `(?ms).*Moving .* failed:.*405 Method Not Allowed.*`,
229                 },
230                 {
231                         path:  pdhPath,
232                         cmd:   "copy foo bar\n",
233                         match: `(?ms).*Copying .* failed:.*405 Method Not Allowed.*`,
234                 },
235                 {
236                         path:  pdhPath,
237                         cmd:   "delete foo\n",
238                         match: `(?ms).*Deleting .* failed:.*405 Method Not Allowed.*`,
239                 },
240         } {
241                 c.Logf("%s %+v", "http://"+s.testServer.Addr, trial)
242
243                 os.Remove(checkfile.Name())
244
245                 cmd := exec.Command("cadaver", "http://"+s.testServer.Addr+trial.path)
246                 if password != "" {
247                         // cadaver won't try username/password
248                         // authentication unless the server responds
249                         // 401 to an unauthenticated request, which it
250                         // only does in AttachmentOnlyHost,
251                         // TrustAllContent, and per-collection vhost
252                         // cases.
253                         s.testServer.Config.AttachmentOnlyHost = s.testServer.Addr
254
255                         cmd.Env = append(os.Environ(), "HOME="+tempdir)
256                         f, err := os.OpenFile(filepath.Join(tempdir, ".netrc"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
257                         c.Assert(err, check.IsNil)
258                         _, err = fmt.Fprintf(f, "default login none password %s\n", password)
259                         c.Assert(err, check.IsNil)
260                         c.Assert(f.Close(), check.IsNil)
261                 }
262                 cmd.Stdin = bytes.NewBufferString(trial.cmd)
263                 stdout, err := cmd.StdoutPipe()
264                 c.Assert(err, check.Equals, nil)
265                 cmd.Stderr = cmd.Stdout
266                 go cmd.Start()
267
268                 var buf bytes.Buffer
269                 _, err = io.Copy(&buf, stdout)
270                 c.Check(err, check.Equals, nil)
271                 err = cmd.Wait()
272                 c.Check(err, check.Equals, nil)
273                 c.Check(buf.String(), check.Matches, trial.match)
274
275                 if trial.data == nil {
276                         continue
277                 }
278                 checkfile, err = os.Open(checkfile.Name())
279                 c.Assert(err, check.IsNil)
280                 checkfile.Seek(0, os.SEEK_SET)
281                 got, err := ioutil.ReadAll(checkfile)
282                 c.Check(got, check.DeepEquals, trial.data)
283                 c.Check(err, check.IsNil)
284         }
285 }