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;
16  
17  import static java.nio.charset.StandardCharsets.ISO_8859_1;
18  import static org.junit.Assert.assertTrue;
19  import static org.junit.Assert.fail;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.lang.reflect.Field;
24  import java.util.ArrayList;
25  import java.util.Iterator;
26  import java.util.LinkedList;
27  import java.util.List;
28  
29  import org.apache.commons.io.FileUtils;
30  import org.htmlunit.javascript.configuration.AbstractJavaScriptConfiguration;
31  import org.htmlunit.javascript.configuration.BrowserFeature;
32  import org.htmlunit.javascript.configuration.SupportedBrowser;
33  import org.junit.Test;
34  
35  /**
36   * Tests for {@link BrowserVersionFeatures}.
37   *
38   * @author Ahmed Ashour
39   * @author Ronald Brill
40   * @author Frank Danek
41   */
42  public class BrowserVersionFeaturesTest {
43  
44      /**
45       * Test of alphabetical order.
46       */
47      @Test
48      public void lexicographicOrder() {
49          String lastFeatureName = null;
50          for (final BrowserVersionFeatures feature : BrowserVersionFeatures.values()) {
51              final String featureName = feature.name();
52              if (lastFeatureName != null && featureName.compareTo(lastFeatureName) < 1) {
53                  fail("BrowserVersionFeatures.java: '"
54                      + featureName + "' should be before '" + lastFeatureName + "'");
55              }
56              lastFeatureName = featureName;
57          }
58      }
59  
60      /**
61       * Test of usage.
62       * @throws Exception in case of problems
63       */
64      @Test
65      public void unusedFeatures() throws Exception {
66          final List<BrowserVersion> browsers = new LinkedList<>();
67          browsers.add(BrowserVersion.CHROME);
68          browsers.add(BrowserVersion.EDGE);
69          browsers.add(BrowserVersion.FIREFOX);
70          browsers.add(BrowserVersion.FIREFOX_ESR);
71  
72          for (final BrowserVersionFeatures feature : BrowserVersionFeatures.values()) {
73              int useCount = 0;
74              for (final BrowserVersion browserVersion : browsers) {
75                  if (browserVersion.hasFeature(feature)) {
76                      useCount++;
77                  }
78              }
79              assertTrue("BrowserVersionFeatures.java: '" + feature.name() + "' in no longer in use.", useCount > 0);
80              assertTrue("BrowserVersionFeatures.java: '" + feature.name() + "' is enabled for all supported browsers.",
81                      useCount < browsers.size());
82          }
83  
84          for (final BrowserVersionFeatures feature : BrowserVersionFeatures.values()) {
85              final Field field = BrowserVersionFeatures.class.getField(feature.name());
86              final BrowserFeature browserFeature = field.getAnnotation(BrowserFeature.class);
87  
88              if (browserFeature != null) {
89                  for (final SupportedBrowser annotatedBrowser : browserFeature.value()) {
90                      boolean inUse = false;
91                      for (final BrowserVersion supportedBrowser : browsers) {
92                          if (AbstractJavaScriptConfiguration.isCompatible(expectedBrowserName(supportedBrowser),
93                                  annotatedBrowser)) {
94                              inUse = true;
95                              continue;
96                          }
97                      }
98                      assertTrue("BrowserVersionFeatures.java: Annotation '"
99                              + annotatedBrowser + "' of feature '"
100                             + feature.name() + "' in no longer in use.", inUse);
101                 }
102             }
103         }
104     }
105 
106     private static SupportedBrowser expectedBrowserName(final BrowserVersion browser) {
107         if (browser == BrowserVersion.EDGE) {
108             return SupportedBrowser.EDGE;
109         }
110         if (browser == BrowserVersion.FIREFOX) {
111             return SupportedBrowser.FF;
112         }
113         if (browser == BrowserVersion.FIREFOX_ESR) {
114             return SupportedBrowser.FF_ESR;
115         }
116 
117         return SupportedBrowser.CHROME;
118     }
119 
120     /**
121      * Test of usage in the Java files.
122      *
123      * @throws Exception in case of problems
124      */
125     @Test
126     public void unusedFeaturesInCode() throws Exception {
127         final List<String> unusedFeatures = new ArrayList<>(BrowserVersionFeatures.values().length);
128         for (final BrowserVersionFeatures feature : BrowserVersionFeatures.values()) {
129             unusedFeatures.add(feature.name());
130         }
131         unusedCheck(new File("src/main/java"), unusedFeatures);
132         if (!unusedFeatures.isEmpty()) {
133             fail("The following " + BrowserVersionFeatures.class.getSimpleName() + " "
134                     + (unusedFeatures.size() == 1 ? "is" : "are") + " not used: "
135                     + String.join(", ", unusedFeatures));
136         }
137     }
138 
139     private void unusedCheck(final File dir, final List<String> unusedFeatures) throws IOException {
140         final File[] files = dir.listFiles();
141         if (files != null) {
142             for (final File file : files) {
143                 if (file.isDirectory() && !".git".equals(file.getName())) {
144                     unusedCheck(file, unusedFeatures);
145                 }
146                 else if (file.getName().endsWith(".java")) {
147                     final List<String> lines = FileUtils.readLines(file, ISO_8859_1);
148                     final String browserVersionFeatures = BrowserVersionFeatures.class.getSimpleName();
149                     for (final String line : lines) {
150                         for (final Iterator<String> it = unusedFeatures.iterator(); it.hasNext();) {
151                             if (line.contains(browserVersionFeatures + '.' + it.next())) {
152                                 it.remove();
153                             }
154                         }
155                     }
156                 }
157             }
158         }
159     }
160 }