Skip to content

Commit

Permalink
HV-913 Providing new profile for the "tck-runner" module for executin…
Browse files Browse the repository at this point in the history
…g the TCK with a security manager enabled
  • Loading branch information
gunnarmorling authored and hferentschik committed Feb 10, 2015
1 parent 88c6d44 commit a1aed64
Show file tree
Hide file tree
Showing 12 changed files with 524 additions and 8 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -78,7 +78,7 @@ You will also need a JDK 8 and Maven 3 (>= 3.0.3). With these prerequisites in p

mvn clean install -s settings-example.xml

There are more build options available as well. For more information refer to [Contributing to Hibernate Validator](http://community.jboss.org/wiki/ContributingtoHibernateValidator).
There are more build options available as well. For more information refer to [Contributing to Hibernate Validator](http://hibernate.org/validator/contribute/).

## Hibernate Validator URLs

Expand Down
31 changes: 24 additions & 7 deletions tck-runner/pom.xml
Expand Up @@ -22,7 +22,6 @@
<properties>
<tck.version>1.1.2.Final</tck.version>
<tck.suite.file>${project.build.directory}/dependency/beanvalidation-tck-tests-suite.xml</tck.suite.file>
<arquillian.version>1.0.0.Final</arquillian.version>
<wildflyTargetDir>${project.build.directory}/wildfly-${wildfly.version}</wildflyTargetDir>
<validation.provider>org.hibernate.validator.HibernateValidator</validation.provider>
<remote.debug />
Expand Down Expand Up @@ -66,13 +65,11 @@
<dependency>
<groupId>org.jboss.arquillian.testng</groupId>
<artifactId>arquillian-testng-container</artifactId>
<version>${arquillian.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.protocol</groupId>
<artifactId>arquillian-protocol-servlet</artifactId>
<version>${arquillian.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand Down Expand Up @@ -168,7 +165,8 @@
</property>
</activation>
<properties>
<arquillian.protocol>Local</arquillian.protocol>
<!-- The properties "arquillian.protocol" and "surefire.argLine" are set based on this setting via GMaven-->
<with-security-manager>true</with-security-manager>
</properties>
<dependencies>
<dependency>
Expand All @@ -179,6 +177,26 @@
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<executions>
<execution>
<id>configure-properties</id>
<phase>validate</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source><![CDATA[
project.properties['arquillian.protocol'] = Boolean.valueOf(pom.properties['with-security-manager']) ? 'LocalSecurityManagerTesting' : 'Local';
project.properties['surefire.argLine'] = Boolean.valueOf(pom.properties['with-security-manager']) ? '-Djava.security.manager -Djava.security.policy=${project.build.directory}/test-classes/test.policy -Djava.security.debug=access' : '';
]]>
</source>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
Expand All @@ -193,6 +211,7 @@
<value>true</value>
</property>
</systemProperties>
<argLine>${surefire.argLine}</argLine>
</configuration>
</plugin>
</plugins>
Expand All @@ -206,9 +225,7 @@
</property>
</activation>
<properties>
<remote.debug>-Xnoagent -Djava.compiler=NONE -Xdebug
-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005
</remote.debug>
<remote.debug>-Xnoagent -Djava.compiler=NONE -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005</remote.debug>
</properties>
</profile>
<profile>
Expand Down
10 changes: 10 additions & 0 deletions tck-runner/readme.md
Expand Up @@ -10,6 +10,16 @@ used when running

$ mvn clean test

By default this will run the tests with a security manager enabled in order to make sure Hibernate Validator invokes
security-relevant APIs using privileged actions. You can run the tests without the security manager e.g. for analysis
purposes like this:

$ mvn clean test -Dwith-security-manager=false

The policy file is located at src/test/resources/test.policy. You may need to adapt the URL of the Hibernate Validator
engine entry depending on your specific set-up, e.g. when obtaining these classes from engine/target/classes while
running the tests from within an IDE.

## In container

You can also run the TCK test against Wildfly. In this case the tests are bundled as war files and executed
Expand Down
@@ -0,0 +1,34 @@
/*
* Hibernate Validator, declare and validate application constraints
*
* License: Apache License, Version 2.0
* See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
*/
package org.hibernate.validator.tckrunner.securitymanager;

/**
* Executes a given operation.
* <p>
* The whole purpose of this class is to establish a frame on the stack which is as close as possible to the running
* tests and whose protection domain has no permissions at all. It is separated from the other Arquillian-related
* classes which need special permissions on their own.
* <p>
* This will reveal any invocation of security-relevant methods in the HV code base which don't make use of a
* do-privileged block.
*
* @author Gunnar Morling
*
*/
public class DelegatingExecutor implements Executor {

private final Executor delegate;

public DelegatingExecutor(Executor delegate) {
this.delegate = delegate;
}

@Override
public void invoke(Object... parameters) throws Throwable {
delegate.invoke( parameters );
}
}
@@ -0,0 +1,18 @@
/*
* Hibernate Validator, declare and validate application constraints
*
* License: Apache License, Version 2.0
* See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
*/
package org.hibernate.validator.tckrunner.securitymanager;

/**
* Executes a given operation.
*
* @author Gunnar Morling
*
*/
public interface Executor {

void invoke(Object... parameters) throws Throwable;
}
@@ -0,0 +1,73 @@
/*
* Hibernate Validator, declare and validate application constraints
*
* License: Apache License, Version 2.0
* See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
*/
package org.hibernate.validator.tckrunner.securitymanager;

import java.util.Collections;
import java.util.List;

import org.hibernate.beanvalidation.tck.util.IntegrationTestsMethodSelector;
import org.testng.ITestResult;
import org.testng.TestListenerAdapter;
import org.testng.TestNG;
import org.testng.xml.XmlMethodSelector;
import org.testng.xml.XmlPackage;
import org.testng.xml.XmlSuite;
import org.testng.xml.XmlTest;

/**
* Main class for running the test suite programmatically, for debugging purposes.
* <p>
* Specify the following arguments when running this test:
* <pre>
* -Dvalidation.provider=org.hibernate.validator.HibernateValidator
* -Djava.security.manager=default
* -Djava.security.policy=target/test-classes/test.policy
* -Djava.security.debug=access
* -DexcludeIntegrationTests=true
* -Darquillian.protocol=LocalSecurityManagerTesting
* -Dorg.jboss.testharness.spi.StandaloneContainers=org.hibernate.jsr303.tck.util.StandaloneContainersImpl
* </pre>
*
* @author Gunnar Morling
*/
public class TckRunner {

public static void main(String[] args) {
XmlSuite suite = new XmlSuite();
suite.setName( "JSR-349-TCK" );

XmlTest test = new XmlTest(suite);
test.setName("JSR-349-TCK");

List<XmlPackage> packages = Collections.singletonList( new XmlPackage( "org.hibernate.beanvalidation.tck.tests" ) );
test.setXmlPackages( packages );

// Alternatively e.g. use this for running single tests
// List<XmlClass> classes = Collections.singletonList( new XmlClass( ValidateTest.class ) );
// test.setXmlClasses( classes );

XmlMethodSelector selector = new XmlMethodSelector();
selector.setClassName( IntegrationTestsMethodSelector.class.getName() );
test.setMethodSelectors( Collections.singletonList( selector ) );

TestListenerAdapter tla = new TestListenerAdapter();
TestNG testng = new TestNG();
testng.setXmlSuites( Collections.singletonList( suite ) );
testng.addListener(tla);
testng.run();

for ( ITestResult failure: tla.getConfigurationFailures() ) {
System.out.println( "Failure: " + failure.getName() );
failure.getThrowable().printStackTrace();
}

for ( ITestResult result : tla.getFailedTests() ) {
System.out.println( "Failed:" + result.getName() );
result.getThrowable().printStackTrace();
}
}
}
@@ -0,0 +1,34 @@
/*
* Hibernate Validator, declare and validate application constraints
*
* License: Apache License, Version 2.0
* See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
*/
package org.hibernate.validator.tckrunner.securitymanager.arquillian;

import org.jboss.arquillian.container.test.spi.ContainerMethodExecutor;
import org.jboss.arquillian.core.api.Event;
import org.jboss.arquillian.core.api.Instance;
import org.jboss.arquillian.core.api.annotation.Inject;
import org.jboss.arquillian.test.spi.TestMethodExecutor;
import org.jboss.arquillian.test.spi.TestResult;

/**
* A custom {@link ContainerMethodExecutor} based on {@link LocalSecurityManagerTestingExecutionEvent}.
*
* @author Gunnar Morling
*/
public class LocalSecurityManagerTestingContainerMethodExecutor implements ContainerMethodExecutor {

@Inject
private Event<LocalSecurityManagerTestingExecutionEvent> event;

@Inject
private Instance<TestResult> testResult;

@Override
public TestResult invoke(TestMethodExecutor testMethodExecutor) {
event.fire( new LocalSecurityManagerTestingExecutionEvent( testMethodExecutor ) );
return testResult.get();
}
}
@@ -0,0 +1,74 @@
/*
* Hibernate Validator, declare and validate application constraints
*
* License: Apache License, Version 2.0
* See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
*/
package org.hibernate.validator.tckrunner.securitymanager.arquillian;

import java.lang.reflect.Method;

import org.hibernate.validator.tckrunner.securitymanager.DelegatingExecutor;
import org.hibernate.validator.tckrunner.securitymanager.Executor;
import org.jboss.arquillian.container.test.impl.execution.event.LocalExecutionEvent;
import org.jboss.arquillian.test.spi.TestMethodExecutor;

/**
* A custom {@link LocalExecutionEvent} which channels execution through a specific protection domain.
*
* @author Gunnar Morling
*/
public class LocalSecurityManagerTestingExecutionEvent extends LocalExecutionEvent {

public LocalSecurityManagerTestingExecutionEvent(TestMethodExecutor executor) {
super( new DelegatingTestMethodExecutor( executor ) );
}

/**
* Invokes the given test method via {@link DelegatingExecutor} which lives in its own protection domain.
*/
private static class DelegatingTestMethodExecutor implements TestMethodExecutor {

private final Executor delegate;
private final Method method;
private final Object instance;

public DelegatingTestMethodExecutor(TestMethodExecutor delegate) {
this.method = delegate.getMethod();
this.instance = delegate.getInstance();
this.delegate = new DelegatingExecutor( new ArquillianExecutor( delegate ) );
}

@Override
public Method getMethod() {
return method;
}

@Override
public Object getInstance() {
return instance;
}

@Override
public void invoke(Object... parameters) throws Throwable {
delegate.invoke( parameters );
}
}

/**
* Executes a given test via a given Arquillian test executor.
*/
private static class ArquillianExecutor implements Executor {

private final TestMethodExecutor delegate;

public ArquillianExecutor(TestMethodExecutor delegate) {
this.delegate = delegate;
}

@Override
public void invoke(Object... parameters) throws Throwable {
delegate.invoke( parameters );
}
}
}
@@ -0,0 +1,29 @@
/*
* Hibernate Validator, declare and validate application constraints
*
* License: Apache License, Version 2.0
* See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
*/
package org.hibernate.validator.tckrunner.securitymanager.arquillian;

import org.jboss.arquillian.container.test.spi.client.protocol.Protocol;
import org.jboss.arquillian.core.spi.LoadableExtension;

/**
* An Arquillian extension which contributes a special protocol, {@link LocalSecurityManagerTestingProtocol}.
* <p>
* This protocol is essentially the same as
* {@link org.jboss.arquillian.container.test.impl.client.protocol.local.LocalProtocol}, only that the execution of
* tests is channeled through a specific protection domain (basically, "target/classes" of this module, or the
* equivalent JAR). Specifying only minimal permissions to this protection domain allows for the identification of code
* in the HV JAR which doesn't use privileged actions as required.
*
* @author Gunnar Morling
*/
public class LocalSecurityManagerTestingExtension implements LoadableExtension {

@Override
public void register(ExtensionBuilder builder) {
builder.service( Protocol.class, LocalSecurityManagerTestingProtocol.class );
}
}

0 comments on commit a1aed64

Please sign in to comment.