modernc.org/ccgo/v3@v3.16.14/lib/unix_test.go (about) 1 // Copyright 2021 The CCGO 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:build !windows 6 // +build !windows 7 8 package ccgo // import "modernc.org/ccgo/v3/lib" 9 10 import ( 11 "bytes" 12 "context" 13 "fmt" 14 "io/ioutil" 15 "os" 16 "os/exec" 17 "path/filepath" 18 "strings" 19 "syscall" 20 "testing" 21 22 "golang.org/x/sys/unix" 23 ) 24 25 // See the discussion at https://groups.google.com/g/golang-nuts/c/U1BLt5JM8F0/m/x9pQVq5RDwAJ 26 // 27 // Thanks to Brian Candler for fixing the code of this function. 28 func testSingle(t *testing.T, main, path string, ccgoArgs []string, runargs []string) (r bool) { 29 defer func() { 30 if err := recover(); err != nil { 31 if *oStackTrace { 32 fmt.Printf("%s\n", stack()) 33 } 34 if *oTrace { 35 fmt.Println(err) 36 } 37 t.Errorf("%s: %v", path, err) 38 r = false 39 } 40 }() 41 42 ccgoArgs = append(ccgoArgs, "-D__ccgo_test__") 43 ccgoArgs = append(ccgoArgs, path) 44 if err := NewTask(ccgoArgs, nil, nil).Main(); err != nil { 45 if *oTrace { 46 fmt.Println(err) 47 } 48 err = cpp(*oCpp, ccgoArgs, err) 49 t.Errorf("%s: %v", path, err) 50 return false 51 } 52 53 out, err := func() ([]byte, error) { 54 ctx, cancel := context.WithTimeout(context.Background(), execTimeout) 55 defer cancel() 56 57 execcmd := exec.Command("go", append([]string{"run", main}, runargs...)...) 58 return testSingleCombinedoutput(ctx, execcmd) 59 60 }() 61 if err != nil { 62 if *oTrace { 63 fmt.Println(err) 64 } 65 b, _ := ioutil.ReadFile(main) 66 t.Errorf("\n%s\n%v: %s\n%v", b, path, out, err) 67 return false 68 } 69 70 if *oTraceF { 71 b, _ := ioutil.ReadFile(main) 72 fmt.Printf("\n----\n%s\n----\n", b) 73 } 74 if *oTraceO { 75 fmt.Printf("%s\n", out) 76 } 77 exp, err := ioutil.ReadFile(noExt(path) + ".expect") 78 if err != nil { 79 if os.IsNotExist(err) { 80 return true 81 } 82 83 return false 84 } 85 86 out = trim(out) 87 exp = trim(exp) 88 switch base := filepath.Base(path); base { 89 case "70_floating_point_literals.c": //TODO TCC binary extension 90 a := strings.Split(string(exp), "\n") 91 exp = []byte(strings.Join(a[:35], "\n")) 92 } 93 94 if !bytes.Equal(out, exp) { 95 if *oTrace { 96 fmt.Println(err) 97 } 98 t.Errorf("%v: out\n%s\nexp\n%s", path, out, exp) 99 return false 100 } 101 102 return true 103 } 104 105 func testSingleCombinedoutput(ctx context.Context, cmd *exec.Cmd) ([]byte, error) { 106 var b bytes.Buffer 107 cmd.Stdout = &b 108 cmd.Stderr = &b 109 110 err := testSingleRun(ctx, cmd) 111 return b.Bytes(), err 112 } 113 114 func testSingleRun(ctx context.Context, cmd *exec.Cmd) error { 115 cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true} 116 err := cmd.Start() 117 if err == nil { 118 waitDone := make(chan struct{}) 119 go func() { 120 select { 121 case <-ctx.Done(): 122 unix.Kill(-cmd.Process.Pid, os.Kill.(syscall.Signal)) 123 case <-waitDone: 124 } 125 }() 126 err = cmd.Wait() 127 close(waitDone) 128 } 129 return err 130 }