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  }