From: Mathieu Baudier Date: Sat, 22 Nov 2008 10:47:37 +0000 (+0000) Subject: Introduce org.argeo.slc.support.castor X-Git-Tag: argeo-slc-2.1.7~2411 X-Git-Url: http://git.argeo.org/?a=commitdiff_plain;h=c64525cc73c704705e4fa629fc0cca7f98c13b90;p=gpl%2Fargeo-slc.git Introduce org.argeo.slc.support.castor git-svn-id: https://svn.argeo.org/slc/trunk@1842 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- diff --git a/runtime/org.argeo.slc.support.castor/.classpath b/runtime/org.argeo.slc.support.castor/.classpath new file mode 100644 index 000000000..9653ef0ac --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/.classpath @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/runtime/org.argeo.slc.support.castor/.project b/runtime/org.argeo.slc.support.castor/.project new file mode 100644 index 000000000..ba3744df4 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/.project @@ -0,0 +1,23 @@ + + + org.argeo.slc.core + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.maven.ide.eclipse.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.maven.ide.eclipse.maven2Nature + + diff --git a/runtime/org.argeo.slc.support.castor/.settings/org.eclipse.jdt.core.prefs b/runtime/org.argeo.slc.support.castor/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..93d31747f --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +#Fri Aug 29 11:10:18 CEST 2008 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/runtime/org.argeo.slc.support.castor/build.xml b/runtime/org.argeo.slc.support.castor/build.xml new file mode 100644 index 000000000..4213f1de9 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/build.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/pom.xml b/runtime/org.argeo.slc.support.castor/pom.xml new file mode 100644 index 000000000..973f69a0e --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/pom.xml @@ -0,0 +1,128 @@ + + 4.0.0 + + org.argeo.slc + argeo-slc + 0.11.2-SNAPSHOT + ../org.argeo.slc + + org.argeo.slc.core + Argeo SLC Core + SLC Core + + + scm:svn:https://www.argeo.org/svn/slc/trunk/org.argeo.slc.core + + + https://www.argeo.org/svn/slc/trunk/org.argeo.slc.core + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + org.apache.felix + maven-bundle-plugin + + + + org.argeo.slc.* + + *,org.apache.commons.logging;version="1.1" + + + + + + + + + org.apache.commons + com.springsource.org.apache.commons.logging + + + org.apache.log4j + + com.springsource.org.apache.log4j + + + + + + org.springframework + org.springframework.context + + + org.springframework.ws + org.springframework.oxm + + + + org.codehaus.castor + com.springsource.org.castor + + + + org.apache.xerces + com.springsource.org.apache.xerces + + + + edu.emory.mathcs.backport + + com.springsource.edu.emory.mathcs.backport + + + + javax.xml.stream + com.springsource.javax.xml.stream + + + + org.apache.commons + + com.springsource.org.apache.commons.io + + + + org.dbunit + com.springsource.org.dbunit + + + org.junit + com.springsource.junit + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/castor/structure/tree/TreeSPathFieldHandler.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/castor/structure/tree/TreeSPathFieldHandler.java new file mode 100644 index 000000000..ad117ff14 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/castor/structure/tree/TreeSPathFieldHandler.java @@ -0,0 +1,41 @@ +package org.argeo.slc.castor.structure.tree; + +import org.exolab.castor.mapping.AbstractFieldHandler; +import org.exolab.castor.mapping.MapItem; + +import org.argeo.slc.core.structure.tree.TreeSPath; + +public class TreeSPathFieldHandler extends AbstractFieldHandler { + + @Override + public Object getValue(Object object) throws IllegalStateException { + MapItem part = (MapItem) object; + return ((TreeSPath) part.getKey()).getAsUniqueString(); + } + + @Override + public Object newInstance(Object parent) throws IllegalStateException { + return null; + } + + @Override + public Object newInstance(Object parent, Object[] args) + throws IllegalStateException { + return null; + } + + @Override + public void resetValue(Object object) throws IllegalStateException, + IllegalArgumentException { + MapItem part = (MapItem) object; + part.setKey(null); + } + + @Override + public void setValue(Object object, Object value) + throws IllegalStateException, IllegalArgumentException { + MapItem part = (MapItem) object; + part.setKey(TreeSPath.parseToCreatePath(value.toString())); + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/castor/test/tree/StatusFieldHandler.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/castor/test/tree/StatusFieldHandler.java new file mode 100644 index 000000000..4cc334878 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/castor/test/tree/StatusFieldHandler.java @@ -0,0 +1,43 @@ +package org.argeo.slc.castor.test.tree; + +import org.argeo.slc.core.test.SimpleResultPart; +import org.argeo.slc.core.test.SlcTestUtils; +import org.argeo.slc.core.test.TestStatus; +import org.exolab.castor.mapping.AbstractFieldHandler; + +public class StatusFieldHandler extends AbstractFieldHandler { + + @Override + public Object getValue(Object object) throws IllegalStateException { + SimpleResultPart part = (SimpleResultPart) object; + return SlcTestUtils.statusToString(part.getStatus()); + } + + @Override + public Object newInstance(Object parent) throws IllegalStateException { + return null; + } + + @Override + public Object newInstance(Object parent, Object[] args) + throws IllegalStateException { + return null; + } + + @Override + public void resetValue(Object object) throws IllegalStateException, + IllegalArgumentException { + SimpleResultPart part = (SimpleResultPart) object; + // ERROR by default since it should be explicitely set + part.setStatus(TestStatus.ERROR); + } + + @Override + public void setValue(Object object, Object value) + throws IllegalStateException, IllegalArgumentException { + SimpleResultPart part = (SimpleResultPart) object; + Integer status = SlcTestUtils.stringToStatus((String) value); + part.setStatus(status); + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/SlcException.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/SlcException.java new file mode 100644 index 000000000..7daffaf87 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/SlcException.java @@ -0,0 +1,17 @@ +package org.argeo.slc.core; + +/** Basis for all SLC exceptions. This is an unchecked exception. */ +public class SlcException extends RuntimeException { + static final long serialVersionUID = 1l; + + /** Constructor. */ + public SlcException(String message) { + super(message); + } + + /** Constructor. */ + public SlcException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/UnsupportedException.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/UnsupportedException.java new file mode 100644 index 000000000..4b46b35de --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/UnsupportedException.java @@ -0,0 +1,54 @@ +package org.argeo.slc.core; + +/** Exception for unsupported features or actions. */ +public class UnsupportedException extends SlcException { + static final long serialVersionUID = 1l; + + /** Action not supported. */ + public UnsupportedException() { + this("Action not supported"); + } + + /** Constructor with a message. */ + public UnsupportedException(String message) { + super(message); + } + + /** + * Constructor generating a message. + * + * @param nature + * the nature of the unsupported object + * @param obj + * the object itself (its class name will be used in message) + */ + public UnsupportedException(String nature, Object obj) { + super("Unsupported " + nature + ": " + + (obj != null ? obj.getClass() : "[object is null]")); + } + + /** + * Constructor generating a message. + * + * @param nature + * the nature of the unsupported object + * @param clss + * the class itself (will be used in message) + */ + public UnsupportedException(String nature, Class clss) { + super("Unsupported " + nature + ": " + clss); + } + + /** + * Constructor generating a message. + * + * @param nature + * the nature of the unsupported object + * @param value + * the problematic value itself + */ + public UnsupportedException(String nature, String value) { + super("Unsupported " + nature + ": " + value); + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/build/Distribution.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/build/Distribution.java new file mode 100644 index 000000000..a9ada27f0 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/build/Distribution.java @@ -0,0 +1,6 @@ +package org.argeo.slc.core.build; + +public interface Distribution { + public String getDistributionId(); + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/build/VersionDistributionId.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/build/VersionDistributionId.java new file mode 100644 index 000000000..44a02cd60 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/build/VersionDistributionId.java @@ -0,0 +1,82 @@ +package org.argeo.slc.core.build; + +import java.util.StringTokenizer; + +/** + *

+ * An implementation of the distribution id using the standard + * Major.Minor.Release notation. And additional arbitrary string can also be + * added. + *

+ * + *

+ * Examples:
+ * 0.2.6
+ * 2.4.12.RC1 + *

+ */ +public class VersionDistributionId { + + private Integer major; + private Integer minor; + private Integer release; + private String additional; + + /** Parse the provided string in order to set the various components. */ + public void setVersionString(String str) { + StringTokenizer st = new StringTokenizer(str, "."); + if (st.hasMoreTokens()) + major = Integer.parseInt(st.nextToken()); + if (st.hasMoreTokens()) + minor = Integer.parseInt(st.nextToken()); + if (st.hasMoreTokens()) + release = Integer.parseInt(st.nextToken()); + if (st.hasMoreTokens()) + additional = st.nextToken(); + } + + public Integer getMajor() { + return major; + } + + public void setMajor(Integer major) { + this.major = major; + } + + public Integer getMinor() { + return minor; + } + + public void setMinor(Integer minor) { + this.minor = minor; + } + + public Integer getRelease() { + return release; + } + + public void setRelease(Integer release) { + this.release = release; + } + + public String getAdditional() { + return additional; + } + + public void setAdditional(String additional) { + this.additional = additional; + } + + @Override + public boolean equals(Object obj) { + // TODO Auto-generated method stub + return super.equals(obj); + } + + @Override + public String toString() { + return major + "." + minor + "." + release + + (additional != null ? "." + additional : ""); + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/build/package.html b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/build/package.html new file mode 100644 index 000000000..5da205278 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/build/package.html @@ -0,0 +1,6 @@ + + + +SLC Build: building of software systems. + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/AbstractDeployedSystem.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/AbstractDeployedSystem.java new file mode 100644 index 000000000..3941f5529 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/AbstractDeployedSystem.java @@ -0,0 +1,24 @@ +package org.argeo.slc.core.deploy; + +import org.argeo.slc.core.UnsupportedException; +import org.argeo.slc.core.build.Distribution; + +public abstract class AbstractDeployedSystem implements DeployedSystem { + public String getDeployedSystemId() { + // TODO Auto-generated method stub + return null; + } + + public DeploymentData getDeploymentData() { + throw new UnsupportedException("Method not supported"); + } + + public Distribution getDistribution() { + throw new UnsupportedException("Method not supported"); + } + + public TargetData getTargetData() { + throw new UnsupportedException("Method not supported"); + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/DeployEnvironment.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/DeployEnvironment.java new file mode 100644 index 000000000..ca747f65e --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/DeployEnvironment.java @@ -0,0 +1,9 @@ +package org.argeo.slc.core.deploy; + +import java.io.File; +import java.util.Map; + +public interface DeployEnvironment { + public void unpackTo(Object packg, File targetLocation, + Map filter); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/DeployedSystem.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/DeployedSystem.java new file mode 100644 index 000000000..fa383c331 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/DeployedSystem.java @@ -0,0 +1,14 @@ +package org.argeo.slc.core.deploy; + +import org.argeo.slc.core.build.Distribution; + +/** An instance of a software system. */ +public interface DeployedSystem extends TargetData { + public String getDeployedSystemId(); + + public Distribution getDistribution(); + + public DeploymentData getDeploymentData(); + + public TargetData getTargetData(); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/DeployedSystemManager.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/DeployedSystemManager.java new file mode 100644 index 000000000..281f81c73 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/DeployedSystemManager.java @@ -0,0 +1,5 @@ +package org.argeo.slc.core.deploy; + +public interface DeployedSystemManager { + public void setDeployedSystem(T deployedSystem); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/Deployment.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/Deployment.java new file mode 100644 index 000000000..fede6c1b3 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/Deployment.java @@ -0,0 +1,16 @@ +package org.argeo.slc.core.deploy; + +import org.argeo.slc.core.build.Distribution; + +public interface Deployment { + public DeployedSystem getDeployedSystem(); + + public void setTargetData(TargetData targetData); + + public void setDeploymentData(DeploymentData deploymentData); + + public void setDistribution(Distribution distribution); + + public void execute(); + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/DeploymentData.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/DeploymentData.java new file mode 100644 index 000000000..0148ea529 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/DeploymentData.java @@ -0,0 +1,5 @@ +package org.argeo.slc.core.deploy; + +public interface DeploymentData { + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/InstalledExecutables.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/InstalledExecutables.java new file mode 100644 index 000000000..a5d0b6d90 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/InstalledExecutables.java @@ -0,0 +1,5 @@ +package org.argeo.slc.core.deploy; + +public interface InstalledExecutables extends DeployedSystem { + public String getExecutablePath(String key); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/SimpleExecutables.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/SimpleExecutables.java new file mode 100644 index 000000000..5f9894014 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/SimpleExecutables.java @@ -0,0 +1,72 @@ +package org.argeo.slc.core.deploy; + +import java.io.File; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.core.build.Distribution; + +public class SimpleExecutables implements InstalledExecutables { + private final static Log log = LogFactory.getLog(SimpleExecutables.class); + + private String baseDir; + private Map paths = new TreeMap(); + + private Distribution distribution; + + public String getExecutablePath(String key) { + String path = paths.get(key); + if (path == null) { + if (log.isDebugEnabled()) + log.debug("No executable path found for key " + key + + ", using the key as executable name."); + path = key; + } + + if (baseDir != null) + path = baseDir + File.separator + path; + return path; + } + + public String getDeployedSystemId() { + // TODO Auto-generated method stub + return null; + } + + public DeploymentData getDeploymentData() { + // TODO Auto-generated method stub + return null; + } + + public Distribution getDistribution() { + return distribution; + } + + public TargetData getTargetData() { + // TODO Auto-generated method stub + return null; + } + + public String getBaseDir() { + return baseDir; + } + + public void setBaseDir(String baseDir) { + this.baseDir = baseDir; + } + + public Map getPaths() { + return paths; + } + + public void setPaths(Map paths) { + this.paths = paths; + } + + public void setDistribution(Distribution distribution) { + this.distribution = distribution; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/TargetData.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/TargetData.java new file mode 100644 index 000000000..2fe155d31 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/TargetData.java @@ -0,0 +1,5 @@ +package org.argeo.slc.core.deploy; + +public interface TargetData { + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/package.html b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/package.html new file mode 100644 index 000000000..f3a4c5bd6 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/deploy/package.html @@ -0,0 +1,6 @@ + + + +SLC Deploy: deployment of software systems. + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/package.html b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/package.html new file mode 100644 index 000000000..db808c822 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/package.html @@ -0,0 +1,6 @@ + + + +Common classes of teh SLC framework. + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/process/FileSlcExecutionNotifier.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/process/FileSlcExecutionNotifier.java new file mode 100644 index 000000000..0b9f682b0 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/process/FileSlcExecutionNotifier.java @@ -0,0 +1,82 @@ +package org.argeo.slc.core.process; + +import java.io.File; +import java.io.FileWriter; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.transform.stream.StreamResult; + +import org.apache.commons.io.IOUtils; +import org.argeo.slc.core.SlcException; +import org.springframework.oxm.Marshaller; + +public class FileSlcExecutionNotifier implements SlcExecutionNotifier { + private final static SimpleDateFormat sdf = new SimpleDateFormat( + "yyyyMMdd-HHmmss"); + + private String basePath; + private Marshaller marshaller; + + private Map uuidToDir = new HashMap(); + + public void addSteps(SlcExecution slcExecution, + List additionalSteps) { + writeSlcExecution(slcExecution); + } + + public void newExecution(SlcExecution slcExecution) { + String dirPath = basePath + File.separator + sdf.format(new Date()) + + '-' + slcExecution.getUuid(); + File dir = new File(dirPath); + dir.mkdirs(); + + uuidToDir.put(slcExecution.getUuid(), dirPath); + + writeSlcExecution(slcExecution); + } + + public void updateExecution(SlcExecution slcExecution) { + writeSlcExecution(slcExecution); + } + + public void updateStatus(SlcExecution slcExecution, String oldStatus, + String newStatus) { + writeSlcExecution(slcExecution); + } + + protected void writeSlcExecution(SlcExecution slcExecution) { + FileWriter out = null; + try { + out = new FileWriter(getFilePath(slcExecution)); + marshaller.marshal(slcExecution, new StreamResult(out)); + } catch (Exception e) { + throw new SlcException("Cannot marshall SlcExecution to " + + getFilePath(slcExecution), e); + } finally { + IOUtils.closeQuietly(out); + } + } + + protected String getFileName(SlcExecution slcExecution) { + return "SlcExecution-" + slcExecution.getUuid() + ".xml"; + } + + protected String getFilePath(SlcExecution slcExecution) { + String dirPath = uuidToDir.get(slcExecution.getUuid()); + return dirPath + File.separator + "SlcExecution-" + + slcExecution.getUuid() + ".xml"; + } + + public void setBasePath(String basePath) { + this.basePath = basePath; + } + + public void setMarshaller(Marshaller marshaller) { + this.marshaller = marshaller; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/process/SlcExecution.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/process/SlcExecution.java new file mode 100644 index 000000000..8264796f6 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/process/SlcExecution.java @@ -0,0 +1,101 @@ +package org.argeo.slc.core.process; + +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.Vector; + +public class SlcExecution { + public final static String STATUS_SCHEDULED = "SCHEDULED"; + public final static String STATUS_RUNNING = "RUNNING"; + public final static String STATUS_FINISHED = "FINISHED"; + public final static String STATUS_ERROR = "ERROR"; + public final static String STATUS_CLEANED = "CLEANED"; + + public final static String UNKOWN_HOST = "UNKOWN_HOST"; + + private String uuid; + private String host; + private String user; + private String type; + private String status; + private Map attributes = new TreeMap(); + + private List steps = new Vector(); + + public List getSteps() { + return steps; + } + + public void setSteps(List steps) { + this.steps = steps; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public SlcExecutionStep currentStep() { + if (steps.size() > 0) + return steps.get(steps.size() - 1); + else + return null; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof SlcExecution) { + return getUuid().equals(((SlcExecution) obj).getUuid()); + } + return false; + } + + @Override + public int hashCode() { + return getUuid().hashCode(); + } + + public Map getAttributes() { + return attributes; + } + + public void setAttributes(Map attributes) { + this.attributes = attributes; + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/process/SlcExecutionAware.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/process/SlcExecutionAware.java new file mode 100644 index 000000000..089dc317e --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/process/SlcExecutionAware.java @@ -0,0 +1,5 @@ +package org.argeo.slc.core.process; + +public interface SlcExecutionAware { + public void notifySlcExecution(SlcExecution slcExecution); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/process/SlcExecutionNotifier.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/process/SlcExecutionNotifier.java new file mode 100644 index 000000000..bf3b67ba5 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/process/SlcExecutionNotifier.java @@ -0,0 +1,15 @@ +package org.argeo.slc.core.process; + +import java.util.List; + +public interface SlcExecutionNotifier { + public void newExecution(SlcExecution slcExecution); + + public void addSteps(SlcExecution slcExecution, + List additionalSteps); + + public void updateExecution(SlcExecution slcExecution); + + public void updateStatus(SlcExecution slcExecution, String oldStatus, + String newStatus); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/process/SlcExecutionStep.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/process/SlcExecutionStep.java new file mode 100644 index 000000000..50032d8cd --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/process/SlcExecutionStep.java @@ -0,0 +1,88 @@ +package org.argeo.slc.core.process; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import java.util.Vector; + +import org.apache.commons.io.IOUtils; + +public class SlcExecutionStep { + public final static String TYPE_LOG = "LOG"; + + private String uuid; + private String type; + private Date begin; + private List logLines = new Vector(); + + /** Empty constructor */ + public SlcExecutionStep() { + } + + public SlcExecutionStep(String log) { + this.type = TYPE_LOG; + this.begin = new Date(); + this.uuid = UUID.randomUUID().toString(); + addLog(log); + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Date getBegin() { + return begin; + } + + public void setBegin(Date begin) { + this.begin = begin; + } + + public List getLogLines() { + return logLines; + } + + public void setLogLines(List logLines) { + this.logLines = logLines; + } + + public String logAsString() { + StringWriter writer = new StringWriter(); + String log = writer.toString(); + IOUtils.closeQuietly(writer); + return log; + } + + public void addLog(String log) { + if (log == null) + return; + + try { + List lines = IOUtils.readLines(new StringReader(log)); + logLines.addAll(lines); + } catch (IOException e) { + throw new RuntimeException("Cannot add log", e); + } + } + + @Override + public String toString() { + return getClass().getSimpleName() + "#" + uuid; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/SimpleSElement.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/SimpleSElement.java new file mode 100644 index 000000000..2bab2e74c --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/SimpleSElement.java @@ -0,0 +1,69 @@ +package org.argeo.slc.core.structure; + +import java.util.Map; +import java.util.TreeMap; + +import org.argeo.slc.core.structure.tree.TreeSPath; + +/** + * Basic implementation of StructureElement. + * + * @see TreeSPath + */ +public class SimpleSElement implements StructureElement { + /** For ORM */ + private Long tid; + private String label; + private Map tags = new TreeMap(); + + /** For ORM */ + public SimpleSElement() { + } + + /** Constructor */ + public SimpleSElement(String label) { + this.label = label; + } + + /** Constructor */ + public SimpleSElement(String label, String defaultLabel) { + this(label != null ? label : defaultLabel); + } + + /** Constructor */ + public SimpleSElement(SimpleSElement sElement) { + setLabel(sElement.getLabel()); + setTags(new TreeMap(sElement.getTags())); + } + + public String getLabel() { + return label; + } + + /** Sets the label. */ + public void setLabel(String label) { + this.label = label; + } + + public Long getTid() { + return tid; + } + + void setTid(Long tid) { + this.tid = tid; + } + + public Map getTags() { + return tags; + } + + public void setTags(Map tags) { + this.tags = tags; + } + + @Override + public SimpleSElement clone() { + return new SimpleSElement(this); + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/StructureAware.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/StructureAware.java new file mode 100644 index 000000000..643af73af --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/StructureAware.java @@ -0,0 +1,10 @@ +package org.argeo.slc.core.structure; + +/** + * Wrapper for an element, which is able to propagate registration to + * sub-elements. + */ +public interface StructureAware { + /** Called after registration. */ + public void notifyCurrentPath(StructureRegistry registry, T path); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/StructureElement.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/StructureElement.java new file mode 100644 index 000000000..8e9d15bff --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/StructureElement.java @@ -0,0 +1,10 @@ +package org.argeo.slc.core.structure; + +/** + * Atomic element holding metadata such as description about the element which + * registered. + */ +public interface StructureElement { + /** Label of this element. */ + public String getLabel(); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/StructureElementProvider.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/StructureElementProvider.java new file mode 100644 index 000000000..b9aa14452 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/StructureElementProvider.java @@ -0,0 +1,5 @@ +package org.argeo.slc.core.structure; + +public interface StructureElementProvider { + public StructureElement createStructureElement(); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/StructurePath.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/StructurePath.java new file mode 100644 index 000000000..452dc9514 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/StructurePath.java @@ -0,0 +1,16 @@ +package org.argeo.slc.core.structure; + +/** + * Path allowing to uniquely identify a StructureElement within a + * registry. + * + * @see StructureElement + * @see StructurePath + */ +public interface StructurePath { + /** + * Unique representation as a string. Most implementation will also provide + * a mean to interpret this string. + */ + public String getAsUniqueString(); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/StructureRegistry.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/StructureRegistry.java new file mode 100644 index 000000000..e90916408 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/StructureRegistry.java @@ -0,0 +1,55 @@ +package org.argeo.slc.core.structure; + +import java.util.List; + +/** Registry where the whole structure is stored. */ +public interface StructureRegistry

{ + /** Read mode: the structure is only read. */ + public static String READ = "READ"; + /** All mode: everything is executed regardless of the active paths. */ + public static String ALL = "ALL"; + /** Active mode: only the active paths are executed. */ + public static String ACTIVE = "ACTIVE"; + + /** Adds an element to the registry. */ + public void register(P path, StructureElement element); + + /** Lists all registered elements. */ + public List listElements(); + + /** Lists all registered elements. */ + public List

listPaths(); + + /** Gets a element based on its path. */ + public T getElement(P path); + + /** + * Set the interpreter mode: read, all or active. + * + * @see #READ + * @see #ALL + * @see #STATUS_ACTIVE + */ + public void setMode(String mode); + + /** + * Gets the current interpreter mode. + * + * @see #READ + * @see #ALL + * @see #STATUS_ACTIVE + */ + public String getMode(); + + /** + * Gets the list of active paths, which will be run if executed in + * STATUS_ACTIVE mode. + */ + public List

getActivePaths(); + + /** + * Sets the list of active path, which will be run if executed in + * STATUS_ACTIVE mode. + */ + public void setActivePaths(List

activePaths); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/package.html b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/package.html new file mode 100644 index 000000000..d9bab8a55 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/package.html @@ -0,0 +1,6 @@ + + + +SLC Structure framework allowing to uniquely reference actions. + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/tree/TreeSPath.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/tree/TreeSPath.java new file mode 100644 index 000000000..c673faa65 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/tree/TreeSPath.java @@ -0,0 +1,205 @@ +package org.argeo.slc.core.structure.tree; + +import java.util.List; +import java.util.StringTokenizer; +import java.util.Vector; + +import org.argeo.slc.core.SlcException; +import org.argeo.slc.core.structure.StructurePath; +import org.argeo.slc.core.structure.StructureRegistry; + +/** + * Path for tree based StructureRegistry implementations. + */ +public class TreeSPath implements StructurePath, Comparable { + /** Default character to use a separator: /. */ + private static Character DEFAULT_SEPARATOR = '/'; + + private Character separator = DEFAULT_SEPARATOR; + + private String asUniqueString; + + /** For ORM */ + private Long tid; + + public TreeSPath() { + + } + + public TreeSPath(String asUniqueString) { + this.asUniqueString = checkAndFormatPath(asUniqueString); + } + + public String getAsUniqueString() { + return asUniqueString; + } + + /** + * Sets all the required data from a string. ATTENTION: the path is + * not checked for performance reason. This method should be used only by + * ORM/OXM frameworks. Use constructor to create immutable tree structure + * paths. + */ + public void setAsUniqueString(String str) { + this.asUniqueString = str; + } + + /** The separator actually used by this path. */ + public Character getSeparator() { + return separator; + } + + /** Gets the parent path. */ + public TreeSPath getParent() { + int lastSep = getAsUniqueString().lastIndexOf(separator); + if (lastSep < 1) { + return null; + } + String parentUniqueString = getAsUniqueString().substring(0, lastSep); + return new TreeSPath(parentUniqueString); + } + + /** Gets the name part of the path. */ + public String getName() { + int lastSep = getAsUniqueString().lastIndexOf(separator); + return getAsUniqueString().substring(lastSep + 1); + } + + /** Create a path without parent. */ + public static TreeSPath createRootPath(String name) { + if (name.indexOf(DEFAULT_SEPARATOR) >= 0) { + throw new SlcException("Name cannot contain " + DEFAULT_SEPARATOR); + } + return new TreeSPath('/' + name); + } + + /** Create a child . */ + public TreeSPath createChild(String name) { + if (name.indexOf(separator) > -1) { + throw new SlcException("Tree path name '" + name + + "' contains separator character " + separator); + } + return new TreeSPath(getAsUniqueString() + '/' + name); + } + + /** + * Parses a string to a path. + * + * @deprecated use constructor instead + */ + public static TreeSPath parseToCreatePath(String path) { + return parseToCreatePath(path, DEFAULT_SEPARATOR); + } + + protected String checkAndFormatPath(String str) { + if (str.length() < 2) { + throw new SlcException("Path " + str + " is not short"); + } + if (str.charAt(0) != separator) { + throw new SlcException("Path " + str + " have to start with " + + separator); + } + + StringBuffer buf = new StringBuffer(str.length() + 5); + StringTokenizer st = new StringTokenizer(str, separator.toString()); + while (st.hasMoreTokens()) { + buf.append(separator).append(st.nextToken()); + } + return buf.toString(); + } + + /** + * Parses a string to a path. + * + * @deprecated use constructor instead + */ + public static TreeSPath parseToCreatePath(String path, Character separator) { + return new TreeSPath(path); + } + + /** Lists the children from a registry. */ + public List listChildren(StructureRegistry registry) { + return listChildrenPaths(registry, this); + } + + /** Lists the children from a given path from a registry. */ + public static List listChildrenPaths( + StructureRegistry registry, TreeSPath path) { + List paths = new Vector(); + List allPaths = registry.listPaths(); + for (TreeSPath pathT : allPaths) { + if (pathT.getParent() != null && pathT.getParent().equals(path)) { + paths.add(pathT); + } + } + return paths; + } + + /** Gets the root tree path of this path. */ + public TreeSPath getRoot() { + TreeSPath root = this; + while (root.getParent() != null) { + root = root.getParent(); + } + return root; + } + + /** Depth of this path. */ + public Integer getDepth() { + return depthImpl(this); + } + + protected int depthImpl(TreeSPath path) { + if (path.getParent() == null) { + return 1; + } else { + return depthImpl(path.getParent()) + 1; + } + } + + public List getHierarchyAsList() { + List lst = new Vector(); + addParentToList(lst, this); + lst.add(this); + return lst; + } + + protected void addParentToList(List lst, TreeSPath current) { + TreeSPath parent = current.getParent(); + if (parent != null) { + addParentToList(lst, parent); + lst.add(parent); + } + } + + @Override + public String toString() { + return getAsUniqueString(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof StructurePath) { + StructurePath path = (StructurePath) obj; + return getAsUniqueString().equals(path.getAsUniqueString()); + } + return false; + } + + @Override + public int hashCode() { + return getAsUniqueString().hashCode(); + } + + public int compareTo(StructurePath o) { + return getAsUniqueString().compareTo(o.getAsUniqueString()); + } + + public Long getTid() { + return tid; + } + + void setTid(Long tid) { + this.tid = tid; + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/tree/TreeSRegistry.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/tree/TreeSRegistry.java new file mode 100644 index 000000000..36c85728f --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/tree/TreeSRegistry.java @@ -0,0 +1,90 @@ +package org.argeo.slc.core.structure.tree; + +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.Vector; + +import org.argeo.slc.core.UnsupportedException; +import org.argeo.slc.core.structure.SimpleSElement; +import org.argeo.slc.core.structure.StructureElement; +import org.argeo.slc.core.structure.StructureRegistry; + +/** Tree based implementation of a structure registry. */ +public class TreeSRegistry implements StructureRegistry { + /** For ORM */ + private Long tid; + private Map elements = new TreeMap(); + + private String mode = StructureRegistry.ALL; + + private List activePaths; + + public T getElement(TreeSPath path) { + return (T) elements.get(path); + } + + public List listElements() { + return new Vector(elements.values()); + } + + public List listPaths() { + return new Vector(elements.keySet()); + } + + public void register(TreeSPath path, StructureElement element) { + if (path == null) + throw new UnsupportedException("Cannot register under a null path."); + if (element == null) + throw new UnsupportedException( + "Cannot register null element for path " + path); + if (element.getLabel() == null) + throw new UnsupportedException( + "Cannot register an element with null label for path " + + path); + + final SimpleSElement simpleSElement; + if (element instanceof SimpleSElement) { + simpleSElement = (SimpleSElement) element; + } else { + simpleSElement = new SimpleSElement(element.getLabel()); + } + + elements.put(path, simpleSElement); + } + + public String getMode() { + return mode; + } + + public void setMode(String mode) { + this.mode = mode; + } + + public List getActivePaths() { + return activePaths; + } + + public void setActivePaths(List activePaths) { + this.activePaths = activePaths; + } + + /** Gets the elements. */ + public Map getElements() { + return elements; + } + + /** Sets the elements (for ORM). */ + public void setElements(Map elements) { + this.elements = elements; + } + + Long getTid() { + return tid; + } + + void setTid(Long tid) { + this.tid = tid; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/tree/TreeSRelated.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/tree/TreeSRelated.java new file mode 100644 index 000000000..43a145a4e --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/tree/TreeSRelated.java @@ -0,0 +1,13 @@ +package org.argeo.slc.core.structure.tree; + +import org.argeo.slc.core.structure.StructureAware; +import org.argeo.slc.core.structure.StructureElement; +import org.argeo.slc.core.structure.StructureRegistry; + +public interface TreeSRelated extends StructureAware { + public TreeSPath getBasePath(); + + public StructureRegistry getRegistry(); + + public StructureElement getStructureElement(String key); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/tree/TreeSRelatedHelper.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/tree/TreeSRelatedHelper.java new file mode 100644 index 000000000..acc829c36 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/tree/TreeSRelatedHelper.java @@ -0,0 +1,32 @@ +package org.argeo.slc.core.structure.tree; + +import org.argeo.slc.core.structure.SimpleSElement; +import org.argeo.slc.core.structure.StructureElement; +import org.argeo.slc.core.structure.StructureRegistry; + +/** + * Provides default implementations of some methods of TreeSRelated. + */ +public abstract class TreeSRelatedHelper implements TreeSRelated { + private TreeSPath basePath; + private StructureRegistry registry; + + public TreeSPath getBasePath() { + return basePath; + } + + public StructureRegistry getRegistry() { + return registry; + } + + public void notifyCurrentPath(StructureRegistry registry, + TreeSPath path) { + basePath = path; + this.registry = registry; + } + + public StructureElement getStructureElement(String key) { + return new SimpleSElement(key); + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/tree/package.html b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/tree/package.html new file mode 100644 index 000000000..a2a51e4d9 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/structure/tree/package.html @@ -0,0 +1,6 @@ + + + +Tree-based implementation of the SLC structure framework. + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/BasicTestData.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/BasicTestData.java new file mode 100644 index 000000000..e6be49632 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/BasicTestData.java @@ -0,0 +1,23 @@ +package org.argeo.slc.core.test; + +public class BasicTestData implements TestData { + private Object expected; + private Object reached; + + public Object getExpected() { + return expected; + } + + public void setExpected(Object expected) { + this.expected = expected; + } + + public Object getReached() { + return reached; + } + + public void setReached(Object reached) { + this.reached = reached; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/BasicTestDefinition.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/BasicTestDefinition.java new file mode 100644 index 000000000..4d62ba39d --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/BasicTestDefinition.java @@ -0,0 +1,39 @@ +package org.argeo.slc.core.test; + +import org.argeo.slc.core.SlcException; +import org.argeo.slc.core.structure.tree.TreeSRelatedHelper; +import org.argeo.slc.core.test.context.ContextAware; +import org.argeo.slc.core.test.context.ContextUtils; + +/** Understands basic test data and context aware test data. */ +public class BasicTestDefinition extends TreeSRelatedHelper implements + TestDefinition { + + public void execute(TestRun testRun) { + if (testRun. getTestData() instanceof BasicTestData) { + BasicTestData testData = testRun.getTestData(); + TestResult result = testRun.getTestResult(); + + try { + if (testData.getExpected().equals(testData.getReached())) { + result.addResultPart(new SimpleResultPart( + TestStatus.PASSED, "Reached and expected equals")); + } else { + result.addResultPart(new SimpleResultPart( + TestStatus.FAILED, "Expected " + + testData.getExpected() + " but reched " + + testData.getReached())); + } + } catch (Exception e) { + result.addResultPart(new SimpleResultPart(TestStatus.ERROR, + "Could not compare", e)); + } + } else if (testRun. getTestData() instanceof ContextAware) { + TestData testData = testRun.getTestData(); + ContextUtils.compareReachedExpected((ContextAware) testData, + testRun.getTestResult(), this); + } else { + throw new SlcException("No test data defined."); + } + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/ExecutableTestRun.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/ExecutableTestRun.java new file mode 100644 index 000000000..34216799f --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/ExecutableTestRun.java @@ -0,0 +1,9 @@ +package org.argeo.slc.core.test; + +/** A test run that can be executed */ +public interface ExecutableTestRun extends TestRun { + + /** Executes this test run. */ + public void execute(); + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/IncompatibleTestDataException.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/IncompatibleTestDataException.java new file mode 100644 index 000000000..db4184d05 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/IncompatibleTestDataException.java @@ -0,0 +1,18 @@ +package org.argeo.slc.core.test; + +import org.argeo.slc.core.SlcException; + +/** + * Exception to throw when a test definition cannot interpret the provided test + * data. + */ +public class IncompatibleTestDataException extends SlcException { + static final long serialVersionUID = 1l; + + public IncompatibleTestDataException(TestData testData, + TestDefinition testDefinition) { + super("TestData " + testData.getClass() + + " is not compatible with TestDefinition " + + testDefinition.getClass()); + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/SimpleResultPart.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/SimpleResultPart.java new file mode 100644 index 000000000..db5f22228 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/SimpleResultPart.java @@ -0,0 +1,127 @@ +package org.argeo.slc.core.test; + +/** + *

+ * Basic implementation of a result part, implementing the standard three status + * approach for test results. + *

+ * + * @see TestStatus + */ +public class SimpleResultPart implements TestResultPart, TestStatus, + TestRunAware { + + private Long tid; + + private String testRunUuid; + + /** The status. Default to ERROR since it should always be explicitely set. */ + private Integer status = ERROR; + private String message; + private String exceptionMessage; + + public SimpleResultPart() { + } + + public SimpleResultPart(Integer status, String message) { + this(status, message, null); + } + + public SimpleResultPart(Integer status, String message, Exception exception) { + this.status = status; + this.message = message; + setException(exception); + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public Integer getStatus() { + return status; + } + + public String getExceptionMessage() { + return exceptionMessage; + } + + public void setException(Exception exception) { + if (exception == null) + return; + + StringBuffer buf = new StringBuffer(""); + buf.append(exception.toString()); + buf.append('\n'); + for (StackTraceElement elem : exception.getStackTrace()) { + buf.append('\t').append(elem.toString()).append('\n'); + } + + if (exception.getCause() != null) + addRootCause(buf, exception.getCause()); + + this.exceptionMessage = buf.toString(); + } + + protected void addRootCause(StringBuffer buf, Throwable cause) { + if (cause == null) + return; + + buf.append("Caused by: " + cause.getMessage()); + for (StackTraceElement elem : cause.getStackTrace()) { + buf.append('\t').append(elem.toString()).append('\n'); + } + + if (cause.getCause() != null) { + addRootCause(buf, cause.getCause()); + } + } + + @Override + public String toString() { + StringBuffer buf = new StringBuffer(""); + buf.append(SlcTestUtils.statusToString(status)); + if (status == PASSED || status == FAILED) { + buf.append(' '); + } else if (status == ERROR) { + buf.append(" "); + } + buf.append(message); + return buf.toString(); + } + + /** @deprecated */ + Long getTid() { + return tid; + } + + /** @deprecated */ + void setTid(Long tid) { + this.tid = tid; + } + + public String getTestRunUuid() { + return testRunUuid; + } + + /** For ORM */ + public void setTestRunUuid(String testRunUuid) { + this.testRunUuid = testRunUuid; + } + + public void notifyTestRun(TestRun testRun) { + testRunUuid = testRun.getUuid(); + } + + public void setExceptionMessage(String exceptionMessage) { + this.exceptionMessage = exceptionMessage; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/SimpleTestResult.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/SimpleTestResult.java new file mode 100644 index 000000000..4dcc63bbf --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/SimpleTestResult.java @@ -0,0 +1,82 @@ +package org.argeo.slc.core.test; + +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.UUID; +import java.util.Vector; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.argeo.slc.core.SlcException; + +/** + * Basic implementation of a test result containing only a list of result parts. + */ +public class SimpleTestResult implements TestResult { + private static Log log = LogFactory.getLog(SimpleTestResult.class); + + private String uuid; + private String currentTestRunUuid; + + private Boolean throwError = true; + + private Date closeDate; + private List parts = new Vector(); + + private Map attributes = new TreeMap(); + + public void addResultPart(TestResultPart part) { + if (throwError && part.getStatus() == ERROR) { + throw new SlcException( + "There was an error in the underlying test: " + + part.getExceptionMessage()); + } + parts.add(part); + if (log.isDebugEnabled()) + log.debug(part); + } + + public void close() { + parts.clear(); + closeDate = new Date(); + } + + public List getParts() { + return parts; + } + + public Date getCloseDate() { + return closeDate; + } + + public void setThrowError(Boolean throwError) { + this.throwError = throwError; + } + + public void notifyTestRun(TestRun testRun) { + currentTestRunUuid = testRun.getUuid(); + } + + public String getUuid() { + if (uuid == null) { + uuid = UUID.randomUUID().toString(); + } + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getCurrentTestRunUuid() { + return currentTestRunUuid; + } + + public Map getAttributes() { + return attributes; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/SimpleTestRun.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/SimpleTestRun.java new file mode 100644 index 000000000..bbe5b215c --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/SimpleTestRun.java @@ -0,0 +1,98 @@ +package org.argeo.slc.core.test; + +import java.util.UUID; + +import org.argeo.slc.core.deploy.DeployedSystem; +import org.argeo.slc.core.process.SlcExecution; +import org.argeo.slc.core.process.SlcExecutionStep; + +/** + * A basic bean implementation of a WritableTestRun, holding + * references to the various parts of a test run. + */ +public class SimpleTestRun implements WritableTestRun, ExecutableTestRun { + private String uuid; + + private String slcExecutionUuid; + private String slcExecutionStepUuid; + + private DeployedSystem deployedSystem; + private TestData testData; + private TestDefinition testDefinition; + private TestResult testResult; + + /** Executes the underlying test definition. */ + public void execute() { + uuid = UUID.randomUUID().toString(); + if (testResult != null) + testResult.notifyTestRun(this); + testDefinition.execute(this); + } + + public T getDeployedSystem() { + return (T) deployedSystem; + } + + public void setDeployedSystem(DeployedSystem deployedSystem) { + this.deployedSystem = deployedSystem; + } + + public T getTestData() { + return (T) testData; + } + + public void setTestData(TestData testData) { + this.testData = testData; + } + + public T getTestDefinition() { + return (T) testDefinition; + } + + public void setTestDefinition(TestDefinition testDefinition) { + this.testDefinition = testDefinition; + } + + public T getTestResult() { + return (T) testResult; + } + + public void setTestResult(TestResult testResult) { + this.testResult = testResult; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getSlcExecutionUuid() { + return slcExecutionUuid; + } + + public void setSlcExecutionUuid(String slcExecutionUuid) { + this.slcExecutionUuid = slcExecutionUuid; + } + + public String getSlcExecutionStepUuid() { + return slcExecutionStepUuid; + } + + public void setSlcExecutionStepUuid(String slcExecutionStepUuid) { + this.slcExecutionStepUuid = slcExecutionStepUuid; + } + + public void notifySlcExecution(SlcExecution slcExecution) { + if (slcExecution != null) { + slcExecutionUuid = slcExecution.getUuid(); + SlcExecutionStep step = slcExecution.currentStep(); + if (step != null) { + slcExecutionStepUuid = step.getUuid(); + } + } + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/SlcTestUtils.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/SlcTestUtils.java new file mode 100644 index 000000000..9eeda4064 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/SlcTestUtils.java @@ -0,0 +1,34 @@ +package org.argeo.slc.core.test; + +import org.argeo.slc.core.SlcException; + +public abstract class SlcTestUtils { + public static String statusToString(Integer status) { + if (status.equals(TestStatus.PASSED)) { + return TestStatus.STATUSSTR_PASSED; + } else if (status.equals(TestStatus.FAILED)) { + return TestStatus.STATUSSTR_FAILED; + } else if (status.equals(TestStatus.ERROR)) { + return TestStatus.STATUSSTR_ERROR; + } else { + throw new SlcException("Unrecognized status " + status); + } + } + + public static Integer stringToStatus(String statusStr) { + if (statusStr.equals(TestStatus.STATUSSTR_PASSED)) { + return TestStatus.PASSED; + } else if (statusStr.equals(TestStatus.STATUSSTR_FAILED)) { + return TestStatus.FAILED; + } else if (statusStr.equals(TestStatus.STATUSSTR_ERROR)) { + return TestStatus.ERROR; + } else { + throw new SlcException("Unrecognized status string " + statusStr); + } + } + + private SlcTestUtils() { + + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestData.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestData.java new file mode 100644 index 000000000..4105e0925 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestData.java @@ -0,0 +1,9 @@ +package org.argeo.slc.core.test; + +/** + * Any data required by a test in order to run: configuration, expected, + * reached, etc. + */ +public interface TestData { + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestDataProvider.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestDataProvider.java new file mode 100644 index 000000000..e0e02c3a6 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestDataProvider.java @@ -0,0 +1,5 @@ +package org.argeo.slc.core.test; + +public interface TestDataProvider { + public T getTestData(Class clss, String key); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestDataUtils.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestDataUtils.java new file mode 100644 index 000000000..66cae87c3 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestDataUtils.java @@ -0,0 +1,45 @@ +package org.argeo.slc.core.test; + +import org.argeo.slc.core.UnsupportedException; + +/** Utilities for dealing with test datas. */ +public class TestDataUtils { + /** Extracts the test data from the given provider. */ + public static T getFromProvider(Object obj, + Class clss, String key) { + if (obj instanceof TestDataProvider) { + TestDataProvider testDataProvider = (TestDataProvider) obj; + return testDataProvider.getTestData(clss, key); + } else { + throw new UnsupportedException("test data provider", obj); + } + } + + /** + * Extracts the test data from the given provider using null + * as key. + */ + public static T getFromProvider(Object obj, + Class clss) { + return getFromProvider(obj, clss, null); + } + + /** + * Returns it self after making the proper checks. Used for test data being + * their own data providers. + */ + public static T getItSelf(Class clss, + TestData testDataObject) { + if (clss.isAssignableFrom(testDataObject.getClass())) { + return (T) testDataObject; + } else { + throw new UnsupportedException("test data", testDataObject); + } + + } + + /** Makes sure this is an utility class. */ + private TestDataUtils() { + + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestDefinition.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestDefinition.java new file mode 100644 index 000000000..7c75d6a73 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestDefinition.java @@ -0,0 +1,10 @@ +package org.argeo.slc.core.test; + +/** + * The programmatic definition of a test, which will be associated with + * transient objects within a test run. + */ +public interface TestDefinition extends TestStatus { + /** Performs the test. */ + public void execute(TestRun testRun); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestReport.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestReport.java new file mode 100644 index 000000000..8256e8644 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestReport.java @@ -0,0 +1,10 @@ +package org.argeo.slc.core.test; + +/** + * A report that can be generated based on a given test result. This + * interface may change in the future. + */ +public interface TestReport { + /** Performs the actions necessary to generate a report. */ + public void generateTestReport(TestResult result); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestResult.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestResult.java new file mode 100644 index 000000000..5de69700c --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestResult.java @@ -0,0 +1,27 @@ +package org.argeo.slc.core.test; + +import java.util.Date; +import java.util.Map; + +/** The result of a test */ +public interface TestResult extends TestStatus, TestRunAware { + public String getUuid(); + + /** Adds a part of the result. */ + public void addResultPart(TestResultPart part); + + /** + * Marks that the collection of test results is completed and free the + * related resources (also closing listeners). + */ + public void close(); + + /** + * The date when this test result was closed. Can be null, which means the + * result is not closed. + */ + public Date getCloseDate(); + + /** Additional arbitrary meta data */ + public Map getAttributes(); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestResultListener.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestResultListener.java new file mode 100644 index 000000000..fc8f1d73f --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestResultListener.java @@ -0,0 +1,10 @@ +package org.argeo.slc.core.test; + +/** Listener to the operations on a test result. */ +public interface TestResultListener { + /** Notified when a part was added to a test result. */ + public void resultPartAdded(T testResult, TestResultPart testResultPart); + + /** Stops listening and release the related resources. */ + public void close(T testResult); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestResultPart.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestResultPart.java new file mode 100644 index 000000000..9956d8624 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestResultPart.java @@ -0,0 +1,17 @@ +package org.argeo.slc.core.test; + +/** + * Part of a test result. + * + * @see TestResult + */ +public interface TestResultPart { + /** The status, as defined in {@link TestStatus}. */ + public Integer getStatus(); + + /** The related message. */ + public String getMessage(); + + /** The underlying Exception. Can be null. */ + public String getExceptionMessage(); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestRun.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestRun.java new file mode 100644 index 000000000..17cf42394 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestRun.java @@ -0,0 +1,22 @@ +package org.argeo.slc.core.test; + +import org.argeo.slc.core.deploy.DeployedSystem; +import org.argeo.slc.core.process.SlcExecutionAware; + +/** The actual run of a test */ +public interface TestRun extends SlcExecutionAware { + /** Gets UUID */ + public String getUuid(); + + /** Gets the related test definition. */ + public T getTestDefinition(); + + /** Gets the related test data */ + public T getTestData(); + + /** Gets the related deployed system. */ + public T getDeployedSystem(); + + /** Gets the related result where to record results. */ + public T getTestResult(); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestRunAware.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestRunAware.java new file mode 100644 index 000000000..6cca1440e --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestRunAware.java @@ -0,0 +1,7 @@ +package org.argeo.slc.core.test; + +public interface TestRunAware { + /** Notifies the current test run. */ + public void notifyTestRun(TestRun testRun); + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestRunDescriptor.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestRunDescriptor.java new file mode 100644 index 000000000..d136e802c --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestRunDescriptor.java @@ -0,0 +1,81 @@ +package org.argeo.slc.core.test; + +import org.argeo.slc.core.deploy.DeployedSystem; + +public class TestRunDescriptor { + private String testRunUuid; + private String slcExecutionUuid; + private String slcExecutionStepUuid; + private String testResultUuid; + private String deployedSytemId; + + public TestRunDescriptor() { + + } + + public TestRunDescriptor(TestRun testRun) { + testRunUuid = testRun.getUuid(); + + if (testRun.getTestResult() != null) + testResultUuid = testRun. getTestResult().getUuid(); + + if (testRun.getDeployedSystem() != null) + deployedSytemId = testRun. getDeployedSystem() + .getDeployedSystemId(); + + if (testRun instanceof SimpleTestRun) { + slcExecutionUuid = ((SimpleTestRun) testRun).getSlcExecutionUuid(); + slcExecutionStepUuid = ((SimpleTestRun) testRun) + .getSlcExecutionStepUuid(); + } + } + + public String getTestRunUuid() { + return testRunUuid; + } + + public void setTestRunUuid(String testRunUuid) { + this.testRunUuid = testRunUuid; + } + + public String getSlcExecutionUuid() { + return slcExecutionUuid; + } + + public void setSlcExecutionUuid(String slcExecutionUuid) { + this.slcExecutionUuid = slcExecutionUuid; + } + + public String getSlcExecutionStepUuid() { + return slcExecutionStepUuid; + } + + public void setSlcExecutionStepUuid(String slcExecutionStepUuid) { + this.slcExecutionStepUuid = slcExecutionStepUuid; + } + + public String getTestResultUuid() { + return testResultUuid; + } + + public void setTestResultUuid(String testResultUuid) { + this.testResultUuid = testResultUuid; + } + + public String getDeployedSytemId() { + return deployedSytemId; + } + + public void setDeployedSytemId(String deploymentId) { + this.deployedSytemId = deploymentId; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof TestRunDescriptor) { + return getTestRunUuid().equals( + ((TestRunDescriptor) obj).getTestRunUuid()); + } + return false; + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestStatus.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestStatus.java new file mode 100644 index 000000000..d6954be8f --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/TestStatus.java @@ -0,0 +1,29 @@ +package org.argeo.slc.core.test; + +/** + * Simple statuses. + *

+ *

    + *
  • {@link #PASSED}: the test succeeded
  • + *
  • {@link #FAILED}: the test could run, but did not reach the expected + * result
  • + *
  • {@link #ERROR}: an error during the test run prevented to get a + * significant information on the tested system.
  • + *
+ *

+ */ +public interface TestStatus { + /** The flag for a passed test: 0 */ + public final static Integer PASSED = 0; + /** The flag for a failed test: 1 */ + public final static Integer FAILED = 1; + /** + * The flag for a test which could not properly run because of an error + * (there is no feedback on the behavior of the tested component): 2 + */ + public final static Integer ERROR = 2; + public final static String STATUSSTR_PASSED = "PASSED"; + public final static String STATUSSTR_FAILED = "FAILED"; + public final static String STATUSSTR_ERROR = "ERROR"; + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/WritableTestRun.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/WritableTestRun.java new file mode 100644 index 000000000..8cfe2b72c --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/WritableTestRun.java @@ -0,0 +1,14 @@ +package org.argeo.slc.core.test; + +import org.argeo.slc.core.deploy.DeployedSystem; + +/** Test run whose various components can be externally set. */ +public interface WritableTestRun extends ExecutableTestRun { + public void setDeployedSystem(DeployedSystem deployedSystem); + + public void setTestData(TestData testData); + + public void setTestDefinition(TestDefinition testDefinition); + + public void setTestResult(TestResult testResult); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/ContextAware.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/ContextAware.java new file mode 100644 index 000000000..5e411831e --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/ContextAware.java @@ -0,0 +1,18 @@ +package org.argeo.slc.core.test.context; + +import java.util.Map; + +public interface ContextAware { + public final static String DEFAULT_SKIP_FLAG = "!"; + public final static String DEFAULT_ANY_FLAG = "*"; + + public Map getValues(); + + public void setValues(Map values); + + public Map getExpectedValues(); + + public String getContextSkipFlag(); + + public String getContextAnyFlag(); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/ContextUtils.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/ContextUtils.java new file mode 100644 index 000000000..3826a8710 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/ContextUtils.java @@ -0,0 +1,165 @@ +package org.argeo.slc.core.test.context; + +import java.util.Map; +import java.util.TreeMap; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.argeo.slc.core.structure.StructureAware; +import org.argeo.slc.core.structure.StructureElement; +import org.argeo.slc.core.structure.StructureRegistry; +import org.argeo.slc.core.structure.tree.TreeSPath; +import org.argeo.slc.core.structure.tree.TreeSRelated; +import org.argeo.slc.core.test.SimpleResultPart; +import org.argeo.slc.core.test.TestResult; +import org.argeo.slc.core.test.TestStatus; + +public class ContextUtils { + private final static Log log = LogFactory.getLog(ContextUtils.class); + + public static void compareReachedExpected(ContextAware contextAware, + TestResult testResult, TreeSRelated treeSRelated) { + for (String key : contextAware.getExpectedValues().keySet()) { + + // Compare expected values with reached ones + Object expectedValue = contextAware.getExpectedValues().get(key); + + if (expectedValue.toString().equals( + contextAware.getContextSkipFlag())) { + if (log.isDebugEnabled()) + log.debug("Skipped check for key '" + key + "'"); + continue; + } + + // Register in structure + registerInStructure(testResult, treeSRelated, key); + + if (contextAware.getValues().containsKey(key)) { + Object reachedValue = contextAware.getValues().get(key); + + if (expectedValue.equals(contextAware.getContextAnyFlag())) { + testResult.addResultPart(new SimpleResultPart( + TestStatus.PASSED, "Expected any value for key '" + + key + "'")); + } else if (expectedValue.equals(reachedValue)) { + testResult.addResultPart(new SimpleResultPart( + TestStatus.PASSED, "Values matched for key '" + key + + "'")); + } else { + testResult.addResultPart(new SimpleResultPart( + TestStatus.FAILED, "Mismatch for key '" + key + + "': expected '" + expectedValue + + "' but reached '" + reachedValue + "'")); + } + } else { + testResult.addResultPart(new SimpleResultPart( + TestStatus.FAILED, "No value reached for key '" + key + + "'")); + } + resetStructure(testResult, treeSRelated); + } + } + + private static void registerInStructure(TestResult testResult, + TreeSRelated treeSRelated, String key) { + if (treeSRelated != null) { + if (treeSRelated.getBasePath() != null) { + TreeSPath path = treeSRelated.getBasePath().createChild(key); + StructureRegistry registry = treeSRelated + .getRegistry(); + final StructureElement element = treeSRelated + .getStructureElement(key); + registry.register(path, element); + if (testResult instanceof StructureAware) + ((StructureAware) testResult).notifyCurrentPath( + registry, path); + + if (log.isDebugEnabled()) + log.debug("Checking key " + key + " for path " + path); + } + } + } + + private static void resetStructure(TestResult testResult, + TreeSRelated treeSRelated) { + if (treeSRelated != null) { + if (treeSRelated.getBasePath() != null) { + if (testResult instanceof StructureAware) { + ((StructureAware) testResult).notifyCurrentPath( + treeSRelated.getRegistry(), treeSRelated + .getBasePath()); + } + } + } + } + + /** + * Makes sure that all children and sub-children of parent share the same + * maps for values and expected values. + */ + public static void synchronize(ParentContextAware parent) { + Map expectedValuesCommon = new TreeMap( + parent.getExpectedValues()); + synchronize(parent, expectedValuesCommon); + if (log.isDebugEnabled()) + log.debug("Synchonized context " + parent); + + } + + private static void synchronize(ParentContextAware parent, + Map expectedValuesCommon) { + for (ContextAware child : parent.getChildContexts()) { + // Values + putNotContained(parent.getValues(), child.getValues()); + child.setValues(parent.getValues()); + + // Expected Values + // Expected values reference is not overridden: each child has its + // own expected values map. + overrideContained(expectedValuesCommon, child.getExpectedValues()); + + // Creates a new Map in order not to disturb other context using the + // same keys + Map expectedValuesCommonChild = new TreeMap( + expectedValuesCommon); + putNotContained(expectedValuesCommonChild, child + .getExpectedValues()); + + if (child instanceof ParentContextAware) { + // Recursive sync + synchronize((ParentContextAware) child, + expectedValuesCommonChild); + } + } + + } + + /** + * Put into common map the values from child map which are not already + * defined in common map. + */ + public static void putNotContained(Map commonMap, + Map childMap) { + for (String key : childMap.keySet()) { + if (!commonMap.containsKey(key)) { + commonMap.put(key, childMap.get(key)); + } + } + } + + /** Overrides child map values with the values already set in common map */ + public static void overrideContained(Map commonMap, + Map childMap) { + for (String key : childMap.keySet()) { + if (commonMap.containsKey(key)) { + childMap.put(key, commonMap.get(key)); + } + } + } + + /** Makes sure this cannot be instantiated. */ + private ContextUtils() { + + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/DefaultContextTestData.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/DefaultContextTestData.java new file mode 100644 index 000000000..a39a91539 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/DefaultContextTestData.java @@ -0,0 +1,14 @@ +package org.argeo.slc.core.test.context; + +import org.argeo.slc.core.test.TestData; +import org.argeo.slc.core.test.TestDataProvider; +import org.argeo.slc.core.test.TestDataUtils; + +public class DefaultContextTestData extends SimpleContextAware implements + TestData, TestDataProvider { + + public T getTestData(Class clss, String key) { + return TestDataUtils.getItSelf(clss, this); + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/ParentContextAware.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/ParentContextAware.java new file mode 100644 index 000000000..5d13324a2 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/ParentContextAware.java @@ -0,0 +1,9 @@ +package org.argeo.slc.core.test.context; + +import java.util.Collection; + +public interface ParentContextAware extends ContextAware { + public Collection getChildContexts(); + + public void addChildContext(ContextAware contextAware); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/SimpleContextAware.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/SimpleContextAware.java new file mode 100644 index 000000000..c4fb5ab40 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/SimpleContextAware.java @@ -0,0 +1,69 @@ +package org.argeo.slc.core.test.context; + +import java.util.Map; +import java.util.TreeMap; + +import org.springframework.beans.factory.InitializingBean; + +import org.argeo.slc.core.SlcException; + +public class SimpleContextAware implements ContextAware, InitializingBean { + private ParentContextAware parentContext; + + private Map values = new TreeMap(); + private Map expectedValues = new TreeMap(); + + private String contextSkipFlag = DEFAULT_SKIP_FLAG; + private String contextAnyFlag = DEFAULT_ANY_FLAG; + + public Map getValues() { + return values; + } + + public void setValues(Map values) { + this.values = values; + } + + public Map getExpectedValues() { + return expectedValues; + } + + public void setExpectedValues(Map expectedValues) { + this.expectedValues = expectedValues; + } + + /** Used to add this context as a child by setting a property. */ + public void setParentContext(ParentContextAware parentContextAware) { + if (parentContext != null) + throw new SlcException("Parent context already set"); + this.parentContext = parentContextAware; + this.parentContext.addChildContext(this); + } + + protected ParentContextAware getParentContext() { + return parentContext; + } + + public void afterPropertiesSet() throws Exception { + if (parentContext != null) { + ContextUtils.synchronize(parentContext); + } + } + + public String getContextSkipFlag() { + return contextSkipFlag; + } + + public void setContextSkipFlag(String contextSkipFlag) { + this.contextSkipFlag = contextSkipFlag; + } + + public String getContextAnyFlag() { + return contextAnyFlag; + } + + public void setContextAnyFlag(String contextAnyFlag) { + this.contextAnyFlag = contextAnyFlag; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/SimpleParentContextAware.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/SimpleParentContextAware.java new file mode 100644 index 000000000..76ea43f3c --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/SimpleParentContextAware.java @@ -0,0 +1,33 @@ +package org.argeo.slc.core.test.context; + +import java.util.Collection; +import java.util.List; +import java.util.Vector; + +import org.springframework.beans.factory.InitializingBean; + +public class SimpleParentContextAware extends SimpleContextAware implements + ParentContextAware, InitializingBean { + private List children = new Vector(); + + public Collection getChildContexts() { + return children; + } + + public void addChildContext(ContextAware contextAware) { + children.add(contextAware); + } + + @Override + public void afterPropertiesSet() throws Exception { + if (getParentContext() != null) { + // If has a parent, sync it. + super.afterPropertiesSet(); + } else { + if (children.size() > 0) { + // No need to synchronize if no children + ContextUtils.synchronize(this); + } + } + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/package.html b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/package.html new file mode 100644 index 000000000..cd08d63f3 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/context/package.html @@ -0,0 +1,6 @@ + + + +Context variables to be passed between parts of tests. + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/package.html b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/package.html new file mode 100644 index 000000000..c70d2d151 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/package.html @@ -0,0 +1,6 @@ + + + +SLC Test: test of software systems. + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/CompositeTreeTestDefinition.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/CompositeTreeTestDefinition.java new file mode 100644 index 000000000..3468bcb25 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/CompositeTreeTestDefinition.java @@ -0,0 +1,89 @@ +package org.argeo.slc.core.test.tree; + +import java.util.List; +import java.util.Vector; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.core.structure.SimpleSElement; +import org.argeo.slc.core.structure.StructureAware; +import org.argeo.slc.core.structure.StructureElement; +import org.argeo.slc.core.structure.StructureElementProvider; +import org.argeo.slc.core.structure.StructureRegistry; +import org.argeo.slc.core.structure.tree.TreeSPath; +import org.argeo.slc.core.test.TestDefinition; +import org.argeo.slc.core.test.TestResult; +import org.argeo.slc.core.test.TestRun; + +/** + * Collection of test definitions propagating tree structure information to its + * children. + */ +public class CompositeTreeTestDefinition implements TestDefinition, + StructureAware { + private Log log = LogFactory.getLog(CompositeTreeTestDefinition.class); + + private List tasks = null; + private List taskPaths = null; + private TreeSPath path; + private StructureRegistry registry; + + public void execute(TestRun testRun) { + if (log.isTraceEnabled()) + log.trace("Execute sequence of test definitions..."); + + int i = 0; + for (TestDefinition task : tasks) { + TestResult result = testRun.getTestResult(); + if (result instanceof StructureAware) { + ((StructureAware) result).notifyCurrentPath(registry, taskPaths + .get(i)); + } + + task.execute(testRun); + + // Reset current path in case it has been changed + if (result instanceof StructureAware) { + ((StructureAware) result).notifyCurrentPath(registry, path); + } + i++; + } + } + + /** Sets the list of children test definitions */ + public void setTasks(List tasks) { + this.tasks = tasks; + if (tasks != null) { + taskPaths = new Vector(); + } + } + + public void notifyCurrentPath(StructureRegistry registry, + TreeSPath path) { + this.path = path; + this.registry = registry; + + // clear task paths + taskPaths.clear(); + + Integer count = 0; + for (TestDefinition task : tasks) { + final StructureElement element; + if (task instanceof StructureElementProvider) { + element = ((StructureElementProvider) task) + .createStructureElement(); + } else { + element = new SimpleSElement("[no desc]"); + } + TreeSPath taskPath = this.path.createChild(count.toString()); + registry.register(taskPath, element); + taskPaths.add(taskPath); + if (task instanceof StructureAware) { + ((StructureAware) task).notifyCurrentPath(registry, + taskPath); + } + count++; + } + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/PartSubList.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/PartSubList.java new file mode 100644 index 000000000..128da6abb --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/PartSubList.java @@ -0,0 +1,50 @@ +package org.argeo.slc.core.test.tree; + +import java.util.List; +import java.util.Vector; + +import org.argeo.slc.core.test.TestResultPart; +import org.argeo.slc.core.test.TestStatus; + +/** + * List of TestResultPart. It can be used to build complex + * TestResult affording the possibility to a + * TestDefinition to add a list of result part under the same + * StructurePath. + * + * @see TreeTestResult + */ +public class PartSubList { + + /** For ORM */ + private Long tid; + + private List parts = new Vector(); + + /** Gets the result parts. */ + public List getParts() { + return parts; + } + + /** Sets the result parts. */ + public void setParts(List parts) { + this.parts = parts; + } + + Long getTid() { + return tid; + } + + void setTid(Long tid) { + this.tid = tid; + } + + public Boolean getIsPassed() { + for (TestResultPart part : parts) { + if (part.getStatus() != TestStatus.PASSED) { + return false; + } + } + return true; + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/TreeTestResult.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/TreeTestResult.java new file mode 100644 index 000000000..3e365afe0 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/TreeTestResult.java @@ -0,0 +1,219 @@ +package org.argeo.slc.core.test.tree; + +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.Vector; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.core.SlcException; +import org.argeo.slc.core.structure.StructureAware; +import org.argeo.slc.core.structure.StructureElement; +import org.argeo.slc.core.structure.StructureRegistry; +import org.argeo.slc.core.structure.tree.TreeSPath; +import org.argeo.slc.core.test.TestResult; +import org.argeo.slc.core.test.TestResultListener; +import org.argeo.slc.core.test.TestResultPart; +import org.argeo.slc.core.test.TestRun; +import org.argeo.slc.core.test.TestRunAware; + +/** + * Complex implementation of a test result compatible with a tree based + * structure. + */ +public class TreeTestResult implements TestResult, StructureAware, + Comparable { + private Log log = LogFactory.getLog(TreeTestResult.class); + + private List> listeners = new Vector>(); + + private TreeSPath currentPath; + private TestRun currentTestRun; + + private Date closeDate; + + private Boolean isClosed = false; + + private Boolean warnIfAlreadyClosed = true; + + private String uuid; + + private SortedMap resultParts = new TreeMap(); + private SortedMap elements = new TreeMap(); + + private Map attributes = new TreeMap(); + + /** Sets the list of listeners. */ + public void setListeners(List> listeners) { + this.listeners = listeners; + } + + public void addResultPart(TestResultPart part) { + if (isClosed) + throw new SlcException("Cannot result parts to a closed result"); + + if (currentPath == null) + throw new SlcException("No current path set."); + + PartSubList subList = resultParts.get(currentPath); + if (subList == null) { + subList = new PartSubList(); + resultParts.put(currentPath, subList); + } + if (part instanceof TestRunAware && currentTestRun != null) { + ((TestRunAware) part).notifyTestRun(currentTestRun); + } + subList.getParts().add(part); + + // notify listeners + synchronized (listeners) { + for (TestResultListener listener : listeners) { + listener.resultPartAdded(this, part); + } + } + } + + public void notifyCurrentPath(StructureRegistry registry, + TreeSPath path) { + if (registry != null) { + for (TreeSPath p : path.getHierarchyAsList()) { + if (!elements.containsKey(p)) { + StructureElement elem = registry.getElement(p); + if (elem != null) { + elements.put(p, elem); + } + } else { + if (log.isTraceEnabled()) + log.trace("An element is already registered for path " + + p + " and was not updated"); + } + + } + } + + currentPath = path; + } + + /** Gets the current path. */ + public TreeSPath getCurrentPath() { + return currentPath; + } + + /** Gets all the results structured as a map of PartSubLists. */ + public SortedMap getResultParts() { + return resultParts; + } + + /** Used by ORM systems. */ + void setResultParts(SortedMap resultParts) { + this.resultParts = resultParts; + } + + public void close() { + if (resultParts.size() == 0) { + if (log.isTraceEnabled()) + log.trace("Test Result #" + getUuid() + + " contains no results, no need to close it."); + return; + } + + if (isClosed) { + if (warnIfAlreadyClosed) + log.warn("Test Result #" + getUuid() + + " already closed. Doing nothing."); + return; + } + + closeDate = new Date(); + + synchronized (listeners) { + for (TestResultListener listener : listeners) { + listener.close(this); + } + listeners.clear(); + } + isClosed = true; + + if (log.isTraceEnabled()) + log.trace("Test Result " + getUuid() + " closed."); + } + + public Date getCloseDate() { + return closeDate; + } + + /** Sets the close date (for ORM) */ + public void setCloseDate(Date closeDate) { + this.closeDate = closeDate; + } + + public void notifyTestRun(TestRun testRun) { + currentTestRun = testRun; + } + + public SortedMap getElements() { + return elements; + } + + public void setElements(SortedMap pathNames) { + this.elements = pathNames; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public SortedMap getRelatedElements( + TreeSPath path) { + if (path == null) + throw new SlcException( + "Cannot retrieve element for a null path in result #" + + uuid); + + SortedMap relatedElements = new TreeMap(); + List hierarchy = path.getHierarchyAsList(); + for (TreeSPath currPath : elements.keySet()) { + if (hierarchy.contains(currPath)) { + relatedElements.put(currPath, elements.get(currPath)); + } + } + return relatedElements; + } + + public TestRun getCurrentTestRun() { + return currentTestRun; + } + + public int compareTo(TreeTestResult ttr2) { + TreeTestResult ttr1 = this; + if (ttr1.getCloseDate() != null && ttr2.getCloseDate() != null) { + return -ttr1.getCloseDate().compareTo(ttr2.getCloseDate()); + } else if (ttr1.getCloseDate() != null && ttr2.getCloseDate() == null) { + return 1; + } else if (ttr1.getCloseDate() == null && ttr2.getCloseDate() != null) { + return -1; + } else { + return ttr1.getUuid().compareTo(ttr2.getUuid()); + } + } + + public Map getAttributes() { + return attributes; + } + + public void setAttributes(Map attributes) { + this.attributes = attributes; + } + + public void setWarnIfAlreadyClosed(Boolean warnIfAlreadyClosed) { + this.warnIfAlreadyClosed = warnIfAlreadyClosed; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/TreeTestResultCollection.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/TreeTestResultCollection.java new file mode 100644 index 000000000..1c454687c --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/TreeTestResultCollection.java @@ -0,0 +1,45 @@ +package org.argeo.slc.core.test.tree; + +import java.util.SortedSet; +import java.util.TreeSet; + +public class TreeTestResultCollection implements + Comparable { + private String id; + private SortedSet results = new TreeSet(); + + public TreeTestResultCollection() { + } + + public TreeTestResultCollection(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public SortedSet getResults() { + return results; + } + + public void setResults(SortedSet results) { + this.results = results; + } + + public int compareTo(TreeTestResultCollection o) { + return getId().compareTo(o.getId()); + } + + @Override + public boolean equals(Object o) { + if (o instanceof TreeTestResultCollection) { + return getId().equals(((TreeTestResultCollection) o).getId()); + } + return false; + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/TreeTestResultLogger.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/TreeTestResultLogger.java new file mode 100644 index 000000000..535abe61b --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/TreeTestResultLogger.java @@ -0,0 +1,52 @@ +package org.argeo.slc.core.test.tree; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.argeo.slc.core.test.TestResultListener; +import org.argeo.slc.core.test.TestResultPart; +import org.argeo.slc.core.test.TestStatus; + +/** + * Listener logging tree-based test results to the underlying logging system. + * + * @see TreeTestResult + * + */ +public class TreeTestResultLogger implements TestResultListener { + + private static Log log = LogFactory.getLog(TreeTestResultLogger.class); + + private Boolean logExceptionMessages = false; + + public void resultPartAdded(TreeTestResult testResult, + TestResultPart testResultPart) { + String msg = testResultPart + " - " + testResult.getUuid() + ":" + + testResult.getCurrentPath(); + if (testResultPart.getStatus().equals(TestStatus.PASSED)) { + log.info(msg); + } else if (testResultPart.getStatus().equals(TestStatus.FAILED)) { + log.warn(msg); + } else if (testResultPart.getStatus().equals(TestStatus.ERROR)) { + if (logExceptionMessages) + msg = msg + "\n" + testResultPart.getExceptionMessage(); + + log.error(msg); + + if (!logExceptionMessages || log.isDebugEnabled()) + log.debug(testResultPart.getExceptionMessage()); + + } else { + log.error("Unknow test status: " + msg); + } + } + + public void close(TreeTestResult testResult) { + log.info("Test result " + testResult.getUuid() + " closed."); + } + + public void setLogExceptionMessages(Boolean logExceptionMessages) { + this.logExceptionMessages = logExceptionMessages; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/XsltReportGenerator.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/XsltReportGenerator.java new file mode 100644 index 000000000..059c209f1 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/XsltReportGenerator.java @@ -0,0 +1,156 @@ +package org.argeo.slc.core.test.tree; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Templates; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.springframework.core.io.Resource; +import org.springframework.oxm.Marshaller; +import org.springframework.xml.transform.StringResult; +import org.w3c.dom.Document; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.argeo.slc.core.SlcException; +import org.argeo.slc.core.test.TestResultListener; +import org.argeo.slc.core.test.TestResultPart; + +public class XsltReportGenerator implements TestResultListener { + private Log log = LogFactory.getLog(getClass()); + + private DocumentBuilder documentBuilder = null; + + private Resource xsltStyleSheet; + + private Templates templates; + + private Marshaller marshaller; + + private String outputDir; + private String outputFileExtension = "html"; + + private Boolean logXml = false; + + public void init() { + if (templates != null) + return; + + if (xsltStyleSheet == null) + throw new SlcException("XSLT style sheet not specified."); + + InputStream in = null; + try { + TransformerFactory transformerFactory = TransformerFactory + .newInstance(); + in = xsltStyleSheet.getInputStream(); + StreamSource xsltSource = new StreamSource(in); + templates = transformerFactory.newTemplates(xsltSource); + } catch (Exception e) { + throw new SlcException("Could not initialize templates", e); + } finally { + IOUtils.closeQuietly(in); + } + } + + public void resultPartAdded(TreeTestResult testResult, + TestResultPart testResultPart) { + + } + + public void close(TreeTestResult testResult) { + if (templates == null) + throw new SlcException("XSLT template not initialized"); + + File file = getFile(testResult); + OutputStream out = null; + + try { + Transformer transformer = templates.newTransformer(); + + if (documentBuilder == null) + documentBuilder = DocumentBuilderFactory.newInstance() + .newDocumentBuilder(); + + Document document = documentBuilder.newDocument(); + DOMResult marshallResult = new DOMResult(document); + marshaller.marshal(testResult, marshallResult); + + if (logXml) { + Transformer identityTransformer = TransformerFactory + .newInstance().newTransformer(); + StringResult xmlResult = new StringResult(); + identityTransformer.transform(new DOMSource(marshallResult + .getNode()), xmlResult); + log.info("Marshalled XML:\n" + xmlResult); + } + + DOMSource transfoSource = new DOMSource(marshallResult.getNode()); + + if (outputDir != null) { + File dir = new File(outputDir); + dir.mkdirs(); + out = new FileOutputStream(file); + StreamResult outputResult = new StreamResult(out); + transformer.transform(transfoSource, outputResult); + } else { + // print on console if no output dir + StringResult result = new StringResult(); + transformer.transform(transfoSource, result); + log.info("Generated report:\n" + result); + } + } catch (Exception e) { + throw new SlcException( + "Could not transform test result to " + file, e); + } finally { + IOUtils.closeQuietly(out); + } + } + + public Resource getXsltStyleSheet() { + return xsltStyleSheet; + } + + public void setXsltStyleSheet(Resource xsltStyleSheet) { + this.xsltStyleSheet = xsltStyleSheet; + } + + public void setTemplates(Templates templates) { + this.templates = templates; + } + + public void setMarshaller(Marshaller marshaller) { + this.marshaller = marshaller; + } + + public void setOutputDir(String outputDir) { + this.outputDir = outputDir; + } + + public void setOutputFileExtension(String outputFileExtension) { + this.outputFileExtension = outputFileExtension; + } + + protected File getFile(TreeTestResult result) { + Long time = System.currentTimeMillis(); + return new File(outputDir + File.separator + time + "-" + + result.getUuid() + "." + outputFileExtension); + } + + public void setLogXml(Boolean logXml) { + this.logXml = logXml; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/package.html b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/package.html new file mode 100644 index 000000000..8ad12037e --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/core/test/tree/package.html @@ -0,0 +1,6 @@ + + + +Extension of SLC Test integrating tree-based structure. + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/process/SlcExecutionDao.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/process/SlcExecutionDao.java new file mode 100644 index 000000000..ca3d9f46a --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/process/SlcExecutionDao.java @@ -0,0 +1,21 @@ +package org.argeo.slc.dao.process; + +import java.util.List; + +import org.argeo.slc.core.process.SlcExecution; +import org.argeo.slc.core.process.SlcExecutionStep; + +public interface SlcExecutionDao { + public void create(SlcExecution slcExecution); + + public void update(SlcExecution slcExecution); + + public void merge(SlcExecution slcExecution); + + public SlcExecution getSlcExecution(String uuid); + + public List listSlcExecutions(); + + public void addSteps(String slcExecutionId, + List additionalSteps); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/test/TestResultDao.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/test/TestResultDao.java new file mode 100644 index 000000000..6b72cfa7c --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/test/TestResultDao.java @@ -0,0 +1,27 @@ +package org.argeo.slc.dao.test; + +import java.util.Date; +import java.util.List; + +import org.argeo.slc.core.test.TestResult; + +/** + * The dao for TestResult. + * + * @see TestResult + */ +public interface TestResultDao { + /** Gets a test result based on its id. */ + public T getTestResult(String uuid); + + /** Persists a new test result. */ + public void create(TestResult testResult); + + /** Updates an already persisted test result. */ + public void update(TestResult testResult); + + /** Lists all test results. */ + public List listTestResults(); + + public void close(String id, Date closeDate); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/test/TestRunDescriptorDao.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/test/TestRunDescriptorDao.java new file mode 100644 index 000000000..53bc89a3c --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/test/TestRunDescriptorDao.java @@ -0,0 +1,9 @@ +package org.argeo.slc.dao.test; + +import org.argeo.slc.core.test.TestRunDescriptor; + +public interface TestRunDescriptorDao { + public TestRunDescriptor getTestRunDescriptor(String id); + + public void saveOrUpdate(TestRunDescriptor testRunDescriptor); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/test/package.html b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/test/package.html new file mode 100644 index 000000000..38ae2b5bf --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/test/package.html @@ -0,0 +1,6 @@ + + + +Data Access Objects for SLC Test. + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/test/tree/TreeTestResultCollectionDao.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/test/tree/TreeTestResultCollectionDao.java new file mode 100644 index 000000000..730c9d988 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/test/tree/TreeTestResultCollectionDao.java @@ -0,0 +1,22 @@ +package org.argeo.slc.dao.test.tree; + +import java.util.SortedSet; + +import org.argeo.slc.core.test.tree.TreeTestResultCollection; + +public interface TreeTestResultCollectionDao { + public void create(TreeTestResultCollection ttrCollection); + + public void update(TreeTestResultCollection ttrCollection); + + public TreeTestResultCollection getTestResultCollection(String id); + + public SortedSet listCollections(); + + public void addResultToCollection(TreeTestResultCollection ttrc, + String resultUuid); + + public void removeResultFromCollection(TreeTestResultCollection ttrc, + String resultUuid); + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/test/tree/TreeTestResultDao.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/test/tree/TreeTestResultDao.java new file mode 100644 index 000000000..70db08790 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/test/tree/TreeTestResultDao.java @@ -0,0 +1,22 @@ +package org.argeo.slc.dao.test.tree; + +import java.util.List; +import java.util.Map; + +import org.argeo.slc.core.structure.StructureElement; +import org.argeo.slc.core.structure.tree.TreeSPath; +import org.argeo.slc.core.test.SimpleResultPart; +import org.argeo.slc.core.test.tree.TreeTestResult; +import org.argeo.slc.dao.test.TestResultDao; + +public interface TreeTestResultDao extends TestResultDao { + /** Lists results containing this path */ + public List listResults(TreeSPath path); + + public void addResultPart(String testResultId, TreeSPath path, + SimpleResultPart resultPart, + Map relatedElements); + + public void updateAttributes(String testResultId, + Map attributes); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/test/tree/TreeTestResultPersister.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/test/tree/TreeTestResultPersister.java new file mode 100644 index 000000000..73766ead6 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/dao/test/tree/TreeTestResultPersister.java @@ -0,0 +1,55 @@ +package org.argeo.slc.dao.test.tree; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.argeo.slc.core.test.TestResultListener; +import org.argeo.slc.core.test.TestResultPart; +import org.argeo.slc.core.test.tree.TreeTestResult; + +/** + * Listener persisting tree-based results. + * + * @see TreeTestResult + */ +public class TreeTestResultPersister implements + TestResultListener { + private static Log log = LogFactory.getLog(TreeTestResultPersister.class); + + private TreeTestResultDao testResultDao; + + public void resultPartAdded(TreeTestResult testResult, + TestResultPart testResultPart) { + try { + TreeTestResult persistedResult = testResultDao + .getTestResult(testResult.getUuid()); + + if (persistedResult == null) { + testResultDao.create(testResult); + } else { + testResultDao.update(testResult); + } + } catch (Exception e) { + log.error("Could not persist result part " + testResultPart + + " for result " + testResult.getUuid()); + } + } + + public void close(TreeTestResult testResult) { + TreeTestResult persistedResult = (TreeTestResult) testResultDao + .getTestResult(testResult.getUuid()); + + if (persistedResult != null) { + persistedResult.setCloseDate(testResult.getCloseDate()); + testResultDao.update(persistedResult); + } + if (log.isDebugEnabled()) + log.debug("Closed result persister for result " + + testResult.getUuid()); + } + + /** Sets the DAO to use in order to persist the results. */ + public void setTestResultDao(TreeTestResultDao testResultDao) { + this.testResultDao = testResultDao; + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DataInterpreter.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DataInterpreter.java new file mode 100644 index 000000000..7a57b0552 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DataInterpreter.java @@ -0,0 +1,20 @@ +package org.argeo.slc.diff; + +/** + * Converts data into a format better adapted for comparison. It is typically + * used to convert String into typed format such as + * BigDecimal + */ +public interface DataInterpreter { + /** + * Converts data + * + * @param key + * any object used to differentiate the type of data (e.g. + * column, path) + * @param value + * the data to convert + * @return the converted object + */ + public Object convert(Object key, Object value); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/Diff.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/Diff.java new file mode 100644 index 000000000..0b28996e9 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/Diff.java @@ -0,0 +1,9 @@ +package org.argeo.slc.diff; + +import org.springframework.core.io.Resource; + +/** A comparator providing structured information about the differences found. */ +public interface Diff { + /** Performs the comparison. */ + public DiffResult compare(Resource expected, Resource reached); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffIssue.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffIssue.java new file mode 100644 index 000000000..5517b3a66 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffIssue.java @@ -0,0 +1,22 @@ +package org.argeo.slc.diff; + +/** The root class for issues which happened during a diff. */ +public abstract class DiffIssue implements Comparable { + /** The position of this issue. */ + protected final DiffPosition position; + + /** Constructor */ + public DiffIssue(DiffPosition position) { + super(); + this.position = position; + } + + public int compareTo(DiffIssue o) { + return position.compareTo(o.position); + } + + /** The position of this issue within the test file */ + public DiffPosition getPosition() { + return position; + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffIssueKey.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffIssueKey.java new file mode 100644 index 000000000..9894edd32 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffIssueKey.java @@ -0,0 +1,31 @@ +package org.argeo.slc.diff; + +/** Intermediate class that can hold the key to be displayed. */ +public abstract class DiffIssueKey extends DiffIssue { + /** The position of this issue. */ + protected DiffKey key; + + /** Constructor without key */ + public DiffIssueKey(DiffPosition position) { + super(position); + } + + /** Constructor with key */ + public DiffIssueKey(DiffPosition position, DiffKey key) { + super(position); + this.key = key; + } + + public Object getKey() { + return key; + } + + @Override + public String toString() { + if (key != null) { + return key.toString(); + } else { + return ""; + } + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffKey.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffKey.java new file mode 100644 index 000000000..9d34f720a --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffKey.java @@ -0,0 +1,9 @@ +package org.argeo.slc.diff; + +/** + * Object able to uniquely identify an atomic diff part. Used to identify + * missings and left-overs. + */ +public interface DiffKey { + public String toString(); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffMissing.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffMissing.java new file mode 100644 index 000000000..fe2ab106f --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffMissing.java @@ -0,0 +1,26 @@ +package org.argeo.slc.diff; + +/** + * A value missing in one of the file. If its position is related to expected, + * this means it is a left over in the reached, if its position is related to + * the reached it means that it is missing from the reached. If the value is + * null it means that the entire line is missing. + */ +public class DiffMissing extends DiffIssueKey { + + public DiffMissing(DiffPosition position, DiffKey key) { + super(position); + super.key = key; + } + + @Override + public String toString() { + if (position.relatedFile == RelatedFile.EXPECTED) { + return position + ": left over " + super.toString(); + } else if (position.relatedFile == RelatedFile.REACHED) { + return position + ": missing " + super.toString(); + } + return super.toString(); + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffMissingXml.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffMissingXml.java new file mode 100644 index 000000000..ca3fd21a2 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffMissingXml.java @@ -0,0 +1,43 @@ +package org.argeo.slc.diff; + +/** + * DiffMissing using the XPath of the position as + * DiffKey + */ +public class DiffMissingXml extends DiffMissing { + + public DiffMissingXml(XPathDiffPosition position) { + super(position, new DiffKeyXml(position.getXPath())); + } + + /** Implementation of DiffKey based on an XPath string. */ + protected static class DiffKeyXml implements DiffKey { + private final String xPath; + + public DiffKeyXml(String xPath) { + this.xPath = xPath; + } + + public String getXPath() { + return xPath; + } + + @Override + public String toString() { + return xPath; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof DiffKeyXml)) + return false; + return xPath.equals(((DiffKeyXml) obj).xPath); + } + + @Override + public int hashCode() { + return xPath.hashCode(); + } + + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffNotMatched.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffNotMatched.java new file mode 100644 index 000000000..4b205e98f --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffNotMatched.java @@ -0,0 +1,40 @@ +package org.argeo.slc.diff; + +/** Diff issue where reached and expected values are different. */ +public class DiffNotMatched extends DiffIssueKey { + private final Object expected; + private final Object reached; + + public DiffNotMatched(DiffPosition position, Object expected, Object reached) { + super(position); + this.expected = expected; + this.reached = reached; + } + + public DiffNotMatched(DiffPosition position, Object expected, + Object reached, DiffKey key) { + super(position, key); + this.expected = expected; + this.reached = reached; + } + + public Object getExpected() { + return expected; + } + + public Object getReached() { + return reached; + } + + @Override + public String toString() { + String result = position + ": not matched " + expected + " <> " + + reached; + if (super.key != null) { + result = result + " - Key: " + super.toString(); + } + + return result; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffPosition.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffPosition.java new file mode 100644 index 000000000..302c0afa9 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffPosition.java @@ -0,0 +1,16 @@ +package org.argeo.slc.diff; + +/** The position of a diff issue within the test resource. */ +public abstract class DiffPosition implements Comparable { + protected RelatedFile relatedFile; + + public DiffPosition(RelatedFile relatedFile) { + super(); + this.relatedFile = relatedFile; + } + + public RelatedFile getRelatedFile() { + return relatedFile; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffResult.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffResult.java new file mode 100644 index 000000000..0e29fdd05 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/DiffResult.java @@ -0,0 +1,12 @@ +package org.argeo.slc.diff; + +import java.util.List; + +/** + * The result of a diff. Can be subclassed to provided more structured + * information. + */ +public interface DiffResult { + /** The list of issues, a zero size meaning that the diff succeeded. */ + public List getIssues(); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/LineTokenizer.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/LineTokenizer.java new file mode 100644 index 000000000..fed4c37b5 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/LineTokenizer.java @@ -0,0 +1,96 @@ +package org.argeo.slc.diff; + +import java.util.ArrayList; +import java.util.List; + +/** + * Parses a string as a vector of strings according to a separator, dealing + * properly with missing values. This is intended to be used instead of the + * standard StringTokenizer, which does not deal well with empty values. + * Contrary to the StringTokenizer the provided String is parsed in the + * constructor and the values stored as a property. This should therefore not be + * used to parse long strings. No reference to the argument passed in + * constructor is kept. + */ +public class LineTokenizer { + private final List tokens; + + /** Complete constructor. */ + public LineTokenizer(String stringToParse, Character separator, + String noValueString) { + this.tokens = parse(stringToParse, separator, noValueString); + } + + /** + * Parse the string as a vector of strings. Can be overridden in order to + * provide another implementation. + */ + protected List parse(final String stringToParse, + final char separator, final String noValueString) { + // Init + final int NULL = -1; + List res = new ArrayList(); + final char[] array = stringToParse.toCharArray(); + int lastSeparatorIndex = NULL; + + // Loop on chars + for (int currIndex = 0; currIndex < array.length; currIndex++) { + char c = array[currIndex]; + if (c == separator) { + if (currIndex == 0) { + // first char is a separator + res.add(new String(noValueString)); + lastSeparatorIndex = 0; + } else if (lastSeparatorIndex == NULL) { + // first separator found + res.add(new String(array, 0, currIndex)); + lastSeparatorIndex = currIndex; + } else if (lastSeparatorIndex != NULL + && (lastSeparatorIndex == (currIndex - 1))) { + // consecutive separators + res.add(new String(noValueString)); + lastSeparatorIndex = currIndex; + } else { + // simple case + res.add(new String(array, lastSeparatorIndex + 1, currIndex + - lastSeparatorIndex - 1)); + lastSeparatorIndex = currIndex; + } + } + } + + // Finalize + if (lastSeparatorIndex == NULL) { + // no separator found + res.add(new String(stringToParse)); + } else if (lastSeparatorIndex == (array.length - 1)) { + // last char is a separator + res.add(new String(noValueString)); + } else { + // last token + res.add(new String(array, lastSeparatorIndex + 1, array.length + - lastSeparatorIndex - 1)); + } + return res; + } + + /** The tokens. */ + public List getTokens() { + return tokens; + } + + /** Parse */ + public static List tokenize(String stringToParse, + Character separator, String noValueString) { + LineTokenizer lt = new LineTokenizer(stringToParse, separator, + noValueString); + return lt.getTokens(); + } + + /** Parse, using the empty string as no value string. */ + public static List tokenize(String stringToParse, + Character separator) { + return tokenize(stringToParse, separator, ""); + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/RelatedFile.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/RelatedFile.java new file mode 100644 index 000000000..757968355 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/RelatedFile.java @@ -0,0 +1,9 @@ +package org.argeo.slc.diff; + +/** Enumeration of the types of resource tested. */ +public enum RelatedFile { + /** The expected resource */ + EXPECTED, + /** The reached resource */ + REACHED +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/SimpleDiffResult.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/SimpleDiffResult.java new file mode 100644 index 000000000..6eefb7f28 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/SimpleDiffResult.java @@ -0,0 +1,14 @@ +package org.argeo.slc.diff; + +import java.util.List; +import java.util.Vector; + +/** A basic implementation of DiffResult. */ +public class SimpleDiffResult implements DiffResult { + private List issues = new Vector(); + + public List getIssues() { + return issues; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/TableDiffPosition.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/TableDiffPosition.java new file mode 100644 index 000000000..d8a3d785d --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/TableDiffPosition.java @@ -0,0 +1,66 @@ +package org.argeo.slc.diff; + +import org.argeo.slc.core.UnsupportedException; + +/** + * A diff position within a table structure such a CSV file or an SQL result + * set. + */ +public class TableDiffPosition extends DiffPosition { + private Integer line; + /** Can be null */ + private Integer column; + /** Can be null */ + private String columnName; + + public TableDiffPosition(RelatedFile relatedFile, Integer line, + Integer column, String columnName) { + super(relatedFile); + this.line = line; + this.column = column; + this.columnName = columnName; + } + + public Integer getLine() { + return line; + } + + public Integer getColumn() { + return column; + } + + public String getColumnName() { + return columnName; + } + + public int compareTo(DiffPosition dp) { + if (!(dp instanceof TableDiffPosition)) + throw new UnsupportedException("position", dp); + + TableDiffPosition o = (TableDiffPosition) dp; + if (relatedFile.equals(o.relatedFile)) { + if (line == o.line) { + return column.compareTo(o.column); + } else { + return line.compareTo(o.line); + } + } else { + return relatedFile.compareTo(o.relatedFile); + } + } + + @Override + public String toString() { + StringBuffer buf = new StringBuffer(""); + buf.append(relatedFile).append('[').append(line); + if (column != null) { + buf.append(',').append(column); + if (columnName != null) { + buf.append('-').append(columnName); + } + } + buf.append(']'); + return buf.toString(); + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/Tolerance.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/Tolerance.java new file mode 100644 index 000000000..b44a7123a --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/Tolerance.java @@ -0,0 +1,18 @@ +package org.argeo.slc.diff; + +/** Compares objects, eventually using tolerance mechanisms. */ +public interface Tolerance { + /** + * Compares objects + * + * @param key + * any object used to differentiate the type of data (e.g. + * column, path) + * @param expected + * the expected value + * @param reached + * the reached value + * @return the converted object + */ + public Boolean compare(Object key, Object expected, Object reached); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/XPathDiffPosition.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/XPathDiffPosition.java new file mode 100644 index 000000000..0d2234240 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/XPathDiffPosition.java @@ -0,0 +1,35 @@ +package org.argeo.slc.diff; + +import org.argeo.slc.core.UnsupportedException; + +/** A diff position within an Xml file. NOT YET IMPLEMENTED. */ +public class XPathDiffPosition extends DiffPosition { + + private String xPath; + + public XPathDiffPosition(RelatedFile relatedFile, String path) { + super(relatedFile); + xPath = path; + } + + public int compareTo(DiffPosition dp) { + if (!(dp instanceof XPathDiffPosition)) + throw new UnsupportedException("position", dp); + + XPathDiffPosition o = (XPathDiffPosition) dp; + if (relatedFile.equals(o.relatedFile)) { + return xPath.compareTo(o.xPath); + } else { + return relatedFile.compareTo(o.relatedFile); + } + } + + public String getXPath() { + return xPath; + } + + @Override + public String toString() { + return xPath; + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/package.html b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/package.html new file mode 100644 index 000000000..a58e68575 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/diff/package.html @@ -0,0 +1,6 @@ + + + +Abstraction of diff comparison with structured results. + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/logging/Log4jUtils.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/logging/Log4jUtils.java new file mode 100644 index 000000000..6398e608e --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/logging/Log4jUtils.java @@ -0,0 +1,79 @@ +package org.argeo.slc.logging; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import org.apache.commons.io.IOUtils; +import org.apache.log4j.LogManager; +import org.apache.log4j.PropertyConfigurator; +import org.argeo.slc.core.SlcException; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.util.ResourceUtils; +import org.springframework.util.SystemPropertyUtils; + +public class Log4jUtils { + + /** + * Configure log4j based on properties, with the following priorities (from + * highest to lowest):
+ * 1. System properties
+ * 2. configuration file itself + */ + public static void initLog4j(String configuration) { + // clears previous configuration + shutDownLog4j(); + + ClassLoader cl = Log4jUtils.class.getClassLoader(); + Properties properties = new Properties(); + if (configuration != null) { + InputStream in = null; + try { + if (configuration + .startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)) { + String path = configuration + .substring(ResourceUtils.CLASSPATH_URL_PREFIX + .length()); + in = cl.getResourceAsStream(path); + } else { + in = new DefaultResourceLoader(cl).getResource( + configuration).getInputStream(); + } + + properties.load(in); + } catch (IOException e) { + throw new SlcException("Cannot load properties from " + + configuration); + } finally { + IOUtils.closeQuietly(in); + } + } + + // Overrides with System properties + overrideLog4jProperties(properties, System.getProperties()); + + PropertyConfigurator.configure(properties); + } + + private static void overrideLog4jProperties(Properties target, + Properties additional) { + for (Object obj : additional.keySet()) { + String key = obj.toString(); + if (key.startsWith("log4j.")) { + if (!key.equals("log4j.configuration")) { + String value = SystemPropertyUtils + .resolvePlaceholders(additional.getProperty(key)); + target.put(key, value); + } + } + } + } + + public static void shutDownLog4j() { + LogManager.shutdown(); + } + + private Log4jUtils() { + + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/msg/process/SlcExecutionRequest.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/msg/process/SlcExecutionRequest.java new file mode 100644 index 000000000..54b896cf3 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/msg/process/SlcExecutionRequest.java @@ -0,0 +1,27 @@ +package org.argeo.slc.msg.process; + +import org.argeo.slc.core.process.SlcExecution; + +public class SlcExecutionRequest { + private SlcExecution slcExecution; + + public SlcExecutionRequest() { + } + + public SlcExecutionRequest(SlcExecution slcExecution) { + this.slcExecution = slcExecution; + } + + public SlcExecution getSlcExecution() { + return slcExecution; + } + + public void setSlcExecution(SlcExecution slcExecution) { + this.slcExecution = slcExecution; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "#" + slcExecution.getUuid(); + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/msg/process/SlcExecutionStatusRequest.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/msg/process/SlcExecutionStatusRequest.java new file mode 100644 index 000000000..44a463b9e --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/msg/process/SlcExecutionStatusRequest.java @@ -0,0 +1,35 @@ +package org.argeo.slc.msg.process; + +public class SlcExecutionStatusRequest { + private String slcExecutionUuid; + private String newStatus; + + public SlcExecutionStatusRequest() { + } + + public SlcExecutionStatusRequest(String slcExecutionUuid, String newStatus) { + this.slcExecutionUuid = slcExecutionUuid; + this.newStatus = newStatus; + } + + public String getSlcExecutionUuid() { + return slcExecutionUuid; + } + + public void setSlcExecutionUuid(String slcExecutionUuid) { + this.slcExecutionUuid = slcExecutionUuid; + } + + public String getNewStatus() { + return newStatus; + } + + public void setNewStatus(String newStatus) { + this.newStatus = newStatus; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "#" + slcExecutionUuid; + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/msg/process/SlcExecutionStepsRequest.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/msg/process/SlcExecutionStepsRequest.java new file mode 100644 index 000000000..7da2b43f5 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/msg/process/SlcExecutionStepsRequest.java @@ -0,0 +1,55 @@ +package org.argeo.slc.msg.process; + +import java.util.List; +import java.util.Vector; + +import org.argeo.slc.core.process.SlcExecutionStep; + +public class SlcExecutionStepsRequest { + private String slcExecutionUuid; + private List steps = new Vector(); + + public SlcExecutionStepsRequest() { + + } + + public SlcExecutionStepsRequest(String slcExecutionUuid, + List steps) { + this.slcExecutionUuid = slcExecutionUuid; + this.steps = steps; + } + + public SlcExecutionStepsRequest(String slcExecutionUuid, + SlcExecutionStep step) { + this.slcExecutionUuid = slcExecutionUuid; + List steps = new Vector(); + steps.add(step); + this.steps = steps; + } + + public String getSlcExecutionUuid() { + return slcExecutionUuid; + } + + public void setSlcExecutionUuid(String slcExecutionUuid) { + this.slcExecutionUuid = slcExecutionUuid; + } + + public List getSteps() { + return steps; + } + + public void setSteps(List step) { + this.steps = step; + } + + public void addStep(SlcExecutionStep step) { + steps.add(step); + } + + @Override + public String toString() { + return getClass().getSimpleName() + "#" + slcExecutionUuid + " " + + steps; + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/msg/test/tree/CloseTreeTestResultRequest.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/msg/test/tree/CloseTreeTestResultRequest.java new file mode 100644 index 000000000..311269626 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/msg/test/tree/CloseTreeTestResultRequest.java @@ -0,0 +1,46 @@ +package org.argeo.slc.msg.test.tree; + +import java.util.Date; + +import org.argeo.slc.core.test.tree.TreeTestResult; + +public class CloseTreeTestResultRequest { + private String resultUuid; + private Date closeDate; + + public CloseTreeTestResultRequest() { + + } + + public CloseTreeTestResultRequest(String resultUuid, Date closeDate) { + this.resultUuid = resultUuid; + this.closeDate = closeDate; + } + + public CloseTreeTestResultRequest(TreeTestResult ttr) { + this.resultUuid = ttr.getUuid(); + this.closeDate = ttr.getCloseDate(); + } + + public String getResultUuid() { + return resultUuid; + } + + public void setResultUuid(String id) { + this.resultUuid = id; + } + + public Date getCloseDate() { + return closeDate; + } + + public void setCloseDate(Date closeDate) { + this.closeDate = closeDate; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "#" + resultUuid; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/msg/test/tree/CreateTreeTestResultRequest.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/msg/test/tree/CreateTreeTestResultRequest.java new file mode 100644 index 000000000..0bac8a821 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/msg/test/tree/CreateTreeTestResultRequest.java @@ -0,0 +1,41 @@ +package org.argeo.slc.msg.test.tree; + +import org.argeo.slc.core.test.TestRunDescriptor; +import org.argeo.slc.core.test.tree.TreeTestResult; + +public class CreateTreeTestResultRequest { + private TreeTestResult treeTestResult; + private TestRunDescriptor testRunDescriptor; + + public CreateTreeTestResultRequest() { + + } + + public CreateTreeTestResultRequest(TreeTestResult treeTestResult) { + this.treeTestResult = treeTestResult; + if (treeTestResult.getCurrentTestRun() != null) + testRunDescriptor = new TestRunDescriptor(treeTestResult + .getCurrentTestRun()); + } + + public TreeTestResult getTreeTestResult() { + return treeTestResult; + } + + public void setTreeTestResult(TreeTestResult treeTestResult) { + this.treeTestResult = treeTestResult; + } + + public TestRunDescriptor getTestRunDescriptor() { + return testRunDescriptor; + } + + public void setTestRunDescriptor(TestRunDescriptor testRunDescriptor) { + this.testRunDescriptor = testRunDescriptor; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "#" + treeTestResult.getUuid(); + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/msg/test/tree/ResultPartRequest.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/msg/test/tree/ResultPartRequest.java new file mode 100644 index 000000000..0b4278f34 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/msg/test/tree/ResultPartRequest.java @@ -0,0 +1,107 @@ +package org.argeo.slc.msg.test.tree; + +import java.util.Map; +import java.util.SortedMap; + +import org.argeo.slc.core.SlcException; +import org.argeo.slc.core.structure.StructureElement; +import org.argeo.slc.core.structure.tree.TreeSPath; +import org.argeo.slc.core.test.SimpleResultPart; +import org.argeo.slc.core.test.TestRunDescriptor; +import org.argeo.slc.core.test.tree.PartSubList; +import org.argeo.slc.core.test.tree.TreeTestResult; + +public class ResultPartRequest { + private String resultUuid; + private SimpleResultPart resultPart; + private TreeSPath path; + private Map relatedElements; + private TestRunDescriptor testRunDescriptor; + private Map attributes; + + public ResultPartRequest() { + + } + + public ResultPartRequest(TreeTestResult ttr, TreeSPath path, + SimpleResultPart resultPart) { + resultUuid = ttr.getUuid(); + this.resultPart = resultPart; + this.path = (path != null ? path : ttr.getCurrentPath()); + relatedElements = ttr.getRelatedElements(this.path); + if (ttr.getCurrentTestRun() != null) + testRunDescriptor = new TestRunDescriptor(ttr.getCurrentTestRun()); + attributes = ttr.getAttributes(); + } + + public ResultPartRequest(TreeTestResult ttr) { + resultUuid = ttr.getUuid(); + this.path = ttr.getCurrentPath(); + + PartSubList lst = ttr.getResultParts().get(path); + if (lst.getParts().size() < 1) { + throw new SlcException("Cannot find part for path " + path + + " in result " + resultUuid); + } + + this.resultPart = (SimpleResultPart) lst.getParts().get( + lst.getParts().size() - 1); + relatedElements = ttr.getRelatedElements(path); + if (ttr.getCurrentTestRun() != null) + testRunDescriptor = new TestRunDescriptor(ttr.getCurrentTestRun()); + } + + public String getResultUuid() { + return resultUuid; + } + + public void setResultUuid(String resultUuid) { + this.resultUuid = resultUuid; + } + + public SimpleResultPart getResultPart() { + return resultPart; + } + + public void setResultPart(SimpleResultPart resultPart) { + this.resultPart = resultPart; + } + + public TreeSPath getPath() { + return path; + } + + public void setPath(TreeSPath path) { + this.path = path; + } + + public TestRunDescriptor getTestRunDescriptor() { + return testRunDescriptor; + } + + public void setTestRunDescriptor(TestRunDescriptor testRunDescriptor) { + this.testRunDescriptor = testRunDescriptor; + } + + public Map getRelatedElements() { + return relatedElements; + } + + public void setRelatedElements( + Map relatedElements) { + this.relatedElements = relatedElements; + } + + public Map getAttributes() { + return attributes; + } + + public void setAttributes(SortedMap attributes) { + this.attributes = attributes; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "#" + resultUuid + " " + path; + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/runtime/SlcExecutionContext.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/runtime/SlcExecutionContext.java new file mode 100644 index 000000000..23788313b --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/runtime/SlcExecutionContext.java @@ -0,0 +1,10 @@ +package org.argeo.slc.runtime; + +import org.argeo.slc.core.process.SlcExecution; + +/** Provides access to the object used during the execution */ +public interface SlcExecutionContext { + public T getBean(String name); + + public SlcExecution getSlcExecution(); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/runtime/SlcExecutionOutput.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/runtime/SlcExecutionOutput.java new file mode 100644 index 000000000..7db938399 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/runtime/SlcExecutionOutput.java @@ -0,0 +1,6 @@ +package org.argeo.slc.runtime; + +public interface SlcExecutionOutput { + /** Called after the execution, before the resources are freed. */ + public void postExecution(T executionContext); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/spring/SpringUtils.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/spring/SpringUtils.java new file mode 100644 index 000000000..798b5648e --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/spring/SpringUtils.java @@ -0,0 +1,69 @@ +package org.argeo.slc.spring; + +import java.io.IOException; +import java.net.URI; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.core.SlcException; +import org.springframework.beans.factory.BeanFactoryUtils; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; + +public class SpringUtils { + private final static Log log = LogFactory.getLog(SpringUtils.class); + + public static T loadSingleFromContext(ListableBeanFactory context, + Class clss) { + // Map beans = context.getBeansOfType(clss); + Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors( + context, clss, false, false); + if (beans.size() == 1) { + return beans.values().iterator().next(); + } else if (beans.size() > 1) { + if (log.isDebugEnabled()) { + log + .debug(("Found more that on bean for type " + clss + + ": " + beans.keySet())); + } + return null; + } else { + return null; + } + } + + public static Resource getParent(Resource res) { + try { + if (res.getURL().getPath().equals("/")) + return null; + + String urlStr = res.getURL().toString(); + if (urlStr.charAt(urlStr.length() - 1) == '/') + urlStr = urlStr.substring(0, urlStr.length() - 2); + + String parentUrlStr = urlStr.substring(0, urlStr.lastIndexOf('/')) + '/'; + URI uri = new URI(parentUrlStr).normalize(); + return new DefaultResourceLoader(Thread.currentThread() + .getContextClassLoader()).getResource(uri.toString()); + } catch (Exception e) { + throw new SlcException("Cannot get parent for resource " + res, e); + } + } + + public static String extractRelativePath(Resource ancestor, Resource child) { + try { + + return ancestor.getURL().toURI().relativize(child.getURL().toURI()) + .normalize().toString(); + } catch (Exception e) { + throw new SlcException("Cannot extract relative path of " + child + + " based on " + ancestor, e); + } + } + + private SpringUtils() { + + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdApplicationDeployment.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdApplicationDeployment.java new file mode 100644 index 000000000..6c6cffdce --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdApplicationDeployment.java @@ -0,0 +1,68 @@ +package org.argeo.slc.support.deploy; + +import java.io.File; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.core.SlcException; +import org.argeo.slc.core.build.Distribution; +import org.argeo.slc.core.deploy.DeployEnvironment; +import org.argeo.slc.core.deploy.DeployedSystem; +import org.argeo.slc.core.deploy.Deployment; +import org.argeo.slc.core.deploy.DeploymentData; +import org.argeo.slc.core.deploy.TargetData; + +public class HttpdApplicationDeployment implements Deployment { + private static final Log log = LogFactory + .getLog(HttpdApplicationDeployment.class); + + private HttpdApplicationTargetData targetData; + private DeploymentData deploymentData; + private SimpleHttpdApplication deployedSystem; + private Distribution distribution; + + private DeployEnvironment deployEnvironment; + + public void execute() { + try { + deployEnvironment.unpackTo(distribution, targetData + .getTargetRootLocation(), null); + + // FIXME: make it generic + String deployDataPath = targetData.getTargetRootLocation() + .getCanonicalPath(); + + deployEnvironment.unpackTo(deploymentData, + new File(deployDataPath), null); + deployedSystem = new SimpleHttpdApplication(); + deployedSystem.setTargetData(targetData); + + log.info("Deployed " + distribution + " to " + targetData); + } catch (Exception e) { + throw new SlcException("Cannot deploy " + distribution + " to " + + targetData, e); + } + + } + + public void setTargetData(TargetData targetData) { + this.targetData = (HttpdApplicationTargetData) targetData; + } + + public void setDeploymentData(DeploymentData deploymentData) { + this.deploymentData = deploymentData; + } + + public DeployedSystem getDeployedSystem() { + return deployedSystem; + } + + public void setDistribution(Distribution distribution) { + this.distribution = distribution; + } + + public void setDeployEnvironment(DeployEnvironment deployEnvironment) { + this.deployEnvironment = deployEnvironment; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdApplicationTargetData.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdApplicationTargetData.java new file mode 100644 index 000000000..c162340ca --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdApplicationTargetData.java @@ -0,0 +1,65 @@ +package org.argeo.slc.support.deploy; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; + +import org.argeo.slc.core.SlcException; +import org.argeo.slc.core.deploy.TargetData; + +public class HttpdApplicationTargetData implements TargetData { + private HttpdServer webServer; + private String relativePath; + private String targetRootPath; + + public HttpdServer getWebServer() { + return webServer; + } + + public void setWebServer(HttpdServer webServer) { + this.webServer = webServer; + } + + public String getRelativePath() { + return relativePath; + } + + /** + * If targetRootLocation not set, used to build the targetRootLocation, + * relative to the webserver base. + */ + public void setRelativePath(String relativePath) { + this.relativePath = relativePath; + } + + public String getTargetRootPath() { + return targetRootPath; + } + + public void setTargetRootPath(String targetRootPath) { + this.targetRootPath = targetRootPath; + } + + public URL getTargetBaseUrl() { + try { + URL wsUrl = getWebServer().getBaseUrl(); + // TODO: use URI + return new URL(wsUrl, wsUrl.getFile() + '/' + relativePath); + } catch (MalformedURLException e) { + throw new SlcException("Cannot get base url for " + relativePath, e); + } + } + + public File getTargetRootLocation() { + if (targetRootPath != null && !targetRootPath.equals("")) { + return new File(targetRootPath); + } else { + HttpdServerTargetData targetData = (HttpdServerTargetData) getWebServer() + .getTargetData(); + String path = targetData.getServerRoot() + File.separator + + getRelativePath(); + return new File(path); + } + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdServer.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdServer.java new file mode 100644 index 000000000..586f263ae --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdServer.java @@ -0,0 +1,50 @@ +package org.argeo.slc.support.deploy; + +import java.io.IOException; +import java.net.URL; + +import org.argeo.slc.core.SlcException; +import org.argeo.slc.core.build.Distribution; +import org.argeo.slc.core.deploy.DeploymentData; +import org.argeo.slc.core.deploy.TargetData; + +public class HttpdServer implements WebServer { + private HttpdServerTargetData targetData; + private HttpdServerDeploymentData deploymentData; + + public URL getBaseUrl() { + try { + return new URL("http://localhost:" + targetData.getPort()); + } catch (IOException e) { + throw new SlcException("Cannot get url for Httpd server " + + getDeployedSystemId(), e); + } + } + + public String getDeployedSystemId() { + // TODO Auto-generated method stub + return null; + } + + public Distribution getDistribution() { + // TODO Auto-generated method stub + return null; + } + + public DeploymentData getDeploymentData() { + return deploymentData; + } + + public TargetData getTargetData() { + return targetData; + } + + public void setTargetData(TargetData targetData) { + this.targetData = (HttpdServerTargetData)targetData; + } + + public void setDeploymentData(DeploymentData deploymentData) { + this.deploymentData = (HttpdServerDeploymentData)deploymentData; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdServerDeployment.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdServerDeployment.java new file mode 100644 index 000000000..12036f5e2 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdServerDeployment.java @@ -0,0 +1,34 @@ +package org.argeo.slc.support.deploy; + +import org.argeo.slc.core.build.Distribution; +import org.argeo.slc.core.deploy.DeployedSystem; +import org.argeo.slc.core.deploy.Deployment; +import org.argeo.slc.core.deploy.DeploymentData; +import org.argeo.slc.core.deploy.TargetData; + +public class HttpdServerDeployment implements Deployment { + private HttpdServerTargetData targetData; + + public void execute() { + // TODO Auto-generated method stub + + } + + public DeployedSystem getDeployedSystem() { + // TODO Auto-generated method stub + return null; + } + + public void setDeploymentData(DeploymentData deploymentData) { + // TODO Auto-generated method stub + + } + + public void setDistribution(Distribution distribution) { + } + + public void setTargetData(TargetData targetData) { + this.targetData = (HttpdServerTargetData) targetData; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdServerDeploymentData.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdServerDeploymentData.java new file mode 100644 index 000000000..8af51ece8 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdServerDeploymentData.java @@ -0,0 +1,16 @@ +package org.argeo.slc.support.deploy; + +import org.argeo.slc.core.deploy.DeploymentData; + +public class HttpdServerDeploymentData implements DeploymentData { + private String configFile; + + public String getConfigFile() { + return configFile; + } + + public void setConfigFile(String configFile) { + this.configFile = configFile; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdServerManager.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdServerManager.java new file mode 100644 index 000000000..8d455965d --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdServerManager.java @@ -0,0 +1,81 @@ +package org.argeo.slc.support.deploy; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Arrays; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.core.SlcException; +import org.argeo.slc.core.deploy.DeployedSystemManager; + +public class HttpdServerManager implements DeployedSystemManager { + private final static Log log = LogFactory.getLog(HttpdServerManager.class); + + private HttpdServer httpdServer; + + public void start() { + runProcessAsync(createCommandLine("start")); + log.info("Started httpd server with root " + + getHttpdServerTargetData().getServerRoot()); + } + + public void stop() { + runProcessAsync(createCommandLine("stop")); + log.info("Stopped httpd server with root " + + getHttpdServerTargetData().getServerRoot()); + } + + protected String[] createCommandLine(String action) { + String httpdPath = getHttpdServerTargetData().getExecutables() + .getExecutablePath("httpd"); + String[] cmd = { httpdPath, "-d", + getHttpdServerTargetData().getServerRoot(), "-f", + getHttpdServerDeploymentData().getConfigFile(), "-k", action }; + if (log.isDebugEnabled()) + log.debug("Command line: " + Arrays.asList(cmd)); + return cmd; + } + + protected static void runProcessAsync(String... command) { + ProcessBuilder procBuilder = new ProcessBuilder(command); + procBuilder.redirectErrorStream(true); + try { + Process proc = procBuilder.start(); + final InputStream in = proc.getInputStream(); + Thread logThread = new Thread() { + + @Override + public void run() { + BufferedReader reader = new BufferedReader( + new InputStreamReader(in)); + String line = null; + try { + while ((line = reader.readLine()) != null) + log.info(line); + } catch (IOException e) { + log.error("Failed to read stdout", e); + } + } + }; + + logThread.start(); + } catch (IOException e) { + throw new SlcException("Could not run command", e); + } + } + + public void setDeployedSystem(HttpdServer httpdServer) { + this.httpdServer = httpdServer; + } + + protected HttpdServerDeploymentData getHttpdServerDeploymentData() { + return (HttpdServerDeploymentData) httpdServer.getDeploymentData(); + } + + protected HttpdServerTargetData getHttpdServerTargetData() { + return (HttpdServerTargetData) httpdServer.getTargetData(); + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdServerTargetData.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdServerTargetData.java new file mode 100644 index 000000000..0e1b17195 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/HttpdServerTargetData.java @@ -0,0 +1,35 @@ +package org.argeo.slc.support.deploy; + +import org.argeo.slc.core.deploy.InstalledExecutables; +import org.argeo.slc.core.deploy.TargetData; + +public class HttpdServerTargetData implements TargetData { + private String serverRoot; + private Integer port; + private InstalledExecutables executables; + + public String getServerRoot() { + return serverRoot; + } + + public void setServerRoot(String serverRoot) { + this.serverRoot = serverRoot; + } + + public Integer getPort() { + return port; + } + + public void setPort(Integer port) { + this.port = port; + } + + public InstalledExecutables getExecutables() { + return executables; + } + + public void setExecutables(InstalledExecutables executables) { + this.executables = executables; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/SimpleHttpdApplication.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/SimpleHttpdApplication.java new file mode 100644 index 000000000..bbcf60dfb --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/SimpleHttpdApplication.java @@ -0,0 +1,47 @@ +package org.argeo.slc.support.deploy; + +import java.io.File; +import java.net.URL; + +import org.argeo.slc.core.build.Distribution; +import org.argeo.slc.core.deploy.DeploymentData; + +public class SimpleHttpdApplication implements WebApplication { + private HttpdApplicationTargetData targetData; + private Distribution distribution; + + public void setDistribution(Distribution distribution) { + this.distribution = distribution; + } + + public URL getBaseUrl() { + return targetData.getTargetBaseUrl(); + } + + public File getRootLocation() { + return targetData.getTargetRootLocation(); + } + + public String getDeployedSystemId() { + // TODO Auto-generated method stub + return null; + } + + public HttpdApplicationTargetData getTargetData() { + return targetData; + } + + public void setTargetData(HttpdApplicationTargetData targetData) { + this.targetData = targetData; + } + + public Distribution getDistribution() { + return distribution; + } + + public DeploymentData getDeploymentData() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/WebApplication.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/WebApplication.java new file mode 100644 index 000000000..ef167ba21 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/WebApplication.java @@ -0,0 +1,12 @@ +package org.argeo.slc.support.deploy; + +import java.io.File; +import java.net.URL; + +import org.argeo.slc.core.deploy.DeployedSystem; + +public interface WebApplication extends DeployedSystem { + public URL getBaseUrl(); + + public File getRootLocation(); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/WebServer.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/WebServer.java new file mode 100644 index 000000000..fc747bc94 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/WebServer.java @@ -0,0 +1,9 @@ +package org.argeo.slc.support.deploy; + +import java.net.URL; + +import org.argeo.slc.core.deploy.DeployedSystem; + +public interface WebServer extends DeployedSystem { + public URL getBaseUrl(); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/db/DbModel.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/db/DbModel.java new file mode 100644 index 000000000..6140d7bc0 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/db/DbModel.java @@ -0,0 +1,7 @@ +package org.argeo.slc.support.deploy.db; + +import java.sql.Connection; + +public interface DbModel { + public void createSchema(Connection connection); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/db/DbUnitDeployment.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/db/DbUnitDeployment.java new file mode 100644 index 000000000..9df6a1d74 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/db/DbUnitDeployment.java @@ -0,0 +1,80 @@ +package org.argeo.slc.support.deploy.db; + +import java.sql.SQLException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.core.SlcException; +import org.argeo.slc.core.UnsupportedException; +import org.argeo.slc.core.build.Distribution; +import org.argeo.slc.core.deploy.DeployedSystem; +import org.argeo.slc.core.deploy.Deployment; +import org.argeo.slc.core.deploy.DeploymentData; +import org.argeo.slc.core.deploy.TargetData; +import org.dbunit.DataSourceDatabaseTester; +import org.dbunit.DatabaseUnitException; +import org.dbunit.IDatabaseTester; +import org.dbunit.database.IDatabaseConnection; +import org.dbunit.dataset.IDataSet; +import org.dbunit.operation.DatabaseOperation; + +public class DbUnitDeployment implements Deployment { + private static Log log = LogFactory.getLog(DbUnitDeployment.class); + + private JdbcAware mxDatabase; + private DbUnitDeploymentData deploymentData; + private DbModel dbModel; + + public void execute() { + try { + IDatabaseTester databaseTester = new DataSourceDatabaseTester( + mxDatabase.getDataSource()); + databaseTester.setSetUpOperation(new DatabaseOperation() { + + @Override + public void execute(IDatabaseConnection connection, + IDataSet dataSet) throws DatabaseUnitException, + SQLException { + if (dbModel != null) { + dbModel.createSchema(connection.getConnection()); + DatabaseOperation.INSERT.execute(connection, dataSet); + } else { + DatabaseOperation.UPDATE.execute(connection, dataSet); + } + } + + }); + databaseTester.setDataSet(deploymentData.createDataSet()); + databaseTester.onSetup(); + databaseTester.onTearDown(); + + log.info("Database deployed."); + } catch (Exception e) { + throw new SlcException("Could not initialize the database", e); + } + } + + public DeployedSystem getDeployedSystem() { + // TODO: think of a more generic approach. MxDtaabse deployed system? + // (with deployment id etc.) + throw new UnsupportedException("Method not supported"); + } + + public void setDbModel(DbModel dbModel) { + this.dbModel = dbModel; + } + + public void setDeploymentData(DeploymentData deploymentData) { + this.deploymentData = (DbUnitDeploymentData) deploymentData; + } + + public void setTargetData(TargetData targetData) { + this.mxDatabase = (JdbcAware) targetData; + + } + + public void setDistribution(Distribution distribution) { + throw new UnsupportedException("Method not supported"); + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/db/DbUnitDeploymentData.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/db/DbUnitDeploymentData.java new file mode 100644 index 000000000..3d328a0fb --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/db/DbUnitDeploymentData.java @@ -0,0 +1,30 @@ +package org.argeo.slc.support.deploy.db; + +import java.io.InputStream; + +import org.argeo.slc.core.SlcException; +import org.argeo.slc.core.deploy.DeploymentData; +import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.xml.FlatXmlDataSet; +import org.springframework.core.io.Resource; + +public class DbUnitDeploymentData implements DeploymentData { + private Resource dataSetLocation; + + public IDataSet createDataSet() { + try { + InputStream in = dataSetLocation.getInputStream(); + IDataSet dataSet = new FlatXmlDataSet(in); + in.close(); + return dataSet; + } catch (Exception e) { + throw new SlcException("Cannot create data set", e); + } + + } + + public void setDataSetLocation(Resource dataSetLocation) { + this.dataSetLocation = dataSetLocation; + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/db/JdbcAware.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/db/JdbcAware.java new file mode 100644 index 000000000..0d4de5eae --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/db/JdbcAware.java @@ -0,0 +1,7 @@ +package org.argeo.slc.support.deploy.db; + +import javax.sql.DataSource; + +public interface JdbcAware { + public DataSource getDataSource(); +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/db/SimpleJdbcDatabase.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/db/SimpleJdbcDatabase.java new file mode 100644 index 000000000..5fe1d4a67 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/support/deploy/db/SimpleJdbcDatabase.java @@ -0,0 +1,22 @@ +package org.argeo.slc.support.deploy.db; + +import javax.sql.DataSource; + +import org.argeo.slc.core.deploy.AbstractDeployedSystem; + +public class SimpleJdbcDatabase extends AbstractDeployedSystem implements + JdbcAware { + private DataSource dataSource; + + public String getDeployedSystemId() { + return dataSource.toString(); + } + + public DataSource getDataSource() { + return dataSource; + } + + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/AbstractSpringTestCase.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/AbstractSpringTestCase.java new file mode 100644 index 000000000..a37c4a7ce --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/AbstractSpringTestCase.java @@ -0,0 +1,62 @@ +package org.argeo.slc.unit; + +import junit.framework.TestCase; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.core.SlcException; +import org.argeo.slc.spring.SpringUtils; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** Helper for tests using a Spring application co,text. */ +public abstract class AbstractSpringTestCase extends TestCase { + protected final Log log = LogFactory.getLog(getClass()); + private ConfigurableApplicationContext context; + + /** + * Gets (and create if necessary) the application context to use. Default + * implementation uses a class path xml application context and calls + * {@link #getApplicationContextLocation()}. + */ + protected ConfigurableApplicationContext getContext() { + if (context == null) { + context = new ClassPathXmlApplicationContext( + getApplicationContextLocation()); + } + return context; + } + + /** Returns a bean from the underlying context */ + protected T getBean(String beanId) { + return (T) getContext().getBean(beanId); + } + + protected T getBean(Class clss) { + T bean = SpringUtils.loadSingleFromContext(getContext(), clss); + if (bean == null) { + throw new SlcException("Cannot retrieve a unique bean of type " + + clss); + } else { + return bean; + } + } + + /** + * Th location of the application to load. The default implementation + * returns applicationContext.xml found in the same package as the + * test. + */ + protected String getApplicationContextLocation() { + return inPackage("applicationContext.xml"); + } + + /** + * Prefixes the package of the class after converting the '.' to '/' in + * order to have a resource path. + */ + protected String inPackage(String suffix) { + String prefix = getClass().getPackage().getName().replace('.', '/'); + return prefix + '/' + suffix; + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/UnitUtils.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/UnitUtils.java new file mode 100644 index 000000000..e88deed01 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/UnitUtils.java @@ -0,0 +1,42 @@ +package org.argeo.slc.unit; + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNull; +import static junit.framework.Assert.assertNotNull; + +public abstract class UnitUtils { + public static void assertDateSec(Date expected, Date reached) { + if (expected == null) { + assertNull(reached); + return; + } else { + assertNotNull(reached); + } + + Calendar expectedCal = new GregorianCalendar(); + expectedCal.setTime(expected); + Calendar reachedCal = new GregorianCalendar(); + reachedCal.setTime(reached); + assertEquals(expectedCal.get(Calendar.YEAR), reachedCal + .get(Calendar.YEAR)); + assertEquals(expectedCal.get(Calendar.MONTH), reachedCal + .get(Calendar.MONTH)); + assertEquals(expectedCal.get(Calendar.DATE), reachedCal + .get(Calendar.DATE)); + assertEquals(expectedCal.get(Calendar.HOUR_OF_DAY), reachedCal + .get(Calendar.HOUR_OF_DAY)); + assertEquals(expectedCal.get(Calendar.MINUTE), reachedCal + .get(Calendar.MINUTE)); + assertEquals(expectedCal.get(Calendar.SECOND), reachedCal + .get(Calendar.SECOND)); + } + + private UnitUtils() { + + } + +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/UnitXmlUtils.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/UnitXmlUtils.java new file mode 100644 index 000000000..af6f92320 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/UnitXmlUtils.java @@ -0,0 +1,39 @@ +package org.argeo.slc.unit; + +import java.io.IOException; + +import javax.xml.transform.Source; + +import junit.framework.TestCase; + +import org.springframework.xml.validation.XmlValidator; +import org.springframework.xml.xsd.XsdSchema; +import org.xml.sax.SAXParseException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public abstract class UnitXmlUtils { + private final static Log log = LogFactory.getLog(UnitXmlUtils.class); + + public static void assertXsdSchemaValidation(XsdSchema schema, Source source) + throws IOException { + XmlValidator validator = schema.createValidator(); + assertXmlValidation(validator, source); + } + + public static void assertXmlValidation(XmlValidator validator, Source source) + throws IOException { + SAXParseException[] exceptions = validator.validate(source); + if (exceptions.length != 0) { + for (SAXParseException ex : exceptions) { + log.error(ex.getMessage()); + } + TestCase.fail("Could not validate"); + } + } + + private UnitXmlUtils() { + + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/package.html b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/package.html new file mode 100644 index 000000000..907430d09 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/package.html @@ -0,0 +1,6 @@ + + + +Helpers for unit tests. + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/process/SlcExecutionTestUtils.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/process/SlcExecutionTestUtils.java new file mode 100644 index 000000000..25f40c5f9 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/process/SlcExecutionTestUtils.java @@ -0,0 +1,63 @@ +package org.argeo.slc.unit.process; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static org.argeo.slc.unit.UnitUtils.assertDateSec; + +import java.util.UUID; + +import org.argeo.slc.core.process.SlcExecution; +import org.argeo.slc.core.process.SlcExecutionStep; + +public abstract class SlcExecutionTestUtils { + + public static SlcExecution createSimpleSlcExecution() { + SlcExecution slcExec = new SlcExecution(); + slcExec.setUuid(UUID.randomUUID().toString()); + slcExec.setHost("localhost"); + slcExec.setUser("user"); + slcExec.setType("slcAnt"); + slcExec.setStatus("STARTED"); + slcExec.getAttributes().put("ant.file", "/test"); + return slcExec; + } + + public static void assertSlcExecution(SlcExecution expected, + SlcExecution reached) { + assertNotNull(reached); + assertEquals(expected.getHost(), reached.getHost()); + assertEquals(expected.getUser(), reached.getUser()); + assertEquals(expected.getType(), reached.getType()); + assertEquals(expected.getStatus(), reached.getStatus()); + + // Attributes + assertEquals(expected.getAttributes().size(), reached.getAttributes() + .size()); + for (String key : expected.getAttributes().keySet()) { + String expectedValue = expected.getAttributes().get(key); + String reachedValue = reached.getAttributes().get(key); + assertNotNull(reachedValue); + assertEquals(expectedValue, reachedValue); + } + + assertEquals(expected.getSteps().size(), reached.getSteps().size()); + for (int i = 0; i < expected.getSteps().size(); i++) { + SlcExecutionStep stepExpected = expected.getSteps().get(i); + SlcExecutionStep stepReached = reached.getSteps().get(i); + assertSlcExecutionStep(stepExpected, stepReached); + } + } + + public static void assertSlcExecutionStep(SlcExecutionStep expected, + SlcExecutionStep reached) { + assertNotNull(reached); + assertEquals(expected.getUuid(), reached.getUuid()); + assertEquals(expected.getType(), reached.getType()); + assertEquals(expected.logAsString(), reached.logAsString()); + assertDateSec(expected.getBegin(), reached.getBegin()); + } + + private SlcExecutionTestUtils() { + + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/test/tree/TreeTestResultTestUtils.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/test/tree/TreeTestResultTestUtils.java new file mode 100644 index 000000000..fedaa266a --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/test/tree/TreeTestResultTestUtils.java @@ -0,0 +1,130 @@ +package org.argeo.slc.unit.test.tree; + +import java.util.UUID; + +import org.argeo.slc.core.build.Distribution; +import org.argeo.slc.core.deploy.DeployedSystem; +import org.argeo.slc.core.deploy.DeploymentData; +import org.argeo.slc.core.deploy.TargetData; +import org.argeo.slc.core.process.SlcExecution; +import org.argeo.slc.core.process.SlcExecutionStep; +import org.argeo.slc.core.structure.SimpleSElement; +import org.argeo.slc.core.structure.tree.TreeSPath; +import org.argeo.slc.core.structure.tree.TreeSRegistry; +import org.argeo.slc.core.test.SimpleResultPart; +import org.argeo.slc.core.test.SimpleTestRun; +import org.argeo.slc.core.test.TestStatus; +import org.argeo.slc.core.test.tree.PartSubList; +import org.argeo.slc.core.test.tree.TreeTestResult; +import org.argeo.slc.msg.test.tree.ResultPartRequest; +import org.argeo.slc.unit.process.SlcExecutionTestUtils; + +public abstract class TreeTestResultTestUtils { + + public static TreeTestResult createSimpleTreeTestResult() { + TreeTestResult treeTestResult = new TreeTestResult(); + treeTestResult.setUuid(UUID.randomUUID().toString()); + return treeTestResult; + } + + public static TreeTestResult createCompleteTreeTestResult() { + SlcExecution slcExecution = SlcExecutionTestUtils + .createSimpleSlcExecution(); + SlcExecutionStep step = new SlcExecutionStep("JUnit step"); + slcExecution.getSteps().add(step); + + TreeTestResult ttr = createMinimalConsistentTreeTestResult(slcExecution); + + ttr.addResultPart(createSimpleResultPartPassed()); + ttr.addResultPart(createSimpleResultPartFailed()); + ttr.addResultPart(createSimpleResultPartError()); + return ttr; + } + + public static TreeTestResult createMinimalConsistentTreeTestResult( + SlcExecution slcExecution) { + SimpleTestRun testRun = new SimpleTestRun(); + testRun.setUuid(UUID.randomUUID().toString()); + + String pathStr = "/test"; + TreeSPath path = new TreeSPath(pathStr); + + TreeSRegistry registry = new TreeSRegistry(); + SimpleSElement elem = new SimpleSElement("Unit Test"); + elem.getTags().put("myTag", "myTagValue"); + registry.register(path, elem); + + TreeTestResult ttr = createSimpleTreeTestResult(); + ttr.getAttributes().put("testCase", "UNIT"); + + // Simulate test run + ttr.notifyCurrentPath(registry, path); + ttr.notifyTestRun(testRun); + testRun.setTestResult(ttr); + testRun.setDeployedSystem(new DeployedSystem() { + private String uuid = UUID.randomUUID().toString(); + + public String getDeployedSystemId() { + return uuid; + } + + public Distribution getDistribution() { + return null; + } + + public DeploymentData getDeploymentData() { + // TODO Auto-generated method stub + return null; + } + + public TargetData getTargetData() { + // TODO Auto-generated method stub + return null; + } + + }); + testRun.notifySlcExecution(slcExecution); + return ttr; + } + + public static SimpleResultPart createSimpleResultPartPassed() { + SimpleResultPart partPassed = new SimpleResultPart(); + String msgPassed = "message\nnew line"; + partPassed.setStatus(TestStatus.PASSED); + partPassed.setMessage(msgPassed); + return partPassed; + } + + public static SimpleResultPart createSimpleResultPartFailed() { + SimpleResultPart partFailed = new SimpleResultPart(); + String msgFailed = "too bad"; + partFailed.setStatus(TestStatus.FAILED); + partFailed.setMessage(msgFailed); + return partFailed; + } + + public static SimpleResultPart createSimpleResultPartError() { + SimpleResultPart partFailed = new SimpleResultPart(); + String msgFailed = "crashed\nanother line"; + partFailed.setStatus(TestStatus.ERROR); + partFailed.setMessage(msgFailed); + partFailed.setException(new Exception("Test Exception")); + return partFailed; + } + + public static ResultPartRequest createSimpleResultPartRequest( + TreeTestResult ttr) { + TreeSPath path = ttr.getCurrentPath(); + PartSubList lst = ttr.getResultParts().get(path); + SimpleResultPart part = (SimpleResultPart) lst.getParts().get(2); + + ResultPartRequest req = new ResultPartRequest(ttr, path, part); + req.setPath(ttr.getCurrentPath()); + + return req; + } + + private TreeTestResultTestUtils() { + + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/test/tree/UnitTestTreeUtil.java b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/test/tree/UnitTestTreeUtil.java new file mode 100644 index 000000000..62b4f8226 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/java/org/argeo/slc/unit/test/tree/UnitTestTreeUtil.java @@ -0,0 +1,187 @@ +package org.argeo.slc.unit.test.tree; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertNull; +import static junit.framework.Assert.fail; +import static org.argeo.slc.unit.UnitUtils.assertDateSec; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.core.structure.SimpleSElement; +import org.argeo.slc.core.structure.tree.TreeSPath; +import org.argeo.slc.core.test.SimpleResultPart; +import org.argeo.slc.core.test.TestResultPart; +import org.argeo.slc.core.test.tree.PartSubList; +import org.argeo.slc.core.test.tree.TreeTestResult; + +/** Utilities for unit tests. */ +public class UnitTestTreeUtil { + private final static Log log = LogFactory.getLog(UnitTestTreeUtil.class); + + public static void assertTreeTestResult(TreeTestResult expected, + TreeTestResult reached) { + assertEquals(expected.getUuid(), reached.getUuid()); + assertDateSec(expected.getCloseDate(), reached.getCloseDate()); + + // Attributes + assertEquals(expected.getAttributes().size(), reached.getAttributes() + .size()); + for (String key : expected.getAttributes().keySet()) { + String expectedValue = expected.getAttributes().get(key); + String reachedValue = reached.getAttributes().get(key); + assertNotNull(reachedValue); + assertEquals(expectedValue, reachedValue); + } + + // Result parts + assertEquals(expected.getResultParts().size(), reached.getResultParts() + .size()); + for (TreeSPath path : expected.getResultParts().keySet()) { + PartSubList lstExpected = expected.getResultParts().get(path); + PartSubList lstReached = expected.getResultParts().get(path); + if (lstReached == null) { + fail("No result for path " + path); + return; + } + assertPartSubList(lstExpected, lstReached); + } + + // Elements + assertEquals(expected.getElements().size(), reached.getElements() + .size()); + for (TreeSPath path : expected.getElements().keySet()) { + // String nameExpected = expected.getElements().get(path); + // String nameReached = expected.getElements().get(path); + SimpleSElement elemExpected = (SimpleSElement) expected + .getElements().get(path); + SimpleSElement elemReached = (SimpleSElement) expected + .getElements().get(path); + assertNotNull(elemReached); + assertElements(elemExpected, elemReached); + } + + } + + public static void assertElements(SimpleSElement expected, + SimpleSElement reached) { + assertEquals(expected.getLabel(), reached.getLabel()); + assertEquals(expected.getTags().size(), reached.getTags().size()); + for (String tagName : expected.getTags().keySet()) { + String expectedTagValue = expected.getTags().get(tagName); + String reachedTagValue = reached.getTags().get(tagName); + assertNotNull(reachedTagValue); + assertEquals(expectedTagValue, reachedTagValue); + } + } + + public static void assertPartSubList(PartSubList lstExpected, + PartSubList lstReached) { + assertEquals(lstExpected.getParts().size(), lstReached.getParts() + .size()); + for (int i = 0; i < lstExpected.getParts().size(); i++) { + assertPart(lstExpected.getParts().get(i), lstReached.getParts() + .get(i)); + } + } + + /** Asserts one part of a tree test result */ + public static void assertPart(TreeTestResult testResult, String pathStr, + int index, Integer status, String message) { + TreeSPath path = new TreeSPath(pathStr); + PartSubList list = testResult.getResultParts().get(path); + if (list == null) { + fail("No result for path " + path); + return; + } + if (index >= list.getParts().size()) { + fail("Not enough parts."); + } + SimpleResultPart part = (SimpleResultPart) list.getParts().get(index); + assertPart(part, status, message, null, part.getTestRunUuid(), true); + } + + public static void assertPart(TestResultPart expected, + TestResultPart reached) { + String expectedTestRunUuid = null; + if (expected instanceof SimpleResultPart) { + expectedTestRunUuid = ((SimpleResultPart) expected) + .getTestRunUuid(); + } + + assertPart(reached, expected.getStatus(), expected.getMessage(), + expected.getExceptionMessage(), expectedTestRunUuid, false); + } + + /** Assert one part of a tree test result. */ + private static void assertPart(TestResultPart part, Integer status, + String message, String exceptionDescription, + String expectedTestRunUuid, boolean skipExceptionMessage) { + assertEquals(status, part.getStatus()); + + if (message != null) { + if (log.isTraceEnabled()) { + log.trace("Expected message:" + message); + log.trace("Reached message:" + part.getMessage()); + } + assertEquals(message, part.getMessage()); + } + + if (!skipExceptionMessage) { + if (exceptionDescription == null) { + assertNull(part.getExceptionMessage()); + } else { + if (log.isTraceEnabled()) { + log.trace("Expected exception message:" + + exceptionDescription); + log.trace("Reached exception message:" + + part.getExceptionMessage()); + } + + assertEquals(exceptionDescription, part.getExceptionMessage()); + } + } + + if (expectedTestRunUuid != null) { + SimpleResultPart reachedPart = (SimpleResultPart) part; + assertNotNull(reachedPart.getTestRunUuid()); + assertEquals(expectedTestRunUuid, reachedPart.getTestRunUuid()); + } else { + if (part instanceof SimpleResultPart) { + assertNull(((SimpleResultPart) part).getTestRunUuid()); + } + + } + + } + + public static void describeTreeTestResult(TreeTestResult ttr) { + log.info("TreeTestResult #" + ttr.getUuid()); + log.info(" Close date: " + ttr.getCloseDate()); + log.info(" Attributes:"); + for (String key : ttr.getAttributes().keySet()) + log.info(" " + key + "=" + ttr.getAttributes().get(key)); + + log.info(" Result parts: (size=" + ttr.getResultParts().size() + ")"); + for (TreeSPath path : ttr.getResultParts().keySet()) { + log.info(" Path: " + path); + PartSubList lst = ttr.getResultParts().get(path); + for (TestResultPart part : lst.getParts()) + log.info(" " + part); + } + + log.info(" Elements: (size=" + ttr.getElements().size() + ")"); + for (TreeSPath path : ttr.getElements().keySet()) { + SimpleSElement elem = (SimpleSElement) ttr.getElements().get(path); + log.info(" Path: " + path + ", Element: " + elem.getLabel()); + for (String tag : elem.getTags().keySet()) + log.info(" " + tag + "=" + elem.getTags().get(tag)); + } + + } + + /** Makes sure this is a singleton */ + private UnitTestTreeUtil() { + + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/main/resources/META-INF/MANIFEST.MF b/runtime/org.argeo.slc.support.castor/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 000000000..2c064a187 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1,125 @@ +Manifest-Version: 1.0 +Export-Package: org.argeo.slc.castor.process;version="0.11.2.SNAPSHOT" + ,org.argeo.slc.core.test.spring;version="0.11.2.SNAPSHOT",org.argeo.s + lc.dao.process;uses:="org.argeo.slc.core.process";version="0.11.2.SNA + PSHOT",org.argeo.slc.dao.test.tree;uses:="org.argeo.slc.dao.test,org. + apache.commons.logging,org.argeo.slc.core.test.tree,org.argeo.slc.cor + e.structure.tree,org.argeo.slc.core.test";version="0.11.2.SNAPSHOT",o + rg.argeo.slc.core.test;uses:="org.apache.commons.logging,org.argeo.sl + c.core,org.argeo.slc.core.test.context,org.argeo.slc.core.deploy,org. + argeo.slc.core.process,org.argeo.slc.core.structure.tree";version="0. + 11.2.SNAPSHOT",org.argeo.slc.core.structure;version="0.11.2.SNAPSHOT" + ,org.argeo.slc.msg.test.tree;uses:="org.argeo.slc.core,org.argeo.slc. + core.test.tree,org.argeo.slc.core.structure.tree,org.argeo.slc.core.t + est";version="0.11.2.SNAPSHOT",org.argeo.slc.core;version="0.11.2.SNA + PSHOT",org.argeo.slc.castor.test.tree;uses:="org.exolab.castor.mappin + g,org.argeo.slc.core.test";version="0.11.2.SNAPSHOT",org.argeo.slc.co + re.test.context;uses:="org.argeo.slc.core.structure,org.apache.common + s.logging,org.argeo.slc.core,org.argeo.slc.core.structure.tree,org.ar + geo.slc.core.test,org.springframework.beans.factory";version="0.11.2. + SNAPSHOT",org.argeo.slc.core.build;version="0.11.2.SNAPSHOT",org.arge + o.slc.core.process;uses:="org.springframework.oxm,org.argeo.slc.core, + javax.xml.transform,javax.xml.transform.stream,org.apache.commons.io" + ;version="0.11.2.SNAPSHOT",org.argeo.slc.core.structure.tree;uses:="o + rg.argeo.slc.core.structure,org.argeo.slc.core";version="0.11.2.SNAPS + HOT",org.argeo.slc.castor.msg;version="0.11.2.SNAPSHOT",org.argeo.slc + .castor.structure;version="0.11.2.SNAPSHOT",org.argeo.slc.core.proces + s.spring;version="0.11.2.SNAPSHOT",org.argeo.slc.unit;uses:="org.apac + he.commons.logging,org.springframework.context.support,org.springfram + ework.context,org.springframework.xml.xsd,org.springframework.xml.val + idation,org.xml.sax,org.argeo.slc.core,junit.framework,javax.xml.tran + sform,org.argeo.slc.spring,org.springframework.beans.factory";version + ="0.11.2.SNAPSHOT",org.argeo.slc.diff;uses:="org.argeo.slc.core,org.s + pringframework.core.io";version="0.11.2.SNAPSHOT",org.argeo.slc.xml.s + pring;version="0.11.2.SNAPSHOT",org.argeo.slc.logging;uses:="org.apac + he.log4j,org.argeo.slc.core,org.springframework.util,org.springframew + ork.core.io,org.apache.commons.io";version="0.11.2.SNAPSHOT",org.arge + o.slc.core.test.tree;uses:="org.springframework.oxm,org.apache.common + s.logging,org.springframework.xml.transform,org.springframework.core. + io,javax.xml.parsers,javax.xml.transform.dom,org.w3c.dom,org.argeo.sl + c.core.test,org.argeo.slc.core.structure,org.argeo.slc.core,javax.xml + .transform,javax.xml.transform.stream,org.apache.commons.io,org.argeo + .slc.core.structure.tree";version="0.11.2.SNAPSHOT",org.argeo.slc.cas + tor;version="0.11.2.SNAPSHOT",org.argeo.slc.unit.test.tree;uses:="org + .apache.commons.logging,org.argeo.slc.unit,org.argeo.slc.core.test.tr + ee,org.argeo.slc.core.test,org.argeo.slc.core.structure,org.argeo.slc + .msg.test.tree,junit.framework,org.argeo.slc.core.build,org.argeo.slc + .unit.process,org.argeo.slc.core.deploy,org.argeo.slc.core.process,or + g.argeo.slc.core.structure.tree";version="0.11.2.SNAPSHOT",org.argeo. + slc.dao.test;uses:="org.argeo.slc.core.test";version="0.11.2.SNAPSHOT + ",org.argeo.slc.castor.test;version="0.11.2.SNAPSHOT",org.argeo.slc.s + upport.deploy;uses:="org.apache.commons.logging,org.argeo.slc.core,or + g.argeo.slc.core.build,org.argeo.slc.core.deploy";version="0.11.2.SNA + PSHOT",org.argeo.slc.castor.structure.tree;uses:="org.exolab.castor.m + apping,org.argeo.slc.core.structure.tree";version="0.11.2.SNAPSHOT",o + rg.argeo.slc.castor.spring;version="0.11.2.SNAPSHOT",org.argeo.slc.su + pport.deploy.db;uses:="org.apache.commons.logging,org.dbunit.operatio + n,org.springframework.core.io,org.dbunit.dataset,org.argeo.slc.core,j + avax.sql,org.argeo.slc.core.build,org.dbunit.dataset.xml,org.dbunit.d + atabase,org.dbunit,org.argeo.slc.core.deploy";version="0.11.2.SNAPSHO + T",org.argeo.slc.core.test.tree.htmlreport;version="0.11.2.SNAPSHOT", + org.argeo.slc.unit.process;uses:="junit.framework,org.argeo.slc.unit, + org.argeo.slc.core.process";version="0.11.2.SNAPSHOT",org.argeo.slc.s + pring;uses:="org.apache.commons.logging,org.argeo.slc.core,org.spring + framework.core.io,org.springframework.beans.factory";version="0.11.2. + SNAPSHOT",org.argeo.slc.runtime;uses:="org.argeo.slc.core.process";ve + rsion="0.11.2.SNAPSHOT",org.argeo.slc.core.deploy;uses:="org.apache.c + ommons.logging,org.argeo.slc.core,org.argeo.slc.core.build";version=" + 0.11.2.SNAPSHOT",org.argeo.slc.msg.process;uses:="org.argeo.slc.core. + process";version="0.11.2.SNAPSHOT",org.argeo.slc.xml;version="0.11.2. + SNAPSHOT" +Tool: Bnd-0.0.255 +Bundle-Name: Argeo SLC Core +Created-By: 1.6.0 (Sun Microsystems Inc.) +Bundle-Vendor: Argeo +Bundle-Version: 0.11.2.SNAPSHOT +Bundle-ManifestVersion: 2 +Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt +Bundle-Description: SLC Core +Import-Package: javax.sql,javax.xml.parsers;version="1.3",javax.xml.tr + ansform;version="1.3",javax.xml.transform.dom;version="1.3",javax.xml + .transform.stream;version="1.3",junit.framework;version="3.8",org.apa + che.commons.io;version="1.4",org.apache.commons.logging;version="1.1" + ,org.apache.log4j;version="1.2",org.argeo.slc.castor;version="0.11.2. + SNAPSHOT",org.argeo.slc.castor.msg;version="0.11.2.SNAPSHOT",org.arge + o.slc.castor.process;version="0.11.2.SNAPSHOT",org.argeo.slc.castor.s + pring;version="0.11.2.SNAPSHOT",org.argeo.slc.castor.structure;versio + n="0.11.2.SNAPSHOT",org.argeo.slc.castor.structure.tree;version="0.11 + .2.SNAPSHOT",org.argeo.slc.castor.test;version="0.11.2.SNAPSHOT",org. + argeo.slc.castor.test.tree;version="0.11.2.SNAPSHOT",org.argeo.slc.co + re;version="0.11.2.SNAPSHOT",org.argeo.slc.core.build;version="0.11.2 + .SNAPSHOT",org.argeo.slc.core.deploy;version="0.11.2.SNAPSHOT",org.ar + geo.slc.core.process;version="0.11.2.SNAPSHOT",org.argeo.slc.core.pro + cess.spring;version="0.11.2.SNAPSHOT",org.argeo.slc.core.structure;ve + rsion="0.11.2.SNAPSHOT",org.argeo.slc.core.structure.tree;version="0. + 11.2.SNAPSHOT",org.argeo.slc.core.test;version="0.11.2.SNAPSHOT",org. + argeo.slc.core.test.context;version="0.11.2.SNAPSHOT",org.argeo.slc.c + ore.test.spring;version="0.11.2.SNAPSHOT",org.argeo.slc.core.test.tre + e;version="0.11.2.SNAPSHOT",org.argeo.slc.core.test.tree.htmlreport;v + ersion="0.11.2.SNAPSHOT",org.argeo.slc.dao.process;version="0.11.2.SN + APSHOT",org.argeo.slc.dao.test;version="0.11.2.SNAPSHOT",org.argeo.sl + c.dao.test.tree;version="0.11.2.SNAPSHOT",org.argeo.slc.diff;version= + "0.11.2.SNAPSHOT",org.argeo.slc.logging;version="0.11.2.SNAPSHOT",org + .argeo.slc.msg.process;version="0.11.2.SNAPSHOT",org.argeo.slc.msg.te + st.tree;version="0.11.2.SNAPSHOT",org.argeo.slc.runtime;version="0.11 + .2.SNAPSHOT",org.argeo.slc.spring;version="0.11.2.SNAPSHOT",org.argeo + .slc.support.deploy;version="0.11.2.SNAPSHOT",org.argeo.slc.support.d + eploy.db;version="0.11.2.SNAPSHOT",org.argeo.slc.unit;version="0.11.2 + .SNAPSHOT",org.argeo.slc.unit.process;version="0.11.2.SNAPSHOT",org.a + rgeo.slc.unit.test.tree;version="0.11.2.SNAPSHOT",org.argeo.slc.xml;v + ersion="0.11.2.SNAPSHOT",org.argeo.slc.xml.spring;version="0.11.2.SNA + PSHOT",org.dbunit;version="2.2",org.dbunit.database;version="2.2",org + .dbunit.dataset;version="2.2",org.dbunit.dataset.xml;version="2.2",or + g.dbunit.operation;version="2.2",org.exolab.castor.mapping;version="1 + .2",org.springframework.beans.factory;version="2.5.6.A",org.springfra + mework.context;version="2.5.6.A",org.springframework.context.support; + version="2.5.6.A",org.springframework.core.io;version="2.5.6.A",org.s + pringframework.oxm;version="1.5.5.A",org.springframework.util;version + ="2.5.6.A",org.springframework.xml.transform;version="1.5.5.A",org.sp + ringframework.xml.validation;version="1.5.5.A",org.springframework.xm + l.xsd;version="1.5.5.A",org.w3c.dom;version="1.3",org.xml.sax;version + ="1.3" +Bundle-SymbolicName: org.argeo.slc.core +Bundle-DocURL: http://www.argeo.org +Originally-Created-By: 1.6.0 (Sun Microsystems Inc.) + diff --git a/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/mapping.xml b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/mapping.xml new file mode 100644 index 000000000..92c2c71d0 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/mapping.xml @@ -0,0 +1,41 @@ + + + + Mapping of generic types + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/msg/mapping.xml b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/msg/mapping.xml new file mode 100644 index 000000000..2f54085c0 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/msg/mapping.xml @@ -0,0 +1,99 @@ + + + + Message objects XML mapping + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/process/mapping.xml b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/process/mapping.xml new file mode 100644 index 000000000..1b5b2ec95 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/process/mapping.xml @@ -0,0 +1,51 @@ + + + + + + Process objects XML mapping + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/spring/applicationContext.xml b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/spring/applicationContext.xml new file mode 100644 index 000000000..45a470a3f --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/spring/applicationContext.xml @@ -0,0 +1,38 @@ + + + + + + + classpath:org/argeo/slc/castor/msg/mapping.xml + + + classpath:org/argeo/slc/castor/process/mapping.xml + + + classpath:org/argeo/slc/castor/structure/mapping.xml + + + classpath:org/argeo/slc/castor/test/mapping.xml + + + + + + + + + + + + + + + diff --git a/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/structure/mapping.xml b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/structure/mapping.xml new file mode 100644 index 000000000..3e20025b3 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/structure/mapping.xml @@ -0,0 +1,35 @@ + + + + Structure related objects XML mapping + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/test/mapping.xml b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/test/mapping.xml new file mode 100644 index 000000000..5b6384ddd --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/test/mapping.xml @@ -0,0 +1,108 @@ + + + + Test objects XML mapping + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/core/process/spring/applicationContext.xml b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/core/process/spring/applicationContext.xml new file mode 100644 index 000000000..45bcac91a --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/core/process/spring/applicationContext.xml @@ -0,0 +1,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/core/test/spring/applicationContext.xml b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/core/test/spring/applicationContext.xml new file mode 100644 index 000000000..20c821401 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/core/test/spring/applicationContext.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/core/test/tree/basicReport.xslt b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/core/test/tree/basicReport.xslt new file mode 100644 index 000000000..947cef0f9 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/core/test/tree/basicReport.xslt @@ -0,0 +1,50 @@ + + + + + + + + + Result + + +

+ Result + +

+ +

+ +

+ + + + + + + + + + + + + +
+ + + +
+
+ + +
+
\ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/core/test/tree/htmlreport/index.html b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/core/test/tree/htmlreport/index.html new file mode 100644 index 000000000..32beed3b5 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/core/test/tree/htmlreport/index.html @@ -0,0 +1,16 @@ + + + +SLC test results + + + + + + <h2>Frame Alert</h2> + <p>This document is designed to be viewed using the frames feature. + If you see this message, you are using a non-frame-capable web client. + </p> + + + diff --git a/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/core/test/tree/htmlreport/style.css b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/core/test/tree/htmlreport/style.css new file mode 100644 index 000000000..134c6b55d --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/core/test/tree/htmlreport/style.css @@ -0,0 +1,64 @@ +body { + font-family: sans-serif; + font-size: 12px; + color: black; + background-color: white; +} + +h1 { + font-family: sans-serif; + font-size: 16px; + font-weight: bold; + color: #000000; + padding: 0px 0px 5px 0px; + margin: 0px; +} + +h2 { + font-family: sans-serif; + font-size: 14px; + font-weight: bold; + color: #000000; + padding: 5px 0px 5px 0px; + margin: 0px; + margin-top: 5px; +} + +table,form { + margin: 0px; +} + +th { + font-size: 12px; + padding: 2px 20px 2px 2px; + vertical-align: top; + text-align: left; +} + +td { + font-size: 12px; + padding: 1px; + vertical-align: top; + text-align: left; +} + +.passed { + color: green; +} + +.failed { + color: red; +} + +a { + text-decoration: none; +} + +a.nav { + color: #0066CC; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/xml/slc.xsd b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/xml/slc.xsd new file mode 100644 index 000000000..5b7b43e15 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/xml/slc.xsd @@ -0,0 +1,259 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/xml/spring/applicationContext.xml b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/xml/spring/applicationContext.xml new file mode 100644 index 000000000..13bd1dd03 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/xml/spring/applicationContext.xml @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/runtime/org.argeo.slc.support.castor/src/site/apt/index.apt b/runtime/org.argeo.slc.support.castor/src/site/apt/index.apt new file mode 100644 index 000000000..f414460db --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/site/apt/index.apt @@ -0,0 +1 @@ +Argeo SLC Site \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/test/java/org/argeo/slc/core/process/SlcExecutionCastorTest.java b/runtime/org.argeo.slc.support.castor/src/test/java/org/argeo/slc/core/process/SlcExecutionCastorTest.java new file mode 100644 index 000000000..efb4cf513 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/test/java/org/argeo/slc/core/process/SlcExecutionCastorTest.java @@ -0,0 +1,110 @@ +package org.argeo.slc.core.process; + +import java.io.IOException; +import java.io.StringReader; +import java.text.SimpleDateFormat; +import java.util.UUID; + +import javax.xml.transform.stream.StreamSource; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.msg.process.SlcExecutionRequest; +import org.argeo.slc.msg.process.SlcExecutionStepsRequest; +import org.argeo.slc.unit.AbstractSpringTestCase; +import org.argeo.slc.unit.UnitXmlUtils; +import org.argeo.slc.unit.process.SlcExecutionTestUtils; +import org.springframework.oxm.Marshaller; +import org.springframework.oxm.Unmarshaller; +import org.springframework.xml.transform.StringResult; +import org.springframework.xml.transform.StringSource; +import org.springframework.xml.validation.XmlValidator; + +public class SlcExecutionCastorTest extends AbstractSpringTestCase { + private Log log = LogFactory.getLog(getClass()); + + private Marshaller marshaller; + private Unmarshaller unmarshaller; + + @Override + public void setUp() { + marshaller = getBean(Marshaller.class); + unmarshaller = getBean(Unmarshaller.class); + } + + public void testMarshalling() throws Exception { + SlcExecution slcExec = SlcExecutionTestUtils.createSimpleSlcExecution(); + + SlcExecutionRequest msgSave = new SlcExecutionRequest(); + msgSave.setSlcExecution(slcExec); + + String msgSaveXml = marshallAndLog(marshaller, msgSave); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + SlcExecutionStep step0 = new SlcExecutionStep(); + step0.setUuid(UUID.randomUUID().toString()); + step0.setBegin(sdf.parse("2008-04-17 18:21")); + step0.setType("LOG"); + step0.addLog("A log message\nand another line"); + + SlcExecutionStep step1 = new SlcExecutionStep(); + step1.setUuid(UUID.randomUUID().toString()); + step1.setBegin(sdf.parse("2008-04-17 18:25")); + step1.setType("LOG"); + step1.addLog("A nother log message"); + + SlcExecutionStepsRequest msgNotif = new SlcExecutionStepsRequest(); + msgNotif.addStep(step0); + msgNotif.addStep(step1); + msgNotif.setSlcExecutionUuid(slcExec.getUuid()); + + String msgNotifXml = marshallAndLog(marshaller, msgNotif); + + SlcExecutionRequest msgSaveUnm = unmarshall(unmarshaller, msgSaveXml); + assertNotNull(msgSaveUnm); + SlcExecutionTestUtils.assertSlcExecution(slcExec, msgSaveUnm + .getSlcExecution()); + + SlcExecutionStepsRequest msgNotifUnm = unmarshall(unmarshaller, + msgNotifXml); + assertNotNull(msgNotifUnm); + assertEquals(slcExec.getUuid(), msgNotifUnm.getSlcExecutionUuid()); + assertEquals(2, msgNotifUnm.getSteps().size()); + SlcExecutionTestUtils.assertSlcExecutionStep(step0, msgNotifUnm + .getSteps().get(0)); + SlcExecutionTestUtils.assertSlcExecutionStep(step1, msgNotifUnm + .getSteps().get(1)); + + SlcExecution slcExecUnm = msgSaveUnm.getSlcExecution(); + slcExecUnm.getSteps().addAll(msgNotifUnm.getSteps()); + + SlcExecutionRequest msgUpdate = new SlcExecutionRequest(); + msgUpdate.setSlcExecution(slcExecUnm); + String msgUpdateXml = marshallAndLog(marshaller, msgUpdate); + + SlcExecutionRequest msgUpdateUnm = unmarshall(unmarshaller, + msgUpdateXml); + assertNotNull(msgUpdateUnm); + } + + private String marshallAndLog(Marshaller marshaller, Object obj) + throws IOException { + StringResult xml = new StringResult(); + marshaller.marshal(obj, xml); + log.info("Marshalled object: " + xml); + + UnitXmlUtils.assertXmlValidation(getBean(XmlValidator.class), + new StringSource(xml.toString())); + + return xml.toString(); + } + + private T unmarshall(Unmarshaller unmarshaller, String xml) + throws IOException { + StringReader reader = new StringReader(xml); + Object obj = unmarshaller.unmarshal(new StreamSource(reader)); + IOUtils.closeQuietly(reader); + return (T) obj; + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/test/java/org/argeo/slc/core/structure/tree/TreeSPathTest.java b/runtime/org.argeo.slc.support.castor/src/test/java/org/argeo/slc/core/structure/tree/TreeSPathTest.java new file mode 100644 index 000000000..f24abc580 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/test/java/org/argeo/slc/core/structure/tree/TreeSPathTest.java @@ -0,0 +1,58 @@ +package org.argeo.slc.core.structure.tree; + +import junit.framework.TestCase; + +public class TreeSPathTest extends TestCase { + + public void testNew() { + TreeSPath path = new TreeSPath("/test"); + assertEquals("test", path.getName()); + assertNull(path.getParent()); + + path = new TreeSPath("/root/subdir"); + assertEquals("subdir", path.getName()); + assertEquals(new TreeSPath("/root"), path.getParent()); + } + + public void testEquals() { + TreeSPath path1 = new TreeSPath("/test"); + TreeSPath path2 = new TreeSPath("/test"); + assertEquals(path1, path2); + + path1 = new TreeSPath("/test/subdir/anotherdir"); + path2 = new TreeSPath("/test/subdir/anotherdir"); + assertEquals(path1, path2); + + path1 = new TreeSPath("/test/subdir/anotherd"); + path2 = new TreeSPath("/test/subdir/anotherdir"); + assertNotSame(path1, path2); + + path1 = new TreeSPath("/test/subdir"); + path2 = new TreeSPath("/test/subdir/anotherdir"); + assertNotSame(path1, path2); + + path1 = new TreeSPath("/test/subd/anotherdir"); + path2 = new TreeSPath("/test/subdir/anotherdir"); + assertNotSame(path1, path2); + } + + public void testCheckFormat() { + try { + new TreeSPath("hello"); + fail("Bad format should be rejected"); + } catch (Exception e) { + // exception expected + } + + try { + new TreeSPath("/"); + fail("Bad format should be rejected"); + } catch (Exception e) { + // exception expected + } + + assertEquals(new TreeSPath("/test"), new TreeSPath("/test/")); + assertEquals(new TreeSPath("/test/dir"), new TreeSPath( + "//test///dir////")); + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/test/java/org/argeo/slc/core/test/context/ContextTest.java b/runtime/org.argeo.slc.support.castor/src/test/java/org/argeo/slc/core/test/context/ContextTest.java new file mode 100644 index 000000000..6d53ef7e3 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/test/java/org/argeo/slc/core/test/context/ContextTest.java @@ -0,0 +1,30 @@ +package org.argeo.slc.core.test.context; + +import java.util.List; + +import org.argeo.slc.core.test.SimpleTestResult; +import org.argeo.slc.core.test.TestResultPart; +import org.argeo.slc.core.test.TestStatus; +import org.argeo.slc.unit.AbstractSpringTestCase; + +public class ContextTest extends AbstractSpringTestCase { + + public void testComplexContext() { + SimpleTestResult testResult = new SimpleTestResult(); + ContextUtils.compareReachedExpected( + (ContextAware) getBean("context.c1"), testResult, null); + ContextUtils.compareReachedExpected( + (ContextAware) getBean("context.c2"), testResult, null); + ContextUtils.compareReachedExpected( + (ContextAware) getBean("context.c3"), testResult, null); + + List parts = testResult.getParts(); + assertEquals(6, parts.size()); + assertEquals(TestStatus.PASSED, parts.get(0).getStatus()); + assertEquals(TestStatus.PASSED, parts.get(1).getStatus()); + assertEquals(TestStatus.PASSED, parts.get(2).getStatus()); + assertEquals(TestStatus.FAILED, parts.get(3).getStatus()); + assertEquals(TestStatus.PASSED, parts.get(4).getStatus()); + assertEquals(TestStatus.PASSED, parts.get(5).getStatus()); + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/test/java/org/argeo/slc/core/test/tree/TreeTestResultCastorTest.java b/runtime/org.argeo.slc.support.castor/src/test/java/org/argeo/slc/core/test/tree/TreeTestResultCastorTest.java new file mode 100644 index 000000000..baf8e3b7e --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/test/java/org/argeo/slc/core/test/tree/TreeTestResultCastorTest.java @@ -0,0 +1,96 @@ +package org.argeo.slc.core.test.tree; + +import static org.argeo.slc.unit.UnitUtils.assertDateSec; +import static org.argeo.slc.unit.test.tree.TreeTestResultTestUtils.createCompleteTreeTestResult; +import static org.argeo.slc.unit.test.tree.TreeTestResultTestUtils.createSimpleResultPartRequest; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.msg.test.tree.CloseTreeTestResultRequest; +import org.argeo.slc.msg.test.tree.CreateTreeTestResultRequest; +import org.argeo.slc.msg.test.tree.ResultPartRequest; +import org.argeo.slc.unit.AbstractSpringTestCase; +import org.argeo.slc.unit.UnitXmlUtils; +import org.argeo.slc.unit.test.tree.UnitTestTreeUtil; +import org.springframework.oxm.Marshaller; +import org.springframework.oxm.Unmarshaller; +import org.springframework.xml.transform.StringResult; +import org.springframework.xml.transform.StringSource; +import org.springframework.xml.validation.XmlValidator; + +public class TreeTestResultCastorTest extends AbstractSpringTestCase { + private Log log = LogFactory.getLog(getClass()); + + private Marshaller marshaller; + private Unmarshaller unmarshaller; + + @Override + public void setUp() { + marshaller = getBean(Marshaller.class); + unmarshaller = getBean(Unmarshaller.class); + } + + public void testMarshUnmarsh() throws Exception { + TreeTestResult ttr = createCompleteTreeTestResult(); + + StringResult xml = marshallAndValidate(ttr); + + TreeTestResult ttrUnm = (TreeTestResult) unmarshaller + .unmarshal(new StringSource(xml.toString())); + + UnitTestTreeUtil.assertTreeTestResult(ttr, ttrUnm); + } + + public void testCreateTreeTestResultRequest() throws Exception { + CreateTreeTestResultRequest req = new CreateTreeTestResultRequest(); + req.setTreeTestResult(createCompleteTreeTestResult()); + + StringResult xml = marshallAndValidate(req); + + CreateTreeTestResultRequest reqUnm = (CreateTreeTestResultRequest) unmarshaller + .unmarshal(new StringSource(xml.toString())); + + UnitTestTreeUtil.assertTreeTestResult(req.getTreeTestResult(), reqUnm + .getTreeTestResult()); + } + + public void testResultPartRequest() throws Exception { + TreeTestResult ttr = createCompleteTreeTestResult(); + ResultPartRequest req = createSimpleResultPartRequest(ttr); + + StringResult xml = marshallAndValidate(req); + + ResultPartRequest reqUnm = (ResultPartRequest) unmarshaller + .unmarshal(new StringSource(xml.toString())); + + UnitTestTreeUtil + .assertPart(req.getResultPart(), reqUnm.getResultPart()); + } + + public void testCloseTreeTestResultRequest() throws Exception { + TreeTestResult ttr = createCompleteTreeTestResult(); + ttr.close(); + + CloseTreeTestResultRequest req = new CloseTreeTestResultRequest(ttr + .getUuid(), ttr.getCloseDate()); + + StringResult xml = marshallAndValidate(req); + + CloseTreeTestResultRequest reqUnm = (CloseTreeTestResultRequest) unmarshaller + .unmarshal(new StringSource(xml.toString())); + + assertEquals(ttr.getUuid(), reqUnm.getResultUuid()); + assertDateSec(ttr.getCloseDate(), ttr.getCloseDate()); + } + + private StringResult marshallAndValidate(Object obj) throws Exception { + StringResult xml = new StringResult(); + marshaller.marshal(obj, xml); + + log.info("Marshalled ResultPart Request: " + xml); + + UnitXmlUtils.assertXmlValidation(getBean(XmlValidator.class), + new StringSource(xml.toString())); + return xml; + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/test/java/org/argeo/slc/core/test/tree/TreeTestResultCollectionCastorTest.java b/runtime/org.argeo.slc.support.castor/src/test/java/org/argeo/slc/core/test/tree/TreeTestResultCollectionCastorTest.java new file mode 100644 index 000000000..29ee30d82 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/test/java/org/argeo/slc/core/test/tree/TreeTestResultCollectionCastorTest.java @@ -0,0 +1,62 @@ +package org.argeo.slc.core.test.tree; + +import static org.argeo.slc.unit.test.tree.TreeTestResultTestUtils.createCompleteTreeTestResult; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.unit.AbstractSpringTestCase; +import org.argeo.slc.unit.UnitXmlUtils; +import org.argeo.slc.unit.test.tree.UnitTestTreeUtil; +import org.springframework.oxm.Marshaller; +import org.springframework.oxm.Unmarshaller; +import org.springframework.xml.transform.StringResult; +import org.springframework.xml.transform.StringSource; +import org.springframework.xml.validation.XmlValidator; + +public class TreeTestResultCollectionCastorTest extends AbstractSpringTestCase { + private Log log = LogFactory.getLog(getClass()); + + private Marshaller marshaller; + private Unmarshaller unmarshaller; + + @Override + public void setUp() { + marshaller = getBean(Marshaller.class); + unmarshaller = getBean(Unmarshaller.class); + } + + public void testMarshUnmarsh() throws Exception { + TreeTestResult ttr = createCompleteTreeTestResult(); + TreeTestResult ttr2 = createCompleteTreeTestResult(); + + TreeTestResultCollection ttrc = new TreeTestResultCollection(); + ttrc.setId("testCollection"); + ttrc.getResults().add(ttr); + ttrc.getResults().add(ttr2); + + StringResult xml = marshallAndValidate(ttrc); + + TreeTestResultCollection ttrcUnm = (TreeTestResultCollection) unmarshaller + .unmarshal(new StringSource(xml.toString())); + + assertEquals(ttrc.getId(), ttrcUnm.getId()); + assertEquals(ttrc.getResults().size(), ttrcUnm.getResults().size()); + for (TreeTestResult ttrT : ttrc.getResults()) { + if (ttrT.getUuid().equals(ttr.getUuid())) + UnitTestTreeUtil.assertTreeTestResult(ttr, ttrT); + else + UnitTestTreeUtil.assertTreeTestResult(ttr2, ttrT); + } + } + + private StringResult marshallAndValidate(Object obj) throws Exception { + StringResult xml = new StringResult(); + marshaller.marshal(obj, xml); + + log.info("Marshalled ResultPart Request: " + xml); + + UnitXmlUtils.assertXmlValidation(getBean(XmlValidator.class), + new StringSource(xml.toString())); + return xml; + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/test/java/org/argeo/slc/diff/LineTokenizerTest.java b/runtime/org.argeo.slc.support.castor/src/test/java/org/argeo/slc/diff/LineTokenizerTest.java new file mode 100644 index 000000000..58ed61a92 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/test/java/org/argeo/slc/diff/LineTokenizerTest.java @@ -0,0 +1,53 @@ +package org.argeo.slc.diff; + +import java.util.List; + +import junit.framework.TestCase; + +public class LineTokenizerTest extends TestCase { + public void testSimple() throws Exception { + testAndAssert("a,b,c", new String[] { "a", "b", "c" }); + testAndAssert("hello,bonjour,hallo,priviet", new String[] { "hello", + "bonjour", "hallo", "priviet" }); + } + + public void testTricky() throws Exception { + testAndAssert("alone", new String[] { "alone" }); + testAndAssert("", new String[] { "" }); + + testAndAssert(",hello,bonjour,hallo,priviet", new String[] { "", + "hello", "bonjour", "hallo", "priviet" }); + testAndAssert("hello,bonjour,,hallo,priviet", new String[] { "hello", + "bonjour", "", "hallo", "priviet" }); + testAndAssert("hello,bonjour,hallo,priviet,", new String[] { "hello", + "bonjour", "hallo", "priviet", "" }); + testAndAssert(",hello,,bonjour,hallo,,,,priviet,", new String[] { "", + "hello", "", "bonjour", "hallo", "", "", "", "priviet", "" }); + + testAndAssert(",,,", new String[] { "", "", "", "" }); + } + + public void testComplex() throws Exception { + testAndAssert("a#b#c", '#', "", new String[] { "a", "b", "c" }); + testAndAssert("hello!bonjour!hallo!priviet", '!', "", new String[] { + "hello", "bonjour", "hallo", "priviet" }); + + testAndAssert("hello,,bonjour,,hallo,priviet", ',', "", + new String[] { "hello", "", "bonjour", "", + "hallo", "priviet" }); + } + + private void testAndAssert(String str, String[] expected) { + testAndAssert(str, ',', "", expected); + } + + private void testAndAssert(String str, Character sep, String noValueStr, + String[] expected) { + List res = LineTokenizer.tokenize(str, sep, noValueStr); + assertEquals("Size", expected.length, res.size()); + for (int i = 0; i < res.size(); i++) { + String token = res.get(i); + assertEquals("Value@" + i, expected[i], token); + } + } +} diff --git a/runtime/org.argeo.slc.support.castor/src/test/resources/log4j.properties b/runtime/org.argeo.slc.support.castor/src/test/resources/log4j.properties new file mode 100644 index 000000000..0133bab88 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/test/resources/log4j.properties @@ -0,0 +1,22 @@ +# Set root logger level to DEBUG and its only appender to A1. +log4j.rootLogger=WARN, console + +## Levels +# Slc +log4j.logger.org.argeo=DEBUG + +# Castor +log4j.logger.org.exolab.castor=WARN + +# Spring +log4j.logger.org.springframework=WARN + + +## Appenders +# A1 is set to be a ConsoleAppender. +log4j.appender.console=org.apache.log4j.ConsoleAppender + +# A1 uses PatternLayout. +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n + diff --git a/runtime/org.argeo.slc.support.castor/src/test/resources/org/argeo/slc/castor/applicationContext.xml b/runtime/org.argeo.slc.support.castor/src/test/resources/org/argeo/slc/castor/applicationContext.xml new file mode 100644 index 000000000..7a89af927 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/test/resources/org/argeo/slc/castor/applicationContext.xml @@ -0,0 +1,11 @@ + + + + diff --git a/runtime/org.argeo.slc.support.castor/src/test/resources/org/argeo/slc/core/process/applicationContext.xml b/runtime/org.argeo.slc.support.castor/src/test/resources/org/argeo/slc/core/process/applicationContext.xml new file mode 100644 index 000000000..899daf548 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/test/resources/org/argeo/slc/core/process/applicationContext.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/test/resources/org/argeo/slc/core/test/context/applicationContext.xml b/runtime/org.argeo.slc.support.castor/src/test/resources/org/argeo/slc/core/test/context/applicationContext.xml new file mode 100644 index 000000000..e45899c11 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/test/resources/org/argeo/slc/core/test/context/applicationContext.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/runtime/org.argeo.slc.support.castor/src/test/resources/org/argeo/slc/core/test/tree/applicationContext.xml b/runtime/org.argeo.slc.support.castor/src/test/resources/org/argeo/slc/core/test/tree/applicationContext.xml new file mode 100644 index 000000000..9601c3301 --- /dev/null +++ b/runtime/org.argeo.slc.support.castor/src/test/resources/org/argeo/slc/core/test/tree/applicationContext.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file