View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2026 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.api;
21  
22  import static com.google.common.truth.Truth.assertWithMessage;
23  import static com.puppycrawl.tools.checkstyle.utils.CommonUtil.EMPTY_OBJECT_ARRAY;
24  
25  import org.junit.jupiter.api.Test;
26  import org.junitpioneer.jupiter.DefaultLocale;
27  
28  import com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationLocationCheck;
29  import com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationOnSameLineCheck;
30  import nl.jqno.equalsverifier.EqualsVerifier;
31  import nl.jqno.equalsverifier.EqualsVerifierReport;
32  
33  public class ViolationTest {
34  
35      @Test
36      public void testEqualsAndHashCode() {
37          final EqualsVerifierReport ev = EqualsVerifier.forClass(Violation.class)
38                  .usingGetClass().report();
39          assertWithMessage("Error: %s", ev.getMessage())
40                  .that(ev.isSuccessful())
41                  .isTrue();
42      }
43  
44      @Test
45      public void testGetSeverityLevel() {
46          final Violation violation = createSampleViolation();
47  
48          assertWithMessage("Invalid severity level")
49              .that(violation.getSeverityLevel())
50              .isEqualTo(SeverityLevel.ERROR);
51      }
52  
53      @Test
54      public void testGetModuleId() {
55          final Violation violation = createSampleViolation();
56  
57          assertWithMessage("Invalid module id")
58              .that(violation.getModuleId())
59              .isEqualTo("module");
60      }
61  
62      @Test
63      public void testGetSourceName() {
64          final Violation violation = createSampleViolation();
65  
66          assertWithMessage("Invalid source name")
67              .that(violation.getSourceName())
68              .isEqualTo("com.puppycrawl.tools.checkstyle.api.Violation");
69      }
70  
71      @DefaultLocale("en")
72      @Test
73      public void testMessageInEnglish() {
74          final Violation violation = createSampleViolation();
75  
76          assertWithMessage("Invalid violation")
77              .that(violation.getViolation())
78              .isEqualTo("Empty statement.");
79      }
80  
81      @DefaultLocale("fr")
82      @Test
83      public void testGetKey() {
84          final Violation violation = createSampleViolation();
85  
86          assertWithMessage("Invalid violation key")
87              .that(violation.getKey())
88              .isEqualTo("empty.statement");
89      }
90  
91      @Test
92      public void testTokenType() {
93          final Violation violation1 = new Violation(1, 1, TokenTypes.CLASS_DEF,
94                  "messages.properties", "key", null, SeverityLevel.ERROR, null,
95                  getClass(), null);
96          final Violation violation2 = new Violation(1, 1, TokenTypes.OBJBLOCK,
97                  "messages.properties", "key", EMPTY_OBJECT_ARRAY, SeverityLevel.ERROR, null,
98                  getClass(), null);
99  
100         assertWithMessage("Invalid token type")
101             .that(violation1.getTokenType())
102             .isEqualTo(TokenTypes.CLASS_DEF);
103         assertWithMessage("Invalid token type")
104             .that(violation2.getTokenType())
105             .isEqualTo(TokenTypes.OBJBLOCK);
106     }
107 
108     @Test
109     public void testGetColumnCharIndex() {
110         final Violation violation1 = new Violation(1, 1, 123,
111                 TokenTypes.CLASS_DEF, "messages.properties", "key", null, SeverityLevel.ERROR,
112                 null, getClass(), null);
113 
114         assertWithMessage("Invalid column char index")
115             .that(violation1.getColumnCharIndex())
116             .isEqualTo(123);
117     }
118 
119     @Test
120     public void testCompareToWithDifferentModuleId() {
121         final Violation message1 = createSampleViolationWithId("module1");
122         final Violation message2 = createSampleViolationWithId("module2");
123         final Violation messageNull = createSampleViolationWithId(null);
124 
125         assertWithMessage("Invalid comparing result")
126                 .that(message1.compareTo(messageNull) > 0)
127                 .isTrue();
128         assertWithMessage("Invalid comparing result")
129                 .that(messageNull.compareTo(message1) < 0)
130                 .isTrue();
131         assertWithMessage("Invalid comparing result")
132                 .that(message1.compareTo(message2) < 0)
133                 .isTrue();
134     }
135 
136     @Test
137     public void testCompareToWithDifferentClass() {
138         final Violation message1 = createSampleViolationWithClass(AnnotationLocationCheck.class);
139         final Violation message2 = createSampleViolationWithClass(AnnotationOnSameLineCheck.class);
140         final Violation messageNull = createSampleViolationWithClass(null);
141 
142         assertWithMessage("Invalid comparing result")
143                 .that(message1.compareTo(messageNull) > 0)
144                 .isTrue();
145         assertWithMessage("Invalid comparing result")
146                 .that(messageNull.compareTo(message1) < 0)
147                 .isTrue();
148         assertWithMessage("Invalid comparing result")
149                 .that(message1.compareTo(message2) < 0)
150                 .isTrue();
151     }
152 
153     @Test
154     public void testCompareToWithDifferentLines() {
155         final Violation message1 = createSampleViolationWithLine(1);
156         final Violation message1a = createSampleViolationWithLine(1);
157         final Violation message2 = createSampleViolationWithLine(2);
158 
159         assertWithMessage("Invalid comparing result")
160                 .that(message1.compareTo(message2) < 0)
161                 .isTrue();
162         assertWithMessage("Invalid comparing result")
163                 .that(message2.compareTo(message1) > 0)
164                 .isTrue();
165         final int actual = message1.compareTo(message1a);
166         assertWithMessage("Invalid comparing result")
167             .that(actual)
168             .isEqualTo(0);
169     }
170 
171     @Test
172     public void testCompareToWithDifferentColumns() {
173         final Violation message1 = createSampleViolationWithColumn(1);
174         final Violation message1a = createSampleViolationWithColumn(1);
175         final Violation message2 = createSampleViolationWithColumn(2);
176 
177         assertWithMessage("Invalid comparing result")
178                 .that(message1.compareTo(message2) < 0)
179                 .isTrue();
180         assertWithMessage("Invalid comparing result")
181                 .that(message2.compareTo(message1) > 0)
182                 .isTrue();
183         final int actual = message1.compareTo(message1a);
184         assertWithMessage("Invalid comparing result")
185             .that(actual)
186             .isEqualTo(0);
187     }
188 
189     @Test
190     public void testCompareToWithDifferentTokenType() {
191         final Violation violation1 = new Violation(1, 1, TokenTypes.CLASS_DEF,
192                 "com.puppycrawl.tools.checkstyle.checks.coding.messages", "empty.statement",
193                 EMPTY_OBJECT_ARRAY, SeverityLevel.ERROR, "module", Violation.class, null);
194         final Violation violation2 = new Violation(1, 1, TokenTypes.OBJBLOCK,
195                 "com.puppycrawl.tools.checkstyle.checks.coding.messages", "empty.statement",
196                 EMPTY_OBJECT_ARRAY, SeverityLevel.ERROR, "module", Violation.class, null);
197 
198         assertWithMessage("Invalid comparing result")
199                 .that(violation1.compareTo(violation2))
200                 .isNotEqualTo(0);
201         assertWithMessage("Invalid comparing result")
202                 .that(Integer.signum(violation1.compareTo(violation2)))
203                 .isEqualTo(-Integer.signum(violation2.compareTo(violation1)));
204     }
205 
206     @Test
207     public void testCompareToWithDifferentColumnCharIndex() {
208         final Violation violation1 = new Violation(1, 1, 1, TokenTypes.CLASS_DEF,
209                 "com.puppycrawl.tools.checkstyle.checks.coding.messages", "empty.statement",
210                 EMPTY_OBJECT_ARRAY, SeverityLevel.ERROR, "module", Violation.class, null);
211         final Violation violation2 = new Violation(1, 1, 2, TokenTypes.CLASS_DEF,
212                 "com.puppycrawl.tools.checkstyle.checks.coding.messages", "empty.statement",
213                 EMPTY_OBJECT_ARRAY, SeverityLevel.ERROR, "module", Violation.class, null);
214 
215         assertWithMessage("Invalid comparing result")
216                 .that(violation1.compareTo(violation2) < 0)
217                 .isTrue();
218         assertWithMessage("Invalid comparing result")
219                 .that(violation2.compareTo(violation1) > 0)
220                 .isTrue();
221     }
222 
223     @Test
224     public void testCompareToWithDifferentSeverityLevel() {
225         final Violation violation1 = new Violation(1, 1, TokenTypes.CLASS_DEF,
226                 "com.puppycrawl.tools.checkstyle.checks.coding.messages", "empty.statement",
227                 EMPTY_OBJECT_ARRAY, SeverityLevel.INFO, "module", Violation.class, null);
228         final Violation violation2 = new Violation(1, 1, TokenTypes.CLASS_DEF,
229                 "com.puppycrawl.tools.checkstyle.checks.coding.messages", "empty.statement",
230                 EMPTY_OBJECT_ARRAY, SeverityLevel.WARNING, "module", Violation.class, null);
231 
232         assertWithMessage("Invalid comparing result")
233                 .that(violation1.compareTo(violation2) < 0)
234                 .isTrue();
235         assertWithMessage("Invalid comparing result")
236                 .that(violation2.compareTo(violation1) > 0)
237                 .isTrue();
238     }
239 
240     @Test
241     public void testCompareToWithDifferentKeySameCustomMessage() {
242         final Violation violation1 = new Violation(1, 1,
243                 "com.puppycrawl.tools.checkstyle.checks.coding.messages", "empty.statement",
244                 EMPTY_OBJECT_ARRAY, "module", Violation.class, "custom text");
245         final Violation violation2 = new Violation(1, 1,
246                 "com.puppycrawl.tools.checkstyle.checks.coding.messages", "other.key",
247                 EMPTY_OBJECT_ARRAY, "module", Violation.class, "custom text");
248 
249         assertWithMessage("Invalid comparing result")
250                 .that(violation1.compareTo(violation2) < 0)
251                 .isTrue();
252         assertWithMessage("Invalid comparing result")
253                 .that(violation2.compareTo(violation1) > 0)
254                 .isTrue();
255     }
256 
257     @Test
258     public void testCompareToWithDifferentBundleSameCustomMessage() {
259         final Violation violation1 = new Violation(1, 1,
260                 "com.puppycrawl.tools.checkstyle.checks.coding.messages", "empty.statement",
261                 EMPTY_OBJECT_ARRAY, "module", Violation.class, "custom text");
262         final Violation violation2 = new Violation(1, 1,
263                 "com.puppycrawl.tools.checkstyle.checks.naming.messages", "empty.statement",
264                 EMPTY_OBJECT_ARRAY, "module", Violation.class, "custom text");
265 
266         assertWithMessage("Invalid comparing result")
267                 .that(violation1.compareTo(violation2) < 0)
268                 .isTrue();
269         assertWithMessage("Invalid comparing result")
270                 .that(violation2.compareTo(violation1) > 0)
271                 .isTrue();
272     }
273 
274     @DefaultLocale("en")
275     @Test
276     public void testCompareToWithCustomMessageMatchingBundleMessage() {
277         final Violation violation1 = new Violation(1, 1,
278                 "com.puppycrawl.tools.checkstyle.checks.coding.messages", "empty.statement",
279                 EMPTY_OBJECT_ARRAY, "module", Violation.class, null);
280         final Violation violation2 = new Violation(1, 1,
281                 "com.puppycrawl.tools.checkstyle.checks.coding.messages", "empty.statement",
282                 EMPTY_OBJECT_ARRAY, "module", Violation.class, "Empty statement.");
283 
284         assertWithMessage("Rendered messages must match for this test to be valid")
285                 .that(violation1.getViolation())
286                 .isEqualTo(violation2.getViolation());
287         assertWithMessage("Invalid comparing result")
288                 .that(violation1.compareTo(violation2))
289                 .isNotEqualTo(0);
290         assertWithMessage("Invalid comparing result")
291                 .that(Integer.signum(violation1.compareTo(violation2)))
292                 .isEqualTo(-Integer.signum(violation2.compareTo(violation1)));
293     }
294 
295     @Test
296     public void testCompareToWithDifferentArgsSameRenderedMessage() {
297         final Violation violation1 = new Violation(1, 1,
298                 "com.puppycrawl.tools.checkstyle.checks.coding.messages", "empty.statement",
299                 new String[] {"first"}, "module", Violation.class, "custom text");
300         final Violation violation2 = new Violation(1, 1,
301                 "com.puppycrawl.tools.checkstyle.checks.coding.messages", "empty.statement",
302                 new String[] {"second"}, "module", Violation.class, "custom text");
303 
304         assertWithMessage("Rendered messages must match for this test to be valid")
305                 .that(violation1.getViolation())
306                 .isEqualTo(violation2.getViolation());
307         assertWithMessage("Invalid comparing result")
308                 .that(violation1.compareTo(violation2) < 0)
309                 .isTrue();
310         assertWithMessage("Invalid comparing result")
311                 .that(violation2.compareTo(violation1) > 0)
312                 .isTrue();
313     }
314 
315     @Test
316     public void testCompareToOrdersByTextBeforeTokenType() {
317         // OBJBLOCK sorts before CLASS_DEF, so the token type alone would order these
318         // the other way round
319         final Violation violation1 = new Violation(1, 1, TokenTypes.OBJBLOCK,
320                 "com.puppycrawl.tools.checkstyle.checks.coding.messages", "empty.statement",
321                 EMPTY_OBJECT_ARRAY, SeverityLevel.ERROR, "module", Violation.class, "zebra");
322         final Violation violation2 = new Violation(1, 1, TokenTypes.CLASS_DEF,
323                 "com.puppycrawl.tools.checkstyle.checks.coding.messages", "empty.statement",
324                 EMPTY_OBJECT_ARRAY, SeverityLevel.ERROR, "module", Violation.class, "apple");
325 
326         assertWithMessage("Invalid comparing result")
327                 .that(violation1.compareTo(violation2) > 0)
328                 .isTrue();
329         assertWithMessage("Invalid comparing result")
330                 .that(violation2.compareTo(violation1) < 0)
331                 .isTrue();
332     }
333 
334     @Test
335     public void testCompareToConsistentWithEquals() {
336         final Violation violation1 = new Violation(1, 1, 1, TokenTypes.CLASS_DEF,
337                 "com.puppycrawl.tools.checkstyle.checks.coding.messages", "empty.statement",
338                 EMPTY_OBJECT_ARRAY, SeverityLevel.ERROR, "module", Violation.class, "custom");
339         final Violation violation2 = new Violation(1, 1, 1, TokenTypes.CLASS_DEF,
340                 "com.puppycrawl.tools.checkstyle.checks.coding.messages", "empty.statement",
341                 EMPTY_OBJECT_ARRAY, SeverityLevel.ERROR, "module", Violation.class, "custom");
342 
343         assertWithMessage("Equal violations must compare to zero")
344                 .that(violation1.compareTo(violation2))
345                 .isEqualTo(0);
346         assertWithMessage("Violations comparing to zero must be equal")
347                 .that(violation1)
348                 .isEqualTo(violation2);
349     }
350 
351     private static Violation createSampleViolation() {
352         return createSampleViolationWithId("module");
353     }
354 
355     private static Violation createSampleViolationWithClass(Class<?> clss) {
356         return new Violation(1, "com.puppycrawl.tools.checkstyle.checks.coding.messages",
357                 "empty.statement", EMPTY_OBJECT_ARRAY, null, clss, null);
358     }
359 
360     private static Violation createSampleViolationWithId(String id) {
361         return new Violation(1, "com.puppycrawl.tools.checkstyle.checks.coding.messages",
362                 "empty.statement", EMPTY_OBJECT_ARRAY, id, Violation.class, null);
363     }
364 
365     private static Violation createSampleViolationWithLine(int line) {
366         return new Violation(line, "com.puppycrawl.tools.checkstyle.checks.coding.messages",
367                 "empty.statement", EMPTY_OBJECT_ARRAY, "module", Violation.class, null);
368     }
369 
370     private static Violation createSampleViolationWithColumn(int column) {
371         return new Violation(1, column,
372                 "com.puppycrawl.tools.checkstyle.checks.coding.messages", "empty.statement",
373                 EMPTY_OBJECT_ARRAY, "module", Violation.class, null);
374     }
375 
376 }