Merge branch '21366-subprocess-output-loading-bug' into main. Closes #21366
[arvados.git] / lib / crunchrun / git_mount_test.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package crunchrun
6
7 import (
8         "io/ioutil"
9         "os"
10         "path/filepath"
11
12         "git.arvados.org/arvados.git/sdk/go/arvados"
13         "git.arvados.org/arvados.git/sdk/go/arvadostest"
14         check "gopkg.in/check.v1"
15         git_client "gopkg.in/src-d/go-git.v4/plumbing/transport/client"
16         git_http "gopkg.in/src-d/go-git.v4/plumbing/transport/http"
17 )
18
19 type GitMountSuite struct {
20         tmpdir string
21 }
22
23 var _ = check.Suite(&GitMountSuite{})
24
25 func (s *GitMountSuite) SetUpTest(c *check.C) {
26         var err error
27         s.tmpdir, err = ioutil.TempDir("", "")
28         c.Assert(err, check.IsNil)
29         git_client.InstallProtocol("https", git_http.NewClient(arvados.InsecureHTTPClient))
30 }
31
32 func (s *GitMountSuite) TearDownTest(c *check.C) {
33         err := os.RemoveAll(s.tmpdir)
34         c.Check(err, check.IsNil)
35 }
36
37 // Commit fd3531f is crunch-run-tree-test
38 func (s *GitMountSuite) TestExtractTree(c *check.C) {
39         gm := gitMount{
40                 Path:   "/",
41                 UUID:   arvadostest.Repository2UUID,
42                 Commit: "fd3531f42995344f36c30b79f55f27b502f3d344",
43         }
44         ac := arvados.NewClientFromEnv()
45         err := gm.extractTree(ac, s.tmpdir, arvadostest.ActiveToken)
46         c.Check(err, check.IsNil)
47
48         fnm := filepath.Join(s.tmpdir, "dir1/dir2/file with mode 0644")
49         data, err := ioutil.ReadFile(fnm)
50         c.Check(err, check.IsNil)
51         c.Check(data, check.DeepEquals, []byte{0, 1, 2, 3})
52         fi, err := os.Stat(fnm)
53         c.Check(err, check.IsNil)
54         if err == nil {
55                 c.Check(fi.Mode(), check.Equals, os.FileMode(0644))
56         }
57
58         fnm = filepath.Join(s.tmpdir, "dir1/dir2/file with mode 0755")
59         data, err = ioutil.ReadFile(fnm)
60         c.Check(err, check.IsNil)
61         c.Check(string(data), check.DeepEquals, "#!/bin/sh\nexec echo OK\n")
62         fi, err = os.Stat(fnm)
63         c.Check(err, check.IsNil)
64         if err == nil {
65                 c.Check(fi.Mode(), check.Equals, os.FileMode(0755))
66         }
67
68         // Ensure there's no extra stuff like a ".git" dir
69         s.checkTmpdirContents(c, []string{"dir1"})
70
71         // Ensure tmpdir is world-readable and world-executable so the
72         // UID inside the container can use it.
73         fi, err = os.Stat(s.tmpdir)
74         c.Check(err, check.IsNil)
75         c.Check(fi.Mode()&os.ModePerm, check.Equals, os.FileMode(0755))
76 }
77
78 // Commit 5ebfab0 is not the tip of any branch or tag, but is
79 // reachable in branch "crunch-run-non-tip-test".
80 func (s *GitMountSuite) TestExtractNonTipCommit(c *check.C) {
81         gm := gitMount{
82                 UUID:   arvadostest.Repository2UUID,
83                 Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e",
84         }
85         err := gm.extractTree(arvados.NewClientFromEnv(), s.tmpdir, arvadostest.ActiveToken)
86         c.Check(err, check.IsNil)
87
88         fnm := filepath.Join(s.tmpdir, "file only on testbranch")
89         data, err := ioutil.ReadFile(fnm)
90         c.Check(err, check.IsNil)
91         c.Check(string(data), check.DeepEquals, "testfile\n")
92 }
93
94 func (s *GitMountSuite) TestNonexistentRepository(c *check.C) {
95         gm := gitMount{
96                 Path:   "/",
97                 UUID:   "zzzzz-s0uqq-nonexistentrepo",
98                 Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e",
99         }
100         err := gm.extractTree(arvados.NewClientFromEnv(), s.tmpdir, arvadostest.ActiveToken)
101         c.Check(err, check.NotNil)
102         c.Check(err, check.ErrorMatches, ".*repository not found.*")
103
104         s.checkTmpdirContents(c, []string{})
105 }
106
107 func (s *GitMountSuite) TestNonexistentCommit(c *check.C) {
108         gm := gitMount{
109                 Path:   "/",
110                 UUID:   arvadostest.Repository2UUID,
111                 Commit: "bb66b6bb6b6bbb6b6b6b66b6b6b6b6b6b6b6b66b",
112         }
113         err := gm.extractTree(arvados.NewClientFromEnv(), s.tmpdir, arvadostest.ActiveToken)
114         c.Check(err, check.NotNil)
115         c.Check(err, check.ErrorMatches, ".*object not found.*")
116
117         s.checkTmpdirContents(c, []string{})
118 }
119
120 func (s *GitMountSuite) TestGitUrlDiscoveryFails(c *check.C) {
121         delete(discoveryMap, "gitUrl")
122         gm := gitMount{
123                 Path:   "/",
124                 UUID:   arvadostest.Repository2UUID,
125                 Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e",
126         }
127         err := gm.extractTree(&arvados.Client{}, s.tmpdir, arvadostest.ActiveToken)
128         c.Check(err, check.ErrorMatches, ".*error getting discovery doc.*")
129 }
130
131 func (s *GitMountSuite) TestInvalid(c *check.C) {
132         for _, trial := range []struct {
133                 gm      gitMount
134                 matcher string
135         }{
136                 {
137                         gm: gitMount{
138                                 Path:   "/",
139                                 UUID:   arvadostest.Repository2UUID,
140                                 Commit: "abc123",
141                         },
142                         matcher: ".*SHA1.*",
143                 },
144                 {
145                         gm: gitMount{
146                                 Path:           "/",
147                                 UUID:           arvadostest.Repository2UUID,
148                                 RepositoryName: arvadostest.Repository2Name,
149                                 Commit:         "5ebfab0522851df01fec11ec55a6d0f4877b542e",
150                         },
151                         matcher: ".*repository_name.*",
152                 },
153                 {
154                         gm: gitMount{
155                                 Path:   "/",
156                                 GitURL: "https://localhost:0/" + arvadostest.Repository2Name + ".git",
157                                 Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e",
158                         },
159                         matcher: ".*git_url.*",
160                 },
161                 {
162                         gm: gitMount{
163                                 Path:   "/dir1/",
164                                 UUID:   arvadostest.Repository2UUID,
165                                 Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e",
166                         },
167                         matcher: ".*path.*",
168                 },
169                 {
170                         gm: gitMount{
171                                 Path:   "/",
172                                 Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e",
173                         },
174                         matcher: ".*UUID.*",
175                 },
176                 {
177                         gm: gitMount{
178                                 Path:     "/",
179                                 UUID:     arvadostest.Repository2UUID,
180                                 Commit:   "5ebfab0522851df01fec11ec55a6d0f4877b542e",
181                                 Writable: true,
182                         },
183                         matcher: ".*writable.*",
184                 },
185         } {
186                 err := trial.gm.extractTree(arvados.NewClientFromEnv(), s.tmpdir, arvadostest.ActiveToken)
187                 c.Check(err, check.NotNil)
188                 s.checkTmpdirContents(c, []string{})
189
190                 err = trial.gm.validate()
191                 c.Check(err, check.ErrorMatches, trial.matcher)
192         }
193 }
194
195 func (s *GitMountSuite) checkTmpdirContents(c *check.C, expect []string) {
196         f, err := os.Open(s.tmpdir)
197         c.Check(err, check.IsNil)
198         names, err := f.Readdirnames(-1)
199         c.Check(err, check.IsNil)
200         c.Check(names, check.DeepEquals, expect)
201 }