blob: 4c46c06a441c4d17f7e18b3f7f1a7063768269f6 [file] [log] [blame]
package npanday.its;
/*
* 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 junit.framework.TestCase;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.it.VerificationException;
import org.apache.maven.it.Verifier;
import org.apache.maven.it.util.FileUtils;
import org.apache.maven.it.util.ResourceExtractor;
import org.apache.maven.it.util.cli.CommandLineException;
import org.apache.maven.it.util.cli.CommandLineUtils;
import org.apache.maven.it.util.cli.Commandline;
import org.apache.maven.it.util.cli.StreamConsumer;
import org.apache.maven.it.util.cli.WriterStreamConsumer;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipFile;
public abstract class AbstractNPandayIntegrationTestCase
extends TestCase
{
protected boolean skip;
protected String skipReason;
private static final String NPANDAY_MAX_FRAMEWORK_VERSION_PROPERTY = "npanday.framework.version";
private static final String NPANDAY_VERSION_SYSTEM_PROPERTY = "npanday.version";
protected static DefaultArtifactVersion version = checkVersion();
private static DefaultArtifactVersion frameworkVersion = checkFrameworkVersion();
private static boolean debugMaven = Boolean.valueOf( System.getProperty( "debug.maven", "false" ) );
private static boolean debugOutput = Boolean.valueOf( System.getProperty( "npanday.log.debug", "false" ) );
private static boolean forceVersion = Boolean.valueOf( System.getProperty( "npanday.version.force", "false" ) );
private static final Pattern PATTERN = Pattern.compile( "(.*?)-(RC[0-9]+|SNAPSHOT)" );
private static String disasmArg;
private static String disasmExec;
protected AbstractNPandayIntegrationTestCase()
{
this( "(0,)" );
}
protected AbstractNPandayIntegrationTestCase( String versionRangeStr )
{
VersionRange versionRange = createVersionRange(versionRangeStr);
if ( !checkNPandayVersion( versionRange, version ) && !forceVersion )
{
skip = true;
skipReason = "NPanday version " + version + " not in range " + versionRange;
}
}
protected static boolean checkNPandayVersion( VersionRange versionRange, DefaultArtifactVersion version )
{
String v = version.toString();
Matcher m = PATTERN.matcher(v);
if ( m.matches() )
{
return versionRange.containsVersion( new DefaultArtifactVersion( m.group( 1 ) ) );
}
else
{
return versionRange.containsVersion( version );
}
}
protected AbstractNPandayIntegrationTestCase( String versionRangeStr, String frameworkVersionStr )
{
this( versionRangeStr );
VersionRange versionRange = createVersionRange(frameworkVersionStr);
if ( frameworkVersion != null && !versionRange.containsVersion( frameworkVersion ) && !forceVersion )
{
skip = true;
skipReason = "Framework version " + frameworkVersion + " not in range " + versionRange;
}
}
private static DefaultArtifactVersion checkVersion()
{
DefaultArtifactVersion version = null;
String v = System.getProperty( NPANDAY_VERSION_SYSTEM_PROPERTY );
if ( v != null )
{
version = new DefaultArtifactVersion( v );
System.out.println( "Using NPanday version " + version );
}
else
{
System.out.println( "No NPanday version given" );
}
return version;
}
private static DefaultArtifactVersion checkFrameworkVersion()
{
DefaultArtifactVersion version = null;
String v = System.getProperty( NPANDAY_MAX_FRAMEWORK_VERSION_PROPERTY );
if ( v != null )
{
version = new DefaultArtifactVersion( v );
System.out.println( "Using Framework versions <= " + version );
}
else
{
// TODO: this is not necessarily accurate. While it gets all those available, the max should actually be
// the one in the path (which can be obtained from the output for csc, but there may be other better
// ways such as a small C# app to interrogate it.
// It may be best to have an NPanday plugin that can reveal it then call that first to set it,
// reusing the vendor info
File versions = new File( System.getenv( "systemroot" ) + "\\Microsoft.NET\\Framework" );
if ( versions.exists() )
{
List<DefaultArtifactVersion> frameworkVersions = new ArrayList<DefaultArtifactVersion>();
String[] list = versions.list( new java.io.FilenameFilter()
{
public boolean accept( File parent, String name )
{
File f = new File( parent, name );
// Mscorlib.dll can be used to detect 2.0 SDK, Microsoft.CompactFramework.Build.Tasks.dll for 3.5 SDK
// Having just the runtime (without these files) is not sufficient
return f.isDirectory() && ( new File( f, "Mscorlib.dll" ).exists() || new File( f,
"Microsoft.CompactFramework.Build.Tasks.dll" ).exists() );
}
} );
if ( list != null && list.length > 0 )
{
for ( String frameworkVersion : list )
{
frameworkVersions.add( new DefaultArtifactVersion( frameworkVersion ) );
}
Collections.sort( frameworkVersions );
System.out.println( "Available framework versions: " + frameworkVersions );
version = frameworkVersions.get( frameworkVersions.size() - 1 );
System.out.println( "Selected framework version: " + version );
}
}
if ( version == null )
{
System.out.println( "No Framework version given - attempting to use all" );
}
}
return version;
}
protected static VersionRange createVersionRange( String versionRangeStr )
{
VersionRange versionRange;
try
{
versionRange = VersionRange.createFromVersionSpec( versionRangeStr );
}
catch ( InvalidVersionSpecificationException e )
{
throw new RuntimeException( "Invalid version range: " + versionRangeStr + " - " + e.getMessage(), e );
}
return versionRange;
}
protected static void assertZipEntries( File zipFile, List<String> expectedEntries )
throws IOException
{
assertZipEntries( zipFile, expectedEntries, true );
}
protected static void assertNoZipEntries( File zipFile, List<String> unexpectedEntries )
throws IOException
{
assertZipEntries( zipFile, unexpectedEntries, false );
}
protected static void assertZipEntries( File zipFile, List<String> expectedEntries, boolean expected )
throws IOException
{
ZipFile zip = new ZipFile( zipFile );
try
{
for ( String name : expectedEntries )
{
if ( expected )
{
assertNotNull( "expected " + name + " to be present in zip", zip.getEntry( name ) );
}
else
{
assertNull( "expected " + name + " to be absent in zip", zip.getEntry( name ) );
}
}
}
finally
{
zip.close();
}
}
protected static String translateMsDeployPath( String basedir, String path )
{
String p = new File( new File( basedir, "target/packages" ), path ).getAbsolutePath();
p = p.replace( '\\', '/' );
p = "Content/C_C" + p.substring( 2 ); // transform C:
// Note: above is an assumption for where you can run these tests - not sure how other drive letters transformed
// by Web Deploy
return p;
}
protected void runTest()
throws Throwable
{
System.out.println();
System.out.print( String.format("%1$-70s", getITName() + "." + getName()));
if ( skip )
{
System.out.print( " Skipping (" + skipReason + ")" );
return;
}
try
{
super.runTest();
System.out.print( "OK" );
}
catch ( Throwable t )
{
// TODO: this actually never happens on my machine. me@lcorneliussen.de
System.out.print( "FAILURE" );
throw t;
}
}
private String getITName()
{
String simpleName = getClass().getSimpleName();
simpleName = simpleName.endsWith( "Test" ) ? simpleName.substring( 0, simpleName.length() - 4 ) : simpleName;
return simpleName;
}
protected Verifier getVerifier( File testDirectory )
throws VerificationException
{
Verifier verifier;
if ( debugMaven )
{
verifier = new Verifier( testDirectory.getAbsolutePath() ) {
public String getExecutable() { return super.getExecutable() + "Debug"; }
};
}
else
{
verifier = new Verifier( testDirectory.getAbsolutePath() );
}
List<String> cliOptions = new ArrayList<String>( 2 );
cliOptions.add( "-Dnpanday.version=" + version );
cliOptions.add( "-Dnpanday.settings=" + new File( testDirectory, "npanday-settings.xml" ).getAbsolutePath() );
if ( debugOutput )
{
cliOptions.add( "-X" );
}
verifier.setCliOptions( cliOptions );
return verifier;
}
protected String getCommentsFile()
{
return "target/comments.xml";
}
protected String getBuildSourcesGenerated( String fileName )
{
return getBuildFile("build-sources", fileName);
}
protected String getBuildFile( String buildDirectory, String fileName )
{
return "target/" + buildDirectory + "/" + fileName;
}
protected String getAssemblyFile( String assemblyName, String type )
{
return getAssemblyFile(assemblyName, null, type, null);
}
protected String getAssemblyFile( String assemblyName, String version, String type )
{
return getAssemblyFile(assemblyName, version, type, null);
}
protected String getAssemblyFile( String assemblyName, String version, String type, String classifier )
{
return getAssemblyFilePath( "target", assemblyName, type );
}
protected void clearRdfCache()
throws IOException
{
FileUtils.deleteDirectory(new File(System.getProperty("user.home"), ".m2/uac/rdfRepository"));
}
protected void deleteArtifact( Verifier verifier, String groupId, String artifactId, String version, String type )
throws IOException
{
FileUtils.deleteDirectory( new File( System.getProperty( "user.home" ), ".m2/uac/gac_msil/" + artifactId + "/" + version + "__" + groupId ) );
verifier.deleteArtifact(groupId, artifactId, version, type);
}
protected void assertSubsystem( String assembly, int subsystem )
throws VerificationException
{
assertEquals( "Subsystem was not " + subsystem + " as expected in assembly " + assembly, subsystem, getSubsystem( assembly ) );
}
private int getSubsystem( String assembly )
throws VerificationException
{
String output = runILDisasm( assembly );
for ( String line : output.split( "\n" ) )
{
line = line.trim();
if ( line.startsWith( ".subsystem 0x" ) )
{
String value = line.substring( 13, line.indexOf( ' ', 13 ) );
return Integer.parseInt( value );
}
}
throw new VerificationException( "Unable to determine subsystem" );
}
protected void assertClassPresent( String assembly, String className )
throws VerificationException
{
if ( !isClassPresent( assembly, className ) )
{
fail( "Unable to find class " + className + " in assembly " + assembly );
}
}
protected void assertClassNotPresent( String assembly, String className )
throws VerificationException
{
if ( isClassPresent( assembly, className ) )
{
fail( "Found unexpected class " + className + " in assembly " + assembly );
}
}
private boolean isClassPresent( String assembly, String className )
throws VerificationException
{
String output = runILDisasm( assembly );
String currentClassName = className;
int index = className.indexOf( '.' );
String namespace = index > 0 ? className.substring( 0, index ) : "";
for ( String line : output.split( "\n" ) )
{
line = line.trim();
// mono disassembles like this instead
if ( line.startsWith( ".namespace " + namespace ) )
{
currentClassName = className.substring( namespace.length() + 1 );
}
if ( line.startsWith( ".class " ) && line.endsWith( currentClassName ) )
{
return true;
}
}
return false;
}
private String runILDisasm( String assembly )
throws VerificationException
{
if ( disasmExec != null )
{
if ( disasmArg != null )
{
return execute( disasmExec, new String[]{disasmArg, assembly} );
}
else
{
return execute( disasmExec, new String[]{assembly} );
}
}
String value;
for (String path : new String[] { System.getenv("ProgramFiles"), System.getenv("ProgramFiles(x86)")}) {
File[] versions = new File(path, "Microsoft SDKs\\Windows").listFiles();
if (versions != null) {
for (File f : versions) {
File ildasm = new File(f, "bin\\ildasm.exe");
if (ildasm.exists()) {
disasmExec = ildasm.getAbsolutePath();
}
}
}
}
if (disasmExec != null) {
value = execute( disasmExec, new String[]{"/text", assembly} );
disasmArg = "/text";
}
else {
value = execute( "monodis", new String[]{assembly} );
disasmExec = "monodis";
disasmArg = null;
}
return value;
}
private String execute( String executable, String[] args )
throws VerificationException
{
try
{
Commandline cli = new Commandline();
cli.setExecutable( executable );
for ( String arg : args )
{
cli.createArgument().setValue( arg );
}
Writer logWriter = new StringWriter();
StreamConsumer out = new WriterStreamConsumer( logWriter );
StreamConsumer err = new WriterStreamConsumer( logWriter );
// System.err.println( "Command: " + Commandline.toString( cli.getCommandline() ) );
int ret = CommandLineUtils.executeCommandLine( cli, out, err );
logWriter.close();
String output = logWriter.toString();
if ( ret > 0 )
{
System.err.println( output );
throw new VerificationException( "Exit code: " + ret );
}
return output;
}
catch ( CommandLineException e )
{
throw new VerificationException( e );
}
catch ( IOException e )
{
throw new VerificationException( e );
}
}
protected String getTestAssemblyFile( String artifactId, String version, String type )
{
String basedir = "target/test-assemblies";
return getAssemblyFilePath(basedir, artifactId, type);
}
private String getAssemblyFilePath( String basedir, String artifactId, String type )
{
StringBuilder sb = new StringBuilder();
sb.append( basedir );
sb.append( "/" );
sb.append( artifactId );
sb.append( "." );
sb.append( type );
return sb.toString();
}
protected String getAssemblyResourceFile( String fileName )
{
return getBuildFile( "assembly-resources", fileName );
}
protected void assertResourcePresent( String assembly, String resource )
throws VerificationException
{
if ( !isResourcePresent( assembly, resource ) )
{
fail( "Unable to find resource " + resource + " in assembly " + assembly );
}
}
protected void assertResourcePresent( String assembly, String assemblyName, String resource )
throws VerificationException
{
if ( !isResourcePresent( assembly, assemblyName, resource ) )
{
fail( "Unable to find resource " + resource + " in assembly " + assembly );
}
}
private boolean isResourcePresent( String assembly, String resource )
throws VerificationException
{
return isResourcePresent(assembly, getAssemblyName(assembly), resource);
}
private boolean isResourcePresent( String assembly, String assemblyName, String resource )
throws VerificationException
{
String output = runILDisasm( assembly );
String prefix = ".mresource public ";
String value = assemblyName + "." + resource.replace( '/', '.' );
for ( String line : output.split( "\n" ) )
{
line = line.trim();
if ( line.startsWith( prefix ) )
{
line = line.substring( prefix.length() );
if ( line.equals( value ) || line.equals( "'" + value + "'" ) )
{
return true;
}
}
}
return false;
}
private String getAssemblyName( String assembly )
{
return assembly.substring( assembly.lastIndexOf( File.separatorChar ) + 1, assembly.lastIndexOf( '.' ) );
}
protected void assertPublicKey( String assembly )
throws VerificationException
{
if ( !hasPublicKey( assembly ) )
{
fail( "Couldn't find public key in assembly " + assembly );
}
}
private boolean hasPublicKey( String assembly )
throws VerificationException
{
String output = runILDisasm(assembly);
boolean insideCorrectAssembly = false;
for ( String line : output.split( "\n" ) )
{
if ( line.startsWith( ".assembly " + getAssemblyName( assembly ) ) )
{
insideCorrectAssembly = true;
}
else if ( line.startsWith( "}" ) )
{
insideCorrectAssembly = false;
}
else if ( insideCorrectAssembly && line.trim().startsWith( ".publickey" ) )
{
return true;
}
}
return false;
}
private String getAssemblyFrameworkVersion( File assembly )
throws VerificationException
{
String output = runILDisasm(assembly.getAbsolutePath());
String prefix = "// Metadata version: v";
for ( String line : output.split( "\n" ) )
{
line = line.trim();
if ( line.startsWith( prefix ) )
{
return line.substring( prefix.length() ).trim();
}
}
return null;
}
private boolean isAssemblyFrameworkVersion( File assembly, String versionRangeStr )
throws VerificationException
{
String frameworkVersion = getAssemblyFrameworkVersion( assembly );
VersionRange versionRange = createVersionRange( versionRangeStr );
return versionRange.containsVersion( new DefaultArtifactVersion( frameworkVersion ) );
}
protected void assertAssemblyFrameworkVersion( File assembly, String versionRangeStr )
throws VerificationException
{
String frameworkVersion = getAssemblyFrameworkVersion( assembly );
VersionRange versionRange = createVersionRange(versionRangeStr);
if ( !versionRange.containsVersion( new DefaultArtifactVersion( frameworkVersion ) ) )
{
fail( "Framework version " + frameworkVersion + " is not in range " + versionRangeStr );
}
}
protected static boolean checkNPandayVersion( String versionRangeStr )
{
return checkNPandayVersion( createVersionRange( versionRangeStr ), version ) || forceVersion;
}
protected NPandayIntegrationTestContext createDefaultTestContext()
throws IOException, VerificationException
{
NPandayIntegrationTestContext context = new NPandayIntegrationTestContext();
File testDir = ResourceExtractor.simpleExtractResources( getClass(), "/" + getClass().getSimpleName() );
context.setGroupId("NPanday.ITs." + getClass().getSimpleName());
context.setTestDir(testDir);
Verifier verifier = getVerifier( testDir );
verifier.deleteArtifacts( context.getGroupId() );
context.setVerifier(verifier);
return context;
}
protected void skipIfMissingGAC( String gac, String message )
{
File f = new File( System.getenv( "SYSTEMROOT" ), "assembly/GAC_MSIL/" + gac );
if ( !f.exists() || !f.isDirectory() )
{
skipReason = message;
skip = true;
}
}
protected void skipIfMissingProgramFilesDirectory( String directory, String message )
{
File f = new File( System.getenv( "PROGRAMFILES" ), directory );
if ( !f.exists() || !f.isDirectory() )
{
skipReason = message;
skip = true;
}
}
protected void skipIfMissingMSBuildTask( String path, String message )
{
File f = new File( System.getenv( "PROGRAMFILES" ), "MSBuild" );
f = new File( f, path );
if ( !f.exists() )
{
skipReason = message;
skip = true;
}
}
protected void skipIfXdtNotPresent()
{
File f = new File( System.getenv( "PROGRAMFILES" ), "MSBuild" );
f = new File( f, "Microsoft/VisualStudio" );
File[] versions = f.listFiles();
if ( versions != null ) {
for ( File v : versions )
{
if ( new File( v, "Web/Microsoft.Web.Publishing.Tasks.dll" ).exists() )
{
return;
}
}
}
skipReason = "Visual Studio 2010 (or above) with web platform is not installed";
skip = true;
}
protected void skipIfMissingWebDeployV2() {
skipIfMissingProgramFilesDirectory("IIS/Microsoft Web Deploy V2", "Web Deploy 2.0 not installed");
}
protected void skipIfMissingAzureSDK(String sdkVersion) {
if ("1.6".equals(sdkVersion)) {
skipIfMissingProgramFilesDirectory( "Windows Azure SDK", "Azure SDK is not installed" );
}
else if ("1.7".equals(sdkVersion)) {
skipIfMissingProgramFilesDirectory( "Microsoft SDKs\\Windows Azure\\.NET SDK\\2012-06", "Azure SDK is not installed" );
}
else {
throw new IllegalArgumentException("Unknown SDK version: " + sdkVersion);
}
}
protected void skipIfMissingMVC2() {
skipIfMissingGAC( "System.Web.MVC", "MVC.NET is not installed" );
}
}