github.com/SahandAslani/gomobile@v0.0.0-20210909130135-2cb2d44c09b2/cmd/gobind/gobind_test.go (about)

     1  // Copyright 2016 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 main
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"io/ioutil"
    11  	"log"
    12  	"os"
    13  	"os/exec"
    14  	"runtime"
    15  	"strings"
    16  	"testing"
    17  
    18  	"golang.org/x/tools/go/packages/packagestest"
    19  )
    20  
    21  var tests = []struct {
    22  	name string
    23  	lang string
    24  	pkg  string
    25  	goos string
    26  	// reverse is true if the test needs to generate reverse bindings using
    27  	// external tools such as javap.
    28  	reverse bool
    29  }{
    30  	{
    31  		name: "ObjC-Testpkg",
    32  		lang: "objc",
    33  		pkg:  "github.com/SahandAslani/gomobile/bind/testdata/testpkg",
    34  	},
    35  	{
    36  		name: "Java-Testpkg",
    37  		lang: "java",
    38  		pkg:  "github.com/SahandAslani/gomobile/bind/testdata/testpkg",
    39  	},
    40  	{
    41  		name: "Go-Testpkg",
    42  		lang: "go",
    43  		pkg:  "github.com/SahandAslani/gomobile/bind/testdata/testpkg",
    44  	},
    45  	{
    46  		name:    "Java-Javapkg",
    47  		lang:    "java",
    48  		pkg:     "github.com/SahandAslani/gomobile/bind/testdata/testpkg/javapkg",
    49  		goos:    "android",
    50  		reverse: true,
    51  	},
    52  	{
    53  		name:    "Go-Javapkg",
    54  		lang:    "go",
    55  		pkg:     "github.com/SahandAslani/gomobile/bind/testdata/testpkg/javapkg",
    56  		goos:    "android",
    57  		reverse: true,
    58  	},
    59  	{
    60  		name: "Go-Cgopkg",
    61  		lang: "go,java,objc",
    62  		pkg:  "github.com/SahandAslani/gomobile/bind/testdata/cgopkg",
    63  		goos: "android",
    64  	},
    65  }
    66  
    67  var gobindBin string
    68  
    69  func TestMain(m *testing.M) {
    70  	os.Exit(testMain(m))
    71  }
    72  
    73  func testMain(m *testing.M) int {
    74  	bin, err := ioutil.TempFile("", "*.exe")
    75  	if err != nil {
    76  		log.Fatal(err)
    77  	}
    78  	bin.Close()
    79  	defer os.Remove(bin.Name())
    80  	if runtime.GOOS != "android" {
    81  		if out, err := exec.Command("go", "build", "-o", bin.Name(), "github.com/SahandAslani/gomobile/cmd/gobind").CombinedOutput(); err != nil {
    82  			log.Fatalf("gobind build failed: %v: %s", err, out)
    83  		}
    84  		gobindBin = bin.Name()
    85  	}
    86  	return m.Run()
    87  }
    88  
    89  func runGobind(t testing.TB, lang, pkg, goos string, exported *packagestest.Exported) error {
    90  	if gobindBin == "" {
    91  		t.Skipf("gobind is not available on %s", runtime.GOOS)
    92  	}
    93  	cmd := exec.Command(gobindBin, "-lang", lang, pkg)
    94  	cmd.Dir = exported.Config.Dir
    95  	cmd.Env = exported.Config.Env
    96  	if goos != "" {
    97  		// Add CGO_ENABLED=1 explicitly since Cgo is disabled when GOOS is different from host OS.
    98  		cmd.Env = append(cmd.Env, "GOOS="+goos, "CGO_ENABLED=1")
    99  	}
   100  	if out, err := cmd.CombinedOutput(); err != nil {
   101  		var cmd string
   102  		for _, env := range exported.Config.Env {
   103  			if strings.HasPrefix(env, "GO111MODULE=") {
   104  				cmd = env + " "
   105  				break
   106  			}
   107  		}
   108  		cmd += fmt.Sprintf("gobind -lang %s %s", lang, pkg)
   109  		return fmt.Errorf("%s failed: %v: %s", cmd, err, out)
   110  	}
   111  	return nil
   112  }
   113  
   114  func TestGobind(t *testing.T) { packagestest.TestAll(t, testGobind) }
   115  func testGobind(t *testing.T, exporter packagestest.Exporter) {
   116  	_, javapErr := exec.LookPath("javap")
   117  	exported := packagestest.Export(t, exporter, []packagestest.Module{{
   118  		Name:  "github.com/SahandAslani/gomobile",
   119  		Files: packagestest.MustCopyFileTree("../.."),
   120  	}})
   121  	defer exported.Cleanup()
   122  
   123  	for _, test := range tests {
   124  		t.Run(test.name, func(t *testing.T) {
   125  			if exporter == packagestest.Modules && test.reverse {
   126  				t.Skip("reverse binding does't work with Go modules")
   127  			}
   128  			if test.reverse && javapErr != nil {
   129  				t.Skip("reverse bind test requires javap which is not available")
   130  			}
   131  			if err := runGobind(t, test.lang, test.pkg, test.goos, exported); err != nil {
   132  				t.Error(err)
   133  			}
   134  		})
   135  	}
   136  }
   137  
   138  func TestDocs(t *testing.T) { packagestest.TestAll(t, testDocs) }
   139  func testDocs(t *testing.T, exporter packagestest.Exporter) {
   140  	if gobindBin == "" {
   141  		t.Skipf("gobind is not available on %s", runtime.GOOS)
   142  	}
   143  
   144  	const docsrc = `
   145  package doctest
   146  
   147  // This is a comment.
   148  type Struct struct{
   149  }`
   150  
   151  	exported := packagestest.Export(t, exporter, []packagestest.Module{
   152  		{
   153  			Name: "example.com/doctest",
   154  			Files: map[string]interface{}{
   155  				"doc.go": docsrc,
   156  			},
   157  		},
   158  		{
   159  			// gobind requires github.com/SahandAslani/gomobile to generate code for reverse bindings.
   160  			Name:  "github.com/SahandAslani/gomobile",
   161  			Files: packagestest.MustCopyFileTree("../.."),
   162  		},
   163  	})
   164  	defer exported.Cleanup()
   165  
   166  	const comment = "This is a comment."
   167  	for _, lang := range []string{"java", "objc"} {
   168  		cmd := exec.Command(gobindBin, "-lang", lang, "example.com/doctest")
   169  		cmd.Dir = exported.Config.Dir
   170  		cmd.Env = exported.Config.Env
   171  		out, err := cmd.CombinedOutput()
   172  		if err != nil {
   173  			t.Errorf("gobind -lang %s failed: %v: %s", lang, err, out)
   174  			continue
   175  		}
   176  		if bytes.Index(out, []byte(comment)) == -1 {
   177  			t.Errorf("gobind output for language %s did not contain the comment %q", lang, comment)
   178  		}
   179  	}
   180  }
   181  
   182  func BenchmarkGobind(b *testing.B) {
   183  	packagestest.BenchmarkAll(b, benchmarkGobind)
   184  }
   185  
   186  func benchmarkGobind(b *testing.B, exporter packagestest.Exporter) {
   187  	_, javapErr := exec.LookPath("javap")
   188  	exported := packagestest.Export(b, exporter, []packagestest.Module{{
   189  		Name:  "github.com/SahandAslani/gomobile",
   190  		Files: packagestest.MustCopyFileTree("../.."),
   191  	}})
   192  	defer exported.Cleanup()
   193  
   194  	for _, test := range tests {
   195  		b.Run(test.name, func(b *testing.B) {
   196  			if exporter == packagestest.Modules && test.reverse {
   197  				b.Skip("reverse binding does't work with Go modules")
   198  			}
   199  			if test.reverse && javapErr != nil {
   200  				b.Skip("reverse bind test requires javap which is not available")
   201  			}
   202  			for i := 0; i < b.N; i++ {
   203  				if err := runGobind(b, test.lang, test.pkg, test.goos, exported); err != nil {
   204  					b.Error(err)
   205  				}
   206  			}
   207  		})
   208  	}
   209  }