Initial check-in of Bindu's AlfrescoTestRunner frameowork plus sample tests, #401

This commit is contained in:
Martin Bergljung 2017-02-16 10:45:51 +00:00
parent f5404b9d40
commit 6f1d01394d
35 changed files with 2980 additions and 1560 deletions

View File

@ -54,7 +54,7 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<version>4.12</version>
<scope>test</scope>
</dependency>

View File

@ -17,13 +17,6 @@
</properties>
<dependencies>
<!-- The main Alfresco Repo dependency for compiling Java code in src/main/java -->
<dependency>
<groupId>${alfresco.groupId}</groupId>
<artifactId>alfresco-repository</artifactId>
</dependency>
</dependencies>
<build>

View File

@ -1,6 +1,23 @@
#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
/**
* Copyright (C) 2017 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK project.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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 ${package}.platformsample;
/**

View File

@ -1,21 +1,22 @@
#set($symbol_pound='#')
#set($symbol_dollar='$')
#set($symbol_escape='\' )
/*
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.
/**
* Copyright (C) 2017 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK project.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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 ${package}.platformsample;
@ -56,7 +57,7 @@ public class DemoComponent extends AbstractModuleComponent {
protected void executeInternal() throws Throwable {
System.out.println("DemoComponent has been executed");
logger.debug("Test debug logging. Congratulation your JAR Module is working");
logger.info("This is only for information purposed. Better remove me from the log in Production");
logger.info("This is only for information purposes. Better remove me from the log in Production");
}
/**

View File

@ -1,21 +1,22 @@
#set($symbol_pound='#')
#set($symbol_dollar='$')
#set($symbol_escape='\' )
/*
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.
/**
* Copyright (C) 2017 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK project.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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 ${package}.platformsample;

View File

@ -22,15 +22,15 @@
<beans>
<!-- A simple class that is initialized by Spring -->
<bean id="${package}.exampleBean" class="${package}.platformsample.Demo" init-method="init" />
<bean id="${package}.Demo" class="${package}.platformsample.Demo" init-method="init" />
<!-- A simple module component that will be executed once.
Note. this module component will only be executed once, and then there will be an entry for it in the Repo DB.
So doing for example $ mvn clean install alfresco:run twice will only execute this component the first time.
You need to remove /alf_data_dev for it to be executed again. -->
<bean id="${package}.exampleComponent" class="${package}.platformsample.DemoComponent" parent="module.baseComponent" >
<bean id="${package}.DemoComponent" class="${package}.platformsample.DemoComponent" parent="module.baseComponent" >
<property name="moduleId" value="${artifactId}" /> <!-- See module.properties -->
<property name="name" value="exampleComponent" />
<property name="name" value="DemoComponent" />
<property name="description" value="A demonstration component" />
<property name="sinceVersion" value="1.0" />
<property name="appliesFromVersion" value="0.99" /> <!-- 1.0 would not work here when using SNAPSHOT version in project -->

View File

@ -0,0 +1,191 @@
#set($symbol_pound='#')
#set($symbol_dollar='$')
#set($symbol_escape='\' )
/**
* Copyright (C) 2017 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK project.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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 ${package}.platformsample;
import org.alfresco.model.ContentModel;
import org.alfresco.rad.test.AbstractAlfrescoIT;
import org.alfresco.rad.test.AlfrescoTestRunner;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.nodelocator.CompanyHomeNodeLocator;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.apache.commons.io.IOUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* Integration Test sample for a custom content model.
* See {@link DemoComponentIT} for more info.
*
* @author martin.bergljung@alfresco.com
* @since 3.0
*/
@RunWith(value = AlfrescoTestRunner.class)
public class CustomContentModelIT extends AbstractAlfrescoIT {
private static final String ACME_MODEL_NS = "{http://www.acme.org/model/content/1.0}";
private static final String ACME_MODEL_LOCALNAME = "contentModel";
private static final String ACME_DOCUMENT_TYPE = "document";
private static final String ACME_SECURITY_CLASSIFIED_ASPECT = "securityClassified";
private static final String ACME_DOCUMENT_ID_PROPNAME = "documentId";
@Test
public void testCustomContentModelPresence() {
Collection<QName> allContentModels = getServiceRegistry().getDictionaryService().getAllModels();
QName customContentModelQName = createQName(ACME_MODEL_LOCALNAME);
assertTrue("Custom content model " + customContentModelQName.toString() +
" is not present", allContentModels.contains(customContentModelQName));
}
@Test
public void testCreateAcmeDocument() {
// Create the ACME Doc file
QName type = createQName(ACME_DOCUMENT_TYPE);
String textContent = "Hello World!";
String documentId = "DOC001";
Map<QName, Serializable> nodeProperties = new HashMap<>();
nodeProperties.put(createQName(ACME_DOCUMENT_ID_PROPNAME), documentId);
nodeProperties.put(createQName("securityClassification"), "Company Confidential");
NodeRef nodeRef = createNode("AcmeFile.txt", type, nodeProperties);
addFileContent(nodeRef, textContent);
// Add an Aspect to the file (could be a custom aspect...)
Map<QName, Serializable> aspectProperties = new HashMap<>();
aspectProperties.put(ContentModel.PROP_TITLE, "Some Doc Title");
aspectProperties.put(ContentModel.PROP_DESCRIPTION, "Some Doc Description");
getServiceRegistry().getNodeService().addAspect(nodeRef, ContentModel.ASPECT_TITLED, aspectProperties);
// Assert that the file is created correctly
assertEquals("Invalid type", type, getServiceRegistry().getNodeService().getType(nodeRef));
assertTrue("Missing security aspect",
getServiceRegistry().getNodeService().hasAspect(nodeRef, createQName(ACME_SECURITY_CLASSIFIED_ASPECT)));
assertTrue("Missing titled aspect",
getServiceRegistry().getNodeService().hasAspect(nodeRef, ContentModel.ASPECT_TITLED));
assertEquals("Invalid property value", documentId,
getServiceRegistry().getNodeService().getProperty(nodeRef, createQName(ACME_DOCUMENT_ID_PROPNAME)));
readTextContent(nodeRef).equals(textContent);
// Clean up node
if (nodeRef != null) {
getServiceRegistry().getNodeService().deleteNode(nodeRef);
}
}
/**
* ==================== Helper Methods ============================================================================
*/
/**
* Create a QName for the ACME content model
*
* @param localname the local content model name without namespace specified
* @return the full ACME QName including namespace
*/
private QName createQName(String localname) {
return QName.createQName(ACME_MODEL_NS + localname);
}
/**
* Create a new node, such as a file or a folder, with passed in type and properties
*
* @param name the name of the file or folder
* @param type the content model type
* @param properties the properties from the content model
* @return the Node Reference for the newly created node
*/
private NodeRef createNode(String name, QName type, Map<QName, Serializable> properties) {
NodeRef parentFolderNodeRef = getCompanyHomeNodeRef();
QName associationType = ContentModel.ASSOC_CONTAINS;
QName associationQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI,
QName.createValidLocalName(name));
properties.put(ContentModel.PROP_NAME, name);
ChildAssociationRef parentChildAssocRef = getServiceRegistry().getNodeService().createNode(
parentFolderNodeRef, associationType, associationQName, type, properties);
return parentChildAssocRef.getChildRef();
}
/**
* Add some text content to a file node
*
* @param nodeRef the node reference for the file that should have some text content added to it
* @param fileContent the text content
*/
private void addFileContent(NodeRef nodeRef, String fileContent) {
boolean updateContentPropertyAutomatically = true;
ContentWriter writer = getServiceRegistry().getContentService().getWriter(nodeRef, ContentModel.PROP_CONTENT,
updateContentPropertyAutomatically);
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
writer.setEncoding("UTF-8");
writer.putContent(fileContent);
}
/**
* Read text content for passed in file Node Reference
*
* @param nodeRef the node reference for a file containing text
* @return the text content
*/
private String readTextContent(NodeRef nodeRef) {
ContentReader reader = getServiceRegistry().getContentService().getReader(nodeRef, ContentModel.PROP_CONTENT);
if (reader == null) {
return ""; // Maybe it was a folder after all
}
InputStream is = reader.getContentInputStream();
try {
return IOUtils.toString(is, "UTF-8");
} catch (IOException ioe) {
throw new RuntimeException(ioe);
} finally {
if (is != null) {
try {
is.close();
} catch (Throwable e) {
e.printStackTrace();
}
}
}
}
/**
* Get the node reference for the /Company Home top folder in Alfresco.
* Use the standard node locator service.
*
* @return the node reference for /Company Home
*/
private NodeRef getCompanyHomeNodeRef() {
return getServiceRegistry().getNodeLocatorService().getNode(CompanyHomeNodeLocator.NAME, null, null);
}
}

View File

@ -0,0 +1,73 @@
#set($symbol_pound='#')
#set($symbol_dollar='$')
#set($symbol_escape='\' )
/**
* Copyright (C) 2017 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK project.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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 ${package}.platformsample;
import org.alfresco.rad.test.AbstractAlfrescoIT;
import org.alfresco.rad.test.AlfrescoTestRunner;
import org.alfresco.rad.test.Remote;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* Integration Test of the DemoComponent using the Alfresco Test Runner.
* The Alfresco Test Runner (i.e. AlfrescoTestRunner.class) will check if it is running in an Alfresco instance,
* if so it will execute normally locally. On the other hand, if it detects no
* Alfresco Spring context, then it will make a call to a custom Web Script that
* will execute this test in the running container remotely. The remote location is
* determined by the @Remote config.
*
* @author martin.bergljung@alfresco.com
* @since 3.0
*/
@RunWith(value = AlfrescoTestRunner.class)
// Specifying the remote endpoint is not required, it
// will default to http://localhost:8080/alfresco if
// not provided. This shows the syntax but simply
// sets the value back to the default value.
@Remote(endpoint = "http://localhost:8080/alfresco")
public class DemoComponentIT extends AbstractAlfrescoIT {
@Test
public void testGetCompanyHome() {
DemoComponent demoComponent = (DemoComponent) getApplicationContext().getBean("org.alfresco.test.DemoComponent");
NodeRef companyHome = demoComponent.getCompanyHome();
assertNotNull(companyHome);
String companyHomeName = (String) getServiceRegistry().getNodeService().getProperty(
companyHome, ContentModel.PROP_NAME);
assertNotNull(companyHomeName);
assertEquals("Company Home", companyHomeName);
}
@Test
public void testChildNodesCount() {
DemoComponent demoComponent = (DemoComponent) getApplicationContext().getBean("org.alfresco.test.DemoComponent");
NodeRef companyHome = demoComponent.getCompanyHome();
int childNodeCount = demoComponent.childNodesCount(companyHome);
assertNotNull(childNodeCount);
// There are 7 folders by default under Company Home
assertEquals(7, childNodeCount);
}
}

View File

@ -0,0 +1,56 @@
#set($symbol_pound='#')
#set($symbol_dollar='$')
#set($symbol_escape='\' )
/**
* Copyright (C) 2017 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK project.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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 ${package}.platformsample;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.extensions.webscripts.*;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* Unit testing the Web Script Java Controller
*
* @author martin.bergljung@alfresco.com
* @version 1.0
* @since 3.0
*/
public class HelloWorldWebScriptControllerTest {
@Test
public void testController() {
WebScriptRequest req = Mockito.mock(WebScriptRequest.class);
Status status = Mockito.mock(Status.class);
Cache cache = Mockito.mock(Cache.class);
String helloPropName = "fromJava";
String helloPropExpectedValue = "HelloFromJava";
HelloWorldWebScript ws = new HelloWorldWebScript();
Map<String, Object> model = ws.executeImpl(req, status, cache);
assertNotNull("Response from Web Script Java Controller is null", model);
assertEquals("Incorrect Web Script Java Controller Response",
helloPropExpectedValue, model.get(helloPropName));
}
}

View File

@ -0,0 +1,75 @@
#set($symbol_pound='#')
#set($symbol_dollar='$')
#set($symbol_escape='\' )
/**
* Copyright (C) 2017 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK project.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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 ${package}.platformsample;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* Integration Test (IT) for Hello World web script.
*
* @author martin.bergljung@alfresco.com
* @version 1.0
* @since 3.0
*/
public class HelloWorldWebScriptIT {
@Test
public void testWebScriptCall() throws Exception {
String webscriptURL = "http://localhost:8080/alfresco/service/sample/helloworld";
String expectedResponse = "Message: 'Hello from JS!' 'HelloFromJava'";
// Login credentials for Alfresco Repo
CredentialsProvider provider = new BasicCredentialsProvider();
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("admin", "admin");
provider.setCredentials(AuthScope.ANY, credentials);
// Create HTTP Client with credentials
CloseableHttpClient httpclient = HttpClientBuilder.create()
.setDefaultCredentialsProvider(provider)
.build();
// Execute Web Script call
try {
HttpGet httpget = new HttpGet(webscriptURL);
HttpResponse httpResponse = httpclient.execute(httpget);
assertEquals("Incorrect HTTP Response Status",
HttpStatus.SC_OK, httpResponse.getStatusLine().getStatusCode());
HttpEntity entity = httpResponse.getEntity();
assertNotNull("Response from Web Script is null", entity);
assertEquals("Incorrect Web Script Response", expectedResponse, EntityUtils.toString(entity));
} finally {
httpclient.close();
}
}
}

View File

@ -59,6 +59,52 @@
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<!-- Libs used in Unit and Integration tests -->
<!-- IMPORTANT - Test dependencies need to be here in the top parent POM as
the Alfresco Maven IT Mojo runs as part of the parent project ... -->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
<scope>test</scope>
</dependency>
<!-- The main Alfresco Repo dependency for compiling Java code in src/main/java -->
<dependency>
<groupId>${alfresco.groupId}</groupId>
<artifactId>alfresco-repository</artifactId>
</dependency>
<!-- Bring in Spring Context so we can use ApplicationContext, ApplicationContextAware etc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.17.RELEASE</version>
<scope>test</scope>
</dependency>
<!-- Bring in Alfresco RAD so we get access to AlfrescoTestRunner classes -->
<dependency>
<groupId>org.alfresco.maven</groupId>
<artifactId>alfresco-rad</artifactId>
<version>${alfresco.sdk.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!-- This will import the dependencyManagement for all artifacts in the selected Alfresco platform.

View File

@ -56,7 +56,7 @@ public class DemoComponent extends AbstractModuleComponent {
protected void executeInternal() throws Throwable {
System.out.println("DemoComponent has been executed");
logger.debug("Test debug logging. Congratulation your JAR Module is working");
logger.info("This is only for information purposed. Better remove me from the log in Production");
logger.info("This is only for information purposes. Better remove me from the log in Production");
}
/**

View File

@ -22,15 +22,15 @@
<beans>
<!-- A simple class that is initialized by Spring -->
<bean id="${package}.exampleBean" class="${package}.platformsample.Demo" init-method="init" />
<bean id="${package}.Demo" class="${package}.platformsample.Demo" init-method="init" />
<!-- A simple module component that will be executed once.
Note. this module component will only be executed once, and then there will be an entry for it in the Repo DB.
So doing for example $ mvn clean install alfresco:run twice will only execute this component the first time.
You need to remove /alf_data_dev for it to be executed again. -->
<bean id="${package}.exampleComponent" class="${package}.platformsample.DemoComponent" parent="module.baseComponent" >
<bean id="${package}.DemoComponent" class="${package}.platformsample.DemoComponent" parent="module.baseComponent" >
<property name="moduleId" value="${artifactId}" /> <!-- See module.properties -->
<property name="name" value="exampleComponent" />
<property name="name" value="DemoComponent" />
<property name="description" value="A demonstration component" />
<property name="sinceVersion" value="1.0" />
<property name="appliesFromVersion" value="0.99" /> <!-- 1.0 would not work here when using SNAPSHOT version in project -->

View File

@ -5,7 +5,8 @@
<packaging>jar</packaging>
<name>Rapid Application Development Support</name>
<description>SDK module for Rapid Development support</description>
<description>SDK module for Rapid Development support, such as Alfresco JUnit runner</description>
<parent>
<groupId>org.alfresco.maven</groupId>
<artifactId>alfresco-sdk-aggregator</artifactId>
@ -13,116 +14,29 @@
<relativePath>../../pom.xml</relativePath>
</parent>
<properties>
<pgsql.dialect.folder>${project.build.directory}/pg-dialect-tmp</pgsql.dialect.folder>
</properties>
<dependencies>
<!-- Enables JUnit remote testing (using JRebel) -->
<!-- Access to org.alfresco.service.ServiceRegistry -->
<dependency>
<groupId>com.tradeshift</groupId>
<artifactId>junit-remote</artifactId>
<version>3</version>
<type>jar</type>
<exclusions>
<exclusion>
<artifactId>servlet-api</artifactId>
<groupId>javax.servlet</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- Required to have annotation based remote testing working -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.0.6.RELEASE</version>
<type>jar</type>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Copied PostgreSQL dialect files to generate H2 dialect files on-the-fly -->
<!--
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>extract-postgres-dialect</id>
<phase>generate-test-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-repository</artifactId>
<version>${alfresco.community.default.version}</version>
<includes>alfresco/dbscripts/create/org.hibernate.dialect.PostgreSQLDialect/*,alfresco/dbscripts/upgrade/*/org.hibernate.dialect.PostgreSQLDialect/*,alfresco/ibatis/org.hibernate.dialect.PostgreSQLDialect/*</includes>
<outputDirectory>${pgsql.dialect.folder}</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>generate-h2-dialect</id>
<phase>generate-test-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
<resources>
<resource>
<directory>${pgsql.dialect.folder}/alfresco/dbscripts/create/org.hibernate.dialect.PostgreSQLDialect</directory>
<includes>
<include>*</include>
</includes>
<targetPath>alfresco/dbscripts/create/org.hibernate.dialect.H2Dialect</targetPath>
</resource>
<resource>
<directory>${pgsql.dialect.folder}/alfresco/ibatis/org.hibernate.dialect.PostgreSQLDialect</directory>
<includes>
<include>*</include>
</includes>
<targetPath>alfresco/ibatis/org.hibernate.dialect.H2Dialect</targetPath>
</resource>
Upgrade scripts - does not seem to be picked up, so any changes you would make to them are not picked up...
<resource>
<directory>${pgsql.dialect.folder}/alfresco/dbscripts/upgrade/4.1/org.hibernate.dialect.PostgreSQLDialect</directory>
<includes>
<include>*</include>
</includes>
<targetPath>alfresco/dbscripts/upgrade/4.1/org.hibernate.dialect.H2Dialect</targetPath>
</resource>
<resource>
<directory>${pgsql.dialect.folder}/alfresco/dbscripts/upgrade/4.2/org.hibernate.dialect.PostgreSQLDialect</directory>
<includes>
<include>*</include>
</includes>
<targetPath>alfresco/dbscripts/upgrade/4.2/org.hibernate.dialect.H2Dialect</targetPath>
</resource>
<resource>
<directory>${pgsql.dialect.folder}/alfresco/dbscripts/upgrade/5.0/org.hibernate.dialect.PostgreSQLDialect</directory>
<includes>
<include>*</include>
</includes>
<targetPath>alfresco/dbscripts/upgrade/5.0/org.hibernate.dialect.H2Dialect</targetPath>
</resource>
<scope>provided</scope>
</dependency>
</resources>
</configuration>
</execution>
</executions>
</plugin>
-->
</plugins>
<!-- Bring in ApplicationContextAware, ApplicationContext etc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.17.RELEASE</version>
</dependency>
</build>
<!-- Access to JUnit runner classes -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>

View File

@ -1,16 +0,0 @@
package org.alfresco.maven.rad;
import com.tradeshift.test.remote.RemoteServer;
public class RemoteRunnerWrapper implements Runnable {
public void run() {
try {
RemoteServer.main(new String []{});
} catch (Exception e) {
System.out.println("Could not start JUnit remoteServer because of: " + e.getMessage());
}
}
}

View File

@ -0,0 +1,69 @@
/**
* Copyright (C) 2017 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK project.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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 org.alfresco.rad;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* This Spring bean is aware of the application context in which
* it is initialized.
*
* @author martin.bergljung@alfresco.com
* @since 3.0
*/
public class SpringContextHolder implements ApplicationContextAware {
/**
* The instance of SpringContextHolder
*/
private static SpringContextHolder springContextHolderInstance;
/**
* The Alfresco Spring Application Context.
*/
private ApplicationContext applicationContext;
/**
* Default constructor.
*/
public SpringContextHolder() {
System.out.println("Initializing the SpringContextHolder class.");
springContextHolderInstance = this;
}
/**
* Return the singleton instance
*
* @return
*/
public static SpringContextHolder Instance() {
return springContextHolderInstance;
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("Setting current Spring Application Context in SpringContextHolder class.");
this.applicationContext = applicationContext;
}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
}

View File

@ -0,0 +1,89 @@
/**
* Copyright (C) 2017 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK project.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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 org.alfresco.rad.test;
import org.alfresco.rad.SpringContextHolder;
import org.alfresco.service.ServiceRegistry;
import org.junit.Rule;
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
import org.springframework.context.ApplicationContext;
/**
* Abstract Integration Test class to be used
* by Alfresco Integration Tests. Gives access to
* Alfresco Spring Application context and the
* {@link ServiceRegistry} that should be used when
* accessing Alfresco Services.
*
* @author martin.bergljung@alfresco.com
* @since 3.0
*/
public abstract class AbstractAlfrescoIT {
private ApplicationContext applicationContext = null;
private ServiceRegistry serviceRegistry = null;
/**
* Print the test we are currently running, useful if the test is running remotely
* and we don't see the server logs
*/
@Rule
public MethodRule testAnnouncer = new MethodRule() {
@Override
public Statement apply(Statement base, FrameworkMethod method, Object target) {
System.out.println("Running " + getClassName() + " Integration Test: " + method.getName() + "()");
return base;
}
};
protected String getClassName() {
Class<?> enclosingClass = getClass().getEnclosingClass();
if (enclosingClass != null) {
return enclosingClass.getName();
} else {
return getClass().getName();
}
}
protected ApplicationContext getApplicationContext() {
if (applicationContext == null) {
SpringContextHolder springContextHolder = SpringContextHolder.Instance();
if (springContextHolder != null) {
applicationContext = springContextHolder.getApplicationContext();
}
}
return applicationContext;
}
protected ServiceRegistry getServiceRegistry() {
if (serviceRegistry == null) {
ApplicationContext ctx = getApplicationContext();
if (ctx != null) {
Object bean = ctx.getBean("ServiceRegistry");
if (bean != null && bean instanceof ServiceRegistry) {
serviceRegistry = (ServiceRegistry) bean;
}
}
}
return serviceRegistry;
}
}

View File

@ -0,0 +1,249 @@
/**
* Copyright (C) 2017 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK project.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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 org.alfresco.rad.test;
import org.alfresco.rad.SpringContextHolder;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.junit.Ignore;
import org.junit.runner.Description;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
/**
* This is a JUnit test runner that is designed to work with an Alfresco repository.
* It detects if it's executing a test inside of a running Alfresco instance. If that
* is the case the tests are all run normally. If however the test is being run from
* outside the repository, from the maven command line or from an IDE
* such as IntelliJ or STS/Eclipse for example, then instead of running the actual
* test an HTTP request is made to a Web Script in a running Alfresco instance. This
* Web Script runs the test and returns enough information to this class so we can
* emulate having run the test locally.
* <p/>
* By doing this, we are able to create Integration Tests (IT) using standard JUnit
* capabilities. These can then be run from our IDEs with the associated visualizations,
* support for re-running failed tests, etc.
* <p/>
* Integration testing framework donated by Zia Consulting
*
* @author Bindu Wavell <bindu@ziaconsulting.com>
* @author martin.bergljung@alfresco.com (some editing)
* @since 3.0
*/
public class AlfrescoTestRunner extends BlockJUnit4ClassRunner {
public static final String SUCCESS = "SUCCESS";
public static final String FAILURE = "FAILURE";
public AlfrescoTestRunner(Class<?> klass) throws InitializationError {
super(klass);
}
public static String serializableToString(Serializable serializable) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(serializable);
oos.close();
String string = Base64.encodeBase64URLSafeString(baos.toByteArray());
return string;
}
@Override
protected void runChild(FrameworkMethod method, RunNotifier notifier) {
if (areWeRunningInAlfresco()) {
// Just run the test as normally
super.runChild(method, notifier);
} else {
// We are not running in an Alfresco Server, we need to call one and have it execute the test...
Description desc = describeChild(method);
if (method.getAnnotation(Ignore.class) != null) {
notifier.fireTestIgnored(desc);
} else {
callProxiedChild(method, notifier, desc);
}
}
}
/**
* Call a remote Alfresco server and have the test run there.
*
* @param method the test method to run
* @param notifier
* @param desc
*/
protected void callProxiedChild(FrameworkMethod method, RunNotifier notifier, Description desc) {
notifier.fireTestStarted(desc);
String className = method.getMethod().getDeclaringClass().getCanonicalName();
String methodName = method.getName();
if (null != methodName) {
className += "#" + methodName;
}
// Login credentials for Alfresco Repo
// TODO: Maybe configure credentials in props...
CredentialsProvider provider = new BasicCredentialsProvider();
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("admin", "admin");
provider.setCredentials(AuthScope.ANY, credentials);
// Create HTTP Client with credentials
CloseableHttpClient httpclient = HttpClientBuilder.create()
.setDefaultCredentialsProvider(provider)
.build();
// Create the GET Request for the Web Script that will run the test
String testWebScriptUrl = "/service/testing/test.xml?clazz=" + className.replace("#", "%23");
System.out.println("AlfrescoTestRunner: Invoking Web Script for test execution: " + testWebScriptUrl);
HttpGet get = new HttpGet(getContextRoot(method) + testWebScriptUrl);
try {
// Send proxied request and read response
HttpResponse resp = httpclient.execute(get);
InputStream is = resp.getEntity().getContent();
InputStreamReader ir = new InputStreamReader(is);
BufferedReader br = new BufferedReader(ir);
String body = "";
String line;
while ((line = br.readLine()) != null) {
body += line + "\n";
}
// Process response
if (body.length() > 0) {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = null;
dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(new InputSource(new StringReader(body)));
Element root = doc.getDocumentElement();
NodeList results = root.getElementsByTagName("result");
if (null != results && results.getLength() > 0) {
String result = results.item(0).getFirstChild().getNodeValue();
if (SUCCESS.equals(result)) {
notifier.fireTestFinished(desc);
} else {
boolean failureFired = false;
NodeList throwableNodes = root.getElementsByTagName("throwable");
for (int tid = 0; tid < throwableNodes.getLength(); tid++) {
String throwableBody = null;
Object object = null;
Throwable throwable = null;
throwableBody = throwableNodes.item(tid).getFirstChild().getNodeValue();
if (null != throwableBody) {
try {
object = objectFromString(throwableBody);
} catch (ClassNotFoundException e) {
}
if (null != object && object instanceof Throwable) {
throwable = (Throwable) object;
}
}
if (null == throwable) {
throwable = new Throwable("Unable to process exception body: " + throwableBody);
}
notifier.fireTestFailure(new Failure(desc, throwable));
failureFired = true;
}
if (!failureFired) {
notifier.fireTestFailure(new Failure(desc, new Throwable(
"There was an error but we can't figure out what it was, sorry!")));
}
}
} else {
notifier.fireTestFailure(new Failure(desc, new Throwable(
"Unable to process response for proxied test request: " + body)));
}
} else {
notifier.fireTestFailure(new Failure(desc, new Throwable(
"Attempt to proxy test into running Alfresco instance failed, no response received")));
}
} catch (IOException e) {
notifier.fireTestFailure(new Failure(desc, e));
} catch (ParserConfigurationException e) {
notifier.fireTestFailure(new Failure(desc, e));
} catch (SAXException e) {
notifier.fireTestFailure(new Failure(desc, e));
} finally {
try {
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
protected static Object objectFromString(String string) throws IOException, ClassNotFoundException {
byte[] buffer = Base64.decodeBase64(string);
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(buffer));
Object object = ois.readObject();
ois.close();
return object;
}
/**
* Check if we are running this test in an Alfresco server instance.
*
* @return true if we are running in an Alfresco server
*/
protected boolean areWeRunningInAlfresco() {
Object contextHolder = SpringContextHolder.Instance();
return (contextHolder != null);
}
/**
* Check the @Remote config on the test class to see where the
* Alfresco Repo is running
*
* @param method
* @return
*/
protected String getContextRoot(FrameworkMethod method) {
Class<?> declaringClass = method.getMethod().getDeclaringClass();
boolean annotationPresent = declaringClass.isAnnotationPresent(Remote.class);
if (annotationPresent) {
Remote annotation = declaringClass.getAnnotation(Remote.class);
return annotation.endpoint();
}
return "http://localhost:8080/alfresco";
}
}

View File

@ -0,0 +1,43 @@
/**
* Copyright (C) 2017 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK project.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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 org.alfresco.rad.test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* By default the ${@link AlfrescoTestRunner} will attempt to find a
* running Alfresco instance at http://localhost:8080/alfresco
* This annotation can be applied to a test class to have the
* proxy calls go to a different host/port.
* <p/>
* Integration testing framework donated by Zia Consulting.
*
* @author Bindu Wavell <bindu@ziaconsulting.com>
* @since 3.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Remote {
String endpoint() default "http://localhost:8080/alfresco";
}

View File

@ -0,0 +1,154 @@
/**
* Copyright (C) 2017 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK project.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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 org.alfresco.rad.test;
import org.alfresco.error.AlfrescoRuntimeException;
import org.junit.runner.JUnitCore;
import org.junit.runner.Request;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* This Web Script works in consort with the ${@link AlfrescoTestRunner}. When a test is run from an IDE or
* command line, the Alfresco test runner sends a proxied request to perform the test to this script. This runs
* the test and wraps the results up so that the test initiator can be fooled into thinking they are
* running the tests locally.
* <p/>
* Integration testing framework donated by Zia Consulting.
*
* @author Bindu Wavell <bindu@ziaconsulting.com>
* @author martin.bergljung@alfresco.com (some editing)
* @since 3.0
*/
public class RunTestWebScript extends DeclarativeWebScript {
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache) {
System.out.println("RunTestWebScript: Start executing ...");
String result = AlfrescoTestRunner.FAILURE;
String clazzAndMethod = null;
String clazz = null; // Test class
String method = null; // Test method
Result junitRunnerResult = null;
// Example invocation:
// /service/testing/test.xml?clazz=org.alfresco.test.platformsample.DemoComponentIT%23testChildNodesCount
// First, try and get the test class, including method, from a template var, i.e. /clazz/{class%23method}
clazzAndMethod = req.getServiceMatch().getTemplateVars().get("clazz");
if (clazzAndMethod == null) {
// Not found in template var, try parameter, i.e. ?clazz={class%23method}
clazzAndMethod = req.getParameter("clazz");
}
System.out.println("RunTestWebScript: clazzAndMethod = " + clazzAndMethod);
// Do we have a test class and method now?
if (clazzAndMethod == null) {
// No, set class and method as not provided
clazzAndMethod = "not provided";
} else {
// We got a test class and method, proceed
Class c = null;
// Split class and method on %23 = #
String[] clazzAndMethodArray = clazzAndMethod.split("#");
if (clazzAndMethodArray.length > 1) {
clazz = clazzAndMethodArray[0];
method = clazzAndMethodArray[1];
}
System.out.println("RunTestWebScript: [clazz=" + clazz + "][method=" + method + "]");
try {
// Load the Java class that will be run by JUnit
c = Class.forName(clazz);
} catch (ClassNotFoundException ex) {
throw new AlfrescoRuntimeException("Could not find test class: " + clazzAndMethod);
}
// See if JUnit should run test for whole class, or just specified method
if (method == null) {
// No method, run all tests in class
junitRunnerResult = JUnitCore.runClasses(c);
} else {
// We got one specific test method to run
Request jreq = Request.method(c, method);
junitRunnerResult = new JUnitCore().run(jreq);
}
// Check if test was successful
if (junitRunnerResult.wasSuccessful()) {
result = AlfrescoTestRunner.SUCCESS;
}
}
// Set up model to send to Web Script template
//
// What test did we run
Map<String, Object> model = new HashMap<String, Object>();
if (method == null) {
// We don't have a test method...
model.put("test", clazzAndMethod);
} else {
model.put("test", clazzAndMethod + "#" + method);
}
// Overall Alfresco Test runner result
model.put("result", result);
// JUnit Runner stats
if (junitRunnerResult != null) {
model.put("resultObject", junitRunnerResult);
model.put("failures", junitRunnerResult.getFailures());
model.put("failureCount", junitRunnerResult.getFailureCount());
model.put("ignoreCount", junitRunnerResult.getIgnoreCount());
model.put("runCount", junitRunnerResult.getRunCount());
model.put("runTime", junitRunnerResult.getRunTime());
List<String> throwables = new ArrayList<>();
if (null != junitRunnerResult.getFailures()) {
for (Failure failure : junitRunnerResult.getFailures()) {
try {
throwables.add(AlfrescoTestRunner.serializableToString(failure.getException()));
} catch (IOException e) {
try {
throwables.add(AlfrescoTestRunner.serializableToString(
"Unable to serialize exception."));
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
model.put("throwables", throwables);
model.put("wasSuccessful", junitRunnerResult.wasSuccessful());
}
System.out.println("RunTestWebScript: model = " + model);
System.out.println("RunTestWebScript: Stopped executing");
return model;
}
}

View File

@ -1,10 +1,12 @@
<?xml version='1.0' encoding='UTF-8'?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.
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
Copyright (C) 2017 Alfresco Software Limited.
This file is part of the Alfresco SDK project.
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
@ -13,17 +15,19 @@
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.
-->
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<bean id="remoteRunnnerWrapper" class="org.alfresco.maven.rad.RemoteRunnerWrapper"/>
<!-- Bean that holds current Alfresco Spring context -->
<bean id="org.alfresco.rad.springContextHolder" class="org.alfresco.rad.SpringContextHolder"/>
<bean id="remoteRunnnerWrapperThread" class="java.lang.Thread" init-method="start" destroy-method="interrupt">
<constructor-arg ref="remoteRunnnerWrapper"/>
<!-- Web Script that can be used to invoke integration tests remotely.
Integration testing framework donated by Zia Consulting -->
<bean id="webscript.org.alfresco.rad.test.runtest.get"
class="org.alfresco.rad.test.RunTestWebScript"
parent="webscript">
</bean>
</beans>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2017 Alfresco Software Limited.
This file is part of the Alfresco SDK project.
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.
-->
<webscript>
<shortname>Perform Test</shortname>
<description>Run integration test in Alfresco context</description>
<url>/testing/test?clazz={clazz}</url>
<format default="html">any</format>
<lifecycle>internal</lifecycle>
<authentication>user</authentication>
<family>Alfresco SDK</family>
<cache>
<never>false</never>
<public>false</public>
<mustrevalidate/>
</cache>
<negotiate accept="text/html">html</negotiate>
<negotiate accept="text/xml">html</negotiate>
</webscript>

View File

@ -0,0 +1,34 @@
<html>
<head>
<title>${test?html}</title>
<script language="JavaScript">
function showdiv(id) {
//safe function to show an element with a specified id
if (document.getElementById) { // DOM3 = IE5, NS6
document.getElementById(id).style.display = 'block';
}
else {
if (document.layers) { // Netscape 4
document.id.display = 'block';
}
else { // IE 4
document.all.id.style.display = 'block';
}
}
}
</script>
</head>
<body>
<h1>Integration Test: ${test?html}</h1>
<div><b>Result:</b> ${result}</div>
<#if failures??>
<#list failures as failure>
<div id="testHeader"><b>${failure.getTestHeader()?html}</b></div>
<div id="message"><a href="#" onclick="showdiv('trace');return false;">${failure.getMessage()?html}</a></div>
<div id="trace" style="display:none;"><pre>${failure.getTrace()?html}</pre></div>
<br/>
</#list>
</#if>
</body>
</html>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<response>
<test>${test?html}</test>
<result>${result?html}</result>
<#if failures??>
<failures>
<#list failures as failure>
<trace>${failure.getTrace()?html}</trace>
<exception>${failure.getException()?html}</exception>
<message>${failure.getMessage()?html}</message>
<testHeader>${failure.getTestHeader()?html}</testHeader>
</#list>
</failures>
</#if>
<failureCount>${failureCount?html}</failureCount>
<ignoreCount>${ignoreCount?html}</ignoreCount>
<runCount>${runCount?html}</runCount>
<runTime>${runTime?html}</runTime>
<#if throwables??>
<throwables>
<#list throwables as throwable>
<throwable>${throwable?html}</throwable>
</#list>
</throwables>
</#if>
<wasSuccessful>${wasSuccessful?string}</wasSuccessful>
</response>

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2015 Alfresco Software Limited.
* Copyright (C) 2017 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK.
* <p/>

View File

@ -1,3 +1,20 @@
/**
* Copyright (C) 2017 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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 org.alfresco.maven.plugin;
import java.io.File;

View File

@ -0,0 +1,274 @@
/**
* Copyright (C) 2017 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK project.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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 org.alfresco.maven.plugin;
import org.alfresco.maven.plugin.config.ModuleDependency;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.zeroturnaround.zip.ZipUtil;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import static org.twdata.maven.mojoexecutor.MojoExecutor.*;
/**
* Alfresco Plugin mojo that are used when you want to run Integration Tests.
* It will package up all the Integration Test classes and execute contained
* tests with the Maven Failsafe plugin. The test classes will be added
* to the platform war so they can be executed remotely via
* the ${@link org.alfresco.rad.test.AlfrescoTestRunner}
* <p/>
* The Alfresco RAD module is also added to the Platform WAR so
* the Alfresco Test runner classes are available.
*
* @author martin.bergljung@alfresco.com
* @since 3.0
*/
@Mojo(name = "it",
defaultPhase = LifecyclePhase.INTEGRATION_TEST,
aggregator = true, // Only run against the top-level project in a Maven build
requiresDependencyResolution = ResolutionScope.TEST)
public class IntegrationTestMojo extends AbstractRunMojo {
@Override
public void execute() throws MojoExecutionException {
execEnv = executionEnvironment(
project,
session,
pluginManager
);
if (enableSolr) {
unpackSolrConfig();
fixSolrHomePath();
replaceSolrConfigProperties();
installSolr10InLocalRepo();
}
if (enableTestProperties && enablePlatform) {
copyAlfrescoGlobalProperties();
renameAlfrescoGlobalProperties();
}
String testJarArtifactId = null;
if (enablePlatform) {
// Add alfresco-rad module to platform WAR
// So we got access to Alfresco Test Runner in the server
platformModules.add(
new ModuleDependency(
"org.alfresco.maven",
"alfresco-rad",
"${alfresco.sdk.version}",
ModuleDependency.TYPE_JAR));
// Create a JAR with all tests and add to module dependencies for platform WAR
// So we can run tests on the server
copyTestClassesFromSubModules2Parent();
testJarArtifactId = packageAndInstallTestsJar();
platformModules.add(
new ModuleDependency(
project.getGroupId(),
testJarArtifactId,
project.getVersion(),
ModuleDependency.TYPE_JAR));
// Now build the platform WAR
buildPlatformWar();
}
if (enableShare) {
buildShareWar();
}
if (enableActivitiApp) {
buildActivitiAppWar();
}
if (startTomcat) {
boolean fork = true;
startTomcat(fork);
runIntegrationTests(testJarArtifactId);
stopTomcat();
}
}
/**
* In an AIO project copy all integration test (IT) test-classes from sub projects/modules
* to the parent target/test-classes
*
* @throws MojoExecutionException
*/
protected void copyTestClassesFromSubModules2Parent() throws MojoExecutionException {
// Get sub-module names, so we can see where to copy test classes from
List<String> childModules = project.getModules();
if (childModules == null || childModules.size() <= 0) {
// Running in a single JAR module, nothing to copy,
// all test classes are already in top level target/test-classes
return;
}
for (String module : childModules) {
getLog().info("Copying integration test-classes (*IT.class) from module '" + module +
"' to parent target/test-classes");
executeMojo(
plugin(
groupId("org.apache.maven.plugins"),
artifactId("maven-resources-plugin"),
version(MAVEN_RESOURCE_PLUGIN_VERSION)
),
goal("copy-resources"),
configuration(
element(name("outputDirectory"), "${project.build.testOutputDirectory}"),
element(name("resources"),
element(name("resource"),
element(name("directory"), module + "/target/test-classes"),
element(name("includes"),
element(name("include"), "**/*.class")
),
element(name("filtering"), "false")
)
)
),
execEnv
);
}
}
/**
* Package all IT Tests in JAR file and install it in local maven repo.
*
* @return the customized JAR file artifactId, to be used by the failsafe plugin
* @throws MojoExecutionException
*/
protected String packageAndInstallTestsJar() throws MojoExecutionException {
final String jarArtifactId = project.getArtifactId() + "-IT-classes";
// Package the JAR file with all the Integration Tests (IT)
// Note. don't use the maven-war-plugin here as it will package the module files twice, once from the
// target/classes dir and once via the JAR
final String jarPath = project.getBuild().getDirectory() + "/" + jarArtifactId + ".jar";
final String jarSourceDir = project.getBuild().getDirectory() + "/test-classes";
ZipUtil.pack(new File(jarSourceDir), new File(jarPath));
getLog().info("Installing integration test JAR into local Maven repo.");
// Install the Test JAR file in the local maven repo
executeMojo(
plugin(
groupId("org.apache.maven.plugins"),
artifactId("maven-install-plugin"),
version(MAVEN_INSTALL_PLUGIN_VERSION)
),
goal("install-file"),
configuration(
element(name("file"), jarPath),
element(name("groupId"), "${project.groupId}"),
element(name("artifactId"), jarArtifactId),
element(name("version"), "${project.version}"),
element(name("packaging"), "jar") // Don't forget, otherwise installed as .POM
)
, execEnv
);
return jarArtifactId;
}
/**
* Run all IT tests contained in JAR with passed in artifact ID. Group ID and Version will be the same
* as the project.
*
* @param testJarArtifactId
* @throws MojoExecutionException
*/
protected void runIntegrationTests(String testJarArtifactId) throws MojoExecutionException {
getLog().info("Executing integration tests (*IT.class)...");
// JUnit runner
List<Dependency> failsafePluginDependencies = new ArrayList<Dependency>();
failsafePluginDependencies.add(dependency("org.apache.maven.surefire", "surefire-junit47", "2.19.1"));
// Add dependencies to classes under test
List<Element> classpathElements = new ArrayList<>();
List<String> childModules = project.getModules();
if (childModules != null && childModules.size() > 0) {
// Get sub-module names, so we can see what libs to include
for (String module : childModules) {
String classpathElement = project.getBasedir() + "/" + module + "/target/" + module + "-1.0-SNAPSHOT.jar";
getLog().info("Adding module '" + classpathElement + "' to test classpath");
classpathElements.add(element(name("additionalClasspathElement"), classpathElement));
}
}
// Execute Failsafe Mojo
Plugin failsafePlugin = plugin(
groupId("org.apache.maven.plugins"),
artifactId("maven-failsafe-plugin"),
version("2.19.1"),
failsafePluginDependencies
);
getLog().info("Start executing failsafe Mojo...");
// This might be ugly, the MojoExecuter will only accept Element[] and we need this list to be dynamic
// to avoid NPEs. If there's a better way to do this, then feel free to change it!
Element[] classpathElementArray = new Element[classpathElements.size()];
classpathElements.toArray(classpathElementArray);
executeMojo(failsafePlugin,
goal("integration-test"),
configuration(
element(name("includes"),
element(name("include"), "**/*IT.class")
),
element(name("additionalClasspathElements"),
classpathElementArray
),
// IT Test dependency to scan
element(name("dependenciesToScan"),
element(name("dependency"), project.getGroupId() + ":" + testJarArtifactId)
)
),
execEnv
);
getLog().info("Stopped executing failsafe Mojo");
}
protected void stopTomcat() throws MojoExecutionException {
getLog().info("Stopping Tomcat...");
Plugin tomcatPlugin = plugin(
groupId("org.apache.tomcat.maven"),
artifactId("tomcat7-maven-plugin"),
version(MAVEN_TOMCAT7_PLUGIN_VERSION)
);
executeMojo(tomcatPlugin,
goal("shutdown") ,
configuration(),
execEnv
);
}
}

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2015 Alfresco Software Limited.
* Copyright (C) 2017 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK.
* <p/>

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2015 Alfresco Software Limited.
* Copyright (C) 2017 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK.
* <p/>

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2015 Alfresco Software Limited.
* Copyright (C) 2017 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK.
* <p/>

View File

@ -1,7 +1,22 @@
/**
* Copyright (C) 2017 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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 org.alfresco.maven.plugin;
import java.io.File;
import org.alfrescolabs.technical.validation.AlfrescoTechnicalValidation;
import org.alfrescolabs.technical.validation.impl.AlfrescoTechnicalValidationImpl;
import org.apache.maven.plugin.AbstractMojo;

View File

@ -1,3 +1,20 @@
/**
* Copyright (C) 2017 Alfresco Software Limited.
* <p/>
* This file is part of the Alfresco SDK.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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 org.alfresco.maven.plugin;
import java.text.DateFormat;

View File

@ -138,7 +138,7 @@
<alfresco.sdk.tests.exclude>*/*-enterprise/*</alfresco.sdk.tests.exclude>
<!-- The following version is needed to grab the alfresco-mmt -->
<alfresco.community.default.version>5.1.g</alfresco.community.default.version>
<alfresco.community.default.version>5.2.e</alfresco.community.default.version>
<scm.url.base>https://github.com/Alfresco/alfresco-sdk</scm.url.base>
</properties>