/*
* Copyright (c) 2014 the original author or authors
*
* Licensed 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.
*/
package io.werval.maven;
import io.werval.runtime.util.Holder;
import io.werval.test.util.Processes;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.Arrays;
import org.apache.maven.shared.invoker.DefaultInvocationRequest;
import org.apache.maven.shared.invoker.DefaultInvoker;
import org.apache.maven.shared.invoker.InvocationRequest;
import org.apache.maven.shared.invoker.InvocationResult;
import org.apache.maven.shared.invoker.InvokerLogger;
import org.apache.maven.shared.invoker.PrintStreamLogger;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.rules.TemporaryFolder;
import static io.werval.api.BuildVersion.VERSION;
/**
* Base class for run goals integration tests.
* <p>
* Deploy a test project into a temporary folder, gracefully shutdown devshell if running, provide base code for
* parallel maven invocation etc...
*/
public abstract class AbstractRunGoalIT
{
protected static final Charset UTF_8 = Charset.forName( "UTF-8" );
private static final String POM;
private static final String ROUTES;
private static final String CONFIG;
private static final String CONTROLLER;
protected static final String CONTROLLER_CHANGED;
protected static final File BASEDIR = new File( System.getProperty( "project.basedir", "" ) );
static
{
POM
= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n"
+ " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
+ " xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n"
+ " <modelVersion>4.0.0</modelVersion>\n"
+ "\n"
+ " <groupId>io.werval.maven.test</groupId>\n"
+ " <artifactId>io.werval.maven.test.unit</artifactId>\n"
+ " <version>" + VERSION + "</version>\n"
+ "\n"
+ " <properties>\n"
+ " <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n"
+ " <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>\n"
+ " </properties>\n"
+ "\n"
+ " <build>\n"
+ " <plugins>\n"
+ " <plugin>\n"
+ " <groupId>io.werval</groupId>\n"
+ " <artifactId>io.werval.maven</artifactId>\n"
+ " <version>" + VERSION + "</version>\n"
+ " <configuration>\n"
+ " <openBrowser>false</openBrowser>\n"
+ " <configResource>application-custom.conf</configResource>\n"
+ " <extraClassPath>\n"
+ " <param>src/main/custom</param>\n"
+ " </extraClassPath>\n"
+ " </configuration>\n"
+ " </plugin>\n"
+ " <plugin>\n"
+ " <artifactId>maven-resources-plugin</artifactId>\n"
+ " <version>2.6</version>\n"
+ " </plugin>\n"
+ " <plugin>\n"
+ " <artifactId>maven-compiler-plugin</artifactId>\n"
+ " <version>3.1</version>\n"
+ " </plugin>\n"
+ " <plugin>\n"
+ " <artifactId>maven-surefire-plugin</artifactId>\n"
+ " <version>2.17</version>\n"
+ " </plugin>\n"
+ " <plugin>\n"
+ " <artifactId>maven-jar-plugin</artifactId>\n"
+ " <version>2.4</version>\n"
+ " </plugin>\n"
+ " </plugins>\n"
+ " </build>\n"
+ " \n"
+ " <dependencies>\n"
+ " <dependency>\n"
+ " <groupId>io.werval</groupId>\n"
+ " <artifactId>io.werval.api</artifactId>\n"
+ " <version>" + VERSION + "</version>\n"
+ " </dependency>\n"
+ " <dependency>\n"
+ " <groupId>io.werval</groupId>\n"
+ " <artifactId>io.werval.server.bootstrap</artifactId>\n"
+ " <version>" + VERSION + "</version>\n"
+ " <scope>runtime</scope>\n"
+ " </dependency>\n"
+ " <dependency>\n"
+ " <groupId>org.slf4j</groupId>\n"
+ " <artifactId>slf4j-simple</artifactId>\n"
+ " <version>1.7.12</version>\n"
+ " <scope>runtime</scope>\n"
+ " </dependency>\n"
+ " </dependencies>\n"
+ " \n"
+ "</project>\n";
CONFIG
= "app {\n"
+ " secret = e6bcdba3bc6840aa08013ef20505a0c27f800dbbcced6fbb71e8cf197fe83866\n"
+ "}\n";
ROUTES = "GET / controllers.Application.index";
CONTROLLER
= "package controllers;\n"
+ "import io.werval.api.outcomes.Outcome;\n"
+ "import static io.werval.api.context.CurrentContext.outcomes;\n"
+ "public class Application\n"
+ "{\n"
+ " public Outcome index()\n"
+ " {\n"
+ " return outcomes().ok( \"I ran!\" ).build();\n"
+ " }\n"
+ "}\n";
CONTROLLER_CHANGED
= "package controllers;\n"
+ "import io.werval.api.outcomes.Outcome;\n"
+ "import static io.werval.api.context.CurrentContext.outcomes;\n"
+ "public class Application\n"
+ "{\n"
+ " public Outcome index()\n"
+ " {\n"
+ " return outcomes().ok( \"I ran changed!\" ).build();\n"
+ " }\n"
+ "}\n";
new File( BASEDIR, "target/it-tmp" ).mkdirs();
}
@ClassRule
public static TemporaryFolder tmp = new TemporaryFolder( new File( BASEDIR, "target/it-tmp" ) )
{
@Override
public void delete()
{
// NOOP
}
};
protected static File lock;
@BeforeClass
public static void setupProjectLayout()
throws IOException
{
Files.write(
new File( tmp.getRoot(), "pom.xml" ).toPath(),
POM.getBytes( UTF_8 )
);
File custom = new File( tmp.getRoot(), "src/main/custom" );
Files.createDirectories( custom.toPath() );
Files.write(
new File( custom, "application-custom.conf" ).toPath(),
CONFIG.getBytes( UTF_8 )
);
File resources = new File( tmp.getRoot(), "src/main/resources" );
Files.createDirectories( resources.toPath() );
Files.write(
new File( resources, "routes.conf" ).toPath(),
ROUTES.getBytes( UTF_8 )
);
File controllers = new File( tmp.getRoot(), "src/main/java/controllers" );
Files.createDirectories( controllers.toPath() );
Files.write(
new File( controllers, "Application.java" ).toPath(),
CONTROLLER.getBytes( UTF_8 )
);
lock = new File( tmp.getRoot(), ".devshell.lock" );
}
@AfterClass
public static void killZombies()
throws Exception
{
try
{
String self = Processes.currentPID( "NO_PID" );
Processes.killJvms(
line -> line.contains( "org.codehaus.plexus.classworlds.launcher.Launcher" )
&& !line.startsWith( self )
);
}
finally
{
if( lock.exists() )
{
Files.delete( lock.toPath() );
}
}
}
protected final Runnable newRunnable( Holder<Exception> errorHolder, String... goals )
{
return () ->
{
try
{
DefaultInvoker invoker = new DefaultInvoker();
invoker.setLocalRepositoryDirectory( new File( BASEDIR, "target/it-local-repository" ) );
invoker.setWorkingDirectory( tmp.getRoot() );
invoker.setLogger( new PrintStreamLogger( System.err, InvokerLogger.INFO ) );
InvocationRequest request = new DefaultInvocationRequest();
request.setOffline( true );
request.setPomFile( new File( tmp.getRoot(), "pom.xml" ) );
request.setGoals( Arrays.asList( goals ) );
InvocationResult result = invoker.execute( request );
if( result.getExecutionException() != null )
{
errorHolder.set( result.getExecutionException() );
}
else if( result.getExitCode() != 0 )
{
errorHolder.set(
new RuntimeException( "Maven invocation failure, exit code was: " + result.getExitCode() )
);
}
}
catch( Exception ex )
{
errorHolder.set( ex );
}
};
}
}