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 */ 017package org.apache.wicket.util.tester; 018 019import static org.junit.jupiter.api.Assertions.assertEquals; 020 021import java.io.File; 022import java.io.FileOutputStream; 023import java.io.IOException; 024import java.io.InputStream; 025import java.io.PrintWriter; 026import java.net.URISyntaxException; 027import java.net.URL; 028 029import org.apache.wicket.markup.MarkupParser; 030import org.apache.wicket.markup.MarkupStream; 031import org.apache.wicket.util.diff.Diff; 032import org.apache.wicket.util.diff.DifferentiationFailedException; 033import org.apache.wicket.util.io.Streams; 034import org.apache.wicket.util.lang.Args; 035import org.apache.wicket.util.resource.ResourceStreamNotFoundException; 036import org.apache.wicket.util.string.StringList; 037import org.slf4j.Logger; 038import org.slf4j.LoggerFactory; 039 040/** 041 * This is a utility class. It serves two purposes. 042 * <p> 043 * First: compare a string output generated by wicket with a file's content (expected result). 044 * <p> 045 * Second: Create/replace the expected result file with the new content, if a system property has be 046 * made available like -Dwicket.replace.expected.results=true 047 * 048 * @author Juergen Donnerstag 049 */ 050public final class DiffUtil 051{ 052 private static final Logger log = LoggerFactory.getLogger(DiffUtil.class); 053 private static final String ENCODING = "UTF-8"; 054 055 /** 056 * Replace the expected result file with the current output. 057 * 058 * @param document 059 * How the expected result should look like 060 * @param clazz 061 * Used to load the file (relative to clazz package) 062 * @param file 063 * The name of the expected result file to be created 064 * @throws IOException 065 */ 066 public static void replaceExpectedResultFile(final String document, final Class<?> clazz, 067 final String file) throws IOException 068 { 069 String filename = clazz.getPackage().getName(); 070 filename = filename.replace('.', '/'); 071 filename += "/" + file; 072 073 try 074 { 075 final URL url = clazz.getClassLoader().getResource(filename); 076 filename = new File(url.toURI()).getAbsolutePath(); 077 } 078 catch (URISyntaxException ex) 079 { 080 throw new IOException(ex); 081 } 082 083 filename = filename.replaceAll("([/\\\\])target\\1test-classes\\1", "$1src$1test$1java$1"); 084 PrintWriter out = new PrintWriter(new FileOutputStream(filename)); 085 out.print(document); 086 out.close(); 087 } 088 089 /** 090 * Compare the output generated by Wicket ("document") with the a previously generated file 091 * which contains the expected result. 092 * 093 * @param document 094 * Current output 095 * @param file 096 * Expected output 097 * @param clazz 098 * Used to load the file (relative to clazz package) 099 * @param failWithAssert 100 * @return true, if equal 101 * @throws IOException 102 */ 103 public static boolean validatePage(String document, final Class<?> clazz, 104 final String file, boolean failWithAssert) throws IOException 105 { 106 Args.notNull(document, "document"); 107 108 String filename = clazz.getPackage().getName(); 109 filename = filename.replace('.', '/'); 110 filename += "/" + file; 111 112 InputStream in = clazz.getClassLoader().getResourceAsStream(filename); 113 if (in == null) 114 { 115 throw new IOException("File not found: " + filename); 116 } 117 118 String reference = Streams.readString(in, ENCODING); 119 120 // replace all line endings with unix style line ending 121 reference = reference.replaceAll("\n\r", "\n"); 122 reference = reference.replaceAll("\r\n", "\n"); 123 124 // replace all line endings with unix style line ending 125 document = document.replaceAll("\n\r", "\n"); 126 document = document.replaceAll("\r\n", "\n"); 127 128 boolean equals = compareMarkup(document, reference); 129 if (equals == false) 130 { 131 // Change the condition to true, if you want to make the new output 132 // the reference output for future tests. That is, it is regarded as 133 // correct. It'll replace the current reference files. Thus change 134 // it only for one test-run. 135 // -Dwicket.replace.expected.results=true 136 if (Boolean.getBoolean("wicket.replace.expected.results")) 137 { 138 in.close(); 139 in = null; 140 141 replaceExpectedResultFile(document, clazz, file); 142 return true; 143 } 144 145 log.error("File name: " + file); 146 /* */ 147 log.error("==================="); 148 log.error(reference); 149 log.error("==================="); 150 151 log.error(document); 152 log.error("==================="); 153 /* */ 154 155 String[] test1 = StringList.tokenize(reference, "\n").toArray(); 156 String[] test2 = StringList.tokenize(document, "\n").toArray(); 157 Diff df = new Diff(test1); 158 try 159 { 160 df.diff(test2); 161 } 162 catch (DifferentiationFailedException e) 163 { 164 throw new RuntimeException(e); 165 } 166 167 // System.out.println(r.toString()); 168 169 if (failWithAssert) 170 { 171 assertEquals(reference, document, filename); 172 } 173 } 174 175 return equals; 176 } 177 178 /** 179 * @param a 180 * String a 181 * @param b 182 * String b 183 * @return True if the two strings have the same markup tags 184 */ 185 private static boolean compareMarkup(final String a, final String b) 186 { 187 try 188 { 189 // Parse a and b into markup and compare 190 final MarkupStream amarkup = new MarkupStream(new MarkupParser(a).parse()); 191 final MarkupStream bmarkup = new MarkupStream(new MarkupParser(b).parse()); 192 return amarkup.equalTo(bmarkup); 193 } 194 catch (IOException e) 195 { 196 log.error(e.getMessage(), e); 197 } 198 catch (ResourceStreamNotFoundException e) 199 { 200 log.error(e.getMessage(), e); 201 } 202 return false; 203 } 204 205}