blob: eb3b32b3381d7a29d84894e3a446b38cbd5d3aa9 [file] [log] [blame]
/*
* 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;
}
}
}