Source file src/cmd/distpack/test.go

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

View as plain text