/******************************************************************** * Copyright (c) 2006 Contributors. All rights reserved. * This program and the accompanying materials are made available * under the terms of the Eclipse Public License v1.0 * which accompanies this distribution and is available at * http://eclipse.org/legal/epl-v10.html * * 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.Iterator; import java.util.List; import org.aspectj.asm.AsmManager; import org.aspectj.asm.IElementHandleProvider; import org.aspectj.asm.IModelFilter; import org.aspectj.asm.internal.JDTLikeHandleProvider; 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 handleProvider = AsmManager.getDefault().getHandleProvider(); AsmManager.getDefault().setHandleProvider(new JDTLikeHandleProvider()); // 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().getAbsolutePath())); } 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.getDefault().setHandleProvider(handleProvider); 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 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) { fileContents.add(expectedLine); } List expectedFileContents = new ArrayList(); expectedFileContents.addAll(fileContents); // Load the file with the output from this test run BufferedReader found = new BufferedReader(new FileReader(new File(modelOutput))); String foundLine = null; List foundFileContents = new ArrayList(); while((foundLine=found.readLine())!=null) { // 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 (Iterator iter = foundFileContents.iterator(); iter.hasNext();) { String line = (String) iter.next(); 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 (Iterator iterator = fileContents.iterator(); iterator .hasNext();) { String element = (String) iterator.next(); 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 (Iterator iter = fileContents.iterator(); iter .hasNext();) { String element = (String) iter.next(); 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()); } } }