You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2016/01/26 13:04:48 UTC

[17/21] syncope git commit: [SYNCOPE-152] Moving console IT under fit/core-reference in order to speed-up the total build time

http://git-wip-us.apache.org/repos/asf/syncope/blob/17d5d892/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LoggerITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LoggerITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LoggerITCase.java
new file mode 100644
index 0000000..8e825ea
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LoggerITCase.java
@@ -0,0 +1,231 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.fit.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.text.ParseException;
+import java.util.List;
+import javax.ws.rs.core.Response;
+import javax.xml.ws.WebServiceException;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.EventCategoryTO;
+import org.apache.syncope.common.lib.to.LoggerTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.AuditElements;
+import org.apache.syncope.common.lib.types.AuditElements.EventCategoryType;
+import org.apache.syncope.common.lib.types.AuditLoggerName;
+import org.apache.syncope.common.lib.types.LoggerLevel;
+import org.apache.syncope.common.lib.types.LoggerType;
+import org.apache.syncope.common.lib.types.ResourceOperation;
+import org.apache.syncope.common.rest.api.LoggerWrapper;
+import org.apache.syncope.core.logic.ReportLogic;
+import org.apache.syncope.core.logic.ResourceLogic;
+import org.apache.syncope.core.logic.GroupLogic;
+import org.apache.syncope.core.logic.UserLogic;
+import org.apache.syncope.fit.AbstractITCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class LoggerITCase extends AbstractITCase {
+
+    @Test
+    public void listLogs() {
+        List<LoggerTO> loggers = loggerService.list(LoggerType.LOG);
+        assertNotNull(loggers);
+        assertFalse(loggers.isEmpty());
+        for (LoggerTO logger : loggers) {
+            assertNotNull(logger);
+        }
+    }
+
+    @Test
+    public void listAudits() throws ParseException {
+        List<LoggerTO> audits = loggerService.list(LoggerType.AUDIT);
+
+        assertNotNull(audits);
+        assertFalse(audits.isEmpty());
+        for (LoggerTO audit : audits) {
+            assertNotNull(AuditLoggerName.fromLoggerName(audit.getKey()));
+        }
+    }
+
+    @Test
+    public void setLevel() {
+        List<LoggerTO> loggers = loggerService.list(LoggerType.LOG);
+        assertNotNull(loggers);
+        int startSize = loggers.size();
+
+        LoggerTO logger = new LoggerTO();
+        logger.setKey("TEST");
+        logger.setLevel(LoggerLevel.INFO);
+        loggerService.update(LoggerType.LOG, logger);
+        logger = loggerService.read(LoggerType.LOG, logger.getKey());
+        assertNotNull(logger);
+        assertEquals(LoggerLevel.INFO, logger.getLevel());
+
+        loggers = loggerService.list(LoggerType.LOG);
+        assertNotNull(loggers);
+        assertEquals(startSize + 1, loggers.size());
+
+        // TEST Delete
+        loggerService.delete(LoggerType.LOG, "TEST");
+        loggers = loggerService.list(LoggerType.LOG);
+        assertNotNull(loggers);
+        assertEquals(startSize, loggers.size());
+    }
+
+    @Test
+    public void enableDisableAudit() {
+        AuditLoggerName auditLoggerName = new AuditLoggerName(
+                EventCategoryType.REST,
+                ReportLogic.class.getSimpleName(),
+                null,
+                "deleteExecution",
+                AuditElements.Result.FAILURE);
+
+        List<AuditLoggerName> audits = LoggerWrapper.wrap(loggerService.list(LoggerType.AUDIT));
+        assertNotNull(audits);
+        assertFalse(audits.contains(auditLoggerName));
+
+        LoggerTO loggerTO = new LoggerTO();
+        loggerTO.setKey(auditLoggerName.toLoggerName());
+        loggerTO.setLevel(LoggerLevel.DEBUG);
+        loggerService.update(LoggerType.AUDIT, loggerTO);
+
+        audits = LoggerWrapper.wrap(loggerService.list(LoggerType.AUDIT));
+        assertNotNull(audits);
+        assertTrue(audits.contains(auditLoggerName));
+
+        loggerService.delete(LoggerType.AUDIT, auditLoggerName.toLoggerName());
+
+        audits = LoggerWrapper.wrap(loggerService.list(LoggerType.AUDIT));
+        assertNotNull(audits);
+        assertFalse(audits.contains(auditLoggerName));
+    }
+
+    @Test
+    public void listAuditEvents() {
+        final List<EventCategoryTO> events = loggerService.events();
+
+        boolean found = false;
+
+        for (EventCategoryTO eventCategoryTO : events) {
+            if (UserLogic.class.getSimpleName().equals(eventCategoryTO.getCategory())) {
+                assertEquals(EventCategoryType.REST, eventCategoryTO.getType());
+                assertTrue(eventCategoryTO.getEvents().contains("create"));
+                assertTrue(eventCategoryTO.getEvents().contains("list"));
+                assertFalse(eventCategoryTO.getEvents().contains("doCreate"));
+                assertFalse(eventCategoryTO.getEvents().contains("setStatusOnWfAdapter"));
+                assertFalse(eventCategoryTO.getEvents().contains("resolveReference"));
+                found = true;
+            }
+        }
+        assertTrue(found);
+
+        found = false;
+        for (EventCategoryTO eventCategoryTO : events) {
+            if (GroupLogic.class.getSimpleName().equals(eventCategoryTO.getCategory())) {
+                assertEquals(EventCategoryType.REST, eventCategoryTO.getType());
+                assertTrue(eventCategoryTO.getEvents().contains("create"));
+                assertTrue(eventCategoryTO.getEvents().contains("list"));
+                assertFalse(eventCategoryTO.getEvents().contains("resolveReference"));
+                found = true;
+            }
+        }
+        assertTrue(found);
+
+        found = false;
+        for (EventCategoryTO eventCategoryTO : events) {
+            if (ResourceLogic.class.getSimpleName().equals(eventCategoryTO.getCategory())) {
+                assertEquals(EventCategoryType.REST, eventCategoryTO.getType());
+                assertTrue(eventCategoryTO.getEvents().contains("create"));
+                assertTrue(eventCategoryTO.getEvents().contains("read"));
+                assertTrue(eventCategoryTO.getEvents().contains("delete"));
+                assertFalse(eventCategoryTO.getEvents().contains("resolveReference"));
+                found = true;
+            }
+        }
+        assertTrue(found);
+
+        found = false;
+        for (EventCategoryTO eventCategoryTO : events) {
+            if (AnyTypeKind.USER.name().toLowerCase().equals(eventCategoryTO.getCategory())) {
+                if (RESOURCE_NAME_LDAP.equals(eventCategoryTO.getSubcategory())
+                        && EventCategoryType.SYNCHRONIZATION == eventCategoryTO.getType()) {
+                    assertTrue(eventCategoryTO.getEvents().contains(ResourceOperation.CREATE.name().toLowerCase()));
+                    assertTrue(eventCategoryTO.getEvents().contains(ResourceOperation.UPDATE.name().toLowerCase()));
+                    assertTrue(eventCategoryTO.getEvents().contains(ResourceOperation.DELETE.name().toLowerCase()));
+                    found = true;
+                }
+            }
+        }
+        assertTrue(found);
+
+        found = false;
+        for (EventCategoryTO eventCategoryTO : events) {
+            if (AnyTypeKind.USER.name().toLowerCase().equals(eventCategoryTO.getCategory())) {
+                if (RESOURCE_NAME_CSV.equals(eventCategoryTO.getSubcategory())
+                        && EventCategoryType.PROPAGATION == eventCategoryTO.getType()) {
+                    assertTrue(eventCategoryTO.getEvents().contains(ResourceOperation.CREATE.name().toLowerCase()));
+                    assertTrue(eventCategoryTO.getEvents().contains(ResourceOperation.UPDATE.name().toLowerCase()));
+                    assertTrue(eventCategoryTO.getEvents().contains(ResourceOperation.DELETE.name().toLowerCase()));
+                    found = true;
+                }
+            }
+        }
+        assertTrue(found);
+
+        found = false;
+        for (EventCategoryTO eventCategoryTO : events) {
+            if (EventCategoryType.TASK == eventCategoryTO.getType()
+                    && "TestSampleJobDelegate".equals(eventCategoryTO.getCategory())) {
+                found = true;
+            }
+        }
+        assertTrue(found);
+
+        found = false;
+        for (EventCategoryTO eventCategoryTO : events) {
+            if (EventCategoryType.TASK == eventCategoryTO.getType()
+                    && "SyncJobDelegate".equals(eventCategoryTO.getCategory())) {
+                found = true;
+            }
+        }
+        assertTrue(found);
+    }
+
+    @Test
+    public void issueSYNCOPE708() {
+        try {
+            loggerService.read(LoggerType.LOG, "notExists");
+            fail("Reading non-existing logger, it should go in exception");
+        } catch (final WebServiceException ex) {
+            fail("Exception is WebServiceException but it should be SyncopeClientException");
+        } catch (final SyncopeClientException ex) {
+            assertEquals(Response.Status.NOT_FOUND, ex.getType().getResponseStatus());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/17d5d892/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MultitenancyITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MultitenancyITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MultitenancyITCase.java
new file mode 100644
index 0000000..c70029a
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MultitenancyITCase.java
@@ -0,0 +1,223 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.fit.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import java.security.AccessControlException;
+import java.util.List;
+import java.util.Locale;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.Response;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.ConnInstanceTO;
+import org.apache.syncope.common.lib.to.MappingItemTO;
+import org.apache.syncope.common.lib.to.MappingTO;
+import org.apache.syncope.common.lib.to.PagedResult;
+import org.apache.syncope.common.lib.to.ProvisionTO;
+import org.apache.syncope.common.lib.to.ProvisioningResult;
+import org.apache.syncope.common.lib.to.RealmTO;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.to.SyncTaskTO;
+import org.apache.syncope.common.lib.to.TaskExecTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.LoggerType;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.common.lib.types.SyncMode;
+import org.apache.syncope.common.rest.api.beans.AnySearchQuery;
+import org.apache.syncope.common.rest.api.beans.SchemaQuery;
+import org.apache.syncope.common.rest.api.service.ConnectorService;
+import org.apache.syncope.common.rest.api.service.DomainService;
+import org.apache.syncope.common.rest.api.service.LoggerService;
+import org.apache.syncope.common.rest.api.service.RealmService;
+import org.apache.syncope.common.rest.api.service.ResourceService;
+import org.apache.syncope.common.rest.api.service.SchemaService;
+import org.apache.syncope.common.rest.api.service.TaskService;
+import org.apache.syncope.common.rest.api.service.UserService;
+import org.apache.syncope.fit.AbstractITCase;
+import org.identityconnectors.framework.common.objects.ObjectClass;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class MultitenancyITCase extends AbstractITCase {
+
+    @BeforeClass
+    public static void restSetup() {
+        clientFactory = new SyncopeClientFactoryBean().setAddress(ADDRESS).setDomain("Two");
+
+        String envContentType = System.getProperty(ENV_KEY_CONTENT_TYPE);
+        if (StringUtils.isNotBlank(envContentType)) {
+            clientFactory.setContentType(envContentType);
+        }
+        LOG.info("Performing IT with content type {}", clientFactory.getContentType().getMediaType());
+
+        adminClient = clientFactory.create(ADMIN_UNAME, "password2");
+    }
+
+    @Test
+    public void masterOnly() {
+        try {
+            adminClient.getService(DomainService.class).read("Two");
+            fail();
+        } catch (AccessControlException e) {
+            assertNotNull(e);
+        }
+
+        try {
+            adminClient.getService(LoggerService.class).list(LoggerType.LOG);
+            fail();
+        } catch (AccessControlException e) {
+            assertNotNull(e);
+        }
+
+        adminClient.getService(LoggerService.class).list(LoggerType.AUDIT);
+    }
+
+    @Test
+    public void readPlainSchemas() {
+        assertEquals(17, adminClient.getService(SchemaService.class).
+                list(new SchemaQuery.Builder().type(SchemaType.PLAIN).build()).size());
+    }
+
+    @Test
+    public void readRealm() {
+        List<RealmTO> realms = adminClient.getService(RealmService.class).list();
+        assertEquals(1, realms.size());
+        assertEquals(SyncopeConstants.ROOT_REALM, realms.get(0).getName());
+    }
+
+    @Test
+    public void createUser() {
+        assertNull(adminClient.getService(RealmService.class).list().get(0).getPasswordPolicy());
+
+        UserTO user = new UserTO();
+        user.setRealm(SyncopeConstants.ROOT_REALM);
+        user.setUsername(getUUIDString());
+        user.setPassword("password");
+
+        Response response = adminClient.getService(UserService.class).create(user);
+        assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());
+
+        user = response.readEntity(new GenericType<ProvisioningResult<UserTO>>() {
+        }).getAny();
+        assertNotNull(user);
+    }
+
+    @Test
+    public void createResourceAndSync() {
+        // read connector
+        ConnInstanceTO conn = adminClient.getService(ConnectorService.class).read(100L, Locale.ENGLISH.getLanguage());
+        assertNotNull(conn);
+        assertEquals("LDAP", conn.getDisplayName());
+
+        // prepare resource
+        ResourceTO resource = new ResourceTO();
+        resource.setKey("new-ldap-resource");
+        resource.setConnector(conn.getKey());
+
+        ProvisionTO provisionTO = new ProvisionTO();
+        provisionTO.setAnyType(AnyTypeKind.USER.name());
+        provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
+        resource.getProvisions().add(provisionTO);
+
+        MappingTO mapping = new MappingTO();
+        mapping.setConnObjectLink("'uid=' + username + ',ou=people,o=isp'");
+        provisionTO.setMapping(mapping);
+
+        MappingItemTO item = new MappingItemTO();
+        item.setIntAttrName("username");
+        item.setIntMappingType(IntMappingType.Username);
+        item.setExtAttrName("cn");
+        item.setPurpose(MappingPurpose.BOTH);
+        mapping.setConnObjectKeyItem(item);
+
+        item = new MappingItemTO();
+        item.setPassword(true);
+        item.setIntMappingType(IntMappingType.Password);
+        item.setExtAttrName("userPassword");
+        item.setPurpose(MappingPurpose.BOTH);
+        item.setMandatoryCondition("true");
+        mapping.add(item);
+
+        item = new MappingItemTO();
+        item.setIntMappingType(IntMappingType.UserKey);
+        item.setPurpose(MappingPurpose.BOTH);
+        item.setExtAttrName("sn");
+        item.setMandatoryCondition("true");
+        mapping.add(item);
+
+        item = new MappingItemTO();
+        item.setIntAttrName("email");
+        item.setIntMappingType(IntMappingType.UserPlainSchema);
+        item.setPurpose(MappingPurpose.BOTH);
+        item.setExtAttrName("mail");
+        mapping.add(item);
+
+        // create resource
+        Response response = adminClient.getService(ResourceService.class).create(resource);
+        assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());
+        resource = adminClient.getService(ResourceService.class).read(resource.getKey());
+        assertNotNull(resource);
+
+        // create sync task
+        SyncTaskTO task = new SyncTaskTO();
+        task.setName("LDAP Sync Task");
+        task.setActive(true);
+        task.setDestinationRealm(SyncopeConstants.ROOT_REALM);
+        task.setResource(resource.getKey());
+        task.setSyncMode(SyncMode.FULL_RECONCILIATION);
+        task.setPerformCreate(true);
+
+        response = adminClient.getService(TaskService.class).create(task);
+        assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());
+        task = adminClient.getService(TaskService.class).read(
+                Long.valueOf(StringUtils.substringAfterLast(response.getLocation().toASCIIString(), "/")), true);
+        assertNotNull(resource);
+
+        // synchronize
+        TaskExecTO execution = AbstractTaskITCase.execProvisioningTask(
+                adminClient.getService(TaskService.class), task.getKey(), 50, false);
+
+        // verify execution status
+        String status = execution.getStatus();
+        assertNotNull(status);
+        assertEquals(PropagationTaskExecStatus.SUCCESS, PropagationTaskExecStatus.valueOf(status));
+
+        // verify that synchronized user is found
+        PagedResult<UserTO> matchingUsers = adminClient.getService(UserService.class).search(
+                new AnySearchQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
+                fiql(SyncopeClient.getUserSearchConditionBuilder().is("username").equalTo("syncFromLDAP").query()).
+                build());
+        assertNotNull(matchingUsers);
+        assertEquals(1, matchingUsers.getResult().size());
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/17d5d892/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationITCase.java
new file mode 100644
index 0000000..b1c125d
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationITCase.java
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.fit.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.util.List;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.NotificationTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.TraceLevel;
+import org.apache.syncope.common.rest.api.service.NotificationService;
+import org.apache.syncope.fit.AbstractITCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class NotificationITCase extends AbstractITCase {
+
+    private NotificationTO buildNotificationTO() {
+        NotificationTO notificationTO = new NotificationTO();
+        notificationTO.setTraceLevel(TraceLevel.SUMMARY);
+        notificationTO.getEvents().add("create");
+
+        notificationTO.getAbouts().put(AnyTypeKind.USER.name(),
+                SyncopeClient.getUserSearchConditionBuilder().
+                is("fullname").equalTo("*o*").and("fullname").equalTo("*i*").query());
+
+        notificationTO.setRecipientAttrName("email");
+        notificationTO.setRecipientAttrType(IntMappingType.UserPlainSchema);
+
+        notificationTO.setSender("syncope@syncope.apache.org");
+        notificationTO.setSubject("Test notification");
+        notificationTO.setTemplate("test");
+        return notificationTO;
+    }
+
+    @Test
+    public void read() {
+        NotificationTO notificationTO = notificationService.read(10L);
+        assertNotNull(notificationTO);
+    }
+
+    @Test
+    public void list() {
+        List<NotificationTO> notificationTOs = notificationService.list();
+        assertNotNull(notificationTOs);
+        assertFalse(notificationTOs.isEmpty());
+        for (NotificationTO instance : notificationTOs) {
+            assertNotNull(instance);
+        }
+    }
+
+    @Test
+    public void create() {
+        NotificationTO notificationTO = buildNotificationTO();
+        notificationTO.setRecipientsFIQL(SyncopeClient.getUserSearchConditionBuilder().inGroups(7L).query());
+
+        Response response = notificationService.create(notificationTO);
+        NotificationTO actual = getObject(response.getLocation(), NotificationService.class, NotificationTO.class);
+
+        assertNotNull(actual);
+        assertNotNull(actual.getKey());
+        notificationTO.setKey(actual.getKey());
+        assertEquals(actual, notificationTO);
+    }
+
+    @Test
+    public void update() {
+        NotificationTO notificationTO = notificationService.read(10L);
+        notificationTO.setRecipientsFIQL(SyncopeClient.getUserSearchConditionBuilder().inGroups(7L).query());
+
+        notificationService.update(notificationTO);
+        NotificationTO actual = notificationService.read(notificationTO.getKey());
+        assertNotNull(actual);
+        assertEquals(actual, notificationTO);
+    }
+
+    @Test
+    public void delete() {
+        NotificationTO notification = buildNotificationTO();
+        notification.setSelfAsRecipient(true);
+        Response response = notificationService.create(notification);
+        notification = getObject(response.getLocation(), NotificationService.class, NotificationTO.class);
+
+        notificationService.delete(notification.getKey());
+
+        try {
+            notificationService.read(notification.getKey());
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.NotFound, e.getType());
+        }
+    }
+
+    @Test
+    public void issueSYNCOPE83() {
+        NotificationTO notificationTO = buildNotificationTO();
+        notificationTO.setSelfAsRecipient(true);
+
+        NotificationTO actual = null;
+        try {
+            Response response = notificationService.create(notificationTO);
+            actual = getObject(response.getLocation(), NotificationService.class, NotificationTO.class);
+        } catch (SyncopeClientException e) {
+            assertNotNull(e);
+        }
+        assertNotNull(actual);
+        assertNotNull(actual.getKey());
+        notificationTO.setKey(actual.getKey());
+        assertEquals(actual, notificationTO);
+    }
+
+    @Test
+    public void issueSYNCOPE445() {
+        NotificationTO notificationTO = buildNotificationTO();
+        notificationTO.getStaticRecipients().add("syncope445@syncope.apache.org");
+
+        NotificationTO actual = null;
+        try {
+            Response response = notificationService.create(notificationTO);
+            actual = getObject(response.getLocation(), NotificationService.class, NotificationTO.class);
+        } catch (SyncopeClientException e) {
+            assertNotNull(e);
+        }
+        assertNotNull(actual);
+        assertNotNull(actual.getKey());
+        notificationTO.setKey(actual.getKey());
+        assertEquals(actual, notificationTO);
+    }
+
+    @Test
+    public void issueSYNCOPE446() {
+        NotificationTO notificationTO = buildNotificationTO();
+        notificationTO.getStaticRecipients().add("syncope446@syncope.apache.org");
+        notificationTO.getAbouts().put(AnyTypeKind.GROUP.name(),
+                SyncopeClient.getGroupSearchConditionBuilder().is("name").equalTo("citizen").query());
+
+        NotificationTO actual = null;
+        try {
+            Response response = notificationService.create(notificationTO);
+            actual = getObject(response.getLocation(), NotificationService.class, NotificationTO.class);
+        } catch (SyncopeClientException e) {
+            assertNotNull(e);
+        }
+        assertNotNull(actual);
+        assertNotNull(actual.getKey());
+        notificationTO.setKey(actual.getKey());
+        assertEquals(actual, notificationTO);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/17d5d892/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
new file mode 100644
index 0000000..605663f
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
@@ -0,0 +1,399 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.fit.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import com.icegreen.greenmail.util.GreenMail;
+import com.icegreen.greenmail.util.ServerSetup;
+import java.io.InputStream;
+import java.util.Properties;
+import javax.mail.Flags;
+import javax.mail.Folder;
+import javax.mail.Message;
+import javax.mail.Session;
+import javax.mail.Store;
+import javax.ws.rs.core.Response;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.NotificationTO;
+import org.apache.syncope.common.lib.to.NotificationTaskTO;
+import org.apache.syncope.common.lib.to.TaskExecTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.TraceLevel;
+import org.apache.syncope.common.rest.api.beans.ExecuteQuery;
+import org.apache.syncope.common.rest.api.service.NotificationService;
+import org.apache.syncope.core.logic.notification.NotificationJob;
+import org.apache.syncope.fit.core.reference.TestNotificationRecipientsProvider;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class NotificationTaskITCase extends AbstractTaskITCase {
+
+    private static final String MAIL_ADDRESS = "notificationtest@syncope.apache.org";
+
+    private static final String POP3_HOST = "localhost";
+
+    private static final int POP3_PORT = 1110;
+
+    private static String SMTP_HOST;
+
+    private static int SMTP_PORT;
+
+    private static GreenMail greenMail;
+
+    @BeforeClass
+    public static void startGreenMail() {
+        Properties props = new Properties();
+        InputStream propStream = null;
+        try {
+            propStream = ExceptionMapperITCase.class.getResourceAsStream("/mail.properties");
+            props.load(propStream);
+        } catch (Exception e) {
+            LOG.error("Could not load /mail.properties", e);
+        } finally {
+            IOUtils.closeQuietly(propStream);
+        }
+
+        SMTP_HOST = props.getProperty("smtpHost");
+        assertNotNull(SMTP_HOST);
+        SMTP_PORT = Integer.parseInt(props.getProperty("smtpPort"));
+        assertNotNull(SMTP_PORT);
+
+        ServerSetup[] config = new ServerSetup[2];
+        config[0] = new ServerSetup(SMTP_PORT, SMTP_HOST, ServerSetup.PROTOCOL_SMTP);
+        config[1] = new ServerSetup(POP3_PORT, POP3_HOST, ServerSetup.PROTOCOL_POP3);
+        greenMail = new GreenMail(config);
+        greenMail.start();
+    }
+
+    @AfterClass
+    public static void stopGreenMail() {
+        if (greenMail != null) {
+            greenMail.stop();
+        }
+    }
+
+    private boolean verifyMail(final String sender, final String subject, final String mailAddress) throws Exception {
+        LOG.info("Waiting for notification to be sent...");
+        greenMail.waitForIncomingEmail(1);
+
+        boolean found = false;
+        Session session = Session.getDefaultInstance(System.getProperties());
+        session.setDebug(true);
+        Store store = session.getStore("pop3");
+        store.connect(POP3_HOST, POP3_PORT, mailAddress, mailAddress);
+
+        Folder inbox = store.getFolder("INBOX");
+        assertNotNull(inbox);
+        inbox.open(Folder.READ_WRITE);
+
+        Message[] messages = inbox.getMessages();
+        for (Message message : messages) {
+            if (sender.equals(message.getFrom()[0].toString()) && subject.equals(message.getSubject())) {
+                found = true;
+                message.setFlag(Flags.Flag.DELETED, true);
+            }
+        }
+
+        inbox.close(true);
+        store.close();
+        return found;
+    }
+
+    @Test
+    public void notifyByMail() throws Exception {
+        String sender = "syncopetest-" + getUUIDString() + "@syncope.apache.org";
+        String subject = "Test notification " + getUUIDString();
+        String recipient = createNotificationTask(true, true, TraceLevel.ALL, sender, subject);
+        NotificationTaskTO taskTO = findNotificationTaskBySender(sender);
+        assertNotNull(taskTO);
+        assertTrue(taskTO.getExecutions().isEmpty());
+
+        execNotificationTask(taskService, taskTO.getKey(), 50);
+
+        assertTrue(verifyMail(sender, subject, recipient));
+
+        // verify message body
+        taskTO = taskService.read(taskTO.getKey(), true);
+        assertNotNull(taskTO);
+        assertTrue(taskTO.isExecuted());
+        assertNotNull(taskTO.getTextBody());
+        assertTrue("Notification mail text doesn't contain expected content.",
+                taskTO.getTextBody().contains("Your email address is " + recipient + "."));
+        assertTrue("Notification mail text doesn't contain expected content.",
+                taskTO.getTextBody().contains("Your email address inside a link: "
+                        + "http://localhost/?email=" + recipient.replaceAll("@", "%40") + " ."));
+    }
+
+    @Test
+    public void notifyByMailEmptyAbout() throws Exception {
+        String sender = "syncopetest-" + getUUIDString() + "@syncope.apache.org";
+        String subject = "Test notification " + getUUIDString();
+        String recipient = createNotificationTask(true, false, TraceLevel.ALL, sender, subject);
+        NotificationTaskTO taskTO = findNotificationTaskBySender(sender);
+        assertNotNull(taskTO);
+        assertTrue(taskTO.getExecutions().isEmpty());
+
+        execNotificationTask(taskService, taskTO.getKey(), 50);
+
+        assertTrue(verifyMail(sender, subject, recipient));
+    }
+
+    @Test
+    public void notifyByMailWithRetry() throws Exception {
+        // 1. Set higher number of retries
+        AttrTO origMaxRetries = configurationService.get("notification.maxRetries");
+
+        configurationService.set(attrTO(origMaxRetries.getSchema(), "10"));
+
+        // 2. Stop mail server to force errors while sending out e-mails
+        stopGreenMail();
+
+        try {
+            // 3. create notification and user
+            String sender = "syncopetest-" + getUUIDString() + "@syncope.apache.org";
+            String subject = "Test notification " + getUUIDString();
+            createNotificationTask(true, true, TraceLevel.ALL, sender, subject);
+            NotificationTaskTO taskTO = findNotificationTaskBySender(sender);
+            assertNotNull(taskTO);
+            assertTrue(taskTO.getExecutions().isEmpty());
+
+            // 4. verify notification could not be delivered
+            execTask(taskService, taskTO.getKey(), NotificationJob.Status.NOT_SENT.name(), 5, false);
+
+            taskTO = taskService.read(taskTO.getKey(), true);
+            assertNotNull(taskTO);
+            assertFalse(taskTO.isExecuted());
+            assertFalse(taskTO.getExecutions().isEmpty());
+            for (TaskExecTO exec : taskTO.getExecutions()) {
+                assertEquals(NotificationJob.Status.NOT_SENT.name(), exec.getStatus());
+            }
+        } finally {
+            // start mail server again
+            startGreenMail();
+            // reset number of retries
+            configurationService.set(origMaxRetries);
+        }
+    }
+
+    @Test
+    public void issueSYNCOPE81() {
+        String sender = "syncope81@syncope.apache.org";
+        createNotificationTask(true, true, TraceLevel.ALL, sender, "Test notification");
+        NotificationTaskTO taskTO = findNotificationTaskBySender(sender);
+        assertNotNull(taskTO);
+        assertTrue(taskTO.getExecutions().isEmpty());
+
+        // generate an execution in order to verify the deletion of a notification task with one or more executions
+        execNotificationTask(taskService, taskTO.getKey(), 50);
+
+        taskTO = taskService.read(taskTO.getKey(), true);
+        assertTrue(taskTO.isExecuted());
+        assertFalse(taskTO.getExecutions().isEmpty());
+
+        taskService.delete(taskTO.getKey());
+    }
+
+    @Test
+    public void issueSYNCOPE86() {
+        // 1. create notification task
+        String sender = "syncope86@syncope.apache.org";
+        createNotificationTask(true, true, TraceLevel.ALL, sender, "Test notification");
+
+        // 2. get NotificationTaskTO for user just created
+        NotificationTaskTO taskTO = findNotificationTaskBySender(sender);
+        assertNotNull(taskTO);
+        assertTrue(taskTO.getExecutions().isEmpty());
+
+        try {
+            // 3. execute the generated NotificationTask
+            execNotificationTask(taskService, taskTO.getKey(), 50);
+
+            // 4. verify
+            taskTO = taskService.read(taskTO.getKey(), true);
+            assertNotNull(taskTO);
+            assertTrue(taskTO.isExecuted());
+            assertEquals(1, taskTO.getExecutions().size());
+        } finally {
+            // Remove execution to make test re-runnable
+            taskService.deleteExecution(taskTO.getExecutions().get(0).getKey());
+        }
+    }
+
+    @Test
+    public void issueSYNCOPE192() throws Exception {
+        String sender = "syncopetest-" + getUUIDString() + "@syncope.apache.org";
+        String subject = "Test notification " + getUUIDString();
+        String recipient = createNotificationTask(true, true, TraceLevel.NONE, sender, subject);
+        NotificationTaskTO taskTO = findNotificationTaskBySender(sender);
+        assertNotNull(taskTO);
+        assertTrue(taskTO.getExecutions().isEmpty());
+
+        taskService.execute(new ExecuteQuery.Builder().key(taskTO.getKey()).build());
+
+        try {
+            Thread.sleep(5);
+        } catch (InterruptedException e) {
+        }
+
+        assertTrue(verifyMail(sender, subject, recipient));
+
+        // verify that last exec status was updated
+        taskTO = taskService.read(taskTO.getKey(), true);
+        assertNotNull(taskTO);
+        assertTrue(taskTO.isExecuted());
+        assertTrue(taskTO.getExecutions().isEmpty());
+        assertTrue(StringUtils.isNotBlank(taskTO.getLatestExecStatus()));
+    }
+
+    @Test
+    public void issueSYNCOPE445() throws Exception {
+        String sender = "syncopetest-" + getUUIDString() + "@syncope.apache.org";
+        String subject = "Test notification " + getUUIDString();
+        String recipient = createNotificationTask(
+                true, true, TraceLevel.ALL, sender, subject, "syncope445@syncope.apache.org");
+        NotificationTaskTO taskTO = findNotificationTaskBySender(sender);
+        assertNotNull(taskTO);
+        assertTrue(taskTO.getExecutions().isEmpty());
+
+        execNotificationTask(taskService, taskTO.getKey(), 50);
+
+        assertTrue(verifyMail(sender, subject, recipient));
+
+        // verify task
+        taskTO = taskService.read(taskTO.getKey(), true);
+        assertTrue(taskTO.isExecuted());
+        assertNotNull(taskTO);
+        assertTrue(taskTO.getRecipients().contains("syncope445@syncope.apache.org"));
+    }
+
+    @Test
+    public void issueSYNCOPE446() throws Exception {
+        // 1. Create notification
+        NotificationTO notification = new NotificationTO();
+        notification.setTraceLevel(TraceLevel.ALL);
+        notification.getEvents().add("[REST]:[GroupLogic]:[]:[create]:[SUCCESS]");
+
+        String groupName = "group" + getUUIDString();
+        notification.getAbouts().put(AnyTypeKind.GROUP.name(),
+                SyncopeClient.getGroupSearchConditionBuilder().is("name").equalTo(groupName).query());
+
+        notification.setRecipientsFIQL(SyncopeClient.getUserSearchConditionBuilder().inGroups(8L).query());
+        notification.setSelfAsRecipient(false);
+        notification.setRecipientAttrName("email");
+        notification.setRecipientAttrType(IntMappingType.UserPlainSchema);
+        notification.getStaticRecipients().add(MAIL_ADDRESS);
+        notification.setRecipientsProviderClassName(TestNotificationRecipientsProvider.class.getName());
+
+        String sender = "syncopetest-" + getUUIDString() + "@syncope.apache.org";
+        notification.setSender(sender);
+        String subject = "Test notification " + getUUIDString();
+        notification.setSubject(subject);
+        notification.setTemplate("optin");
+        notification.setActive(true);
+
+        Response response = notificationService.create(notification);
+        notification = getObject(response.getLocation(), NotificationService.class, NotificationTO.class);
+        assertNotNull(notification);
+        assertEquals(TestNotificationRecipientsProvider.class.getName(), notification.getRecipientsProviderClassName());
+
+        // 2. create group
+        GroupTO groupTO = new GroupTO();
+        groupTO.setName(groupName);
+        groupTO.setRealm("/even/two");
+        groupTO = createGroup(groupTO).getAny();
+        assertNotNull(groupTO);
+
+        // 3. verify
+        NotificationTaskTO taskTO = findNotificationTaskBySender(sender);
+        assertNotNull(taskTO);
+        assertTrue(taskTO.getRecipients().containsAll(
+                new TestNotificationRecipientsProvider().provideRecipients(null)));
+
+        execNotificationTask(taskService, taskTO.getKey(), 50);
+
+        assertTrue(verifyMail(sender, subject, MAIL_ADDRESS));
+    }
+
+    @Test
+    public void issueSYNCOPE492() throws Exception {
+        String sender = "syncopetest-" + getUUIDString() + "@syncope.apache.org";
+        String subject = "Test notification " + getUUIDString();
+        createNotificationTask(false, true, TraceLevel.NONE, sender, subject, "syncope445@syncope.apache.org");
+
+        // verify that no task was created for disabled notification
+        assertNull(findNotificationTaskBySender(sender));
+    }
+
+    private String createNotificationTask(final boolean active, final boolean includeAbout, final TraceLevel traceLevel,
+            final String sender, final String subject, final String... staticRecipients) {
+
+        // 1. Create notification
+        NotificationTO notification = new NotificationTO();
+        notification.setTraceLevel(traceLevel);
+        notification.getEvents().add("[REST]:[UserLogic]:[]:[create]:[SUCCESS]");
+
+        if (includeAbout) {
+            notification.getAbouts().put(AnyTypeKind.USER.name(),
+                    SyncopeClient.getUserSearchConditionBuilder().inGroups(7L).query());
+        }
+
+        notification.setRecipientsFIQL(SyncopeClient.getUserSearchConditionBuilder().inGroups(8L).query());
+        notification.setSelfAsRecipient(true);
+        notification.setRecipientAttrName("email");
+        notification.setRecipientAttrType(IntMappingType.UserPlainSchema);
+        if (staticRecipients != null) {
+            CollectionUtils.addAll(notification.getStaticRecipients(), staticRecipients);
+        }
+
+        notification.setSender(sender);
+        notification.setSubject(subject);
+        notification.setTemplate("optin");
+        notification.setActive(active);
+
+        Response response = notificationService.create(notification);
+        notification = getObject(response.getLocation(), NotificationService.class, NotificationTO.class);
+        assertNotNull(notification);
+
+        // 2. create user
+        UserTO userTO = UserITCase.getUniqueSampleTO(MAIL_ADDRESS);
+        userTO.getMemberships().add(new MembershipTO.Builder().group(7L).build());
+
+        userTO = createUser(userTO).getAny();
+        assertNotNull(userTO);
+        return userTO.getUsername();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/17d5d892/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java
new file mode 100644
index 0000000..973b09e
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java
@@ -0,0 +1,336 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.fit.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.List;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.Response;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.commons.lang3.SerializationUtils;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
+import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.PlainSchemaTO;
+import org.apache.syncope.common.lib.to.ProvisioningResult;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.lib.types.CipherAlgorithm;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.common.rest.api.beans.SchemaQuery;
+import org.apache.syncope.fit.AbstractITCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class PlainSchemaITCase extends AbstractITCase {
+
+    private PlainSchemaTO buildPlainSchemaTO(final String name, final AttrSchemaType type) {
+        PlainSchemaTO schemaTO = new PlainSchemaTO();
+        schemaTO.setKey(name + getUUIDString());
+        schemaTO.setType(type);
+        return schemaTO;
+    }
+
+    @Test
+    public void create() {
+        PlainSchemaTO schemaTO = buildPlainSchemaTO("testAttribute", AttrSchemaType.String);
+        schemaTO.setMandatoryCondition("false");
+
+        PlainSchemaTO newPlainSchemaTO = createSchema(SchemaType.PLAIN, schemaTO);
+        assertEquals(schemaTO, newPlainSchemaTO);
+
+        try {
+            createSchema(SchemaType.PLAIN, schemaTO);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.EntityExists, e.getType());
+        }
+    }
+
+    @Test
+    public void createWithNotPermittedName() {
+        PlainSchemaTO schemaTO = new PlainSchemaTO();
+        schemaTO.setKey("failedLogins");
+        schemaTO.setType(AttrSchemaType.String);
+
+        try {
+            createSchema(SchemaType.PLAIN, schemaTO);
+            fail("This should not be reacheable");
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.InvalidPlainSchema, e.getType());
+            assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidName.name()));
+        }
+    }
+
+    @Test
+    public void createREnumWithoutEnumeration() {
+        PlainSchemaTO schemaTO = new PlainSchemaTO();
+        schemaTO.setKey("enumcheck");
+        schemaTO.setType(AttrSchemaType.Enum);
+
+        try {
+            createSchema(SchemaType.PLAIN, schemaTO);
+            fail("This should not be reacheable");
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.InvalidPlainSchema, e.getType());
+            assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidSchemaEnum.name()));
+        }
+    }
+
+    @Test
+    public void createUEnumWithoutEnumeration() {
+        PlainSchemaTO schemaTO = new PlainSchemaTO();
+        schemaTO.setKey("enumcheck");
+        schemaTO.setType(AttrSchemaType.Enum);
+
+        try {
+            createSchema(SchemaType.PLAIN, schemaTO);
+            fail("This should not be reacheable");
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.InvalidPlainSchema, e.getType());
+            assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidSchemaEnum.name()));
+        }
+    }
+
+    @Test
+    public void createEncrypted() {
+        PlainSchemaTO schemaTO = new PlainSchemaTO();
+        schemaTO.setKey("encrypted");
+        schemaTO.setType(AttrSchemaType.Encrypted);
+        schemaTO.setCipherAlgorithm(CipherAlgorithm.AES);
+        schemaTO.setSecretKey("huhadfhsjfsfsdkj!####");
+
+        createSchema(SchemaType.PLAIN, schemaTO);
+    }
+
+    @Test
+    public void createBinary() {
+        PlainSchemaTO schemaTO = new PlainSchemaTO();
+        schemaTO.setKey("x509certificate");
+        schemaTO.setType(AttrSchemaType.Binary);
+        schemaTO.setMimeType("application/x-x509-ca-cert");
+
+        createSchema(SchemaType.PLAIN, schemaTO);
+    }
+
+    @Test
+    public void delete() {
+        PlainSchemaTO schemaTO = buildPlainSchemaTO("todelete", AttrSchemaType.String);
+        schemaTO.setMandatoryCondition("false");
+        createSchema(SchemaType.PLAIN, schemaTO);
+
+        schemaService.delete(SchemaType.PLAIN, schemaTO.getKey());
+        PlainSchemaTO firstname = null;
+        try {
+            firstname = schemaService.read(SchemaType.PLAIN, schemaTO.getKey());
+        } catch (SyncopeClientException e) {
+            assertEquals(Response.Status.NOT_FOUND, e.getType().getResponseStatus());
+        }
+        assertNull(firstname);
+    }
+
+    @Test
+    public void list() {
+        List<PlainSchemaTO> schemas = schemaService.list(new SchemaQuery.Builder().type(SchemaType.PLAIN).build());
+        assertFalse(schemas.isEmpty());
+        for (PlainSchemaTO schemaTO : schemas) {
+            assertNotNull(schemaTO);
+        }
+    }
+
+    @Test
+    public void listByAnyTypeClass() {
+        final String clazz = anyTypeService.read(AnyTypeKind.USER.name()).getClasses().get(0);
+
+        List<PlainSchemaTO> userSchemas = schemaService.list(
+                new SchemaQuery.Builder().type(SchemaType.PLAIN).anyTypeClass(clazz).build());
+
+        assertTrue(IterableUtils.matchesAny(userSchemas, new Predicate<PlainSchemaTO>() {
+
+            @Override
+            public boolean evaluate(final PlainSchemaTO object) {
+                return "fullname".equals(object.getKey());
+            }
+        }));
+
+        assertFalse(IterableUtils.matchesAny(userSchemas, new Predicate<PlainSchemaTO>() {
+
+            @Override
+            public boolean evaluate(final PlainSchemaTO object) {
+                return "password.cipher.algorithm".equals(object.getKey())
+                        || "rderived_dx".equals(object.getKey())
+                        || "icon".equals(object.getKey())
+                        || "mderived_sx".equals(object.getKey())
+                        || "self.membership.layout".equals(object.getKey());
+            }
+        }));
+    }
+
+    @Test
+    public void update() {
+        PlainSchemaTO schemaTO = schemaService.read(SchemaType.PLAIN, "icon");
+        assertNotNull(schemaTO);
+
+        schemaService.update(SchemaType.PLAIN, schemaTO);
+        PlainSchemaTO updatedTO = schemaService.read(SchemaType.PLAIN, "icon");
+        assertEquals(schemaTO, updatedTO);
+
+        updatedTO.setType(AttrSchemaType.Date);
+        try {
+            schemaService.update(SchemaType.PLAIN, updatedTO);
+            fail("This should not be reacheable");
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.InvalidPlainSchema, e.getType());
+        }
+    }
+
+    @Test
+    public void issue258() {
+        PlainSchemaTO schemaTO = new PlainSchemaTO();
+        schemaTO.setKey("schema_issue258");
+        schemaTO.setType(AttrSchemaType.Double);
+
+        schemaTO = createSchema(SchemaType.PLAIN, schemaTO);
+        assertNotNull(schemaTO);
+
+        AnyTypeClassTO typeClass = new AnyTypeClassTO();
+        typeClass.setKey("issue258");
+        typeClass.getPlainSchemas().add(schemaTO.getKey());
+        anyTypeClassService.create(typeClass);
+
+        UserTO userTO = UserITCase.getUniqueSampleTO("issue258@syncope.apache.org");
+        userTO.getAuxClasses().add(typeClass.getKey());
+        userTO.getPlainAttrs().add(attrTO(schemaTO.getKey(), "1.2"));
+
+        userTO = createUser(userTO).getAny();
+        assertNotNull(userTO);
+
+        schemaTO.setType(AttrSchemaType.Long);
+        try {
+            schemaService.update(SchemaType.PLAIN, schemaTO);
+            fail("This should not be reacheable");
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.InvalidPlainSchema, e.getType());
+        }
+    }
+
+    @Test
+    public void issue259() {
+        PlainSchemaTO schemaTO = buildPlainSchemaTO("schema_issue259", AttrSchemaType.Double);
+        schemaTO.setUniqueConstraint(true);
+
+        schemaTO = createSchema(SchemaType.PLAIN, schemaTO);
+        assertNotNull(schemaTO);
+
+        AnyTypeClassTO typeClass = new AnyTypeClassTO();
+        typeClass.setKey("issue259");
+        typeClass.getPlainSchemas().add(schemaTO.getKey());
+        anyTypeClassService.create(typeClass);
+
+        UserTO userTO = UserITCase.getUniqueSampleTO("issue259@syncope.apache.org");
+        userTO.getAuxClasses().add(typeClass.getKey());
+        userTO.getPlainAttrs().add(attrTO(schemaTO.getKey(), "1"));
+        userTO = createUser(userTO).getAny();
+        assertNotNull(userTO);
+
+        UserTO newUserTO = SerializationUtils.clone(userTO);
+        newUserTO.getMemberships().add(new MembershipTO.Builder().group(2L).build());
+
+        userTO = userService.update(newUserTO).readEntity(new GenericType<ProvisioningResult<UserTO>>() {
+        }).getAny();
+        assertNotNull(userTO);
+    }
+
+    @Test
+    public void issue260() {
+        PlainSchemaTO schemaTO = buildPlainSchemaTO("schema_issue260", AttrSchemaType.Double);
+        schemaTO.setUniqueConstraint(true);
+
+        schemaTO = createSchema(SchemaType.PLAIN, schemaTO);
+        assertNotNull(schemaTO);
+
+        AnyTypeClassTO typeClass = new AnyTypeClassTO();
+        typeClass.setKey("issue260");
+        typeClass.getPlainSchemas().add(schemaTO.getKey());
+        anyTypeClassService.create(typeClass);
+
+        UserTO userTO = UserITCase.getUniqueSampleTO("issue260@syncope.apache.org");
+        userTO.getAuxClasses().add(typeClass.getKey());
+        userTO.getPlainAttrs().add(attrTO(schemaTO.getKey(), "1.2"));
+        userTO = createUser(userTO).getAny();
+        assertNotNull(userTO);
+
+        schemaTO.setUniqueConstraint(false);
+        try {
+            schemaService.update(SchemaType.PLAIN, schemaTO);
+            fail("This should not be reacheable");
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.InvalidPlainSchema, e.getType());
+        }
+    }
+
+    @Test
+    public void issueSYNCOPE323() {
+        PlainSchemaTO actual = schemaService.read(SchemaType.PLAIN, "icon");
+        assertNotNull(actual);
+
+        try {
+            createSchema(SchemaType.PLAIN, actual);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(Response.Status.CONFLICT, e.getType().getResponseStatus());
+            assertEquals(ClientExceptionType.EntityExists, e.getType());
+        }
+
+        actual.setKey(null);
+        try {
+            createSchema(SchemaType.PLAIN, actual);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(Response.Status.BAD_REQUEST, e.getType().getResponseStatus());
+            assertEquals(ClientExceptionType.RequiredValuesMissing, e.getType());
+        }
+    }
+
+    @Test
+    public void issueSYNCOPE418() {
+        PlainSchemaTO schema = buildPlainSchemaTO("http://schemas.examples.org/security/authorization/organizationUnit",
+                AttrSchemaType.Double);
+
+        try {
+            createSchema(SchemaType.PLAIN, schema);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.InvalidPlainSchema, e.getType());
+            assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidName.name()));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/17d5d892/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java
new file mode 100644
index 0000000..1930579
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.fit.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+import java.util.List;
+import org.apache.commons.lang3.SerializationUtils;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.policy.AccountPolicyTO;
+import org.apache.syncope.common.lib.policy.PasswordPolicyTO;
+import org.apache.syncope.common.lib.policy.SyncPolicyTO;
+import org.apache.syncope.common.lib.policy.DefaultAccountRuleConf;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf;
+import org.apache.syncope.common.lib.types.PolicyType;
+import org.apache.syncope.common.lib.policy.SyncPolicySpec;
+import org.apache.syncope.fit.AbstractITCase;
+import org.apache.syncope.fit.core.reference.TestSyncRule;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class PolicyITCase extends AbstractITCase {
+
+    private SyncPolicyTO buildSyncPolicyTO() {
+        SyncPolicyTO policy = new SyncPolicyTO();
+
+        SyncPolicySpec spec = new SyncPolicySpec();
+        spec.getCorrelationRules().put(AnyTypeKind.USER.name(), TestSyncRule.class.getName());
+
+        policy.setSpecification(spec);
+        policy.setDescription("Sync policy");
+
+        return policy;
+    }
+
+    @Test
+    public void listByType() {
+        List<SyncPolicyTO> policyTOs = policyService.list(PolicyType.SYNC);
+
+        assertNotNull(policyTOs);
+        assertFalse(policyTOs.isEmpty());
+    }
+
+    @Test
+    public void getAccountPolicy() {
+        AccountPolicyTO policyTO = policyService.read(6L);
+
+        assertNotNull(policyTO);
+        assertTrue(policyTO.getUsedByResources().isEmpty());
+        assertTrue(policyTO.getUsedByRealms().contains("/odd"));
+    }
+
+    @Test
+    public void getPasswordPolicy() {
+        PasswordPolicyTO policyTO = policyService.read(4L);
+
+        assertNotNull(policyTO);
+        assertTrue(policyTO.getUsedByResources().contains(RESOURCE_NAME_NOPROPAGATION));
+        assertTrue(policyTO.getUsedByRealms().containsAll(Arrays.asList("/", "/odd", "/even")));
+    }
+
+    @Test
+    public void getSyncPolicy() {
+        SyncPolicyTO policyTO = policyService.read(1L);
+
+        assertNotNull(policyTO);
+        assertTrue(policyTO.getUsedByRealms().isEmpty());
+    }
+
+    @Test
+    public void createMissingDescription() {
+        SyncPolicyTO policy = new SyncPolicyTO();
+        policy.setSpecification(new SyncPolicySpec());
+
+        try {
+            createPolicy(policy);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.InvalidPolicy, e.getType());
+        }
+    }
+
+    @Test
+    public void create() {
+        SyncPolicyTO policy = buildSyncPolicyTO();
+
+        SyncPolicyTO policyTO = createPolicy(policy);
+
+        assertNotNull(policyTO);
+        assertEquals(PolicyType.SYNC, policyTO.getType());
+        assertEquals(TestSyncRule.class.getName(),
+                policyTO.getSpecification().getCorrelationRules().get(AnyTypeKind.USER.name()));
+    }
+
+    @Test
+    public void update() {
+        PasswordPolicyTO globalPolicy = policyService.read(2L);
+
+        PasswordPolicyTO policy = SerializationUtils.clone(globalPolicy);
+        policy.setDescription("A simple password policy");
+
+        // create a new password policy using the former as a template
+        policy = createPolicy(policy);
+        assertNotNull(policy);
+        assertNotEquals(2L, policy.getKey());
+
+        ((DefaultPasswordRuleConf) policy.getRuleConfs().get(0)).setMaxLength(22);
+
+        // update new password policy
+        policyService.update(policy);
+        policy = policyService.read(policy.getKey());
+
+        assertNotNull(policy);
+        assertEquals(PolicyType.PASSWORD, policy.getType());
+        assertEquals(22, ((DefaultPasswordRuleConf) policy.getRuleConfs().get(0)).getMaxLength());
+        assertEquals(8, ((DefaultPasswordRuleConf) policy.getRuleConfs().get(0)).getMinLength());
+    }
+
+    @Test
+    public void delete() {
+        SyncPolicyTO policy = buildSyncPolicyTO();
+
+        SyncPolicyTO policyTO = createPolicy(policy);
+        assertNotNull(policyTO);
+
+        policyService.delete(policyTO.getKey());
+
+        try {
+            policyService.read(policyTO.getKey());
+            fail();
+        } catch (SyncopeClientException e) {
+            assertNotNull(e);
+        }
+    }
+
+    @Test
+    public void getCorrelationRules() {
+        assertEquals(2, syncopeService.info().getSyncCorrelationRules().size());
+    }
+
+    @Test
+    public void issueSYNCOPE553() {
+        AccountPolicyTO policy = new AccountPolicyTO();
+        policy.setDescription("SYNCOPE553");
+
+        DefaultAccountRuleConf ruleConf = new DefaultAccountRuleConf();
+        ruleConf.setMinLength(3);
+        ruleConf.setMaxLength(8);
+        policy.getRuleConfs().add(ruleConf);
+
+        policy = createPolicy(policy);
+        assertNotNull(policy);
+    }
+
+    @Test
+    public void issueSYNCOPE682() {
+        AccountPolicyTO policy = new AccountPolicyTO();
+        policy.setDescription("SYNCOPE682");
+        policy.getResources().add(RESOURCE_NAME_LDAP);
+
+        DefaultAccountRuleConf ruleConf = new DefaultAccountRuleConf();
+        ruleConf.setMinLength(3);
+        ruleConf.setMaxLength(8);
+        policy.getRuleConfs().add(ruleConf);
+
+        policy = createPolicy(policy);
+        assertNotNull(policy);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/17d5d892/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
new file mode 100644
index 0000000..9686e20
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.fit.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.to.BulkAction;
+import org.apache.syncope.common.lib.to.PagedResult;
+import org.apache.syncope.common.lib.to.PropagationTaskTO;
+import org.apache.syncope.common.lib.to.TaskExecTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.common.rest.api.beans.ExecuteQuery;
+import org.apache.syncope.common.rest.api.beans.TaskExecQuery;
+import org.apache.syncope.common.rest.api.beans.TaskQuery;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class PropagationTaskITCase extends AbstractTaskITCase {
+
+    @Test
+    public void paginatedList() {
+        PagedResult<PropagationTaskTO> tasks = taskService.list(
+                new TaskQuery.Builder().type(TaskType.PROPAGATION).page(1).size(2).build());
+        assertNotNull(tasks);
+        assertEquals(2, tasks.getResult().size());
+
+        for (AbstractTaskTO task : tasks.getResult()) {
+            assertNotNull(task);
+        }
+
+        tasks = taskService.list(
+                new TaskQuery.Builder().type(TaskType.PROPAGATION).page(2).size(2).build());
+        assertNotNull(tasks);
+        assertEquals(2, tasks.getPage());
+        assertEquals(2, tasks.getResult().size());
+
+        for (AbstractTaskTO task : tasks.getResult()) {
+            assertNotNull(task);
+        }
+
+        tasks = taskService.list(
+                new TaskQuery.Builder().type(TaskType.PROPAGATION).page(1000).size(2).build());
+        assertNotNull(tasks);
+        assertTrue(tasks.getResult().isEmpty());
+    }
+
+    @Test
+    public void read() {
+        final PropagationTaskTO taskTO = taskService.read(3L, true);
+        assertNotNull(taskTO);
+        assertNotNull(taskTO.getExecutions());
+        assertTrue(taskTO.getExecutions().isEmpty());
+    }
+
+    @Test
+    public void bulkAction() {
+        PagedResult<PropagationTaskTO> before = taskService.list(
+                new TaskQuery.Builder().type(TaskType.PROPAGATION).build());
+
+        // create user with testdb resource
+        UserTO userTO = UserITCase.getUniqueSampleTO("taskBulk@apache.org");
+        userTO.getResources().add(RESOURCE_NAME_TESTDB);
+        createUser(userTO);
+
+        List<PropagationTaskTO> after = new ArrayList<>(
+                taskService.<PropagationTaskTO>list(new TaskQuery.Builder().type(TaskType.PROPAGATION).build()).
+                getResult());
+        after.removeAll(before.getResult());
+        assertFalse(after.isEmpty());
+
+        BulkAction bulkAction = new BulkAction();
+        bulkAction.setType(BulkAction.Type.DELETE);
+
+        for (PropagationTaskTO taskTO : after) {
+            bulkAction.getTargets().add(String.valueOf(taskTO.getKey()));
+        }
+
+        taskService.bulk(bulkAction);
+
+        assertFalse(taskService.list(new TaskQuery.Builder().type(TaskType.PROPAGATION).build()).getResult().
+                containsAll(after));
+    }
+
+    @Test
+    public void issueSYNCOPE741() {
+        for (int i = 0; i < 3; i++) {
+            taskService.execute(new ExecuteQuery.Builder().key(1L).build());
+            taskService.execute(new ExecuteQuery.Builder().key(2L).build());
+        }
+        try {
+            Thread.sleep(3000);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+
+        // check list
+        PagedResult<AbstractTaskTO> tasks = taskService.list(
+                new TaskQuery.Builder().type(TaskType.PROPAGATION).page(1).size(2).details(false).build());
+        for (AbstractTaskTO item : tasks.getResult()) {
+            assertTrue(item.getExecutions().isEmpty());
+        }
+
+        tasks = taskService.list(
+                new TaskQuery.Builder().type(TaskType.PROPAGATION).page(1).size(2).details(true).build());
+        for (AbstractTaskTO item : tasks.getResult()) {
+            assertFalse(item.getExecutions().isEmpty());
+        }
+
+        // check read
+        PropagationTaskTO task = taskService.read(1L, false);
+        assertNotNull(task);
+        assertEquals(1L, task.getKey(), 0);
+        assertTrue(task.getExecutions().isEmpty());
+
+        task = taskService.read(1L, true);
+        assertNotNull(task);
+        assertEquals(1L, task.getKey(), 0);
+        assertFalse(task.getExecutions().isEmpty());
+
+        // check list executions
+        PagedResult<TaskExecTO> execs = taskService.listExecutions(
+                new TaskExecQuery.Builder().key(1L).page(1).size(2).build());
+        assertTrue(execs.getTotalCount() >= execs.getResult().size());
+    }
+}