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
5package platform_test
6
7import (
8	"bytes"
9	"encoding/json"
10	"flag"
11	"internal/diff"
12	"internal/testenv"
13	"os"
14	"os/exec"
15	"testing"
16	"text/template"
17)
18
19var flagFix = flag.Bool("fix", false, "if true, fix out-of-date generated files")
20
21// TestGenerated verifies that zosarch.go is up to date,
22// or regenerates it if the -fix flag is set.
23func TestGenerated(t *testing.T) {
24	testenv.MustHaveGoRun(t)
25
26	// Here we use 'go run cmd/dist' instead of 'go tool dist' in case the
27	// installed cmd/dist is stale or missing. We don't want to miss a
28	// skew in the data due to a stale binary.
29	cmd := testenv.Command(t, "go", "run", "cmd/dist", "list", "-json", "-broken")
30
31	// cmd/dist requires GOROOT to be set explicitly in the environment.
32	cmd.Env = append(cmd.Environ(), "GOROOT="+testenv.GOROOT(t))
33
34	out, err := cmd.Output()
35	if err != nil {
36		if ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {
37			t.Logf("stderr:\n%s", ee.Stderr)
38		}
39		t.Fatalf("%v: %v", cmd, err)
40	}
41
42	type listEntry struct {
43		GOOS, GOARCH string
44		CgoSupported bool
45		FirstClass   bool
46		Broken       bool
47	}
48	var entries []listEntry
49	if err := json.Unmarshal(out, &entries); err != nil {
50		t.Fatal(err)
51	}
52
53	tmplOut := new(bytes.Buffer)
54	tmpl := template.Must(template.New("zosarch").Parse(zosarchTmpl))
55	err = tmpl.Execute(tmplOut, entries)
56	if err != nil {
57		t.Fatal(err)
58	}
59
60	cmd = testenv.Command(t, "gofmt")
61	cmd.Stdin = bytes.NewReader(tmplOut.Bytes())
62	want, err := cmd.Output()
63	if err != nil {
64		t.Logf("stdin:\n%s", tmplOut.Bytes())
65		if ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {
66			t.Logf("stderr:\n%s", ee.Stderr)
67		}
68		t.Fatalf("%v: %v", cmd, err)
69	}
70
71	got, err := os.ReadFile("zosarch.go")
72	if err == nil && bytes.Equal(got, want) {
73		return
74	}
75
76	if !*flagFix {
77		if err != nil {
78			t.Log(err)
79		} else {
80			t.Logf("diff:\n%s", diff.Diff("zosarch.go", got, "want", want))
81		}
82		t.Fatalf("zosarch.go is missing or out of date; to regenerate, run\ngo generate internal/platform")
83	}
84
85	if err := os.WriteFile("zosarch.go", want, 0666); err != nil {
86		t.Fatal(err)
87	}
88}
89
90const zosarchTmpl = `// Code generated by go test internal/platform -fix. DO NOT EDIT.
91
92// To change the information in this file, edit the cgoEnabled and/or firstClass
93// maps in cmd/dist/build.go, then run 'go generate internal/platform'.
94
95package platform
96
97// List is the list of all valid GOOS/GOARCH combinations,
98// including known-broken ports.
99var List = []OSArch{
100{{range .}}	{ {{ printf "%q" .GOOS }}, {{ printf "%q" .GOARCH }} },
101{{end}}
102}
103
104var distInfo = map[OSArch]osArchInfo {
105{{range .}}	{ {{ printf "%q" .GOOS }}, {{ printf "%q" .GOARCH }} }:
106{ {{if .CgoSupported}}CgoSupported: true, {{end}}{{if .FirstClass}}FirstClass: true, {{end}}{{if .Broken}} Broken: true, {{end}} },
107{{end}}
108}
109`
110