File: stdlib_test.go

package info (click to toggle)
golang-golang-x-tools 1%3A0.0~git20190125.d66bd3c%2Bds-4
  • links: PTS, VCS
  • area: main
  • in suites: buster, buster-backports
  • size: 8,912 kB
  • sloc: asm: 1,394; yacc: 155; makefile: 109; sh: 108; ansic: 17; xml: 11
file content (136 lines) | stat: -rw-r--r-- 4,053 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright 2018 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 packages_test

import (
	"bytes"
	"io/ioutil"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
	"time"

	"golang.org/x/tools/go/packages"
)

// This test loads the metadata for the standard library,
func TestStdlibMetadata(t *testing.T) {
	// TODO(adonovan): see if we can get away without this hack.
	// if runtime.GOOS == "android" {
	// 	t.Skipf("incomplete std lib on %s", runtime.GOOS)
	// }

	runtime.GC()
	t0 := time.Now()
	var memstats runtime.MemStats
	runtime.ReadMemStats(&memstats)
	alloc := memstats.Alloc

	// Load, parse and type-check the program.
	cfg := &packages.Config{Mode: packages.LoadAllSyntax}
	pkgs, err := packages.Load(cfg, "std")
	if err != nil {
		t.Fatalf("failed to load metadata: %v", err)
	}
	if packages.PrintErrors(pkgs) > 0 {
		t.Fatal("there were errors loading standard library")
	}

	t1 := time.Now()
	runtime.GC()
	runtime.ReadMemStats(&memstats)
	runtime.KeepAlive(pkgs)

	t.Logf("Loaded %d packages", len(pkgs))
	numPkgs := len(pkgs)

	want := 150 // 186 on linux, 185 on windows.
	if numPkgs < want {
		t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want)
	}

	t.Log("GOMAXPROCS: ", runtime.GOMAXPROCS(0))
	t.Log("Metadata:   ", t1.Sub(t0))                          // ~800ms on 12 threads
	t.Log("#MB:        ", int64(memstats.Alloc-alloc)/1000000) // ~1MB
}

func TestCgoOption(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping in short mode; uses tons of memory (https://golang.org/issue/14113)")
	}

	// TODO(adonovan): see if we can get away without these old
	// go/loader hacks now that we use the go list command.
	//
	// switch runtime.GOOS {
	// // On these systems, the net and os/user packages don't use cgo
	// // or the std library is incomplete (Android).
	// case "android", "plan9", "solaris", "windows":
	// 	t.Skipf("no cgo or incomplete std lib on %s", runtime.GOOS)
	// }
	// // In nocgo builds (e.g. linux-amd64-nocgo),
	// // there is no "runtime/cgo" package,
	// // so cgo-generated Go files will have a failing import.
	// if !build.Default.CgoEnabled {
	// 	return
	// }

	// Test that we can load cgo-using packages with
	// DisableCgo=true/false, which, among other things, causes go
	// list to select pure Go/native implementations, respectively,
	// based on build tags.
	//
	// Each entry specifies a package-level object and the generic
	// file expected to define it when cgo is disabled.
	// When cgo is enabled, the exact file is not specified (since
	// it varies by platform), but must differ from the generic one.
	//
	// The test also loads the actual file to verify that the
	// object is indeed defined at that location.
	for _, test := range []struct {
		pkg, name, genericFile string
	}{
		{"net", "cgoLookupHost", "cgo_stub.go"},
		{"os/user", "current", "lookup_stubs.go"},
	} {
		cfg := &packages.Config{Mode: packages.LoadSyntax}
		pkgs, err := packages.Load(cfg, test.pkg)
		if err != nil {
			t.Errorf("Load failed: %v", err)
			continue
		}
		if packages.PrintErrors(pkgs) > 0 {
			t.Error("there were errors loading standard library")
			continue
		}
		pkg := pkgs[0]
		obj := pkg.Types.Scope().Lookup(test.name)
		if obj == nil {
			t.Errorf("no object %s.%s", test.pkg, test.name)
			continue
		}
		posn := pkg.Fset.Position(obj.Pos())
		gotFile := filepath.Base(posn.Filename)
		filesMatch := gotFile == test.genericFile

		if filesMatch {
			t.Errorf("!DisableCgo: %s found in %s, want native file",
				obj, gotFile)
		}

		// Load the file and check the object is declared at the right place.
		b, err := ioutil.ReadFile(posn.Filename)
		if err != nil {
			t.Errorf("can't read %s: %s", posn.Filename, err)
			continue
		}
		line := string(bytes.Split(b, []byte("\n"))[posn.Line-1])
		// Don't assume posn.Column is accurate.
		if !strings.Contains(line, "func "+test.name) {
			t.Errorf("%s: %s not declared here (looking at %q)", posn, obj, line)
		}
	}
}