github.com/shijuvar/go@v0.0.0-20141209052335-e8f13700b70c/src/go/build/deps_test.go (about) 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 "runtime" 12 "sort" 13 "testing" 14 ) 15 16 // pkgDeps defines the expected dependencies between packages in 17 // the Go source tree. It is a statement of policy. 18 // Changes should not be made to this map without prior discussion. 19 // 20 // The map contains two kinds of entries: 21 // 1) Lower-case keys are standard import paths and list the 22 // allowed imports in that package. 23 // 2) Upper-case keys define aliases for package sets, which can then 24 // be used as dependencies by other rules. 25 // 26 // DO NOT CHANGE THIS DATA TO FIX BUILDS. 27 // 28 var pkgDeps = map[string][]string{ 29 // L0 is the lowest level, core, nearly unavoidable packages. 30 "errors": {}, 31 "io": {"errors", "sync"}, 32 "runtime": {"unsafe"}, 33 "sync": {"runtime", "sync/atomic", "unsafe"}, 34 "sync/atomic": {"unsafe"}, 35 "unsafe": {}, 36 37 "L0": { 38 "errors", 39 "io", 40 "runtime", 41 "sync", 42 "sync/atomic", 43 "unsafe", 44 }, 45 46 // L1 adds simple functions and strings processing, 47 // but not Unicode tables. 48 "math": {"unsafe"}, 49 "math/cmplx": {"math"}, 50 "math/rand": {"L0", "math"}, 51 "sort": {}, 52 "strconv": {"L0", "unicode/utf8", "math"}, 53 "unicode/utf16": {}, 54 "unicode/utf8": {}, 55 56 "L1": { 57 "L0", 58 "math", 59 "math/cmplx", 60 "math/rand", 61 "sort", 62 "strconv", 63 "unicode/utf16", 64 "unicode/utf8", 65 }, 66 67 // L2 adds Unicode and strings processing. 68 "bufio": {"L0", "unicode/utf8", "bytes"}, 69 "bytes": {"L0", "unicode", "unicode/utf8"}, 70 "path": {"L0", "unicode/utf8", "strings"}, 71 "strings": {"L0", "unicode", "unicode/utf8"}, 72 "unicode": {}, 73 74 "L2": { 75 "L1", 76 "bufio", 77 "bytes", 78 "path", 79 "strings", 80 "unicode", 81 }, 82 83 // L3 adds reflection and some basic utility packages 84 // and interface definitions, but nothing that makes 85 // system calls. 86 "crypto": {"L2", "hash"}, // interfaces 87 "crypto/cipher": {"L2", "crypto/subtle"}, // interfaces 88 "crypto/subtle": {}, 89 "encoding/base32": {"L2"}, 90 "encoding/base64": {"L2"}, 91 "encoding/binary": {"L2", "reflect"}, 92 "hash": {"L2"}, // interfaces 93 "hash/adler32": {"L2", "hash"}, 94 "hash/crc32": {"L2", "hash"}, 95 "hash/crc64": {"L2", "hash"}, 96 "hash/fnv": {"L2", "hash"}, 97 "image": {"L2", "image/color"}, // interfaces 98 "image/color": {"L2"}, // interfaces 99 "image/color/palette": {"L2", "image/color"}, 100 "reflect": {"L2"}, 101 102 "L3": { 103 "L2", 104 "crypto", 105 "crypto/cipher", 106 "crypto/subtle", 107 "encoding/base32", 108 "encoding/base64", 109 "encoding/binary", 110 "hash", 111 "hash/adler32", 112 "hash/crc32", 113 "hash/crc64", 114 "hash/fnv", 115 "image", 116 "image/color", 117 "image/color/palette", 118 "reflect", 119 }, 120 121 // End of linear dependency definitions. 122 123 // Operating system access. 124 "syscall": {"L0", "unicode/utf16"}, 125 "time": {"L0", "syscall"}, 126 "os": {"L1", "os", "syscall", "time"}, 127 "path/filepath": {"L2", "os", "syscall"}, 128 "io/ioutil": {"L2", "os", "path/filepath", "time"}, 129 "os/exec": {"L2", "os", "path/filepath", "syscall"}, 130 "os/signal": {"L2", "os", "syscall"}, 131 132 // OS enables basic operating system functionality, 133 // but not direct use of package syscall, nor os/signal. 134 "OS": { 135 "io/ioutil", 136 "os", 137 "os/exec", 138 "path/filepath", 139 "time", 140 }, 141 142 // Formatted I/O: few dependencies (L1) but we must add reflect. 143 "fmt": {"L1", "os", "reflect"}, 144 "log": {"L1", "os", "fmt", "time"}, 145 146 // Packages used by testing must be low-level (L2+fmt). 147 "regexp": {"L2", "regexp/syntax"}, 148 "regexp/syntax": {"L2"}, 149 "runtime/debug": {"L2", "fmt", "io/ioutil", "os", "time"}, 150 "runtime/pprof": {"L2", "fmt", "text/tabwriter"}, 151 "text/tabwriter": {"L2"}, 152 153 "testing": {"L2", "flag", "fmt", "os", "runtime/pprof", "time"}, 154 "testing/iotest": {"L2", "log"}, 155 "testing/quick": {"L2", "flag", "fmt", "reflect"}, 156 157 // L4 is defined as L3+fmt+log+time, because in general once 158 // you're using L3 packages, use of fmt, log, or time is not a big deal. 159 "L4": { 160 "L3", 161 "fmt", 162 "log", 163 "time", 164 }, 165 166 // Go parser. 167 "go/ast": {"L4", "OS", "go/scanner", "go/token"}, 168 "go/doc": {"L4", "go/ast", "go/token", "regexp", "text/template"}, 169 "go/parser": {"L4", "OS", "go/ast", "go/scanner", "go/token"}, 170 "go/printer": {"L4", "OS", "go/ast", "go/scanner", "go/token", "text/tabwriter"}, 171 "go/scanner": {"L4", "OS", "go/token"}, 172 "go/token": {"L4"}, 173 174 "GOPARSER": { 175 "go/ast", 176 "go/doc", 177 "go/parser", 178 "go/printer", 179 "go/scanner", 180 "go/token", 181 }, 182 183 // One of a kind. 184 "archive/tar": {"L4", "OS", "syscall"}, 185 "archive/zip": {"L4", "OS", "compress/flate"}, 186 "compress/bzip2": {"L4"}, 187 "compress/flate": {"L4"}, 188 "compress/gzip": {"L4", "compress/flate"}, 189 "compress/lzw": {"L4"}, 190 "compress/zlib": {"L4", "compress/flate"}, 191 "database/sql": {"L4", "container/list", "database/sql/driver"}, 192 "database/sql/driver": {"L4", "time"}, 193 "debug/dwarf": {"L4"}, 194 "debug/elf": {"L4", "OS", "debug/dwarf"}, 195 "debug/gosym": {"L4"}, 196 "debug/macho": {"L4", "OS", "debug/dwarf"}, 197 "debug/pe": {"L4", "OS", "debug/dwarf"}, 198 "encoding": {"L4"}, 199 "encoding/ascii85": {"L4"}, 200 "encoding/asn1": {"L4", "math/big"}, 201 "encoding/csv": {"L4"}, 202 "encoding/gob": {"L4", "OS", "encoding"}, 203 "encoding/hex": {"L4"}, 204 "encoding/json": {"L4", "encoding"}, 205 "encoding/pem": {"L4"}, 206 "encoding/xml": {"L4", "encoding"}, 207 "flag": {"L4", "OS"}, 208 "go/build": {"L4", "OS", "GOPARSER"}, 209 "html": {"L4"}, 210 "image/draw": {"L4"}, 211 "image/gif": {"L4", "compress/lzw", "image/color/palette", "image/draw"}, 212 "image/jpeg": {"L4"}, 213 "image/png": {"L4", "compress/zlib"}, 214 "index/suffixarray": {"L4", "regexp"}, 215 "math/big": {"L4"}, 216 "mime": {"L4", "OS", "syscall"}, 217 "net/url": {"L4"}, 218 "text/scanner": {"L4", "OS"}, 219 "text/template/parse": {"L4"}, 220 221 "html/template": { 222 "L4", "OS", "encoding/json", "html", "text/template", 223 "text/template/parse", 224 }, 225 "text/template": { 226 "L4", "OS", "net/url", "text/template/parse", 227 }, 228 229 // Cgo. 230 "runtime/cgo": {"L0", "C"}, 231 "CGO": {"C", "runtime/cgo"}, 232 233 // Fake entry to satisfy the pseudo-import "C" 234 // that shows up in programs that use cgo. 235 "C": {}, 236 237 // Plan 9 alone needs io/ioutil and os. 238 "os/user": {"L4", "CGO", "io/ioutil", "os", "syscall"}, 239 240 // Basic networking. 241 // Because net must be used by any package that wants to 242 // do networking portably, it must have a small dependency set: just L1+basic os. 243 "net": {"L1", "CGO", "os", "syscall", "time"}, 244 245 // NET enables use of basic network-related packages. 246 "NET": { 247 "net", 248 "mime", 249 "net/textproto", 250 "net/url", 251 }, 252 253 // Uses of networking. 254 "log/syslog": {"L4", "OS", "net"}, 255 "net/mail": {"L4", "NET", "OS"}, 256 "net/textproto": {"L4", "OS", "net"}, 257 258 // Core crypto. 259 "crypto/aes": {"L3"}, 260 "crypto/des": {"L3"}, 261 "crypto/hmac": {"L3"}, 262 "crypto/md5": {"L3"}, 263 "crypto/rc4": {"L3"}, 264 "crypto/sha1": {"L3"}, 265 "crypto/sha256": {"L3"}, 266 "crypto/sha512": {"L3"}, 267 268 "CRYPTO": { 269 "crypto/aes", 270 "crypto/des", 271 "crypto/hmac", 272 "crypto/md5", 273 "crypto/rc4", 274 "crypto/sha1", 275 "crypto/sha256", 276 "crypto/sha512", 277 }, 278 279 // Random byte, number generation. 280 // This would be part of core crypto except that it imports 281 // math/big, which imports fmt. 282 "crypto/rand": {"L4", "CRYPTO", "OS", "math/big", "syscall", "internal/syscall"}, 283 284 // Mathematical crypto: dependencies on fmt (L4) and math/big. 285 // We could avoid some of the fmt, but math/big imports fmt anyway. 286 "crypto/dsa": {"L4", "CRYPTO", "math/big"}, 287 "crypto/ecdsa": {"L4", "CRYPTO", "crypto/elliptic", "math/big", "encoding/asn1"}, 288 "crypto/elliptic": {"L4", "CRYPTO", "math/big"}, 289 "crypto/rsa": {"L4", "CRYPTO", "crypto/rand", "math/big"}, 290 291 "CRYPTO-MATH": { 292 "CRYPTO", 293 "crypto/dsa", 294 "crypto/ecdsa", 295 "crypto/elliptic", 296 "crypto/rand", 297 "crypto/rsa", 298 "encoding/asn1", 299 "math/big", 300 }, 301 302 // SSL/TLS. 303 "crypto/tls": { 304 "L4", "CRYPTO-MATH", "CGO", "OS", 305 "container/list", "crypto/x509", "encoding/pem", "net", "syscall", 306 }, 307 "crypto/x509": { 308 "L4", "CRYPTO-MATH", "OS", "CGO", 309 "crypto/x509/pkix", "encoding/pem", "encoding/hex", "net", "syscall", 310 }, 311 "crypto/x509/pkix": {"L4", "CRYPTO-MATH"}, 312 313 // Simple net+crypto-aware packages. 314 "mime/multipart": {"L4", "OS", "mime", "crypto/rand", "net/textproto"}, 315 "net/smtp": {"L4", "CRYPTO", "NET", "crypto/tls"}, 316 317 // HTTP, kingpin of dependencies. 318 "net/http": { 319 "L4", "NET", "OS", 320 "compress/gzip", "crypto/tls", "mime/multipart", "runtime/debug", 321 "net/http/internal", 322 }, 323 324 // HTTP-using packages. 325 "expvar": {"L4", "OS", "encoding/json", "net/http"}, 326 "net/http/cgi": {"L4", "NET", "OS", "crypto/tls", "net/http", "regexp"}, 327 "net/http/fcgi": {"L4", "NET", "OS", "net/http", "net/http/cgi"}, 328 "net/http/httptest": {"L4", "NET", "OS", "crypto/tls", "flag", "net/http"}, 329 "net/http/httputil": {"L4", "NET", "OS", "net/http", "net/http/internal"}, 330 "net/http/pprof": {"L4", "OS", "html/template", "net/http", "runtime/pprof"}, 331 "net/rpc": {"L4", "NET", "encoding/gob", "html/template", "net/http"}, 332 "net/rpc/jsonrpc": {"L4", "NET", "encoding/json", "net/rpc"}, 333 } 334 335 // isMacro reports whether p is a package dependency macro 336 // (uppercase name). 337 func isMacro(p string) bool { 338 return 'A' <= p[0] && p[0] <= 'Z' 339 } 340 341 func allowed(pkg string) map[string]bool { 342 m := map[string]bool{} 343 var allow func(string) 344 allow = func(p string) { 345 if m[p] { 346 return 347 } 348 m[p] = true // set even for macros, to avoid loop on cycle 349 350 // Upper-case names are macro-expanded. 351 if isMacro(p) { 352 for _, pp := range pkgDeps[p] { 353 allow(pp) 354 } 355 } 356 } 357 for _, pp := range pkgDeps[pkg] { 358 allow(pp) 359 } 360 return m 361 } 362 363 var bools = []bool{false, true} 364 var geese = []string{"android", "darwin", "dragonfly", "freebsd", "linux", "nacl", "netbsd", "openbsd", "plan9", "solaris", "windows"} 365 var goarches = []string{"386", "amd64", "arm"} 366 367 type osPkg struct { 368 goos, pkg string 369 } 370 371 // allowedErrors are the operating systems and packages known to contain errors 372 // (currently just "no Go source files") 373 var allowedErrors = map[osPkg]bool{ 374 osPkg{"windows", "log/syslog"}: true, 375 osPkg{"plan9", "log/syslog"}: true, 376 } 377 378 func TestDependencies(t *testing.T) { 379 if runtime.GOOS == "nacl" { 380 // NaCl tests run in a limited file system and we do not 381 // provide access to every source file. 382 t.Skip("skipping on NaCl") 383 } 384 var all []string 385 386 for k := range pkgDeps { 387 all = append(all, k) 388 } 389 sort.Strings(all) 390 391 ctxt := Default 392 test := func(mustImport bool) { 393 for _, pkg := range all { 394 if isMacro(pkg) { 395 continue 396 } 397 if pkg == "runtime/cgo" && !ctxt.CgoEnabled { 398 continue 399 } 400 p, err := ctxt.Import(pkg, "", 0) 401 if err != nil { 402 if allowedErrors[osPkg{ctxt.GOOS, pkg}] { 403 continue 404 } 405 if !ctxt.CgoEnabled && pkg == "runtime/cgo" { 406 continue 407 } 408 // Some of the combinations we try might not 409 // be reasonable (like arm,plan9,cgo), so ignore 410 // errors for the auto-generated combinations. 411 if !mustImport { 412 continue 413 } 414 t.Errorf("%s/%s/cgo=%v %v", ctxt.GOOS, ctxt.GOARCH, ctxt.CgoEnabled, err) 415 continue 416 } 417 ok := allowed(pkg) 418 var bad []string 419 for _, imp := range p.Imports { 420 if !ok[imp] { 421 bad = append(bad, imp) 422 } 423 } 424 if bad != nil { 425 t.Errorf("%s/%s/cgo=%v unexpected dependency: %s imports %v", ctxt.GOOS, ctxt.GOARCH, ctxt.CgoEnabled, pkg, bad) 426 } 427 } 428 } 429 test(true) 430 431 if testing.Short() { 432 t.Logf("skipping other systems") 433 return 434 } 435 436 for _, ctxt.GOOS = range geese { 437 for _, ctxt.GOARCH = range goarches { 438 for _, ctxt.CgoEnabled = range bools { 439 test(false) 440 } 441 } 442 } 443 }