1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.source;
16
17 import static java.nio.charset.StandardCharsets.ISO_8859_1;
18
19 import java.io.BufferedReader;
20 import java.io.BufferedWriter;
21 import java.io.File;
22 import java.io.FileReader;
23 import java.io.FileWriter;
24 import java.io.IOException;
25 import java.lang.reflect.Method;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.Collections;
29 import java.util.HashMap;
30 import java.util.HashSet;
31 import java.util.Iterator;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.TreeMap;
35 import java.util.TreeSet;
36 import java.util.regex.Matcher;
37 import java.util.regex.Pattern;
38
39 import org.apache.commons.io.FileUtils;
40 import org.apache.commons.lang3.reflect.MethodUtils;
41 import org.htmlunit.WebDriverTestCase;
42 import org.htmlunit.junit.annotation.NotYetImplemented;
43 import org.htmlunit.junit.annotation.TestedBrowser;
44 import org.htmlunit.libraries.JQuery1x8x2Test;
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 public final class JQueryExtractor {
63 private static final String RERUN_ID = "Rerun [";
64
65 private JQueryExtractor() {
66 }
67
68
69
70
71
72
73 public static void main(final String[] args) throws Exception {
74 final Class<? extends WebDriverTestCase> testClass = JQuery1x8x2Test.class;
75
76
77
78 final String version = (String) MethodUtils.invokeExactMethod(testClass.newInstance(), "getVersion");
79 final File baseDir = new File("src/test/resources/libraries/jQuery/" + version + "/expectations");
80
81 for (final String browser : new String[] {"CHROME", "EDGE", "FF", "FF_ESR"}) {
82 final File out = new File(baseDir, browser + ".out");
83 final File results = new File(baseDir, "results." + browser + ".txt");
84 extractExpectations(out, results);
85 }
86
87 generateTestCases(testClass, baseDir);
88 }
89
90
91
92
93
94
95
96
97
98 public static void extractExpectations(final File input, final File output) throws IOException {
99 try (BufferedReader reader = new BufferedReader(new FileReader(input))) {
100 try (BufferedWriter writer = new BufferedWriter(new FileWriter(output))) {
101 int testNumber = 1;
102 String line;
103 while ((line = reader.readLine()) != null) {
104 line = line.trim();
105
106
107
108 if (line.contains(RERUN_ID)) {
109
110 line = line.replace(".skipped", ".");
111
112 final int start = line.indexOf(RERUN_ID) + RERUN_ID.length();
113 final int end = line.indexOf(']', start);
114 final String testId = line.substring(start, end);
115
116 line = line.substring(0, line.indexOf(RERUN_ID)).trim();
117 final String prefix = "" + testNumber + ".";
118 if (line.startsWith(prefix)) {
119 line = line.substring(prefix.length());
120 }
121 line = "" + testNumber + '.' + ' ' + line + " [" + testId + ']';
122 writer.write(line + System.lineSeparator());
123 testNumber++;
124 }
125
126
127
128
129 else if (line.indexOf("Rerun") > -1) {
130 line = line.substring(0, line.indexOf("Rerun"))
131 + " [" + testNumber + ']';
132 writer.write(line + System.lineSeparator());
133 testNumber++;
134 }
135 else if (line.endsWith("Rerun")) {
136 if (line.indexOf("" + testNumber + '.', 4) != -1) {
137 System.out.println("Incorrect line for test# " + testNumber
138 + ", please correct it manually");
139 break;
140 }
141 line = "" + testNumber + '.'
142 + ' ' + line.substring(0, line.length() - 5)
143 + " [" + testNumber + ']';
144 writer.write(line + System.lineSeparator());
145 testNumber++;
146 }
147 }
148 System.out.println("Last output #" + (testNumber - 1));
149 }
150 }
151 }
152
153
154
155
156
157
158
159 public static void generateTestCases(final Class<? extends WebDriverTestCase> testClass,
160 final File dir) throws Exception {
161 final TestedBrowser[] browsers = TestedBrowser.values();
162
163 final List<String> mainNames = new ArrayList<>();
164 for (final TestedBrowser b : browsers) {
165 final String name = b.name();
166 if (!"NONE".equals(name) && Character.isLetter(name.charAt(name.length() - 1))) {
167 mainNames.add(name);
168 }
169 }
170
171 final Map<String, List<String>> browserVersions = new HashMap<>();
172 for (final TestedBrowser b : browsers) {
173 final String name = b.name();
174 for (final String mainName : mainNames) {
175 if (!name.equals(mainName) && name.startsWith(mainName)) {
176 List<String> list = browserVersions.get(mainName);
177 if (list == null) {
178 list = new ArrayList<>();
179 browserVersions.put(mainName, list);
180 }
181 list.add(name);
182 }
183 }
184 }
185 final Map<String, Expectations> browserExpectations = new HashMap<>();
186 final File[] files = dir.listFiles();
187 if (files != null) {
188 for (final File file : files) {
189 if (file.isFile() && file.getName().endsWith(".txt")) {
190 for (final TestedBrowser b : browsers) {
191 final String browserName = b.name();
192 if (file.getName().equalsIgnoreCase("results." + browserName.replace('_', '.') + ".txt")) {
193 browserExpectations.put(browserName, Expectations.readExpectations(file));
194 }
195 }
196 }
197 }
198 }
199
200
201 final List<Test> allTests = computeTestsList(browserExpectations);
202
203 final Collection<String> availableBrowserNames = new TreeSet<>(browserExpectations.keySet());
204 for (final Test test : allTests) {
205 final Map<String, String> testExpectation = new TreeMap<>();
206 final Map<Integer, List<String>> lineToBrowser = new TreeMap<>();
207 for (final String browserName : availableBrowserNames) {
208 final Expectation expectation = browserExpectations.get(browserName).getExpectation(test);
209 if (expectation != null) {
210 List<String> browsersForLine = lineToBrowser.get(expectation.getLine());
211 if (browsersForLine == null) {
212 browsersForLine = new ArrayList<>();
213 lineToBrowser.put(expectation.getLine(), browsersForLine);
214 }
215 browsersForLine.add(browserName);
216 final String str = expectation.getTestResult();
217 testExpectation.put(browserName,
218 str.replaceAll("\\\\", "\\\\\\\\").replaceAll("\\\"", "\\\\\""));
219 }
220 }
221 System.out.println(" /**");
222 System.out.println(" * Test " + lineToBrowser + ".");
223 System.out.println(" * @throws Exception if an error occurs");
224 System.out.println(" */");
225 System.out.println(" @Test");
226 System.out.print(" @Alerts(");
227
228 final boolean allSame = testExpectation.size() == availableBrowserNames.size()
229 && new HashSet<>(testExpectation.values()).size() == 1;
230 if (allSame) {
231 final String first = testExpectation.keySet().iterator().next();
232 String expectation = testExpectation.get(first);
233 if (expectation.length() > 100) {
234 expectation = expectation.substring(0, 50) + "\"\n + \"" + expectation.substring(50);
235 }
236 System.out.print("\"" + expectation + '"');
237 }
238 else {
239 final List<String> cleanedBrowserNames = new ArrayList<>(testExpectation.keySet());
240 Collections.sort(cleanedBrowserNames);
241
242 if (testExpectation.size() == availableBrowserNames.size()) {
243
244
245 int matches = 0;
246 ArrayList<String> defaultBrowsers = null;
247
248 for (final String browser : cleanedBrowserNames) {
249 final String expectation = testExpectation.get(browser);
250
251 final ArrayList<String> matchBrowsers = new ArrayList<>();
252 int matchCount = 0;
253 for (final String otherBrowser : cleanedBrowserNames) {
254 if (!browser.equals(otherBrowser)
255 && expectation.equals(testExpectation.get(otherBrowser))) {
256 matchCount++;
257 matchBrowsers.add(otherBrowser);
258 }
259 }
260 if (matches < matchCount) {
261 matches = matchCount;
262 matchBrowsers.add(browser);
263 defaultBrowsers = matchBrowsers;
264 }
265 }
266
267 if (matches > 1) {
268 testExpectation.put("DEFAULT", testExpectation.get(defaultBrowsers.get(0)));
269 cleanedBrowserNames.add(0, "DEFAULT");
270 for (final String browser : defaultBrowsers) {
271 testExpectation.remove(browser);
272 cleanedBrowserNames.remove(browser);
273 }
274 }
275 }
276
277 boolean first = true;
278 if (cleanedBrowserNames.size() == 1 && "DEFAULT".equals(cleanedBrowserNames.get(0))) {
279 System.out.print("\"" + testExpectation.get("DEFAULT") + '"');
280 }
281 else {
282 for (final String browserName : cleanedBrowserNames) {
283 final String expectation = testExpectation.get(browserName);
284 if (expectation == null) {
285 continue;
286 }
287 if (!first) {
288 System.out.println(",");
289 System.out.print(" ");
290 }
291 System.out.print(browserName + " = \"" + expectation + '"');
292 first = false;
293 }
294 }
295 }
296 System.out.println(")");
297
298 final String methodName = test.getName().replaceAll("\\W", "_");
299 try {
300 final Method method = testClass.getMethod(methodName);
301 final NotYetImplemented notYetImplemented = method.getAnnotation(NotYetImplemented.class);
302 if (null != notYetImplemented) {
303 final TestedBrowser[] notYetImplementedBrowsers = notYetImplemented.value();
304 if (notYetImplementedBrowsers.length > 0) {
305 final List<String> browserNames = new ArrayList<>(notYetImplementedBrowsers.length);
306 for (final TestedBrowser browser : notYetImplementedBrowsers) {
307 browserNames.add(browser.name());
308 }
309 Collections.sort(browserNames);
310
311
312 if (browserNames.size() == 5
313 && browserNames.contains("CHROME")
314 && browserNames.contains("EDGE")
315 && browserNames.contains("FF")
316 && browserNames.contains("FF_ESR")) {
317 System.out.println(" @NotYetImplemented");
318 }
319 else {
320 System.out.print(" @NotYetImplemented(");
321 if (browserNames.size() > 1) {
322 System.out.print("{ ");
323 }
324 System.out.print(String.join(", ", browserNames));
325 if (browserNames.size() > 1) {
326 System.out.print(" }");
327 }
328 System.out.println(")");
329 }
330 }
331 }
332 }
333 catch (final NoSuchMethodException e) {
334
335 }
336
337 System.out.println(" public void " + methodName + "() throws Exception {");
338 System.out.println(" runTest(\"" + test.getName().replace("\"", "\\\"") + "\");");
339 System.out.println(" }");
340 System.out.println();
341 }
342 }
343
344 private static List<Test> computeTestsList(final Map<String, Expectations> browserExpectations) {
345 final Map<String, Test> map = new HashMap<>();
346 for (final Expectations expectations : browserExpectations.values()) {
347 for (final Expectation expectation : expectations) {
348 final String testName = expectation.getTestName();
349 Test test = map.get(testName);
350 if (test == null) {
351 test = new Test(testName);
352 map.put(testName, test);
353 }
354 test.addLine(expectation.getLine());
355 }
356 }
357
358 final List<Test> tests = new ArrayList<>(map.values());
359 Collections.sort(tests);
360
361 return tests;
362 }
363
364 static class Expectations implements Iterable<Expectation> {
365 static Expectations readExpectations(final File file) throws IOException {
366 final Expectations expectations = new Expectations();
367 final List<String> lines = FileUtils.readLines(file, ISO_8859_1);
368 for (int i = 0; i < lines.size(); i++) {
369 expectations.add(new Expectation(file, i + 1, lines.get(i)));
370 }
371
372 return expectations;
373 }
374
375 private final Map<String, Expectation> expectations_ = new HashMap<>();
376
377 public Expectation getExpectation(final Test test) {
378 return expectations_.get(test.getName());
379 }
380
381 private void add(final Expectation expectation) {
382 expectations_.put(expectation.getTestName(), expectation);
383 }
384
385 @Override
386 public Iterator<Expectation> iterator() {
387 return expectations_.values().iterator();
388 }
389 }
390
391 static class Expectation {
392
393 private static final Pattern PATTERN =
394 Pattern.compile("(\\d+\\. ?)?(.+)\\((\\d+(, \\d+, \\d+)?)\\) \\[([0-9a-f]{1,8})\\]");
395
396 private final int line_;
397 private final String testId_;
398 private final String testName_;
399 private final String testResult_;
400
401 Expectation(final File file, final int line, final String string) {
402 line_ = line;
403 final Matcher matcher = PATTERN.matcher(string);
404 if (!matcher.matches()) {
405 throw new RuntimeException("Invalid line " + line + ": '" + string
406 + "' in file: " + file.getAbsolutePath());
407 }
408 final String testNumber = matcher.group(1);
409 if (testNumber != null && !testNumber.trim().equals(line + ".")) {
410 throw new RuntimeException("Invalid test number for line " + line + ": " + string
411 + " in file: " + file.getAbsolutePath());
412 }
413
414 testName_ = matcher.group(2).trim();
415 testResult_ = matcher.group(3);
416 testId_ = matcher.group(4);
417 }
418
419 public int getLine() {
420 return line_;
421 }
422
423 public String getTestId() {
424 return testId_;
425 }
426
427 public String getTestName() {
428 return testName_;
429 }
430
431 public String getTestResult() {
432 return testResult_;
433 }
434 }
435
436 static class Test implements Comparable<Test> {
437 private final List<Integer> lines_ = new ArrayList<>();
438 private final String name_;
439
440 Test(final String name) {
441 name_ = name;
442 }
443
444 public String getName() {
445 return name_;
446 }
447
448 void addLine(final int line) {
449 if (!lines_.contains(line)) {
450 lines_.add(line);
451 Collections.sort(lines_);
452 }
453 }
454
455 @Override
456 public int compareTo(final Test o) {
457 int diff = lines_.get(0) - o.lines_.get(0);
458 if (diff == 0) {
459 diff = lines_.size() - o.lines_.size();
460 if (diff == 0) {
461 diff = name_.compareTo(o.name_);
462 }
463 }
464 return diff;
465 }
466
467 @Override
468 public int hashCode() {
469 return name_.hashCode();
470 }
471
472 @Override
473 public boolean equals(final Object obj) {
474 return (obj instanceof Test) && name_.equals(((Test) obj).name_);
475 }
476 }
477 }