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