1 /* 2 * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package com.apple.jobjc; 26 27 import com.apple.jobjc.Coder.IDCoder; 28 import com.apple.jobjc.Coder.VoidCoder; 29 import com.apple.jobjc.Invoke.MsgSend; 30 import com.apple.jobjc.Invoke.MsgSendSuper; 31 import com.apple.jobjc.PrimitiveCoder.DoubleCoder; 32 import com.apple.jobjc.PrimitiveCoder.FloatCoder; 33 import com.apple.jobjc.PrimitiveCoder.SIntCoder; 34 import com.apple.jobjc.PrimitiveCoder.SLongLongCoder; 35 import com.apple.jobjc.foundation.NSObject; 36 import com.apple.jobjc.foundation.NSObjectClass; 37 import com.apple.jobjc.foundation.NSPoint; 38 import com.apple.jobjc.foundation.NSString; 39 40 public class SubclassingTest extends PooledTestCase{ 41 JObjCRuntime runtime; 42 NativeArgumentBuffer ctx; 43 44 @Override public void setUp() throws Exception{ 45 super.setUp(); 46 this.runtime = JObjCRuntime.getInstance(); 47 this.ctx = runtime.getThreadLocalState(); 48 49 runtime.registerUserClass(MyObject.class, MyObjectClass.class); 50 } 51 52 public void testClass(){ 53 final MyObjectClass cls = new MyObjectClass(runtime); 54 assertEquals(MyObject.class.getSimpleName(), UnsafeRuntimeAccess.getClassNameFor(cls)); 55 } 56 57 public void testInst(){ 58 final MyObjectClass cls = new MyObjectClass(runtime); 59 final MyObject instObj = cls.alloc(); 60 final MyObject retrievedObj = Subclassing.getJObjectFromIVar(UnsafeRuntimeAccess.getObjPtr(instObj)); 61 assertTrue(instObj == retrievedObj); 62 } 63 64 public void testVoidVoidMethod(){ 65 final MyObject instObj = new MyObjectClass(runtime).alloc(); 66 67 assertEquals(0, instObj.myMethodHits); 68 MsgSend sel = new MsgSend(runtime, "myMethod", VoidCoder.INST); 69 sel.init(ctx, instObj); 70 sel.invoke(ctx); 71 assertEquals(1, instObj.myMethodHits); 72 } 73 74 public void testMsgSendSuper(){ 75 final MyObjectClass cls = new MyObjectClass(runtime); 76 final MyObject obj = ((MyObject) cls.alloc()).init(); 77 78 // direct descr 79 80 assertEquals("foo", Utils.get().strings().javaString(obj.description())); 81 82 // indirect (from native) descr 83 { 84 MsgSend msgSend = new MsgSend(runtime, "description", IDCoder.INST); 85 msgSend.init(ctx, obj); 86 msgSend.invoke(ctx); 87 assertEquals("foo", Utils.get().strings().javaString((NSString) IDCoder.INST.pop(ctx))); 88 } 89 90 // indirect (from native) descr 91 { 92 MsgSendSuper msgSendSuper = new MsgSendSuper(runtime, "description", IDCoder.INST); 93 msgSendSuper.init(ctx, obj, cls); 94 msgSendSuper.invoke(ctx); 95 assertEquals("foo", Utils.get().strings().javaString((NSString) IDCoder.INST.pop(ctx))); 96 } 97 98 // nso descr 99 { 100 MsgSendSuper msgSendSuper = new MsgSendSuper(runtime, "description", IDCoder.INST); 101 msgSendSuper.init(ctx, obj, JObjC.getInstance().Foundation().NSObject()); 102 msgSendSuper.invoke(ctx); 103 104 final NSString nsod = (NSString) IDCoder.INST.pop(ctx); 105 String jde = Utils.get().strings().javaString(nsod); 106 assertEquals(jde.substring(0, 9), "<MyObject"); 107 } 108 } 109 110 public void testPerformSelector(){ 111 final MyObject instObj = new MyObjectClass(runtime).alloc(); 112 113 assertEquals(0, instObj.myMethodHits); 114 instObj.performSelector(new SEL("myMethod")); 115 assertEquals(1, instObj.myMethodHits); 116 117 instObj.performSelectorOnMainThread_withObject_waitUntilDone( 118 new SEL("myMethod"), null, true); 119 assertEquals(2, instObj.myMethodHits); 120 } 121 122 public void testVoidIntMethod(){ 123 final MyObject instObj = new MyObjectClass(runtime).alloc(); 124 125 MsgSend sel2 = new MsgSend(runtime, "intMethod", SIntCoder.INST); 126 sel2.init(ctx, instObj); 127 sel2.invoke(ctx); 128 int ret = SIntCoder.INST.popInt(ctx); 129 assertEquals(3, ret); 130 } 131 132 public void testStructStructMethod(){ 133 final MyObject instObj = new MyObjectClass(runtime).alloc(); 134 135 NSPoint p = JObjC.getInstance().Foundation().NSMakePoint(3, 3); 136 137 MsgSend sel2 = new MsgSend(runtime, "doubleIt:", p.getCoder(), p.getCoder()); 138 sel2.init(ctx, instObj); 139 p.getCoder().push(ctx, p); 140 sel2.invoke(ctx, p); 141 142 assertEquals(6.0, p.x()); 143 } 144 145 public void testNSStringNSStringMethod(){ 146 final MyObject instObj = new MyObjectClass(runtime).alloc(); 147 148 final NSString orig = Utils.get().strings().nsString("foobar"); 149 final String expected = "foobarfoobarfoobar"; 150 151 final MsgSend sel = new MsgSend(runtime, "stringTimesThree:", IDCoder.INST, IDCoder.INST); 152 sel.init(ctx, instObj); 153 IDCoder.INST.push(ctx, orig); 154 sel.invoke(ctx); 155 NSString ret = (NSString) IDCoder.INST.pop(ctx); 156 assertEquals(expected, Utils.get().strings().javaString(ret)); 157 } 158 159 public void testDoubleIntLongMethod(){ 160 final MyObject instObj = new MyObjectClass(runtime).alloc(); 161 162 final int arg1 = 3; 163 final long arg2 = 4; 164 final float arg3 = 5.5F; 165 final double expected = 12.5D; 166 167 final MsgSend sel = new MsgSend(runtime, "add:and:and:", DoubleCoder.INST, 168 SIntCoder.INST, SLongLongCoder.INST, FloatCoder.INST); 169 sel.init(ctx, instObj); 170 SIntCoder.INST.push(ctx, arg1); 171 SLongLongCoder.INST.push(ctx, arg2); 172 FloatCoder.INST.push(ctx, arg3); 173 sel.invoke(ctx); 174 final double ret = DoubleCoder.INST.pop(ctx); 175 assertEquals(expected, ret); 176 } 177 178 public static void main(String[] args){ 179 junit.textui.TestRunner.run(SubclassingTest.class); 180 } 181 } 182 183 class MyObject extends NSObject{ 184 public MyObject(long objPtr, JObjCRuntime runtime) { 185 super(objPtr, runtime); 186 } 187 188 public int myMethodHits = 0; 189 190 public void myMethod(){ 191 myMethodHits++; 192 } 193 194 public int intMethod(){ 195 return 3; 196 } 197 198 public NSString stringTimesThree(NSString nss){ 199 int count = 3; 200 String jss = Utils.get().strings().javaString(nss); 201 String js2 = ""; 202 while(count-- > 0) 203 js2 += jss; 204 return Utils.get().strings().nsString(js2); 205 } 206 207 public double add_and_and(int a, long b, float c){ 208 return a + b + c; 209 } 210 211 public NSPoint doubleIt(NSPoint p){ 212 System.out.println("Doubling NSPoint(" + p.x() + ", " + p.y() + ")."); 213 p.setX(p.x() * 2); 214 p.setY(p.y() * 2); 215 return p; 216 } 217 218 @Override public NSString description(){ 219 return Utils.get().strings().nsString("foo"); 220 } 221 } 222 223 class MyObjectClass extends NSObjectClass{ 224 protected MyObjectClass(String name, JObjCRuntime runtime) { 225 super(name, runtime); 226 } 227 228 public MyObjectClass(JObjCRuntime runtime){ 229 this("MyObject", runtime); 230 } 231 }