| // Copyright 2017 Google Inc. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| package bazel |
| |
| import ( |
| "errors" |
| "fmt" |
| "io/ioutil" |
| "os" |
| "strings" |
| "testing" |
| ) |
| |
| // makeAndEnterTempdir creates a temporary directory and chdirs into it. |
| func makeAndEnterTempdir() (func(), error) { |
| oldCwd, err := os.Getwd() |
| if err != nil { |
| return nil, fmt.Errorf("cannot get path to current directory: %v", err) |
| } |
| |
| tempDir, err := ioutil.TempDir("", "test") |
| if err != nil { |
| return nil, fmt.Errorf("failed to create temporary directory: %v", err) |
| } |
| |
| err = os.Chdir(tempDir) |
| if err != nil { |
| os.RemoveAll(tempDir) |
| return nil, fmt.Errorf("cannot enter temporary directory %s: %v", tempDir, err) |
| } |
| |
| cleanup := func() { |
| defer os.RemoveAll(tempDir) |
| defer os.Chdir(oldCwd) |
| } |
| return cleanup, nil |
| } |
| |
| // createPaths creates a collection of paths for testing purposes. Paths can end with a /, in |
| // which case a directory is created; or they can end with a *, in which case an executable file |
| // is created. (This matches the nomenclature of "ls -F".) |
| func createPaths(paths []string) error { |
| for _, path := range paths { |
| if strings.HasSuffix(path, "/") { |
| if err := os.MkdirAll(path, 0755); err != nil { |
| return fmt.Errorf("failed to create directory %s: %v", path, err) |
| } |
| } else { |
| mode := os.FileMode(0644) |
| if strings.HasSuffix(path, "*") { |
| path = path[0 : len(path)-1] |
| mode |= 0111 |
| } |
| if err := ioutil.WriteFile(path, []byte{}, mode); err != nil { |
| return fmt.Errorf("failed to create file %s with mode %v: %v", path, mode, err) |
| } |
| } |
| } |
| return nil |
| } |
| |
| func TestRunfile(t *testing.T) { |
| file := "go/tools/bazel/empty.txt" |
| runfile, err := Runfile(file) |
| if err != nil { |
| t.Errorf("When reading file %s got error %s", file, err) |
| } |
| |
| // Check that the file actually exist |
| if _, err := os.Stat(runfile); err != nil { |
| t.Errorf("File found by runfile doesn't exist") |
| } |
| } |
| |
| func TestRunfilesPath(t *testing.T) { |
| path, err := RunfilesPath() |
| if err != nil { |
| t.Errorf("Error finding runfiles path: %s", err) |
| } |
| |
| if path == "" { |
| t.Errorf("Runfiles path is empty: %s", path) |
| } |
| } |
| |
| func TestNewTmpDir(t *testing.T) { |
| // prefix := "new/temp/dir" |
| prefix := "demodir" |
| tmpdir, err := NewTmpDir(prefix) |
| if err != nil { |
| t.Errorf("When creating temp dir %s got error %s", prefix, err) |
| } |
| |
| // Check that the tempdir actually exist |
| if _, err := os.Stat(tmpdir); err != nil { |
| t.Errorf("New tempdir (%s) not created. Got error %s", tmpdir, err) |
| } |
| } |
| |
| func TestTestTmpDir(t *testing.T) { |
| if TestTmpDir() == "" { |
| t.Errorf("TestTmpDir (TEST_TMPDIR) was left empty") |
| } |
| } |
| |
| func TestTestWorkspace(t *testing.T) { |
| workspace, err := TestWorkspace() |
| |
| if workspace == "" { |
| t.Errorf("Workspace is left empty") |
| } |
| |
| if err != nil { |
| t.Errorf("Unable to get workspace with error %s", err) |
| } |
| } |
| |
| func TestPythonManifest(t *testing.T) { |
| cleanup, err := makeAndEnterTempdir() |
| if err != nil { |
| t.Fatal(err) |
| } |
| defer cleanup() |
| |
| err = ioutil.WriteFile("MANIFEST", |
| // all on one line to make sure the whitespace stays exactly as in the source file |
| []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"), |
| os.FileMode(0644), |
| ) |
| if err != nil { |
| t.Fatalf("Failed to write sample manifest: %v", err) |
| } |
| |
| originalEnvVar := os.Getenv(RUNFILES_MANIFEST_FILE) |
| defer func() { |
| if err = os.Setenv(RUNFILES_MANIFEST_FILE, originalEnvVar); err != nil { |
| t.Fatalf("Failed to reset environment: %v", err) |
| } |
| }() |
| |
| if err = os.Setenv(RUNFILES_MANIFEST_FILE, "MANIFEST"); err != nil { |
| t.Fatalf("Failed to set manifest file environement variable: %v", err) |
| } |
| |
| initRunfiles() |
| |
| if runfiles.err != nil { |
| t.Errorf("failed to init runfiles: %v", runfiles.err) |
| } |
| |
| entry, ok := runfiles.index.GetIgnoringWorkspace("important.txt") |
| if !ok { |
| t.Errorf("failed to locate runfile %s in index", "important.txt") |
| } |
| |
| if entry.Workspace != "__main__" { |
| t.Errorf("incorrect workspace for runfile. Expected: %s, actual %s", "__main__", entry.Workspace) |
| } |
| } |
| |
| func TestSpliceDelimitedOSArgs(t *testing.T) { |
| testData := map[string]struct { |
| initial []string |
| want []string |
| final []string |
| wantErr error |
| }{ |
| "no args": { |
| []string{}, |
| []string{}, |
| []string{}, |
| nil, |
| }, |
| "empty splice": { |
| []string{"-begin_files", "-end_files"}, |
| []string{}, |
| []string{}, |
| nil, |
| }, |
| "removes inner args": { |
| []string{"-begin_files", "a", "-end_files"}, |
| []string{"a"}, |
| []string{}, |
| nil, |
| }, |
| "preserves outer args": { |
| []string{"a", "-begin_files", "b", "c", "-end_files", "d"}, |
| []string{"b", "c"}, |
| []string{"a", "d"}, |
| nil, |
| }, |
| "complains about missing end delimiter": { |
| []string{"-begin_files"}, |
| []string{}, |
| []string{}, |
| errors.New("error: -begin_files, -end_files not set together or in order"), |
| }, |
| "complains about missing begin delimiter": { |
| []string{"-end_files"}, |
| []string{}, |
| []string{}, |
| errors.New("error: -begin_files, -end_files not set together or in order"), |
| }, |
| "complains about out-of-order delimiter": { |
| []string{"-end_files", "-begin_files"}, |
| []string{}, |
| []string{}, |
| errors.New("error: -begin_files, -end_files not set together or in order"), |
| }, |
| "-- at middle": { |
| []string{"-begin_files", "a", "b", "--", "-end_files"}, |
| []string{}, |
| []string{}, |
| errors.New("error: -begin_files, -end_files not set together or in order"), |
| }, |
| "-- at beginning": { |
| []string{"--", "-begin_files", "a", "-end_files"}, |
| []string{}, |
| []string{"--", "-begin_files", "a", "-end_files"}, |
| nil, |
| }, |
| } |
| for name, tc := range testData { |
| t.Run(name, func(t *testing.T) { |
| os.Args = tc.initial |
| got, err := SpliceDelimitedOSArgs("-begin_files", "-end_files") |
| if err != nil { |
| if tc.wantErr == nil { |
| t.Fatalf("unexpected err: %v", err) |
| } |
| if tc.wantErr.Error() != err.Error() { |
| t.Fatalf("err: want %v, got %v", tc.wantErr, err) |
| } |
| return |
| } |
| if len(tc.want) != len(got) { |
| t.Fatalf("len(want: %d, got %d", len(tc.want), len(got)) |
| } |
| for i, actual := range got { |
| expected := tc.want[i] |
| if expected != actual { |
| t.Errorf("%d: want %v, got %v", i, expected, actual) |
| } |
| } |
| if len(tc.final) != len(os.Args) { |
| t.Fatalf("len(want: %d, os.Args %d", len(tc.final), len(os.Args)) |
| } |
| for i, actual := range os.Args { |
| expected := tc.final[i] |
| if expected != actual { |
| t.Errorf("%d: want %v, os.Args %v", i, expected, actual) |
| } |
| } |
| }) |
| } |
| } |