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