// Copyright 2019 The Bazel Authors. All rights reserved. // // 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 check import ( "fmt" "os" "path/filepath" "runtime" "sort" "strings" "github.com/bazelbuild/rules_go/go/tools/bazel" ) type TestFile struct { Workspace, ShortPath, Path string Binary bool } var DefaultTestFiles = []TestFile{ {Workspace: "io_bazel_rules_go", Path: "tests/core/runfiles/local_file.txt"}, {Workspace: "io_bazel_rules_go", Path: "tests/core/runfiles/local_group.txt"}, {Workspace: "io_bazel_rules_go", Path: "tests/core/runfiles/local_bin", Binary: true}, {Workspace: "runfiles_remote_test", Path: "remote_file.txt"}, {Workspace: "runfiles_remote_test", Path: "remote_group.txt"}, {Workspace: "runfiles_remote_test", Path: "remote_bin", Binary: true}, } func CheckRunfiles(files []TestFile) error { // Check that the runfiles directory matches the current workspace. // There is no runfiles directory on Windows. if runtime.GOOS != "windows" { dir, err := bazel.RunfilesPath() if err != nil { return err } root, base := filepath.Dir(dir), filepath.Base(dir) if !strings.HasSuffix(root, ".runfiles") { return fmt.Errorf("RunfilesPath: %q is not a .runfiles directory", dir) } workspace := os.Getenv("TEST_WORKSPACE") if workspace != "" && workspace != base { return fmt.Errorf("RunfilesPath: %q does not match test workspace %s", dir, workspace) } if srcDir := os.Getenv("TEST_SRCDIR"); srcDir != "" && filepath.Join(srcDir, workspace) != dir { return fmt.Errorf("RunfilesPath: %q does not match TEST_SRCDIR %q", dir, srcDir) } } // Check that files can be found with Runfile or FindBinary. // Make sure the paths returned are absolute paths to actual files. seen := make(map[string]string) for _, f := range files { var got string var err error if !f.Binary { if got, err = bazel.Runfile(f.Path); err != nil { return err } if !filepath.IsAbs(got) { return fmt.Errorf("Runfile %s: got a relative path %q; want absolute", f.Path, got) } seen[f.Path] = got } else { var pkg, name string if i := strings.LastIndex(f.Path, "/"); i < 0 { name = f.Path } else { pkg = f.Path[:i] name = f.Path[i+1:] } var ok bool if got, ok = bazel.FindBinary(pkg, name); !ok { return fmt.Errorf("FindBinary %s %s: could not find binary", pkg, name) } if !filepath.IsAbs(got) { return fmt.Errorf("FindBinary %s %s: got a relative path %q; want absolute", pkg, name, got) } } if _, err := os.Stat(got); err != nil { return fmt.Errorf("%s: could not stat: %v", f.Path, err) } } // Check that the files can be listed. entries, err := bazel.ListRunfiles() if err != nil { return err } for _, e := range entries { if want, ok := seen[e.ShortPath]; ok && want != e.Path { return err } delete(seen, e.ShortPath) } if len(seen) > 0 { unseen := make([]string, 0, len(seen)) for short := range seen { unseen = append(unseen, short) } sort.Strings(unseen) return fmt.Errorf("ListRunfiles did not include files:\n\t%s", strings.Join(unseen, "\n\t")) } return nil }