github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/tools/cmd/stringer/endtoend_test.go (about)

     1  // Copyright 2014 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  // go command is not available on android
     6  
     7  // +build !android
     8  
     9  package main
    10  
    11  import (
    12  	"fmt"
    13  	"go/build"
    14  	"io"
    15  	"io/ioutil"
    16  	"os"
    17  	"os/exec"
    18  	"path/filepath"
    19  	"strings"
    20  	"testing"
    21  )
    22  
    23  // This file contains a test that compiles and runs each program in testdata
    24  // after generating the string method for its type. The rule is that for testdata/x.go
    25  // we run stringer -type X and then compile and run the program. The resulting
    26  // binary panics if the String method for X is not correct, including for error cases.
    27  
    28  func TestEndToEnd(t *testing.T) {
    29  	dir, err := ioutil.TempDir("", "stringer")
    30  	if err != nil {
    31  		t.Fatal(err)
    32  	}
    33  	defer os.RemoveAll(dir)
    34  	// Create stringer in temporary directory.
    35  	stringer := filepath.Join(dir, "stringer.exe")
    36  	err = run("go", "build", "-o", stringer, "stringer.go")
    37  	if err != nil {
    38  		t.Fatalf("building stringer: %s", err)
    39  	}
    40  	// Read the testdata directory.
    41  	fd, err := os.Open("testdata")
    42  	if err != nil {
    43  		t.Fatal(err)
    44  	}
    45  	defer fd.Close()
    46  	names, err := fd.Readdirnames(-1)
    47  	if err != nil {
    48  		t.Fatalf("Readdirnames: %s", err)
    49  	}
    50  	// Generate, compile, and run the test programs.
    51  	for _, name := range names {
    52  		if !strings.HasSuffix(name, ".go") {
    53  			t.Errorf("%s is not a Go file", name)
    54  			continue
    55  		}
    56  		if name == "cgo.go" && !build.Default.CgoEnabled {
    57  			t.Logf("cgo is no enabled for %s", name)
    58  			continue
    59  		}
    60  		// Names are known to be ASCII and long enough.
    61  		typeName := fmt.Sprintf("%c%s", name[0]+'A'-'a', name[1:len(name)-len(".go")])
    62  		stringerCompileAndRun(t, dir, stringer, typeName, name)
    63  	}
    64  }
    65  
    66  // stringerCompileAndRun runs stringer for the named file and compiles and
    67  // runs the target binary in directory dir. That binary will panic if the String method is incorrect.
    68  func stringerCompileAndRun(t *testing.T, dir, stringer, typeName, fileName string) {
    69  	t.Logf("run: %s %s\n", fileName, typeName)
    70  	source := filepath.Join(dir, fileName)
    71  	err := copy(source, filepath.Join("testdata", fileName))
    72  	if err != nil {
    73  		t.Fatalf("copying file to temporary directory: %s", err)
    74  	}
    75  	stringSource := filepath.Join(dir, typeName+"_string.go")
    76  	// Run stringer in temporary directory.
    77  	err = run(stringer, "-type", typeName, "-output", stringSource, source)
    78  	if err != nil {
    79  		t.Fatal(err)
    80  	}
    81  	// Run the binary in the temporary directory.
    82  	err = run("go", "run", stringSource, source)
    83  	if err != nil {
    84  		t.Fatal(err)
    85  	}
    86  }
    87  
    88  // copy copies the from file to the to file.
    89  func copy(to, from string) error {
    90  	toFd, err := os.Create(to)
    91  	if err != nil {
    92  		return err
    93  	}
    94  	defer toFd.Close()
    95  	fromFd, err := os.Open(from)
    96  	if err != nil {
    97  		return err
    98  	}
    99  	defer fromFd.Close()
   100  	_, err = io.Copy(toFd, fromFd)
   101  	return err
   102  }
   103  
   104  // run runs a single command and returns an error if it does not succeed.
   105  // os/exec should have this function, to be honest.
   106  func run(name string, arg ...string) error {
   107  	cmd := exec.Command(name, arg...)
   108  	cmd.Stdout = os.Stdout
   109  	cmd.Stderr = os.Stderr
   110  	return cmd.Run()
   111  }