github.com/bazelbuild/rules_go@v0.47.2-0.20240515105122-e7ddb9ea474e/go/tools/bazel/bazel_test.go (about) 1 // Copyright 2017 Google Inc. 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 package bazel 15 16 import ( 17 "errors" 18 "fmt" 19 "io/ioutil" 20 "os" 21 "strings" 22 "testing" 23 ) 24 25 // makeAndEnterTempdir creates a temporary directory and chdirs into it. 26 func makeAndEnterTempdir() (func(), error) { 27 oldCwd, err := os.Getwd() 28 if err != nil { 29 return nil, fmt.Errorf("cannot get path to current directory: %v", err) 30 } 31 32 tempDir, err := ioutil.TempDir("", "test") 33 if err != nil { 34 return nil, fmt.Errorf("failed to create temporary directory: %v", err) 35 } 36 37 err = os.Chdir(tempDir) 38 if err != nil { 39 os.RemoveAll(tempDir) 40 return nil, fmt.Errorf("cannot enter temporary directory %s: %v", tempDir, err) 41 } 42 43 cleanup := func() { 44 defer os.RemoveAll(tempDir) 45 defer os.Chdir(oldCwd) 46 } 47 return cleanup, nil 48 } 49 50 // createPaths creates a collection of paths for testing purposes. Paths can end with a /, in 51 // which case a directory is created; or they can end with a *, in which case an executable file 52 // is created. (This matches the nomenclature of "ls -F".) 53 func createPaths(paths []string) error { 54 for _, path := range paths { 55 if strings.HasSuffix(path, "/") { 56 if err := os.MkdirAll(path, 0755); err != nil { 57 return fmt.Errorf("failed to create directory %s: %v", path, err) 58 } 59 } else { 60 mode := os.FileMode(0644) 61 if strings.HasSuffix(path, "*") { 62 path = path[0 : len(path)-1] 63 mode |= 0111 64 } 65 if err := ioutil.WriteFile(path, []byte{}, mode); err != nil { 66 return fmt.Errorf("failed to create file %s with mode %v: %v", path, mode, err) 67 } 68 } 69 } 70 return nil 71 } 72 73 func TestRunfile(t *testing.T) { 74 file := "go/tools/bazel/empty.txt" 75 runfile, err := Runfile(file) 76 if err != nil { 77 t.Errorf("When reading file %s got error %s", file, err) 78 } 79 80 // Check that the file actually exist 81 if _, err := os.Stat(runfile); err != nil { 82 t.Errorf("File found by runfile doesn't exist") 83 } 84 } 85 86 func TestRunfilesPath(t *testing.T) { 87 path, err := RunfilesPath() 88 if err != nil { 89 t.Errorf("Error finding runfiles path: %s", err) 90 } 91 92 if path == "" { 93 t.Errorf("Runfiles path is empty: %s", path) 94 } 95 } 96 97 func TestNewTmpDir(t *testing.T) { 98 // prefix := "new/temp/dir" 99 prefix := "demodir" 100 tmpdir, err := NewTmpDir(prefix) 101 if err != nil { 102 t.Errorf("When creating temp dir %s got error %s", prefix, err) 103 } 104 105 // Check that the tempdir actually exist 106 if _, err := os.Stat(tmpdir); err != nil { 107 t.Errorf("New tempdir (%s) not created. Got error %s", tmpdir, err) 108 } 109 } 110 111 func TestTestTmpDir(t *testing.T) { 112 if TestTmpDir() == "" { 113 t.Errorf("TestTmpDir (TEST_TMPDIR) was left empty") 114 } 115 } 116 117 func TestTestWorkspace(t *testing.T) { 118 workspace, err := TestWorkspace() 119 120 if workspace == "" { 121 t.Errorf("Workspace is left empty") 122 } 123 124 if err != nil { 125 t.Errorf("Unable to get workspace with error %s", err) 126 } 127 } 128 129 func TestPythonManifest(t *testing.T) { 130 cleanup, err := makeAndEnterTempdir() 131 if err != nil { 132 t.Fatal(err) 133 } 134 defer cleanup() 135 136 err = ioutil.WriteFile("MANIFEST", 137 // all on one line to make sure the whitespace stays exactly as in the source file 138 []byte("__init__.py \n__main__/external/__init__.py \n__main__/external/rules_python/__init__.py \n__main__/external/rules_python/python/__init__.py \n__main__/external/rules_python/python/runfiles/__init__.py \n__main__/external/rules_python/python/runfiles/runfiles.py C:/users/sam/_bazel_sam/pj4cl7d4/external/rules_python/python/runfiles/runfiles.py\n__main__/go_cat_/go_cat.exe C:/users/sam/_bazel_sam/pj4cl7d4/execroot/__main__/bazel-out/x64_windows-opt-exec-2B5CBBC6/bin/go_cat_/go_cat.exe\n__main__/important.txt C:/users/sam/dev/rules_go_runfiles_repro/important.txt\n__main__/parent.exe C:/users/sam/_bazel_sam/pj4cl7d4/execroot/__main__/bazel-out/x64_windows-opt-exec-2B5CBBC6/bin/parent.exe\n__main__/parent.py C:/users/sam/dev/rules_go_runfiles_repro/parent.py\n__main__/parent.zip C:/users/sam/_bazel_sam/pj4cl7d4/execroot/__main__/bazel-out/x64_windows-opt-exec-2B5CBBC6/bin/parent.zip\nrules_python/__init__.py \nrules_python/python/__init__.py \nrules_python/python/runfiles/__init__.py \nrules_python/python/runfiles/runfiles.py C:/users/sam/_bazel_sam/pj4cl7d4/external/rules_python/python/runfiles/runfiles.py"), 139 os.FileMode(0644), 140 ) 141 if err != nil { 142 t.Fatalf("Failed to write sample manifest: %v", err) 143 } 144 145 originalEnvVar := os.Getenv(RUNFILES_MANIFEST_FILE) 146 defer func() { 147 if err = os.Setenv(RUNFILES_MANIFEST_FILE, originalEnvVar); err != nil { 148 t.Fatalf("Failed to reset environment: %v", err) 149 } 150 }() 151 152 if err = os.Setenv(RUNFILES_MANIFEST_FILE, "MANIFEST"); err != nil { 153 t.Fatalf("Failed to set manifest file environement variable: %v", err) 154 } 155 156 initRunfiles() 157 158 if runfiles.err != nil { 159 t.Errorf("failed to init runfiles: %v", runfiles.err) 160 } 161 162 entry, ok := runfiles.index.GetIgnoringWorkspace("important.txt") 163 if !ok { 164 t.Errorf("failed to locate runfile %s in index", "important.txt") 165 } 166 167 if entry.Workspace != "__main__" { 168 t.Errorf("incorrect workspace for runfile. Expected: %s, actual %s", "__main__", entry.Workspace) 169 } 170 } 171 172 func TestSpliceDelimitedOSArgs(t *testing.T) { 173 testData := map[string]struct { 174 initial []string 175 want []string 176 final []string 177 wantErr error 178 }{ 179 "no args": { 180 []string{}, 181 []string{}, 182 []string{}, 183 nil, 184 }, 185 "empty splice": { 186 []string{"-begin_files", "-end_files"}, 187 []string{}, 188 []string{}, 189 nil, 190 }, 191 "removes inner args": { 192 []string{"-begin_files", "a", "-end_files"}, 193 []string{"a"}, 194 []string{}, 195 nil, 196 }, 197 "preserves outer args": { 198 []string{"a", "-begin_files", "b", "c", "-end_files", "d"}, 199 []string{"b", "c"}, 200 []string{"a", "d"}, 201 nil, 202 }, 203 "complains about missing end delimiter": { 204 []string{"-begin_files"}, 205 []string{}, 206 []string{}, 207 errors.New("error: -begin_files, -end_files not set together or in order"), 208 }, 209 "complains about missing begin delimiter": { 210 []string{"-end_files"}, 211 []string{}, 212 []string{}, 213 errors.New("error: -begin_files, -end_files not set together or in order"), 214 }, 215 "complains about out-of-order delimiter": { 216 []string{"-end_files", "-begin_files"}, 217 []string{}, 218 []string{}, 219 errors.New("error: -begin_files, -end_files not set together or in order"), 220 }, 221 "-- at middle": { 222 []string{"-begin_files", "a", "b", "--", "-end_files"}, 223 []string{}, 224 []string{}, 225 errors.New("error: -begin_files, -end_files not set together or in order"), 226 }, 227 "-- at beginning": { 228 []string{"--", "-begin_files", "a", "-end_files"}, 229 []string{}, 230 []string{"--", "-begin_files", "a", "-end_files"}, 231 nil, 232 }, 233 } 234 for name, tc := range testData { 235 t.Run(name, func(t *testing.T) { 236 os.Args = tc.initial 237 got, err := SpliceDelimitedOSArgs("-begin_files", "-end_files") 238 if err != nil { 239 if tc.wantErr == nil { 240 t.Fatalf("unexpected err: %v", err) 241 } 242 if tc.wantErr.Error() != err.Error() { 243 t.Fatalf("err: want %v, got %v", tc.wantErr, err) 244 } 245 return 246 } 247 if len(tc.want) != len(got) { 248 t.Fatalf("len(want: %d, got %d", len(tc.want), len(got)) 249 } 250 for i, actual := range got { 251 expected := tc.want[i] 252 if expected != actual { 253 t.Errorf("%d: want %v, got %v", i, expected, actual) 254 } 255 } 256 if len(tc.final) != len(os.Args) { 257 t.Fatalf("len(want: %d, os.Args %d", len(tc.final), len(os.Args)) 258 } 259 for i, actual := range os.Args { 260 expected := tc.final[i] 261 if expected != actual { 262 t.Errorf("%d: want %v, os.Args %v", i, expected, actual) 263 } 264 } 265 }) 266 } 267 }