Repository: flex-blazeds Updated Branches: refs/heads/develop 94728dd74 -> a09196c2c
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/a09196c2/remoting/src/test/java/flex/messaging/io/amf/client/AMFConnectionIT.java ---------------------------------------------------------------------- diff --git a/remoting/src/test/java/flex/messaging/io/amf/client/AMFConnectionIT.java b/remoting/src/test/java/flex/messaging/io/amf/client/AMFConnectionIT.java new file mode 100644 index 0000000..134315c --- /dev/null +++ b/remoting/src/test/java/flex/messaging/io/amf/client/AMFConnectionIT.java @@ -0,0 +1,778 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 flex.messaging.io.amf.client; + +import java.net.HttpURLConnection; +import java.net.InetSocketAddress; +import java.net.Proxy; + +import flex.messaging.util.TestServerWrapper; +import junit.extensions.TestSetup; +import org.junit.Assert; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import amfclient.ClientCustomType; + +import flex.messaging.MessageException; +import flex.messaging.messages.RemotingMessage; +import flex.messaging.io.amf.ASObject; +import flex.messaging.io.amf.AmfTrace; +import flex.messaging.io.amf.client.AMFConnection.HttpResponseInfo; +import flex.messaging.io.amf.client.exceptions.ClientStatusException; +import flex.messaging.io.amf.client.exceptions.ServerStatusException; +import flex.messaging.io.MessageIOConstants; + + +/** + * JUnit tests for AMFConnection. Note that most of the tests require a running + * server with the specified destination. + */ +public class AMFConnectionIT extends TestCase +{ + private static final String DEFAULT_DESTINATION_ID = "amfConnectionTestService"; + private static final String DEFAULT_METHOD_NAME = "echoString"; + private static final String DEFAULT_METHOD_ARG = "echo me"; + private static final String DEFAULT_URL = "http://localhost:%s/qa-regress/messagebroker/amf"; + private static final String DEFAULT_AMF_OPERATION = getOperationCall(DEFAULT_METHOD_NAME); + private static final String FOO_STRING = "foo"; + private static final String BAR_STRING = "bar"; + private static final String UNEXPECTED_EXCEPTION_STRING = "Unexpected exception: "; + + private static TestServerWrapper serverWrapper; + private static int serverPort; + + /** + * Given a remote method name, returns the AMF connection call needed using + * the default destination id. + */ + private static String getOperationCall(String method) + { + return DEFAULT_DESTINATION_ID + "." + method; + } + + protected String getConnectionUrl() { + return String.format(DEFAULT_URL, serverPort); + } + + + public AMFConnectionIT(String name) + { + super(name); + } + + public static Test suite() + { + //TestSuite suite = new TestSuite(AMFConnectionIT.class); + TestSuite suite = new TestSuite(); + suite.addTest(new AMFConnectionIT("testConnect")); + suite.addTest(new AMFConnectionIT("testConnectAndClose")); + suite.addTest(new AMFConnectionIT("testConnectBadUrl")); + suite.addTest(new AMFConnectionIT("testCallMultipleTimes")); + suite.addTest(new AMFConnectionIT("testCallNoConnect")); + suite.addTest(new AMFConnectionIT("testCallNoConnectStringMsg")); + suite.addTest(new AMFConnectionIT("testCallUnreachableConnectUrl")); + suite.addTest(new AMFConnectionIT("testCallNonexistantMethod")); + suite.addTest(new AMFConnectionIT("testHttpResponseInfoWithNonexistantMethod")); + suite.addTest(new AMFConnectionIT("testCloseNoConnect")); + suite.addTest(new AMFConnectionIT("testSetGetObjectEncoding")); + suite.addTest(new AMFConnectionIT("testSetGetDefaultObjectEncoding")); + suite.addTest(new AMFConnectionIT("testSetGetAMFHeaderProcessor")); + suite.addTest(new AMFConnectionIT("testAddRemoveAMFHeaderTwoParam")); + suite.addTest(new AMFConnectionIT("testAddRemoveAMFHeader")); + suite.addTest(new AMFConnectionIT("testAddRemoveAllAMFHeaders")); + suite.addTest(new AMFConnectionIT("testAddRemoveHTTPRequestHeader")); + suite.addTest(new AMFConnectionIT("testAddRemoveAllHTTPRequestHeaders")); + suite.addTest(new AMFConnectionIT("testRemoveAMFHeader")); + suite.addTest(new AMFConnectionIT("testRemoveAllAMFHeaders")); + suite.addTest(new AMFConnectionIT("testRemoveHTTPRequestHeader")); + suite.addTest(new AMFConnectionIT("testRemoveAllHTTPRequestHeaders")); + suite.addTest(new AMFConnectionIT("testInstantiateTypes")); + suite.addTest(new AMFConnectionIT("testSetGetAMFTrace")); + suite.addTest(new AMFConnectionIT("testHTTPProxy")); + + return new TestSetup(suite) { + protected void setUp() throws Exception { + serverWrapper = new TestServerWrapper(); + serverPort = serverWrapper.startServer("classpath:/WEB-INF/flex/services-config.xml"); + if(serverPort == -1) { + Assert.fail("Couldn't start server process"); + } + AMFConnection.registerAlias( + "remoting.amfclient.ServerCustomType" /* server type */, + "amfclient.ClientCustomType" /* client type */); + } + protected void tearDown() throws Exception { + serverWrapper.stopServer(); + serverWrapper = null; + } + }; + } + + // Not a test, just an example to show how to use AMFConnection. + public void example() + { + // Create the AMF connection. + AMFConnection amfConnection = new AMFConnection(); + + // Connect to the remote url. + try + { + amfConnection.connect(getConnectionUrl()); + } + catch (ClientStatusException cse) + { + return; + } + + // Make a remoting call and retrieve the result. + try + { + Object result = amfConnection.call(DEFAULT_AMF_OPERATION, DEFAULT_METHOD_ARG); + Assert.assertEquals(DEFAULT_METHOD_ARG, result); + } + catch (ClientStatusException cse) + { + // Ignore. + } + catch (ServerStatusException sse) + { + // Ignore. + } + + // Close the connection. + amfConnection.close(); + } + + public void testConnect() + { + AMFConnection amfConnection = new AMFConnection(); + try + { + amfConnection.connect(getConnectionUrl()); + Assert.assertEquals(getConnectionUrl(), amfConnection.getUrl()); + } + catch (ClientStatusException cse) + { + fail(UNEXPECTED_EXCEPTION_STRING + cse); + } + finally + { + amfConnection.close(); + } + } + + public void testConnectAndClose() + { + AMFConnection amfConnection = new AMFConnection(); + try + { + amfConnection.connect(getConnectionUrl()); + Assert.assertEquals(getConnectionUrl(), amfConnection.getUrl()); + } + catch (ClientStatusException cse) + { + fail(UNEXPECTED_EXCEPTION_STRING + cse); + } + finally + { + amfConnection.close(); + Assert.assertEquals(null, amfConnection.getUrl()); + } + } + + public void testConnectBadUrl() + { + String badUrl = "badUrl"; + AMFConnection amfConnection = new AMFConnection(); + try + { + amfConnection.connect(badUrl); + fail("ClientStatusException expected"); + } + catch (ClientStatusException cse) + { + Assert.assertEquals(ClientStatusException.AMF_CONNECT_FAILED_CODE, cse.getCode()); + } + finally + { + amfConnection.close(); + } + } + + public void testCallMultipleTimes() + { + AMFConnection amfConnection = new AMFConnection(); + try + { + amfConnection.connect(getConnectionUrl()); + } + catch (ClientStatusException cse) + { + fail(UNEXPECTED_EXCEPTION_STRING + cse); + } + // Make a remoting call and retrieve the result. + try + { + for (int i = 1; i < 4; i++) + { + String stringToEcho = DEFAULT_METHOD_ARG + i; + Object result = amfConnection.call(DEFAULT_AMF_OPERATION, stringToEcho); + Assert.assertEquals(stringToEcho, result); + } + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + finally + { + amfConnection.close(); + } + } + + public void testCallNoConnect() + { + AMFConnection amfConnection = new AMFConnection(); + // Make a remoting call without connect. + try + { + Object result = amfConnection.call(DEFAULT_AMF_OPERATION, DEFAULT_METHOD_ARG); + Assert.assertEquals(DEFAULT_METHOD_ARG, result); + } + catch (ClientStatusException cse) + { + Assert.assertEquals(ClientStatusException.AMF_CALL_FAILED_CODE, cse.getCode()); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + finally + { + amfConnection.close(); + } + } + + public void testCallNoConnectStringMsg() + { + AMFConnection amfConnection = new AMFConnection(); + // Make a remoting call without connect. + try + { + Object result = amfConnection.call(DEFAULT_AMF_OPERATION, DEFAULT_METHOD_ARG); + Assert.assertEquals(DEFAULT_METHOD_ARG, result); + } + catch (ClientStatusException cse) + { + Assert.assertEquals(ClientStatusException.AMF_CALL_FAILED_CODE, cse.getCode()); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + finally + { + amfConnection.close(); + } + } + + public void testCallUnreachableConnectUrl() + { + String unreachableUrl = "http://localhost:8400/team/messagebroker/unreachable"; + AMFConnection amfConnection = new AMFConnection(); + try + { + // Connect does not actually connect but simply sets the url. + amfConnection.connect(unreachableUrl); + } + catch (ClientStatusException cse) + { + fail(UNEXPECTED_EXCEPTION_STRING + cse); + } + // Make a remoting call and retrieve the result. + try + { + Object result = amfConnection.call(DEFAULT_AMF_OPERATION, DEFAULT_METHOD_ARG); + Assert.assertEquals(DEFAULT_METHOD_ARG, result); + } + catch (ClientStatusException cse) + { + Assert.assertEquals(ClientStatusException.AMF_CALL_FAILED_CODE, cse.getCode()); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + finally + { + amfConnection.close(); + } + } + + public void testCallNonexistantMethod() + { + String method = "nonExistantMethod"; + final ClientCustomType methodArg = new ClientCustomType(); + methodArg.setId(1); + try + { + internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + public void onResult(Object result) + { + fail("Unexcepted result: " + result); + } + }); + } + catch (ServerStatusException sse) + { + ASObject status = (ASObject)sse.getData(); + String code = (String)status.get("code"); + Assert.assertEquals(MessageException.CODE_SERVER_RESOURCE_UNAVAILABLE, code); + HttpResponseInfo info = sse.getHttpResponseInfo(); + // AMF status messages are reported as HTTP_OK still. + Assert.assertEquals(HttpURLConnection.HTTP_OK, info.getResponseCode()); + Assert.assertEquals("OK", info.getResponseMessage()); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + + public void testHttpResponseInfoWithNonexistantMethod() + { + String method = "nonExistantMethod"; + final ClientCustomType methodArg = new ClientCustomType(); + methodArg.setId(1); + try + { + internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + public void onResult(Object result) + { + fail("Unexcepted result: " + result); + } + }); + } + catch (ServerStatusException sse) + { + HttpResponseInfo info = sse.getHttpResponseInfo(); + // AMF status messages are reported as HTTP_OK still. + Assert.assertEquals(HttpURLConnection.HTTP_OK, info.getResponseCode()); + Assert.assertEquals("OK", info.getResponseMessage()); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + public void testCloseNoConnect() + { + AMFConnection amfConnection = new AMFConnection(); + // Closing with no connection or call. + try + { + amfConnection.close(); + Assert.assertEquals(null, amfConnection.getUrl()); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + + public void testSetGetObjectEncoding() + { + int retAMF; + AMFConnection amfConnection = new AMFConnection(); + try + { + amfConnection.connect(getConnectionUrl()); + Assert.assertEquals(getConnectionUrl(), amfConnection.getUrl()); + amfConnection.setObjectEncoding(MessageIOConstants.AMF0); + retAMF = amfConnection.getObjectEncoding(); + Assert.assertEquals(MessageIOConstants.AMF0, retAMF); + } + catch (ClientStatusException cse) + { + fail(UNEXPECTED_EXCEPTION_STRING + cse); + } + finally + { + amfConnection.close(); + } + } + + public void testSetGetDefaultObjectEncoding() + { + int retAMF; + AMFConnection amfConnection = new AMFConnection(); + try + { + amfConnection.connect(getConnectionUrl()); + Assert.assertEquals(getConnectionUrl(), amfConnection.getUrl()); + AMFConnection.setDefaultObjectEncoding(MessageIOConstants.AMF3); + retAMF = AMFConnection.getDefaultObjectEncoding(); + Assert.assertEquals(MessageIOConstants.AMF3, retAMF); + } + catch (ClientStatusException cse) + { + fail(UNEXPECTED_EXCEPTION_STRING + cse); + } + finally + { + amfConnection.close(); + } + } + + /** + * There doesn't seem to be a single implementation of AMFHeaderProcessor therefore this test + * is pretty useless. + */ + public void testSetGetAMFHeaderProcessor() + { + AMFHeaderProcessor setAMF = null; + AMFHeaderProcessor retAMF; + AMFConnection amfConnection = new AMFConnection(); + try + { + amfConnection.connect(getConnectionUrl()); + Assert.assertEquals(getConnectionUrl(), amfConnection.getUrl()); + amfConnection.setAMFHeaderProcessor(setAMF); + retAMF = amfConnection.getAMFHeaderProcessor(); + Assert.assertEquals(setAMF, retAMF); + } + catch (ClientStatusException cse) + { + fail(UNEXPECTED_EXCEPTION_STRING + cse); + } + finally + { + amfConnection.close(); + } + } + + public void testAddRemoveAMFHeaderTwoParam() + { + boolean retAMF; + Object val = 1; + AMFConnection amfConnection = new AMFConnection(); + try + { + amfConnection.connect(getConnectionUrl()); + Assert.assertEquals(getConnectionUrl(), amfConnection.getUrl()); + amfConnection.addAmfHeader(FOO_STRING,val); + retAMF = amfConnection.removeAmfHeader(FOO_STRING); + Assert.assertTrue(retAMF); + } + catch (ClientStatusException cse) + { + fail(UNEXPECTED_EXCEPTION_STRING + cse); + } + finally + { + amfConnection.close(); + } + } + + public void testAddRemoveAMFHeader() + { + boolean retAMF; + Object val = 1; + AMFConnection amfConnection = new AMFConnection(); + try + { + amfConnection.connect(getConnectionUrl()); + Assert.assertEquals(getConnectionUrl(), amfConnection.getUrl()); + amfConnection.addAmfHeader(FOO_STRING,true,val); + retAMF = amfConnection.removeAmfHeader(FOO_STRING); + Assert.assertTrue(retAMF); + } + catch (ClientStatusException cse) + { + fail(UNEXPECTED_EXCEPTION_STRING + cse); + } + finally + { + amfConnection.close(); + } + } + + public void testAddRemoveAllAMFHeaders() + { + Object val1 = 1; + Object val2 = 2; + AMFConnection amfConnection = new AMFConnection(); + try + { + amfConnection.connect(getConnectionUrl()); + Assert.assertEquals(getConnectionUrl(), amfConnection.getUrl()); + amfConnection.addAmfHeader(FOO_STRING,true,val1); + amfConnection.addAmfHeader(BAR_STRING,true,val2); + amfConnection.removeAllAmfHeaders(); + Assert.assertTrue(true); + } + catch (ClientStatusException cse) + { + fail(UNEXPECTED_EXCEPTION_STRING + cse); + } + finally + { + amfConnection.close(); + } + } + + public void testAddRemoveHTTPRequestHeader() + { + boolean retHttp; + AMFConnection amfConnection = new AMFConnection(); + try + { + amfConnection.connect(getConnectionUrl()); + Assert.assertEquals(getConnectionUrl(), amfConnection.getUrl()); + amfConnection.addHttpRequestHeader(FOO_STRING,BAR_STRING); + retHttp = amfConnection.removeHttpRequestHeader(FOO_STRING); + Assert.assertTrue(retHttp); + } + catch (ClientStatusException cse) + { + fail(UNEXPECTED_EXCEPTION_STRING + cse); + } + finally + { + amfConnection.close(); + } + } + + public void testAddRemoveAllHTTPRequestHeaders() + { + AMFConnection amfConnection = new AMFConnection(); + try + { + amfConnection.connect(getConnectionUrl()); + Assert.assertEquals(getConnectionUrl(), amfConnection.getUrl()); + amfConnection.addHttpRequestHeader(FOO_STRING,BAR_STRING); + amfConnection.addHttpRequestHeader(BAR_STRING,FOO_STRING); + amfConnection.removeAllHttpRequestHeaders(); + Assert.assertTrue(true); + } + catch (ClientStatusException cse) + { + fail(UNEXPECTED_EXCEPTION_STRING + cse); + } + finally + { + amfConnection.close(); + } + } + + public void testRemoveAMFHeader() + { + boolean retAMF; + AMFConnection amfConnection = new AMFConnection(); + try + { + amfConnection.connect(getConnectionUrl()); + Assert.assertEquals(getConnectionUrl(), amfConnection.getUrl()); + retAMF = amfConnection.removeAmfHeader(FOO_STRING); + Assert.assertFalse(retAMF); + } + catch (ClientStatusException cse) + { + fail(UNEXPECTED_EXCEPTION_STRING + cse); + } + finally + { + amfConnection.close(); + } + } + + public void testRemoveAllAMFHeaders() + { + AMFConnection amfConnection = new AMFConnection(); + try + { + amfConnection.connect(getConnectionUrl()); + Assert.assertEquals(getConnectionUrl(), amfConnection.getUrl()); + amfConnection.removeAllAmfHeaders(); + Assert.assertTrue(true); + } + catch (ClientStatusException cse) + { + fail(UNEXPECTED_EXCEPTION_STRING + cse); + } + finally + { + amfConnection.close(); + } + } + + public void testRemoveHTTPRequestHeader() + { + boolean retHttp; + AMFConnection amfConnection = new AMFConnection(); + try + { + amfConnection.connect(getConnectionUrl()); + Assert.assertEquals(getConnectionUrl(), amfConnection.getUrl()); + retHttp = amfConnection.removeHttpRequestHeader(FOO_STRING); + Assert.assertFalse(retHttp); + } + catch (ClientStatusException cse) + { + fail(UNEXPECTED_EXCEPTION_STRING + cse); + } + finally + { + amfConnection.close(); + } + } + + public void testRemoveAllHTTPRequestHeaders() + { + AMFConnection amfConnection = new AMFConnection(); + try + { + amfConnection.connect(getConnectionUrl()); + Assert.assertEquals(getConnectionUrl(), amfConnection.getUrl()); + amfConnection.removeAllHttpRequestHeaders(); + Assert.assertTrue(true); + } + catch (ClientStatusException cse) + { + fail(UNEXPECTED_EXCEPTION_STRING + cse); + } + finally + { + amfConnection.close(); + } + } + + + public void testInstantiateTypes() + { + String method = "getObject2"; + try + { + AMFConnection amfConnection = new AMFConnection(); + amfConnection.connect(getConnectionUrl()); + + // First, make sure we get the strong type. + Object result = amfConnection.call(getOperationCall(method)); + Assert.assertTrue(result instanceof ClientCustomType); + + // Now, call again with instantiateTypes=false and expect an Object. + amfConnection.setInstantiateTypes(false); + result = amfConnection.call(getOperationCall(method)); + Assert.assertTrue(!(result instanceof ClientCustomType)); + amfConnection.close(); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + + public void testSetGetAMFTrace() + { + AMFConnection amfConnection = new AMFConnection(); + try + { + AmfTrace trace = new AmfTrace(); + amfConnection.connect(getConnectionUrl()); + amfConnection.setAmfTrace(trace); + + String stringToEcho = DEFAULT_METHOD_ARG + 1; + Object result = amfConnection.call(DEFAULT_AMF_OPERATION, stringToEcho); + Assert.assertEquals(stringToEcho, result); + + if (trace.toString().length() > 0) Assert.assertTrue(true); + else fail("AmfTrace did not get anything: " + trace.toString() + " " + trace.toString().length()); + + amfConnection.close(); + + } + catch (ClientStatusException cse) + { + fail(UNEXPECTED_EXCEPTION_STRING + cse); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + finally + { + amfConnection.close(); + } + } + + public void testHTTPProxy() + { + AMFConnection amfconn = new AMFConnection(); + try + { + amfconn.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("localhost", 8888))); + amfconn.connect("http://localhost:8400/team/messagebroker/amf"); + RemotingMessage call = new RemotingMessage(); + call.setHeader("DSId", "" + System.identityHashCode(amfconn)); + call.setClientId("ro"); + call.setDestination("remoting_AMF"); + call.setMessageId("12345"); + call.setOperation("echo"); + call.setBody("hello"); + amfconn.call("foo", call); + fail("ClientStatusException expected"); + } + catch (ClientStatusException cse) + { + Assert.assertEquals(ClientStatusException.AMF_CALL_FAILED_CODE, cse.getCode()); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + finally + { + amfconn.close(); + } + } + + // A simple interface to handle AMF call results. + private interface CallResultHandler + { + void onResult(Object result); + } + + // Helper method used by JUnit tests to pass in an operation and method argument + // When the AMF call returns, CallResultHandler.onResult is called to Assert things. + private void internalTestCall(String operation, Object methodArg, CallResultHandler resultHandler) throws ClientStatusException, ServerStatusException + { + AMFConnection amfConnection = new AMFConnection(); + // Connect. + amfConnection.connect(getConnectionUrl()); + // Make a remoting call and retrieve the result. + Object result; + if (methodArg == null) + result = amfConnection.call(operation); + else + result = amfConnection.call(operation, methodArg); + resultHandler.onResult(result); + amfConnection.close(); + } +} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/a09196c2/remoting/src/test/java/flex/messaging/io/amf/client/AMFDataTypeIT.java ---------------------------------------------------------------------- diff --git a/remoting/src/test/java/flex/messaging/io/amf/client/AMFDataTypeIT.java b/remoting/src/test/java/flex/messaging/io/amf/client/AMFDataTypeIT.java new file mode 100644 index 0000000..0347a20 --- /dev/null +++ b/remoting/src/test/java/flex/messaging/io/amf/client/AMFDataTypeIT.java @@ -0,0 +1,534 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 flex.messaging.io.amf.client; + +import java.util.Date; +import java.util.List; + +import flex.messaging.io.SerializationContext; +import flex.messaging.util.TestServerWrapper; +import junit.extensions.TestSetup; +import org.w3c.dom.Document; + +import org.junit.Assert; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import amfclient.ClientCustomType; + +import flex.messaging.io.amf.client.exceptions.ClientStatusException; +import flex.messaging.io.amf.client.exceptions.ServerStatusException; +import flex.messaging.util.XMLUtil; + +/** + * JUnit tests for AMFConnection. Note that most of the tests require a running + * server with the specified destination. + */ +public class AMFDataTypeIT extends TestCase +{ + private static final String DEFAULT_DESTINATION_ID = "amfConnectionTestService"; + private static final String DEFAULT_METHOD_NAME = "echoString"; + private static final String DEFAULT_METHOD_ARG = "echo me"; + private static final String DEFAULT_URL = "http://localhost:%s/qa-regress/messagebroker/amf"; + private static final String DEFAULT_AMF_OPERATION = getOperationCall(DEFAULT_METHOD_NAME); + private static final String UNEXPECTED_EXCEPTION_STRING = "Unexpected exception: "; + + private static TestServerWrapper serverWrapper; + private static int serverPort; + private static SerializationContext serializationContext; + + /** + * Given a remote method name, returns the AMF connection call needed using + * the default destination id. + */ + private static String getOperationCall(String method) + { + return DEFAULT_DESTINATION_ID + "." + method; + } + + protected String getConnectionUrl() { + return String.format(DEFAULT_URL, serverPort); + } + + + public AMFDataTypeIT(String name) + { + super(name); + } + + public static Test suite() + { + //TestSuite suite = new TestSuite(AMFDataTypeIT.class); + TestSuite suite = new TestSuite(); + suite.addTest(new AMFDataTypeIT("testCallStringArgStringReturn")); + suite.addTest(new AMFDataTypeIT("testCallIntArgIntReturn")); + suite.addTest(new AMFDataTypeIT("testCallBooleanArgBooleanReturn")); + suite.addTest(new AMFDataTypeIT("testCallObjectArgObjectReturn")); + suite.addTest(new AMFDataTypeIT("testCallObjectArgCustomReturn")); + suite.addTest(new AMFDataTypeIT("testCallCustomArgObjectReturn")); + suite.addTest(new AMFDataTypeIT("testCallCustomArgCustomReturn")); + suite.addTest(new AMFDataTypeIT("testCallNoArgObjectReturn")); + suite.addTest(new AMFDataTypeIT("testCallNoArgCustomReturn")); + suite.addTest(new AMFDataTypeIT("testCallNoArgObjectArrayReturn")); + suite.addTest(new AMFDataTypeIT("testCallDateArgDateReturn")); + suite.addTest(new AMFDataTypeIT("testCallShortArgShortReturn")); + suite.addTest(new AMFDataTypeIT("testCallDoubleArgDoubleReturn")); + suite.addTest(new AMFDataTypeIT("testCallIntArrayArgIntArrayReturn")); + suite.addTest(new AMFDataTypeIT("testCallObjectArrayArgObjectArrayReturn")); + suite.addTest(new AMFDataTypeIT("testXMLDocumentEnabledXml")); + suite.addTest(new AMFDataTypeIT("testXMLDocumentDisabledXml")); + + + return new TestSetup(suite) { + protected void setUp() throws Exception { + serverWrapper = new TestServerWrapper(); + serverPort = serverWrapper.startServer("classpath:/WEB-INF/flex/services-config.xml"); + if(serverPort == -1) { + Assert.fail("Couldn't start server process"); + } + AMFConnection.registerAlias( + "remoting.amfclient.ServerCustomType" /* server type */, + "amfclient.ClientCustomType" /* client type */); + + serializationContext = new SerializationContext(); + serializationContext.createASObjectForMissingType = true; + // Make sure collections are written out as Arrays (vs. ArrayCollection), + // in case the server does not recognize ArrayCollections. + serializationContext.legacyCollection = true; + // When legacyMap is true, Java Maps are serialized as ECMA arrays + // instead of anonymous Object. + serializationContext.legacyMap = true; + // Disable serialization of xml documents. + serializationContext.allowXml = false; + } + protected void tearDown() throws Exception { + serverWrapper.stopServer(); + serverWrapper = null; + } + }; + } + + public void testCallStringArgStringReturn() + { + try + { + internalTestCall(DEFAULT_AMF_OPERATION, DEFAULT_METHOD_ARG, new CallResultHandler(){ + public void onResult(Object result) + { + Assert.assertEquals(DEFAULT_METHOD_ARG, result); + } + }); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + + public void testCallIntArgIntReturn() + { + String method = "echoInt"; + final int methodArg = 1; + try + { + internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + public void onResult(Object result) + { + Assert.assertEquals(methodArg, ((Double)result).intValue()); + } + }); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + + public void testCallBooleanArgBooleanReturn() + { + try + { + String method = "echoBoolean"; + final boolean methodArg = true; + internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + public void onResult(Object result) + { + Assert.assertEquals(methodArg, result); + } + }); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + + public void testCallDateArgDateReturn() + { + String method = "echoDate"; + final Date methodArg = new Date(999991); + try + { + internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + public void onResult(Object result) + { + Assert.assertEquals(methodArg, result); + } + }); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + + public void testCallShortArgShortReturn() + { + String method = "echoShort"; + final short methodArg = 32000; + try + { + internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + public void onResult(Object result) + { + Assert.assertEquals(methodArg, ((Double)result).shortValue()); + } + }); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + + public void testCallDoubleArgDoubleReturn() + { + String method = "echoDouble"; + final double methodArg = -95.25; + try + { + internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + public void onResult(Object result) + { + Assert.assertEquals(methodArg, result); + } + }); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + + public void testCallObjectArgObjectReturn() + { + String method = "echoObject1"; + ClientCustomType temp = new ClientCustomType(); + temp.setId(1); + final Object methodArg = temp; + try + { + internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + public void onResult(Object result) + { + ClientCustomType temp2 = (ClientCustomType)result; + Assert.assertEquals(1, temp2.getId()); + } + }); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + + public void testCallObjectArgCustomReturn() + { + String method = "echoObject2"; + ClientCustomType temp = new ClientCustomType(); + temp.setId(1); + final Object methodArg = temp; + try + { + internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + public void onResult(Object result) + { + ClientCustomType temp2 = (ClientCustomType)result; + Assert.assertEquals(1, temp2.getId()); + } + }); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + + public void testCallCustomArgObjectReturn() + { + String method = "echoObject3"; + final ClientCustomType methodArg = new ClientCustomType(); + methodArg.setId(1); + try + { + internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + public void onResult(Object result) + { + ClientCustomType temp2 = (ClientCustomType)result; + Assert.assertEquals(1, temp2.getId()); + } + }); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + + public void testCallCustomArgCustomReturn() + { + String method = "echoObject4"; + final ClientCustomType methodArg = new ClientCustomType(); + methodArg.setId(1); + try + { + internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + public void onResult(Object result) + { + ClientCustomType temp2 = (ClientCustomType)result; + Assert.assertEquals(1, temp2.getId()); + } + }); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + + public void testCallNoArgObjectReturn() + { + String method = "getObject1"; + try + { + internalTestCall(getOperationCall(method), null, new CallResultHandler(){ + public void onResult(Object result) + { + ClientCustomType temp2 = (ClientCustomType)result; + Assert.assertEquals(1, temp2.getId()); + } + }); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + + public void testCallNoArgCustomReturn() + { + String method = "getObject2"; + try + { + internalTestCall(getOperationCall(method), null, new CallResultHandler(){ + public void onResult(Object result) + { + ClientCustomType temp2 = (ClientCustomType)result; + Assert.assertEquals(1, temp2.getId()); + } + }); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + + public void testCallNoArgObjectArrayReturn() + { + String method = "getObjectArray1"; + try + { + internalTestCall(getOperationCall(method), null, new CallResultHandler(){ + public void onResult(Object result) + { + List temp = (List)result; + for (int i = 0; i < temp.size(); i++) + { + ClientCustomType temp2 = (ClientCustomType)temp.get(i); + Assert.assertEquals(i, temp2.getId()); + } + } + }); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + + public void testCallIntArrayArgIntArrayReturn() + { + String method = "echoObject5"; + final int[] methodArg = new int[] {0,1,2,3}; + try + { + internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + public void onResult(Object result) + { + List temp = (List)result; + for (int i = 0; i < temp.size(); i++) + { + Assert.assertEquals(i, ((Integer)temp.get(i)).intValue()); + } + } + }); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + + public void testCallObjectArrayArgObjectArrayReturn() + { + String method = "echoObject1"; + Object[] temp = new Object[3]; + for (int i = 0; i < temp.length; i++) + { + ClientCustomType cct = new ClientCustomType(); + cct.setId(i); + temp[i] = cct; + } + final Object[] methodArg = temp; + try + { + internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + public void onResult(Object result) + { + List temp = (List)result; + for (int i = 0; i < temp.size(); i++) + { + ClientCustomType temp2 = (ClientCustomType)temp.get(i); + Assert.assertEquals(i, temp2.getId()); + } + } + }); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + + + public void testXMLDocumentEnabledXml() + { + try + { + // Temporarily enable xml serialization/deserialization. + serializationContext.allowXml = true; + + String method = "echoObject1"; + final StringBuffer xml = new StringBuffer(512); + xml.append("<test> <item id=\"1\"> <sweet/> </item></test>"); + + Document xmlDoc = XMLUtil.stringToDocument(xml.toString()); + final Object methodArg = xmlDoc; + internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + public void onResult(Object result) + { + try + { + Document retXmlDoc = (Document)result; + String retXML = XMLUtil.documentToString(retXmlDoc); + Assert.assertEquals(xml.toString(), retXML); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + }); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + finally { + // Disable xml serialization/deserialization again. + serializationContext.allowXml = false; + } + } + + + public void testXMLDocumentDisabledXml() + { + try + { + String method = "echoObject1"; + final StringBuffer xml = new StringBuffer(512); + xml.append("<test> <item id=\"1\"> <sweet/> </item></test>"); + + Document xmlDoc = XMLUtil.stringToDocument(xml.toString()); + final Object methodArg = xmlDoc; + internalTestCall(getOperationCall(method), methodArg, new CallResultHandler(){ + public void onResult(Object result) + { + try + { + Document retXmlDoc = (Document)result; + String retXML = XMLUtil.documentToString(retXmlDoc); + Assert.assertEquals("", retXML); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + }); + } + catch (Exception e) + { + fail(UNEXPECTED_EXCEPTION_STRING + e); + } + } + + // A simple interface to handle AMF call results. + private interface CallResultHandler + { + void onResult(Object result); + } + + // Helper method used by JUnit tests to pass in an operation and method argument + // When the AMF call returns, CallResultHandler.onResult is called to Assert things. + private void internalTestCall(String operation, Object methodArg, CallResultHandler resultHandler) throws ClientStatusException, ServerStatusException + { + AMFConnection amfConnection = new AMFConnection(); + // Connect. + amfConnection.connect(getConnectionUrl(), serializationContext); + // Make a remoting call and retrieve the result. + Object result; + if (methodArg == null) + result = amfConnection.call(operation); + else + result = amfConnection.call(operation, methodArg); + resultHandler.onResult(result); + amfConnection.close(); + } +} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/a09196c2/remoting/src/test/java/flex/messaging/util/TestServer.java ---------------------------------------------------------------------- diff --git a/remoting/src/test/java/flex/messaging/util/TestServer.java b/remoting/src/test/java/flex/messaging/util/TestServer.java new file mode 100644 index 0000000..df21561 --- /dev/null +++ b/remoting/src/test/java/flex/messaging/util/TestServer.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 flex.messaging.util; + +import flex.messaging.MessageBrokerServlet; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; + +/** + * Simple little wrapper starting up a BlazeDS server in a separate VM useful for unit testing the + * features that need different singletons in client and server. + */ +public class TestServer { + + public static void main(String args[]) throws Exception { + if(args.length != 1) { + throw new Exception("Need exactly two argument containing th path to the configuration " + + "followed by the port number the server should use"); + } + final String configPath = args[0]; + + // Setup a minimal servlet context for hosting our message broker servlet. + final Server server = new Server(0); + final ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); + context.setContextPath("/qa-regress"); + final MessageBrokerServlet messageBrokerServlet = new MessageBrokerServlet(); + final ServletHolder servlet = new ServletHolder(messageBrokerServlet); + servlet.setInitParameter("services.configuration.file", configPath); + context.addServlet(servlet, "/messagebroker/amf/*"); + server.setHandler(context); + server.setDumpAfterStart(true); + try { + server.start(); + } catch(Exception e) { + e.printStackTrace(); + } + + int port = ((ServerConnector) server.getConnectors()[0]).getLocalPort(); + System.out.println("Port:" + port); + } +} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/a09196c2/remoting/src/test/java/flex/messaging/util/TestServerWrapper.java ---------------------------------------------------------------------- diff --git a/remoting/src/test/java/flex/messaging/util/TestServerWrapper.java b/remoting/src/test/java/flex/messaging/util/TestServerWrapper.java new file mode 100644 index 0000000..b9fb954 --- /dev/null +++ b/remoting/src/test/java/flex/messaging/util/TestServerWrapper.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 flex.messaging.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * Simple little wrapper starting up a BlazeDS server in a separate VM useful for unit testing the + * features that need different singletons in client and server. + */ +public class TestServerWrapper { + + private Process serverProcess; + + public int startServer(String configPath) { + // We can only start one server per instance of TestServer. + if(serverProcess != null) { + return -1; + } + + final String separator = System.getProperty("file.separator"); + final String classpath = System.getProperty("java.class.path"); + final String path = System.getProperty("java.home") + separator + "bin" + separator + "java"; + System.out.print("Starting test-server"); + final ProcessBuilder processBuilder = new ProcessBuilder(path, + "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005", + "-cp", /*"\"" +*/ classpath /*+ "\""*/, + TestServer.class.getCanonicalName(), /*"\"" +*/ configPath /*+ "\""*/); + processBuilder.redirectErrorStream(true); + try { + serverProcess = processBuilder.start(); + + BufferedReader in = new BufferedReader(new InputStreamReader(serverProcess.getInputStream())); + + String line; + while((line = in.readLine()) != null) { + if(line.startsWith("Port:")) { + // Read the process output and extract the port + // number the server started on. + int port = Integer.parseInt(line.substring(5)); + System.out.println("STARTED on port " + port); + return port; + } + } + + return -1; + } catch (IOException e) { + System.out.println("ERROR: " + e.toString()); + return -1; + } + } + + public void stopServer() { + if(serverProcess != null) { + System.out.print("Stopping test-server ... "); + // Send a signal to the server process to make itself shut down. + serverProcess.destroy(); + System.out.println("STOPPED"); + } + } + +} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/a09196c2/remoting/src/test/resources/WEB-INF/flex/remoting-config.xml ---------------------------------------------------------------------- diff --git a/remoting/src/test/resources/WEB-INF/flex/remoting-config.xml b/remoting/src/test/resources/WEB-INF/flex/remoting-config.xml new file mode 100644 index 0000000..73e28c1 --- /dev/null +++ b/remoting/src/test/resources/WEB-INF/flex/remoting-config.xml @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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. + +--> +<service id="remoting-service" class="flex.messaging.services.RemotingService"> + + <!-- + The set of adapters available for this service. A service uses an + adapter to handle the implementation specifc details of a + destination. + --> + <adapters> + <!-- + id: A unique id for this adapter-definition. Destinations use this + id to select which adapter should be used to process requests. + class: The implementation class for the adapter. A single Remoting + Service adapter ships with Flex 2: + flex.messaging.services.remoting.adapters.JavaAdapter + default: An optional boolean attribute identifying the adapter to + use when none is specified for a destination. + --> + <adapter-definition id="java-object" + class="flex.messaging.services.remoting.adapters.JavaAdapter" + default="true"/> + </adapters> + + <!-- + The set of default channels to use to transport messages to + remoting-service destinations. + --> + <default-channels> + <channel ref="amf"/> + </default-channels> + + <!-- This destination is used by AMFConnectionIT JUnit test --> + <destination id="amfConnectionTestService" channels="amf"> + <properties> + <source>remoting.amfclient.AMFConnectionTestService</source> + </properties> + <adapter ref="java-object"/> + </destination> + +</service> http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/a09196c2/remoting/src/test/resources/WEB-INF/flex/services-config.xml ---------------------------------------------------------------------- diff --git a/remoting/src/test/resources/WEB-INF/flex/services-config.xml b/remoting/src/test/resources/WEB-INF/flex/services-config.xml new file mode 100644 index 0000000..2bbf7d7 --- /dev/null +++ b/remoting/src/test/resources/WEB-INF/flex/services-config.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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. + +--> +<services-config> + + <services> + <service-include file-path="remoting-config.xml" /> + </services> + + <channels> + <channel-definition id="amf" class="mx.messaging.channels.AMFChannel"> + <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/> + <properties> + <serialization> + <allow-xml>true</allow-xml> + </serialization> + </properties> + </channel-definition> + </channels> + + <logging> + <target class="flex.messaging.log.ConsoleTarget" level="Error"> + <properties> + <prefix>[BlazeDS] </prefix> + <includeDate>false</includeDate> + <includeTime>false</includeTime> + <includeLevel>false</includeLevel> + <includeCategory>false</includeCategory> + </properties> + <filters> + <pattern>Endpoint.*</pattern> + <pattern>Service.*</pattern> + <pattern>Configuration</pattern> + </filters> + </target> + </logging> + +</services-config>
