001: package org.andromda.cartridges.testsuite;
002:
003: import java.io.File;
004: import java.util.ArrayList;
005: import java.util.Arrays;
006: import java.util.Collection;
007: import java.util.Collections;
008: import java.util.Iterator;
009: import java.util.List;
010:
011: import junit.framework.Test;
012: import junit.framework.TestCase;
013: import junit.framework.TestSuite;
014:
015: import org.andromda.core.common.AndroMDALogger;
016: import org.apache.commons.lang.StringUtils;
017: import org.apache.log4j.Logger;
018:
019: /**
020: * <p>
021: * This is the entry point of the cartridge test suite for AndroMDA. The
022: * test checks for a list of expected files that a file with the same name and
023: * the same package was generated by AndroMDA and that the APIs of the expected
024: * file and the generated file are equal. <code>CartridgeTest</code> acts as
025: * the test director which creates the list of files to be compared. The actual
026: * API comparison is carried out by instances of {@link JavaSourceComparator}.
027: * </p>
028: *
029: * @author Ralf Wirdemann
030: * @author Chad Brandon
031: */
032: public class CartridgeTest extends TestCase {
033: private static final Logger logger = Logger
034: .getLogger(CartridgeTest.class);
035:
036: /**
037: * Points to the directory were the expected files are stored which will be
038: * compared to the generated ones.
039: */
040: public static final String EXPECTED_DIRECTORY = "expected.dir";
041:
042: /**
043: * Points to the directory were the generated files are located.
044: */
045: public static final String ACTUAL_DIRECTORY = "actual.dir";
046:
047: /**
048: * Defines the suffixes of binary files (files that will be not be
049: * compared as strings).
050: */
051: public static final String BINARY_SUFFIXES = "binary.suffixes";
052:
053: /**
054: * The shared instanceo of this class.
055: */
056: private static CartridgeTest instance;
057:
058: /**
059: * Retrieves the shared instance of this class.
060: *
061: * @return the shared instance.
062: */
063: public static final CartridgeTest instance() {
064: if (instance == null) {
065: instance = new CartridgeTest();
066: }
067: return instance;
068: }
069:
070: private CartridgeTest() {
071: super ();
072: }
073:
074: /**
075: * Stores a comma seperated list of binary suffixes.
076: */
077: private String binarySuffixes = StringUtils.trimToEmpty(System
078: .getProperty(BINARY_SUFFIXES));
079:
080: /**
081: * Sets the value of the suffixes that indicate a binary file (binary files
082: * are not compared as text).
083: *
084: * @param binarySuffixes a comma seperated list of binary suffixes.
085: */
086: public void setBinarySuffixes(final String binarySuffixes) {
087: this .binarySuffixes = binarySuffixes;
088: }
089:
090: /**
091: * Stores the actual directory.
092: */
093: private String actualOutputPath = StringUtils.trimToEmpty(System
094: .getProperty(ACTUAL_DIRECTORY));
095:
096: /**
097: * Sets the path to the <em>actual</em> directory (that is the
098: * directory which contains the actual output being tested.
099: *
100: * @param actualOutputPath the path to the actual directory.
101: */
102: public void setActualOutputPath(final String actualOutputPath) {
103: this .actualOutputPath = actualOutputPath;
104: }
105:
106: /**
107: * Stores the path to the excepted directory.
108: */
109: private String expectedOutputPath = StringUtils.trimToEmpty(System
110: .getProperty(EXPECTED_DIRECTORY));
111:
112: /**
113: * Sets the path to the <em>expected</em> directory. This is the directory
114: * to which the expected output is extracted.
115: *
116: * @param expectedOutputPath the path to the expected output directory.
117: */
118: public void setExpectedOutputPath(final String expectedOutputPath) {
119: this .expectedOutputPath = expectedOutputPath;
120: }
121:
122: static {
123: AndroMDALogger.initialize();
124: }
125:
126: public CartridgeTest(final String name) {
127: super (name);
128: }
129:
130: public static Test suite() {
131: TestSuite suite = new TestSuite();
132: instance().addTests(suite);
133: return suite;
134: }
135:
136: /**
137: * Adds tests which compare all actual generated files against the expected
138: * files.
139: *
140: * @param suite the test suite to which we'll add the tests.
141: */
142: private void addTests(final TestSuite suite) {
143: final List expectedFiles = new ArrayList();
144: getAllFiles(this .getExpectedOutputDirectory(), expectedFiles);
145: final Iterator iterator = expectedFiles.iterator();
146: logger.info(" --- Expecting " + expectedFiles.size()
147: + " Generated Files --- ");
148: logger.info("binary suffixes --> " + getBinarySuffixes());
149: final List missingFiles = new ArrayList();
150: for (int ctr = 1; iterator.hasNext(); ctr++) {
151: final File expectedFile = (File) iterator.next();
152: final File actualFile = getActualFile(expectedFile);
153: if (!actualFile.exists()) {
154: missingFiles.add(actualFile);
155: }
156: final boolean binary = isBinary(actualFile);
157: final StringBuffer header = new StringBuffer(ctr
158: + ") binary = " + binary);
159: logger.debug(header);
160: logger.debug("expected --> '" + expectedFile + "'");
161: logger.debug("actual --> '" + actualFile + "'");
162: suite.addTest(new FileComparator("testEquals",
163: expectedFile, actualFile, binary));
164: }
165: if (!missingFiles.isEmpty()) {
166: Collections.sort(missingFiles);
167: StringBuffer failureMessage = new StringBuffer(
168: "\n--- The following ");
169: failureMessage.append(missingFiles.size());
170: failureMessage
171: .append(" expected files do not exist ----\n");
172: Iterator missingFileIterator = missingFiles.iterator();
173: for (int ctr = 1; missingFileIterator.hasNext(); ctr++) {
174: failureMessage.append(ctr);
175: failureMessage.append(")");
176: failureMessage.append(" ");
177: failureMessage.append(missingFileIterator.next());
178: if (missingFileIterator.hasNext()) {
179: failureMessage.append("\n");
180: }
181: }
182: TestCase.fail(failureMessage.toString());
183: }
184: }
185:
186: /**
187: * Contructs the expected file path from the <code>actualFile</code> and
188: * the <code>expectedDir</code> path.
189: *
190: * @param actualFile the actual generated file
191: * @return the new expected file.
192: */
193: private File getActualFile(final File expectedFile) {
194: String actualFile;
195: final File actualOutputDirectory = this
196: .getActualOutputDirectory();
197: final File expectedOutputDirectory = this
198: .getExpectedOutputDirectory();
199: final String path = expectedFile.getPath();
200: if (expectedFile.getPath().startsWith(
201: actualOutputDirectory.getPath())) {
202: actualFile = path.substring(actualOutputDirectory.getPath()
203: .length(), path.length());
204: actualFile = expectedOutputDirectory
205: + expectedFile.toString();
206: } else {
207: actualFile = path.substring(expectedOutputDirectory
208: .getPath().length(), path.length());
209: actualFile = actualOutputDirectory + actualFile;
210: }
211: return new File(actualFile);
212: }
213:
214: /**
215: * The expected output directory.
216: */
217: private File expectedOutputDirectory;
218:
219: /**
220: * Retrieves the expected output directory.
221: *
222: * @return the file representing the directory.
223: */
224: private File getExpectedOutputDirectory() {
225: if (this .expectedOutputDirectory == null) {
226: this .expectedOutputDirectory = this
227: .getDirectory(this .expectedOutputPath);
228: }
229: return this .expectedOutputDirectory;
230: }
231:
232: /**
233: * The actual output directory.
234: */
235: private File actualOutputDirectory;
236:
237: private File getActualOutputDirectory() {
238: if (this .actualOutputDirectory == null) {
239: this .actualOutputDirectory = this
240: .getDirectory(this .actualOutputPath);
241: }
242: return this .actualOutputDirectory;
243: }
244:
245: /**
246: * Gets the directory from the system property key.
247: *
248: * @param path the system property key name.
249: * @return the directory as a File instance.
250: */
251: private File getDirectory(final String path) {
252: File directory = new File(path);
253: if (!directory.exists() || !directory.isDirectory()) {
254: throw new RuntimeException("directory <" + path
255: + "> doesn't exist");
256: }
257: return directory;
258: }
259:
260: /**
261: * Checks whether or not the <code>file</code> is a binary file. Does this
262: * by checking to see if the suffix is found in the list of binary suffixes.
263: *
264: * @param file the file to check
265: * @return true/false
266: */
267: private boolean isBinary(final File file) {
268: String suffix = "";
269: final String fileName = file.getName();
270: int dotIndex = fileName.indexOf('.');
271: if (dotIndex != -1) {
272: suffix = fileName
273: .substring(dotIndex + 1, fileName.length());
274: }
275: return this .getBinarySuffixes().contains(suffix);
276: }
277:
278: private Collection binarySuffixCollection;
279:
280: /**
281: * Gets the binary suffixes for the <code>binary.suffixes</code> system
282: * property. Returns an empty collection if none are found.
283: *
284: * @return the Collection of binary suffixes. (ie. jpg, jar, zip, etc).
285: */
286: private Collection getBinarySuffixes() {
287: if (this .binarySuffixCollection == null) {
288: final String suffixes = this .binarySuffixes != null ? this .binarySuffixes
289: .trim()
290: : "";
291: final String[] suffixArray = suffixes.split("\\s*,\\s*");
292: this .binarySuffixCollection = Arrays.asList(suffixArray);
293: }
294: return this .binarySuffixCollection;
295: }
296:
297: /**
298: * Loads all files find in the <code>directory</code> and adds them to the
299: * <code>fileList</code>.
300: *
301: * @param directory the directory from which to load all files.
302: * @param fileList the List of files to which we'll add the found files.
303: */
304: private void getAllFiles(final File directory, final List fileList) {
305: final File[] files = directory.listFiles();
306: for (int ctr = 0; ctr < files.length; ctr++) {
307: final File file = files[ctr];
308: if (!file.isDirectory()) {
309: fileList.add(file);
310: } else {
311: getAllFiles(file, fileList);
312: }
313: }
314: }
315:
316: /**
317: * Releases any resouces help by this cartridge test instance.
318: */
319: public void shutdown() {
320: instance = null;
321: }
322: }
|