/******************************************************************** * 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/ and that the expected model against which to do the comparison is in the file * ../tests/model/expected/.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(,<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()); } } }