View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.model.validation;
20  
21  import java.io.InputStream;
22  import java.util.List;
23  
24  import org.apache.maven.model.Model;
25  import org.apache.maven.model.building.DefaultModelBuildingRequest;
26  import org.apache.maven.model.building.ModelBuildingRequest;
27  import org.apache.maven.model.building.SimpleProblemCollector;
28  import org.apache.maven.model.interpolation.DefaultModelVersionProcessor;
29  import org.apache.maven.model.v4.MavenXpp3Reader;
30  import org.junit.jupiter.api.AfterEach;
31  import org.junit.jupiter.api.BeforeEach;
32  import org.junit.jupiter.api.Test;
33  
34  import static org.junit.jupiter.api.Assertions.assertEquals;
35  import static org.junit.jupiter.api.Assertions.assertNotNull;
36  import static org.junit.jupiter.api.Assertions.assertTrue;
37  
38  /**
39   * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
40   */
41  class DefaultModelValidatorTest {
42  
43      private ModelValidator validator;
44  
45      private Model read(String pom) throws Exception {
46          String resource = "/poms/validation/" + pom;
47          InputStream is = getClass().getResourceAsStream(resource);
48          assertNotNull(is, "missing resource: " + resource);
49          return new Model(new MavenXpp3Reader().read(is));
50      }
51  
52      private SimpleProblemCollector validate(String pom) throws Exception {
53          return validateEffective(pom, ModelBuildingRequest.VALIDATION_LEVEL_STRICT);
54      }
55  
56      private SimpleProblemCollector validateRaw(String pom) throws Exception {
57          return validateRaw(pom, ModelBuildingRequest.VALIDATION_LEVEL_STRICT);
58      }
59  
60      private SimpleProblemCollector validateEffective(String pom, int level) throws Exception {
61          ModelBuildingRequest request = new DefaultModelBuildingRequest().setValidationLevel(level);
62  
63          Model model = read(pom);
64  
65          SimpleProblemCollector problems = new SimpleProblemCollector(model);
66  
67          validator.validateEffectiveModel(model, request, problems);
68  
69          return problems;
70      }
71  
72      private SimpleProblemCollector validateRaw(String pom, int level) throws Exception {
73          ModelBuildingRequest request = new DefaultModelBuildingRequest().setValidationLevel(level);
74  
75          Model model = read(pom);
76  
77          SimpleProblemCollector problems = new SimpleProblemCollector(model);
78  
79          validator.validateFileModel(model, request, problems);
80  
81          validator.validateRawModel(model, request, problems);
82  
83          return problems;
84      }
85  
86      private void assertContains(String msg, String substring) {
87          assertTrue(msg.contains(substring), "\"" + substring + "\" was not found in: " + msg);
88      }
89  
90      @BeforeEach
91      void setUp() throws Exception {
92          validator = new DefaultModelValidator(new DefaultModelVersionProcessor());
93      }
94  
95      @AfterEach
96      void tearDown() throws Exception {
97          this.validator = null;
98      }
99  
100     private void assertViolations(SimpleProblemCollector result, int fatals, int errors, int warnings) {
101         assertEquals(fatals, result.getFatals().size(), String.valueOf(result.getFatals()));
102         assertEquals(errors, result.getErrors().size(), String.valueOf(result.getErrors()));
103         assertEquals(warnings, result.getWarnings().size(), String.valueOf(result.getWarnings()));
104     }
105 
106     @Test
107     void testMissingModelVersion() throws Exception {
108         SimpleProblemCollector result = validate("missing-modelVersion-pom.xml");
109 
110         assertViolations(result, 0, 1, 0);
111 
112         assertEquals("'modelVersion' is missing.", result.getErrors().get(0));
113     }
114 
115     @Test
116     void testBadModelVersion() throws Exception {
117         SimpleProblemCollector result =
118                 validateRaw("bad-modelVersion.xml", ModelBuildingRequest.VALIDATION_LEVEL_STRICT);
119 
120         assertViolations(result, 1, 0, 0);
121 
122         assertTrue(result.getFatals().get(0).contains("modelVersion"));
123     }
124 
125     @Test
126     void testMissingArtifactId() throws Exception {
127         SimpleProblemCollector result = validate("missing-artifactId-pom.xml");
128 
129         assertViolations(result, 0, 1, 0);
130 
131         assertEquals("'artifactId' is missing.", result.getErrors().get(0));
132     }
133 
134     @Test
135     void testMissingGroupId() throws Exception {
136         SimpleProblemCollector result = validate("missing-groupId-pom.xml");
137 
138         assertViolations(result, 0, 1, 0);
139 
140         assertEquals("'groupId' is missing.", result.getErrors().get(0));
141     }
142 
143     @Test
144     void testInvalidCoordinateIds() throws Exception {
145         SimpleProblemCollector result = validate("invalid-coordinate-ids-pom.xml");
146 
147         assertViolations(result, 0, 2, 0);
148 
149         assertEquals(
150                 "'groupId' with value 'o/a/m' does not match a valid coordinate id pattern.",
151                 result.getErrors().get(0));
152 
153         assertEquals(
154                 "'artifactId' with value 'm$-do$' does not match a valid coordinate id pattern.",
155                 result.getErrors().get(1));
156     }
157 
158     @Test
159     void testMissingType() throws Exception {
160         SimpleProblemCollector result = validate("missing-type-pom.xml");
161 
162         assertViolations(result, 0, 1, 0);
163 
164         assertEquals("'packaging' is missing.", result.getErrors().get(0));
165     }
166 
167     @Test
168     void testMissingVersion() throws Exception {
169         SimpleProblemCollector result = validate("missing-version-pom.xml");
170 
171         assertViolations(result, 0, 1, 0);
172 
173         assertEquals("'version' is missing.", result.getErrors().get(0));
174     }
175 
176     @Test
177     void testInvalidAggregatorPackaging() throws Exception {
178         SimpleProblemCollector result = validate("invalid-aggregator-packaging-pom.xml");
179 
180         assertViolations(result, 0, 1, 0);
181 
182         assertTrue(result.getErrors().get(0).contains("Aggregator projects require 'pom' as packaging."));
183     }
184 
185     @Test
186     void testMissingDependencyArtifactId() throws Exception {
187         SimpleProblemCollector result = validate("missing-dependency-artifactId-pom.xml");
188 
189         assertViolations(result, 0, 1, 0);
190 
191         assertTrue(result.getErrors()
192                 .get(0)
193                 .contains("'dependencies.dependency.artifactId' for groupId:null:jar is missing"));
194     }
195 
196     @Test
197     void testMissingDependencyGroupId() throws Exception {
198         SimpleProblemCollector result = validate("missing-dependency-groupId-pom.xml");
199 
200         assertViolations(result, 0, 1, 0);
201 
202         assertTrue(result.getErrors()
203                 .get(0)
204                 .contains("'dependencies.dependency.groupId' for null:artifactId:jar is missing"));
205     }
206 
207     @Test
208     void testMissingDependencyVersion() throws Exception {
209         SimpleProblemCollector result = validate("missing-dependency-version-pom.xml");
210 
211         assertViolations(result, 0, 1, 0);
212 
213         assertTrue(result.getErrors()
214                 .get(0)
215                 .contains("'dependencies.dependency.version' for groupId:artifactId:jar is missing"));
216     }
217 
218     @Test
219     void testMissingDependencyManagementArtifactId() throws Exception {
220         SimpleProblemCollector result = validate("missing-dependency-mgmt-artifactId-pom.xml");
221 
222         assertViolations(result, 0, 1, 0);
223 
224         assertTrue(result.getErrors()
225                 .get(0)
226                 .contains("'dependencyManagement.dependencies.dependency.artifactId' for groupId:null:jar is missing"));
227     }
228 
229     @Test
230     void testMissingDependencyManagementGroupId() throws Exception {
231         SimpleProblemCollector result = validate("missing-dependency-mgmt-groupId-pom.xml");
232 
233         assertViolations(result, 0, 1, 0);
234 
235         assertTrue(result.getErrors()
236                 .get(0)
237                 .contains("'dependencyManagement.dependencies.dependency.groupId' for null:artifactId:jar is missing"));
238     }
239 
240     @Test
241     void testMissingAll() throws Exception {
242         SimpleProblemCollector result = validate("missing-1-pom.xml");
243 
244         assertViolations(result, 0, 4, 0);
245 
246         List<String> messages = result.getErrors();
247 
248         assertTrue(messages.contains("'modelVersion' is missing."));
249         assertTrue(messages.contains("'groupId' is missing."));
250         assertTrue(messages.contains("'artifactId' is missing."));
251         assertTrue(messages.contains("'version' is missing."));
252         // type is inherited from the super pom
253     }
254 
255     @Test
256     void testMissingPluginArtifactId() throws Exception {
257         SimpleProblemCollector result = validate("missing-plugin-artifactId-pom.xml");
258 
259         assertViolations(result, 0, 1, 0);
260 
261         assertEquals(
262                 "'build.plugins.plugin.artifactId' is missing.",
263                 result.getErrors().get(0));
264     }
265 
266     @Test
267     void testEmptyPluginVersion() throws Exception {
268         SimpleProblemCollector result = validate("empty-plugin-version.xml");
269 
270         assertViolations(result, 0, 1, 0);
271 
272         assertEquals(
273                 "'build.plugins.plugin.version' for org.apache.maven.plugins:maven-it-plugin"
274                         + " must be a valid version but is ''.",
275                 result.getErrors().get(0));
276     }
277 
278     @Test
279     void testMissingRepositoryId() throws Exception {
280         SimpleProblemCollector result =
281                 validateRaw("missing-repository-id-pom.xml", ModelBuildingRequest.VALIDATION_LEVEL_STRICT);
282 
283         assertViolations(result, 0, 4, 0);
284 
285         assertEquals(
286                 "'repositories.repository.id' is missing.", result.getErrors().get(0));
287 
288         assertEquals(
289                 "'repositories.repository.[null].url' is missing.",
290                 result.getErrors().get(1));
291 
292         assertEquals(
293                 "'pluginRepositories.pluginRepository.id' is missing.",
294                 result.getErrors().get(2));
295 
296         assertEquals(
297                 "'pluginRepositories.pluginRepository.[null].url' is missing.",
298                 result.getErrors().get(3));
299     }
300 
301     @Test
302     void testMissingResourceDirectory() throws Exception {
303         SimpleProblemCollector result = validate("missing-resource-directory-pom.xml");
304 
305         assertViolations(result, 0, 2, 0);
306 
307         assertEquals(
308                 "'build.resources.resource.directory' is missing.",
309                 result.getErrors().get(0));
310 
311         assertEquals(
312                 "'build.testResources.testResource.directory' is missing.",
313                 result.getErrors().get(1));
314     }
315 
316     @Test
317     void testBadPluginDependencyScope() throws Exception {
318         SimpleProblemCollector result = validate("bad-plugin-dependency-scope.xml");
319 
320         assertViolations(result, 0, 3, 0);
321 
322         assertTrue(result.getErrors().get(0).contains("test:d"));
323 
324         assertTrue(result.getErrors().get(1).contains("test:e"));
325 
326         assertTrue(result.getErrors().get(2).contains("test:f"));
327     }
328 
329     @Test
330     void testBadDependencyScope() throws Exception {
331         SimpleProblemCollector result = validate("bad-dependency-scope.xml");
332 
333         assertViolations(result, 0, 0, 2);
334 
335         assertTrue(result.getWarnings().get(0).contains("test:f"));
336 
337         assertTrue(result.getWarnings().get(1).contains("test:g"));
338     }
339 
340     @Test
341     void testBadDependencyManagementScope() throws Exception {
342         SimpleProblemCollector result = validate("bad-dependency-management-scope.xml");
343 
344         assertViolations(result, 0, 0, 1);
345 
346         assertContains(result.getWarnings().get(0), "test:g");
347     }
348 
349     @Test
350     void testBadDependencyVersion() throws Exception {
351         SimpleProblemCollector result = validate("bad-dependency-version.xml");
352 
353         assertViolations(result, 0, 2, 0);
354 
355         assertContains(
356                 result.getErrors().get(0), "'dependencies.dependency.version' for test:b:jar must be a valid version");
357         assertContains(
358                 result.getErrors().get(1),
359                 "'dependencies.dependency.version' for test:c:jar must not contain any of these characters");
360     }
361 
362     @Test
363     void testDuplicateModule() throws Exception {
364         SimpleProblemCollector result = validateRaw("duplicate-module.xml");
365 
366         assertViolations(result, 0, 1, 0);
367 
368         assertTrue(result.getErrors().get(0).contains("child"));
369     }
370 
371     @Test
372     void testInvalidProfileId() throws Exception {
373         SimpleProblemCollector result = validateRaw("invalid-profile-ids.xml");
374 
375         assertViolations(result, 0, 4, 0);
376 
377         assertTrue(result.getErrors().get(0).contains("+invalid-id"));
378         assertTrue(result.getErrors().get(1).contains("-invalid-id"));
379         assertTrue(result.getErrors().get(2).contains("!invalid-id"));
380         assertTrue(result.getErrors().get(3).contains("?invalid-id"));
381     }
382 
383     public void testDuplicateProfileId() throws Exception {
384         SimpleProblemCollector result = validateRaw("duplicate-profile-id.xml");
385 
386         assertViolations(result, 0, 1, 0);
387 
388         assertTrue(result.getErrors().get(0).contains("non-unique-id"));
389     }
390 
391     @Test
392     void testBadPluginVersion() throws Exception {
393         SimpleProblemCollector result = validate("bad-plugin-version.xml");
394 
395         assertViolations(result, 0, 4, 0);
396 
397         assertContains(
398                 result.getErrors().get(0), "'build.plugins.plugin.version' for test:mip must be a valid version");
399         assertContains(
400                 result.getErrors().get(1), "'build.plugins.plugin.version' for test:rmv must be a valid version");
401         assertContains(
402                 result.getErrors().get(2), "'build.plugins.plugin.version' for test:lmv must be a valid version");
403         assertContains(
404                 result.getErrors().get(3),
405                 "'build.plugins.plugin.version' for test:ifsc must not contain any of these characters");
406     }
407 
408     @Test
409     void testDistributionManagementStatus() throws Exception {
410         SimpleProblemCollector result = validate("distribution-management-status.xml");
411 
412         assertViolations(result, 0, 1, 0);
413 
414         assertTrue(result.getErrors().get(0).contains("distributionManagement.status"));
415     }
416 
417     @Test
418     void testIncompleteParent() throws Exception {
419         SimpleProblemCollector result = validateRaw("incomplete-parent.xml");
420 
421         assertViolations(result, 3, 0, 0);
422         assertTrue(result.getFatals().get(0).contains("parent.groupId"));
423         assertTrue(result.getFatals().get(1).contains("parent.artifactId"));
424         assertTrue(result.getFatals().get(2).contains("parent.version"));
425     }
426 
427     @Test
428     void testHardCodedSystemPath() throws Exception {
429         SimpleProblemCollector result = validateRaw("hard-coded-system-path.xml");
430 
431         assertViolations(result, 0, 0, 3);
432 
433         assertContains(
434                 result.getWarnings().get(0),
435                 "'dependencies.dependency.scope' for test:a:jar declares usage of deprecated 'system' scope");
436         assertContains(
437                 result.getWarnings().get(1),
438                 "'dependencies.dependency.systemPath' for test:a:jar should use a variable instead of a hard-coded path");
439         assertContains(
440                 result.getWarnings().get(2),
441                 "'dependencies.dependency.scope' for test:b:jar declares usage of deprecated 'system' scope");
442     }
443 
444     @Test
445     void testEmptyModule() throws Exception {
446         SimpleProblemCollector result = validate("empty-module.xml");
447 
448         assertViolations(result, 0, 1, 0);
449 
450         assertTrue(result.getErrors().get(0).contains("'modules.module[0]' has been specified without a path"));
451     }
452 
453     @Test
454     void testDuplicatePlugin() throws Exception {
455         SimpleProblemCollector result = validateRaw("duplicate-plugin.xml");
456 
457         assertViolations(result, 0, 4, 0);
458 
459         assertTrue(result.getErrors().get(0).contains("duplicate declaration of plugin test:duplicate"));
460         assertTrue(result.getErrors().get(1).contains("duplicate declaration of plugin test:managed-duplicate"));
461         assertTrue(result.getErrors().get(2).contains("duplicate declaration of plugin profile:duplicate"));
462         assertTrue(result.getErrors().get(3).contains("duplicate declaration of plugin profile:managed-duplicate"));
463     }
464 
465     @Test
466     void testDuplicatePluginExecution() throws Exception {
467         SimpleProblemCollector result = validateRaw("duplicate-plugin-execution.xml");
468 
469         assertViolations(result, 0, 4, 0);
470 
471         assertContains(result.getErrors().get(0), "duplicate execution with id a");
472         assertContains(result.getErrors().get(1), "duplicate execution with id default");
473         assertContains(result.getErrors().get(2), "duplicate execution with id c");
474         assertContains(result.getErrors().get(3), "duplicate execution with id b");
475     }
476 
477     @Test
478     void testReservedRepositoryId() throws Exception {
479         SimpleProblemCollector result = validate("reserved-repository-id.xml");
480 
481         assertViolations(result, 0, 4, 0);
482 
483         assertContains(result.getErrors().get(0), "'repositories.repository.id'" + " must not be 'local'");
484         assertContains(result.getErrors().get(1), "'pluginRepositories.pluginRepository.id' must not be 'local'");
485         assertContains(result.getErrors().get(2), "'distributionManagement.repository.id' must not be 'local'");
486         assertContains(result.getErrors().get(3), "'distributionManagement.snapshotRepository.id' must not be 'local'");
487     }
488 
489     @Test
490     void testMissingPluginDependencyGroupId() throws Exception {
491         SimpleProblemCollector result = validate("missing-plugin-dependency-groupId.xml");
492 
493         assertViolations(result, 0, 1, 0);
494 
495         assertTrue(result.getErrors().get(0).contains(":a:"));
496     }
497 
498     @Test
499     void testMissingPluginDependencyArtifactId() throws Exception {
500         SimpleProblemCollector result = validate("missing-plugin-dependency-artifactId.xml");
501 
502         assertViolations(result, 0, 1, 0);
503 
504         assertTrue(result.getErrors().get(0).contains("test:"));
505     }
506 
507     @Test
508     void testMissingPluginDependencyVersion() throws Exception {
509         SimpleProblemCollector result = validate("missing-plugin-dependency-version.xml");
510 
511         assertViolations(result, 0, 1, 0);
512 
513         assertTrue(result.getErrors().get(0).contains("test:a"));
514     }
515 
516     @Test
517     void testBadPluginDependencyVersion() throws Exception {
518         SimpleProblemCollector result = validate("bad-plugin-dependency-version.xml");
519 
520         assertViolations(result, 0, 1, 0);
521 
522         assertTrue(result.getErrors().get(0).contains("test:b"));
523     }
524 
525     @Test
526     void testBadVersion() throws Exception {
527         SimpleProblemCollector result = validate("bad-version.xml");
528 
529         assertViolations(result, 0, 1, 0);
530 
531         assertContains(result.getErrors().get(0), "'version' must not contain any of these characters");
532     }
533 
534     @Test
535     void testBadSnapshotVersion() throws Exception {
536         SimpleProblemCollector result = validate("bad-snapshot-version.xml");
537 
538         assertViolations(result, 0, 1, 0);
539 
540         assertContains(result.getErrors().get(0), "'version' uses an unsupported snapshot version format");
541     }
542 
543     @Test
544     void testBadRepositoryId() throws Exception {
545         SimpleProblemCollector result = validate("bad-repository-id.xml");
546 
547         assertViolations(result, 0, 4, 0);
548 
549         assertContains(
550                 result.getErrors().get(0), "'repositories.repository.id' must not contain any of these characters");
551         assertContains(
552                 result.getErrors().get(1),
553                 "'pluginRepositories.pluginRepository.id' must not contain any of these characters");
554         assertContains(
555                 result.getErrors().get(2),
556                 "'distributionManagement.repository.id' must not contain any of these characters");
557         assertContains(
558                 result.getErrors().get(3),
559                 "'distributionManagement.snapshotRepository.id' must not contain any of these characters");
560     }
561 
562     @Test
563     void testBadDependencyExclusionId() throws Exception {
564         SimpleProblemCollector result =
565                 validateEffective("bad-dependency-exclusion-id.xml", ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0);
566 
567         assertViolations(result, 0, 0, 2);
568 
569         assertContains(
570                 result.getWarnings().get(0), "'dependencies.dependency.exclusions.exclusion.groupId' for gid:aid:jar");
571         assertContains(
572                 result.getWarnings().get(1),
573                 "'dependencies.dependency.exclusions.exclusion.artifactId' for gid:aid:jar");
574 
575         // MNG-3832: Aether (part of M3+) supports wildcard expressions for exclusions
576 
577         SimpleProblemCollector result_30 = validate("bad-dependency-exclusion-id.xml");
578 
579         assertViolations(result_30, 0, 0, 0);
580     }
581 
582     @Test
583     void testMissingDependencyExclusionId() throws Exception {
584         SimpleProblemCollector result = validate("missing-dependency-exclusion-id.xml");
585 
586         assertViolations(result, 0, 0, 2);
587 
588         assertContains(
589                 result.getWarnings().get(0),
590                 "'dependencies.dependency.exclusions.exclusion.groupId' for gid:aid:jar is missing");
591         assertContains(
592                 result.getWarnings().get(1),
593                 "'dependencies.dependency.exclusions.exclusion.artifactId' for gid:aid:jar is missing");
594     }
595 
596     @Test
597     void testBadImportScopeType() throws Exception {
598         SimpleProblemCollector result = validateRaw("bad-import-scope-type.xml");
599 
600         assertViolations(result, 0, 0, 1);
601 
602         assertContains(
603                 result.getWarnings().get(0),
604                 "'dependencyManagement.dependencies.dependency.type' for test:a:jar must be 'pom'");
605     }
606 
607     @Test
608     void testBadImportScopeClassifier() throws Exception {
609         SimpleProblemCollector result = validateRaw("bad-import-scope-classifier.xml");
610 
611         assertViolations(result, 0, 1, 0);
612 
613         assertContains(
614                 result.getErrors().get(0),
615                 "'dependencyManagement.dependencies.dependency.classifier' for test:a:pom:cls must be empty");
616     }
617 
618     @Test
619     void testSystemPathRefersToProjectBasedir() throws Exception {
620         SimpleProblemCollector result = validateRaw("basedir-system-path.xml");
621 
622         assertViolations(result, 0, 0, 4);
623 
624         assertContains(
625                 result.getWarnings().get(0),
626                 "'dependencies.dependency.scope' for test:a:jar declares usage of deprecated 'system' scope");
627         assertContains(
628                 result.getWarnings().get(1),
629                 "'dependencies.dependency.systemPath' for test:a:jar should not point at files within the project directory");
630         assertContains(
631                 result.getWarnings().get(2),
632                 "'dependencies.dependency.scope' for test:b:jar declares usage of deprecated 'system' scope");
633         assertContains(
634                 result.getWarnings().get(3),
635                 "'dependencies.dependency.systemPath' for test:b:jar should not point at files within the project directory");
636     }
637 
638     @Test
639     void testInvalidVersionInPluginManagement() throws Exception {
640         SimpleProblemCollector result = validateRaw("raw-model/missing-plugin-version-pluginManagement.xml");
641 
642         assertViolations(result, 1, 0, 0);
643 
644         assertEquals(
645                 "'build.pluginManagement.plugins.plugin.(groupId:artifactId)' version of a plugin must be defined. ",
646                 result.getFatals().get(0));
647     }
648 
649     @Test
650     void testInvalidGroupIdInPluginManagement() throws Exception {
651         SimpleProblemCollector result = validateRaw("raw-model/missing-groupId-pluginManagement.xml");
652 
653         assertViolations(result, 1, 0, 0);
654 
655         assertEquals(
656                 "'build.pluginManagement.plugins.plugin.(groupId:artifactId)' groupId of a plugin must be defined. ",
657                 result.getFatals().get(0));
658     }
659 
660     @Test
661     void testInvalidArtifactIdInPluginManagement() throws Exception {
662         SimpleProblemCollector result = validateRaw("raw-model/missing-artifactId-pluginManagement.xml");
663 
664         assertViolations(result, 1, 0, 0);
665 
666         assertEquals(
667                 "'build.pluginManagement.plugins.plugin.(groupId:artifactId)' artifactId of a plugin must be defined. ",
668                 result.getFatals().get(0));
669     }
670 
671     @Test
672     void testInvalidGroupAndArtifactIdInPluginManagement() throws Exception {
673         SimpleProblemCollector result = validateRaw("raw-model/missing-ga-pluginManagement.xml");
674 
675         assertViolations(result, 2, 0, 0);
676 
677         assertEquals(
678                 "'build.pluginManagement.plugins.plugin.(groupId:artifactId)' groupId of a plugin must be defined. ",
679                 result.getFatals().get(0));
680 
681         assertEquals(
682                 "'build.pluginManagement.plugins.plugin.(groupId:artifactId)' artifactId of a plugin must be defined. ",
683                 result.getFatals().get(1));
684     }
685 
686     @Test
687     void testMissingReportPluginVersion() throws Exception {
688         SimpleProblemCollector result = validate("missing-report-version-pom.xml");
689 
690         assertViolations(result, 0, 0, 0);
691     }
692 
693     @Test
694     void testDeprecatedDependencyMetaversionsLatestAndRelease() throws Exception {
695         SimpleProblemCollector result = validateRaw("deprecated-dependency-metaversions-latest-and-release.xml");
696 
697         assertViolations(result, 0, 0, 2);
698 
699         assertContains(
700                 result.getWarnings().get(0),
701                 "'dependencies.dependency.version' for test:a:jar is either LATEST or RELEASE (both of them are being deprecated)");
702         assertContains(
703                 result.getWarnings().get(1),
704                 "'dependencies.dependency.version' for test:b:jar is either LATEST or RELEASE (both of them are being deprecated)");
705     }
706 
707     @Test
708     void testSelfReferencingDependencyInRawModel() throws Exception {
709         SimpleProblemCollector result = validateRaw("raw-model/self-referencing.xml");
710 
711         assertViolations(result, 1, 0, 0);
712 
713         assertEquals(
714                 "'dependencies.dependency[com.example.group:testinvalidpom:0.0.1-SNAPSHOT]' for com.example.group:testinvalidpom:0.0.1-SNAPSHOT is referencing itself.",
715                 result.getFatals().get(0));
716     }
717 
718     @Test
719     void testSelfReferencingDependencyWithClassifierInRawModel() throws Exception {
720         SimpleProblemCollector result = validateRaw("raw-model/self-referencing-classifier.xml");
721 
722         assertViolations(result, 0, 0, 0);
723     }
724 
725     @Test
726     void testCiFriendlySha1() throws Exception {
727         SimpleProblemCollector result = validateRaw("raw-model/ok-ci-friendly-sha1.xml");
728         assertViolations(result, 0, 0, 0);
729     }
730 
731     @Test
732     void testCiFriendlyRevision() throws Exception {
733         SimpleProblemCollector result = validateRaw("raw-model/ok-ci-friendly-revision.xml");
734         assertViolations(result, 0, 0, 0);
735     }
736 
737     @Test
738     void testCiFriendlyChangeList() throws Exception {
739         SimpleProblemCollector result = validateRaw("raw-model/ok-ci-friendly-changelist.xml");
740         assertViolations(result, 0, 0, 0);
741     }
742 
743     @Test
744     void testCiFriendlyAllExpressions() throws Exception {
745         SimpleProblemCollector result = validateRaw("raw-model/ok-ci-friendly-all-expressions.xml");
746         assertViolations(result, 0, 0, 0);
747     }
748 
749     @Test
750     void testCiFriendlyBad() throws Exception {
751         SimpleProblemCollector result = validateRaw("raw-model/bad-ci-friendly.xml");
752         assertViolations(result, 0, 0, 1);
753         assertEquals(
754                 "'version' contains an expression but should be a constant.",
755                 result.getWarnings().get(0));
756     }
757 
758     @Test
759     void testCiFriendlyBadSha1Plus() throws Exception {
760         SimpleProblemCollector result = validateRaw("raw-model/bad-ci-friendly-sha1plus.xml");
761         assertViolations(result, 0, 0, 1);
762         assertEquals(
763                 "'version' contains an expression but should be a constant.",
764                 result.getWarnings().get(0));
765     }
766 
767     @Test
768     void testCiFriendlyBadSha1Plus2() throws Exception {
769         SimpleProblemCollector result = validateRaw("raw-model/bad-ci-friendly-sha1plus2.xml");
770         assertViolations(result, 0, 0, 1);
771         assertEquals(
772                 "'version' contains an expression but should be a constant.",
773                 result.getWarnings().get(0));
774     }
775 
776     @Test
777     void testParentVersionLATEST() throws Exception {
778         SimpleProblemCollector result = validateRaw("raw-model/bad-parent-version-latest.xml");
779         assertViolations(result, 0, 0, 1);
780         assertEquals(
781                 "'parent.version' is either LATEST or RELEASE (both of them are being deprecated)",
782                 result.getWarnings().get(0));
783     }
784 
785     @Test
786     void testParentVersionRELEASE() throws Exception {
787         SimpleProblemCollector result = validateRaw("raw-model/bad-parent-version-release.xml");
788         assertViolations(result, 0, 0, 1);
789         assertEquals(
790                 "'parent.version' is either LATEST or RELEASE (both of them are being deprecated)",
791                 result.getWarnings().get(0));
792     }
793 
794     @Test
795     void repositoryWithExpression() throws Exception {
796         SimpleProblemCollector result = validateRaw("raw-model/repository-with-expression.xml");
797         assertViolations(result, 0, 1, 0);
798         assertEquals(
799                 "'repositories.repository.[repo].url' contains an expression but should be a constant.",
800                 result.getErrors().get(0));
801     }
802 
803     @Test
804     void repositoryWithBasedirExpression() throws Exception {
805         SimpleProblemCollector result = validateRaw("raw-model/repository-with-basedir-expression.xml");
806         assertViolations(result, 0, 0, 0);
807     }
808 }