GoPLS Viewer

Home|gopls/internal/gcimporter/stdlib_test.go
1// Copyright 2022 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package gcimporter_test
6
7import (
8    "bytes"
9    "fmt"
10    "go/token"
11    "go/types"
12    "runtime"
13    "testing"
14    "unsafe"
15
16    "golang.org/x/tools/go/gcexportdata"
17    "golang.org/x/tools/go/packages"
18    "golang.org/x/tools/internal/testenv"
19)
20
21// TestStdlib ensures that all packages in std and x/tools can be
22// type-checked using export data. Takes around 3s.
23func TestStdlib(t *testing.T) {
24    testenv.NeedsGoPackages(t)
25
26    // gcexportdata.Read rapidly consumes FileSet address space,
27    // so disable the test on 32-bit machines.
28    // (We could use a fresh FileSet per type-check, but that
29    // would require us to re-parse the source using it.)
30    if unsafe.Sizeof(token.NoPos) < 8 {
31        t.Skip("skipping test on 32-bit machine")
32    }
33
34    // Load, parse and type-check the standard library.
35    // If we have the full source code for x/tools, also load and type-check that.
36    cfg := &packages.Config{Modepackages.LoadAllSyntax}
37    patterns := []string{"std"}
38    minPkgs := 225 // 'GOOS=plan9 go1.18 list std | wc -l' reports 228; most other platforms have more.
39    switch runtime.GOOS {
40    case "android""ios":
41        // The go_.*_exec script for mobile builders only copies over the source tree
42        // for the package under test.
43    default:
44        patterns = append(patterns"golang.org/x/tools/...")
45        minPkgs += 160 // At the time of writing, 'GOOS=plan9 go list ./... | wc -l' reports 188.
46    }
47    pkgserr := packages.Load(cfgpatterns...)
48    if err != nil {
49        t.Fatalf("failed to load/parse/type-check: %v"err)
50    }
51    if packages.PrintErrors(pkgs) > 0 {
52        t.Fatal("there were errors during loading")
53    }
54    if len(pkgs) < minPkgs {
55        t.Errorf("too few packages (%d) were loaded"len(pkgs))
56    }
57
58    export := make(map[string][]byte// keys are package IDs
59
60    // Re-type check them all in post-order, using export data.
61    packages.Visit(pkgsnil, func(pkg *packages.Package) {
62        packages := make(map[string]*types.Package// keys are package paths
63        cfg := &types.Config{
64            Error: func(e error) {
65                t.Errorf("type error: %v"e)
66            },
67            ImporterimporterFunc(func(importPath string) (*types.Packageerror) {
68                // Resolve import path to (vendored?) package path.
69                imported := pkg.Imports[importPath]
70
71                if imported.PkgPath == "unsafe" {
72                    return types.Unsafenil // unsafe has no exportdata
73                }
74
75                dataok := export[imported.ID]
76                if !ok {
77                    return nilfmt.Errorf("missing export data for %s"importPath)
78                }
79                return gcexportdata.Read(bytes.NewReader(data), pkg.Fsetpackagesimported.PkgPath)
80            }),
81        }
82
83        // Re-typecheck the syntax and save the export data in the map.
84        newPkg := types.NewPackage(pkg.PkgPathpkg.Name)
85        check := types.NewChecker(cfgpkg.FsetnewPkgnil)
86        check.Files(pkg.Syntax)
87
88        var out bytes.Buffer
89        if err := gcexportdata.Write(&outpkg.FsetnewPkg); err != nil {
90            t.Fatalf("internal error writing export data: %v"err)
91        }
92        export[pkg.ID] = out.Bytes()
93    })
94}
95
MembersX
TestStdlib.minPkgs
TestStdlib.err
TestStdlib.BlockStmt.check
TestStdlib.BlockStmt.out
unsafe
TestStdlib
TestStdlib.cfg
TestStdlib.export
TestStdlib.BlockStmt.cfg
TestStdlib.BlockStmt.newPkg
TestStdlib.patterns
TestStdlib.BlockStmt.packages
TestStdlib.t
TestStdlib.pkgs
TestStdlib.BlockStmt.err
Members
X