1package bzl 2 3/* Copyright 2020 The Bazel Authors. All rights reserved. 4 5Licensed under the Apache License, Version 2.0 (the "License"); 6you may not use this file except in compliance with the License. 7You may obtain a copy of the License at 8 9 http://www.apache.org/licenses/LICENSE-2.0 10 11Unless required by applicable law or agreed to in writing, software 12distributed under the License is distributed on an "AS IS" BASIS, 13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14See the License for the specific language governing permissions and 15limitations under the License. 16*/ 17 18import ( 19 "io/ioutil" 20 "os" 21 "os/exec" 22 "path/filepath" 23 "strings" 24 "testing" 25 26 "github.com/bazelbuild/bazel-gazelle/testtools" 27 "github.com/bazelbuild/rules_go/go/tools/bazel" 28) 29 30var gazellePath = findGazelle() 31 32const testDataPath = "bzl/testdata/" 33 34// TestGazelleBinary runs a gazelle binary with starlib installed on each 35// directory in `testdata/*`. Please see `testdata/README.md` for more 36// information on each test. 37func TestGazelleBinary(t *testing.T) { 38 tests := map[string][]bazel.RunfileEntry{} 39 40 files, err := bazel.ListRunfiles() 41 if err != nil { 42 t.Fatalf("bazel.ListRunfiles() error: %v", err) 43 } 44 for _, f := range files { 45 if strings.HasPrefix(f.ShortPath, testDataPath) { 46 relativePath := strings.TrimPrefix(f.ShortPath, testDataPath) 47 parts := strings.SplitN(relativePath, "/", 2) 48 if len(parts) < 2 { 49 // This file is not a part of a testcase since it must be in a dir that 50 // is the test case and then have a path inside of that. 51 continue 52 } 53 54 tests[parts[0]] = append(tests[parts[0]], f) 55 } 56 } 57 if len(tests) == 0 { 58 t.Fatal("no tests found") 59 } 60 61 for testName, files := range tests { 62 testPath(t, testName, files) 63 } 64} 65 66func testPath(t *testing.T, name string, files []bazel.RunfileEntry) { 67 t.Run(name, func(t *testing.T) { 68 var inputs []testtools.FileSpec 69 var goldens []testtools.FileSpec 70 71 for _, f := range files { 72 path := f.Path 73 trim := testDataPath + name + "/" 74 shortPath := strings.TrimPrefix(f.ShortPath, trim) 75 info, err := os.Stat(path) 76 if err != nil { 77 t.Fatalf("os.Stat(%q) error: %v", path, err) 78 } 79 80 // Skip dirs. 81 if info.IsDir() { 82 continue 83 } 84 85 content, err := ioutil.ReadFile(path) 86 if err != nil { 87 t.Errorf("ioutil.ReadFile(%q) error: %v", path, err) 88 } 89 90 // Now trim the common prefix off. 91 if strings.HasSuffix(shortPath, ".in") { 92 inputs = append(inputs, testtools.FileSpec{ 93 Path: strings.TrimSuffix(shortPath, ".in"), 94 Content: string(content), 95 }) 96 } else if strings.HasSuffix(shortPath, ".out") { 97 goldens = append(goldens, testtools.FileSpec{ 98 Path: strings.TrimSuffix(shortPath, ".out"), 99 Content: string(content), 100 }) 101 } else { 102 inputs = append(inputs, testtools.FileSpec{ 103 Path: shortPath, 104 Content: string(content), 105 }) 106 goldens = append(goldens, testtools.FileSpec{ 107 Path: shortPath, 108 Content: string(content), 109 }) 110 } 111 } 112 113 dir, cleanup := testtools.CreateFiles(t, inputs) 114 defer cleanup() 115 116 cmd := exec.Command(gazellePath, "-build_file_name=BUILD") 117 cmd.Stdout = os.Stdout 118 cmd.Stderr = os.Stderr 119 cmd.Dir = dir 120 if err := cmd.Run(); err != nil { 121 t.Fatal(err) 122 } 123 124 testtools.CheckFiles(t, dir, goldens) 125 if t.Failed() { 126 filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { 127 if err != nil { 128 return err 129 } 130 t.Logf("%q exists", path) 131 return nil 132 }) 133 } 134 }) 135} 136 137func findGazelle() string { 138 gazellePath, ok := bazel.FindBinary("bzl", "gazelle-skylib") 139 if !ok { 140 panic("could not find gazelle binary") 141 } 142 return gazellePath 143} 144