/* * 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 org.apache.tools.ant.types.selectors; // Java import java.io.File; import java.text.RuleBasedCollator; import java.util.Comparator; import java.util.Iterator; import org.apache.tools.ant.AntAssert; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildFileRule; import org.apache.tools.ant.Project; import org.apache.tools.ant.Target; import org.apache.tools.ant.Task; import org.apache.tools.ant.types.Parameter; import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.selectors.modifiedselector.Algorithm; import org.apache.tools.ant.types.selectors.modifiedselector.Cache; import org.apache.tools.ant.types.selectors.modifiedselector.ChecksumAlgorithm; import org.apache.tools.ant.types.selectors.modifiedselector.DigestAlgorithm; import org.apache.tools.ant.types.selectors.modifiedselector.EqualComparator; import org.apache.tools.ant.types.selectors.modifiedselector.HashvalueAlgorithm; import org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector; import org.apache.tools.ant.types.selectors.modifiedselector.PropertiesfileCache; import org.apache.tools.ant.util.FileUtils; import org.junit.Assume; import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** * Unit tests for ModifiedSelector. * * @since Ant 1.6 */ public class ModifiedSelectorTest { @Rule public final BaseSelectorRule selectorRule = new BaseSelectorRule(); /** Utilities used for file operations */ private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); // ===================== attributes ===================== /** Path where the testclasses are. */ private Path testclasses = null; // ===================== JUnit stuff ===================== @Before public void setUp() { // init the testclasses path object Project prj = selectorRule.getProject(); testclasses = new Path(prj, prj.getProperty("build.tests.value")); } // ======= testcases for the attributes and nested elements of the selector ===== /** Test right use of cache names. */ @Test public void testValidateWrongCache() { String name = "this-is-not-a-valid-cache-name"; try { ModifiedSelector.CacheName cacheName = new ModifiedSelector.CacheName(); cacheName.setValue(name); fail("CacheSelector.CacheName accepted invalid value."); } catch (BuildException be) { assertEquals(name + " is not a legal value for this attribute", be.getMessage()); } } /** Test right use of cache names. */ @Test public void testValidateWrongAlgorithm() { String name = "this-is-not-a-valid-algorithm-name"; try { ModifiedSelector.AlgorithmName algoName = new ModifiedSelector.AlgorithmName(); algoName.setValue(name); fail("CacheSelector.AlgorithmName accepted invalid value."); } catch (BuildException be) { assertEquals(name + " is not a legal value for this attribute", be.getMessage()); } } /** Test right use of comparator names. */ @Test public void testValidateWrongComparator() { String name = "this-is-not-a-valid-comparator-name"; try { ModifiedSelector.ComparatorName compName = new ModifiedSelector.ComparatorName(); compName.setValue(name); fail("ModifiedSelector.ComparatorName accepted invalid value."); } catch (BuildException be) { assertEquals(name + " is not a legal value for this attribute", be.getMessage()); } } @Test public void testIllegalCustomAlgorithm() { try { getAlgoName("java.lang.Object"); fail("Illegal classname used."); } catch (BuildException e) { assertEquals("Wrong exception message.", "Specified class (java.lang.Object) is not an Algorithm.", e.getMessage()); } } @Test public void testNonExistentCustomAlgorithm() { try { getAlgoName("non.existent.custom.Algorithm"); fail("does 'non.existent.custom.Algorithm' really exist?"); } catch (BuildException e) { assertEquals("Wrong exception message.", "Specified class (non.existent.custom.Algorithm) not found.", e.getMessage()); } } @Test public void testCustomAlgorithm() { String algo = getAlgoName("org.apache.tools.ant.types.selectors.modifiedselector.HashvalueAlgorithm"); assertTrue("Wrong algorithm used: "+algo, algo.startsWith("HashvalueAlgorithm")); } @Test public void testCustomAlgorithm2() { String algo = getAlgoName("org.apache.tools.ant.types.selectors.MockAlgorithm"); assertTrue("Wrong algorithm used: "+algo, algo.startsWith("MockAlgorithm")); } @Test public void testCustomClasses() { Assume.assumeNotNull("Ant home not set", selectorRule.getProject().getProperty("ant.home") ); BFT bft = new BFT(); bft.setUp(); try { // do the actions bft.doTarget("modifiedselectortest-customClasses"); // do the checks - the buildfile stores the fileset as property String fsFullValue = bft.getProperty("fs.full.value"); String fsModValue = bft.getProperty("fs.mod.value"); assertNotNull("'fs.full.value' must be set.", fsFullValue); assertTrue("'fs.full.value' must not be null.", !"".equals(fsFullValue)); assertTrue("'fs.full.value' must contain ant.bat.", fsFullValue.indexOf("ant.bat")>-1); assertNotNull("'fs.mod.value' must be set.", fsModValue); // must be empty according to the Mock* implementations assertTrue("'fs.mod.value' must be empty.", "".equals(fsModValue)); // don't catch the JUnit exceptions } finally { bft.doTarget("modifiedselectortest-scenario-clean"); bft.deletePropertiesfile(); bft.tearDown(); } } @Test public void testDelayUpdateTaskFinished() { doDelayUpdateTest(1); } @Test public void testDelayUpdateTargetFinished() { doDelayUpdateTest(2); } @Test public void testDelayUpdateBuildFinished() { doDelayUpdateTest(3); } public void doDelayUpdateTest(int kind) { // no check for 1<=kind<=3 - only internal use therefore check it // while development // readable form of parameter kind String[] kinds = {"task", "target", "build"}; // setup the "Ant project" MockProject project = new MockProject(); File base = new File("base"); File file1 = new File("file1"); File file2 = new File("file2"); // setup the selector ModifiedSelector sel = new ModifiedSelector(); sel.setProject(project); sel.setUpdate(true); sel.setDelayUpdate(true); // sorry - otherwise we will get a ClassCastException because the MockCache // is loaded by two different classloader ... sel.setClassLoader(this.getClass().getClassLoader()); sel.addClasspath(testclasses); sel.setAlgorithmClass("org.apache.tools.ant.types.selectors.MockAlgorithm"); sel.setCacheClass("org.apache.tools.ant.types.selectors.MockCache"); sel.configure(); // get the cache, so we can check our things MockCache cache = (MockCache)sel.getCache(); // the test assertFalse("Cache must not be saved before 1st selection.", cache.saved); sel.isSelected(base, "file1", file1); assertFalse("Cache must not be saved after 1st selection.", cache.saved); sel.isSelected(base, "file2", file2); assertFalse("Cache must not be saved after 2nd selection.", cache.saved); switch (kind) { case 1 : project.fireTaskFinished(); break; case 2 : project.fireTargetFinished(); break; case 3 : project.fireBuildFinished(); break; } assertTrue("Cache must be saved after " + kinds[kind-1] + "Finished-Event.", cache.saved); // MockCache doesnt create a file - therefore no cleanup needed } /** * Extracts the real used algorithm name from the ModifiedSelector using * its toString() method. * @param classname the classname from the algorithm to use * @return the algorithm part from the toString() (without brackets) */ private String getAlgoName(String classname) { ModifiedSelector sel = new ModifiedSelector(); sel.setProject(selectorRule.getProject()); // add the test classes to its classpath sel.addClasspath(testclasses); sel.setAlgorithmClass(classname); // let the selector do its checks sel.validate(); // extract the algorithm name (and config) from the selectors output String s1 = sel.toString(); int posStart = s1.indexOf("algorithm=") + 10; int posEnd = s1.indexOf(" comparator="); String algo = s1.substring(posStart, posEnd); // '<' and '>' are only used if the algorithm has properties if (algo.startsWith("<")) algo = algo.substring(1); if (algo.endsWith(">")) algo = algo.substring(0, algo.length()-1); // return the clean value return algo; } // ================ testcases for the cache implementations ================ /** * Propertycache must have a set 'cachefile' attribute. * The default in ModifiedSelector "cache.properties" is set by the selector. */ @Test public void testPropcacheInvalid() { Cache cache = new PropertiesfileCache(); if (cache.isValid()) fail("PropertyfilesCache does not check its configuration."); } @Test public void testPropertyfileCache() { PropertiesfileCache cache = new PropertiesfileCache(); File cachefile = new File("cache.properties"); cache.setCachefile(cachefile); doTest(cache); assertFalse("Cache file not deleted.", cachefile.exists()); } /** Checks whether a cache file is created. */ @Test public void testCreatePropertiesCacheDirect() { File cachefile = new File(selectorRule.getProject().getBaseDir(), "cachefile.properties"); PropertiesfileCache cache = new PropertiesfileCache(); cache.setCachefile(cachefile); cache.put("key", "value"); cache.save(); assertTrue("Cachefile not created.", cachefile.exists()); cache.delete(); assertFalse("Cachefile not deleted.", cachefile.exists()); } /** Checks whether a cache file is created. */ @Test public void testCreatePropertiesCacheViaModifiedSelector() { File cachefile = new File(selectorRule.getProject().getBaseDir(), "cachefile.properties"); // Configure the selector ModifiedSelector s = new ModifiedSelector(); s.setDelayUpdate(false); s.addParam("cache.cachefile", cachefile); ModifiedSelector.CacheName cacheName = new ModifiedSelector.CacheName(); cacheName.setValue("propertyfile"); s.setCache(cacheName); s.setUpdate(true); selectorRule.selectionString(s); // evaluate correctness assertTrue("Cache file is not created.", cachefile.exists()); cachefile.delete(); } /** * In earlier implementations there were problems with the <i>order</i> * of the <param>s. The scenario was <pre> * <custom class="ModifiedSelector"> * <param name="cache.cachefile" value="mycache.properties" /> * <param name="cache" value="propertyfiles" /> * </custom> * </pre> It was important first to set the cache and then to set * the cache's configuration parameters. That results in the reorganized * configure() method of ModifiedSelector. This testcase tests that. */ @Test public void testCreatePropertiesCacheViaCustomSelector() { File cachefile = FILE_UTILS.createTempFile("tmp-cache-", ".properties", null, false, false); // Configure the selector ExtendSelector s = new ExtendSelector(); s.setClassname("org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector"); s.addParam(createParam("update", "true")); s.addParam(createParam("cache.cachefile", cachefile.getAbsolutePath())); s.addParam(createParam("cache", "propertyfile")); selectorRule.selectionString(s); // evaluate correctness assertTrue("Cache file is not created.", cachefile.exists()); cachefile.delete(); } @Test @Ignore("same logic as on algorithm, no testcases created") public void testCustomCache() { // same logic as on algorithm, no testcases created } /** * Test the interface semantic of Caches. * This method does some common test for cache implementations. * A cache must return a stored value and a valid iterator. * After calling the delete() the cache must be empty. * * @param cache configured test object */ protected void doTest(Cache cache) { assertTrue("Cache not proper configured.", cache.isValid()); String key1 = "key1"; String value1 = "value1"; String key2 = "key2"; String value2 = "value2"; // given cache must be empty Iterator it1 = cache.iterator(); assertFalse("Cache is not empty", it1.hasNext()); // cache must return a stored value cache.put(key1, value1); cache.put(key2, value2); assertEquals("cache returned wrong value", value1, cache.get(key1)); assertEquals("cache returned wrong value", value2, cache.get(key2)); // test the iterator Iterator it2 = cache.iterator(); Object returned = it2.next(); boolean ok = (key1.equals(returned) || key2.equals(returned)); String msg = "Iterator returned unexpected value." + " key1.equals(returned)="+key1.equals(returned) + " key2.equals(returned)="+key2.equals(returned) + " returned="+returned + " ok="+ok; assertTrue(msg, ok); // clear the cache cache.delete(); Iterator it3 = cache.iterator(); assertFalse("Cache is not empty", it3.hasNext()); } // ============== testcases for the algorithm implementations ============== @Test public void testHashvalueAlgorithm() { HashvalueAlgorithm algo = new HashvalueAlgorithm(); doTest(algo); } @Test public void testDigestAlgorithmMD5() { DigestAlgorithm algo = new DigestAlgorithm(); algo.setAlgorithm("MD5"); doTest(algo); } @Test public void testDigestAlgorithmSHA() { DigestAlgorithm algo = new DigestAlgorithm(); algo.setAlgorithm("SHA"); doTest(algo); } @Test public void testChecksumAlgorithm() { ChecksumAlgorithm algo = new ChecksumAlgorithm(); doTest(algo); } @Test public void testChecksumAlgorithmCRC() { ChecksumAlgorithm algo = new ChecksumAlgorithm(); algo.setAlgorithm("CRC"); doTest(algo); } @Test public void testChecksumAlgorithmAdler() { ChecksumAlgorithm algo = new ChecksumAlgorithm(); algo.setAlgorithm("Adler"); doTest(algo); } /** * Test the interface semantic of Algorithms. * This method does some common test for algorithm implementations. * An algorithm must return always the same value for the same file and * it must not return <i>null</i>. * * @param algo configured test object */ protected void doTest(Algorithm algo) { assertTrue("Algorithm not proper configured.", algo.isValid()); for (int i=0; i<selectorRule.getFiles().length; i++) { File file = selectorRule.getFiles()[i]; // must not be a directory if (file.isFile()) { // get the Hashvalues String hash1 = algo.getValue(file); String hash2 = algo.getValue(file); String hash3 = algo.getValue(file); String hash4 = algo.getValue(file); String hash5 = algo.getValue(new File(file.getAbsolutePath())); // Assert !=null and equality assertNotNull("Hashvalue was null for "+file.getAbsolutePath(), hash1); assertNotNull("Hashvalue was null for "+file.getAbsolutePath(), hash2); assertNotNull("Hashvalue was null for "+file.getAbsolutePath(), hash3); assertNotNull("Hashvalue was null for "+file.getAbsolutePath(), hash4); assertNotNull("Hashvalue was null for "+file.getAbsolutePath(), hash5); assertEquals("getHashvalue() returned different value for "+file.getAbsolutePath(), hash1, hash2); assertEquals("getHashvalue() returned different value for "+file.getAbsolutePath(), hash1, hash3); assertEquals("getHashvalue() returned different value for "+file.getAbsolutePath(), hash1, hash4); assertEquals("getHashvalue() returned different value for "+file.getAbsolutePath(), hash1, hash5); }//if-isFile }//for } // ============== testcases for the comparator implementations ============== @Test public void testEqualComparator() { EqualComparator comp = new EqualComparator(); doTest(comp); } @Test public void testRuleComparator() { RuleBasedCollator comp = (RuleBasedCollator)RuleBasedCollator.getInstance(); doTest(comp); } @Test public void testEqualComparatorViaSelector() { ModifiedSelector s = new ModifiedSelector(); ModifiedSelector.ComparatorName compName = new ModifiedSelector.ComparatorName(); compName.setValue("equal"); s.setComparator(compName); try { performTests(s, "TTTTTTTTTTTT"); } finally { s.getCache().delete(); } } @Test @Ignore("not yet supported see note in selector") public void testRuleComparatorViaSelector() { ModifiedSelector s = new ModifiedSelector(); ModifiedSelector.ComparatorName compName = new ModifiedSelector.ComparatorName(); compName.setValue("rule"); s.setComparator(compName); try { performTests(s, "TTTTTTTTTTTT"); } finally { s.getCache().delete(); } } @Test @Ignore("same logic as on algorithm, no testcases created") public void testCustomComparator() { // same logic as on algorithm, no testcases created } @Test public void testResourceSelectorSimple() { BFT bft = new BFT(); bft.doTarget("modifiedselectortest-ResourceSimple"); bft.deleteCachefile(); //new File("src/etc/testcases/types/resources/selectors/cache.properties").delete(); } @Test public void testResourceSelectorSelresTrue() { BFT bft = new BFT(); bft.doTarget("modifiedselectortest-ResourceSelresTrue"); AntAssert.assertContains("does not provide an InputStream", bft.getLog()); bft.deleteCachefile(); } @Test public void testResourceSelectorSelresFalse() { BFT bft = new BFT(); bft.doTarget("modifiedselectortest-ResourceSelresFalse"); bft.deleteCachefile(); } @Test public void testResourceSelectorScenarioSimple() { Assume.assumeNotNull("Ant home not set", selectorRule.getProject().getProperty("ant.home")); BFT bft = new BFT(); bft.doTarget("modifiedselectortest-scenario-resourceSimple"); bft.doTarget("modifiedselectortest-scenario-clean"); bft.deleteCachefile(); } /** * Test the interface semantic of Comparators. * This method does some common test for comparator implementations. * * @param comp configured test object */ protected void doTest(Comparator comp) { Object o1 = new String("string1"); Object o2 = new String("string2"); Object o3 = new String("string2"); // really "2" assertTrue("Comparator gave wrong value.", comp.compare(o1, o2) != 0); assertTrue("Comparator gave wrong value.", comp.compare(o1, o3) != 0); assertTrue("Comparator gave wrong value.", comp.compare(o2, o3) == 0); } // ===================== scenario tests ===================== /** * Tests whether the seldirs attribute is used. */ @Test public void testSeldirs() { ModifiedSelector s = new ModifiedSelector(); StringBuffer sbTrue = new StringBuffer(); StringBuffer sbFalse = new StringBuffer(); for (int i=0; i<selectorRule.getFiles().length; i++) { if (selectorRule.getFiles()[i].isDirectory()) { sbTrue.append("T"); sbFalse.append("F"); } else { sbTrue.append("T"); sbFalse.append("T"); } } s.setSeldirs(true); performTests(s, sbTrue.toString()); s.getCache().delete(); s.setSeldirs(false); performTests(s, sbFalse.toString()); s.getCache().delete(); s.getCache().delete(); } /** * Complex test scenario using default values (DigestAlgorithm with MD5, * PropertiesfileCache with file=cache.properties, EqualComparator * and update=true). <ol> * <li> try fist time --> should select all </li> * <li> try second time --> should select no files (only directories) </li> * <li> modify timestamp of one file and content of a nother one </li> * <li> try third time --> should select only the file with modified * content </li> */ @Test public void testScenario1() { BFT bft = null; ModifiedSelector s = null; try { String results; // Configure the selector - only defaults are used s = new ModifiedSelector(); // // ***** First Run ***** // the first call should get all files, because nothing is in // the cache // performTests(s, "TTTTTTTTTTTT"); // // ***** Second Run ***** // the second call should get no files, because no content // has changed // performTests(s, "TFFFFFFFFFFT"); // // ***** make some files dirty ***** // // these files are made dirty --> 3+4 with different content String f2name = "tar/bz2/asf-logo-huge.tar.bz2"; String f3name = "asf-logo.gif.md5"; String f4name = "copy.filterset.filtered"; // AccessObject to the test-Ant-environment bft = new BFT(); // give some values (via property file) to that environment bft.writeProperties("f2name="+f2name); bft.writeProperties("f3name="+f3name); bft.writeProperties("f4name="+f4name); // call the target for making the files dirty bft.doTarget("modifiedselectortest-makeDirty"); // // ***** Third Run ***** // third call should get only those files, which CONTENT changed // (no timestamp changes required!) results = selectorRule.selectionString(s); // // ***** Check the result ***** // // Mark all files which should be selected as (T)rue and all others // as (F)alse. Directories are always selected so they always are // (T)rue. StringBuffer expected = new StringBuffer(); for (int i=0; i<selectorRule.getFiles().length; i++) { String ch = "F"; if (selectorRule.getFiles()[i].isDirectory()) ch = "T"; // f2name shouldn't be selected: only timestamp has changed! if (selectorRule.getFilenames()[i].equalsIgnoreCase(f3name)) ch = "T"; if (selectorRule.getFilenames()[i].equalsIgnoreCase(f4name)) ch = "T"; expected.append(ch); } assertEquals( "Wrong files selected. Differing files: " // info text + resolve(diff(expected.toString(), results)), // list of files expected.toString(), // expected result results // result ); } finally { // cleanup the environment if (s!=null) s.getCache().delete(); if (bft!=null) bft.deletePropertiesfile(); } } /** * This scenario is based on scenario 1, but does not use any * default value and its based on <custom> selector. Used values are:<ul> * <li><b>Cache: </b> Propertyfile, * cachefile={java.io.tmpdir}/mycache.txt </li> * <li><b>Algorithm: </b> Digest * algorithm=SHA, Provider=null </li> * <li><b>Comparator: </b> java.text.RuleBasedCollator * <li><b>Update: </b> true </li> */ @Test @Ignore("RuleBasedCollator not yet supported - see Selector:375 note") public void testScenario2() { ExtendSelector s = new ExtendSelector(); BFT bft = new BFT(); String cachefile = System.getProperty("java.io.tmpdir")+"/mycache.txt"; try { s.setClassname("org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector"); s.addParam(createParam("cache.cachefile", cachefile)); //s.addParam(createParam("algorithm.provider","---")); // i don't know any valid s.addParam(createParam("cache","propertyfile")); s.addParam(createParam("update","true")); s.addParam(createParam("comparator","rule")); s.addParam(createParam("algorithm.name","sha")); s.addParam(createParam("algorithm","digest")); // first and second run performTests(s, "TTTTTTTTTTTT"); performTests(s, "TFFFFFFFFFFT"); // make dirty String f2name = "tar/bz2/asf-logo-huge.tar.bz2"; String f3name = "asf-logo.gif.md5"; String f4name = "copy.filterset.filtered"; bft.writeProperties("f2name="+f2name); bft.writeProperties("f3name="+f3name); bft.writeProperties("f4name="+f4name); bft.doTarget("modifiedselectortest-makeDirty"); // third run String results = selectorRule.selectionString(s); StringBuffer expected = new StringBuffer(); for (int i=0; i<selectorRule.getFilenames().length; i++) { String ch = "F"; if (selectorRule.getFiles()[i].isDirectory()) ch = "T"; if (selectorRule.getFilenames()[i].equalsIgnoreCase(f3name)) ch = "T"; if (selectorRule.getFilenames()[i].equalsIgnoreCase(f4name)) ch = "T"; expected.append(ch); } assertEquals( "Wrong files selected. Differing files: " // info text + resolve(diff(expected.toString(), results)), // list of files expected.toString(), // expected result results // result ); } finally { // cleanup the environment (new java.io.File(cachefile)).delete(); bft.deletePropertiesfile(); } } @Test public void testScenarioCoreSelectorDefaults() { Assume.assumeNotNull("Ant home not set", selectorRule.getProject().getProperty("ant.home") ); doScenarioTest("modifiedselectortest-scenario-coreselector-defaults", "cache.properties"); } @Test public void testScenarioCoreSelectorSettings() { Assume.assumeNotNull("Ant home not set", selectorRule.getProject().getProperty("ant.home") ); doScenarioTest("modifiedselectortest-scenario-coreselector-settings", "core.cache.properties"); } @Test public void testScenarioCustomSelectorSettings() { Assume.assumeNotNull("Ant home not set", selectorRule.getProject().getProperty("ant.home") ); doScenarioTest("modifiedselectortest-scenario-customselector-settings", "core.cache.properties"); } public void doScenarioTest(String target, String cachefilename) { BFT bft = new BFT(); bft.setUp(); File cachefile = new File(selectorRule.getProject().getBaseDir(), cachefilename); try { // do the actions bft.doTarget("modifiedselectortest-scenario-clean"); bft.doTarget(target); // the directories to check File to1 = new File(selectorRule.getOutputDir(), "selectortest/to-1"); File to2 = new File(selectorRule.getOutputDir(), "selectortest/to-2"); File to3 = new File(selectorRule.getOutputDir(), "selectortest/to-3"); // do the checks assertTrue("Cache file not created.", cachefile.exists()); assertTrue("Not enough files copied on first time.", to1.list().length>5); assertTrue("Too much files copied on second time.", to2.list().length==0); assertTrue("Too much files copied on third time.", to3.list().length==2); // don't catch the JUnit exceptions } finally { bft.doTarget("modifiedselectortest-scenario-clean"); bft.deletePropertiesfile(); bft.tearDown(); cachefile.delete(); } } // ===================== helper methods and classes ==================== /** * Creates a configured parameter object. * @param name name of the parameter * @param value value of the parameter * @return the parameter object */ private Parameter createParam(String name, String value) { Parameter p = new Parameter(); p.setName(name); p.setValue(value); return p; } /** * The BFT class wrapps the selector test-builfile inside an * ant project. It supports target execution * and property transfer to that project. */ private class BFT extends BuildFileRule { String buildfile = "src/etc/testcases/types/selectors.xml"; String propfile = "ModifiedSelectorTest.properties"; boolean isConfigured = false; public void setUp() { super.configureProject(buildfile); isConfigured = true; } /** * This stub teardown is here because the outer class needs to call the * tearDown method, and in the superclass it is protected. */ public void tearDown() { super.after(); } public void doTarget(String target) { if (!isConfigured) setUp(); executeTarget(target); } public String getProperty(String property) { return super.getProject().getProperty(property); } public void writeProperties(String line) { if (!isConfigured) setUp(); File dir = getProject().getBaseDir(); File file = new File(dir, propfile); try { java.io.FileWriter out = new java.io.FileWriter(file.getAbsolutePath(), true); out.write(line); out.write(System.getProperty("line.separator")); out.flush(); out.close(); } catch (Exception e) { e.printStackTrace(); } } public void deletePropertiesfile() { if (!isConfigured) setUp(); new File(getProject().getBaseDir(), propfile).delete(); } public void deleteCachefile() { File basedir = new File(buildfile).getParentFile(); File cacheFile = new File(basedir, "cache.properties"); cacheFile.delete(); } }//class-BFT /** * MockProject wrappes a very small ant project (one target, one task) * but provides public methods to fire the build events. */ private class MockProject extends Project { private Task task; private Target target; public MockProject() { task = new Task(){ public void execute() { } }; task.setTaskName("testTask"); target = new Target(); target.setName("testTarget"); target.setProject(this); target.addTask(task); task.setOwningTarget(target); } public void fireBuildFinished() { super.fireBuildFinished(null); } public void fireSubBuildFinished() { super.fireSubBuildFinished(null); } public void fireTargetStarted() { super.fireTargetStarted(target); } public void fireTargetFinished() { super.fireTargetFinished(target, null); } public void fireTaskStarted() { super.fireTaskStarted(task); } public void fireTaskFinished() { super.fireTaskFinished(task, null); } }//class-MockProject /** * Does the selection test for a given selector and prints the * filenames of the differing files (selected but shouldn't, * not selected but should). * @param selector The selector to test * @param expected The expected result */ private void performTests(FileSelector selector, String expected) { String result = selectorRule.selectionString(selector); String diff = diff(expected, result); String resolved = resolve(diff); assertEquals("Differing files: " + resolved, result, expected); } /** * Checks which files are selected and shouldn't be or which * are not selected but should. * @param expected String containing 'F's and 'T's * @param result String containing 'F's and 'T's * @return Difference as String containing '-' (equal) and * 'X' (difference). */ private String diff(String expected, String result) { int length1 = expected.length(); int length2 = result.length(); int min = (length1 > length2) ? length2 : length1; StringBuffer sb = new StringBuffer(); for (int i=0; i<min; i++) { sb.append( (expected.charAt(i) == result.charAt(i)) ? "-" : "X" ); } return sb.toString(); } /** * Resolves a diff-String (@see diff()) against the (inherited) filenames- * and files arrays. * @param filelist Diff-String * @return String containing the filenames for all differing files, * separated with semicolons ';' */ private String resolve(String filelist) { StringBuffer sb = new StringBuffer(); int min = (selectorRule.getFilenames().length > filelist.length()) ? filelist.length() : selectorRule.getFilenames().length; for (int i=0; i<min; i++) { if ('X'==filelist.charAt(i)) { sb.append(selectorRule.getFilenames()[i]); sb.append(";"); } } return sb.toString(); } }//class-ModifiedSelectorTest