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