/***************************************************************************** * Copyright [2013] [Jules White] * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * ****************************************************************************/ package org.magnum.soda.test; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import org.junit.Test; import org.magnum.soda.MsgBus; import org.magnum.soda.ObjRegistry; import org.magnum.soda.msg.LocalAddress; import org.magnum.soda.proxy.JavaReflectionProxyCreator; import org.magnum.soda.proxy.ObjProxy.ResponseCatcher; import org.magnum.soda.proxy.ObjRef; import org.magnum.soda.proxy.ProxyFactory; import org.magnum.soda.proxy.SodaAsync; import org.magnum.soda.svc.InvocationInfo; import org.magnum.soda.svc.ObjInvocationMsg; import org.magnum.soda.svc.ObjInvocationRespMsg; import org.mockito.ArgumentCaptor; public class ObjProxyTest { public interface ObjectSync { @SodaAsync public void async(); public void sync(); } public interface TestObj { public boolean equals(Object o); public String getName(); public void setFoo(String a, Boolean b); public String[] calcPrefixes(String[] base, String mod, Object[] foo); public TestObj link(TestObj obj); } private boolean reply_ = false; private String replyString_ = null; private String[] replyStrings_; private TestObj replyObj_; private LocalAddress myAddress_ = new LocalAddress(); @Test public void testNonProxyParamsAndReturnValue() { MsgBus bus = mock(MsgBus.class); ObjRegistry reg = mock(ObjRegistry.class); ProxyFactory factory = new ProxyFactory(reg, new JavaReflectionProxyCreator(getClass().getClassLoader()), myAddress_, bus); ObjRef ref = myAddress_.createObjRef(TestObj.class); final TestObj b = factory.createProxy(TestObj.class, ref); Thread t = new Thread(new Runnable() { @Override public void run() { reply_ = b.equals(false); } }); t.start(); extractAndVerifyInvocationMsg(bus, ref, "equals", new Object[] { false }, true); assertEquals(true, reply_); } @Test public void testNonProxyNoParamsAndReturnValue() { MsgBus bus = mock(MsgBus.class); ObjRegistry reg = mock(ObjRegistry.class); ProxyFactory factory = new ProxyFactory(reg, new JavaReflectionProxyCreator(getClass().getClassLoader()), myAddress_, bus); ObjRef ref = myAddress_.createObjRef(TestObj.class); final TestObj b = factory.createProxy(TestObj.class, ref); Thread t = new Thread(new Runnable() { @Override public void run() { replyString_ = b.getName(); } }); t.start(); extractAndVerifyInvocationMsg(bus, ref, "getName", new Object[] {}, "asdf"); assertEquals("asdf", replyString_); } @Test public void testTwoNonProxyParamsVoidReturn() { MsgBus bus = mock(MsgBus.class); ObjRegistry reg = mock(ObjRegistry.class); ProxyFactory factory = new ProxyFactory(reg, new JavaReflectionProxyCreator(getClass().getClassLoader()), myAddress_, bus); ObjRef ref = myAddress_.createObjRef(TestObj.class); final TestObj b = factory.createProxy(TestObj.class, ref); Thread t = new Thread(new Runnable() { @Override public void run() { b.setFoo("asdf", true); } }); t.start(); extractAndVerifyInvocationMsg(bus, ref, "setFoo", new Object[] { "asdf", true }, null); } @Test public void testNonProxyMultipleParamsArraysAndArrayReturn() { MsgBus bus = mock(MsgBus.class); ObjRegistry reg = mock(ObjRegistry.class); ProxyFactory factory = new ProxyFactory(reg, new JavaReflectionProxyCreator(getClass().getClassLoader()), myAddress_, bus); ObjRef ref = myAddress_.createObjRef(TestObj.class); final TestObj b = factory.createProxy(TestObj.class, ref); Thread t = new Thread(new Runnable() { @Override public void run() { replyStrings_ = b.calcPrefixes(new String[] { "a", "b" }, "c", null); } }); t.start(); extractAndVerifyInvocationMsg(bus, ref, "calcPrefixes", new Object[] { new String[] { "a", "b" }, "c", null }, new String[] { "e", "f" }); assertArrayEquals(new String[] { "e", "f" }, replyStrings_); } @Test public void testNonProxyChainedInvocations() { MsgBus bus = mock(MsgBus.class); ObjRegistry reg = mock(ObjRegistry.class); ProxyFactory factory = new ProxyFactory(reg, new JavaReflectionProxyCreator(getClass().getClassLoader()), myAddress_, bus); ObjRef ref = myAddress_.createObjRef(TestObj.class); final TestObj b = factory.createProxy(TestObj.class, ref); Thread t = new Thread(new Runnable() { @Override public void run() { String a = b.getName(); boolean v = b.equals(a); replyStrings_ = b.calcPrefixes(new String[] { "a", "b" }, a, new Object[] { v }); } }); t.start(); extractAndVerifyInvocationMsg(bus, ref, "getName", new Object[] {}, "a"); extractAndVerifyInvocationMsg(bus, ref, "equals", new Object[] { "a" }, true); extractAndVerifyInvocationMsg(bus, ref, "calcPrefixes", new Object[] { new String[] { "a", "b" }, "a", new Object[] { true } }, new String[] { "22" }); assertArrayEquals(new String[] { "22" }, replyStrings_); } @Test public void testProxyAsParam() { MsgBus bus = mock(MsgBus.class); ObjRegistry reg = mock(ObjRegistry.class); ProxyFactory factory = new ProxyFactory(reg, new JavaReflectionProxyCreator(getClass().getClassLoader()), myAddress_, bus); ObjRef ref = myAddress_.createObjRef(TestObj.class); final TestObj b = factory.createProxy(TestObj.class, ref); final TestObj b2 = factory.createProxy(TestObj.class, ref); Thread t = new Thread(new Runnable() { @Override public void run() { replyObj_ = b.link(b2); } }); t.start(); extractAndVerifyInvocationMsg(bus, ref, "link", new Object[] { ref }, ref); verify(reg).insert(ref, b2); assertEquals(b2, replyObj_); } @Test public void testAutoPublishObjectParam() { MsgBus bus = mock(MsgBus.class); ObjRegistry reg = mock(ObjRegistry.class); ProxyFactory factory = new ProxyFactory(reg, new JavaReflectionProxyCreator(getClass().getClassLoader()), myAddress_, bus); ObjRef ref = myAddress_.createObjRef(TestObj.class); ObjRef ref2 = myAddress_.createObjRef(TestObj.class); final TestObj b = factory.createProxy(TestObj.class, ref); final TestObj b2 = new TestObj() { @Override public void setFoo(String a, Boolean b) { } @Override public TestObj link(TestObj obj) { // TODO Auto-generated method stub return null; } @Override public String getName() { // TODO Auto-generated method stub return null; } @Override public String[] calcPrefixes(String[] base, String mod, Object[] foo) { // TODO Auto-generated method stub return null; } }; when(reg.publish(b2)).thenReturn(ref2); when(reg.get(ref2)).thenReturn(b2); Thread t = new Thread(new Runnable() { @Override public void run() { replyObj_ = b.link(b2); } }); t.start(); extractAndVerifyInvocationMsg(bus, ref, "link", new Object[] { ref2 }, ref2); verify(reg).publish(b2); assertEquals(b2, replyObj_); } @Test public void testSyncAndAsyncBehavior() { MsgBus bus = mock(MsgBus.class); ObjRegistry reg = mock(ObjRegistry.class); ProxyFactory factory = new ProxyFactory(reg, new JavaReflectionProxyCreator(getClass().getClassLoader()), myAddress_, bus); ObjRef ref = myAddress_.createObjRef(ObjectSync.class); final ObjectSync b = factory.createProxy(ObjectSync.class, ref); Thread t = new Thread(new Runnable() { @Override public void run() { reply_ = false; b.async(); reply_ = true; } }); t.start(); sleep(50); assertEquals(true, reply_); t = new Thread(new Runnable() { @Override public void run() { reply_ = false; b.sync(); reply_ = true; } }); t.start(); sleep(50); assertEquals(false, reply_); } @Test public void testEqualsToStringHashcode() { MsgBus bus = mock(MsgBus.class); ObjRegistry reg = mock(ObjRegistry.class); ProxyFactory factory = new ProxyFactory(reg, new JavaReflectionProxyCreator(getClass().getClassLoader()), myAddress_, bus); ObjRef ref = myAddress_.createObjRef(TestObj.class); final TestObj b = factory.createProxy(TestObj.class, ref); final TestObj b2 = factory.createProxy(TestObj.class, ref); assertEquals(b, b2); assertEquals(b.hashCode(), b2.hashCode()); assertEquals(b.toString(), b2.toString()); } private void sleep(int time) { TestUtil.sleep(time); } private ObjInvocationMsg extractAndVerifyInvocationMsg(MsgBus bus, ObjRef objid, String method, Object[] args, Object returnval) { sleep(10); ArgumentCaptor<ResponseCatcher> scaptor = ArgumentCaptor .forClass(ResponseCatcher.class); ArgumentCaptor<ObjInvocationMsg> icaptor = ArgumentCaptor .forClass(ObjInvocationMsg.class); verify(bus, atLeast(1)).subscribe(scaptor.capture()); verify(bus, atLeast(1)).publish(icaptor.capture()); ObjInvocationMsg inv = icaptor.getValue(); assertEquals(objid, inv.getTargetObjectId()); InvocationInfo iinfo = inv.getInvocation(); assertEquals(method, iinfo.getMethod()); assertEquals(args.length, iinfo.getParameters().length); if (args != null) { for (int i = 0; i < args.length; i++) { if (args[i] instanceof Object[]) { assertArrayEquals((Object[]) args[i], (Object[]) iinfo.getParameters()[i]); } else { assertEquals(args[i], iinfo.getParameters()[i]); } } } ObjInvocationRespMsg resp = new ObjInvocationRespMsg(inv, returnval); ResponseCatcher catcher = scaptor.getValue(); catcher.handleResponse(resp); sleep(10); return inv; } }