/* ******************************************************************* * Copyright (c) 1999-2001 Xerox Corporation, * 2002 Palo Alto Research Center, Incorporated (PARC) * 2003 Contributors. * 2005 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://www.eclipse.org/legal/epl-v10.html * * Contributors: * Xerox/PARC initial implementation * IBM ongoing maintenance * ******************************************************************/ package org.aspectj.tools.ant.taskdefs; import java.io.BufferedReader; import java.io.File; import java.io.FileFilter; import java.io.FileReader; import java.io.IOException; import java.io.PrintStream; import java.util.ArrayList; import java.util.Arrays; import java.util.jar.JarEntry; import java.util.jar.JarFile; import junit.framework.TestCase; import org.apache.tools.ant.BuildEvent; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildListener; import org.apache.tools.ant.Location; import org.apache.tools.ant.Project; import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.selectors.FilenameSelector; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.IMessageHolder; import org.aspectj.bridge.MessageHandler; import org.aspectj.bridge.MessageUtil; import org.aspectj.util.FileUtil; import org.aspectj.util.LangUtil; /** * AjcTask test cases. * Please put new ones with others between ------- comments. * * Some API tests, but mostly functional tests driving * the task execute using data in ../taskdefs/testdata. * This will re-run in forked mode for any nonfailing * compile if aspectjtools-dist is built into * ../aj-build/dist/tools/lib/aspectjtools.jar. */ public class AjcTaskTest extends TestCase { private static final Class NO_EXCEPTION = null; private static final String NOFILE = "NOFILE"; private static final File tempDir; private static final String aspectjtoolsJar; private static final String testdataDir; private static final StringBuffer MESSAGES = new StringBuffer(); /** accept writable .class files */ private static FileFilter PICK_CLASS_FILES; static { tempDir = new File("IncrementalAjcTaskTest-temp"); String toolsPath = "../aj-build/dist/tools/lib/aspectjtools.jar"; File toolsjar = new File(toolsPath); if (toolsjar.canRead()) { aspectjtoolsJar = toolsjar.getAbsolutePath(); } else { aspectjtoolsJar = null; String s = "AjcTaskTest not forking - build aspectjtools-dist to get " + toolsPath; System.out.println(s); } File dir = new File("../taskdefs/testdata"); if (dir.canRead() && dir.isDirectory()) { testdataDir = dir.getAbsolutePath(); } else { testdataDir = null; } PICK_CLASS_FILES = new FileFilter() { public boolean accept(File file) { return ( (null != file) && file.isFile() && file.canWrite() && file.getPath().endsWith(".class")); } }; } /** * Check that aspectjtools are found on the classpath, * reporting any errors to System.err. * * Run multiple times with different classpaths. * This should find variants * aspectjtools.jar, * aspectj-tools.jar, * aspectj-tools-1.1.jar, and * aspectjtools-1.0.6.jar * but not * aspectjrt.jar or * aspectj/tools.jar. * XXX use testing aspect to stub out * System.getProperty("java.class.path") * @param args a String[], first is expected path, if any */ public static void main(String[] args) { java.io.File toolsjar = AjcTask.findAspectjtoolsJar(); if ((null == args) || (0 == args.length)) { if (null != toolsjar) { System.err.println("FAIL - not expected: " + toolsjar); } } else if ("-help".equals(args[0])) { System.out.println( "java " + AjcTaskTest.class.getName() + " "); } else if (null == toolsjar) { System.err.println("FAIL - expected: " + args[0]); } else { String path = toolsjar.getAbsolutePath(); if (!path.equals(args[0])) { System.err.println( "FAIL - expected: " + args[0] + " actual: " + path); } } } public static void collectMessage(String s) { MESSAGES.append(s); } private static void deleteTempDir() { if ((null != tempDir) && tempDir.exists()) { FileUtil.deleteContents(tempDir); tempDir.delete(); // when tempDir not used... if (null != testdataDir) { File dataDir = new File(testdataDir); if (dataDir.canRead()) { FileUtil.deleteContents(dataDir, PICK_CLASS_FILES, false); } } } } private static final File getTempDir() { return tempDir; } public AjcTaskTest(String name) { super(name); } public void tearDown() { deleteTempDir(); MESSAGES.setLength(0); } private void checkRun(AjcTask task, String exceptionString) { try { task.execute(); assertTrue(null == exceptionString); } catch (BuildException e) { if (null == exceptionString) { assertTrue("unexpected " + e.getMessage(), false); } else { String m = e.getMessage(); if (null == m) { assertTrue("not " + exceptionString, false); } else if (-1 == m.indexOf(exceptionString)) { assertEquals(exceptionString, e.getMessage()); } } } } private void checkContains(String[] cmd, String option, boolean contains) { for (int i = 0; i < cmd.length; i++) { if (option.equals(cmd[i])) { if (contains) { return; } else { assertTrue( "not expecting " + option + " in " + Arrays.asList(cmd), false); } } } if (contains) { assertTrue( "expecting " + option + " in " + Arrays.asList(cmd), false); } } protected AjcTask getTask(String input) { return getTask(input, getTempDir()); } protected AjcTask getTask(String input, File destDir) { AjcTask task = new AjcTask(); Project p = new Project(); task.setProject(p); if (null != destDir) { task.setDestdir(destDir); } if (NOFILE.equals(input)) { // add nothing } else if (input.endsWith(".lst")) { if (-1 != input.indexOf(",")) { throw new IllegalArgumentException( "lists not supported: " + input); } else if (null == testdataDir) { throw new Error("testdata not found - run in ../taskdefs"); } else { String path = testdataDir + File.separator + input; task.setArgfiles(new Path(task.getProject(), path)); } } else if ((input.endsWith(".java") || input.endsWith(".aj"))) { FilenameSelector fns = new FilenameSelector(); fns.setName(input); task.addFilename(fns); } else { String path = testdataDir + File.separator + input; task.setSourceRoots(new Path(task.getProject(), path)); } task.setClasspath(new Path(p, "../lib/test/aspectjrt.jar")); return task; } /** used in testMessageHolderClassName */ public static class InfoHolder extends MessageHandler { public InfoHolder() { } public boolean handleMessage(IMessage message) { if (0 == IMessage.INFO.compareTo(message.getKind())) { AjcTaskTest.collectMessage(message.getMessage()); } return true; } } /** used in testMessageHolderClassName */ public static class Holder extends MessageHandler { public Holder() { } public boolean handleMessage(IMessage message) { IMessage.Kind kind = message.getKind(); if (IMessage.ERROR.isSameOrLessThan(kind)) { String m = kind.toString(); AjcTaskTest.collectMessage(m.substring(0, 1)); } return true; } } // ------------------------------------------------------ // ------------------------------------------------------ // ------------------------------------------------------ // ------------------------------------------------------ // ------------------------------------------------------ // ------------------------------------------------------ // Start of test cases public void testNullDestDir() { AjcTask task = getTask(NOFILE, null); String[] cmd = task.makeCommand(); for (int i = 0; i < cmd.length; i++) { assertTrue(!"-d".equals(cmd[i])); } } public void testOutputRequirement() { AjcTask task = getTask("default.lst"); checkRun(task, null); // copyInJars now just emits warning b/c unused task = getTask("default.lst", null); task.setCopyInjars(true); checkRun(task, null); // sourceRootCopyFilter requires destDir task = getTask("default.lst", null); task.setSourceRootCopyFilter("**/*.java"); checkRun(task, "sourceRoot"); } public void testSourceRootCopyFilter() { // sourceRootCopyFilter works.. File destDir = getTempDir(); assertTrue( "unable to create " + destDir, destDir.canRead() || destDir.mkdirs()); AjcTask task = getTask("sourceroot", destDir); task.setSourceRootCopyFilter("doNotCopy,**/*.txt"); File file = new File(destDir, "Default.java").getAbsoluteFile(); assertTrue(file + ".canRead() prematurely", !file.canRead()); checkRun(task, null); // got expected resources assertTrue(file + ".canRead() failed", file.canRead()); File pack = new File(destDir, "pack"); file = new File(pack, "Pack.java").getAbsoluteFile(); assertTrue(file + ".canRead() failed", file.canRead()); file = new File(pack, "includeme").getAbsoluteFile(); assertTrue(file + ".canRead() failed", file.canRead()); // didn't get unexpected resources file = new File(pack, "something.txt"); assertTrue(file + ".canRead() passed", !file.canRead()); file = new File(destDir, "doNotCopy"); assertTrue(file + ".canRead() passed", !file.canRead()); file = new File(destDir, "skipTxtFiles.txt"); assertTrue(file + ".canRead() passed", !file.canRead()); } public void testInpathDirCopyFilter() { // inpathDirCopyFilter works with output directory File destDir = getTempDir(); assertTrue( "unable to create " + destDir, destDir.canRead() || destDir.mkdirs()); AjcTask task = getTask(NOFILE, destDir); Project p = task.getProject(); Path indirs = new Path(p); File dir = new File(testdataDir, "inpathDirs").getAbsoluteFile(); indirs.addExisting(new Path(p, new File(dir, "inpathDirOne").getAbsolutePath())); indirs.addExisting(new Path(p, new File(dir, "inpathDirTwo").getAbsolutePath())); task.setInpath(indirs); task.setInpathDirCopyFilter("doNotCopy,**/*.txt"); File file = new File(destDir, "Default.java").getAbsoluteFile(); assertTrue(file + ".canRead() prematurely", !file.canRead()); checkRun(task, null); // got expected resources File pack = new File(destDir, "pack"); file = new File(pack, "includeme").getAbsoluteFile(); assertTrue(file + ".canRead() failed", file.canRead()); file = new File(pack, "Pack.class").getAbsoluteFile(); assertTrue(file + ".canRead() failed", file.canRead()); file = new File(destDir, "copyMe.htm").getAbsoluteFile(); assertTrue(file + ".canRead() failed", file.canRead()); file = new File(destDir, "Default.class").getAbsoluteFile(); assertTrue(file + ".canRead() failed", file.canRead()); // didn't get unexpected resources file = new File(pack, "something.txt"); assertTrue(file + ".canRead() passed", !file.canRead()); file = new File(destDir, "doNotCopy"); assertTrue(file + ".canRead() passed", !file.canRead()); file = new File(destDir, "skipTxtFiles.txt"); assertTrue(file + ".canRead() passed", !file.canRead()); } public void testInpathDirCopyFilterWithJar() throws IOException { checkInpathCopy("testInpathDirCopyFilterWithJar-out.jar"); } // test resource copying for oddball jar files that don't end in .jar public void testInpathDirCopyFilterWithOddjar() throws IOException { checkInpathCopy("testInpathDirCopyFilterWithJar-outJarFile"); } private void checkInpathCopy(String outjarFileStr) throws IOException { // inpathDirCopyFilter works with output jar File destDir = getTempDir(); assertTrue( "unable to create " + destDir, destDir.canRead() || destDir.mkdirs()); AjcTask task = getTask(NOFILE, null); File destJar = new File(destDir, outjarFileStr); task.setOutjar(destJar); Project p = task.getProject(); Path indirs = new Path(p); File dir = new File(testdataDir, "inpathDirs").getAbsoluteFile(); indirs.addExisting(new Path(p, new File(dir, "inpathDirOne").getAbsolutePath())); indirs.addExisting(new Path(p, new File(dir, "inpathDirTwo").getAbsolutePath())); task.setInpath(indirs); task.setInpathDirCopyFilter("doNotCopy,**/*.txt,**/*.class"); checkRun(task, null); JarFile jarFile = new JarFile(destJar); String[] expected = {"copyMe.htm", "pack/includeme", "pack/Pack.class", "Default.class"}; String[] unexpected = {"doNotCopy", "skipTxtFiles.txt", "pack/something.txt"}; for (int i = 0; i < expected.length; i++) { JarEntry entry = jarFile.getJarEntry(expected[i]); assertTrue(expected[i] + " not found", null != entry); } for (int i = 0; i < unexpected.length; i++) { JarEntry entry = jarFile.getJarEntry(unexpected[i]); assertTrue(unexpected[i] + " found", null == entry); } } public void testInpathDirCopyFilterError() { // inpathDirCopyFilter fails with no output directory or jar iff specified AjcTask task = getTask(NOFILE, null); Project p = task.getProject(); Path indirs = new Path(p); File dir = new File(testdataDir, "inpathDirs").getAbsoluteFile(); indirs.addExisting(new Path(p, new File(dir, "inpathDirOne").getAbsolutePath())); indirs.addExisting(new Path(p, new File(dir, "inpathDirTwo").getAbsolutePath())); task.setInpath(indirs); task.setInpathDirCopyFilter("doNotCopy,**/*.txt,**/*.class"); // expecting error checkRun(task, "inpathDirCopyFilter"); } // this test method submitted by patch from Andrew Huff (IBM) // verifies that the log attribute of AjcTask writes output to the given log file public void testLoggingMode() { AjcTask task = getTask("default.lst"); task.setFailonerror(false); File logFile = new File("testLogFile1.txt"); String s = logFile.getAbsolutePath(); logFile.delete(); long initialLength = logFile.length(); task.setLog(logFile); runTest(task,null,MessageHolderChecker.INFOS); long newLength = logFile.length(); assertTrue(newLength > initialLength); logFile.delete(); } public void testCommandEditor() { String className = VerboseCommandEditor.class.getName(); System.setProperty(AjcTask.COMMAND_EDITOR_NAME, className); assertEquals( className, System.getProperty(AjcTask.COMMAND_EDITOR_NAME)); AjcTask task = getTask(NOFILE); task.setCommandEditor(new VerboseCommandEditor()); String[] cmd = task.makeCommand(); assertEquals(VerboseCommandEditor.VERBOSE, cmd[0]); task = getTask(NOFILE); task.setCommandEditorClass(VerboseCommandEditor.class.getName()); cmd = task.makeCommand(); assertEquals(VerboseCommandEditor.VERBOSE, cmd[0]); } // public void testStaticCommandEditor() { // // XXX need to test COMMAND_EDITOR, but can't require property when run // } public void testLimitTo() { int numArgs = 100; String arg = "123456789"; String[] args = new String[numArgs]; for (int i = 0; i < args.length; i++) { args[i] = arg; } // no limit int max = numArgs * (arg.length() + 1); Location location = new Location("AjcTaskTest.java"); String[] newArgs = AjcTask.GuardedCommand.limitTo(args, max, location); assertTrue("same", args == newArgs); // limited - read file and verify arguments max--; newArgs = AjcTask.GuardedCommand.limitTo(args, max, location); assertTrue("not same", args != newArgs); assertTrue("not null", null != newArgs); String label = "newArgs " + Arrays.asList(newArgs); assertTrue("size 2" + label, 2 == newArgs.length); assertEquals("-argfile", newArgs[0]); File file = new File(newArgs[1]); assertTrue("readable newArgs[1]" + label, file.canRead()); FileReader fin = null; try { fin = new FileReader(file); BufferedReader reader = new BufferedReader(fin); String line; int i = 0; while (null != (line = reader.readLine())) { assertEquals(i + ": ", args[i++], line); } assertEquals("num entries", i, args.length); } catch (IOException e) { assertTrue("IOException " + e.getMessage(), false); } finally { if (null != fin) { try { fin.close(); } catch (IOException e) { // ignore } } file.delete(); } } public void testFindAspectjtoolsJar() { File toolsJar = AjcTask.findAspectjtoolsJar(); if (null != toolsJar) { assertNull("tools jar found?: " + toolsJar, toolsJar); } // not found when unit testing b/c not on system classpath // so just checking for exceptions. // XXX need aspect to stub out System.getProperty(..) } public void testMessageHolderClassName() { AjcTask task = getTask("compileError.lst"); task.setFailonerror(false); MESSAGES.setLength(0); runTest( task, null, MessageHolderChecker.ONE_ERROR, Holder.class.getName()); String result = MESSAGES.toString(); MESSAGES.setLength(0); // The test program produces three errors with the current 1.8 compiler, this may change by 1.8 release and so // this will need reverting back to "e" assertEquals("messages", "eee", result); } // TODO skipped test - works locally but not on build machine? public void skip_testMessageHolderClassWithDoneSignal() { AjcTask task = getTask("default.lst"); task.setFailonerror(false); String DONE = "This is a unique message, not confused with others."; task.setXDoneSignal(DONE); MESSAGES.setLength(0); runTest( task, null, MessageHolderChecker.INFOS, InfoHolder.class.getName()); final String result = MESSAGES.toString(); String temp = new String(result); MESSAGES.setLength(0); if (!temp.endsWith(DONE)) { if (temp.length() > 20) { temp = "..." + temp.substring(temp.length()-20, temp.length()); } assertTrue(DONE + " is not suffix of \"" + temp + "\"", false); } // exactly one such message temp = new String(result); temp = temp.substring(0, temp.length()-DONE.length()); if (temp.endsWith(DONE)) { temp = new String(result); if (temp.length() > 20) { temp = "..." + temp.substring(temp.length()-20, temp.length()); } assertTrue(DONE + " signalled twice: \"" + temp + "\"", false); } } public void testDefaultListForkedNoTools() { AjcTask task = getTask("default.lst"); task.setFork(true); boolean passed = false; try { runTest(task, BuildException.class, MessageHolderChecker.NONE); passed = true; } finally { if (!passed) { String m = "AjcTaskTest.testDefaultListForkedNoTools()" + " fails if aspectjtools.jar is on the classpath"; System.err.println(m); } } } public void testDefaultListForkedIncremental() { AjcTask task = getTask("default.lst"); task.setFork(true); task.setIncremental(true); runTest(task, BuildException.class, MessageHolderChecker.NONE); } /** failonerror should default to true, unlike other booleans */ public void testCompileErrorFailOnErrorDefault() { AjcTask task = getTask("compileError.lst"); final PrintStream serr = System.err; try { System.setErr(new PrintStream(new java.io.ByteArrayOutputStream())); // Current 1.8 compiler produces 3 errors for this test program, may need reverting to ONE_ERROR by release runTest(task, BuildException.class, MessageHolderChecker.THREE_ERRORS); } finally { System.setErr(serr); } } public void testCompileErrorListDefaultHolder() { AjcTask task = getTask("compileError.lst"); final PrintStream serr = System.err; try { System.setErr(new PrintStream(new java.io.ByteArrayOutputStream())); task.execute(); fail("expected BuildException from failed compile by default"); } catch (BuildException t) { // ok } finally { System.setErr(serr); deleteTempDir(); } } public void testDefaultList() { AjcTask task = getTask("default.lst"); runTest(task, NO_EXCEPTION, MessageHolderChecker.INFOS); } public void testCompileErrorList() { AjcTask task = getTask("compileError.lst"); task.setFailonerror(false); // Prior to the 1.8 compiler there is one error here, 'syntax error on here' // With 1.8 there are 3 errors about completing the method header, ending the class body, ending the method - this may // change by 1.8 final... this might need reverting back to ONE_ERROR runTest(task, NO_EXCEPTION, MessageHolderChecker.THREE_ERRORS); } public void testShowWeaveInfo() { AjcTask task = getTask("showweaveinfo.lst"); task.setShowWeaveInfo(true); MessageHandler mh = new MessageHandler(false); mh.dontIgnore(IMessage.WEAVEINFO); MessageHolderChecker mhc = new MessageHolderChecker(0,0,0,0,MessageHolderChecker.IGNORE); mhc.weaveinfos = 2; // Expect 2 weaving messages runTest(task,NO_EXCEPTION,mhc); mhc.weaveinfos = MessageHolderChecker.IGNORE; } public void testCompileWarningList() { AjcTask task = getTask("compileWarning.lst"); runTest(task, NO_EXCEPTION, MessageHolderChecker.ONE_WARNING); } public void testNoSuchFileList() { AjcTask task = getTask("NoSuchFile.lst"); task.setFailonerror(false); runTest(task, NO_EXCEPTION, MessageHolderChecker.ONE_ERROR_ONE_ABORT); } public void testVersions() { String[] inputs = AjcTask.TARGET_INPUTS; for (int i = 0; i < inputs.length; i++) { AjcTask task = getTask(NOFILE); task.setTarget(inputs[i]); String[] cmd = task.makeCommand(); checkContains(cmd, "-target", true); checkContains(cmd, inputs[i], true); } inputs = AjcTask.SOURCE_INPUTS; for (int i = 0; i < inputs.length; i++) { AjcTask task = getTask(NOFILE); task.setSource(inputs[i]); String[] cmd = task.makeCommand(); checkContains(cmd, "-source", true); checkContains(cmd, inputs[i], true); } inputs = AjcTask.COMPLIANCE_INPUTS; for (int i = 0; i < inputs.length; i++) { AjcTask task = getTask(NOFILE); task.setCompliance(inputs[i]); String[] cmd = task.makeCommand(); checkContains(cmd, inputs[i], true); } } public void testClasspath() { AjcTask task = getTask(NOFILE); String[] cmd = task.makeCommand(); checkContains(cmd, "-bootclasspath", false); String classpath = null; for (int i = 0; i < cmd.length; i++) { if ("-classpath".equals(cmd[i])) { classpath = cmd[i + 1]; break; } } assertTrue( "expecting aspectj in classpath", (-1 != classpath.indexOf("aspectjrt.jar"))); } // ---------------------------------------- sourcefile // XXX need to figure out how to specify files directly programmatically // public void testDefaultFile() { // AjcTask task = getTask("testdata/Default.java"); // runTest(task, NO_EXCEPTION, MessageHolderChecker.INFOS); // } public void testNoFile() { AjcTask task = getTask(NOFILE); task.setFailonerror(false); runTest(task, NO_EXCEPTION, MessageHolderChecker.ONE_ERROR_ONE_ABORT); } public void testCompileErrorFile() { AjcTask task = getTask("compileError.lst"); task.setFailonerror(false); // 1.8 compiler currently produces 3 errors for the test program, may need to revert to ONE_ERROR by 1.8 release runTest(task, NO_EXCEPTION, MessageHolderChecker.THREE_ERRORS); } public void testCompileWarningFile() { AjcTask task = getTask("compileWarning.lst"); task.setFailonerror(false); runTest(task, NO_EXCEPTION, MessageHolderChecker.ONE_WARNING); } public void testNoSuchFile() { AjcTask task = getTask("NoSuchFile.lst"); task.setFailonerror(false); runTest(task, NO_EXCEPTION, MessageHolderChecker.ONE_ERROR_ONE_ABORT); } public void testDefaultFileComplete() { AjcTask task = getTask("default.lst"); defaultSettings(task); runTest(task, NO_EXCEPTION, MessageHolderChecker.INFOS); } private void defaultSettings(AjcTask task) { task.setDebugLevel("none"); task.setDeprecation(true); task.setFailonerror(false); task.setNoExit(true); // ok to override Ant? task.setNoImportError(true); task.setNowarn(true); task.setXTerminateAfterCompilation(true); task.setPreserveAllLocals(true); task.setProceedOnError(true); task.setReferenceInfo(true); task.setSource("1.3"); task.setTarget("1.1"); task.setTime(true); task.setVerbose(true); task.setXlint("info"); } public void testLogCommand() { final String DEFAULT = "default.lst"; AjcTask task = getTask(DEFAULT); defaultSettings(task); task.setVerbose(false); task.setLogCommand(true); LogListener listener = new LogListener(Project.MSG_INFO); task.getProject().addBuildListener(listener); runTest(task, NO_EXCEPTION, MessageHolderChecker.INFOS); String[] results = listener.getResults(); boolean matched = false; for (int i = 0; !matched && (i < results.length); i++) { String s = results[i]; matched = (null != s) && (-1 != s.indexOf(DEFAULT)); } if (!matched) { fail(DEFAULT + " not found in " + Arrays.asList(results)); } } public void testXOptions() { String[] xopts = new String[] { "serializableAspects", "lazyTjp", "reweavable", "reweavable:compress", "noInline" }; for (int i = 0; i < xopts.length; i++) { AjcTask task = getTask(NOFILE); task.setX(xopts[i]); String[] cmd = task.makeCommand(); checkContains(cmd,"-X" + xopts[i],true); } } public void testAptProc() { AjcTask task = getTask(NOFILE); task.setProc("none"); checkContains(task.makeCommand(), "-proc:none", true); task.setProc("only"); checkContains(task.makeCommand(), "-proc:only", true); } public void testAptProcessor() { AjcTask task = getTask(NOFILE); task.setProcessor("some.SomeClass"); checkContains(task.makeCommand(), "-processor", true); checkContains(task.makeCommand(), "some.SomeClass", true); } public void testAptProcessorpath() { AjcTask task = getTask(NOFILE); task.setProcessorpath("some/path"); checkContains(task.makeCommand(), "-processorpath", true); checkContains(task.makeCommand(), "some/path", true); } public void testAptGeneratedDirectory() { AjcTask task = getTask(NOFILE); task.setS("some/path"); checkContains(task.makeCommand(), "-s", true); checkContains(task.makeCommand(), "some/path", true); } public void testOutxml () { File destDir = getTempDir(); assertTrue( "unable to create " + destDir, destDir.canRead() || destDir.mkdirs()); AjcTask task = getTask("showweaveinfo.lst",destDir); task.setOutxml(true); checkRun(task,null); File outxmlFile = new File(destDir,"META-INF/aop-ajc.xml"); assertTrue("META-INF/aop-ajc.xml missing",outxmlFile.exists()); } public void testOutxmlFile () { String customName = "custom/aop.xml"; File destDir = getTempDir(); assertTrue( "unable to create " + destDir, destDir.canRead() || destDir.mkdirs()); AjcTask task = getTask("showweaveinfo.lst",destDir); task.setOutxmlfile(customName); checkRun(task,null); File outxmlFile = new File(destDir,customName); assertTrue(customName + " missing",outxmlFile.exists()); } // End of test cases // ------------------------------------------------------ // ------------------------------------------------------ // ------------------------------------------------------ // ------------------------------------------------------ // ------------------------------------------------------ // ------------------------------------------------------ protected void runTest( AjcTask task, Class exceptionType, MessageHolderChecker checker, String messageHolderClass) { task.setMessageHolderClass(messageHolderClass); runTest(task, exceptionType, checker, (MessageHandler) null); } protected void runTest( AjcTask task, Class exceptionType, MessageHolderChecker checker) { MessageHandler holder = new MessageHandler(); task.setMessageHolder(holder); runTest(task, exceptionType, checker, holder); } protected void runTest( AjcTask task, Class exceptionType, MessageHolderChecker checker, MessageHandler holder) { Throwable thrown = null; // re-run forked iff tools.jar and expect to pass boolean rerunForked = ((null != aspectjtoolsJar) && (null == exceptionType) && ((null == checker) || !checker.expectFail())); String label = "same-vm "; while (true) { // same vm, then perhaps forked try { task.execute(); } catch (Throwable t) { thrown = t; } finally { deleteTempDir(); } if (null == exceptionType) { if (null != thrown) { assertTrue(label + "thrown: " + render(thrown), false); } } else if (null == thrown) { assertTrue( label + "expected " + exceptionType.getName(), false); } else if (!(exceptionType.isAssignableFrom(thrown.getClass()))) { assertTrue( label + "expected " + exceptionType.getName() + " got " + render(thrown), false); } if (null != holder) { if (null == checker) { checker = MessageHolderChecker.NONE; } checker.check(holder, label); } if (!rerunForked) { break; } else { label = "other-vm "; rerunForked = false; // can't reset without losing values... task.setFork(true); task.setFailonerror(true); task.setForkclasspath( new Path(task.getProject(), aspectjtoolsJar)); } } } protected String render(Throwable thrown) { return LangUtil.renderException(thrown); } static class MessageHolderChecker { // XXX export to testing-utils /** use as value to ignore results */ static int IGNORE = Integer.MIN_VALUE; static MessageHolderChecker NONE = new MessageHolderChecker(0, 0, 0, 0, 0); /** any number (0+) of info messages */ static MessageHolderChecker INFOS = new MessageHolderChecker(0, 0, 0, 0, IGNORE); /** one error, any number of info messages */ static MessageHolderChecker ONE_ERROR = new MessageHolderChecker(0, 0, 1, 0, IGNORE); static MessageHolderChecker ONE_ERROR_ONE_ABORT = new MessageHolderChecker(1, 0, 1, 0, IGNORE); /** one warning, any number of info messages */ static MessageHolderChecker ONE_WARNING = new MessageHolderChecker(0, 0, 0, 1, IGNORE); static MessageHolderChecker THREE_ERRORS = new MessageHolderChecker(0, 0, 3, 0, IGNORE); int aborts, fails, errors, warnings, infos; int weaveinfos; public MessageHolderChecker( int aborts, int fails, int errors, int warnings, int infos) { this.aborts = aborts; this.fails = fails; this.errors = errors; this.warnings = warnings; this.infos = infos; this.weaveinfos = IGNORE; } public boolean expectFail() { return (0 < (aborts + fails + errors)); } public void check(IMessageHolder holder, String label) { boolean failed = true; try { check(holder, aborts, IMessage.ABORT); check(holder, fails, IMessage.FAIL); check(holder, errors, IMessage.ERROR); check(holder, warnings, IMessage.WARNING); check(holder, infos, IMessage.INFO); check(holder, weaveinfos, IMessage.WEAVEINFO); failed = false; } finally { if (failed) { MessageUtil.print(System.err, holder, label + "failed?"); } } } private void check( IMessageHolder holder, int num, IMessage.Kind kind) { if (num != IGNORE) { int actual = holder.numMessages(kind, false); if (num != actual) { if (actual > 0) { MessageUtil.print( System.err, holder, kind + " expected " + num + " got " + actual); } assertEquals(kind.toString(), num, actual); } } } } private static class LogListener implements BuildListener { private final ArrayList results = new ArrayList(); private final int priority; private LogListener(int priority) { this.priority = priority; } public void buildFinished(BuildEvent event) {} public void buildStarted(BuildEvent event) {} public void messageLogged(BuildEvent event) { if (priority == event.getPriority()) { results.add(event.getMessage()); } } public void targetFinished(BuildEvent event) {} public void targetStarted(BuildEvent event) {} public void taskFinished(BuildEvent event) {} public void taskStarted(BuildEvent event) {} String[] getResults() { return (String[]) results.toArray(new String[0]); } } } class SnoopingCommandEditor implements ICommandEditor { private static final String[] NONE = new String[0]; String[] lastCommand; public String[] editCommand(String[] command) { lastCommand = (String[]) LangUtil.safeCopy(command, NONE); return command; } public String[] lastCommand() { return (String[]) LangUtil.safeCopy(lastCommand, NONE); } } class VerboseCommandEditor implements ICommandEditor { public static final String VERBOSE = "-verbose"; public String[] editCommand(String[] command) { for (int i = 0; i < command.length; i++) { if (VERBOSE.equals(command[i])) { return command; } } String[] result = new String[1 + command.length]; result[0] = VERBOSE; System.arraycopy(result, 1, command, 0, command.length); return result; } } class AppendingCommandEditor implements ICommandEditor { private static String[] NONE = new String[0]; public static ICommandEditor VERBOSE = new AppendingCommandEditor(new String[] { "-verbose" }, NONE); public static ICommandEditor INVALID = new AppendingCommandEditor(NONE, new String[] { "-invalidOption" }); final String[] prefix; final String[] suffix; public AppendingCommandEditor(String[] prefix, String[] suffix) { this.prefix = prefix; this.suffix = suffix; } public String[] editCommand(String[] command) { int len = command.length + prefix.length + suffix.length; String[] result = new String[len]; System.arraycopy(result, 0, prefix, 0, prefix.length); System.arraycopy(result, prefix.length, command, 0, command.length); System.arraycopy( result, prefix.length + command.length, suffix, 0, suffix.length); return result; } }