View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.general;
16  
17  import static java.nio.charset.StandardCharsets.ISO_8859_1;
18  import static org.junit.Assert.fail;
19  
20  import java.io.File;
21  import java.io.IOException;
22  import java.util.HashSet;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Set;
26  import java.util.regex.Matcher;
27  import java.util.regex.Pattern;
28  
29  import org.apache.commons.io.FileUtils;
30  import org.junit.Test;
31  
32  /**
33   * Tests the general host tests have all JavaScript objects names defined in all the other tests.
34   *
35   * This classes parses all the test code, searching for [object some_name], and ensures that
36   * {@link HostClassNameTest} and {@link HostTypeOfTest} include those objects.
37   *
38   * @author Ahmed Ashour
39   * @author Ronald Brill
40   */
41  public class HostTestsTest {
42  
43      private Pattern pattern_ = Pattern.compile("\"\\[object (\\w+)\\]\"");
44  
45      /**
46       * @throws Exception if an error occurs
47       */
48      @Test
49      public void test() throws Exception {
50          final Set<String> set = new HashSet<>();
51          final File testRoot = new File("src/test/java");
52          collectionObjectNames(testRoot, set);
53  
54          // Remove all Prototypes, as we plan to have test cases separate for them soon
55          // TODO: add Prototype tests (e.g. alert(Element.prototype)
56          for (final Iterator<String> it = set.iterator(); it.hasNext();) {
57              if (it.next().endsWith("Prototype")) {
58                  it.remove();
59              }
60          }
61          if (set.contains("Arguments")) {
62              set.remove("Arguments");
63              set.add("arguments");
64          }
65  
66          set.remove("Iterator");
67          set.remove("URLSearchParamsIterator");
68  
69          // Worker
70          set.remove("DedicatedWorkerGlobalScope");
71          set.remove("WorkerGlobalScope");
72          set.remove("global");
73  
74          ensure(new File(testRoot, HostClassNameTest.class.getName().replace('.', '/') + ".java"), set);
75          ensure(new File(testRoot, HostTypeOfTest.class.getName().replace('.', '/') + ".java"), set);
76      }
77  
78      private void collectionObjectNames(final File dir, final Set<String> set) throws IOException {
79          final File[] files = dir.listFiles();
80          if (files != null) {
81              for (final File file : files) {
82                  if (file.isDirectory() && !".git".equals(file.getName())) {
83                      collectionObjectNames(file, set);
84                  }
85                  else if (file.getName().endsWith(".java")) {
86                      final List<String> lines = FileUtils.readLines(file, ISO_8859_1);
87                      for (final String line : lines) {
88                          final Matcher matcher = pattern_.matcher(line);
89                          while (matcher.find()) {
90                              set.add(matcher.group(1));
91                          }
92                      }
93                  }
94              }
95          }
96      }
97  
98      private static void ensure(final File file, final Set<String> set) throws IOException {
99          final Set<String> unusedNames = new HashSet<>(set);
100         final List<String> lines = FileUtils.readLines(file, ISO_8859_1);
101         for (final String line : lines) {
102             for (final Iterator<String> it = unusedNames.iterator(); it.hasNext();) {
103                 if (line.contains("(\"" + it.next() + "\")")) {
104                     it.remove();
105                 }
106             }
107         }
108         if (!unusedNames.isEmpty()) {
109             fail("You must specify the following line"
110                     + (unusedNames.size() == 1 ? "" : "s") + " in " + file.getName() + ":\n"
111                     + String.join(", ", unusedNames));
112         }
113     }
114 }