105 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
| // Copyright 2014 The Go Authors. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style
 | |
| // license that can be found in the LICENSE file.
 | |
| 
 | |
| package main
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"go/build"
 | |
| 	"io"
 | |
| 	"io/ioutil"
 | |
| 	"os"
 | |
| 	"os/exec"
 | |
| 	"path/filepath"
 | |
| 	"strings"
 | |
| 	"testing"
 | |
| )
 | |
| 
 | |
| // This file contains a test that compiles and runs each program in testdata
 | |
| // after generating the string method for its type. The rule is that for testdata/x.go
 | |
| // we run stringer -type X and then compile and run the program. The resulting
 | |
| // binary panics if the String method for X is not correct, including for error cases.
 | |
| 
 | |
| func TestEndToEnd(t *testing.T) {
 | |
| 	dir, err := ioutil.TempDir("", "stringer")
 | |
| 	defer os.RemoveAll(dir)
 | |
| 	// Create stringer in temporary directory.
 | |
| 	stringer := filepath.Join(dir, "stringer.exe")
 | |
| 	err = run("go", "build", "-o", stringer, "stringer.go")
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("building stringer: %s", err)
 | |
| 	}
 | |
| 	// Read the testdata directory.
 | |
| 	fd, err := os.Open("testdata")
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 	defer fd.Close()
 | |
| 	names, err := fd.Readdirnames(-1)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Readdirnames: %s", err)
 | |
| 	}
 | |
| 	// Generate, compile, and run the test programs.
 | |
| 	for _, name := range names {
 | |
| 		if !strings.HasSuffix(name, ".go") {
 | |
| 			t.Errorf("%s is not a Go file", name)
 | |
| 			continue
 | |
| 		}
 | |
| 		if name == "cgo.go" && !build.Default.CgoEnabled {
 | |
| 			t.Logf("cgo is no enabled for %s", name)
 | |
| 			continue
 | |
| 		}
 | |
| 		// Names are known to be ASCII and long enough.
 | |
| 		typeName := fmt.Sprintf("%c%s", name[0]+'A'-'a', name[1:len(name)-len(".go")])
 | |
| 		stringerCompileAndRun(t, dir, stringer, typeName, name)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // stringerCompileAndRun runs stringer for the named file and compiles and
 | |
| // runs the target binary in directory dir. That binary will panic if the String method is incorrect.
 | |
| func stringerCompileAndRun(t *testing.T, dir, stringer, typeName, fileName string) {
 | |
| 	t.Logf("run: %s %s\n", fileName, typeName)
 | |
| 	source := filepath.Join(dir, fileName)
 | |
| 	err := copy(source, filepath.Join("testdata", fileName))
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("copying file to temporary directory: %s", err)
 | |
| 	}
 | |
| 	stringSource := filepath.Join(dir, typeName+"_string.go")
 | |
| 	// Run stringer in temporary directory.
 | |
| 	err = run(stringer, "-type", typeName, "-output", stringSource, source)
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 	// Run the binary in the temporary directory.
 | |
| 	err = run("go", "run", stringSource, source)
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // copy copies the from file to the to file.
 | |
| func copy(to, from string) error {
 | |
| 	toFd, err := os.Create(to)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	defer toFd.Close()
 | |
| 	fromFd, err := os.Open(from)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	defer fromFd.Close()
 | |
| 	_, err = io.Copy(toFd, fromFd)
 | |
| 	return err
 | |
| }
 | |
| 
 | |
| // run runs a single command and returns an error if it does not succeed.
 | |
| // os/exec should have this function, to be honest.
 | |
| func run(name string, arg ...string) error {
 | |
| 	cmd := exec.Command(name, arg...)
 | |
| 	cmd.Stdout = os.Stdout
 | |
| 	cmd.Stderr = os.Stderr
 | |
| 	return cmd.Run()
 | |
| }
 |