blob: cd7a2ea047cdca31cfa61e952e4c4d9cf0eaaec0 [file] [log] [blame]
// 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 (
"context"
"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) {}
type MyStruct struct {
}
// Test that constructors with incompatible signatures are ignored.
func NewMyStruct(ctx context.Context) *MyStruct {
return nil
}
type Int32Constructed struct{}
// Test that constuctors that clash with the internal proxy constructor
// are skipped.
func NewInt32Constructed(i int32) *Int32Constructed {
return nil
}