diff options
author | Spandan Das <spandandas@google.com> | 2023-06-15 02:30:50 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-06-15 02:30:50 +0000 |
commit | 9bb1b549b6a84214c53be0924760be030e66b93a (patch) | |
tree | d9fac15bb5a835ae6ba757dc5eaf6ef597ea44cf /tests/integration | |
parent | 9803cf8403d7105bddc1d5304d6e694b781a6605 (diff) | |
parent | 780ccd3956961690db3e36d8fa1ed7649cb0057b (diff) | |
download | bazelbuild-rules_go-9bb1b549b6a84214c53be0924760be030e66b93a.tar.gz |
Merge remote-tracking branch 'aosp/upstream-master' into merge_rules_go am: 49dcd02124 am: 711a453236 am: 6cf433ad1b am: de80525bba am: 96939a977e am: 780ccd3956HEADandroid-14.0.0_r51android-14.0.0_r50android-14.0.0_r37android-14.0.0_r36android-14.0.0_r35android-14.0.0_r34android-14.0.0_r33android-14.0.0_r32android-14.0.0_r31android-14.0.0_r30android-14.0.0_r29android-14.0.0_r28mastermainandroid14-qpr3-releaseandroid14-qpr2-s5-releaseandroid14-qpr2-s4-releaseandroid14-qpr2-s3-releaseandroid14-qpr2-s2-releaseandroid14-qpr2-s1-releaseandroid14-qpr2-release
Original change: https://android-review.googlesource.com/c/platform/external/bazelbuild-rules_go/+/2625353
Change-Id: Id4ca3195d832eca77b29b2896b89027d847bb72d
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
Diffstat (limited to 'tests/integration')
18 files changed, 1835 insertions, 0 deletions
diff --git a/tests/integration/README.rst b/tests/integration/README.rst new file mode 100644 index 00000000..0624954b --- /dev/null +++ b/tests/integration/README.rst @@ -0,0 +1,23 @@ +Integration tests +================= + +This folder is intended to hold larger scale test that check that rules_go +works correctly in the real world, rather than in isolated single feature +tests. + +If the unit tests were correct and exhaustive this directory should in theory +be redundant, but in practice it helps catch many issues and points to places +where more unit tests are needed. + +Contents +-------- + +.. Child list start + +* `Gazelle functionality <gazelle/README.rst>`_ +* `Popular repository tests <popular_repos/README.rst>`_ +* `Reproducibility <reproducibility/README.rst>`_ +* `Functionality related to @go_googleapis <googleapis/README.rst>`_ + +.. Child list end + diff --git a/tests/integration/gazelle/BUILD.bazel b/tests/integration/gazelle/BUILD.bazel new file mode 100644 index 00000000..90bfe2c7 --- /dev/null +++ b/tests/integration/gazelle/BUILD.bazel @@ -0,0 +1,11 @@ +load("//go/tools/bazel_testing:def.bzl", "go_bazel_test") + +go_bazel_test( + name = "gazelle_test", + size = "medium", + srcs = ["gazelle_test.go"], + rule_files = [ + "//:all_files", + "@bazel_gazelle//:all_files", + ], +) diff --git a/tests/integration/gazelle/README.rst b/tests/integration/gazelle/README.rst new file mode 100644 index 00000000..f14f9a7d --- /dev/null +++ b/tests/integration/gazelle/README.rst @@ -0,0 +1,9 @@ +Gazelle functionality +===================== + +Tests that ensure rules_go still works with Gazelle. + +gazelle_test +------------ +Checks that Gazelle can be run in a test workspace. + diff --git a/tests/integration/gazelle/gazelle_test.go b/tests/integration/gazelle/gazelle_test.go new file mode 100644 index 00000000..42ad91db --- /dev/null +++ b/tests/integration/gazelle/gazelle_test.go @@ -0,0 +1,74 @@ +// Copyright 2020 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package gazelle_test + +import ( + "io/ioutil" + "strings" + "testing" + + "github.com/bazelbuild/rules_go/go/tools/bazel_testing" +) + +func TestMain(m *testing.M) { + bazel_testing.TestMain(m, bazel_testing.Args{ + Main: ` +-- BUILD.bazel -- +load("@bazel_gazelle//:def.bzl", "gazelle") + +# gazelle:prefix example.com/hello +gazelle( + name = "gazelle", +) +-- hello.go -- +package hello +`, + WorkspaceSuffix: ` +load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") + +gazelle_dependencies() +`, + }) +} + +func TestUpdate(t *testing.T) { + if err := bazel_testing.RunBazel("run", "//:gazelle"); err != nil { + t.Fatal(err) + } + data, err := ioutil.ReadFile("BUILD.bazel") + if err != nil { + t.Fatal(err) + } + got := strings.TrimSpace(string(data)) + want := strings.TrimSpace(` +load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("@bazel_gazelle//:def.bzl", "gazelle") + +# gazelle:prefix example.com/hello +gazelle( + name = "gazelle", +) + +go_library( + name = "hello", + srcs = ["hello.go"], + importpath = "example.com/hello", + visibility = ["//visibility:public"], +) +`) + if got != want { + t.Errorf("got:\n%s\n\nwant:\n%s", got, want) + } +} diff --git a/tests/integration/go_bin_runner/BUILD.bazel b/tests/integration/go_bin_runner/BUILD.bazel new file mode 100644 index 00000000..e7db9531 --- /dev/null +++ b/tests/integration/go_bin_runner/BUILD.bazel @@ -0,0 +1,6 @@ +load("//go/tools/bazel_testing:def.bzl", "go_bazel_test") + +go_bazel_test( + name = "go_bin_runner_test", + srcs = ["go_bin_runner_test.go"], +) diff --git a/tests/integration/go_bin_runner/go_bin_runner_test.go b/tests/integration/go_bin_runner/go_bin_runner_test.go new file mode 100644 index 00000000..2cd42660 --- /dev/null +++ b/tests/integration/go_bin_runner/go_bin_runner_test.go @@ -0,0 +1,107 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package go_bin_runner_test + +import ( + "os" + "path/filepath" + "strings" + "testing" + + "github.com/bazelbuild/rules_go/go/tools/bazel_testing" +) + +func TestMain(m *testing.M) { + bazel_testing.TestMain(m, bazel_testing.Args{ + Main: ` +-- BUILD.bazel -- +sh_binary( + name = "go_version", + srcs = ["go_version.sh"], + env = {"GO": "$(rlocationpath @io_bazel_rules_go//go)"}, + data = ["@io_bazel_rules_go//go"], + deps = ["@bazel_tools//tools/bash/runfiles"], +) + +genrule( + name = "foo", + outs = ["bar"], + tools = ["@io_bazel_rules_go//go"], + cmd = "$(location @io_bazel_rules_go//go) > $@", +) + +-- go_version.sh -- +# --- begin runfiles.bash initialization v2 --- +# Copy-pasted from the Bazel Bash runfiles library v2. +set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash +source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \ + source "$0.runfiles/$f" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ + { echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e +# --- end runfiles.bash initialization v2 --- + +$(rlocation "$GO") version +`}) +} + +func TestGoEnv(t *testing.T) { + // Set an invalid GOROOT to test that the //go target still finds the expected hermetic GOROOT. + os.Setenv("GOROOT", "invalid") + + bazelInfoOut, err := bazel_testing.BazelOutput("info", "output_base") + if err != nil { + t.Fatal(err) + } + outputBase := strings.TrimSpace(string(bazelInfoOut)) + + goEnvOut, err := bazel_testing.BazelOutput("run", "@io_bazel_rules_go//go", "--", "env", "GOROOT") + if err != nil { + t.Fatal(err) + } + + goRoot := strings.TrimSpace(string(goEnvOut)) + if goRoot != filepath.Join(outputBase, "external", "go_sdk") { + t.Fatalf("GOROOT was not equal to %s", filepath.Join(outputBase, "external", "go_sdk")) + } +} + +func TestGoVersionFromScript(t *testing.T) { + err := os.Chmod("go_version.sh", 0755) + if err != nil { + t.Fatal(err) + } + + goVersionOut, err := bazel_testing.BazelOutput("run", "//:go_version") + if err != nil { + t.Fatal(err) + } + + if !strings.HasPrefix(string(goVersionOut), "go version go1.") { + t.Fatalf("go version output did not start with \"go version go1.\": %s", string(goVersionOut)) + } +} + +func TestNoGoInExec(t *testing.T) { + _, err := bazel_testing.BazelOutput("build", "//:foo") + if err == nil { + t.Fatal("expected build to fail") + } + stderr := string(err.(*bazel_testing.StderrExitError).Err.Stderr) + if !strings.Contains(stderr, "//go is only meant to be used with 'bazel run'") { + t.Fatalf("expected \"//go is only meant to be used with 'bazel run'\" in stderr, got %s", stderr) + } +} diff --git a/tests/integration/googleapis/BUILD.bazel b/tests/integration/googleapis/BUILD.bazel new file mode 100644 index 00000000..53c544c6 --- /dev/null +++ b/tests/integration/googleapis/BUILD.bazel @@ -0,0 +1,46 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") +load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "color_service_proto", + srcs = ["color_service.proto"], + deps = [ + "@go_googleapis//google/rpc:status_proto", + "@go_googleapis//google/type:color_proto", + ], +) + +go_proto_library( + name = "color_service_go_proto", + compilers = ["@io_bazel_rules_go//proto:go_grpc"], + importpath = "github.com/bazelbuild/rules_go/tests/integration/googleapis/color_service_proto", + proto = ":color_service_proto", + deps = [ + "@go_googleapis//google/rpc:status_go_proto", + "@go_googleapis//google/type:color_go_proto", + ], +) + +go_library( + name = "color_service", + srcs = ["color_service.go"], + importpath = "github.com/bazelbuild/rules_go/tests/integration/googleapis/color_service", + deps = [ + ":color_service_go_proto", + "@go_googleapis//google/rpc:code_go_proto", + "@go_googleapis//google/rpc:status_go_proto", + "@go_googleapis//google/type:color_go_proto", + ], +) + +go_test( + name = "color_service_test", + srcs = ["color_service_test.go"], + deps = [ + ":color_service", + ":color_service_go_proto", + "@go_googleapis//google/type:color_go_proto", + "@org_golang_google_grpc//:go_default_library", + ], +) diff --git a/tests/integration/googleapis/README.rst b/tests/integration/googleapis/README.rst new file mode 100644 index 00000000..317f997e --- /dev/null +++ b/tests/integration/googleapis/README.rst @@ -0,0 +1,8 @@ +Functionality related to @go_googleapis +======================================= + +color_service_test +------------------ + +Verifies that a simple gRPC client and server can be built and run. .proto +files are compiled at build time and depend on libraries in ``@go_googleapis``. diff --git a/tests/integration/googleapis/color_service.go b/tests/integration/googleapis/color_service.go new file mode 100644 index 00000000..cde3cc72 --- /dev/null +++ b/tests/integration/googleapis/color_service.go @@ -0,0 +1,49 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package color_service + +import ( + "context" + "sync" + + cspb "github.com/bazelbuild/rules_go/tests/integration/googleapis/color_service_proto" + "google.golang.org/genproto/googleapis/rpc/code" + "google.golang.org/genproto/googleapis/rpc/status" + "google.golang.org/genproto/googleapis/type/color" +) + +type colorServer struct { + colors sync.Map +} + +func New() cspb.ColorServiceServer { + return &colorServer{} +} + +func (s *colorServer) SetColor(ctx context.Context, r *cspb.SetColorRequest) (*cspb.SetColorResponse, error) { + _, loaded := s.colors.LoadOrStore(r.Name, r.Color) + if loaded { + return &cspb.SetColorResponse{Status: &status.Status{Code: int32(code.Code_ALREADY_EXISTS)}}, nil + } + return &cspb.SetColorResponse{}, nil +} + +func (s *colorServer) GetColor(ctx context.Context, r *cspb.GetColorRequest) (*cspb.GetColorResponse, error) { + value, ok := s.colors.Load(r.Name) + if !ok { + return &cspb.GetColorResponse{Status: &status.Status{Code: int32(code.Code_NOT_FOUND)}}, nil + } + return &cspb.GetColorResponse{Color: value.(*color.Color)}, nil +} diff --git a/tests/integration/googleapis/color_service.proto b/tests/integration/googleapis/color_service.proto new file mode 100644 index 00000000..6444c3bd --- /dev/null +++ b/tests/integration/googleapis/color_service.proto @@ -0,0 +1,45 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +import "google/rpc/status.proto"; +import "google/type/color.proto"; + +package rules_go.tests.integration.color_service; + +option go_package = "github.com/bazelbuild/rules_go/tests/integration/googleapis/color_service_proto"; + +message SetColorRequest { + string name = 1; + google.type.Color color = 2; +} + +message SetColorResponse { + google.rpc.Status status = 1; +} + +message GetColorRequest { + string name = 1; +} + +message GetColorResponse { + google.rpc.Status status = 1; + google.type.Color color = 2; +} + +service ColorService { + rpc SetColor(SetColorRequest) returns (SetColorResponse); + rpc GetColor(GetColorRequest) returns (GetColorResponse); +} diff --git a/tests/integration/googleapis/color_service_test.go b/tests/integration/googleapis/color_service_test.go new file mode 100644 index 00000000..f1b9ee2b --- /dev/null +++ b/tests/integration/googleapis/color_service_test.go @@ -0,0 +1,63 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package color_service_test + +import ( + "context" + "net" + "reflect" + "testing" + + "github.com/bazelbuild/rules_go/tests/integration/googleapis/color_service" + cspb "github.com/bazelbuild/rules_go/tests/integration/googleapis/color_service_proto" + "google.golang.org/genproto/googleapis/type/color" + "google.golang.org/grpc" +) + +func TestColorService(t *testing.T) { + lis, err := net.Listen("tcp", "127.0.0.1:") + if err != nil { + t.Fatal(err) + } + grpcServer := grpc.NewServer() + cspb.RegisterColorServiceServer(grpcServer, color_service.New()) + go grpcServer.Serve(lis) + defer grpcServer.Stop() + + conn, err := grpc.Dial(lis.Addr().String(), grpc.WithInsecure()) + if err != nil { + t.Fatal(err) + } + defer conn.Close() + client := cspb.NewColorServiceClient(conn) + + _, err = client.SetColor(context.Background(), &cspb.SetColorRequest{ + Name: "red", + Color: &color.Color{Red: 1.0}, + }) + if err != nil { + t.Errorf("SetColor: %v", err) + } + resp, err := client.GetColor(context.Background(), &cspb.GetColorRequest{ + Name: "red", + }) + if err != nil { + t.Errorf("GetColor: %v", err) + } + want := &color.Color{Red: 1.0} + if !reflect.DeepEqual(resp.Color, want) { + t.Errorf("got %#v; want %#v", resp.Color, want) + } +} diff --git a/tests/integration/popular_repos/BUILD.bazel b/tests/integration/popular_repos/BUILD.bazel new file mode 100644 index 00000000..7b92e2c8 --- /dev/null +++ b/tests/integration/popular_repos/BUILD.bazel @@ -0,0 +1,345 @@ +# Copyright 2017 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +############################## +# Generated file, do not edit! +############################## + +load("@bazel_skylib//rules:build_test.bzl", "build_test") + +test_suite( + name = "org_golang_x_crypto", + tests = [ + "@org_golang_x_crypto//acme:acme_test", + "@org_golang_x_crypto//acme/autocert:autocert_test", + "@org_golang_x_crypto//argon2:argon2_test", + "@org_golang_x_crypto//bcrypt:bcrypt_test", + "@org_golang_x_crypto//blake2b:blake2b_test", + "@org_golang_x_crypto//blake2s:blake2s_test", + "@org_golang_x_crypto//blowfish:blowfish_test", + "@org_golang_x_crypto//bn256:bn256_test", + "@org_golang_x_crypto//cast5:cast5_test", + "@org_golang_x_crypto//chacha20:chacha20_test", + "@org_golang_x_crypto//chacha20poly1305:chacha20poly1305_test", + "@org_golang_x_crypto//cryptobyte:cryptobyte_test", + "@org_golang_x_crypto//curve25519:curve25519_test", + "@org_golang_x_crypto//ed25519:ed25519_test", + "@org_golang_x_crypto//hkdf:hkdf_test", + "@org_golang_x_crypto//internal/subtle:subtle_test", + "@org_golang_x_crypto//md4:md4_test", + "@org_golang_x_crypto//nacl/auth:auth_test", + "@org_golang_x_crypto//nacl/box:box_test", + "@org_golang_x_crypto//nacl/secretbox:secretbox_test", + "@org_golang_x_crypto//nacl/sign:sign_test", + "@org_golang_x_crypto//ocsp:ocsp_test", + "@org_golang_x_crypto//openpgp:openpgp_test", + "@org_golang_x_crypto//openpgp/armor:armor_test", + "@org_golang_x_crypto//openpgp/clearsign:clearsign_test", + "@org_golang_x_crypto//openpgp/elgamal:elgamal_test", + "@org_golang_x_crypto//openpgp/packet:packet_test", + "@org_golang_x_crypto//openpgp/s2k:s2k_test", + "@org_golang_x_crypto//otr:otr_test", + "@org_golang_x_crypto//pbkdf2:pbkdf2_test", + "@org_golang_x_crypto//pkcs12:pkcs12_test", + "@org_golang_x_crypto//pkcs12/internal/rc2:rc2_test", + "@org_golang_x_crypto//poly1305:poly1305_test", + "@org_golang_x_crypto//ripemd160:ripemd160_test", + "@org_golang_x_crypto//salsa20:salsa20_test", + "@org_golang_x_crypto//salsa20/salsa:salsa_test", + "@org_golang_x_crypto//scrypt:scrypt_test", + "@org_golang_x_crypto//sha3:sha3_test", + "@org_golang_x_crypto//ssh/internal/bcrypt_pbkdf:bcrypt_pbkdf_test", + "@org_golang_x_crypto//ssh/knownhosts:knownhosts_test", + "@org_golang_x_crypto//tea:tea_test", + "@org_golang_x_crypto//twofish:twofish_test", + "@org_golang_x_crypto//xtea:xtea_test", + "@org_golang_x_crypto//xts:xts_test", + ], +) + +test_suite( + name = "org_golang_x_net", + tests = [ + "@org_golang_x_net//context:context_test", + "@org_golang_x_net//context/ctxhttp:ctxhttp_test", + "@org_golang_x_net//dns/dnsmessage:dnsmessage_test", + "@org_golang_x_net//html:html_test", + "@org_golang_x_net//html/atom:atom_test", + "@org_golang_x_net//http/httpguts:httpguts_test", + "@org_golang_x_net//http/httpproxy:httpproxy_test", + "@org_golang_x_net//http2/h2c:h2c_test", + "@org_golang_x_net//http2/hpack:hpack_test", + "@org_golang_x_net//idna:idna_test", + "@org_golang_x_net//internal/socks:socks_test", + "@org_golang_x_net//internal/sockstest:sockstest_test", + "@org_golang_x_net//internal/timeseries:timeseries_test", + "@org_golang_x_net//ipv4:ipv4_test", + "@org_golang_x_net//ipv6:ipv6_test", + "@org_golang_x_net//netutil:netutil_test", + "@org_golang_x_net//proxy:proxy_test", + "@org_golang_x_net//publicsuffix:publicsuffix_test", + "@org_golang_x_net//trace:trace_test", + "@org_golang_x_net//webdav:webdav_test", + "@org_golang_x_net//webdav/internal/xml:xml_test", + "@org_golang_x_net//websocket:websocket_test", + "@org_golang_x_net//xsrftoken:xsrftoken_test", + ], +) + +test_suite( + name = "org_golang_x_sys", + tests = [ + "@org_golang_x_sys//cpu:cpu_test", + "@org_golang_x_sys//execabs:execabs_test", + "@org_golang_x_sys//internal/unsafeheader:unsafeheader_test", + "@org_golang_x_sys//plan9:plan9_test", + "@org_golang_x_sys//unix/internal/mkmerge:mkmerge_test", + "@org_golang_x_sys//windows/registry:registry_test", + "@org_golang_x_sys//windows/svc:svc_test", + "@org_golang_x_sys//windows/svc/eventlog:eventlog_test", + "@org_golang_x_sys//windows/svc/mgr:mgr_test", + ], +) + +test_suite( + name = "org_golang_x_text", + tests = [ + "@org_golang_x_text//cases:cases_test", + "@org_golang_x_text//collate:collate_test", + "@org_golang_x_text//collate/build:build_test", + "@org_golang_x_text//currency:currency_test", + "@org_golang_x_text//date:date_test", + "@org_golang_x_text//encoding:encoding_test", + "@org_golang_x_text//encoding/htmlindex:htmlindex_test", + "@org_golang_x_text//encoding/ianaindex:ianaindex_test", + "@org_golang_x_text//feature/plural:plural_test", + "@org_golang_x_text//internal:internal_test", + "@org_golang_x_text//internal/catmsg:catmsg_test", + "@org_golang_x_text//internal/colltab:colltab_test", + "@org_golang_x_text//internal/export/idna:idna_test", + "@org_golang_x_text//internal/export/unicode:unicode_test", + "@org_golang_x_text//internal/format:format_test", + "@org_golang_x_text//internal/language:language_test", + "@org_golang_x_text//internal/language/compact:compact_test", + "@org_golang_x_text//internal/number:number_test", + "@org_golang_x_text//internal/stringset:stringset_test", + "@org_golang_x_text//internal/tag:tag_test", + "@org_golang_x_text//internal/triegen:triegen_test", + "@org_golang_x_text//internal/ucd:ucd_test", + "@org_golang_x_text//language:language_test", + "@org_golang_x_text//language/display:display_test", + "@org_golang_x_text//message:message_test", + "@org_golang_x_text//message/catalog:catalog_test", + "@org_golang_x_text//number:number_test", + "@org_golang_x_text//runes:runes_test", + "@org_golang_x_text//search:search_test", + "@org_golang_x_text//secure/bidirule:bidirule_test", + "@org_golang_x_text//secure/precis:precis_test", + "@org_golang_x_text//transform:transform_test", + "@org_golang_x_text//unicode/bidi:bidi_test", + "@org_golang_x_text//unicode/cldr:cldr_test", + "@org_golang_x_text//unicode/norm:norm_test", + "@org_golang_x_text//unicode/rangetable:rangetable_test", + "@org_golang_x_text//unicode/runenames:runenames_test", + "@org_golang_x_text//width:width_test", + ], +) + +test_suite( + name = "org_golang_x_tools", + tests = [ + "@org_golang_x_tools//benchmark/parse:parse_test", + "@org_golang_x_tools//cmd/benchcmp:benchcmp_test", + "@org_golang_x_tools//cmd/digraph:digraph_test", + "@org_golang_x_tools//cmd/getgo:getgo_test", + "@org_golang_x_tools//cmd/go-contrib-init:go-contrib-init_test", + "@org_golang_x_tools//cmd/splitdwarf/internal/macho:macho_test", + "@org_golang_x_tools//cover:cover_test", + "@org_golang_x_tools//go/analysis:analysis_test", + "@org_golang_x_tools//go/analysis/passes/internal/analysisutil:analysisutil_test", + "@org_golang_x_tools//go/ast/astutil:astutil_test", + "@org_golang_x_tools//go/callgraph/static:static_test", + "@org_golang_x_tools//go/callgraph/vta/internal/trie:trie_test", + "@org_golang_x_tools//go/cfg:cfg_test", + "@org_golang_x_tools//go/vcs:vcs_test", + "@org_golang_x_tools//godoc/redirect:redirect_test", + "@org_golang_x_tools//godoc/vfs:vfs_test", + "@org_golang_x_tools//godoc/vfs/gatefs:gatefs_test", + "@org_golang_x_tools//godoc/vfs/mapfs:mapfs_test", + "@org_golang_x_tools//internal/bug:bug_test", + "@org_golang_x_tools//internal/diff:diff_test", + "@org_golang_x_tools//internal/diff/lcs:lcs_test", + "@org_golang_x_tools//internal/diff/myers:myers_test", + "@org_golang_x_tools//internal/event:event_test", + "@org_golang_x_tools//internal/event/export:export_test", + "@org_golang_x_tools//internal/event/export/ocagent:ocagent_test", + "@org_golang_x_tools//internal/event/export/ocagent/wire:wire_test", + "@org_golang_x_tools//internal/event/label:label_test", + "@org_golang_x_tools//internal/fastwalk:fastwalk_test", + "@org_golang_x_tools//internal/fuzzy:fuzzy_test", + "@org_golang_x_tools//internal/gopathwalk:gopathwalk_test", + "@org_golang_x_tools//internal/jsonrpc2:jsonrpc2_test", + "@org_golang_x_tools//internal/jsonrpc2/servertest:servertest_test", + "@org_golang_x_tools//internal/jsonrpc2_v2:jsonrpc2_v2_test", + "@org_golang_x_tools//internal/memoize:memoize_test", + "@org_golang_x_tools//internal/persistent:persistent_test", + "@org_golang_x_tools//internal/proxydir:proxydir_test", + "@org_golang_x_tools//internal/robustio:robustio_test", + "@org_golang_x_tools//internal/stack:stack_test", + "@org_golang_x_tools//internal/typesinternal:typesinternal_test", + "@org_golang_x_tools//playground/socket:socket_test", + "@org_golang_x_tools//refactor/satisfy:satisfy_test", + "@org_golang_x_tools//txtar:txtar_test", + ], +) + +test_suite( + name = "com_github_golang_glog", + tests = [ + "@com_github_golang_glog//:glog_test", + ], +) + +test_suite( + name = "org_golang_x_sync", + tests = [ + "@org_golang_x_sync//errgroup:errgroup_test", + "@org_golang_x_sync//semaphore:semaphore_test", + "@org_golang_x_sync//singleflight:singleflight_test", + "@org_golang_x_sync//syncmap:syncmap_test", + ], +) + +test_suite( + name = "org_golang_x_mod", + tests = [ + "@org_golang_x_mod//modfile:modfile_test", + "@org_golang_x_mod//module:module_test", + "@org_golang_x_mod//semver:semver_test", + "@org_golang_x_mod//sumdb:sumdb_test", + "@org_golang_x_mod//sumdb/dirhash:dirhash_test", + "@org_golang_x_mod//sumdb/note:note_test", + "@org_golang_x_mod//sumdb/storage:storage_test", + ], +) + +build_test( + name = "build_only", + targets = [ + "@org_golang_x_crypto//ssh/agent:agent", + "@org_golang_x_crypto//ssh/test:test", + "@org_golang_x_crypto//ssh:ssh", + "@org_golang_x_net//bpf:bpf", + "@org_golang_x_net//html/charset:charset", + "@org_golang_x_net//http2:http2", + "@org_golang_x_net//icmp:icmp", + "@org_golang_x_net//nettest:nettest", + "@org_golang_x_net//lif:lif", + "@org_golang_x_net//route:route", + "@org_golang_x_sys//unix:unix", + "@org_golang_x_sys//windows:windows", + "@org_golang_x_text//encoding/charmap:charmap", + "@org_golang_x_text//encoding/japanese:japanese", + "@org_golang_x_text//encoding/korean:korean", + "@org_golang_x_text//encoding/simplifiedchinese:simplifiedchinese", + "@org_golang_x_text//encoding/traditionalchinese:traditionalchinese", + "@org_golang_x_text//encoding/unicode/utf32:utf32", + "@org_golang_x_text//encoding/unicode:unicode", + "@org_golang_x_text//message/pipeline:pipeline", + "@org_golang_x_tools//blog:blog", + "@org_golang_x_tools//cmd/bundle:bundle", + "@org_golang_x_tools//cmd/callgraph:callgraph", + "@org_golang_x_tools//cmd/file2fuzz:file2fuzz", + "@org_golang_x_tools//cmd/fiximports:fiximports", + "@org_golang_x_tools//cmd/godoc:godoc", + "@org_golang_x_tools//cmd/gorename:gorename", + "@org_golang_x_tools//cmd/guru:guru", + "@org_golang_x_tools//cmd/signature-fuzzer/fuzz-driver:fuzz-driver", + "@org_golang_x_tools//cmd/signature-fuzzer/fuzz-runner:fuzz-runner", + "@org_golang_x_tools//cmd/stringer:stringer", + "@org_golang_x_tools//container/intsets:intsets", + "@org_golang_x_tools//copyright:copyright", + "@org_golang_x_tools//go/analysis/analysistest:analysistest", + "@org_golang_x_tools//go/analysis/multichecker:multichecker", + "@org_golang_x_tools//go/analysis/passes/asmdecl:asmdecl", + "@org_golang_x_tools//go/analysis/passes/assign:assign", + "@org_golang_x_tools//go/analysis/passes/atomic:atomic", + "@org_golang_x_tools//go/analysis/passes/atomicalign:atomicalign", + "@org_golang_x_tools//go/analysis/passes/bools:bools", + "@org_golang_x_tools//go/analysis/passes/buildssa:buildssa", + "@org_golang_x_tools//go/analysis/passes/buildtag:buildtag", + "@org_golang_x_tools//go/analysis/passes/cgocall:cgocall", + "@org_golang_x_tools//go/analysis/passes/composite:composite", + "@org_golang_x_tools//go/analysis/passes/copylock:copylock", + "@org_golang_x_tools//go/analysis/passes/ctrlflow:ctrlflow", + "@org_golang_x_tools//go/analysis/passes/deepequalerrors:deepequalerrors", + "@org_golang_x_tools//go/analysis/passes/errorsas:errorsas", + "@org_golang_x_tools//go/analysis/passes/fieldalignment:fieldalignment", + "@org_golang_x_tools//go/analysis/passes/findcall:findcall", + "@org_golang_x_tools//go/analysis/passes/framepointer:framepointer", + "@org_golang_x_tools//go/analysis/passes/httpresponse:httpresponse", + "@org_golang_x_tools//go/analysis/passes/ifaceassert:ifaceassert", + "@org_golang_x_tools//go/analysis/passes/loopclosure:loopclosure", + "@org_golang_x_tools//go/analysis/passes/lostcancel:lostcancel", + "@org_golang_x_tools//go/analysis/passes/nilfunc:nilfunc", + "@org_golang_x_tools//go/analysis/passes/nilness:nilness", + "@org_golang_x_tools//go/analysis/passes/pkgfact:pkgfact", + "@org_golang_x_tools//go/analysis/passes/printf:printf", + "@org_golang_x_tools//go/analysis/passes/reflectvaluecompare:reflectvaluecompare", + "@org_golang_x_tools//go/analysis/passes/shadow:shadow", + "@org_golang_x_tools//go/analysis/passes/shift:shift", + "@org_golang_x_tools//go/analysis/passes/sigchanyzer:sigchanyzer", + "@org_golang_x_tools//go/analysis/passes/sortslice:sortslice", + "@org_golang_x_tools//go/analysis/passes/stdmethods:stdmethods", + "@org_golang_x_tools//go/analysis/passes/stringintconv:stringintconv", + "@org_golang_x_tools//go/analysis/passes/structtag:structtag", + "@org_golang_x_tools//go/analysis/passes/testinggoroutine:testinggoroutine", + "@org_golang_x_tools//go/analysis/passes/tests:tests", + "@org_golang_x_tools//go/analysis/passes/unmarshal:unmarshal", + "@org_golang_x_tools//go/analysis/passes/unreachable:unreachable", + "@org_golang_x_tools//go/analysis/passes/unsafeptr:unsafeptr", + "@org_golang_x_tools//go/analysis/passes/unusedresult:unusedresult", + "@org_golang_x_tools//go/analysis/passes/unusedwrite:unusedwrite", + "@org_golang_x_tools//go/analysis/passes/timeformat:timeformat", + "@org_golang_x_tools//go/analysis/passes/usesgenerics:usesgenerics", + "@org_golang_x_tools//go/analysis/unitchecker:unitchecker", + "@org_golang_x_tools//go/ast/inspector:inspector", + "@org_golang_x_tools//go/buildutil:buildutil", + "@org_golang_x_tools//go/callgraph/cha:cha", + "@org_golang_x_tools//go/callgraph/rta:rta", + "@org_golang_x_tools//go/callgraph/vta:vta", + "@org_golang_x_tools//go/expect:expect", + "@org_golang_x_tools//go/gccgoexportdata:gccgoexportdata", + "@org_golang_x_tools//go/gcexportdata:gcexportdata", + "@org_golang_x_tools//go/loader:loader", + "@org_golang_x_tools//go/packages/packagestest/testdata:testdata", + "@org_golang_x_tools//go/packages/packagestest:packagestest", + "@org_golang_x_tools//go/packages:packages", + "@org_golang_x_tools//go/pointer:pointer", + "@org_golang_x_tools//go/ssa/interp:interp", + "@org_golang_x_tools//go/ssa/ssautil:ssautil", + "@org_golang_x_tools//go/ssa:ssa", + "@org_golang_x_tools//go/types/typeutil:typeutil", + "@org_golang_x_tools//go/types/objectpath:objectpath", + "@org_golang_x_tools//godoc/static:static", + "@org_golang_x_tools//godoc/vfs/zipfs:zipfs", + "@org_golang_x_tools//godoc:godoc", + "@org_golang_x_tools//present:present", + "@org_golang_x_tools//refactor/eg:eg", + "@org_golang_x_tools//refactor/importgraph:importgraph", + "@org_golang_x_tools//refactor/rename:rename", + "@org_golang_x_mod//sumdb/tlog:tlog", + "@org_golang_x_mod//zip:zip", + ], +) diff --git a/tests/integration/popular_repos/README.rst b/tests/integration/popular_repos/README.rst new file mode 100644 index 00000000..ad071a37 --- /dev/null +++ b/tests/integration/popular_repos/README.rst @@ -0,0 +1,234 @@ +Popular repository tests +======================== + +These tests are designed to check that gazelle and rules_go together can cope +with a list of popluar repositories people depend on. + +It helps catch changes that might break a large number of users. + +.. contents:: + +org_golang_x_crypto +___________________ + +This runs tests from the repository `golang.org/x/crypto <https://golang.org/x/crypto>`_ + +* @org_golang_x_crypto//acme:acme_test +* @org_golang_x_crypto//acme/autocert:autocert_test +* @org_golang_x_crypto//argon2:argon2_test +* @org_golang_x_crypto//bcrypt:bcrypt_test +* @org_golang_x_crypto//blake2b:blake2b_test +* @org_golang_x_crypto//blake2s:blake2s_test +* @org_golang_x_crypto//blowfish:blowfish_test +* @org_golang_x_crypto//bn256:bn256_test +* @org_golang_x_crypto//cast5:cast5_test +* @org_golang_x_crypto//chacha20:chacha20_test +* @org_golang_x_crypto//chacha20poly1305:chacha20poly1305_test +* @org_golang_x_crypto//cryptobyte:cryptobyte_test +* @org_golang_x_crypto//curve25519:curve25519_test +* @org_golang_x_crypto//ed25519:ed25519_test +* @org_golang_x_crypto//hkdf:hkdf_test +* @org_golang_x_crypto//internal/subtle:subtle_test +* @org_golang_x_crypto//md4:md4_test +* @org_golang_x_crypto//nacl/auth:auth_test +* @org_golang_x_crypto//nacl/box:box_test +* @org_golang_x_crypto//nacl/secretbox:secretbox_test +* @org_golang_x_crypto//nacl/sign:sign_test +* @org_golang_x_crypto//ocsp:ocsp_test +* @org_golang_x_crypto//openpgp:openpgp_test +* @org_golang_x_crypto//openpgp/armor:armor_test +* @org_golang_x_crypto//openpgp/clearsign:clearsign_test +* @org_golang_x_crypto//openpgp/elgamal:elgamal_test +* @org_golang_x_crypto//openpgp/packet:packet_test +* @org_golang_x_crypto//openpgp/s2k:s2k_test +* @org_golang_x_crypto//otr:otr_test +* @org_golang_x_crypto//pbkdf2:pbkdf2_test +* @org_golang_x_crypto//pkcs12:pkcs12_test +* @org_golang_x_crypto//pkcs12/internal/rc2:rc2_test +* @org_golang_x_crypto//poly1305:poly1305_test +* @org_golang_x_crypto//ripemd160:ripemd160_test +* @org_golang_x_crypto//salsa20:salsa20_test +* @org_golang_x_crypto//salsa20/salsa:salsa_test +* @org_golang_x_crypto//scrypt:scrypt_test +* @org_golang_x_crypto//sha3:sha3_test +* @org_golang_x_crypto//ssh/internal/bcrypt_pbkdf:bcrypt_pbkdf_test +* @org_golang_x_crypto//ssh/knownhosts:knownhosts_test +* @org_golang_x_crypto//tea:tea_test +* @org_golang_x_crypto//twofish:twofish_test +* @org_golang_x_crypto//xtea:xtea_test +* @org_golang_x_crypto//xts:xts_test + + +org_golang_x_net +________________ + +This runs tests from the repository `golang.org/x/net <https://golang.org/x/net>`_ + +* @org_golang_x_net//context:context_test +* @org_golang_x_net//context/ctxhttp:ctxhttp_test +* @org_golang_x_net//dns/dnsmessage:dnsmessage_test +* @org_golang_x_net//html:html_test +* @org_golang_x_net//html/atom:atom_test +* @org_golang_x_net//http/httpguts:httpguts_test +* @org_golang_x_net//http/httpproxy:httpproxy_test +* @org_golang_x_net//http2/h2c:h2c_test +* @org_golang_x_net//http2/hpack:hpack_test +* @org_golang_x_net//idna:idna_test +* @org_golang_x_net//internal/socks:socks_test +* @org_golang_x_net//internal/sockstest:sockstest_test +* @org_golang_x_net//internal/timeseries:timeseries_test +* @org_golang_x_net//ipv4:ipv4_test +* @org_golang_x_net//ipv6:ipv6_test +* @org_golang_x_net//netutil:netutil_test +* @org_golang_x_net//proxy:proxy_test +* @org_golang_x_net//publicsuffix:publicsuffix_test +* @org_golang_x_net//trace:trace_test +* @org_golang_x_net//webdav:webdav_test +* @org_golang_x_net//webdav/internal/xml:xml_test +* @org_golang_x_net//websocket:websocket_test +* @org_golang_x_net//xsrftoken:xsrftoken_test + + +org_golang_x_sys +________________ + +This runs tests from the repository `golang.org/x/sys <https://golang.org/x/sys>`_ + +* @org_golang_x_sys//cpu:cpu_test +* @org_golang_x_sys//execabs:execabs_test +* @org_golang_x_sys//internal/unsafeheader:unsafeheader_test +* @org_golang_x_sys//plan9:plan9_test +* @org_golang_x_sys//unix/internal/mkmerge:mkmerge_test +* @org_golang_x_sys//windows/registry:registry_test +* @org_golang_x_sys//windows/svc:svc_test +* @org_golang_x_sys//windows/svc/eventlog:eventlog_test +* @org_golang_x_sys//windows/svc/mgr:mgr_test + + +org_golang_x_text +_________________ + +This runs tests from the repository `golang.org/x/text <https://golang.org/x/text>`_ + +* @org_golang_x_text//cases:cases_test +* @org_golang_x_text//collate:collate_test +* @org_golang_x_text//collate/build:build_test +* @org_golang_x_text//currency:currency_test +* @org_golang_x_text//date:date_test +* @org_golang_x_text//encoding:encoding_test +* @org_golang_x_text//encoding/htmlindex:htmlindex_test +* @org_golang_x_text//encoding/ianaindex:ianaindex_test +* @org_golang_x_text//feature/plural:plural_test +* @org_golang_x_text//internal:internal_test +* @org_golang_x_text//internal/catmsg:catmsg_test +* @org_golang_x_text//internal/colltab:colltab_test +* @org_golang_x_text//internal/export/idna:idna_test +* @org_golang_x_text//internal/export/unicode:unicode_test +* @org_golang_x_text//internal/format:format_test +* @org_golang_x_text//internal/language:language_test +* @org_golang_x_text//internal/language/compact:compact_test +* @org_golang_x_text//internal/number:number_test +* @org_golang_x_text//internal/stringset:stringset_test +* @org_golang_x_text//internal/tag:tag_test +* @org_golang_x_text//internal/triegen:triegen_test +* @org_golang_x_text//internal/ucd:ucd_test +* @org_golang_x_text//language:language_test +* @org_golang_x_text//language/display:display_test +* @org_golang_x_text//message:message_test +* @org_golang_x_text//message/catalog:catalog_test +* @org_golang_x_text//number:number_test +* @org_golang_x_text//runes:runes_test +* @org_golang_x_text//search:search_test +* @org_golang_x_text//secure/bidirule:bidirule_test +* @org_golang_x_text//secure/precis:precis_test +* @org_golang_x_text//transform:transform_test +* @org_golang_x_text//unicode/bidi:bidi_test +* @org_golang_x_text//unicode/cldr:cldr_test +* @org_golang_x_text//unicode/norm:norm_test +* @org_golang_x_text//unicode/rangetable:rangetable_test +* @org_golang_x_text//unicode/runenames:runenames_test +* @org_golang_x_text//width:width_test + + +org_golang_x_tools +__________________ + +This runs tests from the repository `golang.org/x/tools <https://golang.org/x/tools>`_ + +* @org_golang_x_tools//benchmark/parse:parse_test +* @org_golang_x_tools//cmd/benchcmp:benchcmp_test +* @org_golang_x_tools//cmd/digraph:digraph_test +* @org_golang_x_tools//cmd/getgo:getgo_test +* @org_golang_x_tools//cmd/go-contrib-init:go-contrib-init_test +* @org_golang_x_tools//cmd/splitdwarf/internal/macho:macho_test +* @org_golang_x_tools//cover:cover_test +* @org_golang_x_tools//go/analysis:analysis_test +* @org_golang_x_tools//go/analysis/passes/internal/analysisutil:analysisutil_test +* @org_golang_x_tools//go/ast/astutil:astutil_test +* @org_golang_x_tools//go/callgraph/static:static_test +* @org_golang_x_tools//go/callgraph/vta/internal/trie:trie_test +* @org_golang_x_tools//go/cfg:cfg_test +* @org_golang_x_tools//go/vcs:vcs_test +* @org_golang_x_tools//godoc/redirect:redirect_test +* @org_golang_x_tools//godoc/vfs:vfs_test +* @org_golang_x_tools//godoc/vfs/gatefs:gatefs_test +* @org_golang_x_tools//godoc/vfs/mapfs:mapfs_test +* @org_golang_x_tools//internal/bug:bug_test +* @org_golang_x_tools//internal/diff:diff_test +* @org_golang_x_tools//internal/diff/lcs:lcs_test +* @org_golang_x_tools//internal/diff/myers:myers_test +* @org_golang_x_tools//internal/event:event_test +* @org_golang_x_tools//internal/event/export:export_test +* @org_golang_x_tools//internal/event/export/ocagent:ocagent_test +* @org_golang_x_tools//internal/event/export/ocagent/wire:wire_test +* @org_golang_x_tools//internal/event/label:label_test +* @org_golang_x_tools//internal/fastwalk:fastwalk_test +* @org_golang_x_tools//internal/fuzzy:fuzzy_test +* @org_golang_x_tools//internal/gopathwalk:gopathwalk_test +* @org_golang_x_tools//internal/jsonrpc2:jsonrpc2_test +* @org_golang_x_tools//internal/jsonrpc2/servertest:servertest_test +* @org_golang_x_tools//internal/jsonrpc2_v2:jsonrpc2_v2_test +* @org_golang_x_tools//internal/memoize:memoize_test +* @org_golang_x_tools//internal/persistent:persistent_test +* @org_golang_x_tools//internal/proxydir:proxydir_test +* @org_golang_x_tools//internal/robustio:robustio_test +* @org_golang_x_tools//internal/stack:stack_test +* @org_golang_x_tools//internal/typesinternal:typesinternal_test +* @org_golang_x_tools//playground/socket:socket_test +* @org_golang_x_tools//refactor/satisfy:satisfy_test +* @org_golang_x_tools//txtar:txtar_test + + +com_github_golang_glog +______________________ + +This runs tests from the repository `github.com/golang/glog <https://github.com/golang/glog>`_ + +* @com_github_golang_glog//:glog_test + + +org_golang_x_sync +_________________ + +This runs tests from the repository `golang.org/x/sync <https://golang.org/x/sync>`_ + +* @org_golang_x_sync//errgroup:errgroup_test +* @org_golang_x_sync//semaphore:semaphore_test +* @org_golang_x_sync//singleflight:singleflight_test +* @org_golang_x_sync//syncmap:syncmap_test + + +org_golang_x_mod +________________ + +This runs tests from the repository `golang.org/x/mod <https://golang.org/x/mod>`_ + +* @org_golang_x_mod//modfile:modfile_test +* @org_golang_x_mod//module:module_test +* @org_golang_x_mod//semver:semver_test +* @org_golang_x_mod//sumdb:sumdb_test +* @org_golang_x_mod//sumdb/dirhash:dirhash_test +* @org_golang_x_mod//sumdb/note:note_test +* @org_golang_x_mod//sumdb/storage:storage_test + + diff --git a/tests/integration/popular_repos/popular_repos.bzl b/tests/integration/popular_repos/popular_repos.bzl new file mode 100644 index 00000000..752b654d --- /dev/null +++ b/tests/integration/popular_repos/popular_repos.bzl @@ -0,0 +1,75 @@ +# Copyright 2017 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +############################## +# Generated file, do not edit! +############################## + +load("@bazel_gazelle//:def.bzl", "go_repository") + +def _maybe(repo_rule, name, **kwargs): + if name not in native.existing_rules(): + repo_rule(name = name, **kwargs) + +def popular_repos(): + _maybe( + go_repository, + name = "org_golang_x_crypto", + importpath = "golang.org/x/crypto", + strip_prefix = "crypto-5ea612d1eb830b38bc4e914e37f55311eb58adce", + type = "zip", + urls = ["https://codeload.github.com/golang/crypto/zip/5ea612d1eb830b38bc4e914e37f55311eb58adce"], + ) + _maybe( + go_repository, + name = "org_golang_x_net", + importpath = "golang.org/x/net", + commit = "e18ecbb051101a46fc263334b127c89bc7bff7ea", + ) + _maybe( + go_repository, + name = "org_golang_x_sys", + importpath = "golang.org/x/sys", + commit = "390168757d9c647283340d526204e3409d5903f3", + ) + _maybe( + go_repository, + name = "org_golang_x_text", + importpath = "golang.org/x/text", + commit = "e3aa4adf54f644ca0cb35f1f1fb19b239c40ef04", + ) + _maybe( + go_repository, + name = "org_golang_x_tools", + importpath = "golang.org/x/tools", + commit = "fe37c9e135b934191089b245ac29325091462508", + ) + _maybe( + go_repository, + name = "com_github_golang_glog", + importpath = "github.com/golang/glog", + commit = "23def4e6c14b4da8ac2ed8007337bc5eb5007998", + ) + _maybe( + go_repository, + name = "org_golang_x_sync", + importpath = "golang.org/x/sync", + commit = "036812b2e83c0ddf193dd5a34e034151da389d09", + ) + _maybe( + go_repository, + name = "org_golang_x_mod", + importpath = "golang.org/x/mod", + commit = "86c51ed26bb44749b7d60a57bab0e7524656fe8a", + ) diff --git a/tests/integration/popular_repos/popular_repos.py b/tests/integration/popular_repos/popular_repos.py new file mode 100755 index 00000000..dbe645bf --- /dev/null +++ b/tests/integration/popular_repos/popular_repos.py @@ -0,0 +1,336 @@ +#!/usr/bin/env python3 +# Copyright 2017 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from subprocess import check_output, call +from sys import exit +from os import path + +POPULAR_REPOS = [ + dict( + name = "org_golang_x_crypto", + importpath = "golang.org/x/crypto", + urls = "https://codeload.github.com/golang/crypto/zip/5ea612d1eb830b38bc4e914e37f55311eb58adce", + strip_prefix = "crypto-5ea612d1eb830b38bc4e914e37f55311eb58adce", + type = "zip", + excludes = [ + "internal/wycheproof:wycheproof_test", # Needs GOROOT + "ssh/agent:agent_test", + "ssh/test:test_test", + "ssh:ssh_test", + ], + ), + + dict( + name = "org_golang_x_net", + importpath = "golang.org/x/net", + commit = "e18ecbb051101a46fc263334b127c89bc7bff7ea", + excludes = [ + "bpf:bpf_test", # Needs testdata directory + "html/charset:charset_test", # Needs testdata directory + "http2:http2_test", # Needs testdata directory + "icmp:icmp_test", # icmp requires adjusting kernel options. + "internal/socket:socket_test", # Needs GOROOT. + "nettest:nettest_test", # + "lif:lif_test", + ], + darwin_tests = [ + "route:route_test", # Not supported on linux + ] + ), + + dict( + name = "org_golang_x_sys", + importpath = "golang.org/x/sys", + commit = "390168757d9c647283340d526204e3409d5903f3", + excludes = [ + "unix:unix_test", # TestOpenByHandleAt reads source file. + "windows:windows_test", # Needs testdata directory + ], + ), + + dict( + name = "org_golang_x_text", + importpath = "golang.org/x/text", + commit = "e3aa4adf54f644ca0cb35f1f1fb19b239c40ef04", + excludes = [ + "encoding/charmap:charmap_test", # Needs testdata directory + "encoding/japanese:japanese_test", # Needs testdata directory + "encoding/korean:korean_test", # Needs testdata directory + "encoding/simplifiedchinese:simplifiedchinese_test", # Needs testdata directory + "encoding/traditionalchinese:traditionalchinese_test", # Needs testdata directory + "encoding/unicode/utf32:utf32_test", # Needs testdata directory + "encoding/unicode:unicode_test", # Needs testdata directory + "internal/cldrtree:cldrtree_test", # Needs testdata directory + "internal/gen/bitfield:bitfield_test", # Needs runfiles + "message/pipeline/testdata/test1:test1_test", # Not a real test + "message/pipeline:pipeline_test", # Needs testdata directory + ], + ), + + dict( + name = "org_golang_x_tools", + importpath = "golang.org/x/tools", + commit = "fe37c9e135b934191089b245ac29325091462508", + excludes = [ + "blog:blog_test", # Needs goldmark + "cmd/bundle:bundle_test", # Needs testdata directory + "cmd/callgraph/testdata/src/pkg:pkg_test", # is testdata + "cmd/callgraph:callgraph_test", # Needs testdata directory + "cmd/cover:cover_test", # Needs testdata directory + "cmd/file2fuzz:file2fuzz_test", # Requires working GOROOT, uses go build + "cmd/fiximports:fiximports_test", # requires working GOROOT, not present in CI. + "cmd/godoc:godoc_test", # TODO(#417) + "cmd/gorename:gorename_test", # TODO(#417) + "cmd/guru/testdata/src/referrers:referrers_test", # Not a real test + "cmd/guru:guru_test", # Needs testdata directory + "cmd/signature-fuzzer/fuzz-driver:fuzz-driver_test", # requires working GOROOT + "cmd/signature-fuzzer/fuzz-runner:fuzz-runner_test", # requires working GOROOT + "cmd/signature-fuzzer/internal/fuzz-generator:fuzz-generator_test", # requires working GOROOT + "cmd/stringer:stringer_test", # Needs testdata directory + "container/intsets:intsets_test", # TODO(#413): External test depends on symbols defined in internal test. + "copyright:copyright_test", # # requires runfiles + "go/analysis/analysistest:analysistest_test", # requires build cache + "go/analysis/internal/analysisflags:analysisflags_test", # calls os.Exit(0) in a test + "go/analysis/internal/checker:checker_test", # loads test package with go/packages, which probably needs go list + "go/analysis/multichecker:multichecker_test", # requires go vet + "go/analysis/passes/asmdecl:asmdecl_test", # Needs testdata directory + "go/analysis/passes/assign:assign_test", # Needs testdata directory + "go/analysis/passes/atomic:atomic_test", # Needs testdata directory + "go/analysis/passes/atomicalign:atomicalign_test", # requires go list + "go/analysis/passes/bools:bools_test", # Needs testdata directory + "go/analysis/passes/buildssa:buildssa_test", # Needs testdata directory + "go/analysis/passes/buildtag:buildtag_test", # Needs testdata directory + "go/analysis/passes/cgocall:cgocall_test", # Needs testdata directory + "go/analysis/passes/composite:composite_test", # Needs testdata directory + "go/analysis/passes/composite/testdata/src/a:a_test", # Does not compile + "go/analysis/passes/copylock:copylock_test", # Needs testdata directory + "go/analysis/passes/ctrlflow:ctrlflow_test", # Needs testdata directory + "go/analysis/passes/deepequalerrors:deepequalerrors_test", # requires go list + "go/analysis/passes/errorsas:errorsas_test", # requires go list and testdata + "go/analysis/passes/fieldalignment:fieldalignment_test", # Needs GOROOT + "go/analysis/passes/findcall:findcall_test", # requires build cache + "go/analysis/passes/framepointer:framepointer_test", # Needs GOROOT + "go/analysis/passes/httpresponse:httpresponse_test", # Needs testdata directory + "go/analysis/passes/ifaceassert:ifaceassert_test", # Needs GOROOT + "go/analysis/passes/loopclosure:loopclosure_test", # Needs testdata directory + "go/analysis/passes/lostcancel:lostcancel_test", # Needs testdata directory + "go/analysis/passes/nilfunc:nilfunc_test", # Needs testdata directory + "go/analysis/passes/nilness:nilness_test", # Needs testdata directory + "go/analysis/passes/pkgfact:pkgfact_test", # requires go list + "go/analysis/passes/printf:printf_test", # Needs testdata directory + "go/analysis/passes/reflectvaluecompare:reflectvaluecompare_test", # Needs testdata directory + "go/analysis/passes/shadow:shadow_test", # Needs testdata directory + "go/analysis/passes/shift:shift_test", # Needs testdata director + "go/analysis/passes/sigchanyzer:sigchanyzer_test", # Needs testdata directory + "go/analysis/passes/sortslice:sortslice_test", # Needs 'go list' + "go/analysis/passes/stdmethods:stdmethods_test", # Needs testdata directory + "go/analysis/passes/stringintconv:stringintconv_test", # Needs 'go list' + "go/analysis/passes/structtag:structtag_test", # Needs testdata directory + "go/analysis/passes/testinggoroutine:testinggoroutine_test", # Need 'go env' + "go/analysis/passes/tests/testdata/src/a:a_test", # Not a real test + "go/analysis/passes/tests/testdata/src/b_x_test:b_x_test_test", # Not a real test + "go/analysis/passes/tests/testdata/src/divergent:divergent_test", # Not a real test + "go/analysis/passes/tests/testdata/src/typeparams:typeparams_test", # Not a real test + "go/analysis/passes/tests:tests_test", # Needs testdata directory + "go/analysis/passes/unmarshal:unmarshal_test", # Needs go list + "go/analysis/passes/unreachable:unreachable_test", # Needs testdata directory + "go/analysis/passes/unsafeptr:unsafeptr_test", # Needs testdata directory + "go/analysis/passes/unusedresult:unusedresult_test", # Needs testdata directory + "go/analysis/passes/unusedwrite:unusedwrite_test", # Needs testdata directory + "go/analysis/passes/timeformat:timeformat_test", # Needs go tool + "go/analysis/passes/usesgenerics:usesgenerics_test", # Needs go tool + "go/analysis/unitchecker:unitchecker_test", # requires go vet + "go/ast/inspector:inspector_test", # requires GOROOT and GOPATH + "go/buildutil:buildutil_test", # Needs testdata directory + "go/callgraph/cha:cha_test", # Needs testdata directory + "go/callgraph/rta:rta_test", # Needs testdata directory + "go/callgraph/vta:vta_test", # Needs testdata directory + "go/expect:expect_test", # Needs testdata directory + "go/gccgoexportdata:gccgoexportdata_test", # Needs testdata directory + "go/gcexportdata:gcexportdata_test", # Needs testdata directory + "go/internal/gccgoimporter:gccgoimporter_test", # Needs testdata directory + "go/loader:loader_test", # Needs testdata directory + "go/packages/packagestest/testdata/groups/two/primarymod/expect:expect_test", # Is testdata + "go/packages/packagestest/testdata:testdata_test", # Is testdata + "go/packages/packagestest:packagestest_test", # requires build cache + "go/packages:packages_test", # Hah! + "go/pointer:pointer_test", # Needs testdata directory + "go/ssa/interp:interp_test", # Needs testdata directory + "go/ssa/ssautil:ssautil_test", # Needs testdata directory + "go/ssa:ssa_test", # Needs testdata directory + "go/types/typeutil:typeutil_test", # requires GOROOT + "go/types/objectpath:objectpath_test", # Incomaptible with Go SDK 1.18.3. Fixed in master but not yet released. TODO: fixme + "godoc/static:static_test", # requires data files + "godoc/vfs/zipfs:zipfs_test", # requires GOROOT + "godoc:godoc_test", # requires GOROOT and GOPATH + "internal/apidiff:apidiff_test", # Needs testdata directory + "internal/diff/difftest:difftest_test", # Needs diff tool + "internal/facts:facts_test", # loads test package with go/packages, which probably needs go list + "internal/gcimporter:gcimporter_test", # Needs testdata directory + "internal/gocommand:gocommand_test", # Needs go tool + "internal/imports:imports_test", # Needs testdata directory + "internal/typeparams:typeparams_test", # Needs go tool + "present:present_test", # Needs goldmark + "refactor/eg:eg_test", # Needs testdata directory + "refactor/importgraph:importgraph_test", # TODO(#417) + "refactor/rename:rename_test", # TODO(#417) + ], + ), + + dict( + name = "com_github_golang_glog", + importpath = "github.com/golang/glog", + commit = "23def4e6c14b4da8ac2ed8007337bc5eb5007998", + ), + + dict( + name = "org_golang_x_sync", + importpath = "golang.org/x/sync", + commit = "036812b2e83c0ddf193dd5a34e034151da389d09", + ), + + dict( + name = "org_golang_x_mod", + importpath = "golang.org/x/mod", + commit = "86c51ed26bb44749b7d60a57bab0e7524656fe8a", + excludes = [ + "sumdb/tlog:tlog_test", # Needs network, not available on RBE + "zip:zip_test", # Needs vcs tools, not available on RBE + ], + ), + ] + +COPYRIGHT_HEADER = """ +# Copyright 2017 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +############################## +# Generated file, do not edit! +############################## +""".strip() + +BZL_HEADER = COPYRIGHT_HEADER + """ + +load("@bazel_gazelle//:def.bzl", "go_repository") + +def _maybe(repo_rule, name, **kwargs): + if name not in native.existing_rules(): + repo_rule(name = name, **kwargs) + +def popular_repos(): +""" + +BUILD_HEADER = COPYRIGHT_HEADER + +DOCUMENTATION_HEADER = """ +Popular repository tests +======================== + +These tests are designed to check that gazelle and rules_go together can cope +with a list of popluar repositories people depend on. + +It helps catch changes that might break a large number of users. + +.. contents:: + +""".lstrip() + +LOAD_BAZEL_TEST_RULE = """ +load("@bazel_skylib//rules:build_test.bzl", "build_test") +""" + +def popular_repos_bzl(): + with open(path.join(path.dirname(__file__), "popular_repos.bzl"), "w") as f: + f.write(BZL_HEADER) + for repo in POPULAR_REPOS: + f.write(" _maybe(\n go_repository,\n") + for k in ["name", "importpath", "commit", "strip_prefix", "type", "build_file_proto_mode"]: + if k in repo: f.write(' {} = "{}",\n'.format(k, repo[k])) + for k in ["urls"]: + if k in repo: f.write(' {} = ["{}"],\n'.format(k, repo[k])) + f.write(" )\n") + +def build_bazel(): + with open(path.join(path.dirname(__file__), "BUILD.bazel"), "w") as f: + f.write(BUILD_HEADER) + f.write("\n" + LOAD_BAZEL_TEST_RULE) + build_only = [] + for repo in POPULAR_REPOS: + name = repo["name"] + tests = check_output(["bazel", "query", "kind(go_test, \"@{}//...\")".format(name)], text=True).split("\n") + excludes = ["@{}//{}".format(name, l) for l in repo.get("excludes", [])] + for k in repo: + if k.endswith("_excludes") or k.endswith("_tests"): + excludes.extend(["@{}//{}".format(name, l) for l in repo[k]]) + invalid_excludes = [t for t in excludes if not t in tests] + if invalid_excludes: + exit("Invalid excludes found: {}".format(invalid_excludes)) + build_only.extend(excludes) + f.write('\ntest_suite(\n') + f.write(' name = "{}",\n'.format(name)) + f.write(' tests = [\n') + actual = [] + for test in sorted(tests, key=lambda test: test.replace(":", "!")): + if test in excludes or not test: continue + f.write(' "{}",\n'.format(test)) + actual.append(test) + f.write(' ],\n') + #TODO: add in the platform "select" tests + f.write(')\n') + repo["actual"] = actual + + # add bazel test rule + f.write('\nbuild_test(\n') + f.write(' name = "{}",\n'.format("build_only")) + f.write(' targets = [\n') + for package in build_only: + if "/internal/" not in package and "/testdata/" not in package: + if package.endswith("_test"): + f.write(' "{}",\n'.format(package[:-5])) + else: + f.write(' "{}",\n'.format(package)) + f.write(' ],\n') + f.write(')\n') + +def readme_rst(): + with open(path.join(path.dirname(__file__), "README.rst"), "w") as f: + f.write(DOCUMENTATION_HEADER) + for repo in POPULAR_REPOS: + name = repo["name"] + f.write("{}\n{}\n\n".format(name, "_"*len(name))) + f.write("This runs tests from the repository `{0} <https://{0}>`_\n\n".format(repo["importpath"])) + for test in repo["actual"]: + f.write("* {}\n".format(test)) + f.write("\n\n") + + +def main(): + popular_repos_bzl() + build_bazel() + readme_rst() + +if __name__ == "__main__": + main() diff --git a/tests/integration/reproducibility/BUILD.bazel b/tests/integration/reproducibility/BUILD.bazel new file mode 100644 index 00000000..db5fd9b6 --- /dev/null +++ b/tests/integration/reproducibility/BUILD.bazel @@ -0,0 +1,6 @@ +load("@io_bazel_rules_go//go/tools/bazel_testing:def.bzl", "go_bazel_test") + +go_bazel_test( + name = "reproducibility_test", + srcs = ["reproducibility_test.go"], +) diff --git a/tests/integration/reproducibility/README.rst b/tests/integration/reproducibility/README.rst new file mode 100644 index 00000000..1ac77510 --- /dev/null +++ b/tests/integration/reproducibility/README.rst @@ -0,0 +1,14 @@ +Reproducibility + +reproducibility_test +-------------------- +Verifies that the files generated when building a set of targets are identical, +even when built from multiple copies of the same workspace. + +Currently covers pure ``go_binary`` targets and a cgo ``go_binary`` with +``linkmode = "c-archive"``. + +TODO: cover more modes. Currently, it seems like a cgo ``go_binary`` that +produces an executable is not reproducible on macOS. This is most likely +due to the external linker, since all the inputs to the linker are identical. +Needs investigation. diff --git a/tests/integration/reproducibility/reproducibility_test.go b/tests/integration/reproducibility/reproducibility_test.go new file mode 100644 index 00000000..2e9bc591 --- /dev/null +++ b/tests/integration/reproducibility/reproducibility_test.go @@ -0,0 +1,384 @@ +// Copyright 2019 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package reproducibility_test + +import ( + "bytes" + "crypto/sha256" + "encoding/hex" + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "sync" + "testing" + + "github.com/bazelbuild/rules_go/go/tools/bazel_testing" +) + +func TestMain(m *testing.M) { + bazel_testing.TestMain(m, bazel_testing.Args{ + Main: ` +-- BUILD.bazel -- +load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "empty_lib", + srcs = [], + importpath = "empty_lib", +) + +go_binary( + name = "hello", + srcs = ["hello.go"], +) + +go_binary( + name = "adder", + srcs = [ + "adder_main.go", + "adder.go", + "add.c", + "add.cpp", + "add.h", + ], + cgo = True, + linkmode = "c-archive", +) + +-- hello.go -- +package main + +import "fmt" + +func main() { + fmt.Println("hello") +} + +-- add.h -- +#ifdef __cplusplus +extern "C" { +#endif + +int add_c(int a, int b); +int add_cpp(int a, int b); + +#ifdef __cplusplus +} +#endif + +-- add.c -- +#include "add.h" +#include "_cgo_export.h" + +int add_c(int a, int b) { return add(a, b); } + +-- add.cpp -- +#include "add.h" +#include "_cgo_export.h" + +int add_cpp(int a, int b) { return add(a, b); } + +-- adder.go -- +package main + +/* +#include "add.h" +*/ +import "C" + +func AddC(a, b int32) int32 { + return int32(C.add_c(C.int(a), C.int(b))) +} + +func AddCPP(a, b int32) int32 { + return int32(C.add_cpp(C.int(a), C.int(b))) +} + +//export add +func add(a, b int32) int32 { + return a + b +} + +-- adder_main.go -- +package main + +import "fmt" + +func main() { + // Depend on some stdlib function. + fmt.Println("In C, 2 + 2 = ", AddC(2, 2)) + fmt.Println("In C++, 2 + 2 = ", AddCPP(2, 2)) +} + +`, + }) +} + +func Test(t *testing.T) { + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + + // Copy the workspace to three other directories. + // We'll run bazel commands in those directories, not here. We clean those + // workspaces at the end of the test, but we don't want to clean this + // directory because it's shared with other tests. + dirs := []string{wd + "0", wd + "1", wd + "2"} + for _, dir := range dirs { + if err := copyTree(dir, wd); err != nil { + t.Fatal(err) + } + defer func() { + cmd := bazel_testing.BazelCmd("clean", "--expunge") + cmd.Dir = dir + cmd.Run() + os.RemoveAll(dir) + }() + } + defer func() { + var wg sync.WaitGroup + wg.Add(len(dirs)) + for _, dir := range dirs { + go func(dir string) { + defer wg.Done() + cmd := bazel_testing.BazelCmd("clean", "--expunge") + cmd.Dir = dir + cmd.Run() + os.RemoveAll(dir) + }(dir) + } + wg.Wait() + }() + + // Change the source file in dir2. We should detect a difference here. + hello2Path := filepath.Join(dirs[2], "hello.go") + hello2File, err := os.OpenFile(hello2Path, os.O_WRONLY|os.O_APPEND, 0666) + if err != nil { + t.Fatal(err) + } + defer hello2File.Close() + if _, err := hello2File.WriteString(`func init() { fmt.Println("init") }`); err != nil { + t.Fatal(err) + } + if err := hello2File.Close(); err != nil { + t.Fatal(err) + } + + // Build the targets in each directory. + var wg sync.WaitGroup + wg.Add(len(dirs)) + for _, dir := range dirs { + go func(dir string) { + defer wg.Done() + cmd := bazel_testing.BazelCmd("build", + "//:all", + "@io_bazel_rules_go//go/tools/builders:go_path", + "@go_sdk//:builder", + ) + cmd.Dir = dir + if err := cmd.Run(); err != nil { + t.Fatalf("in %s, error running %s: %v", dir, strings.Join(cmd.Args, " "), err) + } + }(dir) + } + wg.Wait() + + // Hash files in each bazel-bin directory. + dirHashes := make([][]fileHash, len(dirs)) + errs := make([]error, len(dirs)) + wg.Add(len(dirs)) + for i := range dirs { + go func(i int) { + defer wg.Done() + dirHashes[i], errs[i] = hashFiles(filepath.Join(dirs[i], "bazel-bin")) + }(i) + } + wg.Wait() + for _, err := range errs { + if err != nil { + t.Fatal(err) + } + } + + // Compare dir0 and dir1. They should be identical. + if err := compareHashes(dirHashes[0], dirHashes[1]); err != nil { + t.Fatal(err) + } + + // Compare dir0 and dir2. They should be different. + if err := compareHashes(dirHashes[0], dirHashes[2]); err == nil { + t.Fatalf("dir0 and dir2 are the same)", len(dirHashes[0])) + } + + // Check that the go_sdk path doesn't appear in the builder binary. This path is different + // nominally different per workspace (but in these tests, the go_sdk paths are all set to the same + // path in WORKSPACE) -- so if this path is in the builder binary, then builds between workspaces + // would be partially non cacheable. + builder_file, err := os.Open(filepath.Join(dirs[0], "bazel-bin", "external", "go_sdk", "builder")) + if err != nil { + t.Fatal(err) + } + defer builder_file.Close() + builder_data, err := ioutil.ReadAll(builder_file) + if err != nil { + t.Fatal(err) + } + if bytes.Index(builder_data, []byte("go_sdk")) != -1 { + t.Fatalf("Found go_sdk path in builder binary, builder tool won't be reproducible") + } +} + +func copyTree(dstRoot, srcRoot string) error { + return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + rel, err := filepath.Rel(srcRoot, srcPath) + if err != nil { + return err + } + var dstPath string + if rel == "." { + dstPath = dstRoot + } else { + dstPath = filepath.Join(dstRoot, rel) + } + + if info.IsDir() { + return os.Mkdir(dstPath, 0777) + } + r, err := os.Open(srcPath) + if err != nil { + return nil + } + defer r.Close() + w, err := os.Create(dstPath) + if err != nil { + return err + } + defer w.Close() + if _, err := io.Copy(w, r); err != nil { + return err + } + return w.Close() + }) +} + +func compareHashes(lhs, rhs []fileHash) error { + buf := &bytes.Buffer{} + for li, ri := 0, 0; li < len(lhs) || ri < len(rhs); { + if li < len(lhs) && (ri == len(rhs) || lhs[li].rel < rhs[ri].rel) { + fmt.Fprintf(buf, "%s only in left\n", lhs[li].rel) + li++ + continue + } + if ri < len(rhs) && (li == len(lhs) || rhs[ri].rel < lhs[li].rel) { + fmt.Fprintf(buf, "%s only in right\n", rhs[ri].rel) + ri++ + continue + } + if lhs[li].hash != rhs[ri].hash { + fmt.Fprintf(buf, "%s is different: %s %s\n", lhs[li].rel, lhs[li].hash, rhs[ri].hash) + } + li++ + ri++ + } + if errStr := buf.String(); errStr != "" { + return errors.New(errStr) + } + return nil +} + +type fileHash struct { + rel, hash string +} + +func hashFiles(dir string) ([]fileHash, error) { + // Follow top-level symbolic link + root := dir + for { + info, err := os.Lstat(root) + if err != nil { + return nil, err + } + if info.Mode()&os.ModeType != os.ModeSymlink { + break + } + rel, err := os.Readlink(root) + if err != nil { + return nil, err + } + if filepath.IsAbs(rel) { + root = rel + } else { + root = filepath.Join(filepath.Dir(dir), rel) + } + } + + // Gather hashes of files within the tree. + var hashes []fileHash + var sum [16]byte + err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + // Skip directories and symbolic links to directories. + if info.Mode()&os.ModeType == os.ModeSymlink { + info, err = os.Stat(path) + if err != nil { + return err + } + } + if info.IsDir() { + return nil + } + + // Skip MANIFEST, runfiles_manifest, and .lo files. + // TODO(jayconrod): find out why .lo files are not reproducible. + base := filepath.Base(path) + if base == "MANIFEST" || strings.HasSuffix(base, ".runfiles_manifest") || strings.HasSuffix(base, ".lo") { + return nil + } + + rel, err := filepath.Rel(root, path) + if err != nil { + return err + } + + r, err := os.Open(path) + if err != nil { + return err + } + defer r.Close() + h := sha256.New() + if _, err := io.Copy(h, r); err != nil { + return err + } + hashes = append(hashes, fileHash{rel: rel, hash: hex.EncodeToString(h.Sum(sum[:0]))}) + + return nil + }) + if err != nil { + return nil, err + } + return hashes, nil +} |