| /* |
| * 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.MessageException; |
| import flex.messaging.io.SerializationContext; |
| import flex.messaging.io.amf.*; |
| import flex.messaging.validators.ClassDeserializationValidator; |
| import org.junit.After; |
| import org.junit.Assert; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| import java.io.*; |
| import java.net.URL; |
| import java.util.ArrayList; |
| |
| /** |
| * Runs through an extensive suite of deserialization |
| * test cases for AMFX data types and message structures. |
| * <p> |
| * 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 { |
| private String resourceBase = "/flex/messaging/io/amfx/"; |
| private String baseFilePath; |
| private SerializationContext serializationContext; |
| private AmfTrace trace; |
| |
| @Before |
| public void setUp() throws Exception { |
| ClassDeserializationValidator classDeserializationValidator = new ClassDeserializationValidator(); |
| classDeserializationValidator.addAllowClassPattern("flex.messaging.io.amfx.testtypes.*"); |
| serializationContext = new SerializationContext(); |
| serializationContext.setDeserializationValidator(classDeserializationValidator); |
| SerializationContext.setSerializationContext(serializationContext); |
| //trace = new AmfTrace(); |
| } |
| |
| @After |
| public void tearDown() throws Exception { |
| SerializationContext.setSerializationContext(null); |
| trace = null; |
| } |
| |
| @Test |
| 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) { |
| Assert.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()); |
| |
| if (files != null) { |
| for (File f : files) { |
| 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()) { |
| Assert.fail("Only negative tests might cause MessageExceptions: " + testName); |
| } |
| } |
| |
| if (!confirm.isNegativeTest() && !confirm.successMatches(requestMessage)) { |
| Assert.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(); |
| for (Object body : bodies) { |
| MessageBody requestBody = (MessageBody) body; |
| MessageBody responseBody = new MessageBody(); |
| responseBody.setData(requestBody.getData()); |
| responseMessage.addBody(responseBody); |
| } |
| } |
| |
| if (requestMessage.getHeaderCount() > 0) { |
| ArrayList headers = requestMessage.getHeaders(); |
| for (Object header : headers) { |
| responseMessage.addHeader((MessageHeader) header); |
| } |
| } |
| |
| 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)) { |
| Assert.fail("ActionMessage did not match test on deserialization after re-serialization: " + testName); |
| } |
| } |
| } 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(); |
| return (DeserializationConfirmation) obj; |
| } 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; |
| } |
| } |
| } |
| |
| } |