Repository: incubator-unomi
Updated Branches:
  refs/heads/master a171e3d8f -> 38ddefc48


UNOMI-199 fix integration test, increase reliability, add integration test to 
test multiple visitor login on same browser


Project: http://git-wip-us.apache.org/repos/asf/incubator-unomi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-unomi/commit/38ddefc4
Tree: http://git-wip-us.apache.org/repos/asf/incubator-unomi/tree/38ddefc4
Diff: http://git-wip-us.apache.org/repos/asf/incubator-unomi/diff/38ddefc4

Branch: refs/heads/master
Commit: 38ddefc48522977ddbbf93ccc08c9cea12362cad
Parents: a171e3d
Author: dgaillard <[email protected]>
Authored: Fri Sep 21 16:49:16 2018 +0200
Committer: dgaillard <[email protected]>
Committed: Fri Sep 21 16:49:16 2018 +0200

----------------------------------------------------------------------
 itests/pom.xml                                  |  11 +-
 .../java/org/apache/unomi/itests/AllITs.java    |   2 +-
 .../java/org/apache/unomi/itests/BaseIT.java    |  19 +-
 .../java/org/apache/unomi/itests/BasicIT.java   | 314 +++++++++++++++++--
 .../apache/unomi/itests/ModifyConsentIT.java    |   4 +-
 .../unomi/itests/ProfileImportActorsIT.java     |   6 +-
 .../unomi/itests/ProfileImportBasicIT.java      |  75 ++---
 .../unomi/itests/ProfileImportRankingIT.java    |   6 +-
 .../unomi/itests/ProfileImportSurfersIT.java    |   8 +-
 .../java/org/apache/unomi/itests/TestUtils.java |   7 +-
 itests/src/test/resources/1-basic-test.csv      |   6 +-
 itests/src/test/resources/testLogin.json        |  34 ++
 .../test/resources/testLoginEventCondition.json |  23 ++
 .../apache/unomi/lifecycle/BundleWatcher.java   |   2 +-
 .../resources/OSGI-INF/blueprint/blueprint.xml  |   6 +
 15 files changed, 435 insertions(+), 88 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/38ddefc4/itests/pom.xml
----------------------------------------------------------------------
diff --git a/itests/pom.xml b/itests/pom.xml
index eb42ba2..2e9b6fc 100644
--- a/itests/pom.xml
+++ b/itests/pom.xml
@@ -56,7 +56,13 @@
             <version>${project.version}</version>
             <scope>test</scope>
         </dependency>
-        
+        <dependency>
+            <groupId>org.apache.unomi</groupId>
+            <artifactId>unomi-lifecycle-watcher</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
         <dependency>
             <groupId>org.apache.karaf.features</groupId>
             <artifactId>standard</artifactId>
@@ -171,12 +177,13 @@
                 <groupId>com.github.alexcojocaru</groupId>
                 <artifactId>elasticsearch-maven-plugin</artifactId>
                 <!-- REPLACE THE FOLLOWING WITH THE PLUGIN VERSION YOU NEED -->
-                <version>5.7</version>
+                <version>5.6</version>
                 <configuration>
                     <clusterName>contextElasticSearchITests</clusterName>
                     <transportPort>9500</transportPort>
                     <httpPort>9400</httpPort>
                     <version>${elasticsearch.version}</version>
+                    <autoCreateIndex>true</autoCreateIndex>
                 </configuration>
                 <executions>
                     <!--

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/38ddefc4/itests/src/test/java/org/apache/unomi/itests/AllITs.java
----------------------------------------------------------------------
diff --git a/itests/src/test/java/org/apache/unomi/itests/AllITs.java 
b/itests/src/test/java/org/apache/unomi/itests/AllITs.java
index 923ef71..aa39424 100644
--- a/itests/src/test/java/org/apache/unomi/itests/AllITs.java
+++ b/itests/src/test/java/org/apache/unomi/itests/AllITs.java
@@ -28,7 +28,7 @@ import org.junit.runners.Suite.SuiteClasses;
  */
 @RunWith(Suite.class)
 @SuiteClasses({
-        //BasicIT.class,
+        BasicIT.class,
         ConditionEvaluatorIT.class,
         ConditionESQueryBuilderIT.class,
         SegmentIT.class,

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/38ddefc4/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
----------------------------------------------------------------------
diff --git a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java 
b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
index 5849e4c..3d3e610 100644
--- a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
@@ -18,6 +18,7 @@
 package org.apache.unomi.itests;
 
 import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.CoreOptions;
 import org.ops4j.pax.exam.Option;
 import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel;
 import org.ops4j.pax.exam.options.MavenArtifactUrlReference;
@@ -42,8 +43,10 @@ public abstract class BaseIT {
 
     protected static final String KARAF_DIR = "target/exam";
 
+    protected static final String UNOMI_KEY = 
"670c26d1cc413346c3b2fd9ce65dab41";
+
     @Configuration
-    public Option[] config() {
+    public Option[] config() throws InterruptedException {
         MavenArtifactUrlReference karafUrl = maven()
                 .groupId("org.apache.karaf")
                 .artifactId("apache-karaf")
@@ -86,15 +89,17 @@ public abstract class BaseIT {
                 .classifier("features")
                 .type("xml")
                 .versionAsInProject();
-        
+
         return new Option[]{
-                debugConfiguration("5005", false),
+                debugConfiguration("5006", false),
                 karafDistributionConfiguration()
                         .frameworkUrl(karafUrl)
                         .unpackDirectory(new File(KARAF_DIR))
                         .useDeployFolder(true),
                 replaceConfigurationFile("etc/org.apache.unomi.router.cfg", 
new File(
                         "src/test/resources/org.apache.unomi.router.cfg")),
+                replaceConfigurationFile("data/tmp/1-basic-test.csv", new File(
+                        "src/test/resources/1-basic-test.csv")),
                 
replaceConfigurationFile("data/tmp/recurrent_import/2-surfers-test.csv", new 
File(
                         "src/test/resources/2-surfers-test.csv")),
                 
replaceConfigurationFile("data/tmp/recurrent_import/3-surfers-overwrite-test.csv",
 new File(
@@ -105,6 +110,10 @@ public abstract class BaseIT {
                         "src/test/resources/5-ranking-test.csv")),
                 
replaceConfigurationFile("data/tmp/recurrent_import/6-actors-test.csv", new 
File(
                         "src/test/resources/6-actors-test.csv")),
+                replaceConfigurationFile("data/tmp/testLogin.json", new File(
+                        "src/test/resources/testLogin.json")),
+                
replaceConfigurationFile("data/tmp/testLoginEventCondition.json", new File(
+                        "src/test/resources/testLoginEventCondition.json")),
                 keepRuntimeFolder(),
                 configureConsole().ignoreLocalConsole(),
                 logLevel(LogLevel.INFO),
@@ -121,7 +130,9 @@ public abstract class BaseIT {
                 features(karafCxfRepo, "cxf"),
                 features(karafCellarRepo, "cellar"),
                 features(contextServerRepo, "unomi-kar"),
-                features(routerRepo, "unomi-router-karaf-feature")
+                features(routerRepo, "unomi-router-karaf-feature"),
+                CoreOptions.bundleStartLevel(100),
+                CoreOptions.frameworkStartLevel(100)
         };
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/38ddefc4/itests/src/test/java/org/apache/unomi/itests/BasicIT.java
----------------------------------------------------------------------
diff --git a/itests/src/test/java/org/apache/unomi/itests/BasicIT.java 
b/itests/src/test/java/org/apache/unomi/itests/BasicIT.java
index cc91fed..14c524d 100644
--- a/itests/src/test/java/org/apache/unomi/itests/BasicIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/BasicIT.java
@@ -27,28 +27,86 @@ import org.apache.http.entity.ContentType;
 import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.HttpClientBuilder;
 import org.apache.http.util.EntityUtils;
-import org.apache.unomi.api.ContextRequest;
-import org.apache.unomi.api.ContextResponse;
+import org.apache.unomi.api.*;
+import org.apache.unomi.api.conditions.ConditionType;
+import org.apache.unomi.api.rules.Rule;
+import org.apache.unomi.api.services.DefinitionsService;
+import org.apache.unomi.api.services.ProfileService;
+import org.apache.unomi.api.services.RulesService;
+import org.apache.unomi.lifecycle.BundleWatcher;
+import org.apache.unomi.persistence.spi.CustomObjectMapper;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.junit.PaxExam;
 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
 import org.ops4j.pax.exam.spi.reactors.PerSuite;
+import org.ops4j.pax.exam.util.Filter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import javax.inject.Inject;
+import java.io.File;
 import java.io.IOException;
+import java.util.*;
 
 @RunWith(PaxExam.class)
 @ExamReactorStrategy(PerSuite.class)
 public class BasicIT extends BaseIT {
+    private final static Logger LOGGER = 
LoggerFactory.getLogger(BasicIT.class);
+
     private static final String JSON_MYME_TYPE = "application/json";
 
     private ObjectMapper objectMapper = new ObjectMapper();
 
+    private static final String SESSION_ID_0 = 
"aa3b04bd-8f4d-4a07-8e96-d33ffa04d3d0";
+    private static final String SESSION_ID_1 = 
"aa3b04bd-8f4d-4a07-8e96-d33ffa04d3d1";
+    private static final String SESSION_ID_2 = 
"aa3b04bd-8f4d-4a07-8e96-d33ffa04d3d2";
+    private static final String SESSION_ID_3 = 
"aa3b04bd-8f4d-4a07-8e96-d33ffa04d3d3";
+    private static final String SESSION_ID_4 = 
"aa3b04bd-8f4d-4a07-8e96-d33ffa04d3d4";
+
+    private static final String EVENT_TYPE_LOGIN = "login";
+    private static final String EVENT_TYPE_VIEW = "view";
+    private static final String TEST_SCOPE = "testScope";
+
+    private static final String ITEM_TYPE_SITE = "site";
+    private static final String ITEM_ID_SITE = "/test/site";
+    private static final String ITEM_TYPE_VISITOR = "VISITOR";
+    private static final String ITEM_ID_PAGE_1 = "/test/site/page1";
+    private static final String ITEM_TYPE_PAGE = "page";
+
+    private static final String FIRST_NAME = "firstName";
+    private static final String LAST_NAME = "lastName";
+    private static final String EMAIL = "email";
+
+    private static final String FIRST_NAME_VISITOR_1 = "firstNameVisitor1";
+    private static final String FIRST_NAME_VISITOR_2 = "firstNameVisitor2";
+    private static final String LAST_NAME_VISITOR_1 = "lastNameVisitor1";
+    private static final String LAST_NAME_VISITOR_2 = "lastNameVisitor2";
+    private static final String EMAIL_VISITOR_1 = "[email protected]";
+    private static final String EMAIL_VISITOR_2 = "[email protected]";
+
+    @Inject @Filter(timeout = 60000)
+    protected RulesService rulesService;
+    @Inject @Filter(timeout = 60000)
+    protected ProfileService profileService;
+    @Inject @Filter(timeout = 60000)
+    protected DefinitionsService definitionsService;
+    @Inject @Filter(timeout = 60000)
+    protected BundleWatcher bundleWatcher;
+
+    @Before
+    public void setUp() throws InterruptedException {
+        while (!bundleWatcher.isStartupComplete()) {
+            Thread.sleep(1000);
+        }
+    }
+
     @Test
     public void testContextJS() throws IOException {
-        HttpUriRequest request = new HttpGet(URL + 
"/context.js?sessionId=aa3b04bd-8f4d-4a07-8e96-d33ffa04d3d9");
-        CloseableHttpResponse response = 
HttpClientBuilder.create().build().execute(request);
+        LOGGER.info("Start test testContextJS");
+        HttpUriRequest request = new HttpGet(URL + "/context.js?sessionId=" + 
SESSION_ID_0);
         // The underlying HTTP connection is still held by the response object
         // to allow the response content to be streamed directly from the 
network socket.
         // In order to ensure correct deallocation of system resources
@@ -56,32 +114,197 @@ public class BasicIT extends BaseIT {
         // Please note that if response content is not fully consumed the 
underlying
         // connection cannot be safely re-used and will be shut down and 
discarded
         // by the connection manager.
-        String responseContent = null;
-        try {
+        String responseContent;
+        try (CloseableHttpResponse response = 
HttpClientBuilder.create().build().execute(request)) {
             System.out.println(response.getStatusLine());
             HttpEntity entity = response.getEntity();
             // do something useful with the response body
             // and ensure it is fully consumed
             responseContent = EntityUtils.toString(entity);
-        } finally {
-            response.close();
         }
-        Assert.assertTrue("Response should contain context object", 
responseContent.contains("window.digitalData = window.digitalData || {};"));
-        // @todo we should check the validity of the context object, but this 
is rather complex since it would
-        // potentially require parsing the Javascript !
+        Assert.assertTrue("Response should contain context object", 
responseContent.contains("window.digitalData = window.digitalData || {};\n"));
+        // @todo we should check the validity of the context object, but this 
is rather complex since it would potentially require parsing the Javascript !
+        LOGGER.info("End test testContextJS");
+    }
+
+    @Test
+    public void testContextJSONWithUrlParameter() throws IOException, 
InterruptedException {
+        LOGGER.info("Start test testContextJSONWithUrlParameter");
+        ContextRequest contextRequest = new ContextRequest();
+        HttpPost request = new HttpPost(URL + "/context.json?sessionId=" + 
SESSION_ID_1);
+        request.setEntity(new 
StringEntity(objectMapper.writeValueAsString(contextRequest), 
ContentType.create("application/json")));
+
+        executeContextJSONRequest(request, SESSION_ID_1);
+        LOGGER.info("End test testContextJSONWithUrlParameter");
     }
 
     @Test
-    public void testContextJSON() throws IOException {
-        String sessionId = "aa3b04bd-8f4d-4a07-8e96-d33ffa04d3d9";
+    public void testContextJSON() throws IOException, InterruptedException {
+        LOGGER.info("Start test testContextJSON");
         ContextRequest contextRequest = new ContextRequest();
-//        contextRequest.setSource(new EventSource());
-//        
contextRequest.getSource().setId("af6f393a-a537-4586-991b-8521b9c7b05b");
-        HttpPost request = new HttpPost(URL + "/context.json?sessionId=" + 
sessionId);
+        contextRequest.setSessionId(SESSION_ID_2);
+        HttpPost request = new HttpPost(URL + "/context.json");
         request.setEntity(new 
StringEntity(objectMapper.writeValueAsString(contextRequest), 
ContentType.create("application/json")));
-        CloseableHttpResponse response = 
HttpClientBuilder.create().build().execute(request);
 
-        try {
+        executeContextJSONRequest(request, SESSION_ID_2);
+        LOGGER.info("End test testContextJSON");
+    }
+
+    @Test
+    public void testMultipleLoginOnSameBrowser() throws IOException, 
InterruptedException {
+        LOGGER.info("Start test testMultipleLoginOnSameBrowser");
+        // Add login event condition
+        ConditionType conditionType = 
CustomObjectMapper.getObjectMapper().readValue(
+                new 
File("data/tmp/testLoginEventCondition.json").toURI().toURL(), 
ConditionType.class);
+        definitionsService.setConditionType(conditionType);
+        Thread.sleep(2000);
+        // Add login rule
+        Rule rule = CustomObjectMapper.getObjectMapper().readValue(new 
File("data/tmp/testLogin.json").toURI().toURL(),
+                Rule.class);
+        rulesService.setRule(rule);
+        Thread.sleep(2000);
+
+        CustomItem sourceSite = new CustomItem(ITEM_ID_SITE, ITEM_TYPE_SITE);
+        sourceSite.setScope(TEST_SCOPE);
+
+        // First page view with the first visitor aka VISITOR_1 and 
SESSION_ID_3
+        ContextRequest contextRequestPageViewSession1 = 
getContextRequestWithPageViewEvent(sourceSite, SESSION_ID_3);
+        HttpPost requestPageView1 = new HttpPost(URL + "/context.json");
+        requestPageView1.setEntity(new 
StringEntity(objectMapper.writeValueAsString(contextRequestPageViewSession1),
+                ContentType.create("application/json")));
+        RequestResponse requestResponsePageView1 = 
executeContextJSONRequest(requestPageView1, SESSION_ID_3);
+        String profileIdVisitor1 = 
requestResponsePageView1.getContextResponse().getProfileId();
+        Thread.sleep(1000);
+
+        // Initialize VISITOR_1 properties
+        Map<String, Object> loginEventPropertiesVisitor1 = new HashMap<>();
+        loginEventPropertiesVisitor1.put(FIRST_NAME, FIRST_NAME_VISITOR_1);
+        loginEventPropertiesVisitor1.put(LAST_NAME, LAST_NAME_VISITOR_1);
+        loginEventPropertiesVisitor1.put(EMAIL, EMAIL_VISITOR_1);
+
+        // Create login event with VISITOR_1
+        ContextRequest contextRequestLoginVisitor1 = 
getContextRequestWithLoginEvent(sourceSite, loginEventPropertiesVisitor1,
+                EMAIL_VISITOR_1, SESSION_ID_3);
+        HttpPost requestLoginVisitor1 = new HttpPost(URL + "/context.json");
+        requestLoginVisitor1.addHeader("Cookie", 
requestResponsePageView1.getCookieHeaderValue());
+        requestLoginVisitor1.addHeader("X-Unomi-Peer", UNOMI_KEY);
+        requestLoginVisitor1.setEntity(new 
StringEntity(objectMapper.writeValueAsString(contextRequestLoginVisitor1),
+                ContentType.create("application/json")));
+        RequestResponse requestResponseLoginVisitor1 = 
executeContextJSONRequest(requestLoginVisitor1, SESSION_ID_3);
+        Assert.assertEquals("Context profile id should be the same", 
profileIdVisitor1,
+                
requestResponseLoginVisitor1.getContextResponse().getProfileId());
+        
checkVisitor1ResponseProperties(requestResponseLoginVisitor1.getContextResponse().getProfileProperties());
+        Thread.sleep(1000);
+
+        // Lets add a page view with VISITOR_1 to simulate reloading the page 
after login and be able to check the profile properties
+        HttpPost requestPageView2 = new HttpPost(URL + "/context.json");
+        requestPageView2.addHeader("Cookie", 
requestResponsePageView1.getCookieHeaderValue());
+        requestPageView2.setEntity(new 
StringEntity(objectMapper.writeValueAsString(contextRequestPageViewSession1),
+                ContentType.create("application/json")));
+        RequestResponse requestResponsePageView2 = 
executeContextJSONRequest(requestPageView2, SESSION_ID_3);
+        Assert.assertEquals("Context profile id should be the same", 
profileIdVisitor1,
+                requestResponsePageView2.getContextResponse().getProfileId());
+        
checkVisitor1ResponseProperties(requestResponsePageView2.getContextResponse().getProfileProperties());
+        Thread.sleep(1000);
+
+        // Lets simulate a logout by requesting the context with a new page 
view event and a new session id
+        // but we will send the cookie of the profile id from VISITOR_1
+        ContextRequest contextRequestPageViewSession2 = 
getContextRequestWithPageViewEvent(sourceSite, SESSION_ID_4);
+        HttpPost requestPageView3 = new HttpPost(URL + "/context.json");
+        requestPageView3.addHeader("Cookie", 
requestResponsePageView1.getCookieHeaderValue());
+        requestPageView3.setEntity(new 
StringEntity(objectMapper.writeValueAsString(contextRequestPageViewSession2),
+                ContentType.create("application/json")));
+        RequestResponse requestResponsePageView3 = 
executeContextJSONRequest(requestPageView3, SESSION_ID_4);
+        Assert.assertEquals("Context profile id should be the same", 
profileIdVisitor1,
+                requestResponsePageView3.getContextResponse().getProfileId());
+        
checkVisitor1ResponseProperties(requestResponsePageView3.getContextResponse().getProfileProperties());
+        Thread.sleep(1000);
+
+        // Initialize VISITOR_2 properties
+        Map<String, Object> loginEventPropertiesVisitor2 = new HashMap<>();
+        loginEventPropertiesVisitor2.put(FIRST_NAME, FIRST_NAME_VISITOR_2);
+        loginEventPropertiesVisitor2.put(LAST_NAME, LAST_NAME_VISITOR_2);
+        loginEventPropertiesVisitor2.put(EMAIL, EMAIL_VISITOR_2);
+
+        // Create login event with VISITOR_2
+        ContextRequest contextRequestLoginVisitor2 = 
getContextRequestWithLoginEvent(sourceSite, loginEventPropertiesVisitor2,
+                EMAIL_VISITOR_2, SESSION_ID_4);
+        HttpPost requestLoginVisitor2 = new HttpPost(URL + "/context.json");
+        requestLoginVisitor2.addHeader("Cookie", 
requestResponsePageView1.getCookieHeaderValue());
+        requestLoginVisitor2.addHeader("X-Unomi-Peer", UNOMI_KEY);
+        requestLoginVisitor2.setEntity(new 
StringEntity(objectMapper.writeValueAsString(contextRequestLoginVisitor2),
+                ContentType.create("application/json")));
+        RequestResponse requestResponseLoginVisitor2 = 
executeContextJSONRequest(requestLoginVisitor2, SESSION_ID_4);
+        // We should have a new profile id so the session should have been 
moved from VISITOR_1 to VISITOR_2
+        String profileIdVisitor2 = 
requestResponseLoginVisitor2.getContextResponse().getProfileId();
+        Assert.assertNotEquals("Context profile id should not be the same", 
profileIdVisitor1,
+                profileIdVisitor2);
+        
checkVisitor2ResponseProperties(requestResponseLoginVisitor2.getContextResponse().getProfileProperties());
+        Thread.sleep(1000);
+
+        // Lets add a page view with VISITOR_2 to simulate reloading the page 
after login
+        HttpPost requestPageView4 = new HttpPost(URL + "/context.json");
+        requestPageView4.addHeader("Cookie", 
requestResponseLoginVisitor2.getCookieHeaderValue());
+        requestPageView4.setEntity(new 
StringEntity(objectMapper.writeValueAsString(contextRequestPageViewSession2),
+                ContentType.create("application/json")));
+        RequestResponse requestResponsePageView4 = 
executeContextJSONRequest(requestPageView4, SESSION_ID_4);
+        Assert.assertEquals("Context profile id should be the same", 
profileIdVisitor2,
+                requestResponsePageView4.getContextResponse().getProfileId());
+        
checkVisitor2ResponseProperties(requestResponsePageView4.getContextResponse().getProfileProperties());
+        Thread.sleep(1000);
+
+        // Check both visitor profile at the end by loading them directly
+        Profile profileVisitor1 = profileService.load(profileIdVisitor1);
+        checkVisitor1ResponseProperties(profileVisitor1.getProperties());
+        Profile profileVisitor2 = profileService.load(profileIdVisitor2);
+        checkVisitor2ResponseProperties(profileVisitor2.getProperties());
+        LOGGER.info("End test testMultipleLoginOnSameBrowser");
+    }
+
+    private ContextRequest getContextRequestWithLoginEvent(CustomItem 
sourceSite, Map<String, Object> loginEventProperties,
+            String visitorId, String sessionId) {
+
+        CustomItem loginEventTarget = new CustomItem(visitorId, 
ITEM_TYPE_VISITOR);
+        loginEventTarget.setProperties(loginEventProperties);
+
+        Event loginEvent = new Event(EVENT_TYPE_LOGIN, null, new Profile(""), 
TEST_SCOPE,
+                null, loginEventTarget, new Date());
+
+        ContextRequest contextRequest = new ContextRequest();
+        contextRequest.setSource(sourceSite);
+        contextRequest.setRequireSegments(false);
+        contextRequest.setEvents(Collections.singletonList(loginEvent));
+        contextRequest.setRequiredProfileProperties(Arrays.asList(FIRST_NAME, 
LAST_NAME, EMAIL));
+        contextRequest.setSessionId(sessionId);
+        return contextRequest;
+    }
+
+    private ContextRequest getContextRequestWithPageViewEvent(CustomItem 
sourceSite, String sessionId) {
+        CustomItem customPageItem = new CustomItem(ITEM_ID_PAGE_1, 
ITEM_TYPE_PAGE);
+        customPageItem.setScope(TEST_SCOPE);
+        Map<String, Object> pageInfo = new HashMap<>();
+        pageInfo.put("referringURL", "http://localhost:8080";);
+
+        Map<String, Object> properties = new HashMap<>();
+        properties.put("pageInfo", pageInfo);
+
+        customPageItem.setProperties(properties);
+
+        // Create page view event to mock a connection to a site
+        Event pageViewEvent = new Event(EVENT_TYPE_VIEW, null, new 
Profile(""), TEST_SCOPE, sourceSite, customPageItem, new Date());
+
+        // Initialize context like if you display the first page on the website
+        ContextRequest contextRequest = new ContextRequest();
+        contextRequest.setSessionId(sessionId);
+        contextRequest.setSource(customPageItem);
+        contextRequest.setRequireSegments(false);
+        contextRequest.setEvents(Collections.singletonList(pageViewEvent));
+        contextRequest.setRequiredProfileProperties(Arrays.asList(FIRST_NAME, 
LAST_NAME, EMAIL));
+        return contextRequest;
+    }
+
+    private RequestResponse executeContextJSONRequest(HttpPost request, String 
sessionId) throws IOException, InterruptedException {
+        try (CloseableHttpResponse response = 
HttpClientBuilder.create().build().execute(request)) {
             // validate mimeType
             String mimeType = 
ContentType.getOrDefault(response.getEntity()).getMimeType();
             Assert.assertEquals("Response content type should be " + 
JSON_MYME_TYPE, JSON_MYME_TYPE, mimeType);
@@ -90,10 +313,59 @@ public class BasicIT extends BaseIT {
             ContextResponse context = 
TestUtils.retrieveResourceFromResponse(response, ContextResponse.class);
             Assert.assertNotNull("Context should not be null", context);
             Assert.assertNotNull("Context profileId should not be null", 
context.getProfileId());
-            Assert.assertEquals("Context sessionId should be the same as the 
sessionId used to request the context", sessionId, context.getSessionId());
-        } finally {
-            response.close();
+            Assert.assertEquals("Context sessionId should be the same as the 
sessionId used to request the context", sessionId,
+                    context.getSessionId());
+
+            String cookieHeader = null;
+            if (response.containsHeader("Set-Cookie")) {
+                cookieHeader = 
response.getHeaders("Set-Cookie")[0].toString().substring(12);
+            }
+            return new RequestResponse(context, cookieHeader);
         }
     }
 
+    private void checkVisitor1ResponseProperties(Map<String, Object> 
profileProperties) {
+        checkVisitorResponseProperties(profileProperties, 
FIRST_NAME_VISITOR_1, LAST_NAME_VISITOR_1, EMAIL_VISITOR_1);
+    }
+
+    private void checkVisitor2ResponseProperties(Map<String, Object> 
profileProperties) {
+        checkVisitorResponseProperties(profileProperties, 
FIRST_NAME_VISITOR_2, LAST_NAME_VISITOR_2, EMAIL_VISITOR_2);
+    }
+
+    private void checkVisitorResponseProperties(Map<String, Object> 
profileProperties, String firstNameVisitor,
+            String lastNameVisitor, String emailVisitor) {
+        Assert.assertNotNull("Context profile properties should not be null", 
profileProperties);
+
+        Assert.assertTrue("Context profile properties should contains the 
entry " + FIRST_NAME,
+                profileProperties.containsKey(FIRST_NAME));
+        Assert.assertTrue("Context profile properties should contains the 
entry " + LAST_NAME,
+                profileProperties.containsKey(LAST_NAME));
+        Assert.assertTrue("Context profile properties should contains the 
entry " + EMAIL,
+                profileProperties.containsKey(EMAIL));
+
+        Assert.assertEquals("Context profile properties " + FIRST_NAME + " 
should be equal to " + firstNameVisitor,
+                profileProperties.get(FIRST_NAME), firstNameVisitor);
+        Assert.assertEquals("Context profile properties " + LAST_NAME + " 
should be equal to " + lastNameVisitor,
+                profileProperties.get(LAST_NAME), lastNameVisitor);
+        Assert.assertEquals("Context profile properties " + EMAIL + " should 
be equal to " + emailVisitor,
+                profileProperties.get(EMAIL), emailVisitor);
+    }
+
+    private class RequestResponse {
+        private ContextResponse contextResponse;
+        private String cookieHeaderValue;
+
+        public RequestResponse(ContextResponse contextResponse, String 
cookieHeaderValue) {
+            this.contextResponse = contextResponse;
+            this.cookieHeaderValue = cookieHeaderValue;
+        }
+
+        public ContextResponse getContextResponse() {
+            return contextResponse;
+        }
+
+        public String getCookieHeaderValue() {
+            return cookieHeaderValue;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/38ddefc4/itests/src/test/java/org/apache/unomi/itests/ModifyConsentIT.java
----------------------------------------------------------------------
diff --git a/itests/src/test/java/org/apache/unomi/itests/ModifyConsentIT.java 
b/itests/src/test/java/org/apache/unomi/itests/ModifyConsentIT.java
index a602dcb..6b53d79 100644
--- a/itests/src/test/java/org/apache/unomi/itests/ModifyConsentIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/ModifyConsentIT.java
@@ -66,7 +66,7 @@ public class ModifyConsentIT extends BaseIT {
     public void testConsentGrant() throws InterruptedException {
         Profile profile = profileService.load(PROFILE_TEST_ID);
         Assert.assertNotNull(profile);
-        Assert.assertTrue(profile.getConsents().size() == 0);
+        Assert.assertEquals(0, profile.getConsents().size());
 
         Event modifyConsentEvent = new Event("modifyConsent", null, profile, 
null, null, profile, new Date());
         modifyConsentEvent.setPersistent(false);
@@ -92,7 +92,7 @@ public class ModifyConsentIT extends BaseIT {
 
         profile = profileService.load(PROFILE_TEST_ID);
 
-        Assert.assertTrue(profile.getConsents().size() == 2);
+        Assert.assertEquals(2, profile.getConsents().size());
 
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/38ddefc4/itests/src/test/java/org/apache/unomi/itests/ProfileImportActorsIT.java
----------------------------------------------------------------------
diff --git 
a/itests/src/test/java/org/apache/unomi/itests/ProfileImportActorsIT.java 
b/itests/src/test/java/org/apache/unomi/itests/ProfileImportActorsIT.java
index a25fbd1..308009a 100644
--- a/itests/src/test/java/org/apache/unomi/itests/ProfileImportActorsIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/ProfileImportActorsIT.java
@@ -43,11 +43,9 @@ import java.util.*;
 @ExamReactorStrategy(PerSuite.class)
 public class ProfileImportActorsIT extends BaseIT {
 
-    @Inject
-    @Filter("(configDiscriminator=IMPORT)")
+    @Inject @Filter(value="(configDiscriminator=IMPORT)", timeout = 60000)
     protected ImportExportConfigurationService<ImportConfiguration> 
importConfigurationService;
-
-    @Inject
+    @Inject @Filter(timeout = 60000)
     protected ProfileService profileService;
 
     @Test

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/38ddefc4/itests/src/test/java/org/apache/unomi/itests/ProfileImportBasicIT.java
----------------------------------------------------------------------
diff --git 
a/itests/src/test/java/org/apache/unomi/itests/ProfileImportBasicIT.java 
b/itests/src/test/java/org/apache/unomi/itests/ProfileImportBasicIT.java
index 7aad069..e2b1898 100644
--- a/itests/src/test/java/org/apache/unomi/itests/ProfileImportBasicIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/ProfileImportBasicIT.java
@@ -33,10 +33,10 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import javax.inject.Inject;
-import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FileWriter;
 import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -47,21 +47,19 @@ import java.util.Map;
 @RunWith(PaxExam.class)
 @ExamReactorStrategy(PerSuite.class)
 public class ProfileImportBasicIT extends BaseIT {
-
     private Logger logger = 
LoggerFactory.getLogger(ProfileImportBasicIT.class);
     
-    @Inject
-    @Filter("(configDiscriminator=IMPORT)")
+    @Inject @Filter(value="(configDiscriminator=IMPORT)", timeout = 60000)
     protected ImportExportConfigurationService<ImportConfiguration> 
importConfigurationService;
-    @Inject
+    @Inject @Filter(timeout = 60000)
     protected ProfileService profileService;
 
     @Test
     public void testImportBasic() throws IOException, InterruptedException {
-
         /*** Basic Test ***/
         ImportConfiguration importConfiguration = new ImportConfiguration();
-        importConfiguration.setItemId("1-basic-test");
+        String itemId = "1-basic-test";
+        importConfiguration.setItemId(itemId);
         
importConfiguration.setConfigType(RouterConstants.IMPORT_EXPORT_CONFIG_TYPE_ONESHOT);
         importConfiguration.setMergingProperty("email");
         importConfiguration.setOverwriteExistingProfiles(true);
@@ -70,49 +68,52 @@ public class ProfileImportBasicIT extends BaseIT {
         mapping.put("email", 0);
         mapping.put("firstName", 1);
         mapping.put("lastName", 2);
+        mapping.put("city", 3);
 
         importConfiguration.getProperties().put("mapping", mapping);
         importConfiguration.setActive(true);
 
-        logger.info("Save import config oneshot with ID : {}.", 
importConfiguration.getItemId());
-
+        logger.info("Save import config oneshot with ID : {}.", itemId);
         importConfigurationService.save(importConfiguration, false);
 
-        //Wait for the csv to be processed
+        // Wait for the config to be processed
         Thread.sleep(5000);
 
-        logger.info("Check import config oneshot with ID : {}.", 
importConfiguration.getItemId());
-
+        logger.info("Check import config oneshot with ID : {}.", itemId);
         List<ImportConfiguration> importConfigurations = 
importConfigurationService.getAll();
         Assert.assertEquals(1, importConfigurations.size());
 
-        String content = "[email protected],Basic1,User1\n" +
-                "[email protected],Basic2,User2\n" +
-                "[email protected],Basic3,User3";
-        File basicFile = new 
File("data/tmp/unomi_oneshot_import_configs/1-basic-test.csv");
-        basicFile.getParentFile().mkdirs();
-        BufferedWriter out = new BufferedWriter(new FileWriter(basicFile));
-        out.write(content);
-        out.close();
-
-        logger.info("Write the file {}.", 
"data/tmp/unomi_oneshot_import_configs/1-basic-test.csv");
-
-        //Wait for the csv to be processed
-        Thread.sleep(75000);
-
-        //Check saved profiles
-        PartialList<Profile> profiles = 
profileService.findProfilesByPropertyValue("properties.email", 
"[email protected]", 0, 10, null);
-        Assert.assertEquals(3, profileService.getAllProfilesCount());
-        Assert.assertEquals(1, profiles.getList().size());
-        Assert.assertNotNull(profiles.get(0));
-        Assert.assertEquals("Basic1", 
profiles.get(0).getProperty("firstName"));
-        Assert.assertEquals("User1", profiles.get(0).getProperty("lastName"));
-
-        //Check import config status
-        importConfiguration = importConfigurationService.load("1-basic-test");
+        // Move the file to the import folder so the import can start
+        File basicFile = new File("data/tmp/1-basic-test.csv");
+        Files.copy(basicFile.toPath(), new 
File("data/tmp/unomi_oneshot_import_configs/1-basic-test.csv").toPath(), 
StandardCopyOption.REPLACE_EXISTING);
+
+        // Wait for the csv to be processed
+        boolean isDone = false;
+        while (!isDone) {
+            importConfiguration = importConfigurationService.load(itemId);
+            if (importConfiguration != null && importConfiguration.getStatus() 
!= null) {
+                isDone = 
importConfiguration.getStatus().equals(RouterConstants.CONFIG_STATUS_COMPLETE_SUCCESS);
+            }
+            Thread.sleep(1000);
+        }
+        // Check import config status
         Assert.assertEquals(RouterConstants.CONFIG_STATUS_COMPLETE_SUCCESS, 
importConfiguration.getStatus());
         Assert.assertEquals(1, importConfiguration.getExecutions().size());
 
+        // Check saved profiles
+        PartialList<Profile> profiles = 
profileService.findProfilesByPropertyValue("properties.city", 
"oneShotImportCity", 0, 10, null);
+        Assert.assertEquals(3, profiles.getList().size());
+
+        checkProfiles(1);
+        checkProfiles(2);
+        checkProfiles(3);
     }
 
+    private void checkProfiles(int profileNumber) {
+        String propertyValue = "basic" + profileNumber + "@test.com";
+        PartialList<Profile> profiles = 
profileService.findProfilesByPropertyValue("properties.email", propertyValue, 
0, 10, null);
+        Assert.assertNotNull(profiles.get(0));
+        Assert.assertEquals("Basic" + profileNumber, 
profiles.get(0).getProperty("firstName"));
+        Assert.assertEquals("User" + profileNumber, 
profiles.get(0).getProperty("lastName"));
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/38ddefc4/itests/src/test/java/org/apache/unomi/itests/ProfileImportRankingIT.java
----------------------------------------------------------------------
diff --git 
a/itests/src/test/java/org/apache/unomi/itests/ProfileImportRankingIT.java 
b/itests/src/test/java/org/apache/unomi/itests/ProfileImportRankingIT.java
index a2f0f39..b4663ec 100644
--- a/itests/src/test/java/org/apache/unomi/itests/ProfileImportRankingIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/ProfileImportRankingIT.java
@@ -46,11 +46,9 @@ import java.util.Map;
 @ExamReactorStrategy(PerSuite.class)
 public class ProfileImportRankingIT extends BaseIT {
 
-    @Inject
-    @Filter("(configDiscriminator=IMPORT)")
+    @Inject @Filter(value="(configDiscriminator=IMPORT)", timeout = 60000)
     protected ImportExportConfigurationService<ImportConfiguration> 
importConfigurationService;
-
-    @Inject
+    @Inject @Filter(timeout = 60000)
     protected ProfileService profileService;
 
     @Test

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/38ddefc4/itests/src/test/java/org/apache/unomi/itests/ProfileImportSurfersIT.java
----------------------------------------------------------------------
diff --git 
a/itests/src/test/java/org/apache/unomi/itests/ProfileImportSurfersIT.java 
b/itests/src/test/java/org/apache/unomi/itests/ProfileImportSurfersIT.java
index 082ffaf..a845206 100644
--- a/itests/src/test/java/org/apache/unomi/itests/ProfileImportSurfersIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/ProfileImportSurfersIT.java
@@ -49,14 +49,12 @@ import java.util.Map;
 @RunWith(PaxExam.class)
 @ExamReactorStrategy(PerSuite.class)
 public class ProfileImportSurfersIT extends BaseIT {
+    private Logger logger = 
LoggerFactory.getLogger(ProfileImportSurfersIT.class);
 
-    @Inject
-    @Filter("(configDiscriminator=IMPORT)")
+    @Inject @Filter(value="(configDiscriminator=IMPORT)", timeout = 60000)
     protected ImportExportConfigurationService<ImportConfiguration> 
importConfigurationService;
-
-    @Inject
+    @Inject @Filter(timeout = 60000)
     protected ProfileService profileService;
-    private Logger logger = 
LoggerFactory.getLogger(ProfileImportSurfersIT.class);
 
     @Test
     public void testImportSurfers() throws IOException, InterruptedException {

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/38ddefc4/itests/src/test/java/org/apache/unomi/itests/TestUtils.java
----------------------------------------------------------------------
diff --git a/itests/src/test/java/org/apache/unomi/itests/TestUtils.java 
b/itests/src/test/java/org/apache/unomi/itests/TestUtils.java
index 72f2d98..d98d394 100644
--- a/itests/src/test/java/org/apache/unomi/itests/TestUtils.java
+++ b/itests/src/test/java/org/apache/unomi/itests/TestUtils.java
@@ -25,11 +25,10 @@ import org.apache.http.util.EntityUtils;
 import java.io.IOException;
 
 public class TestUtils {
-    public static <T> T retrieveResourceFromResponse(HttpResponse response, 
Class<T> clazz)
-            throws IOException {
+
+    public static <T> T retrieveResourceFromResponse(HttpResponse response, 
Class<T> clazz) throws IOException {
         String jsonFromResponse = EntityUtils.toString(response.getEntity());
-        ObjectMapper mapper = new ObjectMapper().
-                configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, 
false);
+        ObjectMapper mapper = new 
ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, 
false);
         return mapper.readValue(jsonFromResponse, clazz);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/38ddefc4/itests/src/test/resources/1-basic-test.csv
----------------------------------------------------------------------
diff --git a/itests/src/test/resources/1-basic-test.csv 
b/itests/src/test/resources/1-basic-test.csv
index 337940f..520b217 100644
--- a/itests/src/test/resources/1-basic-test.csv
+++ b/itests/src/test/resources/1-basic-test.csv
@@ -1,3 +1,3 @@
[email protected],Basic1,User1
[email protected],Basic2,User2
[email protected],Basic3,User3
\ No newline at end of file
[email protected],Basic1,User1,oneShotImportCity
[email protected],Basic2,User2,oneShotImportCity
[email protected],Basic3,User3,oneShotImportCity
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/38ddefc4/itests/src/test/resources/testLogin.json
----------------------------------------------------------------------
diff --git a/itests/src/test/resources/testLogin.json 
b/itests/src/test/resources/testLogin.json
new file mode 100644
index 0000000..e5a3511
--- /dev/null
+++ b/itests/src/test/resources/testLogin.json
@@ -0,0 +1,34 @@
+{
+  "metadata": {
+    "id": "testLogin",
+    "name": "Test Login",
+    "description": "Copy event properties to profile properties on login"
+  },
+  "condition": {
+    "parameterValues": {
+      "subConditions": [
+        {
+          "parameterValues": {
+          },
+          "type": "loginEventCondition"
+        }
+      ],
+      "operator": "and"
+    },
+    "type": "booleanCondition"
+  },
+  "actions": [
+    {
+      "parameterValues": {
+        "mergeProfilePropertyValue": "eventProperty::target.properties(email)",
+        "mergeProfilePropertyName": "mergeIdentifier"
+      },
+      "type": "mergeProfilesOnPropertyAction"
+    },
+    {
+      "parameterValues": {
+      },
+      "type": "allEventToProfilePropertiesAction"
+    }
+  ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/38ddefc4/itests/src/test/resources/testLoginEventCondition.json
----------------------------------------------------------------------
diff --git a/itests/src/test/resources/testLoginEventCondition.json 
b/itests/src/test/resources/testLoginEventCondition.json
new file mode 100644
index 0000000..5b248ce
--- /dev/null
+++ b/itests/src/test/resources/testLoginEventCondition.json
@@ -0,0 +1,23 @@
+{
+  "metadata": {
+    "id": "loginEventCondition",
+    "name": "loginEventCondition",
+    "description": "",
+    "systemTags": [
+      "profileTags",
+      "event",
+      "condition",
+      "eventCondition"
+    ],
+    "readOnly": true
+  },
+  "parentCondition": {
+    "type": "eventTypeCondition",
+    "parameterValues": {
+      "eventTypeId": "login"
+    }
+  },
+
+  "parameters": [
+  ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/38ddefc4/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcher.java
----------------------------------------------------------------------
diff --git 
a/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcher.java 
b/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcher.java
index 3f4ab5a..828a288 100644
--- 
a/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcher.java
+++ 
b/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcher.java
@@ -176,7 +176,7 @@ public class BundleWatcher implements 
SynchronousBundleListener, ServiceListener
         }
     }
 
-    private boolean isStartupComplete() {
+    public boolean isStartupComplete() {
         if (unomiStartedBundleCount < requiredStartedBundleCount) {
             return false;
         }

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/38ddefc4/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml
----------------------------------------------------------------------
diff --git 
a/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml 
b/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml
index 01112a3..3fe88cf 100644
--- a/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml
+++ b/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -36,4 +36,10 @@
         <property name="requiredStartedBundleCount" 
value="${lifecycle.requiredStartedBundleCount}" />
     </bean>
 
+    <service id="bundleWatcherService" ref="bundleWatcher">
+        <interfaces>
+            <value>org.apache.unomi.lifecycle.BundleWatcher</value>
+        </interfaces>
+    </service>
+
 </blueprint>


Reply via email to