View Javadoc
1   /*
2    * SPDX-FileCopyrightText: Copyright (c) 2011-2026 Yegor Bugayenko
3    * SPDX-License-Identifier: MIT
4    */
5   package com.qulice.checkstyle;
6   
7   import com.qulice.spi.Environment;
8   import com.qulice.spi.Violation;
9   import java.io.File;
10  import java.io.IOException;
11  import java.util.Collection;
12  import org.cactoos.io.ResourceOf;
13  import org.cactoos.list.ListOf;
14  import org.cactoos.text.FormattedText;
15  import org.cactoos.text.IoCheckedText;
16  import org.cactoos.text.TextOf;
17  import org.hamcrest.MatcherAssert;
18  import org.hamcrest.Matchers;
19  import org.hamcrest.collection.IsIterableContainingInOrder;
20  import org.junit.jupiter.api.Test;
21  
22  /**
23   * Test case for {@link CheckstyleValidator}'s detection of banned
24   * API usages such as Guava {@code Lists.newArrayList()} with no
25   * size, Apache Commons {@code CharEncoding}, and interface type
26   * parameter naming.
27   *
28   * @since 0.25.1
29   */
30  final class CheckstyleBannedApiTest {
31  
32      @Test
33      void reportsGuavaNewArrayListWithoutSize() throws Exception {
34          final String file = "GuavaNewArrayList.java";
35          MatcherAssert.assertThat(
36              "Guava Lists.newArrayList without size must be reported",
37              this.runValidation(file, false),
38              Matchers.hasItem(
39                  new ViolationMatcher(
40                      "Lists.newArrayList should be initialized with a size parameter",
41                      file
42                  )
43              )
44          );
45      }
46  
47      @Test
48      @SuppressWarnings("unchecked")
49      void reportsAllCharEncodingUsages() throws Exception {
50          final String message =
51              "Use java.nio.charset.StandardCharsets instead";
52          final String file = "DoNotUseCharEncoding.java";
53          final String name = "RegexpSinglelineCheck";
54          MatcherAssert.assertThat(
55              "9 violations should be found",
56              this.runValidation(file, false),
57              new IsIterableContainingInOrder<>(
58                  new ListOf<>(
59                      new ViolationMatcher(message, file, "6", name),
60                      new ViolationMatcher(message, file, "7", name),
61                      new ViolationMatcher(message, file, "8", name),
62                      new ViolationMatcher(message, file, "9", name),
63                      new ViolationMatcher(message, file, "31", name),
64                      new ViolationMatcher(message, file, "32", name),
65                      new ViolationMatcher(message, file, "33", name),
66                      new ViolationMatcher(
67                          "is redundant, import it and use",
68                          file, "34", "FullyQualifiedTypeCheck"
69                      ),
70                      new ViolationMatcher(message, file, "34", name)
71                  )
72              )
73          );
74      }
75  
76      @Test
77      void reportsInvalidInterfaceTypeParameterName() throws Exception {
78          final String file = "InterfaceTypeParameterName.java";
79          MatcherAssert.assertThat(
80              "Interface type parameter violation must be reported",
81              this.runValidation(file, false),
82              Matchers.hasItem(
83                  new ViolationMatcher(
84                      "Name 'wRoNg' must match pattern", file,
85                      "12", "InterfaceTypeParameterNameCheck"
86                  )
87              )
88          );
89      }
90  
91      @Test
92      @SuppressWarnings("unchecked")
93      void reportsUnnecessaryJavaLangPrefix() throws Exception {
94          final String message =
95              "Unnecessary java.lang. prefix, use the simple class name";
96          final String file = "UnnecessaryJavaLang.java";
97          final String name = "UnnecessaryJavaLangCheck";
98          MatcherAssert.assertThat(
99              "cannot find all java.lang. violations",
100             this.runValidation(file, false),
101             Matchers.hasItems(
102                 new ViolationMatcher(message, file, "11", name),
103                 new ViolationMatcher(message, file, "19", name),
104                 new ViolationMatcher(message, file, "25", name),
105                 new ViolationMatcher(message, file, "27", name)
106             )
107         );
108     }
109 
110     @Test
111     @SuppressWarnings("unchecked")
112     void ignoresJavaLangInsideStringLiterals() throws Exception {
113         final String message =
114             "Unnecessary java.lang. prefix, use the simple class name";
115         final String file = "UnnecessaryJavaLang.java";
116         final String name = "UnnecessaryJavaLangCheck";
117         MatcherAssert.assertThat(
118             "java.lang. inside a string literal or text block must be ignored",
119             this.runValidation(file, false),
120             Matchers.not(
121                 Matchers.anyOf(
122                     Matchers.hasItem(new ViolationMatcher(message, file, "47", name)),
123                     Matchers.hasItem(new ViolationMatcher(message, file, "57", name))
124                 )
125             )
126         );
127     }
128 
129     private Collection<Violation> runValidation(final String file,
130         final boolean passes) throws IOException {
131         final Environment.Mock mock = new Environment.Mock();
132         final Environment env = mock.withParam(
133             "license",
134             String.format(
135                 "file:%s",
136                 new License().savePackageInfo(
137                     new File(mock.basedir(), "src/main/java/foo")
138                 ).withLines("Hello.")
139                     .withEol(String.valueOf('\n')).file()
140             )
141         ).withFile(
142             String.format("src/main/java/foo/%s", file),
143             new IoCheckedText(
144                 new TextOf(
145                     new ResourceOf(
146                         new FormattedText("com/qulice/checkstyle/%s", file)
147                     )
148                 )
149             ).asString()
150         );
151         final Collection<Violation> results =
152             new CheckstyleValidator(env).validate(env.files(file));
153         if (passes) {
154             MatcherAssert.assertThat(
155                 results,
156                 Matchers.<Violation>empty()
157             );
158         } else {
159             MatcherAssert.assertThat(
160                 results,
161                 Matchers.not(Matchers.<Violation>empty())
162             );
163         }
164         return results;
165     }
166 }