]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/cgo/internal/swig/swig_test.go
misc/swig: restructure as a driver
[gostls13.git] / src / cmd / cgo / internal / swig / swig_test.go
1 // Copyright 2023 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 swig
6
7 import (
8         "cmd/internal/quoted"
9         "internal/testenv"
10         "os"
11         "os/exec"
12         "path/filepath"
13         "regexp"
14         "strconv"
15         "strings"
16         "sync"
17         "testing"
18 )
19
20 func TestStdio(t *testing.T) {
21         testenv.MustHaveCGO(t)
22         mustHaveSwig(t)
23         run(t, "testdata/stdio", false)
24 }
25
26 func TestCall(t *testing.T) {
27         testenv.MustHaveCGO(t)
28         mustHaveSwig(t)
29         mustHaveCxx(t)
30         run(t, "testdata/callback", false, "Call")
31         t.Run("lto", func(t *testing.T) { run(t, "testdata/callback", true, "Call") })
32 }
33
34 func TestCallback(t *testing.T) {
35         testenv.MustHaveCGO(t)
36         mustHaveSwig(t)
37         mustHaveCxx(t)
38         run(t, "testdata/callback", false, "Callback")
39         t.Run("lto", func(t *testing.T) { run(t, "testdata/callback", true, "Callback") })
40 }
41
42 func run(t *testing.T, dir string, lto bool, args ...string) {
43         runArgs := append([]string{"run", "."}, args...)
44         cmd := exec.Command("go", runArgs...)
45         cmd.Dir = dir
46         if lto {
47                 const cflags = "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option"
48                 cmd.Env = append(cmd.Environ(),
49                         "CGO_CFLAGS="+cflags,
50                         "CGO_CXXFLAGS="+cflags,
51                         "CGO_LDFLAGS="+cflags)
52         }
53         out, err := cmd.CombinedOutput()
54         if string(out) != "OK\n" {
55                 t.Errorf("%s", string(out))
56         }
57         if err != nil {
58                 t.Errorf("%s", err)
59         }
60 }
61
62 func mustHaveCxx(t *testing.T) {
63         // Ask the go tool for the CXX it's configured to use.
64         cxx, err := exec.Command("go", "env", "CXX").CombinedOutput()
65         if err != nil {
66                 t.Fatalf("go env CXX failed: %s", err)
67         }
68         args, err := quoted.Split(string(cxx))
69         if err != nil {
70                 t.Skipf("could not parse 'go env CXX' output %q: %s", string(cxx), err)
71         }
72         if len(args) == 0 {
73                 t.Skip("no C++ compiler")
74         }
75         testenv.MustHaveExecPath(t, string(args[0]))
76 }
77
78 var (
79         swigOnce sync.Once
80         haveSwig bool
81 )
82
83 func mustHaveSwig(t *testing.T) {
84         swigOnce.Do(func() {
85                 mustHaveSwigOnce(t)
86                 haveSwig = true
87         })
88         // The first call will skip t with a nice message. On later calls, we just skip.
89         if !haveSwig {
90                 t.Skip("swig not found")
91         }
92 }
93
94 func mustHaveSwigOnce(t *testing.T) {
95         swig, err := exec.LookPath("swig")
96         if err != nil {
97                 t.Skipf("swig not in PATH: %s", err)
98         }
99
100         // Check that swig was installed with Go support by checking
101         // that a go directory exists inside the swiglib directory.
102         // See https://golang.org/issue/23469.
103         output, err := exec.Command(swig, "-go", "-swiglib").Output()
104         if err != nil {
105                 t.Skip("swig is missing Go support")
106         }
107         swigDir := strings.TrimSpace(string(output))
108
109         _, err = os.Stat(filepath.Join(swigDir, "go"))
110         if err != nil {
111                 t.Skip("swig is missing Go support")
112         }
113
114         // Check that swig has a new enough version.
115         // See https://golang.org/issue/22858.
116         out, err := exec.Command(swig, "-version").CombinedOutput()
117         if err != nil {
118                 t.Skipf("failed to get swig version:%s\n%s", err, string(out))
119         }
120
121         re := regexp.MustCompile(`[vV]ersion +(\d+)([.]\d+)?([.]\d+)?`)
122         matches := re.FindSubmatch(out)
123         if matches == nil {
124                 // Can't find version number; hope for the best.
125                 t.Logf("failed to find swig version, continuing")
126                 return
127         }
128
129         var parseError error
130         atoi := func(s string) int {
131                 x, err := strconv.Atoi(s)
132                 if err != nil && parseError == nil {
133                         parseError = err
134                 }
135                 return x
136         }
137         var major, minor, patch int
138         major = atoi(string(matches[1]))
139         if len(matches[2]) > 0 {
140                 minor = atoi(string(matches[2][1:]))
141         }
142         if len(matches[3]) > 0 {
143                 patch = atoi(string(matches[3][1:]))
144         }
145         if parseError != nil {
146                 t.Logf("error parsing swig version %q, continuing anyway: %s", string(matches[0]), parseError)
147                 return
148         }
149         t.Logf("found swig version %d.%d.%d", major, minor, patch)
150         if major < 3 || (major == 3 && minor == 0 && patch < 6) {
151                 t.Skip("test requires swig 3.0.6 or later")
152         }
153 }