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 }