// 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 test import ( "internal/goexperiment" "internal/testenv" "io/ioutil" "os" "os/exec" "path/filepath" "regexp" "testing" ) // TestInst tests that only one instantiation of Sort is created, even though generic // Sort is used for multiple pointer types across two packages. func TestInst(t *testing.T) { if goexperiment.Unified { t.Skip("unified currently does stenciling, not dictionaries") } testenv.MustHaveGoBuild(t) testenv.MustHaveGoRun(t) var tmpdir string var err error tmpdir, err = ioutil.TempDir("", "TestDict") if err != nil { t.Fatalf("Failed to create temporary directory: %v", err) } defer os.RemoveAll(tmpdir) // Build ptrsort.go, which uses package mysort. var output []byte filename := "ptrsort.go" exename := "ptrsort" outname := "ptrsort.out" gotool := testenv.GoToolPath(t) dest := filepath.Join(tmpdir, exename) cmd := exec.Command(gotool, "build", "-o", dest, filepath.Join("testdata", filename)) if output, err = cmd.CombinedOutput(); err != nil { t.Fatalf("Failed: %v:\nOutput: %s\n", err, output) } // Test that there is exactly one shape-based instantiation of Sort in // the executable. cmd = exec.Command(gotool, "tool", "nm", dest) if output, err = cmd.CombinedOutput(); err != nil { t.Fatalf("Failed: %v:\nOut: %s\n", err, output) } // Look for shape-based instantiation of Sort, but ignore any extra wrapper // ending in "-tramp" (which are created on riscv). re := regexp.MustCompile(`\bSort\[.*shape.*\][^-]`) r := re.FindAllIndex(output, -1) if len(r) != 1 { t.Fatalf("Wanted 1 instantiations of Sort function, got %d\n", len(r)) } // Actually run the test and make sure output is correct. cmd = exec.Command(gotool, "run", filepath.Join("testdata", filename)) if output, err = cmd.CombinedOutput(); err != nil { t.Fatalf("Failed: %v:\nOut: %s\n", err, output) } out, err := ioutil.ReadFile(filepath.Join("testdata", outname)) if err != nil { t.Fatalf("Could not find %s\n", outname) } if string(out) != string(output) { t.Fatalf("Wanted output %v, got %v\n", string(out), string(output)) } }