golang.org/x/build@v0.0.0-20240506185731-218518f32b70/dashboard/builders_test.go (about) 1 // Copyright 2015 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 package dashboard 6 7 import ( 8 "bytes" 9 "errors" 10 "fmt" 11 "os" 12 "os/exec" 13 "regexp" 14 "sort" 15 "strings" 16 "testing" 17 "time" 18 ) 19 20 func TestOSARCHAccessors(t *testing.T) { 21 valid := func(s string) bool { return s != "" && !strings.Contains(s, "-") } 22 for _, conf := range Builders { 23 os := conf.GOOS() 24 arch := conf.GOARCH() 25 osArch := os + "-" + arch 26 if !valid(os) || !valid(arch) || !(conf.Name == osArch || strings.HasPrefix(conf.Name, osArch+"-")) { 27 t.Errorf("OS+ARCH(%q) = %q, %q; invalid", conf.Name, os, arch) 28 } 29 } 30 } 31 32 func TestDistTestsExecTimeout(t *testing.T) { 33 tests := []struct { 34 c *BuildConfig 35 want time.Duration 36 }{ 37 { 38 &BuildConfig{ 39 env: []string{}, 40 TestHostConf: &HostConfig{}, 41 }, 42 20 * time.Minute, 43 }, 44 { 45 &BuildConfig{ 46 env: []string{"GO_TEST_TIMEOUT_SCALE=2"}, 47 TestHostConf: &HostConfig{}, 48 }, 49 40 * time.Minute, 50 }, 51 { 52 &BuildConfig{ 53 env: []string{}, 54 TestHostConf: &HostConfig{ 55 env: []string{"GO_TEST_TIMEOUT_SCALE=3"}, 56 }, 57 }, 58 60 * time.Minute, 59 }, 60 // BuildConfig's env takes precedence: 61 { 62 &BuildConfig{ 63 env: []string{"GO_TEST_TIMEOUT_SCALE=2"}, 64 TestHostConf: &HostConfig{ 65 env: []string{"GO_TEST_TIMEOUT_SCALE=3"}, 66 }, 67 }, 68 40 * time.Minute, 69 }, 70 } 71 for i, tt := range tests { 72 got := tt.c.DistTestsExecTimeout(nil) 73 if got != tt.want { 74 t.Errorf("%d. got %v; want %v", i, got, tt.want) 75 } 76 } 77 } 78 79 // TestTrybots tests that a given repo & its branch yields the provided complete 80 // set of builders. See also: TestPostSubmit, which tests only post-submit 81 // builders, and TestBuilderConfig, which tests both trybots and post-submit 82 // builders, both at arbitrary branches. 83 func TestTrybots(t *testing.T) { 84 tests := []struct { 85 repo string // "go", "net", etc 86 branch string // of repo 87 want []string 88 }{ 89 { 90 repo: "go", 91 branch: "master", 92 want: []string{ 93 "freebsd-amd64-12_3", 94 "linux-386", 95 "linux-amd64", 96 "linux-amd64-boringcrypto", 97 "linux-amd64-newinliner", 98 "linux-amd64-race", 99 "linux-arm64", 100 "openbsd-amd64-72", 101 "windows-386-2016", 102 "windows-amd64-2016", 103 104 "misc-compile-windows-arm", 105 "misc-compile-windows-arm64", 106 "misc-compile-darwin-amd64", 107 "misc-compile-darwin-arm64", 108 "misc-compile-linux-mips", 109 "misc-compile-linux-mips64", 110 "misc-compile-linux-mipsle", 111 "misc-compile-linux-mips64le", 112 "misc-compile-linux-ppc64", 113 "misc-compile-linux-ppc64le", 114 "misc-compile-aix-ppc64", 115 "misc-compile-freebsd-386", 116 "misc-compile-freebsd-arm", 117 "misc-compile-freebsd-arm64", 118 "misc-compile-freebsd-riscv64", 119 "misc-compile-netbsd-386", 120 "misc-compile-netbsd-amd64", 121 "misc-compile-netbsd-arm", 122 "misc-compile-netbsd-arm64", 123 "misc-compile-openbsd-386", 124 "misc-compile-openbsd-arm", 125 "misc-compile-openbsd-arm64", 126 "misc-compile-openbsd-ppc64-go1.22", 127 "misc-compile-openbsd-riscv64-go1.23", 128 "misc-compile-plan9-386", 129 "misc-compile-plan9-amd64", 130 "misc-compile-plan9-arm", 131 "misc-compile-solaris-amd64", 132 "misc-compile-illumos-amd64", 133 "misc-compile-dragonfly-amd64", 134 "misc-compile-linux-loong64", 135 "misc-compile-linux-riscv64", 136 "misc-compile-linux-s390x", 137 "misc-compile-linux-arm", 138 "misc-compile-linux-arm-arm5", 139 }, 140 }, 141 { 142 repo: "go", 143 branch: "release-branch.go1.22", 144 want: []string{ 145 "freebsd-amd64-12_3", 146 "linux-386", 147 "linux-amd64", 148 "linux-amd64-boringcrypto", 149 "linux-amd64-race", 150 "linux-arm64", 151 "openbsd-amd64-72", 152 "windows-386-2016", 153 "windows-amd64-2016", 154 155 "misc-compile-windows-arm", 156 "misc-compile-windows-arm64", 157 "misc-compile-darwin-amd64", 158 "misc-compile-darwin-arm64", 159 "misc-compile-linux-mips", 160 "misc-compile-linux-mips64", 161 "misc-compile-linux-mipsle", 162 "misc-compile-linux-mips64le", 163 "misc-compile-linux-ppc64", 164 "misc-compile-linux-ppc64le", 165 "misc-compile-aix-ppc64", 166 "misc-compile-freebsd-386", 167 "misc-compile-freebsd-arm", 168 "misc-compile-freebsd-arm64", 169 "misc-compile-freebsd-riscv64", 170 "misc-compile-netbsd-386", 171 "misc-compile-netbsd-amd64", 172 "misc-compile-netbsd-arm", 173 "misc-compile-netbsd-arm64", 174 "misc-compile-openbsd-386", 175 "misc-compile-openbsd-arm", 176 "misc-compile-openbsd-arm64", 177 "misc-compile-openbsd-ppc64-go1.22", // New to Go 1.22. 178 "misc-compile-plan9-386", 179 "misc-compile-plan9-amd64", 180 "misc-compile-plan9-arm", 181 "misc-compile-solaris-amd64", 182 "misc-compile-illumos-amd64", 183 "misc-compile-dragonfly-amd64", 184 "misc-compile-linux-loong64", 185 "misc-compile-linux-riscv64", 186 "misc-compile-linux-s390x", 187 "misc-compile-linux-arm", 188 "misc-compile-linux-arm-arm5", 189 190 // Include longtest builders on Go repo release branches. See issue 37827. 191 "linux-386-longtest", 192 "linux-amd64-longtest", 193 "linux-arm64-longtest", 194 "windows-amd64-longtest", 195 }, 196 }, 197 { 198 repo: "go", 199 branch: "release-branch.go1.21", 200 want: []string{ 201 "freebsd-amd64-12_3", 202 "linux-386", 203 "linux-amd64", 204 "linux-amd64-boringcrypto", 205 "linux-amd64-race", 206 "linux-arm64", 207 "openbsd-amd64-72", 208 "windows-386-2016", 209 "windows-amd64-2016", 210 211 "misc-compile-windows-arm", 212 "misc-compile-windows-arm64", 213 "misc-compile-darwin-amd64", 214 "misc-compile-darwin-arm64", 215 "misc-compile-linux-mips", 216 "misc-compile-linux-mips64", 217 "misc-compile-linux-mipsle", 218 "misc-compile-linux-mips64le", 219 "misc-compile-linux-ppc64", 220 "misc-compile-linux-ppc64le", 221 "misc-compile-aix-ppc64", 222 "misc-compile-freebsd-386", 223 "misc-compile-freebsd-arm", 224 "misc-compile-freebsd-arm64", 225 "misc-compile-freebsd-riscv64", 226 "misc-compile-netbsd-386", 227 "misc-compile-netbsd-amd64", 228 "misc-compile-netbsd-arm", 229 "misc-compile-netbsd-arm64", 230 "misc-compile-openbsd-386", 231 "misc-compile-openbsd-arm", 232 "misc-compile-openbsd-arm64", 233 "misc-compile-plan9-386", 234 "misc-compile-plan9-amd64", 235 "misc-compile-plan9-arm", 236 "misc-compile-solaris-amd64", 237 "misc-compile-illumos-amd64", 238 "misc-compile-dragonfly-amd64", 239 "misc-compile-linux-loong64", 240 "misc-compile-linux-riscv64", 241 "misc-compile-linux-s390x", 242 "misc-compile-linux-arm", 243 "misc-compile-linux-arm-arm5", 244 245 // Include longtest builders on Go repo release branches. See issue 37827. 246 "linux-386-longtest", 247 "linux-amd64-longtest", 248 "linux-arm64-longtest", 249 "windows-amd64-longtest", 250 }, 251 }, 252 { 253 repo: "mobile", 254 branch: "master", 255 want: []string{ 256 "android-amd64-emu", 257 "linux-amd64-androidemu", 258 "linux-amd64", 259 "linux-amd64-race", 260 }, 261 }, 262 { 263 repo: "sys", 264 branch: "master", 265 want: []string{ 266 "freebsd-386-13_0", 267 "freebsd-amd64-12_3", 268 "freebsd-amd64-13_0", 269 "linux-386", 270 "linux-amd64", 271 "linux-amd64-boringcrypto", // GoDeps will exclude, but not in test 272 "linux-amd64-race", 273 "linux-arm64", 274 "netbsd-amd64-9_3", 275 "openbsd-386-72", 276 "openbsd-amd64-72", 277 "windows-386-2016", 278 "windows-amd64-2016", 279 280 "misc-compile-windows-arm", 281 "misc-compile-windows-arm64", 282 "misc-compile-darwin-amd64", 283 "misc-compile-darwin-arm64", 284 "misc-compile-linux-mips", 285 "misc-compile-linux-mips64", 286 "misc-compile-linux-mipsle", 287 "misc-compile-linux-mips64le", 288 "misc-compile-linux-ppc64", 289 "misc-compile-linux-ppc64le", 290 "misc-compile-aix-ppc64", 291 "misc-compile-freebsd-386", 292 "misc-compile-freebsd-arm", 293 "misc-compile-freebsd-arm64", 294 "misc-compile-freebsd-riscv64", 295 "misc-compile-netbsd-386", 296 "misc-compile-netbsd-amd64", 297 "misc-compile-netbsd-arm", 298 "misc-compile-netbsd-arm64", 299 "misc-compile-openbsd-386", 300 "misc-compile-openbsd-arm", 301 "misc-compile-openbsd-arm64", 302 "misc-compile-openbsd-ppc64-go1.22", 303 "misc-compile-openbsd-riscv64-go1.23", 304 "misc-compile-plan9-386", 305 "misc-compile-plan9-amd64", 306 "misc-compile-plan9-arm", 307 "misc-compile-solaris-amd64", 308 "misc-compile-illumos-amd64", 309 "misc-compile-dragonfly-amd64", 310 "misc-compile-linux-loong64", 311 "misc-compile-linux-riscv64", 312 "misc-compile-linux-s390x", 313 "misc-compile-linux-arm", 314 "misc-compile-linux-arm-arm5", 315 }, 316 }, 317 { 318 repo: "exp", 319 branch: "master", 320 want: []string{ 321 "linux-amd64", 322 "linux-amd64-race", 323 "windows-amd64-2016", 324 }, 325 }, 326 { 327 repo: "vulndb", 328 branch: "master", 329 want: []string{ 330 "linux-amd64", 331 "linux-amd64-race", 332 }, 333 }, 334 { 335 repo: "website", 336 branch: "master", 337 want: []string{ 338 "linux-amd64", 339 "linux-amd64-race", 340 }, 341 }, 342 } 343 for i, tt := range tests { 344 if tt.branch == "" || tt.repo == "" { 345 t.Errorf("incomplete test entry %d", i) 346 return 347 } 348 t.Run(fmt.Sprintf("%s/%s", tt.repo, tt.branch), func(t *testing.T) { 349 goBranch := tt.branch // hard-code the common case for now 350 got := TryBuildersForProject(tt.repo, tt.branch, goBranch) 351 checkBuildersForProject(t, got, tt.want) 352 }) 353 } 354 } 355 356 func checkBuildersForProject(t *testing.T, gotBuilders []*BuildConfig, want []string) { 357 t.Helper() 358 359 var got []string 360 for _, bc := range gotBuilders { 361 got = append(got, bc.Name) 362 } 363 m := map[string]bool{} 364 for _, b := range want { 365 m[b] = true 366 } 367 for _, b := range got { 368 if _, ok := m[b]; !ok { 369 t.Errorf("got unexpected %q", b) 370 } 371 delete(m, b) 372 } 373 for b := range m { 374 t.Errorf("missing expected %q", b) 375 } 376 } 377 378 // TestPostSubmit tests that a given repo & its branch yields the provided 379 // complete set of post-submit builders. See also: TestTrybots, which tests only 380 // trybots, and TestBuilderConfig, which tests both trybots and post-submit 381 // builders, both at arbitrary branches. 382 func TestPostSubmit(t *testing.T) { 383 tests := []struct { 384 repo string // "go", "net", etc 385 branch string // of repo 386 want []string 387 }{ 388 { 389 repo: "vulndb", 390 branch: "master", 391 want: []string{ 392 "linux-amd64", 393 "linux-amd64-longtest", 394 "linux-amd64-race", 395 "linux-amd64-longtest-race", 396 }, 397 }, 398 { 399 repo: "website", 400 branch: "master", 401 want: []string{ 402 "linux-amd64", 403 "linux-amd64-longtest", 404 "linux-amd64-race", 405 "linux-amd64-longtest-race", 406 }, 407 }, 408 } 409 for i, tt := range tests { 410 if tt.branch == "" || tt.repo == "" { 411 t.Fatalf("incomplete test entry %d", i) 412 } 413 t.Run(fmt.Sprintf("%s/%s", tt.repo, tt.branch), func(t *testing.T) { 414 goBranch := tt.branch // hard-code the common case for now 415 got := buildersForProject(tt.repo, tt.branch, goBranch, (*BuildConfig).BuildsRepoPostSubmit) 416 checkBuildersForProject(t, got, tt.want) 417 }) 418 } 419 } 420 421 // TestBuilderConfig tests whether a given builder and repo at different branches is 422 // completely disabled ("none"), 423 // a TryBot and a post-submit builder ("both"), or 424 // a post-submit only builder ("onlyPost"). 425 func TestBuilderConfig(t *testing.T) { 426 // want is a bitmask of 4 different things to assert are wanted: 427 // - being a post-submit builder 428 // - NOT being a post-submit builder 429 // - being a trybot builder 430 // - NOT being a post-submit builder 431 // Note: a builder cannot be configured as a TryBot without also being a post-submit builder. 432 type want uint8 433 const ( 434 isTrybot want = 1 << iota 435 notTrybot 436 isBuilder // post-submit 437 notBuilder // not post-submit 438 439 // Available combinations: 440 none = notTrybot + notBuilder 441 both = isTrybot + isBuilder 442 onlyPost = notTrybot + isBuilder 443 ) 444 445 type builderAndRepo struct { 446 testName string 447 builder string 448 repo string 449 branch string 450 goBranch string 451 } 452 // builder may end in "@go1.N" or "@1.N" (as alias for "@release-branch.go1.N") or "@branch-name". 453 // repo (other than "go") may end in "@go1.N" or "@1.N" (as alias for "@release-branch.go1.N"). 454 b := func(builder, repo string) builderAndRepo { 455 br := builderAndRepo{ 456 testName: builder + "," + repo, 457 builder: builder, 458 goBranch: "master", 459 repo: repo, 460 branch: "master", 461 } 462 if strings.Contains(builder, "@") { 463 f := strings.SplitN(builder, "@", 2) 464 br.builder = f[0] 465 br.goBranch = f[1] 466 } 467 if strings.Contains(repo, "@") { 468 f := strings.SplitN(repo, "@", 2) 469 br.repo = f[0] 470 br.branch = f[1] 471 if br.repo == "go" { 472 panic(fmt.Errorf(`b(%q, %q): for "go" repo, must use the @%s suffix on the builder, not on the repo`, builder, repo, br.branch)) 473 } 474 } 475 expandBranch := func(s *string) { 476 if strings.HasPrefix(*s, "go1.") { 477 *s = "release-branch." + *s 478 } else if strings.HasPrefix(*s, "1.") { 479 *s = "release-branch.go" + *s 480 } 481 } 482 expandBranch(&br.branch) 483 expandBranch(&br.goBranch) 484 if br.repo == "go" { 485 br.branch = br.goBranch 486 } 487 return br 488 } 489 tests := []struct { 490 br builderAndRepo 491 want want // none, both, or onlyPost. 492 }{ 493 {b("linux-amd64", "go"), both}, 494 {b("linux-amd64", "net"), both}, 495 {b("linux-amd64", "sys"), both}, 496 {b("linux-amd64", "website"), both}, 497 498 // Don't test all subrepos on all the builders. 499 {b("linux-amd64-ssacheck", "net"), none}, 500 {b("linux-amd64-ssacheck@go1.99", "net"), none}, 501 {b("linux-386-softfloat", "crypto"), onlyPost}, 502 {b("linux-386-softfloat@go1.99", "crypto"), onlyPost}, 503 504 {b("android-amd64-emu", "go"), onlyPost}, 505 {b("android-amd64-emu", "mobile"), both}, 506 {b("android-amd64-emu", "crypto"), onlyPost}, 507 {b("android-amd64-emu", "net"), onlyPost}, 508 {b("android-amd64-emu", "sync"), onlyPost}, 509 {b("android-amd64-emu", "sys"), onlyPost}, 510 {b("android-amd64-emu", "text"), onlyPost}, 511 {b("android-amd64-emu", "time"), onlyPost}, 512 {b("android-amd64-emu", "tools"), onlyPost}, 513 {b("android-amd64-emu", "website"), none}, 514 515 {b("android-386-emu", "go"), onlyPost}, 516 {b("android-386-emu", "mobile"), onlyPost}, 517 {b("android-386-emu", "crypto"), onlyPost}, 518 519 {b("linux-amd64", "net"), both}, 520 521 {b("linux-loong64-3a5000", "go"), onlyPost}, 522 {b("linux-loong64-3a5000@go1.99", "go"), onlyPost}, 523 {b("linux-loong64-3a5000", "sys"), onlyPost}, 524 {b("linux-loong64-3a5000@go1.99", "sys"), onlyPost}, 525 {b("linux-loong64-3a5000", "net"), onlyPost}, 526 527 // OpenBSD 7.2. 528 {b("openbsd-amd64-72", "go"), both}, 529 {b("openbsd-amd64-72@go1.99", "go"), both}, 530 531 // FreeBSD 13.0 532 {b("freebsd-amd64-13_0", "go"), onlyPost}, 533 {b("freebsd-amd64-13_0", "net"), onlyPost}, 534 {b("freebsd-amd64-13_0", "mobile"), none}, 535 {b("freebsd-386-13_0", "go"), onlyPost}, 536 {b("freebsd-386-13_0", "net"), onlyPost}, 537 {b("freebsd-386-13_0", "mobile"), none}, 538 539 // FreeBSD 12.3 540 {b("freebsd-amd64-12_3", "go"), both}, 541 {b("freebsd-amd64-12_3", "net"), both}, 542 {b("freebsd-amd64-12_3", "mobile"), none}, 543 {b("freebsd-386-12_3", "go"), onlyPost}, 544 {b("freebsd-386-12_3", "net"), onlyPost}, 545 {b("freebsd-386-12_3", "mobile"), none}, 546 547 // NetBSD 548 {b("netbsd-amd64-9_3", "go"), onlyPost}, 549 {b("netbsd-amd64-9_3", "net"), onlyPost}, 550 {b("netbsd-amd64-9_3", "sys"), both}, 551 {b("netbsd-386-9_3", "go"), onlyPost}, 552 {b("netbsd-386-9_3", "net"), onlyPost}, 553 554 // AIX 555 {b("aix-ppc64", "go"), onlyPost}, 556 {b("aix-ppc64", "net"), onlyPost}, 557 {b("aix-ppc64", "mobile"), none}, 558 {b("aix-ppc64", "exp"), none}, 559 {b("aix-ppc64", "term"), onlyPost}, 560 561 {b("linux-amd64-nocgo", "mobile"), none}, 562 563 // Virtual mobiledevices 564 {b("ios-arm64-corellium", "go"), onlyPost}, 565 {b("android-arm64-corellium", "go"), onlyPost}, 566 {b("android-arm-corellium", "go"), onlyPost}, 567 568 // Mobile builders that run with GOOS=linux/ios and have 569 // a device attached. 570 {b("linux-amd64-androidemu", "mobile"), both}, 571 572 // The Android emulator builders can test all repos. 573 {b("android-amd64-emu", "mobile"), both}, 574 {b("android-386-emu", "mobile"), onlyPost}, 575 {b("android-amd64-emu", "net"), onlyPost}, 576 {b("android-386-emu", "net"), onlyPost}, 577 {b("android-amd64-emu", "go"), onlyPost}, 578 {b("android-386-emu", "go"), onlyPost}, 579 580 // Builders for js/wasm are fully ported to LUCI and stopped in the coordinator. 581 {b("js-wasm-node18", "go"), none}, 582 {b("js-wasm-node18@go1.21", "go"), none}, 583 {b("js-wasm-node18@go1.20", "go"), none}, 584 {b("js-wasm-node18", "arch"), none}, 585 {b("js-wasm-node18", "crypto"), none}, 586 {b("js-wasm-node18", "sys"), none}, 587 {b("js-wasm-node18", "net"), none}, 588 {b("js-wasm-node18", "benchmarks"), none}, 589 {b("js-wasm-node18", "debug"), none}, 590 {b("js-wasm-node18", "mobile"), none}, 591 {b("js-wasm-node18", "perf"), none}, 592 {b("js-wasm-node18", "talks"), none}, 593 {b("js-wasm-node18", "tools"), none}, 594 {b("js-wasm-node18", "tour"), none}, 595 {b("js-wasm-node18", "website"), none}, 596 597 // Builders for wasip1-wasm are fully ported to LUCI and stopped in the coordinator. 598 {b("wasip1-wasm-wazero", "go"), none}, 599 {b("wasip1-wasm-wazero@go1.21", "go"), none}, 600 {b("wasip1-wasm-wazero@go1.20", "go"), none}, 601 {b("wasip1-wasm-wasmtime", "go"), none}, 602 {b("wasip1-wasm-wasmtime@go1.21", "go"), none}, 603 {b("wasip1-wasm-wasmtime@go1.20", "go"), none}, 604 {b("wasip1-wasm-wasmer", "go"), none}, 605 {b("wasip1-wasm-wasmer@go1.21", "go"), none}, 606 {b("wasip1-wasm-wasmer@go1.20", "go"), none}, 607 {b("wasip1-wasm-wasmedge", "go"), none}, 608 {b("wasip1-wasm-wasmedge@go1.21", "go"), none}, 609 {b("wasip1-wasm-wasmedge@go1.20", "go"), none}, 610 {b("wasip1-wasm-wazero", "arch"), none}, 611 {b("wasip1-wasm-wazero", "crypto"), none}, 612 {b("wasip1-wasm-wazero", "sys"), none}, 613 {b("wasip1-wasm-wazero", "net"), none}, 614 {b("wasip1-wasm-wazero", "benchmarks"), none}, 615 {b("wasip1-wasm-wazero", "debug"), none}, 616 {b("wasip1-wasm-wazero", "mobile"), none}, 617 {b("wasip1-wasm-wazero", "perf"), none}, 618 {b("wasip1-wasm-wazero", "talks"), none}, 619 {b("wasip1-wasm-wazero", "tools"), none}, 620 {b("wasip1-wasm-wazero", "tour"), none}, 621 {b("wasip1-wasm-wazero", "website"), none}, 622 {b("wasip1-wasm-wasmtime", "arch"), none}, 623 {b("wasip1-wasm-wasmtime", "crypto"), none}, 624 {b("wasip1-wasm-wasmtime", "sys"), none}, 625 {b("wasip1-wasm-wasmtime", "net"), none}, 626 {b("wasip1-wasm-wasmtime", "benchmarks"), none}, 627 {b("wasip1-wasm-wasmtime", "debug"), none}, 628 {b("wasip1-wasm-wasmtime", "mobile"), none}, 629 {b("wasip1-wasm-wasmtime", "perf"), none}, 630 {b("wasip1-wasm-wasmtime", "talks"), none}, 631 {b("wasip1-wasm-wasmtime", "tools"), none}, 632 {b("wasip1-wasm-wasmtime", "tour"), none}, 633 {b("wasip1-wasm-wasmtime", "website"), none}, 634 {b("wasip1-wasm-wasmer", "arch"), none}, 635 {b("wasip1-wasm-wasmer", "crypto"), none}, 636 {b("wasip1-wasm-wasmer", "sys"), none}, 637 {b("wasip1-wasm-wasmer", "net"), none}, 638 {b("wasip1-wasm-wasmer", "benchmarks"), none}, 639 {b("wasip1-wasm-wasmer", "debug"), none}, 640 {b("wasip1-wasm-wasmer", "mobile"), none}, 641 {b("wasip1-wasm-wasmer", "perf"), none}, 642 {b("wasip1-wasm-wasmer", "talks"), none}, 643 {b("wasip1-wasm-wasmer", "tools"), none}, 644 {b("wasip1-wasm-wasmer", "tour"), none}, 645 {b("wasip1-wasm-wasmer", "website"), none}, 646 {b("wasip1-wasm-wasmedge", "arch"), none}, 647 {b("wasip1-wasm-wasmedge", "crypto"), none}, 648 {b("wasip1-wasm-wasmedge", "sys"), none}, 649 {b("wasip1-wasm-wasmedge", "net"), none}, 650 {b("wasip1-wasm-wasmedge", "benchmarks"), none}, 651 {b("wasip1-wasm-wasmedge", "debug"), none}, 652 {b("wasip1-wasm-wasmedge", "mobile"), none}, 653 {b("wasip1-wasm-wasmedge", "perf"), none}, 654 {b("wasip1-wasm-wasmedge", "talks"), none}, 655 {b("wasip1-wasm-wasmedge", "tools"), none}, 656 {b("wasip1-wasm-wasmedge", "tour"), none}, 657 {b("wasip1-wasm-wasmedge", "website"), none}, 658 659 // Race builders. Linux for all, GCE builders for 660 // post-submit, and only post-submit for "go" for 661 // Darwin (limited resources). 662 {b("linux-amd64-race", "go"), both}, 663 {b("linux-amd64-race", "net"), both}, 664 {b("windows-amd64-race", "go"), onlyPost}, 665 {b("windows-amd64-race", "net"), onlyPost}, 666 {b("freebsd-amd64-race", "go"), onlyPost}, 667 {b("freebsd-amd64-race", "net"), onlyPost}, 668 {b("darwin-amd64-race", "go"), onlyPost}, 669 {b("darwin-amd64-race", "net"), none}, 670 671 // Long test. 672 {b("linux-amd64-longtest", "go"), onlyPost}, 673 {b("linux-amd64-longtest", "net"), onlyPost}, 674 {b("linux-amd64-longtest@go1.99", "go"), both}, 675 {b("linux-amd64-longtest@go1.99", "net"), none}, 676 {b("darwin-amd64-longtest", "go"), onlyPost}, 677 {b("darwin-amd64-longtest", "net"), onlyPost}, 678 {b("darwin-amd64-longtest@go1.99", "go"), onlyPost}, 679 {b("darwin-amd64-longtest@go1.99", "net"), none}, 680 {b("windows-amd64-longtest", "go"), onlyPost}, 681 {b("windows-amd64-longtest@go1.99", "go"), both}, 682 {b("windows-amd64-longtest", "net"), onlyPost}, 683 {b("windows-amd64-longtest", "exp"), onlyPost}, 684 {b("windows-amd64-longtest", "mobile"), none}, 685 {b("linux-386-longtest", "go"), onlyPost}, 686 {b("linux-386-longtest", "net"), onlyPost}, 687 {b("linux-386-longtest", "exp"), none}, 688 {b("linux-386-longtest", "mobile"), none}, 689 690 // Experimental exp repo runs in very few places. 691 {b("linux-amd64", "exp"), both}, 692 {b("linux-amd64-race", "exp"), both}, 693 {b("linux-amd64-longtest", "exp"), onlyPost}, 694 {b("windows-386-2016", "exp"), none}, 695 {b("windows-amd64-2016", "exp"), both}, 696 {b("darwin-amd64-10_15", "exp"), none}, 697 {b("darwin-amd64-11_0", "exp"), onlyPost}, 698 // ... but not on most others: 699 {b("freebsd-386-12_3", "exp"), none}, 700 {b("freebsd-amd64-12_3", "exp"), none}, 701 {b("js-wasm-node18", "exp"), none}, 702 {b("wasip1-wasm-wazero", "exp"), none}, 703 {b("wasip1-wasm-wasmtime", "exp"), none}, 704 {b("wasip1-wasm-wasmer", "exp"), none}, 705 {b("wasip1-wasm-wasmedge", "exp"), none}, 706 707 // exp is experimental; it doesn't test against release branches. 708 {b("linux-amd64@go1.99", "exp"), none}, 709 710 // the build repo is only really useful for linux-amd64 (where we run it), 711 // and darwin-amd64 and perhaps windows-amd64 (for stuff like gomote). 712 // No need for any other operating systems to use it. 713 {b("linux-amd64", "build"), both}, 714 {b("linux-amd64-longtest", "build"), onlyPost}, 715 {b("windows-amd64-2016", "build"), both}, 716 {b("darwin-amd64-10_15", "build"), none}, 717 {b("darwin-amd64-11_0", "build"), onlyPost}, 718 {b("linux-amd64-fedora", "build"), none}, 719 {b("linux-amd64-clang", "build"), none}, 720 {b("linux-amd64-sid", "build"), none}, 721 {b("linux-amd64-bullseye", "build"), none}, 722 {b("linux-amd64-bookworm", "build"), none}, 723 {b("linux-amd64-nocgo", "build"), none}, 724 {b("linux-386-longtest", "build"), none}, 725 726 {b("linux-amd64", "vulndb"), both}, 727 {b("linux-amd64-longtest", "vulndb"), onlyPost}, 728 729 {b("linux-amd64@go1.20", "pkgsite-metrics"), both}, 730 731 {b("js-wasm-node18", "build"), none}, 732 {b("wasip1-wasm-wazero", "build"), none}, 733 {b("wasip1-wasm-wasmtime", "build"), none}, 734 {b("wasip1-wasm-wasmer", "build"), none}, 735 {b("wasip1-wasm-wasmedge", "build"), none}, 736 {b("android-386-emu", "build"), none}, 737 {b("android-amd64-emu", "build"), none}, 738 739 {b("darwin-amd64-11_0", "go"), onlyPost}, 740 // Go 1.22 is the last release with macOS 10.15 support: 741 {b("darwin-amd64-10_15", "go"), none}, 742 {b("darwin-amd64-10_15@go1.23", "go"), none}, 743 {b("darwin-amd64-10_15@go1.22", "go"), onlyPost}, 744 {b("darwin-amd64-10_15", "net"), none}, 745 {b("darwin-amd64-10_15@go1.23", "net"), none}, 746 {b("darwin-amd64-10_15@go1.22", "net"), onlyPost}, 747 748 // The darwin longtest builder added during the Go 1.21 dev cycle: 749 {b("darwin-amd64-longtest@go1.21", "go"), onlyPost}, 750 {b("darwin-amd64-longtest@go1.20", "go"), none}, 751 752 // plan9 only lived at master. We didn't support any past releases. 753 // But it's off for now as it's always failing. 754 {b("plan9-386", "go"), none}, // temporarily disabled 755 {b("plan9-386", "net"), none}, // temporarily disabled 756 {b("plan9-386", "exp"), none}, 757 {b("plan9-386", "mobile"), none}, 758 {b("plan9-386@go1.99", "go"), none}, 759 {b("plan9-386@go1.99", "net"), none}, 760 {b("plan9-amd64-0intro", "go"), onlyPost}, 761 {b("plan9-amd64-0intro", "exp"), none}, 762 {b("plan9-amd64-0intro", "mobile"), none}, 763 {b("plan9-amd64-0intro@go1.99", "go"), none}, 764 {b("plan9-amd64-0intro", "net"), onlyPost}, 765 {b("plan9-amd64-0intro@go1.99", "net"), none}, 766 {b("plan9-arm", "go"), onlyPost}, 767 {b("plan9-arm", "exp"), none}, 768 {b("plan9-arm", "mobile"), none}, 769 {b("plan9-amd64-0intro@go1.99", "go"), none}, 770 {b("plan9-amd64-0intro", "net"), onlyPost}, 771 {b("plan9-amd64-0intro@go1.99", "net"), none}, 772 {b("dragonfly-amd64-622", "go"), onlyPost}, 773 {b("dragonfly-amd64-622", "net"), onlyPost}, 774 775 {b("linux-amd64-staticlockranking", "go"), onlyPost}, 776 {b("linux-amd64-staticlockranking", "net"), none}, 777 778 {b("linux-amd64-newinliner", "go"), both}, 779 {b("linux-amd64-newinliner", "tools"), none}, 780 {b("linux-amd64-newinliner@go1.22", "go"), none}, 781 } 782 for _, tt := range tests { 783 t.Run(tt.br.testName, func(t *testing.T) { 784 // Require a want value that asserts both dimensions: try or not, post or not. 785 switch tt.want { 786 case none, both, onlyPost: 787 // OK. 788 default: 789 t.Fatalf("tt.want must be one of: none, both, or onlyPost") 790 } 791 792 bc, ok := Builders[tt.br.builder] 793 if !ok { 794 t.Fatalf("unknown builder %q", tt.br.builder) 795 } 796 gotPost := bc.BuildsRepoPostSubmit(tt.br.repo, tt.br.branch, tt.br.goBranch) 797 if tt.want&isBuilder != 0 && !gotPost { 798 t.Errorf("not a post-submit builder, but expected") 799 } 800 if tt.want¬Builder != 0 && gotPost { 801 t.Errorf("unexpectedly a post-submit builder") 802 } 803 804 gotTry := bc.BuildsRepoTryBot(tt.br.repo, tt.br.branch, tt.br.goBranch) 805 if tt.want&isTrybot != 0 && !gotTry { 806 t.Errorf("not trybot, but expected") 807 } 808 if tt.want¬Trybot != 0 && gotTry { 809 t.Errorf("unexpectedly a trybot") 810 } 811 812 if t.Failed() { 813 t.Logf("For: %+v", tt.br) 814 } 815 }) 816 } 817 } 818 819 func TestHostConfigsAllUsed(t *testing.T) { 820 knownUnused := map[string]bool{} 821 822 used := make(map[string]bool) 823 for _, conf := range Builders { 824 used[conf.HostType] = true 825 } 826 for hostType := range Hosts { 827 if !used[hostType] && !knownUnused[hostType] { 828 t.Errorf("host type %q is not referenced from any build config", hostType) 829 } 830 if used[hostType] && knownUnused[hostType] { 831 t.Errorf("host type %q should not be listed in knownUnused since it's in use", hostType) 832 } 833 } 834 } 835 836 // Test that all specified builder owners are non-nil. 837 func TestBuilderOwners(t *testing.T) { 838 for host, config := range Hosts { 839 for i, p := range config.Owners { 840 if p == nil { 841 t.Errorf("dashboard.Hosts[%q].Owners[%d] is nil, want non-nil", host, i) 842 } 843 } 844 } 845 } 846 847 // tests that goBranch is optional for repo == "go" 848 func TestBuildsRepoAtAllImplicitGoBranch(t *testing.T) { 849 builder := Builders["android-amd64-emu"] 850 got := builder.buildsRepoAtAll("go", "master", "") 851 if !got { 852 t.Error("got = false; want true") 853 } 854 } 855 856 func TestShouldRunDistTest(t *testing.T) { 857 type buildMode int 858 const ( 859 tryMode buildMode = 0 860 postSubmit buildMode = 1 861 ) 862 863 tests := []struct { 864 builder string 865 test string 866 mode buildMode 867 want bool 868 }{ 869 {"linux-amd64", "api", postSubmit, true}, 870 {"linux-amd64", "api", tryMode, true}, 871 {"freebsd-amd64-12_3", "api", postSubmit, true}, // freebsd-amd64-12_3 uses fasterTrybots policy, should still build. 872 {"freebsd-amd64-12_3", "api", tryMode, false}, // freebsd-amd64-12_3 uses fasterTrybots policy, should skip in try mode. 873 874 {"linux-amd64", "reboot", tryMode, true}, 875 {"linux-amd64-race", "reboot", tryMode, false}, 876 877 {"darwin-amd64-13", "test:foo", postSubmit, false}, 878 {"darwin-amd64-13", "reboot", postSubmit, false}, 879 {"darwin-amd64-13", "api", postSubmit, false}, 880 {"darwin-amd64-13", "codewalk", postSubmit, false}, 881 {"darwin-amd64-12_0", "test:foo", postSubmit, false}, 882 } 883 for _, tt := range tests { 884 bc, ok := Builders[tt.builder] 885 if !ok { 886 t.Errorf("unknown builder %q", tt.builder) 887 continue 888 } 889 isTry := tt.mode == tryMode 890 if isTry && !bc.BuildsRepoTryBot("go", "master", "master") { 891 t.Errorf("builder %q is not a trybot, so can't run test %q in try mode", tt.builder, tt.test) 892 continue 893 } 894 got := bc.ShouldRunDistTest(tt.test, isTry) 895 if got != tt.want { 896 t.Errorf("%q.ShouldRunDistTest(%q, try %v) = %v; want %v", tt.builder, tt.test, isTry, got, tt.want) 897 } 898 } 899 } 900 901 func TestSlowBotAliases(t *testing.T) { 902 for term, name := range slowBotAliases { 903 if name == "" { 904 // Empty string means known missing builder. 905 continue 906 } 907 if _, ok := Builders[name]; !ok { 908 t.Errorf("slowbot term %q references unknown builder %q", term, name) 909 } 910 } 911 912 ports, err := listPorts() 913 if err != nil { 914 t.Fatal("listPorts:", err) 915 } 916 917 done := map[string]bool{} 918 919 var add bytes.Buffer 920 check := func(term string, isArch bool) { 921 if done[term] { 922 return 923 } 924 done[term] = true 925 _, isBuilderName := Builders[term] 926 _, hasAlias := slowBotAliases[term] 927 if !isBuilderName && !hasAlias { 928 prefix := term 929 if isArch { 930 prefix = "linux-" + term 931 } 932 var matches []string 933 for name := range Builders { 934 if strings.HasPrefix(name, prefix) { 935 matches = append(matches, name) 936 } 937 } 938 sort.Strings(matches) 939 t.Errorf("term %q has no match in slowBotAliases", term) 940 if len(matches) == 1 { 941 fmt.Fprintf(&add, "%q: %q,\n", term, matches[0]) 942 } else if len(matches) > 1 { 943 t.Errorf("maybe add: %q: %q, (matches=%q)", term, matches[len(matches)-1], matches) 944 } 945 } 946 } 947 948 for _, port := range ports { 949 goos, goarch, ok := strings.Cut(port, "/") 950 if !ok { 951 t.Fatalf("unexpected port %q", port) 952 } 953 check(goos+"-"+goarch, false) 954 check(goos, false) 955 check(goarch, true) 956 } 957 958 if add.Len() > 0 { 959 t.Errorf("Missing items from slowBotAliases:\n%s", add.String()) 960 } 961 } 962 963 // TestCrossCompileOnlyBuilders checks to make sure that only misc-compile 964 // builders and the linux-s390x-crosscompile builder have IsCrossCompileOnly 965 // return true. 966 func TestCrossCompileOnlyBuilders(t *testing.T) { 967 for _, conf := range Builders { 968 isMiscCompile := strings.HasPrefix(conf.Name, "misc-compile") || conf.Name == "linux-s390x-crosscompile" 969 if ccOnly := conf.IsCrossCompileOnly(); isMiscCompile != ccOnly { 970 t.Errorf("builder %q has unexpected IsCrossCompileOnly state (want %t, got %t)", conf.Name, isMiscCompile, ccOnly) 971 } 972 } 973 } 974 975 // TestTryBotsCompileAllPorts verifies that each port (go tool dist list) 976 // is covered by either a real TryBot or a misc-compile TryBot. 977 // 978 // The special pseudo-port 'linux-arm-arm5' is tested in TestMiscCompileLinuxGOARM5. 979 func TestTryBotsCompileAllPorts(t *testing.T) { 980 ports, err := listPorts() 981 if err != nil { 982 t.Fatal("listPorts:", err) 983 } 984 985 // knownMissing tracks Go ports that that are known to be 986 // completely missing TryBot (pre-submit) test coverage. 987 // 988 // All completed ports should have either a real TryBot or at least a misc-compile TryBot, 989 // so this map is meant to be used to temporarily fix tests 990 // when the work of adding a new port is actively underway. 991 knownMissing := map[string]bool{ 992 "openbsd-mips64": true, // go.dev/issue/58110 993 994 "js-wasm": true, // Fully ported to LUCI and stopped in the coordinator. 995 "wasip1-wasm": true, // Fully ported to LUCI and stopped in the coordinator. 996 } 997 998 var done = make(map[string]bool) 999 check := func(goos, goarch string) { 1000 if goos == "android" || goos == "ios" { 1001 // TODO(golang.org/issue/25963): support 1002 // compilation-only Android and iOS trybots. 1003 // buildall.bash doesn't set the environment 1004 // up enough for e.g. compiling android-386 1005 // from linux-amd64. (Issue #35596 too) 1006 // iOS likely needs to be built on macOS 1007 // with Xcode available. 1008 return 1009 } 1010 goosArch := goos + "-" + goarch 1011 if done[goosArch] { 1012 return 1013 } 1014 for _, conf := range Builders { 1015 if conf.GOOS() == goos && conf.GOARCH() == goarch && 1016 conf.BuildsRepoTryBot("go", "master", "master") { 1017 1018 // There's a real TryBot for this GOOS/GOARCH pair. 1019 done[goosArch] = true 1020 break 1021 } 1022 1023 if strings.HasPrefix(conf.Name, "misc-compile-") { 1024 var cGoos, cGoarch string 1025 for _, v := range conf.env { 1026 if strings.HasPrefix(v, "GOOS=") { 1027 cGoos = v[len("GOOS="):] 1028 } 1029 if strings.HasPrefix(v, "GOARCH=") { 1030 cGoarch = v[len("GOARCH="):] 1031 } 1032 } 1033 if cGoos == "" { 1034 t.Errorf("missing GOOS env var for misc-compile builder %q", conf.Name) 1035 } 1036 if cGoarch == "" { 1037 t.Errorf("missing GOARCH env var for misc-compile builder %q", conf.Name) 1038 } 1039 cGoosArch := cGoos + "-" + cGoarch 1040 if goosArch == cGoosArch { 1041 // There's a misc-compile TryBot for this GOOS/GOARCH pair. 1042 done[goosArch] = true 1043 break 1044 } 1045 } 1046 } 1047 if knownMissing[goosArch] && done[goosArch] { 1048 // Make it visible when a builder is added but the old 1049 // knownMissing entry isn't removed by failing the test. 1050 t.Errorf("knownMissing[%q] is true, but a corresponding TryBot (real or misc-compile) exists", goosArch) 1051 } else if _, ok := done[goosArch]; !ok && !knownMissing[goosArch] { 1052 t.Errorf("missing real TryBot or misc-compile TryBot for %q", goosArch) 1053 } 1054 } 1055 1056 for _, port := range ports { 1057 goos, goarch, ok := strings.Cut(port, "/") 1058 if !ok { 1059 t.Fatalf("unexpected port %q", port) 1060 } 1061 check(goos, goarch) 1062 } 1063 } 1064 1065 // The 'linux-arm-arm5' pseduo-port is supported by src/buildall.bash 1066 // and tests linux/arm with GOARM=5 set. Since it's not a normal port, 1067 // the TestTryBotsCompileAllPorts wouldn't report if the misc-compile 1068 // TryBot that covers is accidentally removed. Check it explicitly. 1069 func TestMiscCompileLinuxGOARM5(t *testing.T) { 1070 for _, b := range Builders { 1071 if !strings.HasPrefix(b.Name, "misc-compile-") { 1072 continue 1073 } 1074 var hasGOOS, hasGOARCH, hasGOARM bool 1075 for _, v := range b.env { 1076 if v == "GOOS=linux" { 1077 hasGOOS = true 1078 continue 1079 } 1080 if v == "GOARCH=arm" { 1081 hasGOARCH = true 1082 continue 1083 } 1084 if v == "GOARM=5" { 1085 hasGOARM = true 1086 continue 1087 } 1088 } 1089 if hasGOOS && hasGOARCH && hasGOARM { 1090 // Found it. Nothing left to do. 1091 return 1092 } 1093 } 1094 // We get here if the linux-arm-arm5 port is no longer checked by 1095 // a misc-compile TryBot. Report it as a failure in case the coverage 1096 // was removed accidentally (e.g., as part of a refactor). 1097 t.Errorf("no misc-compile TryBot coverage for the special 'linux-arm-arm5' pseudo-port") 1098 } 1099 1100 // Test that we have longtest builders and 1101 // that their environment configurations are okay. 1102 func TestLongTestBuilder(t *testing.T) { 1103 for _, name := range []string{"linux-amd64-longtest", "linux-amd64-longtest-race"} { 1104 name := name 1105 t.Run(name, func(t *testing.T) { 1106 long, ok := Builders[name] 1107 if !ok { 1108 t.Fatalf("we don't have a %s builder anymore, is that intentional?", name) 1109 } 1110 if !long.IsLongTest() { 1111 t.Errorf("the %s builder isn't a longtest builder, is that intentional?", name) 1112 } 1113 var shortDisabled bool 1114 for _, e := range long.Env() { 1115 if e == "GO_TEST_SHORT=0" { 1116 shortDisabled = true 1117 } 1118 } 1119 if !shortDisabled { 1120 t.Errorf("the %s builder doesn't set GO_TEST_SHORT=0, is that intentional?", name) 1121 } 1122 }) 1123 } 1124 } 1125 1126 // Test that we have race builders and 1127 // that their environment configurations are okay. 1128 func TestRaceBuilder(t *testing.T) { 1129 for _, name := range []string{"linux-amd64-race", "linux-amd64-longtest-race"} { 1130 name := name 1131 t.Run(name, func(t *testing.T) { 1132 race, ok := Builders[name] 1133 if !ok { 1134 t.Fatalf("we don't have a %s builder anymore, is that intentional?", name) 1135 } 1136 if !race.IsRace() { 1137 t.Errorf("the %s builder isn't a race builder, is that intentional?", name) 1138 } 1139 if script := race.AllScript(); !strings.Contains(script, "race") { 1140 t.Errorf("the %s builder doesn't use race.bash or race.bat, it uses %s instead, is that intentional?", name, script) 1141 } 1142 }) 1143 } 1144 } 1145 1146 func TestHostConfigIsVM(t *testing.T) { 1147 testCases := []struct { 1148 desc string 1149 config *HostConfig 1150 want bool 1151 }{ 1152 { 1153 desc: "non-ec2-vm", 1154 config: &HostConfig{ 1155 VMImage: "image-x", 1156 ContainerImage: "", 1157 IsEC2: false, 1158 }, 1159 want: true, 1160 }, 1161 { 1162 desc: "non-ec2-container", 1163 config: &HostConfig{ 1164 VMImage: "", 1165 ContainerImage: "container-image-x", 1166 IsEC2: false, 1167 }, 1168 want: false, 1169 }, 1170 { 1171 desc: "ec2-container", 1172 config: &HostConfig{ 1173 VMImage: "image-x", 1174 ContainerImage: "container-image-x", 1175 IsEC2: true, 1176 }, 1177 want: false, 1178 }, 1179 { 1180 desc: "ec2-vm", 1181 config: &HostConfig{ 1182 VMImage: "image-x", 1183 ContainerImage: "", 1184 IsEC2: true, 1185 }, 1186 want: true, 1187 }, 1188 } 1189 for _, tc := range testCases { 1190 t.Run(fmt.Sprintf(tc.desc), func(t *testing.T) { 1191 if got := tc.config.IsVM(); got != tc.want { 1192 t.Errorf("HostConfig.IsVM() = %t; want %t", got, tc.want) 1193 } 1194 }) 1195 } 1196 } 1197 1198 func TestDefaultPlusExpBuild(t *testing.T) { 1199 for _, tc := range []struct { 1200 repo string 1201 want bool 1202 }{ 1203 {"exp", true}, 1204 {"build", true}, 1205 {"anything", true}, 1206 {"vulndb", false}, 1207 } { 1208 got := defaultPlusExpBuild(tc.repo, "", "") 1209 if got != tc.want { 1210 t.Errorf("%s: got %t, want %t", tc.repo, got, tc.want) 1211 } 1212 } 1213 } 1214 1215 func TestHostsSort(t *testing.T) { 1216 data, err := os.ReadFile("builders.go") 1217 if err != nil { 1218 t.Fatal(err) 1219 } 1220 table := regexp.MustCompile(`(?s)\nvar Hosts =.*?\n}\n`).FindString(string(data)) 1221 if table == "" { 1222 t.Fatal("cannot find Hosts table in builders.go") 1223 } 1224 m := regexp.MustCompile(`\n\t"([^"]+)":`).FindAllStringSubmatch(table, -1) 1225 if len(m) < 10 { 1226 t.Fatalf("cannot find host keys in table") 1227 } 1228 var last string 1229 for _, sub := range m { 1230 key := sub[1] 1231 if last > key { 1232 t.Errorf("Host table unsorted: %s before %s", last, key) 1233 } 1234 last = key 1235 } 1236 } 1237 1238 func TestBuildersPortedToLUCI(t *testing.T) { 1239 // Check that map keys refer to builder names that exist, 1240 // otherwise the entry is a no-op. Mostly to catch typos. 1241 for name := range BuildersPortedToLUCI { 1242 if _, ok := Builders[name]; !ok { 1243 t.Errorf("BuildersPortedToLUCI contains an unknown legacy builder name %v", name) 1244 } 1245 } 1246 } 1247 1248 func TestHostConfigCosArchitecture(t *testing.T) { 1249 testCases := []struct { 1250 desc string 1251 hostConfig HostConfig 1252 want CosArch 1253 }{ 1254 {"default", HostConfig{}, CosArchAMD64}, 1255 {"amd64", HostConfig{cosArchitecture: CosArchAMD64}, CosArchAMD64}, 1256 {"arm64", HostConfig{cosArchitecture: CosArchARM64}, CosArchARM64}, 1257 } 1258 for _, tc := range testCases { 1259 t.Run(tc.desc, func(t *testing.T) { 1260 if got := tc.hostConfig.CosArchitecture(); got != tc.want { 1261 t.Errorf("HostConfig.CosArchitecture() = %+v; want %+v", got, tc.want) 1262 } 1263 }) 1264 } 1265 } 1266 1267 // listPorts lists supported Go ports 1268 // found by running go tool dist list. 1269 func listPorts() ([]string, error) { 1270 cmd := exec.Command("go", "tool", "dist", "list") 1271 out, err := cmd.Output() 1272 if err != nil { 1273 if ee := (*exec.ExitError)(nil); errors.As(err, &ee) { 1274 out = append(out, ee.Stderr...) 1275 } 1276 return nil, fmt.Errorf("%q failed: %s\n%s", cmd, err, out) 1277 } 1278 return strings.Fields(string(out)), nil 1279 }