| // 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 go; |
| |
| import android.test.InstrumentationTestCase; |
| import android.test.MoreAsserts; |
| |
| import java.util.Arrays; |
| import java.util.Random; |
| |
| import testpkg.*; |
| import secondpkg.Secondpkg; |
| |
| public class SeqTest extends InstrumentationTestCase { |
| public SeqTest() { |
| } |
| |
| public void testConst() { |
| assertEquals("const String", "a string", Testpkg.AString); |
| assertEquals("const Int", 7, Testpkg.AnInt); |
| assertEquals("const Bool", true, Testpkg.ABool); |
| assertEquals("const Float", 0.12345, Testpkg.AFloat, 0.0001); |
| |
| assertEquals("const MinInt32", -1<<31, Testpkg.MinInt32); |
| assertEquals("const MaxInt32", (1<<31) - 1, Testpkg.MaxInt32); |
| assertEquals("const MinInt64", -1L<<63, Testpkg.MinInt64); |
| assertEquals("const MaxInt64", (1L<<63) - 1, Testpkg.MaxInt64); |
| assertEquals("const SmallestNonzeroFloat64", 4.940656458412465441765687928682213723651e-324, Testpkg.SmallestNonzeroFloat64, 1e-323); |
| assertEquals("const MaxFloat64", 1.797693134862315708145274237317043567981e+308, Testpkg.MaxFloat64, 0.0001); |
| assertEquals("const SmallestNonzeroFloat32", 1.401298464324817070923729583289916131280e-45, Testpkg.SmallestNonzeroFloat32, 1e-44); |
| assertEquals("const MaxFloat32", 3.40282346638528859811704183484516925440e+38, Testpkg.MaxFloat32, 0.0001); |
| assertEquals("const Log2E", 1/0.693147180559945309417232121458176568075500134360255254120680009, Testpkg.Log2E, 0.0001); |
| } |
| |
| public void testRefMap() { |
| // Ensure that the RefMap.live count is kept in sync |
| // even a particular reference number is removed and |
| // added again |
| Seq.RefMap m = new Seq.RefMap(); |
| Seq.Ref r = new Seq.Ref(1, null); |
| m.put(r.refnum, r); |
| m.remove(r.refnum); |
| m.put(r.refnum, r); |
| // Force the RefMap to grow, to activate the sanity |
| // checking of the live count in RefMap.grow. |
| for (int i = 2; i < 24; i++) { |
| m.put(i, new Seq.Ref(i, null)); |
| } |
| } |
| |
| public void testVar() { |
| assertEquals("var StringVar", "a string var", Testpkg.getStringVar()); |
| |
| String newStringVar = "a new string var"; |
| Testpkg.setStringVar(newStringVar); |
| assertEquals("var StringVar", newStringVar, Testpkg.getStringVar()); |
| |
| assertEquals("var IntVar", 77, Testpkg.getIntVar()); |
| |
| long newIntVar = 777; |
| Testpkg.setIntVar(newIntVar); |
| assertEquals("var IntVar", newIntVar, Testpkg.getIntVar()); |
| |
| S s0 = Testpkg.getStructVar(); |
| assertEquals("var StructVar", "a struct var", s0.string()); |
| S s1 = Testpkg.new_(); |
| Testpkg.setStructVar(s1); |
| assertEquals("var StructVar", s1.string(), Testpkg.getStructVar().string()); |
| |
| AnI obj = new AnI(); |
| obj.name = "this is an I"; |
| Testpkg.setInterfaceVar(obj); |
| assertEquals("var InterfaceVar", obj.string(), Testpkg.getInterfaceVar().string()); |
| } |
| |
| public void testAssets() { |
| // Make sure that a valid context is set before reading assets |
| Seq.setContext(getInstrumentation().getContext()); |
| String want = "Hello, Assets.\n"; |
| String got = Testpkg.readAsset(); |
| assertEquals("Asset read", want, got); |
| } |
| |
| public void testAdd() { |
| long res = Testpkg.add(3, 4); |
| assertEquals("Unexpected arithmetic failure", 7, res); |
| } |
| |
| public void testBool() { |
| assertTrue(Testpkg.negate(false)); |
| assertFalse(Testpkg.negate(true)); |
| } |
| |
| public void testShortString() { |
| String want = "a short string"; |
| String got = Testpkg.strDup(want); |
| assertEquals("Strings should match", want, got); |
| |
| want = ""; |
| got = Testpkg.strDup(want); |
| assertEquals("Strings should match (empty string)", want, got); |
| |
| got = Testpkg.strDup(null); |
| assertEquals("Strings should match (null string)", want, got); |
| } |
| |
| public void testLongString() { |
| StringBuilder b = new StringBuilder(); |
| for (int i = 0; i < 128*1024; i++) { |
| b.append("0123456789"); |
| } |
| String want = b.toString(); |
| String got = Testpkg.strDup(want); |
| assertEquals("Strings should match", want, got); |
| } |
| |
| public void testUnicode() { |
| String[] tests = new String[]{ |
| "abcxyz09{}", |
| "Hello, 世界", |
| "\uffff\uD800\uDC00\uD800\uDC01\uD808\uDF45\uDBFF\uDFFF", |
| // From Go std lib tests in unicode/utf16/utf16_test.go |
| "\u0001\u0002\u0003\u0004", |
| "\uffff\ud800\udc00\ud800\udc01\ud808\udf45\udbff\udfff", |
| "\ud800a", |
| "\udfff" |
| }; |
| String[] wants = new String[]{ |
| "abcxyz09{}", |
| "Hello, 世界", |
| "\uffff\uD800\uDC00\uD800\uDC01\uD808\uDF45\uDBFF\uDFFF", |
| "\u0001\u0002\u0003\u0004", |
| "\uffff\ud800\udc00\ud800\udc01\ud808\udf45\udbff\udfff", |
| "\ufffda", |
| "\ufffd" |
| }; |
| for (int i = 0; i < tests.length; i++) { |
| String got = Testpkg.strDup(tests[i]); |
| String want = wants[i]; |
| 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 testByteArray() { |
| for (int i = 0; i < 2048; i++) { |
| if (i == 0) { |
| byte[] got = Testpkg.bytesAppend(null, null); |
| assertEquals("Bytes(null+null) should match", (byte[])null, got); |
| got = Testpkg.bytesAppend(new byte[0], new byte[0]); |
| assertEquals("Bytes(empty+empty) should match", (byte[])null, got); |
| continue; |
| } |
| |
| byte[] want = new byte[i]; |
| new Random().nextBytes(want); |
| |
| byte[] s1 = null; |
| byte[] s2 = null; |
| if (i > 0) { |
| s1 = Arrays.copyOfRange(want, 0, 1); |
| } |
| if (i > 1) { |
| s2 = Arrays.copyOfRange(want, 1, i); |
| } |
| byte[] got = Testpkg.bytesAppend(s1, s2); |
| MoreAsserts.assertEquals("Bytes(len="+i+") should match", want, got); |
| } |
| } |
| |
| // Test for golang.org/issue/9486. |
| public void testByteArrayAfterString() { |
| byte[] bytes = new byte[1024]; |
| for (int i=0; i < bytes.length; i++) { |
| bytes[i] = 8; |
| } |
| |
| String stuff = "stuff"; |
| byte[] got = Testpkg.appendToString(stuff, bytes); |
| |
| try { |
| byte[] s = stuff.getBytes("UTF-8"); |
| byte[] want = new byte[s.length + bytes.length]; |
| System.arraycopy(s, 0, want, 0, s.length); |
| System.arraycopy(bytes, 0, want, s.length, bytes.length); |
| MoreAsserts.assertEquals("Bytes should match", want, got); |
| } catch (Exception e) { |
| fail("Cannot perform the test: " + e.toString()); |
| } |
| } |
| |
| public void testGoRefGC() { |
| S s = Testpkg.new_(); |
| runGC(); |
| long collected = Testpkg.numSCollected(); |
| assertEquals("Only S should be pinned", 0, collected); |
| |
| s = null; |
| runGC(); |
| collected = Testpkg.numSCollected(); |
| assertEquals("S should be collected", 1, collected); |
| } |
| |
| private class AnI implements I { |
| public void e() throws Exception { |
| throw new Exception("my exception from E"); |
| } |
| |
| boolean calledF; |
| public void f() { |
| calledF = true; |
| } |
| |
| public I i() { |
| return this; |
| } |
| |
| public S s() { |
| return Testpkg.new_(); |
| } |
| |
| public String stoString(S s) { |
| return s.string(); |
| } |
| |
| public long v() { |
| return 1234; |
| } |
| |
| public long ve() throws Exception { |
| throw new Exception("my exception from VE"); |
| } |
| |
| public String name; |
| |
| public String string() { |
| return name; |
| } |
| |
| } |
| |
| // TODO(hyangah): add tests for methods that take parameters. |
| |
| public void testInterfaceMethodReturnsError() { |
| final AnI obj = new AnI(); |
| try { |
| Testpkg.callE(obj); |
| fail("Expecting exception but none was thrown."); |
| } catch (Exception e) { |
| assertEquals("Error messages should match", "my exception from E", e.getMessage()); |
| } |
| } |
| |
| public void testInterfaceMethodVoid() { |
| final AnI obj = new AnI(); |
| Testpkg.callF(obj); |
| assertTrue("Want AnI.F to be called", obj.calledF); |
| } |
| |
| public void testInterfaceMethodReturnsInterface() { |
| AnI obj = new AnI(); |
| obj.name = "testing AnI.I"; |
| I i = Testpkg.callI(obj); |
| assertEquals("Want AnI.I to return itself", i.string(), obj.string()); |
| |
| runGC(); |
| |
| i = Testpkg.callI(obj); |
| assertEquals("Want AnI.I to return itself", i.string(), obj.string()); |
| } |
| |
| public void testInterfaceMethodReturnsStructPointer() { |
| final AnI obj = new AnI(); |
| for (int i = 0; i < 5; i++) { |
| S s = Testpkg.callS(obj); |
| runGC(); |
| } |
| } |
| |
| public void testInterfaceMethodTakesStructPointer() { |
| final AnI obj = new AnI(); |
| S s = Testpkg.callS(obj); |
| String got = obj.stoString(s); |
| String want = s.string(); |
| assertEquals("Want AnI.StoString(s) to call s's String", want, got); |
| } |
| |
| public void testInterfaceMethodReturnsInt() { |
| final AnI obj = new AnI(); |
| assertEquals("Values must match", 1234, Testpkg.callV(obj)); |
| } |
| |
| public void testInterfaceMethodReturnsIntOrError() { |
| final AnI obj = new AnI(); |
| try { |
| long v = Testpkg.callVE(obj); |
| fail("Expecting exception but none was thrown and got value " + v); |
| } catch (Exception e) { |
| assertEquals("Error messages should match", "my exception from VE", e.getMessage()); |
| } |
| } |
| |
| boolean finalizedAnI; |
| |
| private class AnI_Traced extends AnI { |
| @Override |
| public void finalize() throws Throwable { |
| finalizedAnI = true; |
| super.finalize(); |
| } |
| } |
| |
| public void testJavaRefKeep() { |
| finalizedAnI = false; |
| AnI obj = new AnI_Traced(); |
| Testpkg.callF(obj); |
| assertTrue("want F to be called", obj.calledF); |
| Testpkg.callF(obj); |
| obj = null; |
| int attempts = 0; |
| while (true) { |
| runGC(); |
| if (finalizedAnI) |
| break; |
| attempts++; |
| try { |
| Thread.sleep(100); |
| } catch (InterruptedException e) { |
| throw new RuntimeException(e); |
| } |
| if (attempts >= 10) |
| fail("want obj not to be kept by Go; tried " + attempts + " garbage collections."); |
| } |
| |
| finalizedAnI = false; |
| obj = new AnI_Traced(); |
| Testpkg.keep(obj); |
| obj = null; |
| runGC(); |
| assertFalse("want obj to be kept live by Go", finalizedAnI); |
| } |
| |
| private int countI = 0; |
| |
| private class CountI implements I { |
| public void f() { countI++; } |
| |
| public void e() throws Exception {} |
| public I i() { return null; } |
| public S s() { return null; } |
| public String stoString(S s) { return ""; } |
| public long v() { return 0; } |
| public long ve() throws Exception { return 0; } |
| public String string() { return ""; } |
| } |
| |
| public void testGoRefMapGrow() { |
| CountI obj = new CountI(); |
| Testpkg.keep(obj); |
| |
| // Push active references beyond base map size. |
| for (int i = 0; i < 24; i++) { |
| CountI o = new CountI(); |
| Testpkg.callF(o); |
| if (i%3==0) { |
| Testpkg.keep(o); |
| } |
| } |
| runGC(); |
| for (int i = 0; i < 128; i++) { |
| Testpkg.callF(new CountI()); |
| } |
| |
| Testpkg.callF(obj); // original object needs to work. |
| |
| assertEquals(countI, 1+24+128); |
| } |
| |
| private void runGC() { |
| System.gc(); |
| System.runFinalization(); |
| Testpkg.gc(); |
| System.gc(); |
| System.runFinalization(); |
| } |
| |
| public void testUnnamedParams() { |
| final String msg = "1234567"; |
| assertEquals("want the length of \"1234567\" passed after unnamed params", |
| 7, Testpkg.unnamedParams(10, 20, msg)); |
| } |
| |
| public void testPointerToStructAsField() { |
| Node a = Testpkg.newNode("A"); |
| Node b = Testpkg.newNode("B"); |
| a.setNext(b); |
| String got = a.string(); |
| assertEquals("want Node A points to Node B", "A:B:<end>", got); |
| } |
| |
| public void testImplementsInterface() { |
| Interface intf = Testpkg.newConcrete(); |
| } |
| |
| public void testErrorField() { |
| Node n = Testpkg.newNode("ErrTest"); |
| Exception want = new Exception("an error message"); |
| n.setErr(want); |
| Exception got = n.getErr(); |
| assertTrue("want back the error we set", want == got); |
| String msg = Testpkg.errorMessage(want); |
| assertEquals("the error message must match", want.getMessage(), msg); |
| } |
| |
| public void testErrorDup() { |
| Exception err = Testpkg.getGlobalErr(); |
| assertTrue("the Go error instance must preserve its identity", Testpkg.isGlobalErr(err)); |
| assertEquals("the Go error message must be preserved", "global err", err.getMessage()); |
| } |
| |
| //test if we have JNI local reference table overflow error |
| public void testLocalReferenceOverflow() { |
| Testpkg.callWithCallback(new GoCallback() { |
| |
| @Override |
| public void varUpdate() { |
| //do nothing |
| } |
| }); |
| } |
| |
| public void testNullReferences() { |
| assertTrue(Testpkg.callWithNull(null, new NullTest() { |
| public NullTest null_() { |
| return null; |
| } |
| })); |
| assertEquals("Go nil interface is null", null, Testpkg.newNullInterface()); |
| assertEquals("Go nil struct pointer is null", null, Testpkg.newNullStruct()); |
| |
| Issue20330 nullArger = new Issue20330(); |
| assertTrue(nullArger.callWithNull(null)); |
| } |
| |
| public void testPassByteArray() { |
| Testpkg.passByteArray(new B() { |
| @Override public void b(byte[] b) { |
| byte[] want = new byte[]{1, 2, 3, 4}; |
| MoreAsserts.assertEquals("bytes should match", want, b); |
| } |
| }); |
| } |
| |
| public void testReader() { |
| byte[] b = new byte[8]; |
| try { |
| long n = Testpkg.readIntoByteArray(b); |
| assertEquals("wrote to the entire byte array", b.length, n); |
| byte[] want = new byte[b.length]; |
| for (int i = 0; i < want.length; i++) |
| want[i] = (byte)i; |
| MoreAsserts.assertEquals("bytes should match", want, b); |
| } catch (Exception e) { |
| fail("Failed to write: " + e.toString()); |
| } |
| } |
| |
| public void testGoroutineCallback() { |
| Testpkg.goroutineCallback(new Receiver() { |
| @Override public void hello(String msg) { |
| } |
| }); |
| } |
| |
| public void testImportedPkg() { |
| Testpkg.callImportedI(new secondpkg.I() { |
| @Override public long f(long i) { |
| return i; |
| } |
| }); |
| assertEquals("imported string should match", Secondpkg.HelloString, Secondpkg.hello()); |
| secondpkg.I i = Testpkg.newImportedI(); |
| secondpkg.S s = Testpkg.newImportedS(); |
| i = Testpkg.getImportedVarI(); |
| s = Testpkg.getImportedVarS(); |
| assertEquals("numbers should match", 8, i.f(8)); |
| assertEquals("numbers should match", 8, s.f(8)); |
| Testpkg.setImportedVarI(i); |
| Testpkg.setImportedVarS(s); |
| ImportedFields fields = Testpkg.newImportedFields(); |
| i = fields.getI(); |
| s = fields.getS(); |
| fields.setI(i); |
| fields.setS(s); |
| Testpkg.withImportedI(i); |
| Testpkg.withImportedS(s); |
| |
| secondpkg.IF f = new AnI(); |
| f = Testpkg.new_(); |
| secondpkg.Ser ser = Testpkg.newSer(); |
| } |
| |
| public void testRoundtripEquality() { |
| I want = new AnI(); |
| assertTrue("java object passed through Go should not be wrapped", want == Testpkg.iDup(want)); |
| InterfaceDupper idup = new InterfaceDupper(){ |
| @Override public Interface iDup(Interface i) { |
| return i; |
| } |
| }; |
| assertTrue("Go interface passed through Java should not be wrapped", Testpkg.callIDupper(idup)); |
| ConcreteDupper cdup = new ConcreteDupper(){ |
| @Override public Concrete cDup(Concrete c) { |
| return c; |
| } |
| }; |
| assertTrue("Go struct passed through Java should not be wrapped", Testpkg.callCDupper(cdup)); |
| } |
| |
| public void testConstructor() { |
| Interface i = new Concrete(); |
| i.f(); |
| |
| S2 s = new S2(1, 2); |
| assertEquals("new S2().sum", 3.0, s.sum()); |
| assertEquals("new S2().tryTwoStrings", "gostring", s.tryTwoStrings("go", "string")); |
| |
| new S3(); |
| |
| S4 s4 = new S4(123); |
| assertEquals("Constructor argument", 123, s4.getI()); |
| |
| s4 = new S4(123.456); |
| assertEquals("Overloaded constructor argument", 123, s4.getI()); |
| |
| s4 = new S4(false); |
| assertEquals("Exceptional constructor", 0, s4.getI()); |
| |
| try { |
| s4 = new S4(true); |
| fail("Constructor error wasn't caught"); |
| } catch (Exception e) { |
| } |
| } |
| |
| public void testEmptyError() { |
| try { |
| Testpkg.emptyError(); |
| fail("Empty error wasn't caught"); |
| } catch (Exception e) { |
| } |
| EmptyErrorer empty = new EmptyErrorer() { |
| @Override public void emptyError() throws Exception { |
| throw new Exception(""); |
| } |
| }; |
| try { |
| Testpkg.callEmptyError(empty); |
| fail("Empty exception wasn't caught"); |
| } catch (Exception e) { |
| } |
| } |
| |
| public void testInitCaller() { |
| Testpkg.init(); |
| |
| InitCaller initer = Testpkg.newInitCaller(); |
| initer.init(); |
| } |
| |
| public void testSIGPIPE() { |
| Testpkg.testSIGPIPE(); |
| } |
| |
| public void testTags() { |
| assertEquals("Constant from a tagged file", 42, Testpkg.TaggedConst); |
| } |
| |
| public void testClassNameWithPackageName() { |
| testpkg.Testpkg_ o = new secondpkg.Secondpkg_(); |
| secondpkg.Secondpkg_ o2 = Secondpkg.newSecondpkg(); |
| o2.m(); |
| o2.setV("hi"); |
| assertEquals(o2.getV(), "hi"); |
| Testpkg.clashingParameterFromOtherPackage(o2); |
| } |
| } |