001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.tools.ant.taskdefs;
020:
021: import java.io.File;
022: import java.io.FileFilter;
023: import java.io.FileInputStream;
024: import java.io.IOException;
025: import java.util.Enumeration;
026: import java.util.Hashtable;
027: import java.util.Properties;
028: import java.util.Vector;
029:
030: import org.apache.tools.ant.BuildFileTest;
031: import org.apache.tools.ant.Project;
032: import org.apache.tools.ant.types.Path;
033: import org.apache.tools.ant.util.FileUtils;
034:
035: /**
036: */
037: public class XmlPropertyTest extends BuildFileTest {
038: private static final FileUtils FILE_UTILS = FileUtils
039: .getFileUtils();
040:
041: public XmlPropertyTest(String name) {
042: super (name);
043: }
044:
045: public void setUp() {
046: configureProject("src/etc/testcases/taskdefs/xmlproperty.xml");
047: }
048:
049: public void testFile() {
050: testProperties("test");
051: }
052:
053: public void testResource() {
054: testProperties("testResource");
055: }
056:
057: private void testProperties(String target) {
058: executeTarget(target);
059: assertEquals("true", getProject().getProperty(
060: "root-tag(myattr)"));
061: assertEquals("Text", getProject().getProperty(
062: "root-tag.inner-tag"));
063: assertEquals("val", getProject().getProperty(
064: "root-tag.inner-tag(someattr)"));
065: assertEquals("false", getProject().getProperty(
066: "root-tag.a2.a3.a4"));
067: assertEquals("CDATA failed", "<test>", getProject()
068: .getProperty("root-tag.cdatatag"));
069: }
070:
071: public void testDTD() {
072: executeTarget("testdtd");
073: assertEquals("Text", getProject().getProperty(
074: "root-tag.inner-tag"));
075: }
076:
077: public void testNone() {
078: doTest("testNone", false, false, false, false, false);
079: }
080:
081: public void testKeeproot() {
082: doTest("testKeeproot", true, false, false, false, false);
083: }
084:
085: public void testCollapse() {
086: doTest("testCollapse", false, true, false, false, false);
087: }
088:
089: public void testSemantic() {
090: doTest("testSemantic", false, false, true, false, false);
091: }
092:
093: public void testKeeprootCollapse() {
094: doTest("testKeeprootCollapse", true, true, false, false, false);
095: }
096:
097: public void testKeeprootSemantic() {
098: doTest("testKeeprootSemantic", true, false, true, false, false);
099: }
100:
101: public void testCollapseSemantic() {
102: doTest("testCollapseSemantic", false, true, true, false, false);
103: }
104:
105: public void testKeeprootCollapseSemantic() {
106: doTest("testKeeprootCollapseSemantic", true, true, true, false,
107: false);
108: }
109:
110: public void testInclude() {
111: doTest("testInclude", false, false, false, true, false);
112: }
113:
114: public void testSemanticInclude() {
115: doTest("testSemanticInclude", false, false, true, true, false);
116: }
117:
118: public void testSemanticLocal() {
119: doTest("testSemanticInclude", false, false, true, false, true);
120: }
121:
122: public void testNeedsCatalog() {
123: executeTarget("testneedscat");
124: assertEquals("true", getProject().getProperty("skinconfig.foo"));
125: }
126:
127: /**
128: * Actually run a test, finding all input files (and corresponding
129: * goldfile)
130: */
131: private void doTest(String msg, boolean keepRoot, boolean collapse,
132: boolean semantic, boolean include, boolean localRoot) {
133: Enumeration iter = getFiles(new File(
134: System.getProperty("root"),
135: "src/etc/testcases/taskdefs/xmlproperty/inputs"));
136: while (iter.hasMoreElements()) {
137: File inputFile = (File) iter.nextElement();
138: // What's the working directory? If local, then its the
139: // folder of the input file. Otherwise, its the "current" dir..
140: File workingDir;
141: if (localRoot) {
142: workingDir = inputFile.getParentFile();
143: } else {
144: workingDir = FILE_UTILS.resolveFile(new File("."), ".");
145: }
146:
147: try {
148:
149: File propertyFile = getGoldfile(inputFile, keepRoot,
150: collapse, semantic, include, localRoot);
151: if (!propertyFile.exists()) {
152: // System.out.println("Skipping as "
153: // + propertyFile.getAbsolutePath()
154: // + ") doesn't exist.");
155: continue;
156: }
157:
158: // System.out.println(msg + " (" + propertyFile.getName() + ") in (" + workingDir + ")");
159:
160: Project p = new Project();
161:
162: XmlProperty xmlproperty = new XmlProperty();
163: xmlproperty.setProject(p);
164: xmlproperty.setFile(inputFile);
165:
166: xmlproperty.setKeeproot(keepRoot);
167: xmlproperty.setCollapseAttributes(collapse);
168: xmlproperty.setSemanticAttributes(semantic);
169: xmlproperty.setIncludeSemanticAttribute(include);
170: xmlproperty.setRootDirectory(workingDir);
171:
172: // Set a property on the project to make sure that loading
173: // a property with the same name from an xml file will
174: // *not* change it.
175: p.setNewProperty("override.property.test", "foo");
176:
177: xmlproperty.execute();
178:
179: Properties props = new Properties();
180: props.load(new FileInputStream(propertyFile));
181:
182: //printProperties(p.getProperties());
183:
184: ensureProperties(msg, inputFile, workingDir, p, props);
185: ensureReferences(msg, inputFile, p.getReferences());
186:
187: } catch (IOException ex) {
188: fail(ex.toString());
189: }
190: }
191: }
192:
193: /**
194: * Make sure every property loaded from the goldfile was also
195: * read from the XmlProperty. We could try and test the other way,
196: * but some other properties may get set in the XmlProperty due
197: * to generic Project/Task configuration.
198: */
199: private static void ensureProperties(String msg, File inputFile,
200: File workingDir, Project p, Properties properties) {
201: Hashtable xmlproperties = p.getProperties();
202: // Every key identified by the Properties must have been loaded.
203: Enumeration propertyKeyEnum = properties.propertyNames();
204: while (propertyKeyEnum.hasMoreElements()) {
205: String currentKey = propertyKeyEnum.nextElement()
206: .toString();
207: String assertMsg = msg + "-" + inputFile.getName()
208: + " Key=" + currentKey;
209:
210: String propertyValue = properties.getProperty(currentKey);
211:
212: String xmlValue = (String) xmlproperties.get(currentKey);
213:
214: if (propertyValue.indexOf("ID.") == 0) {
215: // The property is an id's thing -- either a property
216: // or a path. We need to make sure
217: // that the object was created with the given id.
218: // We don't have an adequate way of testing the actual
219: // *value* of the Path object, though...
220: String id = currentKey;
221: Object obj = p.getReferences().get(id);
222:
223: if (obj == null) {
224: fail(assertMsg + " Object ID does not exist.");
225: }
226:
227: // What is the property supposed to be?
228: propertyValue = propertyValue.substring(3,
229: propertyValue.length());
230: if (propertyValue.equals("path")) {
231: if (!(obj instanceof Path)) {
232: fail(assertMsg + " Path ID is a "
233: + obj.getClass().getName());
234: }
235: } else {
236: assertEquals(assertMsg, propertyValue, obj
237: .toString());
238: }
239:
240: } else {
241:
242: if (propertyValue.indexOf("FILE.") == 0) {
243: // The property is the name of a file. We are testing
244: // a location attribute, so we need to resolve the given
245: // file name in the provided folder.
246: String fileName = propertyValue.substring(5,
247: propertyValue.length());
248: File f = new File(workingDir, fileName);
249: propertyValue = f.getAbsolutePath();
250: }
251:
252: assertEquals(assertMsg, propertyValue, xmlValue);
253: }
254:
255: }
256: }
257:
258: /**
259: * Debugging method to print the properties in the given hashtable
260: */
261: private static void printProperties(Hashtable xmlproperties) {
262: Enumeration keyEnum = xmlproperties.keys();
263: while (keyEnum.hasMoreElements()) {
264: String currentKey = keyEnum.nextElement().toString();
265: System.out.println(currentKey + " = "
266: + xmlproperties.get(currentKey));
267: }
268: }
269:
270: /**
271: * Ensure all references loaded by the project are valid.
272: */
273: private static void ensureReferences(String msg, File inputFile,
274: Hashtable references) {
275: Enumeration referenceKeyEnum = references.keys();
276: while (referenceKeyEnum.hasMoreElements()) {
277: String currentKey = referenceKeyEnum.nextElement()
278: .toString();
279: Object currentValue = references.get(currentKey);
280:
281: if (currentValue instanceof Path) {
282: } else if (currentValue instanceof String) {
283: } else {
284: if (!currentKey.startsWith("ant.")) {
285: fail(msg + "-" + inputFile.getName() + " Key="
286: + currentKey + " is not a recognized type.");
287: }
288: }
289: }
290: }
291:
292: /**
293: * Munge the name of the input file to find an appropriate goldfile,
294: * based on hardwired naming conventions.
295: */
296: private static File getGoldfile(File input, boolean keepRoot,
297: boolean collapse, boolean semantic, boolean include,
298: boolean localRoot) {
299: // Substitute .xml with .properties
300: String baseName = input.getName().toLowerCase();
301: if (baseName.endsWith(".xml")) {
302: baseName = baseName.substring(0, baseName.length() - 4)
303: + ".properties";
304: }
305:
306: File dir = input.getParentFile().getParentFile();
307:
308: String goldFileFolder = "goldfiles/";
309:
310: if (keepRoot) {
311: goldFileFolder += "keeproot-";
312: } else {
313: goldFileFolder += "nokeeproot-";
314: }
315:
316: if (semantic) {
317: goldFileFolder += "semantic-";
318: if (include) {
319: goldFileFolder += "include-";
320: }
321: } else {
322: if (collapse) {
323: goldFileFolder += "collapse-";
324: } else {
325: goldFileFolder += "nocollapse-";
326: }
327: }
328:
329: return new File(dir, goldFileFolder + baseName);
330: }
331:
332: /**
333: * Retrieve a list of xml files in the specified folder
334: * and below.
335: */
336: private static Enumeration getFiles(final File startingDir) {
337: Vector result = new Vector();
338: getFiles(startingDir, result);
339: return result.elements();
340: }
341:
342: /**
343: * Collect a list of xml files in the specified folder
344: * and below.
345: */
346: private static void getFiles(final File startingDir, Vector collect) {
347: FileFilter filter = new FileFilter() {
348: public boolean accept(File file) {
349: if (file.isDirectory()) {
350: return true;
351: } else {
352: return (file.getPath().indexOf("taskdefs") > 0 && file
353: .getPath().toLowerCase().endsWith(".xml"));
354: }
355: }
356: };
357:
358: File[] files = startingDir.listFiles(filter);
359: for (int i = 0; i < files.length; i++) {
360: File f = files[i];
361: if (!f.isDirectory()) {
362: collect.addElement(f);
363: } else {
364: getFiles(f, collect);
365: }
366: }
367: }
368: }
|