blob: 84c32d25be7e758df06a720fc661e92ce281eff9 [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.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;
}
}
}
}