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/runtime/internal/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: "**/.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  
   104  func 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  
   121  func testZip(a *Archive) { test("binary", a, zipRules) }
   122  func testMod(a *Archive) { test("module", a, modRules) }
   123  
   124  func 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  

View as plain text