blob: 0b940ad649414339defb5f3505e8bc70ff93f496 [file] [log] [blame]
/*
* 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;
import java.io.File;
import java.io.FileWriter;
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.apache.tools.ant.util.StringUtils;
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 correct 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 correct 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 correct 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 correct use of algorithm names. */
@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 correct use of algorithm names. */
@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();
// don't catch the JUnit exceptions
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.contains("ant.bat"));
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));
} 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 doesn't 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();
StringBuilder sbTrue = new StringBuilder();
StringBuilder sbFalse = new StringBuilder();
for (File file : selectorRule.getFiles()) {
if (file.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 --&gt; should select all</li>
* <li>try second time --&gt; should select no files (only directories)</li>
* <li>modify timestamp of one file and content of another one</li>
* <li>try third time --&gt; should select only the file with modified
* content</li></ol>
*/
@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.
StringBuilder expected = new StringBuilder();
for (int i = 0; i < selectorRule.getFiles().length; i++) {
String ch = "F";
// f2name shouldn't be selected: only timestamp has changed!
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
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 &lt;custom&gt; 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>
* <li><b>Update:</b> true</li></ul>
*/
@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);
StringBuilder expected = new StringBuilder();
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 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 {
FileWriter out = new FileWriter(file.getAbsolutePath(), true);
out.write(line);
out.write(StringUtils.LINE_SEP);
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();
}
}
/**
* 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);
}
@SuppressWarnings("unused")
public void fireSubBuildFinished() {
super.fireSubBuildFinished(null);
}
@SuppressWarnings("unused")
public void fireTargetStarted() {
super.fireTargetStarted(target);
}
public void fireTargetFinished() {
super.fireTargetFinished(target, null);
}
@SuppressWarnings("unused")
public void fireTaskStarted() {
super.fireTaskStarted(task);
}
public void fireTaskFinished() {
super.fireTaskFinished(task, null);
}
}
/**
* 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;
StringBuilder sb = new StringBuilder();
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) {
StringBuilder sb = new StringBuilder();
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]).append(";");
}
}
return sb.toString();
}
}