/* * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.apple.jobjc; import com.apple.jobjc.Coder.IDCoder; import com.apple.jobjc.Coder.VoidCoder; import com.apple.jobjc.Invoke.MsgSend; import com.apple.jobjc.Invoke.MsgSendSuper; import com.apple.jobjc.PrimitiveCoder.DoubleCoder; import com.apple.jobjc.PrimitiveCoder.FloatCoder; import com.apple.jobjc.PrimitiveCoder.SIntCoder; import com.apple.jobjc.PrimitiveCoder.SLongLongCoder; import com.apple.jobjc.foundation.NSObject; import com.apple.jobjc.foundation.NSObjectClass; import com.apple.jobjc.foundation.NSPoint; import com.apple.jobjc.foundation.NSString; public class SubclassingTest extends PooledTestCase{ JObjCRuntime runtime; NativeArgumentBuffer ctx; @Override public void setUp() throws Exception{ super.setUp(); this.runtime = JObjCRuntime.getInstance(); this.ctx = runtime.getThreadLocalState(); runtime.registerUserClass(MyObject.class, MyObjectClass.class); } public void testClass(){ final MyObjectClass cls = new MyObjectClass(runtime); assertEquals(MyObject.class.getSimpleName(), UnsafeRuntimeAccess.getClassNameFor(cls)); } public void testInst(){ final MyObjectClass cls = new MyObjectClass(runtime); final MyObject instObj = cls.alloc(); final MyObject retrievedObj = Subclassing.getJObjectFromIVar(UnsafeRuntimeAccess.getObjPtr(instObj)); assertTrue(instObj == retrievedObj); } public void testVoidVoidMethod(){ final MyObject instObj = new MyObjectClass(runtime).alloc(); assertEquals(0, instObj.myMethodHits); MsgSend sel = new MsgSend(runtime, "myMethod", VoidCoder.INST); sel.init(ctx, instObj); sel.invoke(ctx); assertEquals(1, instObj.myMethodHits); } public void testMsgSendSuper(){ final MyObjectClass cls = new MyObjectClass(runtime); final MyObject obj = ((MyObject) cls.alloc()).init(); // direct descr assertEquals("foo", Utils.get().strings().javaString(obj.description())); // indirect (from native) descr { MsgSend msgSend = new MsgSend(runtime, "description", IDCoder.INST); msgSend.init(ctx, obj); msgSend.invoke(ctx); assertEquals("foo", Utils.get().strings().javaString((NSString) IDCoder.INST.pop(ctx))); } // indirect (from native) descr { MsgSendSuper msgSendSuper = new MsgSendSuper(runtime, "description", IDCoder.INST); msgSendSuper.init(ctx, obj, cls); msgSendSuper.invoke(ctx); assertEquals("foo", Utils.get().strings().javaString((NSString) IDCoder.INST.pop(ctx))); } // nso descr { MsgSendSuper msgSendSuper = new MsgSendSuper(runtime, "description", IDCoder.INST); msgSendSuper.init(ctx, obj, JObjC.getInstance().Foundation().NSObject()); msgSendSuper.invoke(ctx); final NSString nsod = (NSString) IDCoder.INST.pop(ctx); String jde = Utils.get().strings().javaString(nsod); assertEquals(jde.substring(0, 9), "<MyObject"); } } public void testPerformSelector(){ final MyObject instObj = new MyObjectClass(runtime).alloc(); assertEquals(0, instObj.myMethodHits); instObj.performSelector(new SEL("myMethod")); assertEquals(1, instObj.myMethodHits); instObj.performSelectorOnMainThread_withObject_waitUntilDone( new SEL("myMethod"), null, true); assertEquals(2, instObj.myMethodHits); } public void testVoidIntMethod(){ final MyObject instObj = new MyObjectClass(runtime).alloc(); MsgSend sel2 = new MsgSend(runtime, "intMethod", SIntCoder.INST); sel2.init(ctx, instObj); sel2.invoke(ctx); int ret = SIntCoder.INST.popInt(ctx); assertEquals(3, ret); } public void testStructStructMethod(){ final MyObject instObj = new MyObjectClass(runtime).alloc(); NSPoint p = JObjC.getInstance().Foundation().NSMakePoint(3, 3); MsgSend sel2 = new MsgSend(runtime, "doubleIt:", p.getCoder(), p.getCoder()); sel2.init(ctx, instObj); p.getCoder().push(ctx, p); sel2.invoke(ctx, p); assertEquals(6.0, p.x()); } public void testNSStringNSStringMethod(){ final MyObject instObj = new MyObjectClass(runtime).alloc(); final NSString orig = Utils.get().strings().nsString("foobar"); final String expected = "foobarfoobarfoobar"; final MsgSend sel = new MsgSend(runtime, "stringTimesThree:", IDCoder.INST, IDCoder.INST); sel.init(ctx, instObj); IDCoder.INST.push(ctx, orig); sel.invoke(ctx); NSString ret = (NSString) IDCoder.INST.pop(ctx); assertEquals(expected, Utils.get().strings().javaString(ret)); } public void testDoubleIntLongMethod(){ final MyObject instObj = new MyObjectClass(runtime).alloc(); final int arg1 = 3; final long arg2 = 4; final float arg3 = 5.5F; final double expected = 12.5D; final MsgSend sel = new MsgSend(runtime, "add:and:and:", DoubleCoder.INST, SIntCoder.INST, SLongLongCoder.INST, FloatCoder.INST); sel.init(ctx, instObj); SIntCoder.INST.push(ctx, arg1); SLongLongCoder.INST.push(ctx, arg2); FloatCoder.INST.push(ctx, arg3); sel.invoke(ctx); final double ret = DoubleCoder.INST.pop(ctx); assertEquals(expected, ret); } public static void main(String[] args){ junit.textui.TestRunner.run(SubclassingTest.class); } } class MyObject extends NSObject{ public MyObject(long objPtr, JObjCRuntime runtime) { super(objPtr, runtime); } public int myMethodHits = 0; public void myMethod(){ myMethodHits++; } public int intMethod(){ return 3; } public NSString stringTimesThree(NSString nss){ int count = 3; String jss = Utils.get().strings().javaString(nss); String js2 = ""; while(count-- > 0) js2 += jss; return Utils.get().strings().nsString(js2); } public double add_and_and(int a, long b, float c){ return a + b + c; } public NSPoint doubleIt(NSPoint p){ System.out.println("Doubling NSPoint(" + p.x() + ", " + p.y() + ")."); p.setX(p.x() * 2); p.setY(p.y() * 2); return p; } @Override public NSString description(){ return Utils.get().strings().nsString("foo"); } } class MyObjectClass extends NSObjectClass{ protected MyObjectClass(String name, JObjCRuntime runtime) { super(name, runtime); } public MyObjectClass(JObjCRuntime runtime){ this("MyObject", runtime); } }