blob: dd8c2411f19c90e4e6ec1cf5a432bb3f69760d98 [file] [log] [blame]
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +09001/* Copyright 2020 The Bazel Authors. All rights reserved.
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14*/
15
16// This test file was first seen on:
17// https://github.com/bazelbuild/bazel-skylib/blob/f80bc733d4b9f83d427ce3442be2e07427b2cc8d/gazelle/bzl/BUILD.
18// It was modified for the needs of this extension.
19
20package python_test
21
22import (
23 "bytes"
24 "context"
25 "errors"
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +090026 "os"
27 "os/exec"
28 "path/filepath"
29 "strings"
30 "testing"
31 "time"
32
33 "github.com/bazelbuild/bazel-gazelle/testtools"
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +090034 "github.com/bazelbuild/rules_go/go/tools/bazel"
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +090035 "github.com/ghodss/yaml"
36)
37
38const (
Ignas Anikeviciusfd5f5312023-01-26 04:20:12 +090039 extensionDir = "python" + string(os.PathSeparator)
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +090040 testDataPath = extensionDir + "testdata" + string(os.PathSeparator)
41 gazelleBinaryName = "gazelle_binary"
42)
43
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +090044func TestGazelleBinary(t *testing.T) {
hunshcn7fc79622024-05-20 12:21:52 +080045 gazellePath := mustFindGazelle()
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +090046 tests := map[string][]bazel.RunfileEntry{}
47
48 runfiles, err := bazel.ListRunfiles()
49 if err != nil {
50 t.Fatalf("bazel.ListRunfiles() error: %v", err)
51 }
52 for _, f := range runfiles {
53 if strings.HasPrefix(f.ShortPath, testDataPath) {
54 relativePath := strings.TrimPrefix(f.ShortPath, testDataPath)
55 parts := strings.SplitN(relativePath, string(os.PathSeparator), 2)
56 if len(parts) < 2 {
57 // This file is not a part of a testcase since it must be in a dir that
58 // is the test case and then have a path inside of that.
59 continue
60 }
61
62 tests[parts[0]] = append(tests[parts[0]], f)
63 }
64 }
65 if len(tests) == 0 {
66 t.Fatal("no tests found")
67 }
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +090068 for testName, files := range tests {
hunshcn7fc79622024-05-20 12:21:52 +080069 testPath(t, gazellePath, testName, files)
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +090070 }
71}
72
hunshcn7fc79622024-05-20 12:21:52 +080073func testPath(t *testing.T, gazellePath, name string, files []bazel.RunfileEntry) {
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +090074 t.Run(name, func(t *testing.T) {
Ignas Anikevicius1e869d82023-04-11 03:45:45 +090075 t.Parallel()
76 var inputs, goldens []testtools.FileSpec
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +090077
78 var config *testYAML
79 for _, f := range files {
80 path := f.Path
81 trim := filepath.Join(testDataPath, name) + string(os.PathSeparator)
82 shortPath := strings.TrimPrefix(f.ShortPath, trim)
83 info, err := os.Stat(path)
84 if err != nil {
85 t.Fatalf("os.Stat(%q) error: %v", path, err)
86 }
87
88 if info.IsDir() {
89 continue
90 }
91
92 content, err := os.ReadFile(path)
93 if err != nil {
94 t.Errorf("os.ReadFile(%q) error: %v", path, err)
95 }
96
97 if filepath.Base(shortPath) == "test.yaml" {
98 if config != nil {
99 t.Fatal("only 1 test.yaml is supported")
100 }
101 config = new(testYAML)
102 if err := yaml.Unmarshal(content, config); err != nil {
103 t.Fatal(err)
104 }
105 }
106
107 if strings.HasSuffix(shortPath, ".in") {
108 inputs = append(inputs, testtools.FileSpec{
109 Path: filepath.Join(name, strings.TrimSuffix(shortPath, ".in")),
110 Content: string(content),
111 })
Ignas Anikevicius1e869d82023-04-11 03:45:45 +0900112 continue
113 }
114
115 if strings.HasSuffix(shortPath, ".out") {
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +0900116 goldens = append(goldens, testtools.FileSpec{
117 Path: filepath.Join(name, strings.TrimSuffix(shortPath, ".out")),
118 Content: string(content),
119 })
Ignas Anikevicius1e869d82023-04-11 03:45:45 +0900120 continue
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +0900121 }
Ignas Anikevicius1e869d82023-04-11 03:45:45 +0900122
123 inputs = append(inputs, testtools.FileSpec{
124 Path: filepath.Join(name, shortPath),
125 Content: string(content),
126 })
127 goldens = append(goldens, testtools.FileSpec{
128 Path: filepath.Join(name, shortPath),
129 Content: string(content),
130 })
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +0900131 }
132
133 testdataDir, cleanup := testtools.CreateFiles(t, inputs)
Ignas Anikevicius1e869d82023-04-11 03:45:45 +0900134 t.Cleanup(cleanup)
135 t.Cleanup(func() {
136 if !t.Failed() {
137 return
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +0900138 }
Ignas Anikevicius1e869d82023-04-11 03:45:45 +0900139
140 filepath.Walk(testdataDir, func(path string, info os.FileInfo, err error) error {
141 if err != nil {
142 return err
143 }
144 t.Logf("%q exists", strings.TrimPrefix(path, testdataDir))
145 return nil
146 })
147 })
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +0900148
149 workspaceRoot := filepath.Join(testdataDir, name)
150
151 args := []string{"-build_file_name=BUILD,BUILD.bazel"}
152
153 ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
Ignas Anikevicius1e869d82023-04-11 03:45:45 +0900154 t.Cleanup(cancel)
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +0900155 cmd := exec.CommandContext(ctx, gazellePath, args...)
156 var stdout, stderr bytes.Buffer
157 cmd.Stdout = &stdout
158 cmd.Stderr = &stderr
159 cmd.Dir = workspaceRoot
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +0900160 if err := cmd.Run(); err != nil {
161 var e *exec.ExitError
162 if !errors.As(err, &e) {
163 t.Fatal(err)
164 }
165 }
Zhongpeng Lind9ed9c92023-02-08 19:14:35 -0800166
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +0900167 actualExitCode := cmd.ProcessState.ExitCode()
168 if config.Expect.ExitCode != actualExitCode {
Zhongpeng Lind9ed9c92023-02-08 19:14:35 -0800169 t.Errorf("expected gazelle exit code: %d\ngot: %d",
170 config.Expect.ExitCode, actualExitCode)
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +0900171 }
172 actualStdout := stdout.String()
173 if strings.TrimSpace(config.Expect.Stdout) != strings.TrimSpace(actualStdout) {
Zhongpeng Lind9ed9c92023-02-08 19:14:35 -0800174 t.Errorf("expected gazelle stdout: %s\ngot: %s",
175 config.Expect.Stdout, actualStdout)
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +0900176 }
177 actualStderr := stderr.String()
178 if strings.TrimSpace(config.Expect.Stderr) != strings.TrimSpace(actualStderr) {
Zhongpeng Lind9ed9c92023-02-08 19:14:35 -0800179 t.Errorf("expected gazelle stderr: %s\ngot: %s",
180 config.Expect.Stderr, actualStderr)
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +0900181 }
Zhongpeng Lind9ed9c92023-02-08 19:14:35 -0800182 if t.Failed() {
Ignas Anikevicius0ee2a7e2023-01-24 15:49:15 +0900183 t.FailNow()
184 }
185
186 testtools.CheckFiles(t, testdataDir, goldens)
187 })
188}
189
190func mustFindGazelle() string {
191 gazellePath, ok := bazel.FindBinary(extensionDir, gazelleBinaryName)
192 if !ok {
193 panic("could not find gazelle binary")
194 }
195 return gazellePath
196}
197
198type testYAML struct {
199 Expect struct {
200 ExitCode int `json:"exit_code"`
201 Stdout string `json:"stdout"`
202 Stderr string `json:"stderr"`
203 } `json:"expect"`
204}