blob: ccdadbfcfc4787882b22a8361da932ec895d7687 [file] [log] [blame]
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 ---*/
}