blob: b52f4af170c7ea65727a01825ad4244e79a5d022 [file] [log] [blame]
package org.apache.maven.integrationtests;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.it.IntegrationTestException;
import org.apache.maven.it.IntegrationTestRunner;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.StringUtils;
/**
* This is a sample integration test. The IT tests typically
* operate by having a sample project in the
* /src/test/resources folder along with a junit test like
* this one. The junit test uses the itr (which uses
* the invoker) to invoke a new instance of Maven on the
* project in the resources folder. It then checks the
* results. This is a non-trivial example that shows two
* phases. See more information inline in the code.
*
* @author <a href="mailto:brianf@apache.org">Brian Fox</a>
*
*/
public class MavenITmng3415JunkRepositoryMetadataTest
extends AbstractMavenIntegrationTestCase
{
private static final String RESOURCE_BASE = "/mng-3415-junk-repository-metadata";
public MavenITmng3415JunkRepositoryMetadataTest()
throws InvalidVersionSpecificationException
{
// we're going to control the test execution according to the maven version present within each test method.
// all methods should execute as long as we're using maven 2.0.9+, but the specific tests may vary a little
// depending on which version we're using above 2.0.8.
super( "(2.0.8,)" ); // only test in 2.0.9+
}
/**
* This test simply verifies that when a metadata transfer fails (network error, etc.)
* no metadata file is written to the local repository.
*
* Steps executed to verify this test:
*
* 0. Find the local repository directory:
* a. build the maven-find-local-repo-plugin, then run it, to spit out the path of the
* local repository in use by default. Read the output file to get this path.
* (Yes, it's heavy, but it's reliable.)
* 1. Setup the test:
* a. Make sure the metadata for the test-repo is NOT in the local repository.
* b. Make sure the dependency POM IS in the local repository, so we're not
* distracted by failed builds that are unrelated.
* c. Create the settings file for use in this test, which contains the invalid
* remote repository entry.
* 2. Build the test project the first time
* a. Verify that a TransferFailedException is in the build output for the test-repo
* b. Verify that the metadata for the dependency POM is NOT in the local
* repository afterwards.
* 3. Build the test project the second time
* a. See (2.a) and (2.b) above; the same criteria applies here.
*/
public void testitMNG3415()
throws Exception
{
String methodName = getMethodName();
File testDir = extractTestResources( getClass(), RESOURCE_BASE );
File projectDir = new File( testDir, "project" );
File logFile = new File( projectDir, "log.txt" );
String proto = "invalid";
File settings = writeSettings( proto, testDir );
File localRepo = findLocalRepoDirectory();
setupDummyDependency( testDir, localRepo, true );
IntegrationTestRunner itr;
itr = new IntegrationTestRunner( projectDir.getAbsolutePath() );
List cliOptions = new ArrayList();
cliOptions.add( "-X" );
cliOptions.add( "-s" );
cliOptions.add( settings.getPath() );
itr.executeGoal( "package", cliOptions );
itr.verifyErrorFreeLog();
itr.resetStreams();
File firstLogFile = new File( testDir, "log-" + methodName + "-firstBuild.txt" );
logFile.renameTo( firstLogFile );
assertMetadataMissing( localRepo );
setupDummyDependency( testDir, localRepo, true );
itr.invoke( "package" );
itr.verifyErrorFreeLog();
itr.resetStreams();
File secondLogFile = new File( testDir, "log-" + methodName + "-secondBuild.txt" );
logFile.renameTo( secondLogFile );
assertMetadataMissing( localRepo );
}
private String getMethodName()
{
return new Throwable().getStackTrace()[1].getMethodName();
}
/**
* This test simply verifies that when metadata doesn't exist on the remote
* repository, a basic metadata file is written to the local repository.
*
* Steps executed to verify this test:
*
* 0. Find the local repository directory:
* a. build the maven-find-local-repo-plugin, then run it, to spit out the path of the
* local repository in use by default. Read the output file to get this path.
* (Yes, it's heavy, but it's reliable.)
* 1. Setup the test:
* a. Make sure the metadata for the test-repo is NOT in the local repository.
* b. Make sure the dependency POM IS in the local repository, so we're not
* distracted by failed builds that are unrelated.
* c. Create the settings file for use in this test, which contains the VALID
* remote repository entry.
* 2. Build the test project the first time
* a. Verify that a log message checking the remote repository for the metadata file
* is in the build output for the test-repo
* 3. Build the test project the second time
* a. Verify that a log message checking the remote repository for the metadata file
* IS NOT in the build output for the test-repo
* b. Verify that the file used for updateInterval calculations was NOT changed from
* the first build.
*
* @fixme: Find a better mechanism for testing this than matching console output!
*/
public void testShouldNotRepeatedlyUpdateOnResourceNotFoundException()
throws Exception
{
String methodName = getMethodName();
File testDir = extractTestResources( getClass(), RESOURCE_BASE );
File projectDir = new File( testDir, "project" );
File logFile = new File( projectDir, "log.txt" );
File settings = writeSettings( "file", testDir );
File localRepo = findLocalRepoDirectory();
setupDummyDependency( testDir, localRepo, true );
IntegrationTestRunner itr;
itr = new IntegrationTestRunner( projectDir.getAbsolutePath() );
List cliOptions = new ArrayList();
cliOptions.add( "-X" );
cliOptions.add( "-s" );
cliOptions.add( settings.getPath() );
itr.executeGoal( "package", cliOptions );
itr.verifyErrorFreeLog();
itr.resetStreams();
File firstLogFile = new File( testDir, "log-" + methodName + "-firstBuild.txt" );
logFile.renameTo( firstLogFile );
// FIXME: There really should be a better way than this!
assertOutputLinePresent( itr, firstLogFile, "snapshot tests:missing:1.0-SNAPSHOT: checking for updates from testing-repo" );
File updateCheckFile = getUpdateCheckFile( localRepo );
long firstLastMod = updateCheckFile.lastModified();
setupDummyDependency( testDir, localRepo, false );
itr.invoke( "package" );
itr.verifyErrorFreeLog();
itr.resetStreams();
File secondLogFile = new File( testDir, "log-" + methodName + "-secondBuild.txt" );
logFile.renameTo( secondLogFile );
// FIXME: There really should be a better way than this!
assertOutputLineMissing( itr, secondLogFile, "snapshot tests:missing:1.0-SNAPSHOT: checking for updates from testing-repo" );
assertEquals( "Last-modified time should be unchanged from first build through second build for the file we use for updateInterval checks.", firstLastMod, updateCheckFile.lastModified() );
}
private void assertMetadataMissing( File localRepo )
{
File metadata = getMetadataFile( localRepo );
assertFalse( "Metadata file should NOT be present in local repository: "
+ metadata.getAbsolutePath(), metadata.exists() );
}
private void setupDummyDependency( File testDir,
File localRepo,
boolean resetUpdateInterval )
throws IntegrationTestException, IOException
{
File metadata = getMetadataFile( localRepo );
if ( resetUpdateInterval && metadata.exists() )
{
System.out.println( "Deleting metadata file: " + metadata );
metadata.delete();
}
File resolverStatus = new File( metadata.getParentFile(), "resolver-status.properties" );
if ( resetUpdateInterval && resolverStatus.exists() )
{
System.out.println( "Deleting resolver-status.properties file related to: " + metadata );
resolverStatus.delete();
}
File dir = metadata.getParentFile();
System.out.println( "Setting up dependency POM in: " + dir );
File pom = new File( dir, "missing-1.0-SNAPSHOT.pom" );
if ( pom.exists() )
{
System.out.println( "Deleting pre-existing POM: " + pom );
pom.delete();
}
File pomSrc = new File( testDir, "dependency-pom.xml" );
System.out.println( "Copying dependency POM\nfrom: " + pomSrc + "\nto: " + pom );
FileUtils.copyFile( pomSrc, pom );
}
private File getMetadataFile( File localRepo )
{
File dir = new File( localRepo, "tests/missing/1.0-SNAPSHOT" );
dir.mkdirs();
return new File( dir, "maven-metadata-testing-repo.xml" );
}
/**
* If the current maven version is < 2.1, we'll use the metadata file itself (old maven-artifact code)...
* otherwise, use the new resolver-status.properties file (new artifact code).
*/
private File getUpdateCheckFile( File localRepo )
throws InvalidVersionSpecificationException
{
File dir = new File( localRepo, "tests/missing/1.0-SNAPSHOT" );
dir.mkdirs();
if ( matchesVersionRange( "(2.0.8,2.1-SNAPSHOT)" ) )
{
return new File( dir, "maven-metadata-testing-repo.xml" );
}
else
{
return new File( dir, "resolver-status.properties" );
}
}
private File findLocalRepoDirectory()
throws IntegrationTestException, IOException
{
File testDir = extractTestResources( getClass(),
RESOURCE_BASE
+ "/maven-find-local-repo-plugin" );
IntegrationTestRunner itr = new IntegrationTestRunner( testDir.getAbsolutePath() );
itr.deleteArtifact( "org.apache.maven.plugins", "maven-find-local-repo-plugin", "1.0-SNAPSHOT", "jar" );
itr.invoke( "install" );
itr.verifyErrorFreeLog();
itr.resetStreams();
itr.invoke( "find-local-repo:find" );
itr.verifyErrorFreeLog();
itr.resetStreams();
List lines = itr.loadFile( new File( testDir, "target/local-repository-location.txt" ),
false );
File localRepo = new File( (String) lines.get( 0 ) );
System.out.println( "Using local repository at: " + localRepo );
return localRepo;
}
private File writeSettings( String repositoryProtocol,
File testDir )
throws IOException
{
File settingsIn = new File( testDir, "settings.xml.in" );
String settingsContent = null;
Reader reader = null;
try
{
reader = new FileReader( settingsIn );
settingsContent = IOUtil.toString( reader );
}
finally
{
IOUtil.close( reader );
}
settingsContent = StringUtils.replace( settingsContent, "@PROTO@", repositoryProtocol );
settingsContent = StringUtils.replace( settingsContent,
"@TESTDIR@",
testDir.getAbsolutePath() );
File settingsOut = new File( testDir, "settings.xml" );
System.out.println( "Writing tets settings to: " + settingsOut );
if ( settingsOut.exists() )
{
settingsOut.delete();
}
Writer writer = null;
try
{
writer = new FileWriter( settingsOut );
IOUtil.copy( settingsContent, writer );
}
finally
{
IOUtil.close( writer );
}
return settingsOut;
}
private void assertOutputLinePresent( IntegrationTestRunner itr,
File logFile,
String lineContents )
throws IntegrationTestException
{
List lines = itr.loadFile( logFile, false );
boolean found = false;
for ( Iterator it = lines.iterator(); it.hasNext(); )
{
String line = (String) it.next();
if ( line.indexOf( lineContents ) > -1 )
{
found = true;
break;
}
}
assertTrue( "Build output in:\n\n" + logFile + "\n\nshould contain line with contents:\n\n" + lineContents + "\n", found );
}
private void assertOutputLineMissing( IntegrationTestRunner itr,
File logFile,
String lineContents )
throws IntegrationTestException
{
List lines = itr.loadFile( logFile, false );
boolean found = false;
for ( Iterator it = lines.iterator(); it.hasNext(); )
{
String line = (String) it.next();
if ( line.indexOf( lineContents ) > -1 )
{
found = true;
break;
}
}
assertFalse( "Build output in:\n\n" + logFile + "\n\nshould NOT contain line with contents:\n\n" + lineContents + "\n", found );
}
}