The gobind command is about to get more powerful and able to generate complete and standalone bindings. Platform specific build tags based on GOOS or GOARCH are now meaningless to generate bindings from, so remove them from the test packages. The tags mattered to the reverse bound packages, since the go tool can't build them without the Go wrappers for the imported Java packages. Before this CL, the `android` tag was used to fool the go tool since the host GOOS is unlikely to be android. A fix is to check in the generated Go wrappers, but since the packages are for testing we don't want that. Instead, move the test packages to the testdata directory so the go tool ignores them. Change-Id: I57178e930a400f690ebd7a65758bed894eeb10b0 Reviewed-on: https://go-review.googlesource.com/99315 Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
612 lines
10 KiB
Go
612 lines
10 KiB
Go
// Copyright 2014 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.
|
|
|
|
// Package testpkg contains bound functions for testing the cgo-JNI interface.
|
|
// This is used in tests of golang.org/x/mobile/bind/java.
|
|
package testpkg
|
|
|
|
//go:generate gobind -lang=go -outdir=go_testpkg .
|
|
//go:generate gobind -lang=java -outdir=. .
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"math"
|
|
"os"
|
|
"runtime"
|
|
"syscall"
|
|
"time"
|
|
|
|
"golang.org/x/mobile/asset"
|
|
|
|
"golang.org/x/mobile/bind/testdata/testpkg/secondpkg"
|
|
"golang.org/x/mobile/bind/testdata/testpkg/simplepkg"
|
|
"golang.org/x/mobile/bind/testdata/testpkg/unboundpkg"
|
|
)
|
|
|
|
const (
|
|
AString = "a string"
|
|
AnInt = 7
|
|
ABool = true
|
|
AFloat = 0.12345
|
|
|
|
MinInt32 int32 = math.MinInt32
|
|
MaxInt32 int32 = math.MaxInt32
|
|
MinInt64 = math.MinInt64
|
|
MaxInt64 = math.MaxInt64
|
|
SmallestNonzeroFloat64 = math.SmallestNonzeroFloat64
|
|
MaxFloat64 = math.MaxFloat64
|
|
SmallestNonzeroFloat32 float32 = math.SmallestNonzeroFloat64
|
|
MaxFloat32 float32 = math.MaxFloat32
|
|
Log2E = math.Log2E
|
|
)
|
|
|
|
var (
|
|
StringVar = "a string var"
|
|
IntVar = 77
|
|
StructVar = &S{name: "a struct var"}
|
|
InterfaceVar I
|
|
InterfaceVar2 I2
|
|
NodeVar = &Node{V: "a struct var"}
|
|
)
|
|
|
|
type Nummer interface {
|
|
Num()
|
|
}
|
|
|
|
type I interface {
|
|
F()
|
|
|
|
E() error
|
|
V() int
|
|
VE() (int, error)
|
|
I() I
|
|
S() *S
|
|
StoString(seq *S) string
|
|
|
|
String() string
|
|
}
|
|
|
|
func CallF(i I) {
|
|
i.F()
|
|
}
|
|
|
|
func CallE(i I) error {
|
|
return i.E()
|
|
}
|
|
|
|
func CallV(i I) int {
|
|
return i.V()
|
|
}
|
|
|
|
func CallVE(i I) (int, error) {
|
|
return i.VE()
|
|
}
|
|
|
|
func CallI(i I) I {
|
|
return i
|
|
}
|
|
|
|
func CallS(i I) *S {
|
|
return &S{}
|
|
}
|
|
|
|
var keep []I
|
|
|
|
func Keep(i I) {
|
|
keep = append(keep, i)
|
|
}
|
|
|
|
var numSCollected int
|
|
|
|
type S struct {
|
|
// *S already has a finalizer, so we need another object
|
|
// to count successful collections.
|
|
innerObj *int
|
|
|
|
name string
|
|
}
|
|
|
|
func (s *S) F() {
|
|
fmt.Printf("called F on *S{%s}\n", s.name)
|
|
}
|
|
|
|
func (s *S) String() string {
|
|
return s.name
|
|
}
|
|
|
|
func finalizeInner(a *int) {
|
|
numSCollected++
|
|
}
|
|
|
|
var seq = 0
|
|
|
|
func New() *S {
|
|
s := &S{innerObj: new(int), name: fmt.Sprintf("new%d", seq)}
|
|
runtime.SetFinalizer(s.innerObj, finalizeInner)
|
|
return s
|
|
}
|
|
|
|
func GC() {
|
|
runtime.GC()
|
|
time.Sleep(10 * time.Millisecond)
|
|
runtime.GC()
|
|
}
|
|
|
|
func Add(x, y int) int {
|
|
return x + y
|
|
}
|
|
|
|
func NumSCollected() int {
|
|
return numSCollected
|
|
}
|
|
|
|
func I2Dup(i I2) I2 {
|
|
return i
|
|
}
|
|
|
|
func IDup(i I) I {
|
|
return i
|
|
}
|
|
|
|
func StrDup(s string) string {
|
|
return s
|
|
}
|
|
|
|
func Negate(x bool) bool {
|
|
return !x
|
|
}
|
|
|
|
func Err(s string) error {
|
|
if s != "" {
|
|
return errors.New(s)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func BytesAppend(a []byte, b []byte) []byte {
|
|
return append(a, b...)
|
|
}
|
|
|
|
func AppendToString(str string, someBytes []byte) []byte {
|
|
a := []byte(str)
|
|
fmt.Printf("str=%q (len=%d), someBytes=%v (len=%d)\n", str, len(str), someBytes, len(someBytes))
|
|
return append(a, someBytes...)
|
|
}
|
|
|
|
func UnnamedParams(_, _ int, p0 string) int {
|
|
return len(p0)
|
|
}
|
|
|
|
type Node struct {
|
|
V string
|
|
Next *Node
|
|
Err error
|
|
}
|
|
|
|
func NewNode(name string) *Node {
|
|
return &Node{V: name}
|
|
}
|
|
|
|
func (a *Node) String() string {
|
|
if a == nil {
|
|
return "<end>"
|
|
}
|
|
return a.V + ":" + a.Next.String()
|
|
}
|
|
|
|
type Receiver interface {
|
|
Hello(message string)
|
|
}
|
|
|
|
func Hello(r Receiver, name string) {
|
|
r.Hello(fmt.Sprintf("Hello, %s!\n", name))
|
|
}
|
|
|
|
func GarbageCollect() {
|
|
runtime.GC()
|
|
}
|
|
|
|
type (
|
|
Concrete struct{}
|
|
|
|
Interface interface {
|
|
F()
|
|
}
|
|
)
|
|
|
|
func (_ *Concrete) F() {
|
|
}
|
|
|
|
func NewConcrete() *Concrete {
|
|
return new(Concrete)
|
|
}
|
|
|
|
func ReadAsset() string {
|
|
rc, err := asset.Open("hello.txt")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer rc.Close()
|
|
|
|
b, err := ioutil.ReadAll(rc)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
return string(b)
|
|
}
|
|
|
|
type GoCallback interface {
|
|
VarUpdate()
|
|
}
|
|
|
|
func CallWithCallback(gcb GoCallback) {
|
|
for i := 0; i < 1000; i++ {
|
|
gcb.VarUpdate()
|
|
}
|
|
}
|
|
|
|
type NullTest interface {
|
|
Null() NullTest
|
|
}
|
|
|
|
func NewNullInterface() I {
|
|
return nil
|
|
}
|
|
|
|
func NewNullStruct() *S {
|
|
return nil
|
|
}
|
|
|
|
func CallWithNull(_null NullTest, nuller NullTest) bool {
|
|
return _null == nil && nuller.Null() == nil
|
|
}
|
|
|
|
type Issue20330 struct{}
|
|
|
|
func NewIssue20330() *Issue20330 {
|
|
return new(Issue20330)
|
|
}
|
|
|
|
func (i *Issue20330) CallWithNull(_null *Issue20330) bool {
|
|
return _null == nil
|
|
}
|
|
|
|
type Issue14168 interface {
|
|
F(seq int32)
|
|
}
|
|
|
|
func ReadIntoByteArray(s []byte) (int, error) {
|
|
if len(s) != cap(s) {
|
|
return 0, fmt.Errorf("cap %d != len %d", cap(s), len(s))
|
|
}
|
|
for i := 0; i < len(s); i++ {
|
|
s[i] = byte(i)
|
|
}
|
|
return len(s), nil
|
|
}
|
|
|
|
type B interface {
|
|
B(b []byte)
|
|
}
|
|
|
|
func PassByteArray(b B) {
|
|
b.B([]byte{1, 2, 3, 4})
|
|
}
|
|
|
|
func GoroutineCallback(r Receiver) {
|
|
done := make(chan struct{})
|
|
go func() {
|
|
// Run it multiple times to increase the chance that the goroutine
|
|
// will use different threads for the call. Use a long argument string to
|
|
// make sure the JNI calls take more time.
|
|
for i := 0; i < 100000; i++ {
|
|
r.Hello("HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello")
|
|
}
|
|
close(done)
|
|
}()
|
|
<-done
|
|
}
|
|
|
|
func Hi() {
|
|
fmt.Println("Hi")
|
|
}
|
|
|
|
func Int(x int32) {
|
|
fmt.Println("Received int32", x)
|
|
}
|
|
|
|
type I2 interface {
|
|
Times(v int32) int64
|
|
Error(triggerError bool) error
|
|
|
|
StringError(s string) (string, error)
|
|
}
|
|
|
|
type myI2 struct{}
|
|
|
|
func (_ *myI2) Times(v int32) int64 {
|
|
return int64(v) * 10
|
|
}
|
|
|
|
func (_ *myI2) Error(e bool) error {
|
|
if e {
|
|
return errors.New("some error")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (_ *myI2) StringError(s string) (string, error) {
|
|
return s, nil
|
|
}
|
|
|
|
func CallIError(i I2, triggerError bool) error {
|
|
return i.Error(triggerError)
|
|
}
|
|
|
|
func CallIStringError(i I2, s string) (string, error) {
|
|
return i.StringError(s)
|
|
}
|
|
|
|
func NewI() I2 {
|
|
return &myI2{}
|
|
}
|
|
|
|
var pinnedI = make(map[int32]I2)
|
|
|
|
func RegisterI(idx int32, i I2) {
|
|
pinnedI[idx] = i
|
|
}
|
|
|
|
func UnregisterI(idx int32) {
|
|
delete(pinnedI, idx)
|
|
}
|
|
|
|
func Multiply(idx int32, val int32) int64 {
|
|
i, ok := pinnedI[idx]
|
|
if !ok {
|
|
panic(fmt.Sprintf("unknown I2 with index %d", idx))
|
|
}
|
|
return i.Times(val)
|
|
}
|
|
|
|
func AppendHello(s string) string {
|
|
return fmt.Sprintf("Hello, %s!", s)
|
|
}
|
|
|
|
func ReturnsError(b bool) (string, error) {
|
|
if b {
|
|
return "", errors.New("Error")
|
|
}
|
|
return "OK", nil
|
|
}
|
|
|
|
var collectS2 = make(chan struct{}, 100)
|
|
|
|
func finalizeS(a *S2) {
|
|
collectS2 <- struct{}{}
|
|
}
|
|
|
|
func CollectS2(want, timeoutSec int) int {
|
|
runtime.GC()
|
|
|
|
tick := time.NewTicker(time.Duration(timeoutSec) * time.Second)
|
|
defer tick.Stop()
|
|
|
|
for i := 0; i < want; i++ {
|
|
select {
|
|
case <-collectS2:
|
|
case <-tick.C:
|
|
fmt.Println("CollectS: timed out")
|
|
return i
|
|
}
|
|
}
|
|
return want
|
|
}
|
|
|
|
type S2 struct {
|
|
X, Y float64
|
|
unexported bool
|
|
}
|
|
|
|
func NewS2(x, y float64) *S2 {
|
|
s := &S2{X: x, Y: y}
|
|
runtime.SetFinalizer(s, finalizeS)
|
|
return s
|
|
}
|
|
|
|
func (_ *S2) TryTwoStrings(first, second string) string {
|
|
return first + second
|
|
}
|
|
|
|
func (s *S2) Sum() float64 {
|
|
return s.X + s.Y
|
|
}
|
|
|
|
func CallSSum(s *S2) float64 {
|
|
return s.Sum()
|
|
}
|
|
|
|
// Issue #13033
|
|
type NullFieldStruct struct {
|
|
F *S
|
|
}
|
|
|
|
func NewNullFieldStruct() *NullFieldStruct {
|
|
return &NullFieldStruct{}
|
|
}
|
|
|
|
var (
|
|
ImportedVarI secondpkg.I = NewImportedI()
|
|
ImportedVarS *secondpkg.S = NewImportedS()
|
|
)
|
|
|
|
type (
|
|
ImportedFields struct {
|
|
I secondpkg.I
|
|
S *secondpkg.S
|
|
}
|
|
|
|
ImportedI interface {
|
|
F(_ secondpkg.I)
|
|
}
|
|
|
|
AnSer struct{}
|
|
)
|
|
|
|
func (_ *AnSer) S(_ *secondpkg.S) {
|
|
}
|
|
|
|
func NewImportedFields() *ImportedFields {
|
|
return &ImportedFields{
|
|
I: NewImportedI(),
|
|
S: NewImportedS(),
|
|
}
|
|
}
|
|
|
|
func NewImportedI() secondpkg.I {
|
|
return NewImportedS()
|
|
}
|
|
|
|
func NewImportedS() *secondpkg.S {
|
|
return new(secondpkg.S)
|
|
}
|
|
|
|
func WithImportedI(i secondpkg.I) secondpkg.I {
|
|
return i
|
|
}
|
|
|
|
func WithImportedS(s *secondpkg.S) *secondpkg.S {
|
|
return s
|
|
}
|
|
|
|
func CallImportedI(i secondpkg.I) {
|
|
i.F(0)
|
|
}
|
|
|
|
func NewSer() *AnSer {
|
|
return nil
|
|
}
|
|
|
|
func NewSimpleS() *simplepkg.S {
|
|
return nil
|
|
}
|
|
|
|
func UnboundS(_ *unboundpkg.S) {
|
|
}
|
|
|
|
func UnboundI(_ unboundpkg.I) {
|
|
}
|
|
|
|
type (
|
|
InterfaceDupper interface {
|
|
IDup(i Interface) Interface
|
|
}
|
|
|
|
ConcreteDupper interface {
|
|
CDup(c *Concrete) *Concrete
|
|
}
|
|
)
|
|
|
|
func CallIDupper(d InterfaceDupper) bool {
|
|
var want Interface = new(Concrete)
|
|
got := d.IDup(want)
|
|
return got == want
|
|
}
|
|
|
|
func CallCDupper(d ConcreteDupper) bool {
|
|
want := new(Concrete)
|
|
got := d.CDup(want)
|
|
return got == want
|
|
}
|
|
|
|
type EmptyErrorer interface {
|
|
EmptyError() error
|
|
}
|
|
|
|
func EmptyError() error {
|
|
return errors.New("")
|
|
}
|
|
|
|
func CallEmptyError(c EmptyErrorer) error {
|
|
return c.EmptyError()
|
|
}
|
|
|
|
func Init() {}
|
|
|
|
type InitCaller struct{}
|
|
|
|
func NewInitCaller() *InitCaller {
|
|
return new(InitCaller)
|
|
}
|
|
|
|
func (ic *InitCaller) Init() {}
|
|
|
|
type Issue17073 interface {
|
|
OnError(err error)
|
|
}
|
|
|
|
func ErrorMessage(err error) string {
|
|
return err.Error()
|
|
}
|
|
|
|
var GlobalErr error = errors.New("global err")
|
|
|
|
func IsGlobalErr(err error) bool {
|
|
return GlobalErr == err
|
|
}
|
|
|
|
type S3 struct {
|
|
}
|
|
|
|
type S4 struct {
|
|
I int
|
|
}
|
|
|
|
func NewS4WithInt(i int) *S4 {
|
|
return &S4{i}
|
|
}
|
|
|
|
func NewS4WithFloat(f float64) *S4 {
|
|
return &S4{int(f)}
|
|
}
|
|
|
|
func NewS4WithBoolAndError(b bool) (*S4, error) {
|
|
if b {
|
|
return nil, errors.New("some error")
|
|
}
|
|
return new(S4), nil
|
|
}
|
|
|
|
// Lifted from TestEPIPE in package os.
|
|
func TestSIGPIPE() {
|
|
r, w, err := os.Pipe()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if err := r.Close(); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
_, err = w.Write([]byte("hi"))
|
|
if err == nil {
|
|
panic("unexpected success of Write to broken pipe")
|
|
}
|
|
if pe, ok := err.(*os.PathError); ok {
|
|
err = pe.Err
|
|
}
|
|
if se, ok := err.(*os.SyscallError); ok {
|
|
err = se.Err
|
|
}
|
|
if err != syscall.EPIPE {
|
|
panic(fmt.Errorf("got %v, expected EPIPE", err))
|
|
}
|
|
}
|
|
|
|
// Testpkg is an empty interface with the same name as its package.
|
|
type Testpkg interface{}
|
|
|
|
func ClashingParameterFromOtherPackage(_ *secondpkg.Secondpkg) {}
|