001package org.apache.maven.model.validation; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.io.InputStream; 023import java.util.List; 024 025import org.apache.maven.model.Model; 026import org.apache.maven.model.building.DefaultModelBuildingRequest; 027import org.apache.maven.model.building.ModelBuildingRequest; 028import org.apache.maven.model.building.SimpleProblemCollector; 029import org.apache.maven.model.io.xpp3.MavenXpp3Reader; 030import org.codehaus.plexus.PlexusTestCase; 031 032/** 033 * @author <a href="mailto:trygvis@inamo.no">Trygve Laugstøl</a> 034 */ 035public class DefaultModelValidatorTest 036 extends PlexusTestCase 037{ 038 039 private ModelValidator validator; 040 041 private Model read( String pom ) 042 throws Exception 043 { 044 String resource = "/poms/validation/" + pom; 045 InputStream is = getClass().getResourceAsStream( resource ); 046 assertNotNull( "missing resource: " + resource, is ); 047 return new MavenXpp3Reader().read( is ); 048 } 049 050 private SimpleProblemCollector validate( String pom ) 051 throws Exception 052 { 053 return validateEffective( pom, ModelBuildingRequest.VALIDATION_LEVEL_STRICT ); 054 } 055 056 private SimpleProblemCollector validateRaw( String pom ) 057 throws Exception 058 { 059 return validateRaw( pom, ModelBuildingRequest.VALIDATION_LEVEL_STRICT ); 060 } 061 062 private SimpleProblemCollector validateEffective( String pom, int level ) 063 throws Exception 064 { 065 ModelBuildingRequest request = new DefaultModelBuildingRequest().setValidationLevel( level ); 066 067 SimpleProblemCollector problems = new SimpleProblemCollector( read( pom ) ); 068 069 validator.validateEffectiveModel( problems.getModel(), request, problems ); 070 071 return problems; 072 } 073 074 private SimpleProblemCollector validateRaw( String pom, int level ) 075 throws Exception 076 { 077 ModelBuildingRequest request = new DefaultModelBuildingRequest().setValidationLevel( level ); 078 079 SimpleProblemCollector problems = new SimpleProblemCollector( read( pom ) ); 080 081 validator.validateRawModel( problems.getModel(), request, problems ); 082 083 return problems; 084 } 085 086 private void assertContains( String msg, String substring ) 087 { 088 assertTrue( "\"" + substring + "\" was not found in: " + msg, msg.contains( substring ) ); 089 } 090 091 @Override 092 protected void setUp() 093 throws Exception 094 { 095 super.setUp(); 096 097 validator = lookup( ModelValidator.class ); 098 } 099 100 @Override 101 protected void tearDown() 102 throws Exception 103 { 104 this.validator = null; 105 106 super.tearDown(); 107 } 108 109 private void assertViolations( SimpleProblemCollector result, int fatals, int errors, int warnings ) 110 { 111 assertEquals( String.valueOf( result.getFatals() ), fatals, result.getFatals().size() ); 112 assertEquals( String.valueOf( result.getErrors() ), errors, result.getErrors().size() ); 113 assertEquals( String.valueOf( result.getWarnings() ), warnings, result.getWarnings().size() ); 114 } 115 116 public void testMissingModelVersion() 117 throws Exception 118 { 119 SimpleProblemCollector result = validate( "missing-modelVersion-pom.xml" ); 120 121 assertViolations( result, 0, 1, 0 ); 122 123 assertEquals( "'modelVersion' is missing.", result.getErrors().get( 0 ) ); 124 } 125 126 public void testBadModelVersion() 127 throws Exception 128 { 129 SimpleProblemCollector result = 130 validateRaw( "bad-modelVersion.xml", ModelBuildingRequest.VALIDATION_LEVEL_STRICT ); 131 132 assertViolations( result, 0, 1, 0 ); 133 134 assertTrue( result.getErrors().get( 0 ).contains( "modelVersion" ) ); 135 } 136 137 public void testMissingArtifactId() 138 throws Exception 139 { 140 SimpleProblemCollector result = validate( "missing-artifactId-pom.xml" ); 141 142 assertViolations( result, 0, 1, 0 ); 143 144 assertEquals( "'artifactId' is missing.", result.getErrors().get( 0 ) ); 145 } 146 147 public void testMissingGroupId() 148 throws Exception 149 { 150 SimpleProblemCollector result = validate( "missing-groupId-pom.xml" ); 151 152 assertViolations( result, 0, 1, 0 ); 153 154 assertEquals( "'groupId' is missing.", result.getErrors().get( 0 ) ); 155 } 156 157 public void testInvalidIds() 158 throws Exception 159 { 160 SimpleProblemCollector result = validate( "invalid-ids-pom.xml" ); 161 162 assertViolations( result, 0, 2, 0 ); 163 164 assertEquals( "'groupId' with value 'o/a/m' does not match a valid id pattern.", result.getErrors().get( 0 ) ); 165 166 assertEquals( "'artifactId' with value 'm$-do$' does not match a valid id pattern.", result.getErrors().get( 1 ) ); 167 } 168 169 public void testMissingType() 170 throws Exception 171 { 172 SimpleProblemCollector result = validate( "missing-type-pom.xml" ); 173 174 assertViolations( result, 0, 1, 0 ); 175 176 assertEquals( "'packaging' is missing.", result.getErrors().get( 0 ) ); 177 } 178 179 public void testMissingVersion() 180 throws Exception 181 { 182 SimpleProblemCollector result = validate( "missing-version-pom.xml" ); 183 184 assertViolations( result, 0, 1, 0 ); 185 186 assertEquals( "'version' is missing.", result.getErrors().get( 0 ) ); 187 } 188 189 public void testInvalidAggregatorPackaging() 190 throws Exception 191 { 192 SimpleProblemCollector result = validate( "invalid-aggregator-packaging-pom.xml" ); 193 194 assertViolations( result, 0, 1, 0 ); 195 196 assertTrue( result.getErrors().get( 0 ).contains( "Aggregator projects require 'pom' as packaging." ) ); 197 } 198 199 public void testMissingDependencyArtifactId() 200 throws Exception 201 { 202 SimpleProblemCollector result = validate( "missing-dependency-artifactId-pom.xml" ); 203 204 assertViolations( result, 0, 1, 0 ); 205 206 assertTrue( result.getErrors().get( 0 ).contains( 207 "'dependencies.dependency.artifactId' for groupId:null:jar is missing" ) ); 208 } 209 210 public void testMissingDependencyGroupId() 211 throws Exception 212 { 213 SimpleProblemCollector result = validate( "missing-dependency-groupId-pom.xml" ); 214 215 assertViolations( result, 0, 1, 0 ); 216 217 assertTrue( result.getErrors().get( 0 ).contains( 218 "'dependencies.dependency.groupId' for null:artifactId:jar is missing" ) ); 219 } 220 221 public void testMissingDependencyVersion() 222 throws Exception 223 { 224 SimpleProblemCollector result = validate( "missing-dependency-version-pom.xml" ); 225 226 assertViolations( result, 0, 1, 0 ); 227 228 assertTrue( result.getErrors().get( 0 ).contains( 229 "'dependencies.dependency.version' for groupId:artifactId:jar is missing" ) ); 230 } 231 232 public void testMissingDependencyManagementArtifactId() 233 throws Exception 234 { 235 SimpleProblemCollector result = validate( "missing-dependency-mgmt-artifactId-pom.xml" ); 236 237 assertViolations( result, 0, 1, 0 ); 238 239 assertTrue( result.getErrors().get( 0 ).contains( 240 "'dependencyManagement.dependencies.dependency.artifactId' for groupId:null:jar is missing" ) ); 241 } 242 243 public void testMissingDependencyManagementGroupId() 244 throws Exception 245 { 246 SimpleProblemCollector result = validate( "missing-dependency-mgmt-groupId-pom.xml" ); 247 248 assertViolations( result, 0, 1, 0 ); 249 250 assertTrue( result.getErrors().get( 0 ).contains( 251 "'dependencyManagement.dependencies.dependency.groupId' for null:artifactId:jar is missing" ) ); 252 } 253 254 public void testMissingAll() 255 throws Exception 256 { 257 SimpleProblemCollector result = validate( "missing-1-pom.xml" ); 258 259 assertViolations( result, 0, 4, 0 ); 260 261 List<String> messages = result.getErrors(); 262 263 assertTrue( messages.contains( "\'modelVersion\' is missing." ) ); 264 assertTrue( messages.contains( "\'groupId\' is missing." ) ); 265 assertTrue( messages.contains( "\'artifactId\' is missing." ) ); 266 assertTrue( messages.contains( "\'version\' is missing." ) ); 267 // type is inherited from the super pom 268 } 269 270 public void testMissingPluginArtifactId() 271 throws Exception 272 { 273 SimpleProblemCollector result = validate( "missing-plugin-artifactId-pom.xml" ); 274 275 assertViolations( result, 0, 1, 0 ); 276 277 assertEquals( "'build.plugins.plugin.artifactId' is missing.", result.getErrors().get( 0 ) ); 278 } 279 280 public void testEmptyPluginVersion() 281 throws Exception 282 { 283 SimpleProblemCollector result = validate( "empty-plugin-version.xml" ); 284 285 assertViolations( result, 0, 1, 0 ); 286 287 assertEquals( "'build.plugins.plugin.version' for org.apache.maven.plugins:maven-it-plugin" 288 + " must be a valid version but is ''.", result.getErrors().get( 0 ) ); 289 } 290 291 public void testMissingRepositoryId() 292 throws Exception 293 { 294 SimpleProblemCollector result = 295 validateRaw( "missing-repository-id-pom.xml", ModelBuildingRequest.VALIDATION_LEVEL_STRICT ); 296 297 assertViolations( result, 0, 4, 0 ); 298 299 assertEquals( "'repositories.repository.id' is missing.", result.getErrors().get( 0 ) ); 300 301 assertEquals( "'repositories.repository[null].url' is missing.", result.getErrors().get( 1 ) ); 302 303 assertEquals( "'pluginRepositories.pluginRepository.id' is missing.", result.getErrors().get( 2 ) ); 304 305 assertEquals( "'pluginRepositories.pluginRepository[null].url' is missing.", result.getErrors().get( 3 ) ); 306 } 307 308 public void testMissingResourceDirectory() 309 throws Exception 310 { 311 SimpleProblemCollector result = validate( "missing-resource-directory-pom.xml" ); 312 313 assertViolations( result, 0, 2, 0 ); 314 315 assertEquals( "'build.resources.resource.directory' is missing.", result.getErrors().get( 0 ) ); 316 317 assertEquals( "'build.testResources.testResource.directory' is missing.", result.getErrors().get( 1 ) ); 318 } 319 320 public void testBadPluginDependencyScope() 321 throws Exception 322 { 323 SimpleProblemCollector result = validate( "bad-plugin-dependency-scope.xml" ); 324 325 assertViolations( result, 0, 3, 0 ); 326 327 assertTrue( result.getErrors().get( 0 ).contains( "test:d" ) ); 328 329 assertTrue( result.getErrors().get( 1 ).contains( "test:e" ) ); 330 331 assertTrue( result.getErrors().get( 2 ).contains( "test:f" ) ); 332 } 333 334 public void testBadDependencyScope() 335 throws Exception 336 { 337 SimpleProblemCollector result = validate( "bad-dependency-scope.xml" ); 338 339 assertViolations( result, 0, 0, 2 ); 340 341 assertTrue( result.getWarnings().get( 0 ).contains( "test:f" ) ); 342 343 assertTrue( result.getWarnings().get( 1 ).contains( "test:g" ) ); 344 } 345 346 public void testBadDependencyVersion() 347 throws Exception 348 { 349 SimpleProblemCollector result = validate( "bad-dependency-version.xml" ); 350 351 assertViolations( result, 0, 2, 0 ); 352 353 assertContains( result.getErrors().get( 0 ), 354 "'dependencies.dependency.version' for test:b:jar must be a valid version" ); 355 assertContains( result.getErrors().get( 1 ), 356 "'dependencies.dependency.version' for test:c:jar must not contain any of these characters" ); 357 } 358 359 public void testDuplicateModule() 360 throws Exception 361 { 362 SimpleProblemCollector result = validate( "duplicate-module.xml" ); 363 364 assertViolations( result, 0, 1, 0 ); 365 366 assertTrue( result.getErrors().get( 0 ).contains( "child" ) ); 367 } 368 369 public void testDuplicateProfileId() 370 throws Exception 371 { 372 SimpleProblemCollector result = validateRaw( "duplicate-profile-id.xml" ); 373 374 assertViolations( result, 0, 1, 0 ); 375 376 assertTrue( result.getErrors().get( 0 ).contains( "non-unique-id" ) ); 377 } 378 379 public void testBadPluginVersion() 380 throws Exception 381 { 382 SimpleProblemCollector result = validate( "bad-plugin-version.xml" ); 383 384 assertViolations( result, 0, 4, 0 ); 385 386 assertContains( result.getErrors().get( 0 ), 387 "'build.plugins.plugin.version' for test:mip must be a valid version" ); 388 assertContains( result.getErrors().get( 1 ), 389 "'build.plugins.plugin.version' for test:rmv must be a valid version" ); 390 assertContains( result.getErrors().get( 2 ), 391 "'build.plugins.plugin.version' for test:lmv must be a valid version" ); 392 assertContains( result.getErrors().get( 3 ), 393 "'build.plugins.plugin.version' for test:ifsc must not contain any of these characters" ); 394 } 395 396 public void testDistributionManagementStatus() 397 throws Exception 398 { 399 SimpleProblemCollector result = validate( "distribution-management-status.xml" ); 400 401 assertViolations( result, 0, 1, 0 ); 402 403 assertTrue( result.getErrors().get( 0 ).contains( "distributionManagement.status" ) ); 404 } 405 406 public void testIncompleteParent() 407 throws Exception 408 { 409 SimpleProblemCollector result = validateRaw( "incomplete-parent.xml" ); 410 411 assertViolations( result, 3, 0, 0 ); 412 413 assertTrue( result.getFatals().get( 0 ).contains( "parent.groupId" ) ); 414 assertTrue( result.getFatals().get( 1 ).contains( "parent.artifactId" ) ); 415 assertTrue( result.getFatals().get( 2 ).contains( "parent.version" ) ); 416 } 417 418 public void testHardCodedSystemPath() 419 throws Exception 420 { 421 SimpleProblemCollector result = validateRaw( "hard-coded-system-path.xml" ); 422 423 assertViolations( result, 0, 0, 1 ); 424 425 assertTrue( result.getWarnings().get( 0 ).contains( "test:a:jar" ) ); 426 } 427 428 public void testEmptyModule() 429 throws Exception 430 { 431 SimpleProblemCollector result = validate( "empty-module.xml" ); 432 433 assertViolations( result, 0, 0, 1 ); 434 435 assertTrue( result.getWarnings().get( 0 ).contains( "'modules.module[0]' has been specified without a path" ) ); 436 } 437 438 public void testDuplicatePlugin() 439 throws Exception 440 { 441 SimpleProblemCollector result = validateRaw( "duplicate-plugin.xml" ); 442 443 assertViolations( result, 0, 0, 4 ); 444 445 assertTrue( result.getWarnings().get( 0 ).contains( "duplicate declaration of plugin test:duplicate" ) ); 446 assertTrue( result.getWarnings().get( 1 ).contains( "duplicate declaration of plugin test:managed-duplicate" ) ); 447 assertTrue( result.getWarnings().get( 2 ).contains( "duplicate declaration of plugin profile:duplicate" ) ); 448 assertTrue( result.getWarnings().get( 3 ).contains( "duplicate declaration of plugin profile:managed-duplicate" ) ); 449 } 450 451 public void testDuplicatePluginExecution() 452 throws Exception 453 { 454 SimpleProblemCollector result = validateRaw( "duplicate-plugin-execution.xml" ); 455 456 assertViolations( result, 0, 4, 0 ); 457 458 assertContains( result.getErrors().get( 0 ), "duplicate execution with id a" ); 459 assertContains( result.getErrors().get( 1 ), "duplicate execution with id default" ); 460 assertContains( result.getErrors().get( 2 ), "duplicate execution with id c" ); 461 assertContains( result.getErrors().get( 3 ), "duplicate execution with id b" ); 462 } 463 464 public void testReservedRepositoryId() 465 throws Exception 466 { 467 SimpleProblemCollector result = validate( "reserved-repository-id.xml" ); 468 469 assertViolations( result, 0, 0, 4 ); 470 471 assertContains( result.getWarnings().get( 0 ), "'repositories.repository.id'" + " must not be 'local'" ); 472 assertContains( result.getWarnings().get( 1 ), "'pluginRepositories.pluginRepository.id' must not be 'local'" ); 473 assertContains( result.getWarnings().get( 2 ), "'distributionManagement.repository.id' must not be 'local'" ); 474 assertContains( result.getWarnings().get( 3 ), 475 "'distributionManagement.snapshotRepository.id' must not be 'local'" ); 476 } 477 478 public void testMissingPluginDependencyGroupId() 479 throws Exception 480 { 481 SimpleProblemCollector result = validate( "missing-plugin-dependency-groupId.xml" ); 482 483 assertViolations( result, 0, 1, 0 ); 484 485 assertTrue( result.getErrors().get( 0 ).contains( ":a:" ) ); 486 } 487 488 public void testMissingPluginDependencyArtifactId() 489 throws Exception 490 { 491 SimpleProblemCollector result = validate( "missing-plugin-dependency-artifactId.xml" ); 492 493 assertViolations( result, 0, 1, 0 ); 494 495 assertTrue( result.getErrors().get( 0 ).contains( "test:" ) ); 496 } 497 498 public void testMissingPluginDependencyVersion() 499 throws Exception 500 { 501 SimpleProblemCollector result = validate( "missing-plugin-dependency-version.xml" ); 502 503 assertViolations( result, 0, 1, 0 ); 504 505 assertTrue( result.getErrors().get( 0 ).contains( "test:a" ) ); 506 } 507 508 public void testBadPluginDependencyVersion() 509 throws Exception 510 { 511 SimpleProblemCollector result = validate( "bad-plugin-dependency-version.xml" ); 512 513 assertViolations( result, 0, 1, 0 ); 514 515 assertTrue( result.getErrors().get( 0 ).contains( "test:b" ) ); 516 } 517 518 public void testBadVersion() 519 throws Exception 520 { 521 SimpleProblemCollector result = validate( "bad-version.xml" ); 522 523 assertViolations( result, 0, 0, 1 ); 524 525 assertContains( result.getWarnings().get( 0 ), "'version' must not contain any of these characters" ); 526 } 527 528 public void testBadSnapshotVersion() 529 throws Exception 530 { 531 SimpleProblemCollector result = validate( "bad-snapshot-version.xml" ); 532 533 assertViolations( result, 0, 0, 1 ); 534 535 assertContains( result.getWarnings().get( 0 ), "'version' uses an unsupported snapshot version format" ); 536 } 537 538 public void testBadRepositoryId() 539 throws Exception 540 { 541 SimpleProblemCollector result = validate( "bad-repository-id.xml" ); 542 543 assertViolations( result, 0, 0, 4 ); 544 545 assertContains( result.getWarnings().get( 0 ), 546 "'repositories.repository.id' must not contain any of these characters" ); 547 assertContains( result.getWarnings().get( 1 ), 548 "'pluginRepositories.pluginRepository.id' must not contain any of these characters" ); 549 assertContains( result.getWarnings().get( 2 ), 550 "'distributionManagement.repository.id' must not contain any of these characters" ); 551 assertContains( result.getWarnings().get( 3 ), 552 "'distributionManagement.snapshotRepository.id' must not contain any of these characters" ); 553 } 554 555 public void testBadDependencyExclusionId() 556 throws Exception 557 { 558 SimpleProblemCollector result = validate( "bad-dependency-exclusion-id.xml" ); 559 560 assertViolations( result, 0, 0, 2 ); 561 562 assertContains( result.getWarnings().get( 0 ), 563 "'dependencies.dependency.exclusions.exclusion.groupId' for gid:aid:jar" ); 564 assertContains( result.getWarnings().get( 1 ), 565 "'dependencies.dependency.exclusions.exclusion.artifactId' for gid:aid:jar" ); 566 } 567 568 public void testMissingDependencyExclusionId() 569 throws Exception 570 { 571 SimpleProblemCollector result = validate( "missing-dependency-exclusion-id.xml" ); 572 573 assertViolations( result, 0, 0, 2 ); 574 575 assertContains( result.getWarnings().get( 0 ), 576 "'dependencies.dependency.exclusions.exclusion.groupId' for gid:aid:jar is missing" ); 577 assertContains( result.getWarnings().get( 1 ), 578 "'dependencies.dependency.exclusions.exclusion.artifactId' for gid:aid:jar is missing" ); 579 } 580 581 public void testBadImportScopeType() 582 throws Exception 583 { 584 SimpleProblemCollector result = validateRaw( "bad-import-scope-type.xml" ); 585 586 assertViolations( result, 0, 0, 1 ); 587 588 assertContains( result.getWarnings().get( 0 ), 589 "'dependencyManagement.dependencies.dependency.type' for test:a:jar must be 'pom'" ); 590 } 591 592 public void testBadImportScopeClassifier() 593 throws Exception 594 { 595 SimpleProblemCollector result = validateRaw( "bad-import-scope-classifier.xml" ); 596 597 assertViolations( result, 0, 1, 0 ); 598 599 assertContains( result.getErrors().get( 0 ), 600 "'dependencyManagement.dependencies.dependency.classifier' for test:a:pom:cls must be empty" ); 601 } 602 603 public void testSystemPathRefersToProjectBasedir() 604 throws Exception 605 { 606 SimpleProblemCollector result = validateRaw( "basedir-system-path.xml" ); 607 608 assertViolations( result, 0, 0, 2 ); 609 610 assertContains( result.getWarnings().get( 0 ), "'dependencies.dependency.systemPath' for test:a:jar " 611 + "should not point at files within the project directory" ); 612 assertContains( result.getWarnings().get( 1 ), "'dependencies.dependency.systemPath' for test:b:jar " 613 + "should not point at files within the project directory" ); 614 } 615 616 public void testMissingReportPluginVersion() 617 throws Exception 618 { 619 SimpleProblemCollector result = validate( "missing-report-version-pom.xml" ); 620 621 assertViolations( result, 0, 0, 0 ); 622 } 623}