xref: /aosp_15_r20/external/bazelbuild-rules_go/go/tools/bazel/bazel_test.go (revision 9bb1b549b6a84214c53be0924760be030e66b93a)
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.
14package bazel
15
16import (
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.
26func 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".)
53func 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
73func 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
86func 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
97func 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
111func TestTestTmpDir(t *testing.T) {
112	if TestTmpDir() == "" {
113		t.Errorf("TestTmpDir (TEST_TMPDIR) was left empty")
114	}
115}
116
117func 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
129func 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
172func 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}
268