1   package org.apache.maven.model.validation;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.InputStream;
23  import java.util.List;
24  
25  import org.apache.maven.model.Model;
26  import org.apache.maven.model.building.DefaultModelBuildingRequest;
27  import org.apache.maven.model.building.ModelBuildingRequest;
28  import org.apache.maven.model.building.SimpleProblemCollector;
29  import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
30  import org.codehaus.plexus.PlexusTestCase;
31  
32  /**
33   * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
34   * @version $Id: DefaultModelValidatorTest.java 1037689 2010-11-22 12:17:29Z bentmann $
35   */
36  public class DefaultModelValidatorTest
37      extends PlexusTestCase
38  {
39  
40      private DefaultModelValidator validator;
41  
42      private Model read( String pom )
43          throws Exception
44      {
45          String resource = "/poms/validation/" + pom;
46          InputStream is = getClass().getResourceAsStream( resource );
47          assertNotNull( "missing resource: " + resource, is );
48          return new MavenXpp3Reader().read( is );
49      }
50  
51      private SimpleProblemCollector validate( String pom )
52          throws Exception
53      {
54          return validateEffective( pom, ModelBuildingRequest.VALIDATION_LEVEL_STRICT );
55      }
56  
57      private SimpleProblemCollector validateRaw( String pom )
58          throws Exception
59      {
60          return validateRaw( pom, ModelBuildingRequest.VALIDATION_LEVEL_STRICT );
61      }
62  
63      private SimpleProblemCollector validateEffective( String pom, int level )
64          throws Exception
65      {
66          ModelBuildingRequest request = new DefaultModelBuildingRequest().setValidationLevel( level );
67  
68          SimpleProblemCollector problems = new SimpleProblemCollector();
69  
70          validator.validateEffectiveModel( read( pom ), request, problems );
71  
72          return problems;
73      }
74  
75      private SimpleProblemCollector validateRaw( String pom, int level )
76          throws Exception
77      {
78          ModelBuildingRequest request = new DefaultModelBuildingRequest().setValidationLevel( level );
79  
80          SimpleProblemCollector problems = new SimpleProblemCollector();
81  
82          validator.validateRawModel( read( pom ), request, problems );
83  
84          return problems;
85      }
86  
87      private void assertContains( String msg, String substring )
88      {
89          assertTrue( "\"" + substring + "\" was not found in: " + msg, msg.contains( substring ) );
90      }
91  
92      @Override
93      protected void setUp()
94          throws Exception
95      {
96          super.setUp();
97  
98          validator = (DefaultModelValidator) lookup( ModelValidator.class );
99      }
100 
101     @Override
102     protected void tearDown()
103         throws Exception
104     {
105         this.validator = null;
106 
107         super.tearDown();
108     }
109 
110     private void assertViolations( SimpleProblemCollector result, int fatals, int errors, int warnings )
111     {
112         assertEquals( fatals, result.getFatals().size() );
113         assertEquals( errors, result.getErrors().size() );
114         assertEquals( warnings, result.getWarnings().size() );
115     }
116 
117     public void testMissingModelVersion()
118         throws Exception
119     {
120         SimpleProblemCollector result = validate( "missing-modelVersion-pom.xml" );
121 
122         assertViolations( result, 0, 1, 0 );
123 
124         assertEquals( "'modelVersion' is missing.", result.getErrors().get( 0 ) );
125     }
126 
127     public void testBadModelVersion()
128         throws Exception
129     {
130         SimpleProblemCollector result =
131             validateRaw( "bad-modelVersion.xml", ModelBuildingRequest.VALIDATION_LEVEL_STRICT );
132 
133         assertViolations( result, 0, 1, 0 );
134 
135         assertTrue( result.getErrors().get( 0 ).indexOf( "modelVersion" ) > -1 );
136     }
137 
138     public void testMissingArtifactId()
139         throws Exception
140     {
141         SimpleProblemCollector result = validate( "missing-artifactId-pom.xml" );
142 
143         assertViolations( result, 0, 1, 0 );
144 
145         assertEquals( "'artifactId' is missing.", result.getErrors().get( 0 ) );
146     }
147 
148     public void testMissingGroupId()
149         throws Exception
150     {
151         SimpleProblemCollector result = validate( "missing-groupId-pom.xml" );
152 
153         assertViolations( result, 0, 1, 0 );
154 
155         assertEquals( "'groupId' is missing.", result.getErrors().get( 0 ) );
156     }
157 
158     public void testInvalidIds()
159         throws Exception
160     {
161         SimpleProblemCollector result = validate( "invalid-ids-pom.xml" );
162 
163         assertViolations( result, 0, 2, 0 );
164 
165         assertEquals( "'groupId' with value 'o/a/m' does not match a valid id pattern.", result.getErrors().get( 0 ) );
166 
167         assertEquals( "'artifactId' with value 'm$-do$' does not match a valid id pattern.", result.getErrors().get( 1 ) );
168     }
169 
170     public void testMissingType()
171         throws Exception
172     {
173         SimpleProblemCollector result = validate( "missing-type-pom.xml" );
174 
175         assertViolations( result, 0, 1, 0 );
176 
177         assertEquals( "'packaging' is missing.", result.getErrors().get( 0 ) );
178     }
179 
180     public void testMissingVersion()
181         throws Exception
182     {
183         SimpleProblemCollector result = validate( "missing-version-pom.xml" );
184 
185         assertViolations( result, 0, 1, 0 );
186 
187         assertEquals( "'version' is missing.", result.getErrors().get( 0 ) );
188     }
189 
190     public void testInvalidAggregatorPackaging()
191         throws Exception
192     {
193         SimpleProblemCollector result = validate( "invalid-aggregator-packaging-pom.xml" );
194 
195         assertViolations( result, 0, 1, 0 );
196 
197         assertTrue( result.getErrors().get( 0 ).indexOf( "Aggregator projects require 'pom' as packaging." ) > -1 );
198     }
199 
200     public void testMissingDependencyArtifactId()
201         throws Exception
202     {
203         SimpleProblemCollector result = validate( "missing-dependency-artifactId-pom.xml" );
204 
205         assertViolations( result, 0, 1, 0 );
206 
207         assertTrue( result.getErrors().get( 0 ).indexOf(
208                                                          "'dependencies.dependency.artifactId' for groupId:null:jar is missing" ) > -1 );
209     }
210 
211     public void testMissingDependencyGroupId()
212         throws Exception
213     {
214         SimpleProblemCollector result = validate( "missing-dependency-groupId-pom.xml" );
215 
216         assertViolations( result, 0, 1, 0 );
217 
218         assertTrue( result.getErrors().get( 0 ).indexOf(
219                                                          "'dependencies.dependency.groupId' for null:artifactId:jar is missing" ) > -1 );
220     }
221 
222     public void testMissingDependencyVersion()
223         throws Exception
224     {
225         SimpleProblemCollector result = validate( "missing-dependency-version-pom.xml" );
226 
227         assertViolations( result, 0, 1, 0 );
228 
229         assertTrue( result.getErrors().get( 0 ).indexOf(
230                                                          "'dependencies.dependency.version' for groupId:artifactId:jar is missing" ) > -1 );
231     }
232 
233     public void testMissingDependencyManagementArtifactId()
234         throws Exception
235     {
236         SimpleProblemCollector result = validate( "missing-dependency-mgmt-artifactId-pom.xml" );
237 
238         assertViolations( result, 0, 1, 0 );
239 
240         assertTrue( result.getErrors().get( 0 ).indexOf(
241                                                          "'dependencyManagement.dependencies.dependency.artifactId' for groupId:null:jar is missing" ) > -1 );
242     }
243 
244     public void testMissingDependencyManagementGroupId()
245         throws Exception
246     {
247         SimpleProblemCollector result = validate( "missing-dependency-mgmt-groupId-pom.xml" );
248 
249         assertViolations( result, 0, 1, 0 );
250 
251         assertTrue( result.getErrors().get( 0 ).indexOf(
252                                                          "'dependencyManagement.dependencies.dependency.groupId' for null:artifactId:jar is missing" ) > -1 );
253     }
254 
255     public void testMissingAll()
256         throws Exception
257     {
258         SimpleProblemCollector result = validate( "missing-1-pom.xml" );
259 
260         assertViolations( result, 0, 4, 0 );
261 
262         List<String> messages = result.getErrors();
263 
264         assertTrue( messages.contains( "\'modelVersion\' is missing." ) );
265         assertTrue( messages.contains( "\'groupId\' is missing." ) );
266         assertTrue( messages.contains( "\'artifactId\' is missing." ) );
267         assertTrue( messages.contains( "\'version\' is missing." ) );
268         // type is inherited from the super pom
269     }
270 
271     public void testMissingPluginArtifactId()
272         throws Exception
273     {
274         SimpleProblemCollector result = validate( "missing-plugin-artifactId-pom.xml" );
275 
276         assertViolations( result, 0, 1, 0 );
277 
278         assertEquals( "'build.plugins.plugin.artifactId' is missing.", result.getErrors().get( 0 ) );
279     }
280 
281     public void testEmptyPluginVersion()
282         throws Exception
283     {
284         SimpleProblemCollector result = validate( "empty-plugin-version.xml" );
285 
286         assertViolations( result, 0, 1, 0 );
287 
288         assertEquals( "'build.plugins.plugin.version' for org.apache.maven.plugins:maven-it-plugin"
289             + " must be a valid version but is ''.", result.getErrors().get( 0 ) );
290     }
291 
292     public void testMissingRepositoryId()
293         throws Exception
294     {
295         SimpleProblemCollector result =
296             validateRaw( "missing-repository-id-pom.xml", ModelBuildingRequest.VALIDATION_LEVEL_STRICT );
297 
298         assertViolations( result, 0, 4, 0 );
299 
300         assertEquals( "'repositories.repository.id' is missing.", result.getErrors().get( 0 ) );
301 
302         assertEquals( "'repositories.repository[null].url' is missing.", result.getErrors().get( 1 ) );
303 
304         assertEquals( "'pluginRepositories.pluginRepository.id' is missing.", result.getErrors().get( 2 ) );
305 
306         assertEquals( "'pluginRepositories.pluginRepository[null].url' is missing.", result.getErrors().get( 3 ) );
307     }
308 
309     public void testMissingResourceDirectory()
310         throws Exception
311     {
312         SimpleProblemCollector result = validate( "missing-resource-directory-pom.xml" );
313 
314         assertViolations( result, 0, 2, 0 );
315 
316         assertEquals( "'build.resources.resource.directory' is missing.", result.getErrors().get( 0 ) );
317 
318         assertEquals( "'build.testResources.testResource.directory' is missing.", result.getErrors().get( 1 ) );
319     }
320 
321     public void testBadPluginDependencyScope()
322         throws Exception
323     {
324         SimpleProblemCollector result = validate( "bad-plugin-dependency-scope.xml" );
325 
326         assertViolations( result, 0, 3, 0 );
327 
328         assertTrue( result.getErrors().get( 0 ).contains( "test:d" ) );
329 
330         assertTrue( result.getErrors().get( 1 ).contains( "test:e" ) );
331 
332         assertTrue( result.getErrors().get( 2 ).contains( "test:f" ) );
333     }
334 
335     public void testBadDependencyScope()
336         throws Exception
337     {
338         SimpleProblemCollector result = validate( "bad-dependency-scope.xml" );
339 
340         assertViolations( result, 0, 0, 2 );
341 
342         assertTrue( result.getWarnings().get( 0 ).contains( "test:f" ) );
343 
344         assertTrue( result.getWarnings().get( 1 ).contains( "test:g" ) );
345     }
346 
347     public void testBadDependencyVersion()
348         throws Exception
349     {
350         SimpleProblemCollector result = validate( "bad-dependency-version.xml" );
351 
352         assertViolations( result, 0, 1, 0 );
353 
354         assertTrue( result.getErrors().get( 0 ).contains( "test:b" ) );
355     }
356 
357     public void testDuplicateModule()
358         throws Exception
359     {
360         SimpleProblemCollector result = validate( "duplicate-module.xml" );
361 
362         assertViolations( result, 0, 1, 0 );
363 
364         assertTrue( result.getErrors().get( 0 ).contains( "child" ) );
365     }
366 
367     public void testDuplicateProfileId()
368         throws Exception
369     {
370         SimpleProblemCollector result = validateRaw( "duplicate-profile-id.xml" );
371 
372         assertViolations( result, 0, 1, 0 );
373 
374         assertTrue( result.getErrors().get( 0 ).contains( "non-unique-id" ) );
375     }
376 
377     public void testBadPluginVersion()
378         throws Exception
379     {
380         SimpleProblemCollector result = validate( "bad-plugin-version.xml" );
381 
382         assertViolations( result, 0, 3, 0 );
383 
384         assertTrue( result.getErrors().get( 0 ).contains( "test:mip" ) );
385         assertTrue( result.getErrors().get( 1 ).contains( "test:rmv" ) );
386         assertTrue( result.getErrors().get( 2 ).contains( "test:lmv" ) );
387     }
388 
389     public void testDistributionManagementStatus()
390         throws Exception
391     {
392         SimpleProblemCollector result = validate( "distribution-management-status.xml" );
393 
394         assertViolations( result, 0, 1, 0 );
395 
396         assertTrue( result.getErrors().get( 0 ).contains( "distributionManagement.status" ) );
397     }
398 
399     public void testIncompleteParent()
400         throws Exception
401     {
402         SimpleProblemCollector result = validateRaw( "incomplete-parent.xml" );
403 
404         assertViolations( result, 3, 0, 0 );
405 
406         assertTrue( result.getFatals().get( 0 ).contains( "parent.groupId" ) );
407         assertTrue( result.getFatals().get( 1 ).contains( "parent.artifactId" ) );
408         assertTrue( result.getFatals().get( 2 ).contains( "parent.version" ) );
409     }
410 
411     public void testHardCodedSystemPath()
412         throws Exception
413     {
414         SimpleProblemCollector result = validateRaw( "hard-coded-system-path.xml" );
415 
416         assertViolations( result, 0, 0, 1 );
417 
418         assertTrue( result.getWarnings().get( 0 ).contains( "test:a:jar" ) );
419     }
420 
421     public void testEmptyModule()
422         throws Exception
423     {
424         SimpleProblemCollector result = validate( "empty-module.xml" );
425 
426         assertViolations( result, 0, 0, 1 );
427 
428         assertTrue( result.getWarnings().get( 0 ).contains( "'modules.module[0]' has been specified without a path" ) );
429     }
430 
431     public void testDuplicatePlugin()
432         throws Exception
433     {
434         SimpleProblemCollector result = validateRaw( "duplicate-plugin.xml" );
435 
436         assertViolations( result, 0, 0, 4 );
437 
438         assertTrue( result.getWarnings().get( 0 ).contains( "duplicate declaration of plugin test:duplicate" ) );
439         assertTrue( result.getWarnings().get( 1 ).contains( "duplicate declaration of plugin test:managed-duplicate" ) );
440         assertTrue( result.getWarnings().get( 2 ).contains( "duplicate declaration of plugin profile:duplicate" ) );
441         assertTrue( result.getWarnings().get( 3 ).contains( "duplicate declaration of plugin profile:managed-duplicate" ) );
442     }
443 
444     public void testDuplicatePluginExecution()
445         throws Exception
446     {
447         SimpleProblemCollector result = validateRaw( "duplicate-plugin-execution.xml" );
448 
449         assertViolations( result, 0, 4, 0 );
450 
451         assertContains( result.getErrors().get( 0 ), "duplicate execution with id a" );
452         assertContains( result.getErrors().get( 1 ), "duplicate execution with id default" );
453         assertContains( result.getErrors().get( 2 ), "duplicate execution with id c" );
454         assertContains( result.getErrors().get( 3 ), "duplicate execution with id b" );
455     }
456 
457     public void testReservedRepositoryId()
458         throws Exception
459     {
460         SimpleProblemCollector result = validate( "reserved-repository-id.xml" );
461 
462         assertViolations( result, 0, 0, 4 );
463 
464         assertContains( result.getWarnings().get( 0 ), "'repositories.repository.id'" + " must not be 'local'" );
465         assertContains( result.getWarnings().get( 1 ), "'pluginRepositories.pluginRepository.id' must not be 'local'" );
466         assertContains( result.getWarnings().get( 2 ), "'distributionManagement.repository.id' must not be 'local'" );
467         assertContains( result.getWarnings().get( 3 ),
468                         "'distributionManagement.snapshotRepository.id' must not be 'local'" );
469     }
470 
471     public void testMissingPluginDependencyGroupId()
472         throws Exception
473     {
474         SimpleProblemCollector result = validate( "missing-plugin-dependency-groupId.xml" );
475 
476         assertViolations( result, 0, 1, 0 );
477 
478         assertTrue( result.getErrors().get( 0 ).contains( ":a:" ) );
479     }
480 
481     public void testMissingPluginDependencyArtifactId()
482         throws Exception
483     {
484         SimpleProblemCollector result = validate( "missing-plugin-dependency-artifactId.xml" );
485 
486         assertViolations( result, 0, 1, 0 );
487 
488         assertTrue( result.getErrors().get( 0 ).contains( "test:" ) );
489     }
490 
491     public void testMissingPluginDependencyVersion()
492         throws Exception
493     {
494         SimpleProblemCollector result = validate( "missing-plugin-dependency-version.xml" );
495 
496         assertViolations( result, 0, 1, 0 );
497 
498         assertTrue( result.getErrors().get( 0 ).contains( "test:a" ) );
499     }
500 
501     public void testBadPluginDependencyVersion()
502         throws Exception
503     {
504         SimpleProblemCollector result = validate( "bad-plugin-dependency-version.xml" );
505 
506         assertViolations( result, 0, 1, 0 );
507 
508         assertTrue( result.getErrors().get( 0 ).contains( "test:b" ) );
509     }
510 
511     public void testBadVersion()
512         throws Exception
513     {
514         SimpleProblemCollector result = validate( "bad-version.xml" );
515 
516         assertViolations( result, 0, 0, 1 );
517 
518         assertContains( result.getWarnings().get( 0 ), "'version' must not contain any of these characters" );
519     }
520 
521     public void testBadRepositoryId()
522         throws Exception
523     {
524         SimpleProblemCollector result = validate( "bad-repository-id.xml" );
525 
526         assertViolations( result, 0, 0, 4 );
527 
528         assertContains( result.getWarnings().get( 0 ),
529                         "'repositories.repository.id' must not contain any of these characters" );
530         assertContains( result.getWarnings().get( 1 ),
531                         "'pluginRepositories.pluginRepository.id' must not contain any of these characters" );
532         assertContains( result.getWarnings().get( 2 ),
533                         "'distributionManagement.repository.id' must not contain any of these characters" );
534         assertContains( result.getWarnings().get( 3 ),
535                         "'distributionManagement.snapshotRepository.id' must not contain any of these characters" );
536     }
537 
538     public void testBadDependencyExclusionId()
539         throws Exception
540     {
541         SimpleProblemCollector result = validate( "bad-dependency-exclusion-id.xml" );
542 
543         assertViolations( result, 0, 0, 2 );
544 
545         assertContains( result.getWarnings().get( 0 ),
546                         "'dependencies.dependency.exclusions.exclusion.groupId' for gid:aid:jar" );
547         assertContains( result.getWarnings().get( 1 ),
548                         "'dependencies.dependency.exclusions.exclusion.artifactId' for gid:aid:jar" );
549     }
550 
551     public void testMissingDependencyExclusionId()
552         throws Exception
553     {
554         SimpleProblemCollector result = validate( "missing-dependency-exclusion-id.xml" );
555 
556         assertViolations( result, 0, 0, 2 );
557 
558         assertContains( result.getWarnings().get( 0 ),
559                         "'dependencies.dependency.exclusions.exclusion.groupId' for gid:aid:jar is missing" );
560         assertContains( result.getWarnings().get( 1 ),
561                         "'dependencies.dependency.exclusions.exclusion.artifactId' for gid:aid:jar is missing" );
562     }
563 
564     public void testBadImportScopeType()
565         throws Exception
566     {
567         SimpleProblemCollector result = validateRaw( "bad-import-scope-type.xml" );
568 
569         assertViolations( result, 0, 0, 1 );
570 
571         assertContains( result.getWarnings().get( 0 ),
572                         "'dependencyManagement.dependencies.dependency.type' for test:a:jar must be 'pom'" );
573     }
574 
575     public void testBadImportScopeClassifier()
576         throws Exception
577     {
578         SimpleProblemCollector result = validateRaw( "bad-import-scope-classifier.xml" );
579 
580         assertViolations( result, 0, 1, 0 );
581 
582         assertContains( result.getErrors().get( 0 ),
583                         "'dependencyManagement.dependencies.dependency.classifier' for test:a:pom:cls must be empty" );
584     }
585 
586 }