]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile: add "toolstash -cmp"-like test of -d=unified
authorMatthew Dempsky <mdempsky@google.com>
Fri, 18 Jun 2021 10:21:43 +0000 (03:21 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Fri, 18 Jun 2021 23:20:30 +0000 (23:20 +0000)
This CL adds a longtest test to make sure -d=unified=1 produces output
identical to -d=unified=0.

Change-Id: I2c5d38f67dbc8fecd8332a91ba7cae22225b090c
Reviewed-on: https://go-review.googlesource.com/c/go/+/329429
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
src/cmd/compile/internal/noder/unified_test.go [new file with mode: 0644]

diff --git a/src/cmd/compile/internal/noder/unified_test.go b/src/cmd/compile/internal/noder/unified_test.go
new file mode 100644 (file)
index 0000000..242fa12
--- /dev/null
@@ -0,0 +1,151 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package noder_test
+
+import (
+       "encoding/json"
+       "flag"
+       exec "internal/execabs"
+       "os"
+       "reflect"
+       "runtime"
+       "strings"
+       "testing"
+)
+
+var (
+       flagPkgs     = flag.String("pkgs", "std", "list of packages to compare")
+       flagAll      = flag.Bool("all", false, "enable testing of all GOOS/GOARCH targets")
+       flagParallel = flag.Bool("parallel", false, "test GOOS/GOARCH targets in parallel")
+)
+
+// TestUnifiedCompare implements a test similar to running:
+//
+//     $ go build -toolexec="toolstash -cmp" std
+//
+// The -pkgs flag controls the list of packages tested.
+//
+// By default, only the native GOOS/GOARCH target is enabled. The -all
+// flag enables testing of non-native targets. The -parallel flag
+// additionally enables testing of targets in parallel.
+//
+// Caution: Testing all targets is very resource intensive! On an IBM
+// P920 (dual Intel Xeon Gold 6154 CPUs; 36 cores, 192GB RAM), testing
+// all targets in parallel takes about 5 minutes. Using the 'go test'
+// command's -run flag for subtest matching is recommended for less
+// powerful machines.
+func TestUnifiedCompare(t *testing.T) {
+       if testing.Short() {
+               t.Skip("skipping test in short mode")
+       }
+
+       targets, err := exec.Command("go", "tool", "dist", "list").Output()
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       for _, target := range strings.Fields(string(targets)) {
+               t.Run(target, func(t *testing.T) {
+                       parts := strings.Split(target, "/")
+                       goos, goarch := parts[0], parts[1]
+
+                       if !(*flagAll || goos == runtime.GOOS && goarch == runtime.GOARCH) {
+                               t.Skip("skipping non-native target (use -all to enable)")
+                       }
+                       if *flagParallel {
+                               t.Parallel()
+                       }
+
+                       pkgs1 := loadPackages(t, goos, goarch, "-d=unified=0 -d=inlfuncswithclosures=0")
+                       pkgs2 := loadPackages(t, goos, goarch, "-d=unified=1 -d=inlfuncswithclosures=0")
+
+                       if len(pkgs1) != len(pkgs2) {
+                               t.Fatalf("length mismatch: %v != %v", len(pkgs1), len(pkgs2))
+                       }
+
+                       for i := range pkgs1 {
+                               pkg1 := pkgs1[i]
+                               pkg2 := pkgs2[i]
+
+                               path := pkg1.ImportPath
+                               if path != pkg2.ImportPath {
+                                       t.Fatalf("mismatched paths: %q != %q", path, pkg2.ImportPath)
+                               }
+
+                               // Packages that don't have any source files (e.g., packages
+                               // unsafe, embed/internal/embedtest, and cmd/internal/moddeps).
+                               if pkg1.Export == "" && pkg2.Export == "" {
+                                       continue
+                               }
+
+                               if pkg1.BuildID == pkg2.BuildID {
+                                       t.Errorf("package %q: build IDs unexpectedly matched", path)
+                               }
+
+                               // Unlike toolstash -cmp, we're comparing the same compiler
+                               // binary against itself, just with different flags. So we
+                               // don't need to worry about skipping over mismatched version
+                               // strings, but we do need to account for differing build IDs.
+                               //
+                               // Fortunately, build IDs are cryptographic 256-bit hashes,
+                               // and cmd/go provides us with them up front. So we can just
+                               // use them as delimeters to split the files, and then check
+                               // that the substrings are all equal.
+                               file1 := strings.Split(readFile(t, pkg1.Export), pkg1.BuildID)
+                               file2 := strings.Split(readFile(t, pkg2.Export), pkg2.BuildID)
+                               if !reflect.DeepEqual(file1, file2) {
+                                       t.Errorf("package %q: compile output differs", path)
+                               }
+                       }
+               })
+       }
+}
+
+type pkg struct {
+       ImportPath string
+       Export     string
+       BuildID    string
+       Incomplete bool
+}
+
+func loadPackages(t *testing.T, goos, goarch, gcflags string) []pkg {
+       args := []string{"list", "-e", "-export", "-json", "-gcflags=all=" + gcflags, "--"}
+       args = append(args, strings.Fields(*flagPkgs)...)
+
+       cmd := exec.Command("go", args...)
+       cmd.Env = append(os.Environ(), "GOOS="+goos, "GOARCH="+goarch)
+       cmd.Stderr = os.Stderr
+       stdout, err := cmd.StdoutPipe()
+       if err != nil {
+               t.Fatal(err)
+       }
+       if err := cmd.Start(); err != nil {
+               t.Fatal(err)
+       }
+
+       var res []pkg
+       for dec := json.NewDecoder(stdout); dec.More(); {
+               var pkg pkg
+               if err := dec.Decode(&pkg); err != nil {
+                       t.Fatal(err)
+               }
+               if pkg.Incomplete {
+                       t.Fatalf("incomplete package: %q", pkg.ImportPath)
+               }
+               res = append(res, pkg)
+       }
+       if err := cmd.Wait(); err != nil {
+               t.Fatal(err)
+       }
+       return res
+}
+
+func readFile(t *testing.T, name string) string {
+       buf, err := os.ReadFile(name)
+       if err != nil {
+               t.Fatal(err)
+       }
+       return string(buf)
+}