1// Copyright 2020, 2021, 2022 Google LLC 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// https://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 15package runfiles_test 16 17import ( 18 "errors" 19 "os" 20 "os/exec" 21 "path/filepath" 22 "runtime" 23 "strings" 24 "testing" 25 26 "github.com/bazelbuild/rules_go/go/runfiles" 27) 28 29func TestPath_FileLookup(t *testing.T) { 30 path, err := runfiles.Rlocation("io_bazel_rules_go/tests/runfiles/test.txt") 31 if err != nil { 32 t.Fatal(err) 33 } 34 b, err := os.ReadFile(path) 35 if err != nil { 36 t.Fatal(err) 37 } 38 got := strings.TrimSpace(string(b)) 39 want := "hi!" 40 if got != want { 41 t.Errorf("got %q, want %q", got, want) 42 } 43} 44 45func TestPath_SubprocessRunfilesLookup(t *testing.T) { 46 r, err := runfiles.New() 47 if err != nil { 48 panic(err) 49 } 50 // The binary “testprog” is itself built with Bazel, and needs 51 // runfiles. 52 testprogRpath := "io_bazel_rules_go/tests/runfiles/testprog/testprog_/testprog" 53 if runtime.GOOS == "windows" { 54 testprogRpath += ".exe" 55 } 56 prog, err := r.Rlocation(testprogRpath) 57 if err != nil { 58 panic(err) 59 } 60 cmd := exec.Command(prog) 61 // We add r.Env() after os.Environ() so that runfile environment 62 // variables override anything set in the process environment. 63 cmd.Env = append(os.Environ(), r.Env()...) 64 out, err := cmd.Output() 65 if err != nil { 66 t.Fatal(err) 67 } 68 got := strings.TrimSpace(string(out)) 69 want := "hi!" 70 if got != want { 71 t.Errorf("got %q, want %q", got, want) 72 } 73} 74 75func TestPath_errors(t *testing.T) { 76 r, err := runfiles.New() 77 if err != nil { 78 t.Fatal(err) 79 } 80 for _, s := range []string{"", "/..", "../", "a/../b", "a//b", "a/./b", `\a`} { 81 t.Run(s, func(t *testing.T) { 82 if got, err := r.Rlocation(s); err == nil { 83 t.Errorf("got %q, want error", got) 84 } 85 }) 86 } 87 for _, s := range []string{"foo/..bar", "foo/.bar"} { 88 t.Run(s, func(t *testing.T) { 89 if _, err := r.Rlocation(s); err != nil && !os.IsNotExist(err.(runfiles.Error).Err) { 90 t.Errorf("got %q, want none or 'file not found' error", err) 91 } 92 }) 93 } 94} 95 96func TestRunfiles_zero(t *testing.T) { 97 var r runfiles.Runfiles 98 if got, err := r.Rlocation("a"); err == nil { 99 t.Errorf("Rlocation: got %q, want error", got) 100 } 101 if got := r.Env(); got != nil { 102 t.Errorf("Env: got %v, want nil", got) 103 } 104} 105 106func TestRunfiles_empty(t *testing.T) { 107 dir := t.TempDir() 108 manifest := filepath.Join(dir, "manifest") 109 if err := os.WriteFile(manifest, []byte("__init__.py \n"), 0o600); err != nil { 110 t.Fatal(err) 111 } 112 r, err := runfiles.New(runfiles.ManifestFile(manifest)) 113 if err != nil { 114 t.Fatal(err) 115 } 116 _, got := r.Rlocation("__init__.py") 117 want := runfiles.ErrEmpty 118 if !errors.Is(got, want) { 119 t.Errorf("Rlocation for empty file: got error %q, want something that wraps %q", got, want) 120 } 121} 122 123func TestRunfiles_manifestWithDir(t *testing.T) { 124 dir := t.TempDir() 125 manifest := filepath.Join(dir, "manifest") 126 if err := os.WriteFile(manifest, []byte("foo/dir path/to/foo/dir\n"), 0o600); err != nil { 127 t.Fatal(err) 128 } 129 r, err := runfiles.New(runfiles.ManifestFile(manifest)) 130 if err != nil { 131 t.Fatal(err) 132 } 133 134 for rlocation, want := range map[string]string{ 135 "foo/dir": filepath.FromSlash("path/to/foo/dir"), 136 "foo/dir/file": filepath.FromSlash("path/to/foo/dir/file"), 137 "foo/dir/deeply/nested/file": filepath.FromSlash("path/to/foo/dir/deeply/nested/file"), 138 } { 139 t.Run(rlocation, func(t *testing.T) { 140 got, err := r.Rlocation(rlocation) 141 if err != nil { 142 t.Fatalf("Rlocation failed: got unexpected error %q", err) 143 } 144 if got != want { 145 t.Errorf("Rlocation failed: got %q, want %q", got, want) 146 } 147 }) 148 } 149} 150