| package org.apache.maven.artifact.repository.metadata; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import static org.junit.jupiter.api.Assertions.assertEquals; |
| import static org.junit.jupiter.api.Assertions.assertFalse; |
| import static org.junit.jupiter.api.Assertions.assertTrue; |
| |
| import java.text.DateFormat; |
| import java.text.SimpleDateFormat; |
| import java.util.Date; |
| import java.util.GregorianCalendar; |
| import java.util.TimeZone; |
| |
| import org.eclipse.aether.artifact.Artifact; |
| import org.eclipse.aether.artifact.DefaultArtifact; |
| import org.junit.jupiter.api.BeforeEach; |
| import org.junit.jupiter.api.Test; |
| |
| class MetadataTest |
| { |
| |
| Artifact artifact; |
| |
| Metadata target; |
| |
| @BeforeEach |
| void before() |
| { |
| artifact = new DefaultArtifact( "myGroup:myArtifact:1.0-SNAPSHOT" ); |
| target = createMetadataFromArtifact( artifact ); |
| } |
| |
| /*--- START test common metadata ---*/ |
| @Test |
| void mergeEmptyMetadata() |
| throws Exception |
| { |
| Metadata metadata = new Metadata(); |
| assertFalse( metadata.merge( new Metadata() ) ); |
| } |
| |
| @Test |
| void mergeDifferentGAV() |
| throws Exception |
| { |
| // merge implicitly assumes that merge is only called on the same GAV and does not perform any validation here! |
| Metadata source = new Metadata(); |
| source.setArtifactId( "source-artifact" ); |
| source.setGroupId( "source-group" ); |
| source.setVersion( "2.0" ); |
| assertFalse( target.merge( source ) ); |
| assertEquals( "myArtifact", target.getArtifactId() ); |
| assertEquals( "myGroup", target.getGroupId() ); |
| assertEquals( "1.0-SNAPSHOT", target.getVersion() ); |
| } |
| /*--- END test common metadata ---*/ |
| |
| /*--- START test "groupId/artifactId/version" metadata ---*/ |
| @Test |
| void mergeSnapshotWithEmptyList() |
| throws Exception |
| { |
| Snapshot snapshot = new Snapshot(); |
| snapshot.setBuildNumber( 3 ); |
| snapshot.setTimestamp( "20200710.072412" ); |
| target.getVersioning().setSnapshot( snapshot ); |
| target.getVersioning().setLastUpdated( "20200921071745" ); |
| SnapshotVersion sv = new SnapshotVersion(); |
| sv.setClassifier( "sources" ); |
| sv.setExtension( "jar" ); |
| sv.setUpdated( "20200710072412" ); |
| target.getVersioning().addSnapshotVersion( sv ); |
| |
| Metadata source = createMetadataFromArtifact( artifact ); |
| // nothing should be actually changed, but still merge returns true |
| assertTrue( target.merge( source ) ); |
| |
| // NOTE! Merge updates last updated to source |
| assertEquals( "20200921071745", source.getVersioning().getLastUpdated() ); |
| |
| assertEquals( "myArtifact", target.getArtifactId() ); |
| assertEquals( "myGroup", target.getGroupId() ); |
| |
| assertEquals( 3, target.getVersioning().getSnapshot().getBuildNumber() ); |
| assertEquals( "20200710.072412", target.getVersioning().getSnapshot().getTimestamp() ); |
| |
| assertEquals( 1, target.getVersioning().getSnapshotVersions().size() ); |
| assertEquals( "sources", target.getVersioning().getSnapshotVersions().get( 0 ).getClassifier() ); |
| assertEquals( "jar", target.getVersioning().getSnapshotVersions().get( 0 ).getExtension() ); |
| assertEquals( "20200710072412", target.getVersioning().getSnapshotVersions().get( 0 ).getUpdated() ); |
| } |
| |
| @Test |
| void mergeWithSameSnapshotWithDifferentVersionsAndNewerLastUpdated() |
| { |
| Metadata source = createMetadataFromArtifact( artifact ); |
| Date before = new Date( System.currentTimeMillis() - 5000 ); |
| Date after = new Date( System.currentTimeMillis() ); |
| addSnapshotVersion( target.getVersioning(), "jar", before, "1", 1 ); |
| SnapshotVersion sv2 = |
| addSnapshotVersion( source.getVersioning(), "jar", after, "1.0-" + formatDate( after, true ) + "-2", 2 ); |
| SnapshotVersion sv3 = |
| addSnapshotVersion( source.getVersioning(), "pom", after, "1.0-" + formatDate( after, true ) + "-2", 2 ); |
| assertTrue( target.merge( source ) ); |
| Versioning actualVersioning = target.getVersioning(); |
| assertEquals( 2, actualVersioning.getSnapshotVersions().size() ); |
| assertEquals( sv2, actualVersioning.getSnapshotVersions().get( 0 ) ); |
| assertEquals( sv3, actualVersioning.getSnapshotVersions().get( 1 ) ); |
| assertEquals( formatDate( after, false ), actualVersioning.getLastUpdated() ); |
| assertEquals( formatDate( after, true ), actualVersioning.getSnapshot().getTimestamp() ); |
| assertEquals( 2, actualVersioning.getSnapshot().getBuildNumber() ); |
| } |
| |
| @Test |
| void mergeWithSameSnapshotWithDifferentVersionsAndOlderLastUpdated() |
| { |
| Metadata source = createMetadataFromArtifact( artifact ); |
| Date before = new Date( System.currentTimeMillis() - 5000 ); |
| Date after = new Date( System.currentTimeMillis() ); |
| SnapshotVersion sv1 = addSnapshotVersion( target.getVersioning(), after, artifact ); |
| addSnapshotVersion( source.getVersioning(), before, artifact ); |
| // nothing should be updated, as the target was already updated at a later date than source |
| assertFalse( target.merge( source ) ); |
| assertEquals( 1, target.getVersioning().getSnapshotVersions().size() ); |
| assertEquals( sv1, target.getVersioning().getSnapshotVersions().get( 0 ) ); |
| assertEquals( formatDate( after, false ), target.getVersioning().getLastUpdated() ); |
| assertEquals( formatDate( after, true ), target.getVersioning().getSnapshot().getTimestamp() ); |
| } |
| |
| @Test |
| void mergeWithSameSnapshotWithSameVersionAndTimestamp() |
| { |
| Metadata source = createMetadataFromArtifact( artifact ); |
| Date date = new Date(); |
| addSnapshotVersion( target.getVersioning(), date, artifact ); |
| SnapshotVersion sv1 = addSnapshotVersion( source.getVersioning(), date, artifact ); |
| // although nothing has changed merge returns true, as the last modified date is equal |
| // TODO: improve merge here? |
| assertTrue( target.merge( source ) ); |
| assertEquals( 1, target.getVersioning().getSnapshotVersions().size() ); |
| assertEquals( sv1, target.getVersioning().getSnapshotVersions().get( 0 ) ); |
| assertEquals( formatDate( date, false ), target.getVersioning().getLastUpdated() ); |
| assertEquals( formatDate( date, true ), target.getVersioning().getSnapshot().getTimestamp() ); |
| } |
| |
| @Test |
| void mergeLegacyWithSnapshotLegacy() |
| { |
| Metadata source = createMetadataFromArtifact( artifact ); |
| Date before = new Date( System.currentTimeMillis() - 5000 ); |
| Date after = new Date( System.currentTimeMillis() ); |
| // legacy metadata did not have "versioning.snapshotVersions" |
| addSnapshotVersionLegacy( target.getVersioning(), before, 1 ); |
| addSnapshotVersionLegacy( source.getVersioning(), after, 2 ); |
| // although nothing has changed merge returns true, as the last modified date is equal |
| // TODO: improve merge here? |
| assertTrue( target.merge( source ) ); |
| assertEquals( 0, target.getVersioning().getSnapshotVersions().size() ); |
| assertEquals( formatDate( after, false ), target.getVersioning().getLastUpdated() ); |
| assertEquals( formatDate( after, true ), target.getVersioning().getSnapshot().getTimestamp() ); |
| } |
| |
| @Test |
| void mergeLegacyWithSnapshot() |
| { |
| Metadata source = createMetadataFromArtifact( artifact ); |
| Date before = new Date( System.currentTimeMillis() - 5000 ); |
| Date after = new Date( System.currentTimeMillis() ); |
| // legacy metadata did not have "versioning.snapshotVersions" |
| addSnapshotVersionLegacy( target.getVersioning(), before, 1 ); |
| addSnapshotVersion( source.getVersioning(), after, artifact ); |
| // although nothing has changed merge returns true, as the last modified date is equal |
| // TODO: improve merge here? |
| assertTrue( target.merge( source ) ); |
| // never convert from legacy format to v1.1 format |
| assertEquals( 0, target.getVersioning().getSnapshotVersions().size() ); |
| assertEquals( formatDate( after, false ), target.getVersioning().getLastUpdated() ); |
| assertEquals( formatDate( after, true ), target.getVersioning().getSnapshot().getTimestamp() ); |
| } |
| |
| @Test |
| void mergeWithSnapshotLegacy() |
| { |
| Metadata source = createMetadataFromArtifact( artifact ); |
| Date before = new Date( System.currentTimeMillis() - 5000 ); |
| Date after = new Date( System.currentTimeMillis() ); |
| addSnapshotVersion( target.getVersioning(), before, artifact ); |
| // legacy metadata did not have "versioning.snapshotVersions" |
| addSnapshotVersionLegacy( source.getVersioning(), after, 2 ); |
| // although nothing has changed merge returns true, as the last modified date is equal |
| // TODO: improve merge here? |
| assertTrue( target.merge( source ) ); |
| // the result must be legacy format as well |
| assertEquals( 0, target.getVersioning().getSnapshotVersions().size() ); |
| assertEquals( formatDate( after, false ), target.getVersioning().getLastUpdated() ); |
| assertEquals( formatDate( after, true ), target.getVersioning().getSnapshot().getTimestamp() ); |
| assertEquals( 2, target.getVersioning().getSnapshot().getBuildNumber() ); |
| } |
| /*-- END test "groupId/artifactId/version" metadata ---*/ |
| |
| /*-- START helper methods to populate metadata objects ---*/ |
| private static final String SNAPSHOT = "SNAPSHOT"; |
| |
| private static final String DEFAULT_SNAPSHOT_TIMESTAMP_FORMAT = "yyyyMMdd.HHmmss"; |
| |
| private static final String DEFAULT_DATE_FORMAT = "yyyyMMddHHmmss"; |
| |
| private static String formatDate( Date date, boolean forSnapshotTimestamp ) |
| { |
| // logic from metadata.mdo, class "Versioning" |
| TimeZone timezone = TimeZone.getTimeZone( "UTC" ); |
| DateFormat fmt = |
| new SimpleDateFormat( forSnapshotTimestamp ? DEFAULT_SNAPSHOT_TIMESTAMP_FORMAT : DEFAULT_DATE_FORMAT ); |
| fmt.setCalendar( new GregorianCalendar() ); |
| fmt.setTimeZone( timezone ); |
| return fmt.format( date ); |
| } |
| |
| private static Metadata createMetadataFromArtifact( Artifact artifact ) |
| { |
| Metadata metadata = new Metadata(); |
| metadata.setArtifactId( artifact.getArtifactId() ); |
| metadata.setGroupId( artifact.getGroupId() ); |
| metadata.setVersion( artifact.getVersion() ); |
| metadata.setVersioning( new Versioning() ); |
| return metadata; |
| } |
| |
| private static SnapshotVersion addSnapshotVersion( Versioning versioning, Date timestamp, Artifact artifact ) |
| { |
| int buildNumber = 1; |
| // this generates timestamped versions like maven-resolver-provider: |
| // https://github.com/apache/maven/blob/03df5f7c639db744a3597c7175c92c8e2a27767b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/RemoteSnapshotMetadata.java#L79 |
| String version = artifact.getVersion(); |
| String qualifier = formatDate( timestamp, true ) + '-' + buildNumber; |
| version = version.substring( 0, version.length() - SNAPSHOT.length() ) + qualifier; |
| return addSnapshotVersion( versioning, artifact.getExtension(), timestamp, version, buildNumber ); |
| } |
| |
| private static SnapshotVersion addSnapshotVersion( Versioning versioning, String extension, Date timestamp, |
| String version, int buildNumber ) |
| { |
| Snapshot snapshot = new Snapshot(); |
| snapshot.setBuildNumber( buildNumber ); |
| snapshot.setTimestamp( formatDate( timestamp, true ) ); |
| |
| SnapshotVersion sv = new SnapshotVersion(); |
| sv.setExtension( extension ); |
| sv.setVersion( version ); |
| sv.setUpdated( formatDate( timestamp, false ) ); |
| versioning.addSnapshotVersion( sv ); |
| |
| // make the new snapshot the current one |
| versioning.setSnapshot( snapshot ); |
| versioning.setLastUpdatedTimestamp( timestamp ); |
| return sv; |
| } |
| |
| // the format written by Maven 2 |
| // (https://maven.apache.org/ref/2.2.1/maven-repository-metadata/repository-metadata.html) |
| private static void addSnapshotVersionLegacy( Versioning versioning, Date timestamp, int buildNumber ) |
| { |
| Snapshot snapshot = new Snapshot(); |
| snapshot.setBuildNumber( buildNumber ); |
| snapshot.setTimestamp( formatDate( timestamp, true ) ); |
| |
| versioning.setSnapshot( snapshot ); |
| versioning.setLastUpdatedTimestamp( timestamp ); |
| } |
| /*-- END helper methods to populate metadata objects ---*/ |
| } |