001package org.andromda.maven.plugin.cartridge; 002 003import java.io.File; 004import java.util.List; 005import junit.framework.TestCase; 006import org.apache.commons.io.FileUtils; 007import org.apache.commons.lang.StringUtils; 008 009/** 010 * Compares two files. It checks if both file do exist and if the contents of 011 * both files are equal. 012 * 013 * @author Chad Brandon 014 * @author Bob Fields 015 */ 016public class FileComparator 017 extends TestCase 018{ 019 private File expectedFile; 020 private File actualFile; 021 private boolean binary = false; 022 private boolean ignoreLineEndings = true; 023 private boolean ignoreWhitespace = false; 024 private List<String> ignoreLinesWithStrings = null; 025 026 /** 027 * Constructs a new instance of the FileComparator. 028 * 029 * @param testName the name of the test to run 030 * @param expectedFile the location of the expected file 031 * @param actualFile the location of the actual file. 032 * @param binary whether or not the file is binary, if it is binary contents 033 * of the binary are not compared as Strings but as binary files. 034 */ 035 public FileComparator( 036 String testName, 037 File expectedFile, 038 File actualFile, 039 boolean binary) 040 { 041 super(); 042 this.setName(testName); 043 this.expectedFile = expectedFile; 044 this.actualFile = actualFile; 045 this.binary = binary; 046 } 047 048 /** 049 * Constructs a new instance of the FileComparator. 050 * 051 * @param testName the name of the test to run 052 * @param expectedFile the location of the expected file 053 * @param actualFile the location of the actual file. 054 * @param binary whether or not the file is binary, if it is binary contents 055 * of the binary are not compared as Strings but as binary files. 056 * @param ignoreWhitespace Ignore whitespace in the comparison 057 * @param ignoreLineEndings Ignore Unix/Windows line ending differences \r vs \r\n 058 * @param ignoreLinesWithStrings Ignore lines containing the strings in the comparison 059 */ 060 public FileComparator( 061 String testName, 062 File expectedFile, 063 File actualFile, 064 boolean binary, 065 boolean ignoreWhitespace, 066 boolean ignoreLineEndings, 067 List<String> ignoreLinesWithStrings) 068 { 069 this(testName, expectedFile, actualFile, binary); 070 this.ignoreWhitespace = ignoreWhitespace; 071 this.ignoreLineEndings = ignoreLineEndings; 072 this.ignoreLinesWithStrings = ignoreLinesWithStrings; 073 } 074 075 /** 076 * Test if actual and expected file contents are equal. 077 */ 078 public void testEquals() 079 { 080 assertTrue( 081 "expected file <" + expectedFile.getPath() + "> doesn't exist", 082 expectedFile.exists()); 083 assertTrue( 084 "actual file <" + actualFile.getPath() + "> doesn't exist", 085 actualFile.exists()); 086 this.testContentsEqual(); 087 } 088 089 /** 090 * Loads both the <code>actual</code> and <code>expected</code> files 091 * and tests the contents for equality. 092 */ 093 protected void testContentsEqual() 094 { 095 try 096 { 097 String message = "actual file <" + actualFile + "> does not match\n"; 098 if (this.binary) 099 { 100 assertTrue( 101 message, 102 FileUtils.contentEquals( 103 expectedFile, 104 actualFile)); 105 } 106 else 107 { 108 String actualContents = FileUtils.readFileToString(actualFile); 109 String expectedContents = FileUtils.readFileToString(expectedFile); 110 //Ignore 'generated on ' date comments different between expected/actual 111 // Sometimes it says 'Autogenerated on 04/22/2010 14:49:09-0400 by AndroMDA', sometimes it says 'Generated by ' XX cartridge 112 // Remove the rest of the line from the comparison. 113 if (this.ignoreLinesWithStrings != null && !this.ignoreLinesWithStrings.isEmpty()) 114 { 115 expectedContents = removeLinesWithStrings(expectedContents, ignoreLinesWithStrings); 116 actualContents = removeLinesWithStrings(actualContents, ignoreLinesWithStrings); 117 } 118 if (this.ignoreWhitespace) 119 { 120 expectedContents = StringUtils.remove(expectedContents, ' '); 121 expectedContents = StringUtils.remove(expectedContents, '\t'); 122 actualContents = StringUtils.remove(actualContents, ' '); 123 actualContents = StringUtils.remove(actualContents, '\t'); 124 } 125 if (this.ignoreLineEndings) 126 { 127 expectedContents = StringUtils.remove(expectedContents, '\r'); 128 actualContents = StringUtils.remove(actualContents, '\r'); 129 } 130 // TODO Tell me the line number where the difference is located. 131 assertEquals( 132 message, 133 expectedContents.trim(), 134 actualContents.trim()); 135 } 136 } 137 catch (final Throwable throwable) 138 { 139 fail(throwable.toString()); 140 } 141 } 142 143 /** 144 * @param input 145 * @param patternList 146 * @return String input with the lines containing the string removed 147 */ 148 public String removeLinesWithStrings(String input, List<String> patternList) 149 { 150 String tempString = input; 151 for (String pattern : patternList) 152 { 153 int patternIndex = tempString.indexOf(pattern); 154 while (patternIndex > 0) 155 { 156 String temp = tempString.substring(patternIndex, tempString.length()); 157 temp = temp.substring(temp.indexOf('\n')); 158 tempString = tempString.substring(0, patternIndex) + temp; 159 patternIndex = tempString.indexOf(pattern); 160 } 161 } 162 return tempString; 163 } 164 165 /** 166 * Gets the actual file being compared. 167 * 168 * @return the file being compared. 169 */ 170 public File getActualFile() 171 { 172 return this.actualFile; 173 } 174 175 /** 176 * Gets the file expected file (i.e. the file that 177 * the actual file is compared against). 178 * 179 * @return the expected file. 180 */ 181 public File getExpectedFile() 182 { 183 return this.expectedFile; 184 } 185}