ModelTestCase.java
/********************************************************************
* Copyright (c) 2006 Contributors. All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v 2.0
* which accompanies this distribution and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
*
* Contributors: IBM Corporation - initial API and implementation
* Helen Hawkins - initial version
*******************************************************************/
package org.aspectj.systemtest.model;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.aspectj.asm.AsmManager;
import org.aspectj.asm.IElementHandleProvider;
import org.aspectj.asm.IModelFilter;
import org.aspectj.testing.XMLBasedAjcTestCase;
import org.aspectj.util.FileUtil;
/**
* This class provides an extension to the XMLBasedAjcTestCase to manage testing the model. It assumes the testdata is in
* ../tests/model/<testid> and that the expected model against which to do the comparison is in the file
* ../tests/model/expected/<testid>.txt. One test ensures that both the model and the relationship map are as expected for the given
* testdata.
*
* To write a testcase, create a testdata directory containing the data for the test run and a file containing the expected model
* (this can be generated by setting the regenerate flag to true). Add the required configuration to model.xml. Finally, create a
* testcase in either ModelTests or Model5Tests (depending on whether the testcase has a requirement on Java5) and call
* runModelTest(<title of test>,<testid>).
*/
public abstract class ModelTestCase extends XMLBasedAjcTestCase {
protected static boolean regenerate = false;
protected static boolean debugTest = false;
private final String expectedOutDir = "../tests/model/expected" + File.separator;
private String testid;
private String modelFilename;
private IElementHandleProvider handleProvider;
/*
* (non-Javadoc)
*
* @see junit.framework.TestCase#setUp()
*/
protected void setUp() throws Exception {
super.setUp();
// using the JDTLikeHandleProvider because this produces consistent handles
// over different compiles
// We are about to create a sandbox for the model output file, don't let the
// following compile wipe it.
ajc.setShouldEmptySandbox(false);
// report all information - model, relationships delta processing
modelFilename = ajc.getSandboxDirectory().getAbsolutePath() + File.separator + "model.txt";
AsmManager.setReporting(modelFilename, true, true, true, false,
new TestFilter(ajc.getSandboxDirectory().getCanonicalPath()));
}
static class TestFilter implements IModelFilter {
String sandboxDirectory;
public TestFilter(String sandboxDirectory) {
this.sandboxDirectory = sandboxDirectory;
}
public String processFilelocation(String loc) {
if (loc.toLowerCase().startsWith(sandboxDirectory.toLowerCase())) {
String sub = loc.substring(sandboxDirectory.length());
int forwardSlash = sub.indexOf("/");
// replace all "/" with "\" - to ensure platform independence
if (forwardSlash != -1) {
sub = sub.replace('/', '\\');
}
// don't report the column number since this is sometimes
// different on windows and linux
int column = sub.lastIndexOf(':');
if (column != -1) {
return "TEST_SANDBOX" + sub.substring(0, column);
}
return "TEST_SANDBOX" + sub;
}
return loc;
}
public boolean wantsHandleIds() {
return false;
}
}
/*
* (non-Javadoc)
*
* @see junit.framework.TestCase#tearDown()
*/
protected void tearDown() throws Exception {
super.tearDown();
AsmManager.setDontReport();
ajc.setShouldEmptySandbox(true);
}
/**
* Firstly sets the testid which is both the name of the expected output file and the name of the testdata directory. It then
* invokes XMLBasedAjcTestCase.runTest(String) with the given title and finally verifies that the model file created from this
* test run is the same as the expected output (includes model information, the relationship map and various properties about
* the model) contained in ../tests/model/expected/<testid>.txt
*/
protected void runModelTest(String title, String testid) {
this.testid = testid;
runTest(title);
verifyModel();
}
private void verifyModel() {
File expectedOutput = new File(expectedOutDir + testid + ".txt");
if (regenerate) {
// Create the file
saveModel(expectedOutput);
} else {
// Verify the file matches what we have
compareModel(expectedOutput);
}
}
private void compareModel(File expectedF) {
if (debugTest)
System.out.println("comparing with model in file " + expectedF.getAbsolutePath());
List<String> fileContents = new ArrayList<>();
try {
// String sandboxDir = ajc.getSandboxDirectory().getAbsolutePath();
String modelOutput = modelFilename;
// Load the file with the expected output
BufferedReader expect = new BufferedReader(new FileReader(expectedF));
// String tempDir = expect.readLine();
String expectedLine = null;
while ((expectedLine = expect.readLine()) != null) {
// Remove trailing whitespace
expectedLine = expectedLine.replaceAll("[\t ]+$", "");
fileContents.add(expectedLine);
}
List<String> expectedFileContents = new ArrayList<>(fileContents);
// Load the file with the output from this test run
BufferedReader found = new BufferedReader(new FileReader(new File(modelOutput)));
String foundLine = null;
List<String> foundFileContents = new ArrayList<>();
while ((foundLine = found.readLine()) != null) {
// Remove trailing whitespace
foundLine = foundLine.replaceAll("[\t ]+$", "");
// int i = foundLine.indexOf(sandboxDir);
// if (i == -1) {
// int j = foundLine.indexOf("(targets=");
// if (j == -1) {
foundFileContents.add(foundLine);
// } else {
// foundFileContents.add(foundLine.substring(j));
// }
// } else {
// String newLine = foundLine.substring(0,i) + tempDir
// + foundLine.substring(i + sandboxDir.length());
// foundFileContents.add(newLine);
// }
}
// iterate over what we found
for (String line : foundFileContents) {
if (debugTest)
System.err.println("looking at model entry: " + line);
if (!fileContents.contains(line)) {
// if (!((String)fileContents.get(lineNumber)).equals(line)) {
if (debugTest) {
System.err.println("couldn't find: " + line);
for (String element : fileContents) {
System.err.println("compared with: " + element);
}
}
// StringBuffer errorData = new StringBuffer();
// errorData.append("Problem with comparison at line number: "+)
fail("couldn't find model entry '" + line + "' in expected output");
} else {
fileContents.remove(line);
}
}
if (debugTest && !fileContents.isEmpty()) {
for (String element : fileContents) {
System.err.println("remaining: " + element);
}
}
assertTrue("should have found all expected model output: " + fileContents, fileContents.isEmpty());
} catch (Exception e) {
fail("Unexpected exception comparing model files:" + e);
}
}
private void saveModel(File f) {
if (debugTest)
System.out.println("Saving model into " + f.getAbsolutePath());
File modelFile = new File(modelFilename);
try {
FileUtil.copyFile(modelFile, f);
} catch (IOException ioe) {
ioe.printStackTrace();
fail("Couldn't copy file to " + f.toString());
}
}
}