go.mobile/bind/java: tests of object reference tracking

LGTM=adonovan
R=adonovan
CC=golang-codereviews
https://golang.org/cl/112700044
This commit is contained in:
David Crawshaw 2014-07-31 08:25:23 -04:00
Родитель 6a88edec71
Коммит 5487fc8103
6 изменённых файлов: 426 добавлений и 0 удалений

64
bind/java/SeqTest.java Normal file
Просмотреть файл

@ -0,0 +1,64 @@
package go;
import go.testpkg.Testpkg;
import junit.framework.TestCase;
public class SeqTest extends TestCase {
static {
Go.init(null);
}
public void testAdd() {
long res = Testpkg.instance.Add(3, 4);
assertEquals("Unexpected arithmetic failure", 7, res);
}
public void testGoRefGC() {
Testpkg.S s = Testpkg.instance.New();
System.gc();
Testpkg.instance.GC();
long collected = Testpkg.instance.NumSCollected();
assertEquals("Only S should be pinned", 0, collected);
s = null;
System.gc();
Testpkg.instance.GC();
collected = Testpkg.instance.NumSCollected();
assertEquals("S should be collected", 1, collected);
}
boolean finalizedAnI;
private class AnI extends Testpkg.I.Stub {
boolean called;
public void F() {
called = true;
}
@Override
public void finalize() throws Throwable {
finalizedAnI = true;
super.finalize();
}
}
public void testJavaRefGC() {
finalizedAnI = false;
AnI obj = new AnI();
Testpkg.instance.Call(obj);
assertTrue("want F to be called", obj.called);
obj = null;
Testpkg.instance.GC();
System.gc();
assertTrue("want obj to be collected", finalizedAnI);
}
public void testJavaRefKeep() {
finalizedAnI = false;
AnI obj = new AnI();
Testpkg.instance.Keep(obj);
obj = null;
System.gc();
assertFalse("want obj to be kept live by Go", finalizedAnI);
}
}

17
bind/java/javatest.go Normal file
Просмотреть файл

@ -0,0 +1,17 @@
// 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.
//+build ignore
package main
import (
"code.google.com/p/go.mobile/app"
_ "code.google.com/p/go.mobile/bind/java/testpkg/go_testpkg"
)
func main() {
app.Run()
}

28
bind/java/test.bash Executable file
Просмотреть файл

@ -0,0 +1,28 @@
#!/usr/bin/env bash
# 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.
# TODO(crawshaw):
# This script does not yet run the tests, it just sets them
# up so they can be run by Android Studio.
set -e
if [ ! -f test.bash ]; then
echo 'test.bash must be run from $GOPATH/src/code.google.com/p/go.mobile/bind/java'
exit 1
fi
if [ -z "$ANDROID_APP" ]; then
echo 'ERROR: Environment variable ANDROID_APP is unset.'
exit 1
fi
mkdir -p $ANDROID_APP/src/main/jniLibs/armeabi \
$ANDROID_APP/src/main/java/go/testpkg
ln -sf $PWD/*.java $ANDROID_APP/src/main/java/go
ln -sf $PWD/testpkg/Testpkg.java $ANDROID_APP/src/main/java/go/testpkg
CGO_ENABLED=1 GOOS=android GOARCH=arm GOARM=7 \
go build -ldflags="-shared" javatest.go
mv -f javatest $ANDROID_APP/src/main/jniLibs/armeabi/libgojni.so

Просмотреть файл

@ -0,0 +1,160 @@
// Java Package testpkg is a proxy for talking to a Go program.
//
// File is generated by gobind. Do not edit.
// Or do, I'm a comment, not a cop.
package go.testpkg;
import go.Seq;
public final class Testpkg {
public long Add(long x, long y) {
go.Seq _in = new go.Seq();
go.Seq _out = new go.Seq();
long _result;
_in.writeInt(x);
_in.writeInt(y);
Seq.send(DESCRIPTOR, CALL_Add, _in, _out);
_result = _out.readInt();
return _result;
}
public void Call(I i) {
go.Seq _in = new go.Seq();
go.Seq _out = new go.Seq();
_in.writeRef(i.ref());
Seq.send(DESCRIPTOR, CALL_Call, _in, _out);
}
public void GC() {
go.Seq _in = new go.Seq();
go.Seq _out = new go.Seq();
Seq.send(DESCRIPTOR, CALL_GC, _in, _out);
}
public interface I extends go.Seq.Object {
public void F();
public static abstract class Stub implements I {
static final String DESCRIPTOR = "go.testpkg.I";
private final go.Seq.Ref ref;
public Stub() {
ref = go.Seq.createRef(this);
}
public go.Seq.Ref ref() { return ref; }
public void call(int code, go.Seq in, go.Seq out) {
switch (code) {
case Proxy.CALL_F: {
// TODO(crawshaw): handle catching a Exception
this.F();
return;
}
default:
throw new RuntimeException("unknown code: "+ code);
}
}
}
static final class Proxy implements I {
static final String DESCRIPTOR = Stub.DESCRIPTOR;
private go.Seq.Ref ref;
Proxy(go.Seq.Ref ref) { this.ref = ref; }
public go.Seq.Ref ref() { return ref; }
public void call(int code, go.Seq in, go.Seq out) {
throw new RuntimeException("cycle: cannot call proxy");
}
public void F() {
go.Seq _in = new go.Seq();
go.Seq _out = new go.Seq();
Seq.send(DESCRIPTOR, CALL_F, _in, _out);
}
static final int CALL_F = 0x0a01;
}
}
public void Keep(I i) {
go.Seq _in = new go.Seq();
go.Seq _out = new go.Seq();
_in.writeRef(i.ref());
Seq.send(DESCRIPTOR, CALL_Keep, _in, _out);
}
public S New() {
go.Seq _in = new go.Seq();
go.Seq _out = new go.Seq();
S _result;
Seq.send(DESCRIPTOR, CALL_New, _in, _out);
_result = new S(_out.readRef());
return _result;
}
public long NumSCollected() {
go.Seq _in = new go.Seq();
go.Seq _out = new go.Seq();
long _result;
Seq.send(DESCRIPTOR, CALL_NumSCollected, _in, _out);
_result = _out.readInt();
return _result;
}
public static final class S implements go.Seq.Object {
private static final String DESCRIPTOR = "go.testpkg.S";
private static final int CALL_F = 0x0c00;
private go.Seq.Ref ref;
private S(go.Seq.Ref ref) { this.ref = ref; }
public go.Seq.Ref ref() { return ref; }
public void call(int code, go.Seq in, go.Seq out) {
throw new RuntimeException("cycle: cannot call concrete proxy");
}
public void F() {
go.Seq _in = new go.Seq();
go.Seq _out = new go.Seq();
_in.writeRef(ref);
Seq.send(DESCRIPTOR, CALL_F, _in, _out);
}
@Override public boolean equals(Object o) {
if (o == null || !(o instanceof S)) {
return false;
}
S that = (S)o;
return true;
}
@Override public int hashCode() {
return java.util.Arrays.hashCode(new Object[] {});
}
@Override public String toString() {
// TODO(crawshaw): use String() string if it is defined.
StringBuilder b = new StringBuilder();
b.append("S").append("{");
return b.append("}").toString();
}
}
private static final int CALL_Add = 1;
private static final int CALL_Call = 2;
private static final int CALL_GC = 3;
private static final int CALL_Keep = 4;
private static final int CALL_New = 5;
private static final int CALL_NumSCollected = 6;
private static final String DESCRIPTOR = "testpkg";
public static Testpkg instance = new Testpkg();
}

Просмотреть файл

@ -0,0 +1,99 @@
// Package go_testpkg is an autogenerated binder stub for package testpkg.
//
// File is generated by gobind. Do not edit.
// Or do, I'm a comment, not a cop.
package go_testpkg
import (
"code.google.com/p/go.mobile/bind/java/testpkg"
"code.google.com/p/go.mobile/bind/seq"
)
func proxy_Add(out, in *seq.Buffer) {
param_x := in.ReadInt()
param_y := in.ReadInt()
res := testpkg.Add(param_x, param_y)
// TODO out.WriteNoException();
out.WriteInt(res)
}
func proxy_Call(out, in *seq.Buffer) {
var param_i testpkg.I
param_i_ref := in.ReadRef()
if param_i_ref.Num < 0 {
param_i = param_i_ref.Get().(testpkg.I)
} else {
param_i = (*proxyI)(param_i_ref)
}
testpkg.Call(param_i)
// TODO out.WriteNoException();
}
func proxy_GC(out, in *seq.Buffer) {
testpkg.GC()
// TODO out.WriteNoException();
}
const (
proxyIDescriptor = "go.testpkg.I"
proxyIFCode = 0x0a01
)
type proxyI seq.Ref
func (p *proxyI) F() {
out := new(seq.Buffer)
//out.WriteRef((*seq.Ref)(p))
seq.Transact((*seq.Ref)(p), proxyIFCode, out)
}
func proxy_Keep(out, in *seq.Buffer) {
var param_i testpkg.I
param_i_ref := in.ReadRef()
if param_i_ref.Num < 0 {
param_i = param_i_ref.Get().(testpkg.I)
} else {
param_i = (*proxyI)(param_i_ref)
}
testpkg.Keep(param_i)
// TODO out.WriteNoException();
}
func proxy_New(out, in *seq.Buffer) {
res := testpkg.New()
// TODO out.WriteNoException();
out.WriteGoRef(res)
}
func proxy_NumSCollected(out, in *seq.Buffer) {
res := testpkg.NumSCollected()
// TODO out.WriteNoException();
out.WriteInt(res)
}
const (
proxySDescriptor = "go.testpkg.S"
proxySFCode = 0x0c00
)
type proxyS seq.Ref
func proxySF(out, in *seq.Buffer) {
ref := in.ReadRef()
v := ref.Get().(*testpkg.S)
v.F()
// TODO out.WriteNoException();
}
func init() {
seq.Register(proxySDescriptor, proxySFCode, proxySF)
}
func init() {
seq.Register("testpkg", 1, proxy_Add)
seq.Register("testpkg", 2, proxy_Call)
seq.Register("testpkg", 3, proxy_GC)
seq.Register("testpkg", 4, proxy_Keep)
seq.Register("testpkg", 5, proxy_New)
seq.Register("testpkg", 6, proxy_NumSCollected)
}

Просмотреть файл

@ -0,0 +1,58 @@
// Package testpkg contains bound functions for testing the cgo-JNI interface.
package testpkg
import (
"fmt"
"runtime"
"time"
)
type I interface {
F()
}
func Call(i I) {
i.F()
}
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
}
func (*S) F() {
fmt.Println("called F on *S")
}
func finalizeInner(*int) {
numSCollected++
}
func New() *S {
s := &S{innerObj: new(int)}
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
}