github.com/wolfd/bazel-gazelle@v0.14.0/internal/merger/merger_test.go (about)

     1  /* Copyright 2016 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 merger
    17  
    18  import (
    19  	"testing"
    20  
    21  	"github.com/bazelbuild/bazel-gazelle/internal/language"
    22  	"github.com/bazelbuild/bazel-gazelle/internal/language/go"
    23  	"github.com/bazelbuild/bazel-gazelle/internal/language/proto"
    24  	"github.com/bazelbuild/bazel-gazelle/internal/rule"
    25  )
    26  
    27  // should fix
    28  // * updated srcs from new
    29  // * data and size preserved from old
    30  // * load stmt fixed to those in use and sorted
    31  
    32  type testCase struct {
    33  	desc, previous, current, empty, expected string
    34  }
    35  
    36  var testCases = []testCase{
    37  	{
    38  		desc: "basic functionality",
    39  		previous: `
    40  load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_prefix", "go_test")
    41  
    42  go_prefix("github.com/jr_hacker/tools")
    43  
    44  go_library(
    45      name = "go_default_library",
    46      srcs = [
    47          "lex.go",
    48          "print.go",
    49          "debug.go",
    50      ],
    51  )
    52  
    53  go_test(
    54      name = "go_default_test",
    55      size = "small",
    56      srcs = [
    57          "gen_test.go",  # keep
    58          "parse_test.go",
    59      ],
    60      data = glob(["testdata/*"]),
    61      embed = [":go_default_library"],
    62  )
    63  `,
    64  		current: `
    65  load("@io_bazel_rules_go//go:def.bzl", "go_test", "go_library")
    66  
    67  go_prefix("")
    68  
    69  go_library(
    70      name = "go_default_library",
    71      srcs = [
    72          "lex.go",
    73          "print.go",
    74      ],
    75  )
    76  
    77  go_test(
    78      name = "go_default_test",
    79      srcs = [
    80          "parse_test.go",
    81          "print_test.go",
    82      ],
    83      embed = [":go_default_library"],
    84  )
    85  `,
    86  		expected: `
    87  load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_prefix", "go_test")
    88  
    89  go_prefix("github.com/jr_hacker/tools")
    90  
    91  go_library(
    92      name = "go_default_library",
    93      srcs = [
    94          "lex.go",
    95          "print.go",
    96      ],
    97  )
    98  
    99  go_test(
   100      name = "go_default_test",
   101      size = "small",
   102      srcs = [
   103          "gen_test.go",  # keep
   104          "parse_test.go",
   105          "print_test.go",
   106      ],
   107      data = glob(["testdata/*"]),
   108      embed = [":go_default_library"],
   109  )
   110  `}, {
   111  		desc: "merge dicts",
   112  		previous: `
   113  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   114  
   115  go_library(
   116      name = "go_default_library",
   117      srcs = select({
   118          "darwin_amd64": [
   119              "foo_darwin_amd64.go", # keep
   120              "bar_darwin_amd64.go",
   121          ],
   122          "linux_arm": [
   123              "foo_linux_arm.go", # keep
   124              "bar_linux_arm.go",
   125          ],
   126      }),
   127  )
   128  `,
   129  		current: `
   130  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   131  
   132  go_library(
   133      name = "go_default_library",
   134      srcs = select({
   135          "linux_arm": ["baz_linux_arm.go"],
   136          "darwin_amd64": ["baz_darwin_amd64.go"],
   137          "//conditions:default": [],
   138      }),
   139  )
   140  `,
   141  		expected: `
   142  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   143  
   144  go_library(
   145      name = "go_default_library",
   146      srcs = select({
   147          "darwin_amd64": [
   148              "baz_darwin_amd64.go",
   149              "foo_darwin_amd64.go",  # keep
   150          ],
   151          "linux_arm": [
   152              "baz_linux_arm.go",
   153              "foo_linux_arm.go",  # keep
   154          ],
   155          "//conditions:default": [],
   156      }),
   157  )
   158  `,
   159  	}, {
   160  		desc: "merge old dict with gen list",
   161  		previous: `
   162  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   163  
   164  go_library(
   165      name = "go_default_library",
   166      srcs = select({
   167          "linux_arm": [
   168              "foo_linux_arm.go", # keep
   169              "bar_linux_arm.go", # keep
   170          ],
   171          "darwin_amd64": [
   172              "bar_darwin_amd64.go",
   173          ],
   174      }),
   175  )
   176  `,
   177  		current: `
   178  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   179  
   180  go_library(
   181      name = "go_default_library",
   182      srcs = ["baz.go"],
   183  )
   184  `,
   185  		expected: `
   186  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   187  
   188  go_library(
   189      name = "go_default_library",
   190      srcs = [
   191          "baz.go",
   192      ] + select({
   193          "linux_arm": [
   194              "bar_linux_arm.go",  # keep
   195              "foo_linux_arm.go",  # keep
   196          ],
   197      }),
   198  )
   199  `,
   200  	}, {
   201  		desc: "merge old list with gen dict",
   202  		previous: `
   203  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   204  
   205  go_library(
   206      name = "go_default_library",
   207      srcs = [
   208          "foo.go", # keep
   209          "bar.go", # keep
   210      ],
   211  )
   212  `,
   213  		current: `
   214  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   215  
   216  go_library(
   217      name = "go_default_library",
   218      srcs = select({
   219          "linux_arm": [
   220              "foo_linux_arm.go",
   221              "bar_linux_arm.go",
   222          ],
   223          "darwin_amd64": [
   224              "bar_darwin_amd64.go",
   225          ],
   226          "//conditions:default": [],
   227      }),
   228  )
   229  `,
   230  		expected: `
   231  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   232  
   233  go_library(
   234      name = "go_default_library",
   235      srcs = [
   236          "bar.go",  # keep
   237          "foo.go",  # keep
   238      ] + select({
   239          "linux_arm": [
   240              "bar_linux_arm.go",
   241              "foo_linux_arm.go",
   242          ],
   243          "darwin_amd64": [
   244              "bar_darwin_amd64.go",
   245          ],
   246          "//conditions:default": [],
   247      }),
   248  )
   249  `,
   250  	}, {
   251  		desc: "merge old list and dict with gen list and dict",
   252  		previous: `
   253  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   254  
   255  go_library(
   256      name = "go_default_library",
   257      srcs = [
   258          "foo.go",  # keep
   259          "bar.go",
   260      ] + select({
   261          "linux_arm": [
   262              "foo_linux_arm.go",  # keep
   263          ],
   264          "//conditions:default": [],
   265      }),
   266  )
   267  `,
   268  		current: `
   269  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   270  
   271  go_library(
   272      name = "go_default_library",
   273      srcs = ["baz.go"] + select({
   274          "linux_arm": ["bar_linux_arm.go"],
   275          "darwin_amd64": ["foo_darwin_amd64.go"],
   276          "//conditions:default": [],
   277      }),
   278  )
   279  `,
   280  		expected: `
   281  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   282  
   283  go_library(
   284      name = "go_default_library",
   285      srcs = [
   286          "baz.go",
   287          "foo.go",  # keep
   288      ] + select({
   289          "darwin_amd64": ["foo_darwin_amd64.go"],
   290          "linux_arm": [
   291              "bar_linux_arm.go",
   292              "foo_linux_arm.go",  # keep
   293          ],
   294          "//conditions:default": [],
   295      }),
   296  )
   297  `,
   298  	}, {
   299  		desc: "os and arch",
   300  		previous: `
   301  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   302  
   303  go_library(
   304      name = "go_default_library",
   305      srcs = [
   306          "generic_1.go",
   307      ] + select({
   308          "@io_bazel_rules_go//go/platform:linux": [
   309              "os_linux.go",  # keep
   310          ],
   311          "//conditions:default": [],
   312      }),
   313  )
   314  `,
   315  		current: `
   316  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   317  
   318  go_library(
   319      name = "go_default_library",
   320      srcs = [
   321          "generic_2.go",
   322      ] + select({
   323          "@io_bazel_rules_go//go/platform:amd64": ["arch_amd64.go"],
   324          "//conditions:default": [],
   325      }),
   326  )
   327  `,
   328  		expected: `
   329  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   330  
   331  go_library(
   332      name = "go_default_library",
   333      srcs = [
   334          "generic_2.go",
   335      ] + select({
   336          "@io_bazel_rules_go//go/platform:linux": [
   337              "os_linux.go",  # keep
   338          ],
   339          "//conditions:default": [],
   340      }) + select({
   341          "@io_bazel_rules_go//go/platform:amd64": ["arch_amd64.go"],
   342          "//conditions:default": [],
   343      }),
   344  )
   345  `,
   346  	}, {
   347  		desc: "merge error keeps old",
   348  		previous: `
   349  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   350  
   351  go_library(
   352      name = "go_default_library",
   353      srcs = glob(["*.go"]),
   354  )
   355  `,
   356  		current: `
   357  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   358  
   359  go_library(
   360      name = "go_default_library",
   361      srcs = ["foo.go"],
   362  )
   363  `,
   364  		expected: `
   365  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   366  
   367  go_library(
   368      name = "go_default_library",
   369      srcs = glob(["*.go"]),
   370  )
   371  `,
   372  	}, {
   373  		desc: "delete empty list",
   374  		previous: `
   375  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   376  
   377  go_library(
   378      name = "go_default_library",
   379      srcs = ["deleted.go"],
   380  )
   381  `,
   382  		current: `
   383  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   384  
   385  go_library(
   386      name = "go_default_library",
   387      srcs = select({
   388          "linux_arm": ["foo_linux_arm.go"],
   389      }),
   390  )
   391  `,
   392  		expected: `
   393  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   394  
   395  go_library(
   396      name = "go_default_library",
   397      srcs = select({
   398          "linux_arm": ["foo_linux_arm.go"],
   399      }),
   400  )
   401  `,
   402  	}, {
   403  		desc: "delete empty dict",
   404  		previous: `
   405  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   406  
   407  go_library(
   408      name = "go_default_library",
   409      srcs = select({
   410          "linux_arm": ["foo_linux_arm.go"],
   411          "//conditions:default": [],
   412      }),
   413  )
   414  `,
   415  		current: `
   416  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   417  
   418  go_library(
   419      name = "go_default_library",
   420      srcs = ["foo.go"],
   421  )
   422  `,
   423  		expected: `
   424  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   425  
   426  go_library(
   427      name = "go_default_library",
   428      srcs = ["foo.go"],
   429  )
   430  `,
   431  	}, {
   432  		desc: "delete empty attr",
   433  		previous: `
   434  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   435  
   436  go_library(
   437      name = "go_default_library",
   438      srcs = ["foo.go"],
   439      embed = ["deleted"],
   440  )
   441  `,
   442  		current: `
   443  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   444  
   445  go_library(
   446      name = "go_default_library",
   447      srcs = ["foo.go"],
   448  )
   449  `,
   450  		expected: `
   451  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   452  
   453  go_library(
   454      name = "go_default_library",
   455      srcs = ["foo.go"],
   456  )
   457  `,
   458  	}, {
   459  		desc: "merge comments",
   460  		previous: `
   461  # load
   462  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   463  
   464  # rule
   465  go_library(
   466      # unmerged attr
   467      name = "go_default_library",
   468      # merged attr
   469      srcs = ["foo.go"],
   470  )
   471  `,
   472  		current: `
   473  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   474  
   475  go_library(
   476      name = "go_default_library",
   477      srcs = ["foo.go"],
   478  )
   479  `,
   480  		expected: `
   481  # load
   482  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   483  
   484  # rule
   485  go_library(
   486      # unmerged attr
   487      name = "go_default_library",
   488      # merged attr
   489      srcs = ["foo.go"],
   490  )
   491  `,
   492  	}, {
   493  		desc: "preserve comments",
   494  		previous: `
   495  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   496  
   497  go_library(
   498      name = "go_default_library",
   499      srcs = [
   500          "a.go",  # preserve
   501          "b.go",  # comments
   502      ],
   503  )
   504  `,
   505  		current: `
   506  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   507  
   508  go_library(
   509      name = "go_default_library",
   510      srcs = ["a.go", "b.go"],
   511  )
   512  `,
   513  		expected: `
   514  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   515  
   516  go_library(
   517      name = "go_default_library",
   518      srcs = [
   519          "a.go",  # preserve
   520          "b.go",  # comments
   521      ],
   522  )
   523  `,
   524  	}, {
   525  		desc: "merge copts and clinkopts",
   526  		previous: `
   527  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   528  
   529  go_library(
   530      name = "cgo_default_library",
   531      copts = [
   532          "-O0",
   533          "-g",  # keep
   534      ],
   535      clinkopts = [
   536          "-lX11",
   537      ],
   538  )
   539  `,
   540  		current: `
   541  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   542  
   543  go_library(
   544      name = "cgo_default_library",
   545      cgo = True,
   546      copts = [
   547          "-O2",
   548      ],
   549      clinkopts = [
   550          "-lpng",
   551      ],
   552  )
   553  `,
   554  		expected: `
   555  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   556  
   557  go_library(
   558      name = "cgo_default_library",
   559      cgo = True,
   560      clinkopts = [
   561          "-lpng",
   562      ],
   563      copts = [
   564          "-g",  # keep
   565          "-O2",
   566      ],
   567  )
   568  `,
   569  	}, {
   570  		desc: "keep scalar attr",
   571  		previous: `
   572  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   573  
   574  go_library(
   575      name = "go_default_library",
   576      embed = [":lib"],  # keep
   577  )
   578  `,
   579  		current: `
   580  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   581  
   582  go_library(
   583      name = "go_default_library",
   584  )
   585  `,
   586  		expected: `
   587  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   588  
   589  go_library(
   590      name = "go_default_library",
   591      embed = [":lib"],  # keep
   592  )
   593  `,
   594  	}, {
   595  		desc: "don't delete list with keep",
   596  		previous: `
   597  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   598  
   599  go_library(
   600      name = "go_default_library",
   601      srcs = [
   602          "one.go",  # keep
   603      ],
   604  )
   605  `,
   606  		current: `
   607  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   608  
   609  go_library(
   610      name = "go_default_library",
   611  )
   612  `,
   613  		expected: `
   614  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   615  
   616  go_library(
   617      name = "go_default_library",
   618      srcs = [
   619          "one.go",  # keep
   620      ],
   621  )
   622  `,
   623  	}, {
   624  		desc: "keep list multiline",
   625  		previous: `
   626  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   627  
   628  go_library(
   629      name = "go_default_library",
   630      srcs = [
   631          "one.go",  # keep
   632          "two.go",
   633      ],
   634  )
   635  `,
   636  		current: `
   637  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   638  
   639  go_library(
   640      name = "go_default_library",
   641  )
   642  `,
   643  		expected: `
   644  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   645  
   646  go_library(
   647      name = "go_default_library",
   648      srcs = [
   649          "one.go",  # keep
   650      ],
   651  )
   652  `,
   653  	}, {
   654  		desc: "keep dict list multiline",
   655  		previous: `
   656  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   657  
   658  go_library(
   659      name = "go_default_library",
   660      srcs = select({
   661          "darwin_amd64": [
   662              "one_darwin.go",  # keep
   663          ],
   664          "linux_arm": [
   665              "one_linux.go",  # keep
   666              "two_linux.go",
   667          ],
   668      }),
   669  )
   670  `,
   671  		current: `
   672  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   673  
   674  go_library(
   675      name = "go_default_library",
   676  )
   677  `,
   678  		expected: `
   679  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   680  
   681  go_library(
   682      name = "go_default_library",
   683      srcs = select({
   684          "darwin_amd64": [
   685              "one_darwin.go",  # keep
   686          ],
   687          "linux_arm": [
   688              "one_linux.go",  # keep
   689          ],
   690      }),
   691  )
   692  `,
   693  	}, {
   694  		desc: "keep prevents delete",
   695  		previous: `
   696  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   697  
   698  # keep
   699  go_library(
   700      name = "go_default_library",
   701      srcs = ["lib.go"],
   702  )
   703  `,
   704  		empty: `
   705  go_library(name = "go_default_library")
   706  `,
   707  		expected: `
   708  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   709  
   710  # keep
   711  go_library(
   712      name = "go_default_library",
   713      srcs = ["lib.go"],
   714  )
   715  `,
   716  	}, {
   717  		desc: "keep prevents merge",
   718  		previous: `
   719  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   720  
   721  # keep
   722  go_library(
   723      name = "go_default_library",
   724      srcs = ["old.go"],
   725  )
   726  `,
   727  		current: `
   728  go_library(
   729      name = "go_default_library",
   730      srcs = ["new.go"],
   731  )
   732  `,
   733  		expected: `
   734  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   735  
   736  # keep
   737  go_library(
   738      name = "go_default_library",
   739      srcs = ["old.go"],
   740  )
   741  `,
   742  	}, {
   743  		desc: "delete empty rule",
   744  		previous: `
   745  load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
   746  
   747  go_library(
   748      name = "go_default_library",
   749      srcs = ["lib.go"],
   750  )
   751  
   752  go_binary(
   753      name = "old",
   754      srcs = ["bin.go"],
   755      embed = [":go_default_library"],
   756      importpath = "foo",
   757  )
   758  `,
   759  		current: `
   760  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   761  
   762  go_library(
   763      name = "go_default_library",
   764      srcs = ["lib.go"],
   765  )
   766  `,
   767  		empty: `
   768  go_binary(name = "old")
   769  `,
   770  		expected: `
   771  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   772  
   773  go_library(
   774      name = "go_default_library",
   775      srcs = ["lib.go"],
   776  )
   777  `,
   778  	}, {
   779  		desc: "don't delete kept rule",
   780  		previous: `
   781  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   782  
   783  go_library(
   784      name = "go_default_library",
   785      srcs = [
   786          "lib.go",  # keep
   787      ],
   788  )
   789  `,
   790  		empty: `go_library(name = "go_default_library")`,
   791  		expected: `
   792  load("@io_bazel_rules_go//go:def.bzl", "go_library")
   793  
   794  go_library(
   795      name = "go_default_library",
   796      srcs = [
   797          "lib.go",  # keep
   798      ],
   799  )
   800  `,
   801  	}, {
   802  		desc: "match and rename",
   803  		previous: `
   804  load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
   805  load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
   806  
   807  go_binary(
   808      name = "custom_bin",
   809      embed = [":custom_library"],
   810  )
   811  
   812  go_library(
   813      name = "custom_library",
   814      embed = [":custom_proto_library"],
   815      importpath = "example.com/repo/foo",
   816  )
   817  
   818  go_proto_library(
   819      name = "custom_proto_library",
   820      importpath = "example.com/repo/foo",
   821      proto = ":foo_proto",
   822  )
   823  `,
   824  		current: `
   825  go_binary(
   826      name = "bin",
   827      srcs = ["bin.go"],
   828      embed = [":go_default_library"],
   829  )
   830  
   831  go_library(
   832      name = "go_default_library",
   833      srcs = ["lib.go"],
   834      embed = [":foo_proto_library"],
   835      importpath = "example.com/repo/foo",
   836  )
   837  
   838  go_proto_library(
   839      name = "foo_proto_library",
   840      importpath = "example.com/repo/foo",
   841      proto = ":foo_proto",
   842  )
   843  `,
   844  		expected: `
   845  load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
   846  load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
   847  
   848  go_binary(
   849      name = "custom_bin",
   850      srcs = ["bin.go"],
   851      embed = [":custom_library"],
   852  )
   853  
   854  go_library(
   855      name = "custom_library",
   856      srcs = ["lib.go"],
   857      embed = [":custom_proto_library"],
   858      importpath = "example.com/repo/foo",
   859  )
   860  
   861  go_proto_library(
   862      name = "custom_proto_library",
   863      importpath = "example.com/repo/foo",
   864      proto = ":foo_proto",
   865  )
   866  `,
   867  	},
   868  }
   869  
   870  func TestMergeFile(t *testing.T) {
   871  	for _, tc := range testCases {
   872  		t.Run(tc.desc, func(t *testing.T) {
   873  			genFile, err := rule.LoadData("current", "", []byte(tc.current))
   874  			if err != nil {
   875  				t.Fatalf("%s: %v", tc.desc, err)
   876  			}
   877  			f, err := rule.LoadData("previous", "", []byte(tc.previous))
   878  			if err != nil {
   879  				t.Fatalf("%s: %v", tc.desc, err)
   880  			}
   881  			emptyFile, err := rule.LoadData("empty", "", []byte(tc.empty))
   882  			if err != nil {
   883  				t.Fatalf("%s: %v", tc.desc, err)
   884  			}
   885  			MergeFile(f, emptyFile.Rules, genFile.Rules, PreResolve, testKinds)
   886  			FixLoads(f, testLoads)
   887  
   888  			want := tc.expected
   889  			if len(want) > 0 && want[0] == '\n' {
   890  				want = want[1:]
   891  			}
   892  
   893  			if got := string(f.Format()); got != want {
   894  				t.Fatalf("%s: got %s; want %s", tc.desc, got, want)
   895  			}
   896  		})
   897  	}
   898  }
   899  
   900  var (
   901  	testKinds map[string]rule.KindInfo
   902  	testLoads []rule.LoadInfo
   903  )
   904  
   905  func init() {
   906  	testKinds = make(map[string]rule.KindInfo)
   907  	langs := []language.Language{proto.New(), golang.New()}
   908  	for _, lang := range langs {
   909  		for kind, info := range lang.Kinds() {
   910  			testKinds[kind] = info
   911  		}
   912  		testLoads = append(testLoads, lang.Loads()...)
   913  	}
   914  }
   915  
   916  func TestMatch(t *testing.T) {
   917  	for _, tc := range []struct {
   918  		desc, gen, old string
   919  		wantIndex      int
   920  		wantError      bool
   921  	}{
   922  		{
   923  			desc:      "no_match",
   924  			gen:       `go_library(name = "lib")`,
   925  			wantIndex: -1,
   926  		}, {
   927  			desc:      "name_match",
   928  			gen:       `go_library(name = "lib")`,
   929  			old:       `go_library(name = "lib", srcs = ["lib.go"])`,
   930  			wantIndex: 0,
   931  		}, {
   932  			desc:      "name_match_kind_different",
   933  			gen:       `go_library(name = "lib")`,
   934  			old:       `cc_library(name = "lib")`,
   935  			wantError: true,
   936  		}, {
   937  			desc: "multiple_name_match",
   938  			gen:  `go_library(name = "lib")`,
   939  			old: `
   940  go_library(name = "lib")
   941  go_library(name = "lib")
   942  `,
   943  			wantError: true,
   944  		}, {
   945  			desc:      "attr_match",
   946  			gen:       `go_library(name = "x", importpath = "foo")`,
   947  			old:       `go_library(name = "y", importpath = "foo")`,
   948  			wantIndex: 0,
   949  		}, {
   950  			desc: "multiple_attr_match",
   951  			gen:  `go_library(name = "x", importpath = "foo")`,
   952  			old: `
   953  go_library(name = "y", importpath = "foo")
   954  go_library(name = "z", importpath = "foo")
   955  `,
   956  			wantError: true,
   957  		}, {
   958  			desc:      "any_match",
   959  			gen:       `go_binary(name = "x")`,
   960  			old:       `go_binary(name = "y")`,
   961  			wantIndex: 0,
   962  		}, {
   963  			desc: "multiple_any_match",
   964  			gen:  `go_binary(name = "x")`,
   965  			old: `
   966  go_binary(name = "y")
   967  go_binary(name = "z")
   968  `,
   969  			wantError: true,
   970  		},
   971  	} {
   972  		t.Run(tc.desc, func(t *testing.T) {
   973  			genFile, err := rule.LoadData("gen", "", []byte(tc.gen))
   974  			if err != nil {
   975  				t.Fatal(err)
   976  			}
   977  			oldFile, err := rule.LoadData("old", "", []byte(tc.old))
   978  			if err != nil {
   979  				t.Fatal(err)
   980  			}
   981  			r := genFile.Rules[0]
   982  			info := testKinds[r.Kind()]
   983  			if got, gotErr := match(oldFile.Rules, r, info); gotErr != nil {
   984  				if !tc.wantError {
   985  					t.Errorf("unexpected error: %v", gotErr)
   986  				}
   987  			} else if tc.wantError {
   988  				t.Error("unexpected success")
   989  			} else if got == nil && tc.wantIndex >= 0 {
   990  				t.Errorf("got nil; want index %d", tc.wantIndex)
   991  			} else if got != nil && got.Index() != tc.wantIndex {
   992  				t.Fatalf("got index %d ; want %d", got.Index(), tc.wantIndex)
   993  			}
   994  		})
   995  	}
   996  }