go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/client/isolate/isolate_test.go (about) 1 // Copyright 2015 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package isolate 16 17 import ( 18 "io" 19 "log" 20 "os" 21 "path/filepath" 22 "regexp" 23 "strings" 24 "testing" 25 26 . "github.com/smartystreets/goconvey/convey" 27 28 "go.chromium.org/luci/common/system/filesystem" 29 ) 30 31 func init() { 32 log.SetOutput(io.Discard) 33 } 34 35 func TestReplaceVars(t *testing.T) { 36 t.Parallel() 37 Convey(`Variables replacement should be supported in isolate files.`, t, func() { 38 39 opts := &ArchiveOptions{PathVariables: map[string]string{"VAR": "wonderful"}} 40 41 // Single replacement. 42 r, err := ReplaceVariables("hello <(VAR) world", opts) 43 So(err, ShouldBeNil) 44 So(r, ShouldResemble, "hello wonderful world") 45 46 // Multiple replacement. 47 r, err = ReplaceVariables("hello <(VAR) <(VAR) world", opts) 48 So(err, ShouldBeNil) 49 So(r, ShouldResemble, "hello wonderful wonderful world") 50 51 // Replacement of missing variable. 52 r, err = ReplaceVariables("hello <(MISSING) world", opts) 53 So(err.Error(), ShouldResemble, "no value for variable 'MISSING'") 54 }) 55 } 56 57 func TestIgnoredPathsRegexp(t *testing.T) { 58 t.Parallel() 59 60 Convey(`Ignored file extensions`, t, func() { 61 regexStr := genExtensionsRegex("pyc", "swp") 62 re, err := regexp.Compile(regexStr) 63 So(err, ShouldBeNil) 64 So(re.MatchString("a.pyc"), ShouldBeTrue) 65 So(re.MatchString("foo/a.pyc"), ShouldBeTrue) 66 So(re.MatchString("/b.swp"), ShouldBeTrue) 67 So(re.MatchString(`foo\b.swp`), ShouldBeTrue) 68 69 So(re.MatchString("a.py"), ShouldBeFalse) 70 So(re.MatchString("b.swppp"), ShouldBeFalse) 71 }) 72 73 Convey(`Ignored directories`, t, func() { 74 regexStr := genDirectoriesRegex("\\.git", "\\.hg", "\\.svn") 75 re, err := regexp.Compile(regexStr) 76 So(err, ShouldBeNil) 77 So(re.MatchString(".git"), ShouldBeTrue) 78 So(re.MatchString(".git/"), ShouldBeTrue) 79 So(re.MatchString("/.git/"), ShouldBeTrue) 80 So(re.MatchString("/.hg"), ShouldBeTrue) 81 So(re.MatchString("foo/.svn"), ShouldBeTrue) 82 So(re.MatchString(`.hg\`), ShouldBeTrue) 83 So(re.MatchString(`foo\.svn`), ShouldBeTrue) 84 85 So(re.MatchString(".get"), ShouldBeFalse) 86 So(re.MatchString("foo.git"), ShouldBeFalse) 87 So(re.MatchString(".svnnnn"), ShouldBeFalse) 88 }) 89 } 90 91 func TestProcessIsolateFile(t *testing.T) { 92 t.Parallel() 93 94 Convey(`Directory deps should end with osPathSeparator`, t, func() { 95 tmpDir := t.TempDir() 96 baseDir := filepath.Join(tmpDir, "baseDir") 97 secondDir := filepath.Join(tmpDir, "secondDir") 98 So(os.Mkdir(baseDir, 0700), ShouldBeNil) 99 So(os.Mkdir(secondDir, 0700), ShouldBeNil) 100 So(os.WriteFile(filepath.Join(baseDir, "foo"), []byte("foo"), 0600), ShouldBeNil) 101 // Note that for "secondDir", its separator is omitted intentionally. 102 isolate := `{ 103 'variables': { 104 'files': [ 105 '../baseDir/', 106 '../secondDir', 107 '../baseDir/foo', 108 ], 109 }, 110 }` 111 112 outDir := filepath.Join(tmpDir, "out") 113 So(os.Mkdir(outDir, 0700), ShouldBeNil) 114 isolatePath := filepath.Join(outDir, "my.isolate") 115 So(os.WriteFile(isolatePath, []byte(isolate), 0600), ShouldBeNil) 116 117 opts := &ArchiveOptions{ 118 Isolate: isolatePath, 119 } 120 121 deps, _, err := ProcessIsolate(opts) 122 So(err, ShouldBeNil) 123 for _, dep := range deps { 124 isDir, err := filesystem.IsDir(dep) 125 So(err, ShouldBeNil) 126 So(strings.HasSuffix(dep, osPathSeparator), ShouldEqual, isDir) 127 } 128 }) 129 130 Convey(`Allow missing files and dirs`, t, func() { 131 tmpDir := t.TempDir() 132 dir1 := filepath.Join(tmpDir, "dir1") 133 So(os.Mkdir(dir1, 0700), ShouldBeNil) 134 dir2 := filepath.Join(tmpDir, "dir2") 135 So(os.Mkdir(dir2, 0700), ShouldBeNil) 136 So(os.WriteFile(filepath.Join(dir2, "foo"), []byte("foo"), 0600), ShouldBeNil) 137 isolate := `{ 138 'variables': { 139 'files': [ 140 '../dir1/', 141 '../dir2/foo', 142 '../nodir1/', 143 '../nodir2/nofile', 144 ], 145 }, 146 }` 147 148 outDir := filepath.Join(tmpDir, "out") 149 So(os.Mkdir(outDir, 0700), ShouldBeNil) 150 isolatePath := filepath.Join(outDir, "my.isolate") 151 So(os.WriteFile(isolatePath, []byte(isolate), 0600), ShouldBeNil) 152 153 opts := &ArchiveOptions{ 154 Isolate: isolatePath, 155 AllowMissingFileDir: false, 156 } 157 158 _, _, err := ProcessIsolate(opts) 159 So(err, ShouldNotBeNil) 160 161 opts = &ArchiveOptions{ 162 Isolate: isolatePath, 163 AllowMissingFileDir: true, 164 } 165 166 deps, _, err := ProcessIsolate(opts) 167 So(err, ShouldBeNil) 168 So(deps, ShouldResemble, []string{dir1 + osPathSeparator, filepath.Join(dir2, "foo")}) 169 }) 170 }