]> git.argeo.org Git - gpl/argeo-slc.git/commitdiff
@update:79; First end-to-end integration test
authorMathieu Baudier <mbaudier@argeo.org>
Mon, 8 Jun 2009 07:03:11 +0000 (07:03 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Mon, 8 Jun 2009 07:03:11 +0000 (07:03 +0000)
git-svn-id: https://svn.argeo.org/slc/trunk@2512 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

demo/site/org.argeo.slc.demo.log4j/log4j.properties
integration-tests/org.argeo.slc.it.webapp/src/test/java/org/argeo/slc/it/webapp/SimpleScenarioTest.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/server/client/SlcServerHttpClient.java
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/server/client/impl/AbstractHttpServicesClient.java
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/server/client/impl/SlcServerHttpClientImpl.java
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/server/unit/AbstractHttpClientTestCase.java
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/impl/process/SlcExecutionServiceImpl.java
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/process/NewSlcExecutionController.java
runtime/org.argeo.slc.server/src/main/resources/org/argeo/slc/server/client/spring.xml
runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/spring.xml
runtime/org.argeo.slc.support.hibernate/src/main/java/org/argeo/slc/hibernate/process/SlcExecutionDaoHibernate.java

index a1a6509b69c56c31971bf8693c151d60ed040784..bae808ee83ac232e2be4a934083826ced3f19cd6 100644 (file)
@@ -6,7 +6,7 @@ log4j.logger.org.argeo.slc.execution.ExecutionParameterPostProcessor=TRACE
 log4j.logger.org.argeo.slc.execution.ExecutionContext=DEBUG
 log4j.logger.org.argeo.slc.execution.SimpleExecutionSpec=DEBUG
 
-log4j.logger.org.argeo.slc.services=DEBUG
+log4j.logger.org.argeo.slc.web.mvc=DEBUG
 
 log4j.logger.org.hibernate=WARN
 
diff --git a/integration-tests/org.argeo.slc.it.webapp/src/test/java/org/argeo/slc/it/webapp/SimpleScenarioTest.java b/integration-tests/org.argeo.slc.it.webapp/src/test/java/org/argeo/slc/it/webapp/SimpleScenarioTest.java
new file mode 100644 (file)
index 0000000..1d751f3
--- /dev/null
@@ -0,0 +1,27 @@
+package org.argeo.slc.it.webapp;
+
+import org.argeo.slc.Condition;
+import org.argeo.slc.core.test.tree.TreeTestResultList;
+import org.argeo.slc.runtime.SlcAgentDescriptor;
+import org.argeo.slc.server.unit.AbstractHttpClientTestCase;
+
+public class SimpleScenarioTest extends AbstractHttpClientTestCase {
+       public void testSimpleScenario() throws Exception {
+               // Get agent
+               SlcAgentDescriptor agentDescriptor = getHttpClient().waitForOneAgent();
+               assertNotNull(agentDescriptor);
+
+               // Launch SLC Execution
+               // TODO: don't hardcode tested version
+               assertAnswerOk(getHttpClient().startFlow(agentDescriptor.getUuid(),
+                               "org.argeo.slc.demo.basic", "0.11.4.SNAPSHOT", "main"));
+
+               getHttpClient().callServiceSafe("listResults.service", null,
+                               new Condition<TreeTestResultList>() {
+
+                                       public Boolean check(TreeTestResultList obj) {
+                                               return obj.getList().size() == 3;
+                                       }
+                               }, null);
+       }
+}
index 2113438f8c06566bdcef903c8b464053d9380958..3bd51e9105cfb64dd2062ce97654af8f3f4a75a9 100644 (file)
@@ -1,9 +1,17 @@
 package org.argeo.slc.server.client;
 
+import org.argeo.slc.msg.ExecutionAnswer;
 import org.argeo.slc.runtime.SlcAgentDescriptor;
 
 /** Abstraction of the access to HTTP services of an SLC Server. */
 public interface SlcServerHttpClient extends HttpServicesClient {
        /** Wait for one agent to be available. */
        public SlcAgentDescriptor waitForOneAgent();
+
+       /** Wait for the http server to be ready. */
+       public void waitForServerToBeReady();
+
+       /** Start an execution flow on the given agent. */
+       public ExecutionAnswer startFlow(String agentId, String moduleName,
+                       String version, String flowName);
 }
index ba4e584efb242a9bc12d985a9bb4879cf546d798..410e8d9afe029d119425a8f0d565bf35750a1013 100644 (file)
@@ -1,11 +1,18 @@
 package org.argeo.slc.server.client.impl;
 
 import java.io.IOException;
-import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
 import java.net.HttpURLConnection;
 import java.net.URL;
+import java.net.URLEncoder;
+import java.util.Iterator;
 import java.util.Map;
 
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamResult;
 import javax.xml.transform.stream.StreamSource;
 
 import org.apache.commons.io.IOUtils;
@@ -14,6 +21,7 @@ import org.apache.commons.logging.LogFactory;
 import org.argeo.slc.Condition;
 import org.argeo.slc.SlcException;
 import org.argeo.slc.server.client.HttpServicesClient;
+import org.springframework.oxm.Marshaller;
 import org.springframework.oxm.Unmarshaller;
 import org.springframework.util.Assert;
 
@@ -21,13 +29,22 @@ public abstract class AbstractHttpServicesClient implements HttpServicesClient {
        private final static Log log = LogFactory
                        .getLog(AbstractHttpServicesClient.class);
        private Unmarshaller unmarshaller;
+       private Marshaller marshaller;
        private String baseUrl;
+       private String encoding = "UTF-8";
 
        private Long retryPeriod = 1000l;
-       @SuppressWarnings(value = { "unchecked" })
+       private Long defaultTimeout = 30 * 1000l;
+
        public <T> T callService(String path, Map<String, String> parameters) {
+               return callService(path, parameters, null);
+       }
+
+       @SuppressWarnings(value = { "unchecked" })
+       public <T> T callService(String path, Map<String, String> parameters,
+                       Object body) {
                try {
-                       return (T) callServiceLowLevel(path, parameters);
+                       return (T) callServiceLowLevel(path, parameters, body);
                } catch (Exception e) {
                        throw new SlcException("Cannot call service " + path + " on "
                                        + baseUrl, e);
@@ -37,13 +54,16 @@ public abstract class AbstractHttpServicesClient implements HttpServicesClient {
        @SuppressWarnings(value = { "unchecked" })
        public <T> T callServiceSafe(String path, Map<String, String> parameters,
                        Condition<T> condition, Long timeout) {
+               if (timeout == null)
+                       timeout = defaultTimeout;
+
                long begin = System.currentTimeMillis();
                try {
                        Object obj = null;
                        long duration = System.currentTimeMillis() - begin;
                        while (duration < timeout) {
                                try {
-                                       obj = callServiceLowLevel(path, parameters);
+                                       obj = callServiceLowLevel(path, parameters, null);
                                } catch (IOException e) {
                                        if (log.isTraceEnabled())
                                                log.trace("Exception when calling service " + path
@@ -83,27 +103,76 @@ public abstract class AbstractHttpServicesClient implements HttpServicesClient {
        }
 
        protected Object callServiceLowLevel(String path,
-                       Map<String, String> parameters) throws IOException {
+                       Map<String, String> parameters, Object body) throws IOException {
                Assert.notNull(baseUrl, "base url");
-               InputStream in = null;
+               HttpURLConnection connection = null;
+               Writer writer = null;
+               Reader reader = null;
                try {
-                       URL url = new URL(baseUrl + path);
-                       HttpURLConnection connection = (HttpURLConnection) url
-                                       .openConnection();
-                       if (parameters != null) {
-                               for (String key : parameters.keySet()) {
-                                       connection.addRequestProperty(key, parameters.get(key));
-                               }
+                       URL url = createUrl(path, parameters);
+                       connection = (HttpURLConnection) url.openConnection();
+
+                       if (body != null) {
+                               connection.setRequestMethod("POST");
+                               connection.setDoOutput(true);
+                               connection.setDoInput(true);
+                               connection.setUseCaches(false);
+                               connection.setAllowUserInteraction(false);
+                               connection.setRequestProperty("Content-type",
+                                               "text/xml; charset=" + encoding);
                        }
 
+                       // Establish the connection
                        connection.connect();
 
-                       in = connection.getInputStream();
-                       StreamSource source = new StreamSource(in);
+                       if (body != null) {
+                               writer = new OutputStreamWriter(connection.getOutputStream(),
+                                               encoding);
+                               StreamResult result = new StreamResult(writer);
+                               marshaller.marshal(body, result);
+                               writer.flush();
+                               IOUtils.closeQuietly(writer);
+                       }
+
+                       // Read answer
+                       reader = new InputStreamReader(connection.getInputStream(),
+                                       encoding);
+                       Source source = new StreamSource(reader);
                        Object obj = unmarshaller.unmarshal(source);
                        return obj;
                } finally {
-                       IOUtils.closeQuietly(in);
+                       IOUtils.closeQuietly(reader);
+                       IOUtils.closeQuietly(writer);
+                       if (connection != null) {
+                               connection.disconnect();
+                       }
+               }
+       }
+
+       protected URL createUrl(String service, Map<String, String> parameters) {
+               // URL encoded with UTF-8, as recommended by W3C
+               final String urlEncoding = "UTF-8";
+
+               StringBuffer buf = new StringBuffer(baseUrl + service);
+               try {
+                       if (parameters != null && parameters.size() != 0) {
+                               buf.append('?');
+                               Iterator<String> it = parameters.keySet().iterator();
+                               String key = null;
+                               while (it.hasNext()) {
+                                       if (key != null)
+                                               buf.append('&');
+                                       key = it.next();
+                                       String keyEncoded = URLEncoder.encode(key, urlEncoding);
+                                       String valueEncoded = URLEncoder.encode(
+                                                       parameters.get(key), urlEncoding);
+                                       buf.append(keyEncoded).append('=').append(valueEncoded);
+                               }
+                       }
+
+                       return new URL(buf.toString());
+               } catch (Exception e) {
+                       throw new SlcException("Cannot create URL: " + buf, e);
                }
        }
 
@@ -123,4 +192,19 @@ public abstract class AbstractHttpServicesClient implements HttpServicesClient {
        public void setRetryPeriod(Long retryPeriod) {
                this.retryPeriod = retryPeriod;
        }
+
+       public void setMarshaller(Marshaller marshaller) {
+               this.marshaller = marshaller;
+       }
+
+       /** Default is UTF-8. */
+       public void setEncoding(String encoding) {
+               this.encoding = encoding;
+       }
+
+       /** Default is 30s*/
+       public void setDefaultTimeout(Long defaultTimeout) {
+               this.defaultTimeout = defaultTimeout;
+       }
+
 }
index 75e4e8ea0d1e7b2679e280b0d8a818772bcd91dd..e640c5c697d11f08059ceb07c8233ece408e3360 100644 (file)
@@ -1,20 +1,55 @@
 package org.argeo.slc.server.client.impl;
 
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.slc.Condition;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.execution.ExecutionFlowDescriptor;
+import org.argeo.slc.msg.ExecutionAnswer;
+import org.argeo.slc.msg.MsgConstants;
 import org.argeo.slc.msg.ObjectList;
+import org.argeo.slc.process.RealizedFlow;
+import org.argeo.slc.process.SlcExecution;
 import org.argeo.slc.runtime.SlcAgentDescriptor;
 import org.argeo.slc.server.client.SlcServerHttpClient;
 
 public class SlcServerHttpClientImpl extends AbstractHttpServicesClient
                implements SlcServerHttpClient {
        public final static String LIST_AGENTS = "listAgents.service";
+       public final static String IS_SERVER_READY = "isServerReady.service";
+       public final static String NEW_SLC_EXECUTION = "newSlcExecution.service";
 
        private final static Log log = LogFactory
                        .getLog(SlcServerHttpClientImpl.class);
 
        private Long retryTimeout = 60 * 1000l;
+       private Long serverReadyTimeout = 120 * 1000l;
+
+       public ExecutionAnswer startFlow(String agentId, String moduleName,
+                       String version, String flowName) {
+               SlcExecution slcExecution = new SlcExecution();
+               slcExecution.setUuid(UUID.randomUUID().toString());
+
+               RealizedFlow realizedFlow = new RealizedFlow();
+               realizedFlow.setModuleName(moduleName);
+               realizedFlow.setModuleVersion(version);
+
+               ExecutionFlowDescriptor flowDescriptor = new ExecutionFlowDescriptor();
+               flowDescriptor.setName(flowName);
+
+               realizedFlow.setFlowDescriptor(flowDescriptor);
+               slcExecution.getRealizedFlows().add(realizedFlow);
+
+               Map<String, String> parameters = new HashMap<String, String>();
+               parameters.put(MsgConstants.PROPERTY_SLC_AGENT_ID, agentId);
+               ExecutionAnswer answer = callService(NEW_SLC_EXECUTION, parameters,
+                               slcExecution);
+               return answer;
+       }
 
        public SlcAgentDescriptor waitForOneAgent() {
                ObjectList objectList = callServiceSafe(LIST_AGENTS, null,
@@ -29,9 +64,27 @@ public class SlcServerHttpClientImpl extends AbstractHttpServicesClient
                return (SlcAgentDescriptor) objectList.getObjects().get(0);
        }
 
-       /** Timeout in ms after which a safe call will throw an exception. */
+       public void waitForServerToBeReady() {
+               ExecutionAnswer answer = callServiceSafe(IS_SERVER_READY, null, null,
+                               serverReadyTimeout);
+               if (!answer.isOk())
+                       throw new SlcException("Server is not ready: " + answer);
+       }
+
+       /**
+        * Timeout in ms after which a safe call will throw an exception. Default is
+        * 60s.
+        */
        public void setRetryTimeout(Long retryTimeout) {
                this.retryTimeout = retryTimeout;
        }
 
+       /**
+        * Timeout in ms after which the client will stop waiting for the server to
+        * be ready and throw an exception. Default is 120s.
+        */
+       public void setServerReadyTimeout(Long serverReadyTimeout) {
+               this.serverReadyTimeout = serverReadyTimeout;
+       }
+
 }
index f0142ba50f38f53dc0fc5edfd6bb7cf6e52b27b6..5abb3f6e948b4b9d77196235fab97dd2b776be48 100644 (file)
@@ -1,6 +1,5 @@
 package org.argeo.slc.server.unit;
 
-import org.argeo.slc.SlcException;
 import org.argeo.slc.msg.ExecutionAnswer;
 import org.argeo.slc.server.client.SlcServerHttpClient;
 import org.argeo.slc.unit.AbstractSpringTestCase;
@@ -8,19 +7,10 @@ import org.argeo.slc.unit.AbstractSpringTestCase;
 public abstract class AbstractHttpClientTestCase extends AbstractSpringTestCase {
        private SlcServerHttpClient httpClient = null;
 
-       private String isServerReadyService = "isServerReady.service";
-
        protected void setUp() throws Exception {
                super.setUp();
                httpClient = createHttpClient();
-               waitForServerToBeReady();
-       }
-
-       protected void waitForServerToBeReady() {
-               ExecutionAnswer answer = httpClient.callServiceSafe(
-                               isServerReadyService, null, null, getServerReadyTimeout());
-               if (!answer.isOk())
-                       throw new SlcException("Server is not ready: " + answer);
+               httpClient.waitForServerToBeReady();
        }
 
        protected SlcServerHttpClient createHttpClient() {
@@ -32,8 +22,9 @@ public abstract class AbstractHttpClientTestCase extends AbstractSpringTestCase
                return httpClient;
        }
 
-       /** Default is 120s */
-       protected Long getServerReadyTimeout() {
-               return 120 * 1000l;
+       protected void assertAnswerOk(ExecutionAnswer answer) {
+               if (!answer.isOk()) {
+                       fail("Server execution answer is not ok: " + answer.getMessage());
+               }
        }
 }
index 02398879929e1ad3a2625bd2b36d6593a88c1e03..b3c6f71fc52944962d4ac640631107a4d396f4ea 100644 (file)
@@ -4,7 +4,6 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.slc.SlcException;
 import org.argeo.slc.dao.process.SlcExecutionDao;
-import org.argeo.slc.msg.process.SlcExecutionRequest;
 import org.argeo.slc.msg.process.SlcExecutionStatusRequest;
 import org.argeo.slc.process.SlcExecution;
 import org.argeo.slc.services.process.SlcExecutionService;
index 2e19764e6bb1f38f9c5410c697f19f95fd89e8c2..2e6a45cfe535122ffa6eed3cde394b8b0f4b5585 100644 (file)
@@ -14,6 +14,7 @@ import org.argeo.slc.runtime.SlcAgentFactory;
 import org.argeo.slc.services.process.SlcExecutionService;\r
 import org.argeo.slc.web.mvc.AbstractServiceController;\r
 import org.springframework.oxm.Unmarshaller;\r
+import org.springframework.util.Assert;\r
 import org.springframework.web.servlet.ModelAndView;\r
 import org.springframework.xml.transform.StringSource;\r
 \r
@@ -38,6 +39,7 @@ public class NewSlcExecutionController extends AbstractServiceController {
 \r
                String agentId = request\r
                                .getParameter(MsgConstants.PROPERTY_SLC_AGENT_ID);\r
+               Assert.notNull(agentId, "agent id");\r
 \r
                String answer = request.getParameter("body");\r
                if (answer == null) {\r
index 8f63be9b1dec2bcc059baf1ef302baf0b082c258..c9af00057c720d9cc7d81fd1acc76b1e62e0f346 100644 (file)
@@ -13,6 +13,7 @@
        <bean id="slcDefault.serverHttpClient" class="org.argeo.slc.server.client.impl.SlcServerHttpClientImpl"
                lazy-init="true">
                <property name="unmarshaller" ref="slcDefault.castor.marshaller" />
+               <property name="marshaller" ref="slcDefault.castor.marshaller" />
                <property name="baseUrl" value="http://localhost:7070/org.argeo.slc.webapp/" />
        </bean>
 </beans>
\ No newline at end of file
index de3e0c9772858cb35e64aa9b52a885ad2b5da30b..bdcd63a64d1695850c330c2097156225e8d78e70 100644 (file)
@@ -3,8 +3,7 @@
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
        default-lazy-init="true">
 
-       <bean id="slcDefault.castor.marshaller"
-               class="org.springframework.oxm.castor.CastorMarshaller">
+       <bean id="slcDefault.castor.marshaller" class="org.springframework.oxm.castor.CastorMarshaller">
                <property name="mappingLocations">
                        <list>
                                <value>
                        </list>
                </property>
                <property name="whitespacePreserve" value="true" />
+               <property name="encoding" value="UTF-8" />
        </bean>
 
-       <bean id="slcDefault.castor.xsltReportGenerator"
-               class="org.argeo.slc.xml.test.tree.XsltReportGenerator"
+       <bean id="slcDefault.castor.xsltReportGenerator" class="org.argeo.slc.xml.test.tree.XsltReportGenerator"
                init-method="init">
                <property name="xsltStyleSheet"
                        value="classpath:/org/argeo/slc/core/test/tree/basicReport.xslt" />
@@ -43,8 +42,7 @@
                <property name="outputDir" value="${slc.workDir}/results/html" />
        </bean>
 
-       <bean name="slcDefault.castor.fileSlcExecutionNotifier"
-               class="org.argeo.slc.xml.process.FileSlcExecutionNotifier">
+       <bean name="slcDefault.castor.fileSlcExecutionNotifier" class="org.argeo.slc.xml.process.FileSlcExecutionNotifier">
                <property name="basePath" value="${slc.workDir}/process" />
                <property name="marshaller" ref="slcDefault.castor.marshaller" />
        </bean>
index 5cfde101eff9de9f78a46c5e55cf93c77439b1bd..303443d02c88746c6eeac591d4d2bb8d5d4a29ad 100644 (file)
@@ -33,6 +33,7 @@ public class SlcExecutionDaoHibernate extends HibernateDaoSupport implements
                                uuid);\r
        }\r
 \r
+       @SuppressWarnings("unchecked")\r
        public List<SlcExecution> listSlcExecutions() {\r
                return (List<SlcExecution>) getHibernateTemplate().loadAll(\r
                                SlcExecution.class);\r