Source file src/cmd/internal/bootstrap_test/reboot_test.go

     1  // Copyright 2019 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 bootstrap_test verifies that the current GOROOT can be used to bootstrap
     6  // itself.
     7  package bootstrap_test
     8  
     9  import (
    10  	"fmt"
    11  	"internal/testenv"
    12  	"io"
    13  	"os"
    14  	"os/exec"
    15  	"path/filepath"
    16  	"runtime"
    17  	"strings"
    18  	"testing"
    19  	"time"
    20  )
    21  
    22  func TestRepeatBootstrap(t *testing.T) {
    23  	if testing.Short() {
    24  		t.Skip("skipping test that rebuilds the entire toolchain")
    25  	}
    26  	switch runtime.GOOS {
    27  	case "android", "ios", "js", "wasip1":
    28  		t.Skipf("skipping because the toolchain does not have to bootstrap on GOOS=%s", runtime.GOOS)
    29  	}
    30  
    31  	realGoroot := testenv.GOROOT(t)
    32  
    33  	// To ensure that bootstrapping doesn't unexpectedly depend
    34  	// on the Go repo's git metadata, add a fake (unreadable) git
    35  	// directory above the simulated GOROOT.
    36  	// This mimics the configuration one much have when
    37  	// building from distro-packaged source code
    38  	// (see https://go.dev/issue/54852).
    39  	parent := t.TempDir()
    40  	dotGit := filepath.Join(parent, ".git")
    41  	if err := os.Mkdir(dotGit, 000); err != nil {
    42  		t.Fatal(err)
    43  	}
    44  
    45  	overlayStart := time.Now()
    46  
    47  	goroot := filepath.Join(parent, "goroot")
    48  
    49  	gorootSrc := filepath.Join(goroot, "src")
    50  	if err := overlayDir(gorootSrc, filepath.Join(realGoroot, "src")); err != nil {
    51  		t.Fatal(err)
    52  	}
    53  
    54  	gorootLib := filepath.Join(goroot, "lib")
    55  	if err := overlayDir(gorootLib, filepath.Join(realGoroot, "lib")); err != nil {
    56  		t.Fatal(err)
    57  	}
    58  
    59  	t.Logf("GOROOT overlay set up in %s", time.Since(overlayStart))
    60  
    61  	if err := os.WriteFile(filepath.Join(goroot, "VERSION"), []byte(runtime.Version()), 0666); err != nil {
    62  		t.Fatal(err)
    63  	}
    64  
    65  	var makeScript string
    66  	switch runtime.GOOS {
    67  	case "windows":
    68  		makeScript = "make.bat"
    69  	case "plan9":
    70  		makeScript = "make.rc"
    71  	default:
    72  		makeScript = "make.bash"
    73  	}
    74  
    75  	var stdout strings.Builder
    76  	cmd := exec.Command(filepath.Join(goroot, "src", makeScript))
    77  	cmd.Dir = gorootSrc
    78  	cmd.Env = append(cmd.Environ(), "GOROOT=", "GOROOT_BOOTSTRAP="+realGoroot)
    79  	cmd.Stderr = os.Stderr
    80  	cmd.Stdout = io.MultiWriter(os.Stdout, &stdout)
    81  	if err := cmd.Run(); err != nil {
    82  		t.Fatal(err)
    83  	}
    84  
    85  	// Test that go.dev/issue/42563 hasn't regressed.
    86  	t.Run("PATH reminder", func(t *testing.T) {
    87  		var want string
    88  		switch gorootBin := filepath.Join(goroot, "bin"); runtime.GOOS {
    89  		default:
    90  			want = fmt.Sprintf("*** You need to add %s to your PATH.", gorootBin)
    91  		case "plan9":
    92  			want = fmt.Sprintf("*** You need to bind %s before /bin.", gorootBin)
    93  		}
    94  		if got := stdout.String(); !strings.Contains(got, want) {
    95  			t.Errorf("reminder %q is missing from %s stdout:\n%s", want, makeScript, got)
    96  		}
    97  	})
    98  }
    99  

View as plain text