...

Source file src/go/build/deps_test.go

Documentation: go/build

		 1  // Copyright 2012 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  
		 5  // This file exercises the import parser but also checks that
		 6  // some low-level packages do not have new dependencies added.
		 7  
		 8  package build
		 9  
		10  import (
		11  	"bytes"
		12  	"fmt"
		13  	"go/token"
		14  	"internal/testenv"
		15  	"io/fs"
		16  	"os"
		17  	"path/filepath"
		18  	"runtime"
		19  	"sort"
		20  	"strings"
		21  	"testing"
		22  )
		23  
		24  // depsRules defines the expected dependencies between packages in
		25  // the Go source tree. It is a statement of policy.
		26  //
		27  // DO NOT CHANGE THIS DATA TO FIX BUILDS.
		28  // Existing packages should not have their constraints relaxed
		29  // without prior discussion.
		30  // Negative assertions should almost never be removed.
		31  //
		32  // The general syntax of a rule is:
		33  //
		34  //		a, b < c, d;
		35  //
		36  // which means c and d come after a and b in the partial order
		37  // (that is, c and d can import a and b),
		38  // but doesn't provide a relative order between a vs b or c vs d.
		39  //
		40  // The rules can chain together, as in:
		41  //
		42  //		e < f, g < h;
		43  //
		44  // which is equivalent to
		45  //
		46  //		e < f, g;
		47  //		f, g < h;
		48  //
		49  // Except for the special bottom element "NONE", each name
		50  // must appear exactly once on the right-hand side of a rule.
		51  // That rule serves as the definition of the allowed dependencies
		52  // for that name. The definition must appear before any uses
		53  // of the name on the left-hand side of a rule. (That is, the
		54  // rules themselves must be ordered according to the partial
		55  // order, for easier reading by people.)
		56  //
		57  // Negative assertions double-check the partial order:
		58  //
		59  //		i !< j
		60  //
		61  // means that it must NOT be the case that i < j.
		62  // Negative assertions may appear anywhere in the rules,
		63  // even before i and j have been defined.
		64  //
		65  // Comments begin with #.
		66  //
		67  // All-caps names are pseudo-names for specific points
		68  // in the dependency lattice.
		69  //
		70  var depsRules = `
		71  	# No dependencies allowed for any of these packages.
		72  	NONE
		73  	< container/list, container/ring,
		74  		internal/cfg, internal/cpu, internal/goexperiment,
		75  		internal/goversion, internal/nettrace,
		76  		unicode/utf8, unicode/utf16, unicode,
		77  		unsafe;
		78  
		79  	# These packages depend only on unsafe.
		80  	unsafe
		81  	< internal/abi;
		82  
		83  	# RUNTIME is the core runtime group of packages, all of them very light-weight.
		84  	internal/abi, internal/cpu, internal/goexperiment, unsafe
		85  	< internal/bytealg
		86  	< internal/itoa
		87  	< internal/unsafeheader
		88  	< runtime/internal/sys
		89  	< runtime/internal/atomic
		90  	< runtime/internal/math
		91  	< runtime
		92  	< sync/atomic
		93  	< internal/race
		94  	< sync
		95  	< internal/reflectlite
		96  	< errors
		97  	< internal/oserror, math/bits
		98  	< RUNTIME;
		99  
	 100  	RUNTIME
	 101  	< sort
	 102  	< container/heap;
	 103  
	 104  	RUNTIME
	 105  	< io;
	 106  
	 107  	syscall !< io;
	 108  	reflect !< sort;
	 109  
	 110  	RUNTIME, unicode/utf8
	 111  	< path;
	 112  
	 113  	unicode !< path;
	 114  
	 115  	# SYSCALL is RUNTIME plus the packages necessary for basic system calls.
	 116  	RUNTIME, unicode/utf8, unicode/utf16
	 117  	< internal/syscall/windows/sysdll, syscall/js
	 118  	< syscall
	 119  	< internal/syscall/unix, internal/syscall/windows, internal/syscall/windows/registry
	 120  	< internal/syscall/execenv
	 121  	< SYSCALL;
	 122  
	 123  	# TIME is SYSCALL plus the core packages about time, including context.
	 124  	SYSCALL
	 125  	< time/tzdata
	 126  	< time
	 127  	< context
	 128  	< TIME;
	 129  
	 130  	TIME, io, path, sort
	 131  	< io/fs;
	 132  
	 133  	# MATH is RUNTIME plus the basic math packages.
	 134  	RUNTIME
	 135  	< math
	 136  	< MATH;
	 137  
	 138  	unicode !< math;
	 139  
	 140  	MATH
	 141  	< math/cmplx;
	 142  
	 143  	MATH
	 144  	< math/rand;
	 145  
	 146  	MATH
	 147  	< runtime/metrics;
	 148  
	 149  	MATH, unicode/utf8
	 150  	< strconv;
	 151  
	 152  	unicode !< strconv;
	 153  
	 154  	# STR is basic string and buffer manipulation.
	 155  	RUNTIME, io, unicode/utf8, unicode/utf16, unicode
	 156  	< bytes, strings
	 157  	< bufio;
	 158  
	 159  	bufio, path, strconv
	 160  	< STR;
	 161  
	 162  	# OS is basic OS access, including helpers (path/filepath, os/exec, etc).
	 163  	# OS includes string routines, but those must be layered above package os.
	 164  	# OS does not include reflection.
	 165  	io/fs
	 166  	< internal/testlog
	 167  	< internal/poll
	 168  	< os
	 169  	< os/signal;
	 170  
	 171  	io/fs
	 172  	< embed;
	 173  
	 174  	unicode, fmt !< os, os/signal;
	 175  
	 176  	os/signal, STR
	 177  	< path/filepath
	 178  	< io/ioutil, os/exec;
	 179  
	 180  	io/ioutil, os/exec, os/signal
	 181  	< OS;
	 182  
	 183  	reflect !< OS;
	 184  
	 185  	OS
	 186  	< golang.org/x/sys/cpu;
	 187  
	 188  	# FMT is OS (which includes string routines) plus reflect and fmt.
	 189  	# It does not include package log, which should be avoided in core packages.
	 190  	strconv, unicode
	 191  	< reflect;
	 192  
	 193  	os, reflect
	 194  	< internal/fmtsort
	 195  	< fmt;
	 196  
	 197  	OS, fmt
	 198  	< FMT;
	 199  
	 200  	log !< FMT;
	 201  
	 202  	OS, FMT
	 203  	< internal/execabs;
	 204  
	 205  	OS, internal/execabs
	 206  	< internal/goroot;
	 207  
	 208  	# Misc packages needing only FMT.
	 209  	FMT
	 210  	< flag,
	 211  		html,
	 212  		mime/quotedprintable,
	 213  		net/internal/socktest,
	 214  		net/url,
	 215  		runtime/debug,
	 216  		runtime/trace,
	 217  		text/scanner,
	 218  		text/tabwriter;
	 219  
	 220  	# encodings
	 221  	# core ones do not use fmt.
	 222  	io, strconv
	 223  	< encoding;
	 224  
	 225  	encoding, reflect
	 226  	< encoding/binary
	 227  	< encoding/base32, encoding/base64;
	 228  
	 229  	fmt !< encoding/base32, encoding/base64;
	 230  
	 231  	FMT, encoding/base32, encoding/base64
	 232  	< encoding/ascii85, encoding/csv, encoding/gob, encoding/hex,
	 233  		encoding/json, encoding/pem, encoding/xml, mime;
	 234  
	 235  	# hashes
	 236  	io
	 237  	< hash
	 238  	< hash/adler32, hash/crc32, hash/crc64, hash/fnv, hash/maphash;
	 239  
	 240  	# math/big
	 241  	FMT, encoding/binary, math/rand
	 242  	< math/big;
	 243  
	 244  	# compression
	 245  	FMT, encoding/binary, hash/adler32, hash/crc32
	 246  	< compress/bzip2, compress/flate, compress/lzw
	 247  	< archive/zip, compress/gzip, compress/zlib;
	 248  
	 249  	# templates
	 250  	FMT
	 251  	< text/template/parse;
	 252  
	 253  	net/url, text/template/parse
	 254  	< text/template
	 255  	< internal/lazytemplate;
	 256  
	 257  	encoding/json, html, text/template
	 258  	< html/template;
	 259  
	 260  	# regexp
	 261  	FMT
	 262  	< regexp/syntax
	 263  	< regexp
	 264  	< internal/lazyregexp;
	 265  
	 266  	# suffix array
	 267  	encoding/binary, regexp
	 268  	< index/suffixarray;
	 269  
	 270  	# executable parsing
	 271  	FMT, encoding/binary, compress/zlib
	 272  	< debug/dwarf
	 273  	< debug/elf, debug/gosym, debug/macho, debug/pe, debug/plan9obj, internal/xcoff
	 274  	< DEBUG;
	 275  
	 276  	# go parser and friends.
	 277  	FMT
	 278  	< go/token
	 279  	< go/scanner
	 280  	< go/ast
	 281  	< go/internal/typeparams
	 282  	< go/parser;
	 283  
	 284  	FMT
	 285  	< go/build/constraint;
	 286  
	 287  	go/build/constraint, go/parser, text/tabwriter
	 288  	< go/printer
	 289  	< go/format;
	 290  
	 291  	go/parser, internal/lazyregexp, text/template
	 292  	< go/doc;
	 293  
	 294  	math/big, go/token
	 295  	< go/constant;
	 296  
	 297  	container/heap, go/constant, go/parser, regexp
	 298  	< go/types;
	 299  
	 300  	FMT, internal/goexperiment
	 301  	< internal/buildcfg;
	 302  
	 303  	go/build/constraint, go/doc, go/parser, internal/buildcfg, internal/goroot, internal/goversion
	 304  	< go/build;
	 305  
	 306  	DEBUG, go/build, go/types, text/scanner
	 307  	< go/internal/gcimporter, go/internal/gccgoimporter, go/internal/srcimporter
	 308  	< go/importer;
	 309  
	 310  	# databases
	 311  	FMT
	 312  	< database/sql/internal
	 313  	< database/sql/driver
	 314  	< database/sql;
	 315  
	 316  	# images
	 317  	FMT, compress/lzw, compress/zlib
	 318  	< image/color
	 319  	< image, image/color/palette
	 320  	< image/internal/imageutil
	 321  	< image/draw
	 322  	< image/gif, image/jpeg, image/png;
	 323  
	 324  	# cgo, delayed as long as possible.
	 325  	# If you add a dependency on CGO, you must add the package
	 326  	# to cgoPackages in cmd/dist/test.go as well.
	 327  	RUNTIME
	 328  	< C
	 329  	< runtime/cgo
	 330  	< CGO
	 331  	< runtime/race, runtime/msan;
	 332  
	 333  	# Bulk of the standard library must not use cgo.
	 334  	# The prohibition stops at net and os/user.
	 335  	C !< fmt, go/types, CRYPTO-MATH;
	 336  
	 337  	CGO, OS
	 338  	< plugin;
	 339  
	 340  	CGO, FMT
	 341  	< os/user
	 342  	< archive/tar;
	 343  
	 344  	sync
	 345  	< internal/singleflight;
	 346  
	 347  	os
	 348  	< golang.org/x/net/dns/dnsmessage,
	 349  		golang.org/x/net/lif,
	 350  		golang.org/x/net/route;
	 351  
	 352  	# net is unavoidable when doing any networking,
	 353  	# so large dependencies must be kept out.
	 354  	# This is a long-looking list but most of these
	 355  	# are small with few dependencies.
	 356  	CGO,
	 357  	golang.org/x/net/dns/dnsmessage,
	 358  	golang.org/x/net/lif,
	 359  	golang.org/x/net/route,
	 360  	internal/nettrace,
	 361  	internal/poll,
	 362  	internal/singleflight,
	 363  	internal/race,
	 364  	os
	 365  	< net;
	 366  
	 367  	fmt, unicode !< net;
	 368  	math/rand !< net; # net uses runtime instead
	 369  
	 370  	# NET is net plus net-helper packages.
	 371  	FMT, net
	 372  	< net/textproto;
	 373  
	 374  	mime, net/textproto, net/url
	 375  	< NET;
	 376  
	 377  	# logging - most packages should not import; http and up is allowed
	 378  	FMT
	 379  	< log;
	 380  
	 381  	log !< crypto/tls, database/sql, go/importer, testing;
	 382  
	 383  	FMT, log, net
	 384  	< log/syslog;
	 385  
	 386  	NET, log
	 387  	< net/mail;
	 388  
	 389  	# CRYPTO is core crypto algorithms - no cgo, fmt, net.
	 390  	# Unfortunately, stuck with reflect via encoding/binary.
	 391  	encoding/binary, golang.org/x/sys/cpu, hash
	 392  	< crypto
	 393  	< crypto/subtle
	 394  	< crypto/internal/subtle
	 395  	< crypto/elliptic/internal/fiat
	 396  	< crypto/ed25519/internal/edwards25519/field
	 397  	< crypto/ed25519/internal/edwards25519
	 398  	< crypto/cipher
	 399  	< crypto/aes, crypto/des, crypto/hmac, crypto/md5, crypto/rc4,
	 400  		crypto/sha1, crypto/sha256, crypto/sha512
	 401  	< CRYPTO;
	 402  
	 403  	CGO, fmt, net !< CRYPTO;
	 404  
	 405  	# CRYPTO-MATH is core bignum-based crypto - no cgo, net; fmt now ok.
	 406  	CRYPTO, FMT, math/big
	 407  	< crypto/rand
	 408  	< crypto/internal/randutil
	 409  	< crypto/ed25519
	 410  	< encoding/asn1
	 411  	< golang.org/x/crypto/cryptobyte/asn1
	 412  	< golang.org/x/crypto/cryptobyte
	 413  	< golang.org/x/crypto/curve25519
	 414  	< crypto/dsa, crypto/elliptic, crypto/rsa
	 415  	< crypto/ecdsa
	 416  	< CRYPTO-MATH;
	 417  
	 418  	CGO, net !< CRYPTO-MATH;
	 419  
	 420  	# TLS, Prince of Dependencies.
	 421  	CRYPTO-MATH, NET, container/list, encoding/hex, encoding/pem
	 422  	< golang.org/x/crypto/internal/subtle
	 423  	< golang.org/x/crypto/chacha20
	 424  	< golang.org/x/crypto/poly1305
	 425  	< golang.org/x/crypto/chacha20poly1305
	 426  	< golang.org/x/crypto/hkdf
	 427  	< crypto/x509/internal/macos
	 428  	< crypto/x509/pkix
	 429  	< crypto/x509
	 430  	< crypto/tls;
	 431  
	 432  	# crypto-aware packages
	 433  
	 434  	NET, crypto/rand, mime/quotedprintable
	 435  	< mime/multipart;
	 436  
	 437  	crypto/tls
	 438  	< net/smtp;
	 439  
	 440  	# HTTP, King of Dependencies.
	 441  
	 442  	FMT
	 443  	< golang.org/x/net/http2/hpack
	 444  	< net/http/internal, net/http/internal/ascii, net/http/internal/testcert;
	 445  
	 446  	FMT, NET, container/list, encoding/binary, log
	 447  	< golang.org/x/text/transform
	 448  	< golang.org/x/text/unicode/norm
	 449  	< golang.org/x/text/unicode/bidi
	 450  	< golang.org/x/text/secure/bidirule
	 451  	< golang.org/x/net/idna
	 452  	< golang.org/x/net/http/httpguts, golang.org/x/net/http/httpproxy;
	 453  
	 454  	NET, crypto/tls
	 455  	< net/http/httptrace;
	 456  
	 457  	compress/gzip,
	 458  	golang.org/x/net/http/httpguts,
	 459  	golang.org/x/net/http/httpproxy,
	 460  	golang.org/x/net/http2/hpack,
	 461  	net/http/internal,
	 462  	net/http/internal/ascii,
	 463  	net/http/internal/testcert,
	 464  	net/http/httptrace,
	 465  	mime/multipart,
	 466  	log
	 467  	< net/http;
	 468  
	 469  	# HTTP-aware packages
	 470  
	 471  	encoding/json, net/http
	 472  	< expvar;
	 473  
	 474  	net/http, net/http/internal/ascii
	 475  	< net/http/cookiejar, net/http/httputil;
	 476  
	 477  	net/http, flag
	 478  	< net/http/httptest;
	 479  
	 480  	net/http, regexp
	 481  	< net/http/cgi
	 482  	< net/http/fcgi;
	 483  
	 484  	# Profiling
	 485  	FMT, compress/gzip, encoding/binary, text/tabwriter
	 486  	< runtime/pprof;
	 487  
	 488  	OS, compress/gzip, regexp
	 489  	< internal/profile;
	 490  
	 491  	html, internal/profile, net/http, runtime/pprof, runtime/trace
	 492  	< net/http/pprof;
	 493  
	 494  	# RPC
	 495  	encoding/gob, encoding/json, go/token, html/template, net/http
	 496  	< net/rpc
	 497  	< net/rpc/jsonrpc;
	 498  
	 499  	# System Information
	 500  	internal/cpu, sync
	 501  	< internal/sysinfo;
	 502  
	 503  	# Test-only
	 504  	log
	 505  	< testing/iotest
	 506  	< testing/fstest;
	 507  
	 508  	FMT, flag, math/rand
	 509  	< testing/quick;
	 510  
	 511  	FMT, flag, runtime/debug, runtime/trace, internal/sysinfo, math/rand
	 512  	< testing;
	 513  
	 514  	internal/testlog, runtime/pprof, regexp
	 515  	< testing/internal/testdeps;
	 516  
	 517  	OS, flag, testing, internal/cfg
	 518  	< internal/testenv;
	 519  
	 520  	OS, encoding/base64
	 521  	< internal/obscuretestdata;
	 522  
	 523  	CGO, OS, fmt
	 524  	< os/signal/internal/pty;
	 525  
	 526  	NET, testing, math/rand
	 527  	< golang.org/x/net/nettest;
	 528  
	 529  	FMT, container/heap, math/rand
	 530  	< internal/trace;
	 531  `
	 532  
	 533  // listStdPkgs returns the same list of packages as "go list std".
	 534  func listStdPkgs(goroot string) ([]string, error) {
	 535  	// Based on cmd/go's matchPackages function.
	 536  	var pkgs []string
	 537  
	 538  	src := filepath.Join(goroot, "src") + string(filepath.Separator)
	 539  	walkFn := func(path string, d fs.DirEntry, err error) error {
	 540  		if err != nil || !d.IsDir() || path == src {
	 541  			return nil
	 542  		}
	 543  
	 544  		base := filepath.Base(path)
	 545  		if strings.HasPrefix(base, ".") || strings.HasPrefix(base, "_") || base == "testdata" {
	 546  			return filepath.SkipDir
	 547  		}
	 548  
	 549  		name := filepath.ToSlash(path[len(src):])
	 550  		if name == "builtin" || name == "cmd" {
	 551  			return filepath.SkipDir
	 552  		}
	 553  
	 554  		pkgs = append(pkgs, strings.TrimPrefix(name, "vendor/"))
	 555  		return nil
	 556  	}
	 557  	if err := filepath.WalkDir(src, walkFn); err != nil {
	 558  		return nil, err
	 559  	}
	 560  	return pkgs, nil
	 561  }
	 562  
	 563  func TestDependencies(t *testing.T) {
	 564  	if !testenv.HasSrc() {
	 565  		// Tests run in a limited file system and we do not
	 566  		// provide access to every source file.
	 567  		t.Skipf("skipping on %s/%s, missing full GOROOT", runtime.GOOS, runtime.GOARCH)
	 568  	}
	 569  
	 570  	ctxt := Default
	 571  	all, err := listStdPkgs(ctxt.GOROOT)
	 572  	if err != nil {
	 573  		t.Fatal(err)
	 574  	}
	 575  	sort.Strings(all)
	 576  
	 577  	sawImport := map[string]map[string]bool{} // from package => to package => true
	 578  	policy := depsPolicy(t)
	 579  
	 580  	for _, pkg := range all {
	 581  		imports, err := findImports(pkg)
	 582  		if err != nil {
	 583  			t.Error(err)
	 584  			continue
	 585  		}
	 586  		if sawImport[pkg] == nil {
	 587  			sawImport[pkg] = map[string]bool{}
	 588  		}
	 589  		ok := policy[pkg]
	 590  		var bad []string
	 591  		for _, imp := range imports {
	 592  			sawImport[pkg][imp] = true
	 593  			if !ok[imp] {
	 594  				bad = append(bad, imp)
	 595  			}
	 596  		}
	 597  		if bad != nil {
	 598  			t.Errorf("unexpected dependency: %s imports %v", pkg, bad)
	 599  		}
	 600  	}
	 601  
	 602  	// depPath returns the path between the given from and to packages.
	 603  	// It returns the empty string if there's no dependency path.
	 604  	var depPath func(string, string) string
	 605  	depPath = func(from, to string) string {
	 606  		if sawImport[from][to] {
	 607  			return from + " => " + to
	 608  		}
	 609  		for pkg := range sawImport[from] {
	 610  			if p := depPath(pkg, to); p != "" {
	 611  				return from + " => " + p
	 612  			}
	 613  		}
	 614  		return ""
	 615  	}
	 616  }
	 617  
	 618  var buildIgnore = []byte("\n// +build ignore")
	 619  
	 620  func findImports(pkg string) ([]string, error) {
	 621  	vpkg := pkg
	 622  	if strings.HasPrefix(pkg, "golang.org") {
	 623  		vpkg = "vendor/" + pkg
	 624  	}
	 625  	dir := filepath.Join(Default.GOROOT, "src", vpkg)
	 626  	files, err := os.ReadDir(dir)
	 627  	if err != nil {
	 628  		return nil, err
	 629  	}
	 630  	var imports []string
	 631  	var haveImport = map[string]bool{}
	 632  	fset := token.NewFileSet()
	 633  	for _, file := range files {
	 634  		name := file.Name()
	 635  		if name == "slice_go14.go" || name == "slice_go18.go" {
	 636  			// These files are for compiler bootstrap with older versions of Go and not built in the standard build.
	 637  			continue
	 638  		}
	 639  		if !strings.HasSuffix(name, ".go") || strings.HasSuffix(name, "_test.go") {
	 640  			continue
	 641  		}
	 642  		info := fileInfo{
	 643  			name: filepath.Join(dir, name),
	 644  			fset: fset,
	 645  		}
	 646  		f, err := os.Open(info.name)
	 647  		if err != nil {
	 648  			return nil, err
	 649  		}
	 650  		err = readGoInfo(f, &info)
	 651  		f.Close()
	 652  		if err != nil {
	 653  			return nil, fmt.Errorf("reading %v: %v", name, err)
	 654  		}
	 655  		if bytes.Contains(info.header, buildIgnore) {
	 656  			continue
	 657  		}
	 658  		for _, imp := range info.imports {
	 659  			path := imp.path
	 660  			if !haveImport[path] {
	 661  				haveImport[path] = true
	 662  				imports = append(imports, path)
	 663  			}
	 664  		}
	 665  	}
	 666  	sort.Strings(imports)
	 667  	return imports, nil
	 668  }
	 669  
	 670  // depsPolicy returns a map m such that m[p][d] == true when p can import d.
	 671  func depsPolicy(t *testing.T) map[string]map[string]bool {
	 672  	allowed := map[string]map[string]bool{"NONE": {}}
	 673  	disallowed := [][2][]string{}
	 674  
	 675  	parseDepsRules(t, func(deps []string, op string, users []string) {
	 676  		if op == "!<" {
	 677  			disallowed = append(disallowed, [2][]string{deps, users})
	 678  			return
	 679  		}
	 680  		for _, u := range users {
	 681  			if allowed[u] != nil {
	 682  				t.Errorf("multiple deps lists for %s", u)
	 683  			}
	 684  			allowed[u] = make(map[string]bool)
	 685  			for _, d := range deps {
	 686  				if allowed[d] == nil {
	 687  					t.Errorf("use of %s before its deps list", d)
	 688  				}
	 689  				allowed[u][d] = true
	 690  			}
	 691  		}
	 692  	})
	 693  
	 694  	// Check for missing deps info.
	 695  	for _, deps := range allowed {
	 696  		for d := range deps {
	 697  			if allowed[d] == nil {
	 698  				t.Errorf("missing deps list for %s", d)
	 699  			}
	 700  		}
	 701  	}
	 702  
	 703  	// Complete transitive allowed deps.
	 704  	for k := range allowed {
	 705  		for i := range allowed {
	 706  			for j := range allowed {
	 707  				if i != k && k != j && allowed[i][k] && allowed[k][j] {
	 708  					if i == j {
	 709  						// Can only happen along with a "use of X before deps" error above,
	 710  						// but this error is more specific - it makes clear that reordering the
	 711  						// rules will not be enough to fix the problem.
	 712  						t.Errorf("deps policy cycle: %s < %s < %s", j, k, i)
	 713  					}
	 714  					allowed[i][j] = true
	 715  				}
	 716  			}
	 717  		}
	 718  	}
	 719  
	 720  	// Check negative assertions against completed allowed deps.
	 721  	for _, bad := range disallowed {
	 722  		deps, users := bad[0], bad[1]
	 723  		for _, d := range deps {
	 724  			for _, u := range users {
	 725  				if allowed[u][d] {
	 726  					t.Errorf("deps policy incorrect: assertion failed: %s !< %s", d, u)
	 727  				}
	 728  			}
	 729  		}
	 730  	}
	 731  
	 732  	if t.Failed() {
	 733  		t.FailNow()
	 734  	}
	 735  
	 736  	return allowed
	 737  }
	 738  
	 739  // parseDepsRules parses depsRules, calling save(deps, op, users)
	 740  // for each deps < users or deps !< users rule
	 741  // (op is "<" or "!<").
	 742  func parseDepsRules(t *testing.T, save func(deps []string, op string, users []string)) {
	 743  	p := &depsParser{t: t, lineno: 1, text: depsRules}
	 744  
	 745  	var prev []string
	 746  	var op string
	 747  	for {
	 748  		list, tok := p.nextList()
	 749  		if tok == "" {
	 750  			if prev == nil {
	 751  				break
	 752  			}
	 753  			p.syntaxError("unexpected EOF")
	 754  		}
	 755  		if prev != nil {
	 756  			save(prev, op, list)
	 757  		}
	 758  		prev = list
	 759  		if tok == ";" {
	 760  			prev = nil
	 761  			op = ""
	 762  			continue
	 763  		}
	 764  		if tok != "<" && tok != "!<" {
	 765  			p.syntaxError("missing <")
	 766  		}
	 767  		op = tok
	 768  	}
	 769  }
	 770  
	 771  // A depsParser parses the depsRules syntax described above.
	 772  type depsParser struct {
	 773  	t				*testing.T
	 774  	lineno	 int
	 775  	lastWord string
	 776  	text		 string
	 777  }
	 778  
	 779  // syntaxError reports a parsing error.
	 780  func (p *depsParser) syntaxError(msg string) {
	 781  	p.t.Fatalf("deps:%d: syntax error: %s near %s", p.lineno, msg, p.lastWord)
	 782  }
	 783  
	 784  // nextList parses and returns a comma-separated list of names.
	 785  func (p *depsParser) nextList() (list []string, token string) {
	 786  	for {
	 787  		tok := p.nextToken()
	 788  		switch tok {
	 789  		case "":
	 790  			if len(list) == 0 {
	 791  				return nil, ""
	 792  			}
	 793  			fallthrough
	 794  		case ",", "<", "!<", ";":
	 795  			p.syntaxError("bad list syntax")
	 796  		}
	 797  		list = append(list, tok)
	 798  
	 799  		tok = p.nextToken()
	 800  		if tok != "," {
	 801  			return list, tok
	 802  		}
	 803  	}
	 804  }
	 805  
	 806  // nextToken returns the next token in the deps rules,
	 807  // one of ";" "," "<" "!<" or a name.
	 808  func (p *depsParser) nextToken() string {
	 809  	for {
	 810  		if p.text == "" {
	 811  			return ""
	 812  		}
	 813  		switch p.text[0] {
	 814  		case ';', ',', '<':
	 815  			t := p.text[:1]
	 816  			p.text = p.text[1:]
	 817  			return t
	 818  
	 819  		case '!':
	 820  			if len(p.text) < 2 || p.text[1] != '<' {
	 821  				p.syntaxError("unexpected token !")
	 822  			}
	 823  			p.text = p.text[2:]
	 824  			return "!<"
	 825  
	 826  		case '#':
	 827  			i := strings.Index(p.text, "\n")
	 828  			if i < 0 {
	 829  				i = len(p.text)
	 830  			}
	 831  			p.text = p.text[i:]
	 832  			continue
	 833  
	 834  		case '\n':
	 835  			p.lineno++
	 836  			fallthrough
	 837  		case ' ', '\t':
	 838  			p.text = p.text[1:]
	 839  			continue
	 840  
	 841  		default:
	 842  			i := strings.IndexAny(p.text, "!;,<#\n \t")
	 843  			if i < 0 {
	 844  				i = len(p.text)
	 845  			}
	 846  			t := p.text[:i]
	 847  			p.text = p.text[i:]
	 848  			p.lastWord = t
	 849  			return t
	 850  		}
	 851  	}
	 852  }
	 853  
	 854  // TestStdlibLowercase tests that all standard library package names are
	 855  // lowercase. See Issue 40065.
	 856  func TestStdlibLowercase(t *testing.T) {
	 857  	if !testenv.HasSrc() {
	 858  		t.Skipf("skipping on %s/%s, missing full GOROOT", runtime.GOOS, runtime.GOARCH)
	 859  	}
	 860  
	 861  	ctxt := Default
	 862  	all, err := listStdPkgs(ctxt.GOROOT)
	 863  	if err != nil {
	 864  		t.Fatal(err)
	 865  	}
	 866  
	 867  	for _, pkgname := range all {
	 868  		if strings.ToLower(pkgname) != pkgname {
	 869  			t.Errorf("package %q should not use upper-case path", pkgname)
	 870  		}
	 871  	}
	 872  }
	 873  
	 874  // TestFindImports tests that findImports works.	See #43249.
	 875  func TestFindImports(t *testing.T) {
	 876  	imports, err := findImports("go/build")
	 877  	if err != nil {
	 878  		t.Fatal(err)
	 879  	}
	 880  	t.Logf("go/build imports %q", imports)
	 881  	want := []string{"bytes", "os", "path/filepath", "strings"}
	 882  wantLoop:
	 883  	for _, w := range want {
	 884  		for _, imp := range imports {
	 885  			if imp == w {
	 886  				continue wantLoop
	 887  			}
	 888  		}
	 889  		t.Errorf("expected to find %q in import list", w)
	 890  	}
	 891  }
	 892  

View as plain text