aboutsummaryrefslogtreecommitdiff
path: root/misc/swig/swig_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'misc/swig/swig_test.go')
-rw-r--r--misc/swig/swig_test.go149
1 files changed, 149 insertions, 0 deletions
diff --git a/misc/swig/swig_test.go b/misc/swig/swig_test.go
new file mode 100644
index 0000000000..cbe062ae41
--- /dev/null
+++ b/misc/swig/swig_test.go
@@ -0,0 +1,149 @@
+// Copyright 2023 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.
+
+//go:build cgo
+
+package swig
+
+import (
+ "bytes"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "regexp"
+ "strconv"
+ "strings"
+ "sync"
+ "testing"
+)
+
+func TestStdio(t *testing.T) {
+ mustHaveSwig(t)
+ run(t, "testdata/stdio", false)
+}
+
+func TestCall(t *testing.T) {
+ mustHaveSwig(t)
+ mustHaveCxx(t)
+ run(t, "testdata/callback", false, "Call")
+ t.Run("lto", func(t *testing.T) { run(t, "testdata/callback", true, "Call") })
+}
+
+func TestCallback(t *testing.T) {
+ mustHaveSwig(t)
+ mustHaveCxx(t)
+ run(t, "testdata/callback", false, "Callback")
+ t.Run("lto", func(t *testing.T) { run(t, "testdata/callback", true, "Callback") })
+}
+
+func run(t *testing.T, dir string, lto bool, args ...string) {
+ runArgs := append([]string{"run", "."}, args...)
+ cmd := exec.Command("go", runArgs...)
+ cmd.Dir = dir
+ if lto {
+ const cflags = "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option"
+ cmd.Env = append(cmd.Environ(),
+ "CGO_CFLAGS="+cflags,
+ "CGO_CXXFLAGS="+cflags,
+ "CGO_LDFLAGS="+cflags)
+ }
+ out, err := cmd.CombinedOutput()
+ if string(out) != "OK\n" {
+ t.Errorf("%s", string(out))
+ }
+ if err != nil {
+ t.Errorf("%s", err)
+ }
+}
+
+func mustHaveCxx(t *testing.T) {
+ // Ask the go tool for the CXX it's configured to use.
+ cxx, err := exec.Command("go", "env", "CXX").CombinedOutput()
+ if err != nil {
+ t.Fatalf("go env CXX failed: %s", err)
+ }
+ cxx = bytes.TrimSuffix(cxx, []byte("\n"))
+ // TODO(austin): "go env CXX" can return a quoted list. Use quoted.Split.
+ p, err := exec.LookPath(string(cxx))
+ if p == "" {
+ t.Skipf("test requires C++ compiler, but failed to find %s: %s", string(cxx), err)
+ }
+}
+
+var (
+ swigOnce sync.Once
+ haveSwig bool
+)
+
+func mustHaveSwig(t *testing.T) {
+ swigOnce.Do(func() {
+ mustHaveSwigOnce(t)
+ haveSwig = true
+ })
+ // The first call will skip t with a nice message. On later calls, we just skip.
+ if !haveSwig {
+ t.Skip("swig not found")
+ }
+}
+
+func mustHaveSwigOnce(t *testing.T) {
+ swig, err := exec.LookPath("swig")
+ if err != nil {
+ t.Skipf("swig not in PATH: %s", err)
+ }
+
+ // Check that swig was installed with Go support by checking
+ // that a go directory exists inside the swiglib directory.
+ // See https://golang.org/issue/23469.
+ output, err := exec.Command(swig, "-go", "-swiglib").Output()
+ if err != nil {
+ t.Skip("swig is missing Go support")
+ }
+ swigDir := strings.TrimSpace(string(output))
+
+ _, err = os.Stat(filepath.Join(swigDir, "go"))
+ if err != nil {
+ t.Skip("swig is missing Go support")
+ }
+
+ // Check that swig has a new enough version.
+ // See https://golang.org/issue/22858.
+ out, err := exec.Command(swig, "-version").CombinedOutput()
+ if err != nil {
+ t.Skipf("failed to get swig version:%s\n%s", err, string(out))
+ }
+
+ re := regexp.MustCompile(`[vV]ersion +(\d+)([.]\d+)?([.]\d+)?`)
+ matches := re.FindSubmatch(out)
+ if matches == nil {
+ // Can't find version number; hope for the best.
+ t.Logf("failed to find swig version, continuing")
+ return
+ }
+
+ var parseError error
+ atoi := func(s string) int {
+ x, err := strconv.Atoi(s)
+ if err != nil && parseError == nil {
+ parseError = err
+ }
+ return x
+ }
+ var major, minor, patch int
+ major = atoi(string(matches[1]))
+ if len(matches[2]) > 0 {
+ minor = atoi(string(matches[2][1:]))
+ }
+ if len(matches[3]) > 0 {
+ patch = atoi(string(matches[3][1:]))
+ }
+ if parseError != nil {
+ t.Logf("error parsing swig version %q, continuing anyway: %s", string(matches[0]), parseError)
+ return
+ }
+ t.Logf("found swig version %d.%d.%d", major, minor, patch)
+ if major < 3 || (major == 3 && minor == 0 && patch < 6) {
+ t.Skip("test requires swig 3.0.6 or later")
+ }
+}