1// Copyright 2023 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 contains tests applied to the archives before they are written. 6 7package main 8 9import ( 10 "bytes" 11 "fmt" 12 "log" 13 "os" 14 "path" 15 "path/filepath" 16 "strings" 17) 18 19type testRule struct { 20 name string 21 goos string 22 exclude bool 23} 24 25var srcRules = []testRule{ 26 {name: "go/VERSION"}, 27 {name: "go/src/cmd/go/main.go"}, 28 {name: "go/src/bytes/bytes.go"}, 29 {name: "**/.DS_Store", exclude: true}, 30 {name: "go/.git", exclude: true}, 31 {name: "go/.gitattributes", exclude: true}, 32 {name: "go/.github", exclude: true}, 33 {name: "go/VERSION.cache", exclude: true}, 34 {name: "go/bin/**", exclude: true}, 35 {name: "go/pkg/**", exclude: true}, 36 {name: "go/src/cmd/dist/dist", exclude: true}, 37 {name: "go/src/cmd/dist/dist.exe", exclude: true}, 38 {name: "go/src/runtime/internal/sys/zversion.go", exclude: true}, 39 {name: "go/src/time/tzdata/zzipdata.go", exclude: true}, 40} 41 42var zipRules = []testRule{ 43 {name: "go/VERSION"}, 44 {name: "go/src/cmd/go/main.go"}, 45 {name: "go/src/bytes/bytes.go"}, 46 47 {name: "**/.DS_Store", exclude: true}, 48 {name: "go/.git", exclude: true}, 49 {name: "go/.gitattributes", exclude: true}, 50 {name: "go/.github", exclude: true}, 51 {name: "go/VERSION.cache", exclude: true}, 52 {name: "go/bin", exclude: true}, 53 {name: "go/pkg", exclude: true}, 54 {name: "go/src/cmd/dist/dist", exclude: true}, 55 {name: "go/src/cmd/dist/dist.exe", exclude: true}, 56 57 {name: "go/bin/go", goos: "linux"}, 58 {name: "go/bin/go", goos: "darwin"}, 59 {name: "go/bin/go", goos: "windows", exclude: true}, 60 {name: "go/bin/go.exe", goos: "windows"}, 61 {name: "go/bin/gofmt", goos: "linux"}, 62 {name: "go/bin/gofmt", goos: "darwin"}, 63 {name: "go/bin/gofmt", goos: "windows", exclude: true}, 64 {name: "go/bin/gofmt.exe", goos: "windows"}, 65 {name: "go/pkg/tool/*/compile", goos: "linux"}, 66 {name: "go/pkg/tool/*/compile", goos: "darwin"}, 67 {name: "go/pkg/tool/*/compile", goos: "windows", exclude: true}, 68 {name: "go/pkg/tool/*/compile.exe", goos: "windows"}, 69} 70 71var modRules = []testRule{ 72 {name: "golang.org/toolchain@*/VERSION"}, 73 {name: "golang.org/toolchain@*/src/cmd/go/main.go"}, 74 {name: "golang.org/toolchain@*/src/bytes/bytes.go"}, 75 76 {name: "**/.DS_Store", exclude: true}, 77 {name: "golang.org/toolchain@*/.git", exclude: true}, 78 {name: "golang.org/toolchain@*/.gitattributes", exclude: true}, 79 {name: "golang.org/toolchain@*/.github", exclude: true}, 80 {name: "golang.org/toolchain@*/VERSION.cache", exclude: true}, 81 {name: "golang.org/toolchain@*/bin", exclude: true}, 82 {name: "golang.org/toolchain@*/pkg", exclude: true}, 83 {name: "golang.org/toolchain@*/src/cmd/dist/dist", exclude: true}, 84 {name: "golang.org/toolchain@*/src/cmd/dist/dist.exe", exclude: true}, 85 86 {name: "golang.org/toolchain@*/bin/go", goos: "linux"}, 87 {name: "golang.org/toolchain@*/bin/go", goos: "darwin"}, 88 {name: "golang.org/toolchain@*/bin/go", goos: "windows", exclude: true}, 89 {name: "golang.org/toolchain@*/bin/go.exe", goos: "windows"}, 90 {name: "golang.org/toolchain@*/bin/gofmt", goos: "linux"}, 91 {name: "golang.org/toolchain@*/bin/gofmt", goos: "darwin"}, 92 {name: "golang.org/toolchain@*/bin/gofmt", goos: "windows", exclude: true}, 93 {name: "golang.org/toolchain@*/bin/gofmt.exe", goos: "windows"}, 94 {name: "golang.org/toolchain@*/pkg/tool/*/compile", goos: "linux"}, 95 {name: "golang.org/toolchain@*/pkg/tool/*/compile", goos: "darwin"}, 96 {name: "golang.org/toolchain@*/pkg/tool/*/compile", goos: "windows", exclude: true}, 97 {name: "golang.org/toolchain@*/pkg/tool/*/compile.exe", goos: "windows"}, 98 99 // go.mod are renamed to _go.mod. 100 {name: "**/go.mod", exclude: true}, 101 {name: "**/_go.mod"}, 102} 103 104func testSrc(a *Archive) { 105 test("source", a, srcRules) 106 107 // Check that no generated files slip in, even if new ones are added. 108 for _, f := range a.Files { 109 if strings.HasPrefix(path.Base(f.Name), "z") { 110 data, err := os.ReadFile(filepath.Join(goroot, strings.TrimPrefix(f.Name, "go/"))) 111 if err != nil { 112 log.Fatalf("checking source archive: %v", err) 113 } 114 if strings.Contains(string(data), "generated by go tool dist; DO NOT EDIT") { 115 log.Fatalf("unexpected source archive file: %s (generated by dist)", f.Name) 116 } 117 } 118 } 119} 120 121func testZip(a *Archive) { test("binary", a, zipRules) } 122func testMod(a *Archive) { test("module", a, modRules) } 123 124func test(kind string, a *Archive, rules []testRule) { 125 ok := true 126 have := make([]bool, len(rules)) 127 for _, f := range a.Files { 128 for i, r := range rules { 129 if r.goos != "" && r.goos != goos { 130 continue 131 } 132 match, err := amatch(r.name, f.Name) 133 if err != nil { 134 log.Fatal(err) 135 } 136 if match { 137 if r.exclude { 138 ok = false 139 if !have[i] { 140 log.Printf("unexpected %s archive file: %s", kind, f.Name) 141 have[i] = true // silence future prints for excluded directory 142 } 143 } else { 144 have[i] = true 145 } 146 } 147 } 148 } 149 missing := false 150 for i, r := range rules { 151 if r.goos != "" && r.goos != goos { 152 continue 153 } 154 if !r.exclude && !have[i] { 155 missing = true 156 log.Printf("missing %s archive file: %s", kind, r.name) 157 } 158 } 159 if missing { 160 ok = false 161 var buf bytes.Buffer 162 for _, f := range a.Files { 163 fmt.Fprintf(&buf, "\n\t%s", f.Name) 164 } 165 log.Printf("archive contents: %d files%s", len(a.Files), buf.Bytes()) 166 } 167 if !ok { 168 log.Fatalf("bad archive file") 169 } 170} 171