View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2024 the original author or authors.
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ///////////////////////////////////////////////////////////////////////////////////////////////
19  
20  package com.puppycrawl.tools.checkstyle.checks;
21  
22  import static com.google.common.truth.Truth.assertWithMessage;
23  import static com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheck.MSG_IO_EXCEPTION_KEY;
24  import static com.puppycrawl.tools.checkstyle.checks.UniquePropertiesCheck.MSG_KEY;
25  
26  import java.io.File;
27  import java.io.IOException;
28  import java.io.InputStream;
29  import java.lang.reflect.Constructor;
30  import java.lang.reflect.Method;
31  import java.nio.file.Files;
32  import java.nio.file.NoSuchFileException;
33  import java.util.ArrayList;
34  import java.util.Collections;
35  import java.util.HashMap;
36  import java.util.List;
37  import java.util.Map;
38  import java.util.SortedSet;
39  
40  import org.junit.jupiter.api.Test;
41  
42  import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
43  import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
44  import com.puppycrawl.tools.checkstyle.api.FileText;
45  import com.puppycrawl.tools.checkstyle.api.Violation;
46  import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
47  
48  public class UniquePropertiesCheckTest extends AbstractModuleTestSupport {
49  
50      @Override
51      protected String getPackageLocation() {
52          return "com/puppycrawl/tools/checkstyle/checks/uniqueproperties";
53      }
54  
55      /* Additional test for jacoco, since valueOf()
56       * is generated by javac and jacoco reports that
57       * valueOf() is uncovered.
58       */
59      @Test
60      public void testLineSeparatorOptionValueOf() {
61          final LineSeparatorOption option = LineSeparatorOption.valueOf("CR");
62          assertWithMessage("Invalid valueOf result")
63              .that(option)
64              .isEqualTo(LineSeparatorOption.CR);
65      }
66  
67      /**
68       * Tests the ordinal work of a check.
69       */
70      @Test
71      public void testDefault() throws Exception {
72          final DefaultConfiguration checkConfig = createModuleConfig(UniquePropertiesCheck.class);
73          final String[] expected = {
74              "3: " + getCheckMessage(MSG_KEY, "general.exception", 2),
75              "5: " + getCheckMessage(MSG_KEY, "DefaultLogger.auditStarted", 2),
76              "11: " + getCheckMessage(MSG_KEY, "onlineManual", 3),
77              "22: " + getCheckMessage(MSG_KEY, "time stamp", 3),
78              "28: " + getCheckMessage(MSG_KEY, "Support Link ", 2),
79              "34: " + getCheckMessage(MSG_KEY, "failed", 2),
80          };
81          verify(checkConfig, getPath("InputUniqueProperties.properties"), expected);
82      }
83  
84      /**
85       * Tests the {@link UniquePropertiesCheck#getLineNumber(FileText, String)}
86       * method return value.
87       *
88       * @noinspection JavadocReference
89       * @noinspectionreason JavadocReference - reference is required to specify method under test
90       */
91      @Test
92      public void testNotFoundKey() throws Exception {
93          final List<String> testStrings = new ArrayList<>(3);
94          final Method getLineNumber = UniquePropertiesCheck.class.getDeclaredMethod(
95              "getLineNumber", FileText.class, String.class);
96          assertWithMessage("Get line number method should be present")
97              .that(getLineNumber)
98              .isNotNull();
99          getLineNumber.setAccessible(true);
100         testStrings.add("");
101         testStrings.add("0 = 0");
102         testStrings.add("445");
103         final FileText fileText = new FileText(new File("some.properties"), testStrings);
104         final Object lineNumber = getLineNumber.invoke(UniquePropertiesCheck.class,
105                 fileText, "some key");
106         assertWithMessage("Line number should not be null")
107             .that(lineNumber)
108             .isNotNull();
109         assertWithMessage("Invalid line number")
110             .that(lineNumber)
111             .isEqualTo(1);
112     }
113 
114     @Test
115     public void testDuplicatedProperty() throws Exception {
116         final DefaultConfiguration checkConfig = createModuleConfig(UniquePropertiesCheck.class);
117         final String[] expected = {
118             "2: " + getCheckMessage(MSG_KEY, "key", 2),
119         };
120         verify(checkConfig, getPath("InputUniquePropertiesWithDuplicates.properties"), expected);
121     }
122 
123     @Test
124     public void testShouldNotProcessFilesWithWrongFileExtension() throws Exception {
125         final DefaultConfiguration checkConfig = createModuleConfig(UniquePropertiesCheck.class);
126         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
127         verify(checkConfig, getPath("InputUniqueProperties.txt"), expected);
128     }
129 
130     /**
131      * Tests IO exception, that can occur during reading of properties file.
132      */
133     @Test
134     public void testIoException() throws Exception {
135         final DefaultConfiguration checkConfig = createModuleConfig(UniquePropertiesCheck.class);
136         final UniquePropertiesCheck check = new UniquePropertiesCheck();
137         check.configure(checkConfig);
138         final String fileName =
139                 getPath("InputUniquePropertiesCheckNotExisting.properties");
140         final File file = new File(fileName);
141         final FileText fileText = new FileText(file, Collections.emptyList());
142         final SortedSet<Violation> violations =
143                 check.process(file, fileText);
144         assertWithMessage("Wrong messages count: " + violations.size())
145             .that(violations)
146             .hasSize(1);
147         final Violation violation = violations.iterator().next();
148         final String retrievedMessage = violations.iterator().next().getKey();
149         assertWithMessage("violation key '" + retrievedMessage + "' is not valid")
150             .that(retrievedMessage)
151             .isEqualTo("unable.open.cause");
152         assertWithMessage("violation '" + violation.getViolation() + "' is not valid")
153             .that(getCheckMessage(MSG_IO_EXCEPTION_KEY, fileName, getFileNotFoundDetail(file)))
154             .isEqualTo(violation.getViolation());
155     }
156 
157     @Test
158     public void testWrongKeyTypeInProperties() throws Exception {
159         final Class<?> uniquePropertiesClass = Class
160                 .forName("com.puppycrawl.tools.checkstyle.checks."
161                     + "UniquePropertiesCheck$UniqueProperties");
162         final Constructor<?> constructor = uniquePropertiesClass.getDeclaredConstructor();
163         constructor.setAccessible(true);
164         final Object uniqueProperties = constructor.newInstance();
165         final Method method = uniqueProperties.getClass().getDeclaredMethod("put", Object.class,
166                 Object.class);
167         final Object result = method.invoke(uniqueProperties, 1, "value");
168         final Map<Object, Object> table = new HashMap<>();
169         final Object expected = table.put(1, "value");
170         assertWithMessage("Invalid result of put method")
171             .that(result)
172             .isEqualTo(expected);
173 
174         final Object result2 = method.invoke(uniqueProperties, 1, "value");
175         final Object expected2 = table.put(1, "value");
176         assertWithMessage("Value should be substituted")
177             .that(result2)
178             .isEqualTo(expected2);
179     }
180 
181     /**
182      * Method generates NoSuchFileException details. It tries to open a file that does not exist.
183      *
184      * @param file to be opened
185      * @return localized detail message of {@link NoSuchFileException}
186      */
187     private static String getFileNotFoundDetail(File file) {
188         // Create exception to know detail message we should wait in
189         // LocalisedMessage
190         try (InputStream stream = Files.newInputStream(file.toPath())) {
191             throw new IllegalStateException("File " + file.getPath() + " should not exist");
192         }
193         catch (IOException ex) {
194             return ex.getLocalizedMessage();
195         }
196     }
197 
198 }