github.com/wolfd/bazel-gazelle@v0.14.0/internal/language/go/generate_test.go (about) 1 /* Copyright 2018 The Bazel Authors. All rights reserved. 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. 14 */ 15 16 package golang 17 18 import ( 19 "io/ioutil" 20 "path/filepath" 21 "strings" 22 "testing" 23 24 "github.com/bazelbuild/bazel-gazelle/internal/config" 25 "github.com/bazelbuild/bazel-gazelle/internal/language/proto" 26 "github.com/bazelbuild/bazel-gazelle/internal/merger" 27 "github.com/bazelbuild/bazel-gazelle/internal/rule" 28 "github.com/bazelbuild/bazel-gazelle/internal/walk" 29 bzl "github.com/bazelbuild/buildtools/build" 30 ) 31 32 func TestGenerateRules(t *testing.T) { 33 c, _, langs := testConfig() 34 c.RepoRoot = "testdata" 35 c.Dirs = []string{c.RepoRoot} 36 c.ValidBuildFileNames = []string{"BUILD.old"} 37 gc := getGoConfig(c) 38 gc.prefix = "example.com/repo" 39 gc.prefixSet = true 40 41 cexts := make([]config.Configurer, len(langs)) 42 var loads []rule.LoadInfo 43 for i, lang := range langs { 44 cexts[i] = lang 45 loads = append(loads, lang.Loads()...) 46 } 47 walk.Walk(c, cexts, func(dir, rel string, c *config.Config, update bool, oldFile *rule.File, subdirs, regularFiles, genFiles []string) { 48 t.Run(rel, func(t *testing.T) { 49 var empty, gen []*rule.Rule 50 for _, lang := range langs { 51 e, g := lang.GenerateRules(c, dir, rel, oldFile, subdirs, regularFiles, genFiles, empty, gen) 52 empty = append(empty, e...) 53 gen = append(gen, g...) 54 } 55 isTest := false 56 for _, name := range regularFiles { 57 if name == "BUILD.want" { 58 isTest = true 59 break 60 } 61 } 62 if !isTest { 63 // GenerateRules may have side effects, so we need to run it, even if 64 // there's no test. 65 return 66 } 67 f := rule.EmptyFile("test", "") 68 for _, r := range gen { 69 r.Insert(f) 70 } 71 convertImportsAttrs(f) 72 merger.FixLoads(f, loads) 73 f.Sync() 74 got := string(bzl.Format(f.File)) 75 wantPath := filepath.Join(dir, "BUILD.want") 76 wantBytes, err := ioutil.ReadFile(wantPath) 77 if err != nil { 78 t.Fatalf("error reading %s: %v", wantPath, err) 79 } 80 want := string(wantBytes) 81 82 if got != want { 83 t.Errorf("GenerateRules %q: got:\n%s\nwant:\n%s", rel, got, want) 84 } 85 }) 86 }) 87 } 88 89 func TestGenerateRulesEmpty(t *testing.T) { 90 c, _, langs := testConfig() 91 goLang := langs[1].(*goLang) 92 empty, gen := goLang.GenerateRules(c, "./foo", "foo", nil, nil, nil, nil, nil, nil) 93 if len(gen) > 0 { 94 t.Errorf("got %d generated rules; want 0", len(gen)) 95 } 96 f := rule.EmptyFile("test", "") 97 for _, r := range empty { 98 r.Insert(f) 99 } 100 f.Sync() 101 got := strings.TrimSpace(string(bzl.Format(f.File))) 102 want := strings.TrimSpace(` 103 filegroup(name = "go_default_library_protos") 104 105 go_proto_library(name = "foo_go_proto") 106 107 go_library(name = "go_default_library") 108 109 go_binary(name = "foo") 110 111 go_test(name = "go_default_test") 112 `) 113 if got != want { 114 t.Errorf("got:\n%s\nwant:\n%s", got, want) 115 } 116 } 117 118 func TestGenerateRulesEmptyLegacyProto(t *testing.T) { 119 c, _, langs := testConfig() 120 goLang := langs[1].(*goLang) 121 pc := proto.GetProtoConfig(c) 122 pc.Mode = proto.LegacyMode 123 empty, _ := goLang.GenerateRules(c, "./foo", "foo", nil, nil, nil, nil, nil, nil) 124 for _, e := range empty { 125 if kind := e.Kind(); kind == "proto_library" || kind == "go_proto_library" || kind == "go_grpc_library" { 126 t.Errorf("deleted rule %s ; should not delete in legacy proto mode", kind) 127 } 128 } 129 } 130 131 func TestGenerateRulesEmptyPackageProto(t *testing.T) { 132 c, _, langs := testConfig() 133 pc := proto.GetProtoConfig(c) 134 pc.Mode = proto.PackageMode 135 oldContent := []byte(` 136 proto_library( 137 name = "dead_proto", 138 srcs = ["dead.proto"], 139 ) 140 `) 141 old, err := rule.LoadData("BUILD.bazel", "", oldContent) 142 if err != nil { 143 t.Fatal(err) 144 } 145 var empty []*rule.Rule 146 for _, lang := range langs { 147 es, _ := lang.GenerateRules(c, "./foo", "foo", old, nil, nil, nil, empty, nil) 148 empty = append(empty, es...) 149 } 150 f := rule.EmptyFile("test", "") 151 for _, r := range empty { 152 r.Insert(f) 153 } 154 f.Sync() 155 got := strings.TrimSpace(string(bzl.Format(f.File))) 156 want := strings.TrimSpace(` 157 proto_library(name = "dead_proto") 158 159 go_proto_library(name = "dead_go_proto") 160 161 filegroup(name = "go_default_library_protos") 162 163 go_proto_library(name = "foo_go_proto") 164 165 go_library(name = "go_default_library") 166 167 go_binary(name = "foo") 168 169 go_test(name = "go_default_test") 170 `) 171 if got != want { 172 t.Errorf("got:\n%s\nwant:\n%s", got, want) 173 } 174 } 175 176 // convertImportsAttrs copies private attributes to regular attributes, which 177 // will later be written out to build files. This allows tests to check the 178 // values of private attributes with simple string comparison. 179 func convertImportsAttrs(f *rule.File) { 180 for _, r := range f.Rules { 181 v := r.PrivateAttr(config.GazelleImportsKey) 182 if v != nil { 183 r.SetAttr(config.GazelleImportsKey, v) 184 } 185 } 186 }