blob: 41f6ca7d7ced2d8d8b934dc1ea16f495dc18e53c [file] [log] [blame]
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "Ant" and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.types.selectors;
// Java
import java.io.File;
import java.io.FileWriter;
import java.util.Comparator;
import java.util.Iterator;
import java.text.RuleBasedCollator;
// Ant
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.types.Parameter;
// The classes to test
import org.apache.tools.ant.types.selectors.modifiedselector.*;
/**
* Unit tests for ModifiedSelector.
*
* @author Jan Mat\u00e8rne
* @version 2003-09-13
* @since Ant 1.6
*/
public class ModifiedSelectorTest extends BaseSelectorTest {
/** Package of the CacheSelector classes. */
private static String pkg = "org.apache.tools.ant.types.selectors.modifiedselector";
public ModifiedSelectorTest(String name) {
super(name);
}
/**
* Factory method from base class. This should be overriden in child
* classes to return a specific Selector class (like here).
*/
public BaseSelector getInstance() {
return new ModifiedSelector();
}
/** Test right use of cache names. */
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. */
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. */
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());
}
}
/**
* Propertycache must have a set 'cachefile' attribute.
* The default in ModifiedSelector "cache.properties" is set by the selector.
*/
public void testPropcacheInvalid() {
Cache cache = new PropertiesfileCache();
if (cache.isValid())
fail("PropertyfilesCache does not check its configuration.");
}
/**
* Tests whether the seldirs attribute is used.
*/
public void testSeldirs() {
ModifiedSelector s = (ModifiedSelector)getSelector();
try {
makeBed();
StringBuffer sbTrue = new StringBuffer();
StringBuffer sbFalse = new StringBuffer();
for (int i=0; i<filenames.length; i++) {
if (files[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();
} finally {
cleanupBed();
if (s!=null) 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>
*/
public void testScenario1() {
BFT bft = null;
ModifiedSelector s = null;
try {
//
// ***** initialize test environment (called "bed") *****
//
makeBed();
String results = null;
// Configure the selector - only defaults are used
s = (ModifiedSelector)getSelector();
//
// ***** 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 = 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<filenames.length; i++) {
String ch = "F";
if (files[i].isDirectory()) ch = "T";
// f2name shouldn't be selected: only timestamp has changed!
if (filenames[i].equalsIgnoreCase(f3name)) ch = "T";
if (filenames[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
cleanupBed();
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>
*/
public void testScenario2() {
ExtendSelector s = new ExtendSelector();
BFT bft = new BFT();
String cachefile = System.getProperty("java.io.tmpdir")+"/mycache.txt";
try {
makeBed();
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 = selectionString(s);
StringBuffer expected = new StringBuffer();
for (int i=0; i<filenames.length; i++) {
String ch = "F";
if (files[i].isDirectory()) ch = "T";
if (filenames[i].equalsIgnoreCase(f3name)) ch = "T";
if (filenames[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
cleanupBed();
(new java.io.File(cachefile)).delete();
if (bft!=null) bft.deletePropertiesfile();
}
}
/** Checks whether a cache file is created. */
public void testCreatePropertiesCacheDirect() {
File basedir = getSelector().getProject().getBaseDir();
File cachefile = new File(basedir, "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. */
public void testCreatePropertiesCacheViaModifiedSelector() {
File basedir = getSelector().getProject().getBaseDir();
File cachefile = new File(basedir, "cachefile.properties");
try {
// initialize test environment (called "bed")
makeBed();
// Configure the selector
ModifiedSelector s = (ModifiedSelector)getSelector();
s.addParam("cache.cachefile", cachefile);
ModifiedSelector.CacheName cacheName = new ModifiedSelector.CacheName();
cacheName.setValue("propertyfile");
s.setCache(cacheName);
s.setUpdate(true);
// does the selection
String results = selectionString(s);
// evaluate correctness
assertTrue("Cache file is not created.", cachefile.exists());
} finally {
cleanupBed();
if (cachefile!=null) 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.
*/
public void testCreatePropertiesCacheViaCustomSelector() {
File cachefile = org.apache.tools.ant.util.FileUtils.newFileUtils()
.createTempFile("tmp-cache-", ".properties", null);
try {
// initialize test environment (called "bed")
makeBed();
// 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"));
// does the selection
String results = selectionString(s);
// evaluate correctness
assertTrue("Cache file is not created.", cachefile.exists());
} finally {
cleanupBed();
if (cachefile!=null) cachefile.delete();
}
}
public void testEqualComparatorViaSelector() {
ModifiedSelector s = (ModifiedSelector)getSelector();
ModifiedSelector.ComparatorName compName = new ModifiedSelector.ComparatorName();
compName.setValue("equal");
s.setComparator(compName);
try {
performTests(s, "TTTTTTTTTTTT");
} finally {
s.getCache().delete();
}
}
public void testRuleComparatorViaSelector() {
ModifiedSelector s = (ModifiedSelector)getSelector();
ModifiedSelector.ComparatorName compName = new ModifiedSelector.ComparatorName();
compName.setValue("rule");
s.setComparator(compName);
try {
performTests(s, "TTTTTTTTTTTT");
} finally {
s.getCache().delete();
}
}
public void testHashvalueAlgorithm() {
HashvalueAlgorithm algo = new HashvalueAlgorithm();
doTest(algo);
}
public void testDigestAlgorithmMD5() {
DigestAlgorithm algo = new DigestAlgorithm();
algo.setAlgorithm("MD5");
doTest(algo);
}
public void testDigestAlgorithmSHA() {
DigestAlgorithm algo = new DigestAlgorithm();
algo.setAlgorithm("SHA");
doTest(algo);
}
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());
}
public void testEqualComparator() {
EqualComparator comp = new EqualComparator();
doTest(comp);
}
public void testRuleComparator() {
RuleBasedCollator comp = (RuleBasedCollator)RuleBasedCollator.getInstance();
doTest(comp);
}
public void testScenarioCoreSelectorDefaults() {
doScenarioTest("modifiedselectortest-scenario-coreselector-defaults", "cache.properties");
}
public void testSceanrioCoreSelectorSettings() {
doScenarioTest("modifiedselectortest-scenario-coreselector-settings", "core.cache.properties");
}
public void testScenarioCustomSelectorSettings() {
doScenarioTest("modifiedselectortest-scenario-customselector-settings", "core.cache.properties");
}
public void doScenarioTest(String target, String cachefilename) {
BFT bft = new BFT();
bft.setUp();
File basedir = bft.getProject().getBaseDir();
File cachefile = new File(basedir, cachefilename);
try {
// do the actions
bft.doTarget("modifiedselectortest-scenario-clean");
bft.doTarget(target);
// the directories to check
File to1 = new File(basedir, "selectortest/to-1");
File to2 = new File(basedir, "selectortest/to-2");
File to3 = new File(basedir, "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();
}
}
// ==================== Test interface semantic ===================
/**
* 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());
try {
makeBed();
for (int i=0; i<files.length; i++) {
File file = files[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
} finally {
cleanupBed();
}
}
/**
* 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 algo 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", it1.hasNext());
}
/**
* This method does some common test for comparator implementations.
*
* @param algo 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);
}
// ======================== Helper methods ========================
private Parameter createParam(String name, String value) {
Parameter p = new Parameter();
p.setName(name);
p.setValue(value);
return p;
}
private class BFT extends org.apache.tools.ant.BuildFileTest {
BFT() { super("nothing"); }
BFT(String name) {
super(name);
}
String propfile = "ModifiedSelectorTest.properties";
boolean isConfigured = false;
public void setUp() {
configureProject("src/etc/testcases/types/selectors.xml");
isConfigured = true;
}
public void tearDown() { }
public void doTarget(String target) {
if (!isConfigured) setUp();
executeTarget(target);
}
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 org.apache.tools.ant.Project getProject() {
return super.getProject();
}
}//class-BFT
}//class-ModifiedSelectorTest