seq, java: fix allocation bug in empty strings and test

Fixes golang/go#9271.

Change-Id: I57dcd11ae5afdc23bc9b1a0945d0789c9feeefb1
Reviewed-on: https://go-review.googlesource.com/1423
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This commit is contained in:
David Crawshaw 2014-12-12 08:05:05 -05:00
parent 4ab8f01b53
commit f19599ac73
6 changed files with 60 additions and 13 deletions

View File

@ -38,6 +38,20 @@ public class SeqTest extends TestCase {
assertEquals("Strings should match", want, got);
}
public void testNilErr() throws Exception {
Testpkg.Err(null); // returns nil, no exception
}
public void testErr() {
String msg = "Go errors are dropped into the confusing space of exceptions";
try {
Testpkg.Err(msg);
fail("expected non-nil error to be turned into an exception");
} catch (Exception e) {
assertEquals("messages should match", msg, e.getMessage());
}
}
public void testGoRefGC() {
Testpkg.S s = Testpkg.New();
runGC();

View File

@ -197,6 +197,9 @@ Java_go_Seq_readFloat64(JNIEnv *env, jobject obj) {
JNIEXPORT jstring JNICALL
Java_go_Seq_readUTF16(JNIEnv *env, jobject obj) {
int32_t size = *MEM_READ(obj, int32_t);
if (size == 0) {
return NULL;
}
return (*env)->NewString(env, (jchar*)mem_read(env, obj, 2*size), size);
}

View File

@ -27,6 +27,17 @@ public abstract class Testpkg {
Seq.send(DESCRIPTOR, CALL_Call, _in, _out);
}
public static void Err(String s) throws Exception {
go.Seq _in = new go.Seq();
go.Seq _out = new go.Seq();
_in.writeUTF16(s);
Seq.send(DESCRIPTOR, CALL_Err, _in, _out);
String _err = _out.readUTF16();
if (_err != null) {
throw new Exception(_err);
}
}
public static void GC() {
go.Seq _in = new go.Seq();
go.Seq _out = new go.Seq();
@ -161,10 +172,11 @@ public abstract class Testpkg {
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 int CALL_StrDup = 7;
private static final int CALL_Err = 3;
private static final int CALL_GC = 4;
private static final int CALL_Keep = 5;
private static final int CALL_New = 6;
private static final int CALL_NumSCollected = 7;
private static final int CALL_StrDup = 8;
private static final String DESCRIPTOR = "testpkg";
}

View File

@ -27,6 +27,16 @@ func proxy_Call(out, in *seq.Buffer) {
testpkg.Call(param_i)
}
func proxy_Err(out, in *seq.Buffer) {
param_s := in.ReadUTF16()
err := testpkg.Err(param_s)
if err == nil {
out.WriteUTF16("")
} else {
out.WriteUTF16(err.Error())
}
}
func proxy_GC(out, in *seq.Buffer) {
testpkg.GC()
}
@ -90,9 +100,10 @@ func proxy_StrDup(out, in *seq.Buffer) {
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)
seq.Register("testpkg", 7, proxy_StrDup)
seq.Register("testpkg", 3, proxy_Err)
seq.Register("testpkg", 4, proxy_GC)
seq.Register("testpkg", 5, proxy_Keep)
seq.Register("testpkg", 6, proxy_New)
seq.Register("testpkg", 7, proxy_NumSCollected)
seq.Register("testpkg", 8, proxy_StrDup)
}

View File

@ -2,6 +2,7 @@
package testpkg
import (
"errors"
"fmt"
"runtime"
"time"
@ -60,3 +61,10 @@ func NumSCollected() int {
func StrDup(s string) string {
return s
}
func Err(s string) error {
if s != "" {
return errors.New(s)
}
return nil
}

View File

@ -35,9 +35,8 @@ func writeUint16(b []byte, v rune) {
func (b *Buffer) WriteUTF16(s string) {
// first 4 bytes is the length, as int32. written last.
// next n bytes is utf-16 string.
if len(b.Data)-b.Offset < 4*len(s) {
b.grow(4 * len(s)) // worst case estimate, everything is surrogate pair
if len(b.Data)-b.Offset < 4+4*len(s) {
b.grow(4 + 4*len(s)) // worst case estimate, everything is surrogate pair
}
data := b.Data[b.Offset+4:]
n := 0