| /* |
| * 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.amfx; |
| |
| import flex.messaging.validators.ClassDeserializationValidator; |
| import junit.framework.TestCase; |
| import junit.framework.Test; |
| import junit.framework.TestSuite; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.File; |
| import java.io.FilenameFilter; |
| import java.io.FileInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.ByteArrayInputStream; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| |
| import flex.messaging.io.SerializationContext; |
| import flex.messaging.io.amf.ActionContext; |
| import flex.messaging.io.amf.ActionMessage; |
| import flex.messaging.io.amf.AmfTrace; |
| import flex.messaging.io.amf.MessageBody; |
| import flex.messaging.io.amf.MessageHeader; |
| import flex.messaging.MessageException; |
| |
| /** |
| * Runs through an extensive suite of deserialization |
| * test cases for AMFX data types and message structures. |
| * |
| * The first step is to turn an XML file into an AMFX request. |
| * If the request is not a negative test then it is reserialized |
| * back to XML to test the serializer. Finally, the serialized |
| * XML is re-deserialized back into a request and once more |
| * tested. |
| */ |
| public class AmfxSerializationTest extends TestCase |
| { |
| private String resourceBase = "/flex/messaging/io/amfx/"; |
| private String baseFilePath; |
| private SerializationContext serializationContext; |
| private AmfTrace trace; |
| |
| public AmfxSerializationTest(String name) |
| { |
| super(name); |
| } |
| |
| public static Test suite() |
| { |
| return new TestSuite(AmfxSerializationTest.class); |
| } |
| |
| protected void setUp() throws Exception |
| { |
| super.setUp(); |
| ClassDeserializationValidator classDeserializationValidator = new ClassDeserializationValidator(); |
| classDeserializationValidator.addAllowClassPattern("flex.messaging.io.amfx.testtypes.*"); |
| serializationContext = new SerializationContext(); |
| serializationContext.setDeserializationValidator(classDeserializationValidator); |
| SerializationContext.setSerializationContext(serializationContext); |
| //trace = new AmfTrace(); |
| } |
| |
| protected void tearDown() throws Exception |
| { |
| super.tearDown(); |
| SerializationContext.setSerializationContext(null); |
| trace = null; |
| } |
| |
| public void testSerialization() |
| { |
| try |
| { |
| URL url = this.getClass().getResource(resourceBase + "AmfxSerializationTest.class"); |
| File file = new File(url.getFile()); |
| File dir = new File(file.getParent()); |
| |
| baseFilePath = dir.getAbsolutePath(); |
| |
| if (dir.isDirectory()) |
| { |
| String resourcePath = getResourcePath(baseFilePath); |
| processDirectory(dir, resourcePath); |
| } |
| } |
| catch (IOException ioe) |
| { |
| fail("AMFX deserialization test failed: " + ioe.getMessage()); |
| } |
| finally |
| { |
| if (trace != null) |
| System.out.println(trace.toString()); |
| } |
| } |
| |
| private void processDirectory(File dir, String resourcePath) throws IOException |
| { |
| File[] files = dir.listFiles(new XMLFilenameFilter()); |
| |
| for (int i = 0; i < files.length; i++) |
| { |
| File f = files[i]; |
| if (f.isDirectory()) |
| { |
| resourcePath = getResourcePath(f.getAbsolutePath()); |
| processDirectory(f, resourcePath); |
| } |
| else |
| { |
| String testName = getTestName(f.getName()); |
| System.out.println("Running test: " + testName); |
| |
| FileInputStream fis = new FileInputStream(f); |
| |
| processRequest(resourcePath, testName, fis); |
| } |
| } |
| } |
| |
| private String getResourcePath(String path) |
| { |
| if (path.startsWith(baseFilePath)) |
| { |
| path = path.substring(baseFilePath.length()); |
| path = path.replace('\\', '/'); |
| return path; |
| } |
| |
| return null; |
| } |
| |
| private String getTestName(String fileName) |
| { |
| fileName = fileName.toLowerCase(); |
| int pos = fileName.indexOf(".xml"); |
| return fileName.substring(0, pos); |
| } |
| |
| private void processRequest(String resourcePath, String testName, InputStream is) throws IOException |
| { |
| try |
| { |
| SerializationContext.setSerializationContext((SerializationContext)serializationContext.clone()); |
| // STEP 1. Deserialize Message |
| ActionContext context = new ActionContext(); |
| context.setResponseMessage(new ActionMessage()); |
| |
| ActionMessage requestMessage = new ActionMessage(); |
| context.setRequestMessage(requestMessage); |
| AmfxMessageDeserializer deserializer = new AmfxMessageDeserializer(); |
| deserializer.initialize(serializationContext, is, trace); |
| |
| if (trace != null) |
| trace.startRequest("Deserializing AMF/HTTP request"); |
| |
| DeserializationConfirmation confirm = getConfirmation(resourcePath, testName); |
| confirm.setContext(serializationContext); |
| try |
| { |
| deserializer.readMessage(requestMessage, context); |
| } |
| catch (MessageException me) // For negative tests that cause MessageExceptions. |
| { |
| if (!confirm.isNegativeTest()) |
| fail("Only negative tests might cause MessageExceptions: " + testName); |
| } |
| |
| if (!confirm.isNegativeTest() && !confirm.successMatches(requestMessage)) |
| fail("ActionMessage did not match test: " + testName); |
| |
| // STEP 2. Re-serialize Message (Negative tests won't make it this far...) |
| |
| // create the response body |
| if (requestMessage.getBodyCount() > 0 || requestMessage.getHeaderCount() > 0) |
| { |
| ActionMessage responseMessage = context.getResponseMessage(); |
| |
| if (requestMessage.getBodyCount() > 0) |
| { |
| ArrayList bodies = requestMessage.getBodies(); |
| Iterator it = bodies.iterator(); |
| while (it.hasNext()) |
| { |
| MessageBody requestBody = (MessageBody)it.next(); |
| MessageBody responseBody = new MessageBody(); |
| responseBody.setData(requestBody.getData()); |
| responseMessage.addBody(responseBody); |
| } |
| } |
| |
| if (requestMessage.getHeaderCount() > 0) |
| { |
| ArrayList headers = requestMessage.getHeaders(); |
| Iterator it = headers.iterator(); |
| while (it.hasNext()) |
| { |
| responseMessage.addHeader((MessageHeader)it.next()); |
| } |
| } |
| |
| if (trace != null) |
| trace.startRequest("Serializing AMF/HTTP request"); |
| |
| ByteArrayOutputStream bout = new ByteArrayOutputStream(); |
| |
| AmfxMessageSerializer serializer = new AmfxMessageSerializer(); |
| serializer.initialize(serializationContext, bout, trace); |
| serializer.writeMessage(responseMessage); |
| |
| // STEP 3. Deserialize Message once more... |
| requestMessage = new ActionMessage(); |
| context.setRequestMessage(requestMessage); |
| |
| ByteArrayInputStream bis = new ByteArrayInputStream(bout.toByteArray()); |
| |
| deserializer = new AmfxMessageDeserializer(); |
| deserializer.initialize(serializationContext, bis, trace); |
| |
| if (trace != null) |
| trace.startRequest("Deserializing AMF/HTTP request"); |
| |
| deserializer.readMessage(requestMessage, context); |
| |
| confirm.setContext(serializationContext); |
| |
| if (!confirm.successMatches(requestMessage)) |
| fail("ActionMessage did not match test on deserialization after re-serialization: " + testName); |
| } |
| } |
| catch (MessageException ex) |
| { |
| throw ex; |
| } |
| finally |
| { |
| SerializationContext.setSerializationContext(null); |
| } |
| |
| } |
| |
| private DeserializationConfirmation getConfirmation(String resourcePath, String testName) throws IOException |
| { |
| try |
| { |
| if (resourceBase.endsWith("/") && resourcePath.startsWith("/")) |
| resourcePath = resourcePath.substring(1); |
| |
| String resource = resourceBase + resourcePath; |
| if (resource.startsWith("/")) |
| resource = resource.substring(1); |
| |
| String packageName = resource.replace('/', '.'); |
| |
| if (packageName.length() > 0 && !packageName.endsWith(".")) |
| packageName = packageName + "."; |
| |
| String className = packageName + "Confirm" + testName; |
| Class c = Class.forName(className); |
| |
| Object obj = c.newInstance(); |
| DeserializationConfirmation confirm = (DeserializationConfirmation)obj; |
| return confirm; |
| } |
| catch (Exception e) |
| { |
| throw new IOException("Unable to load confirmation for testName: " + testName + " in " + resourcePath); |
| } |
| } |
| |
| static class XMLFilenameFilter implements FilenameFilter |
| { |
| public boolean accept(File dir, String name) |
| { |
| String child = dir.getAbsolutePath() + File.separator + name; |
| |
| File f = new File(child); |
| |
| if (f.isDirectory() && !name.startsWith(".svn")) |
| return true; |
| else if (name.toLowerCase().endsWith(".xml")) |
| return true; |
| else |
| return false; |
| } |
| } |
| |
| } |