blob: 52903d9c38b87f09d841db9abba70957fb70b77d [file]
// 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)
}
}
})
}
}