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:47 UTC

[16/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/PushTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskITCase.java
new file mode 100644
index 0000000..c766d0b
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskITCase.java
@@ -0,0 +1,384 @@
+/*
+ * 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.HashSet;
+import java.util.Set;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
+import org.apache.syncope.common.lib.to.MappingItemTO;
+import org.apache.syncope.common.lib.to.MappingTO;
+import org.apache.syncope.common.lib.to.NotificationTO;
+import org.apache.syncope.common.lib.to.NotificationTaskTO;
+import org.apache.syncope.common.lib.to.PagedResult;
+import org.apache.syncope.common.lib.to.PlainSchemaTO;
+import org.apache.syncope.common.lib.to.PushTaskTO;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.ProvisionTO;
+import org.apache.syncope.common.lib.to.TaskExecTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.common.lib.types.MatchingRule;
+import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.common.lib.types.TraceLevel;
+import org.apache.syncope.common.lib.types.UnmatchingRule;
+import org.apache.syncope.common.rest.api.beans.TaskQuery;
+import org.apache.syncope.common.rest.api.service.NotificationService;
+import org.apache.syncope.common.rest.api.service.ResourceService;
+import org.apache.syncope.common.rest.api.service.TaskService;
+import org.identityconnectors.framework.common.objects.ObjectClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class PushTaskITCase extends AbstractTaskITCase {
+
+    @Test
+    public void getPushActionsClasses() {
+        Set<String> actions = syncopeService.info().getPushActions();
+        assertNotNull(actions);
+    }
+
+    @Test
+    public void read() {
+        PushTaskTO pushTaskTO = taskService.<PushTaskTO>read(17L, true);
+        assertEquals(UnmatchingRule.ASSIGN, pushTaskTO.getUnmatchingRule());
+        assertEquals(MatchingRule.UPDATE, pushTaskTO.getMatchingRule());
+    }
+
+    @Test
+    public void list() {
+        PagedResult<PushTaskTO> tasks = taskService.list(new TaskQuery.Builder().type(TaskType.PUSH).build());
+        assertFalse(tasks.getResult().isEmpty());
+        for (AbstractTaskTO task : tasks.getResult()) {
+            if (!(task instanceof PushTaskTO)) {
+                fail();
+            }
+        }
+    }
+
+    @Test
+    public void createPushTask() {
+        PushTaskTO task = new PushTaskTO();
+        task.setName("Test create Push");
+        task.setResource(RESOURCE_NAME_WS2);
+        task.getFilters().put(AnyTypeKind.USER.name(),
+                SyncopeClient.getUserSearchConditionBuilder().hasNotResources(RESOURCE_NAME_TESTDB2).query());
+        task.getFilters().put(AnyTypeKind.GROUP.name(),
+                SyncopeClient.getGroupSearchConditionBuilder().isNotNull("cool").query());
+        task.setMatchingRule(MatchingRule.LINK);
+
+        final Response response = taskService.create(task);
+        final PushTaskTO actual = getObject(response.getLocation(), TaskService.class, PushTaskTO.class);
+        assertNotNull(actual);
+
+        task = taskService.read(actual.getKey(), true);
+        assertNotNull(task);
+        assertEquals(task.getKey(), actual.getKey());
+        assertEquals(task.getJobDelegateClassName(), actual.getJobDelegateClassName());
+        assertEquals(task.getFilters().get(AnyTypeKind.USER.name()),
+                actual.getFilters().get(AnyTypeKind.USER.name()));
+        assertEquals(task.getFilters().get(AnyTypeKind.GROUP.name()),
+                actual.getFilters().get(AnyTypeKind.GROUP.name()));
+        assertEquals(UnmatchingRule.ASSIGN, actual.getUnmatchingRule());
+        assertEquals(MatchingRule.LINK, actual.getMatchingRule());
+    }
+
+    @Test
+    public void pushMatchingUnmatchingGroups() {
+        assertFalse(groupService.read(3L).getResources().contains(RESOURCE_NAME_LDAP));
+
+        execProvisioningTask(taskService, 23L, 50, false);
+
+        assertNotNull(resourceService.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), 3L));
+        assertTrue(groupService.read(3L).getResources().contains(RESOURCE_NAME_LDAP));
+
+        execProvisioningTask(taskService, 23L, 50, false);
+
+        assertNotNull(resourceService.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), 3L));
+        assertFalse(groupService.read(3L).getResources().contains(RESOURCE_NAME_LDAP));
+    }
+
+    @Test
+    public void pushUnmatchingUsers() throws Exception {
+        assertFalse(userService.read(2L).getResources().contains(RESOURCE_NAME_TESTDB2));
+        assertFalse(userService.read(3L).getResources().contains(RESOURCE_NAME_TESTDB2));
+        assertFalse(userService.read(4L).getResources().contains(RESOURCE_NAME_TESTDB2));
+        assertTrue(userService.read(5L).getResources().contains(RESOURCE_NAME_TESTDB2));
+
+        final JdbcTemplate jdbcTemplate = new JdbcTemplate(testDataSource);
+        assertEquals(0, jdbcTemplate.queryForList("SELECT ID FROM test2 WHERE ID='puccini'").size());
+
+        // ------------------------------------------
+        // Unmatching --> Assign --> dryRuyn
+        // ------------------------------------------
+        execProvisioningTask(taskService, 13L, 50, true);
+        assertEquals(0, jdbcTemplate.queryForList("SELECT ID FROM test2 WHERE ID='vivaldi'").size());
+        assertFalse(userService.read(3L).getResources().contains(RESOURCE_NAME_TESTDB2));
+        // ------------------------------------------
+
+        Set<Long> pushTaskIds = new HashSet<>();
+        pushTaskIds.add(13L);
+        pushTaskIds.add(14L);
+        pushTaskIds.add(15L);
+        pushTaskIds.add(16L);
+        execProvisioningTasks(taskService, pushTaskIds, 50, false);
+
+        // ------------------------------------------
+        // Unatching --> Ignore
+        // ------------------------------------------
+        assertEquals(1, jdbcTemplate.queryForList("SELECT ID FROM test2 WHERE ID='verdi'").size());
+        assertFalse(userService.read(2L).getResources().contains(RESOURCE_NAME_TESTDB2));
+        // ------------------------------------------
+
+        // ------------------------------------------
+        // Unmatching --> Assign
+        // ------------------------------------------
+        assertEquals(1, jdbcTemplate.queryForList("SELECT ID FROM test2 WHERE ID='vivaldi'").size());
+        assertTrue(userService.read(3L).getResources().contains(RESOURCE_NAME_TESTDB2));
+        jdbcTemplate.execute("DELETE FROM test2 WHERE ID='vivaldi'");
+        // ------------------------------------------
+
+        // ------------------------------------------
+        // Unmatching --> Provision
+        // ------------------------------------------
+        assertEquals(1, jdbcTemplate.queryForList("SELECT ID FROM test2 WHERE ID='bellini'").size());
+        assertFalse(userService.read(4L).getResources().contains(RESOURCE_NAME_TESTDB2));
+        jdbcTemplate.execute("DELETE FROM test2 WHERE ID='bellini'");
+        // ------------------------------------------
+
+        // ------------------------------------------
+        // Unmatching --> Unlink
+        // ------------------------------------------
+        assertEquals(0, jdbcTemplate.queryForList("SELECT ID FROM test2 WHERE ID='puccini'").size());
+        assertFalse(userService.read(5L).getResources().contains(RESOURCE_NAME_TESTDB2));
+        // ------------------------------------------
+    }
+
+    @Test
+    public void pushMatchingUser() throws Exception {
+        assertTrue(userService.read(1L).getResources().contains(RESOURCE_NAME_TESTDB2));
+        assertFalse(userService.read(2L).getResources().contains(RESOURCE_NAME_TESTDB2));
+
+        JdbcTemplate jdbcTemplate = new JdbcTemplate(testDataSource);
+        assertEquals(1, jdbcTemplate.queryForList("SELECT ID FROM test2 WHERE ID='verdi'").size());
+        assertEquals(1, jdbcTemplate.queryForList("SELECT ID FROM test2 WHERE ID='rossini'").size());
+
+        // ------------------------------------------
+        // Matching --> Deprovision --> dryRuyn
+        // ------------------------------------------
+        execProvisioningTask(taskService, 19L, 50, true);
+        assertTrue(userService.read(1L).getResources().contains(RESOURCE_NAME_TESTDB2));
+        assertEquals(1, jdbcTemplate.queryForList("SELECT ID FROM test2 WHERE ID='rossini'").size());
+        // ------------------------------------------
+
+        Set<Long> pushTaskKeys = new HashSet<>();
+        pushTaskKeys.add(18L);
+        pushTaskKeys.add(19L);
+        pushTaskKeys.add(16L);
+
+        execProvisioningTasks(taskService, pushTaskKeys, 50, false);
+
+        // ------------------------------------------
+        // Matching --> Deprovision && Ignore
+        // ------------------------------------------
+        assertFalse(userService.read(2L).getResources().contains(RESOURCE_NAME_TESTDB2));
+        // DELETE Capability not available ....
+        assertEquals(1, jdbcTemplate.queryForList("SELECT ID FROM test2 WHERE ID='verdi'").size());
+        // ------------------------------------------
+
+        // ------------------------------------------
+        // Matching --> Unassign
+        // ------------------------------------------
+        assertFalse(userService.read(1L).getResources().contains(RESOURCE_NAME_TESTDB2));
+        // DELETE Capability not available ....
+        assertEquals(1, jdbcTemplate.queryForList("SELECT ID FROM test2 WHERE ID='rossini'").size());
+        // ------------------------------------------
+
+        // ------------------------------------------
+        // Matching --> Link
+        // ------------------------------------------
+        execProvisioningTask(taskService, 20L, 50, false);
+        assertTrue(userService.read(2L).getResources().contains(RESOURCE_NAME_TESTDB2));
+        assertEquals(1, jdbcTemplate.queryForList("SELECT ID FROM test2 WHERE ID='verdi'").size());
+        // ------------------------------------------
+
+        pushTaskKeys.clear();
+        pushTaskKeys.add(21L);
+        pushTaskKeys.add(22L);
+
+        execProvisioningTasks(taskService, pushTaskKeys, 50, false);
+
+        // ------------------------------------------
+        // Matching --> Unlink && Update
+        // ------------------------------------------
+        assertFalse(userService.read(2L).getResources().contains(RESOURCE_NAME_TESTDB2));
+        assertEquals(1, jdbcTemplate.queryForList("SELECT ID FROM test2 WHERE ID='verdi'").size());
+        // ------------------------------------------
+    }
+
+    @Test
+    public void issueSYNCOPE598() {
+        // create a new group schema
+        PlainSchemaTO schemaTO = new PlainSchemaTO();
+        schemaTO.setKey("LDAPGroupName" + getUUIDString());
+        schemaTO.setType(AttrSchemaType.String);
+        schemaTO.setMandatoryCondition("true");
+
+        schemaTO = createSchema(SchemaType.PLAIN, schemaTO);
+        assertNotNull(schemaTO);
+
+        AnyTypeClassTO typeClass = new AnyTypeClassTO();
+        typeClass.setKey("SYNCOPE-598");
+        typeClass.getPlainSchemas().add(schemaTO.getKey());
+        anyTypeClassService.create(typeClass);
+
+        // create a new sample group
+        GroupTO groupTO = new GroupTO();
+        groupTO.setName("all" + getUUIDString());
+        groupTO.setRealm("/even");
+        groupTO.getAuxClasses().add(typeClass.getKey());
+
+        groupTO.getPlainAttrs().add(attrTO(schemaTO.getKey(), "all"));
+
+        groupTO = createGroup(groupTO).getAny();
+        assertNotNull(groupTO);
+
+        String resourceName = "resource-ldap-grouponly";
+        ResourceTO newResourceTO = null;
+
+        try {
+            // Create resource ad-hoc
+            ResourceTO resourceTO = new ResourceTO();
+            resourceTO.setKey(resourceName);
+            resourceTO.setConnector(105L);
+
+            ProvisionTO provisionTO = new ProvisionTO();
+            provisionTO.setAnyType(AnyTypeKind.GROUP.name());
+            provisionTO.setObjectClass(ObjectClass.GROUP_NAME);
+            resourceTO.getProvisions().add(provisionTO);
+
+            MappingTO mapping = new MappingTO();
+            provisionTO.setMapping(mapping);
+
+            MappingItemTO item = new MappingItemTO();
+            item.setIntMappingType(IntMappingType.GroupPlainSchema);
+            item.setExtAttrName("cn");
+            item.setIntAttrName(schemaTO.getKey());
+            item.setConnObjectKey(true);
+            item.setPurpose(MappingPurpose.BOTH);
+            mapping.setConnObjectKeyItem(item);
+
+            mapping.setConnObjectLink("'cn=' + " + schemaTO.getKey() + " + ',ou=groups,o=isp'");
+
+            Response response = resourceService.create(resourceTO);
+            newResourceTO = getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
+            assertNotNull(newResourceTO);
+            assertNull(newResourceTO.getProvision(AnyTypeKind.USER.name()));
+            assertNotNull(newResourceTO.getProvision(AnyTypeKind.GROUP.name()).getMapping());
+
+            // create push task ad-hoc
+            PushTaskTO task = new PushTaskTO();
+            task.setName("issueSYNCOPE598");
+            task.setActive(true);
+            task.setResource(resourceName);
+            task.setPerformCreate(true);
+            task.setPerformDelete(true);
+            task.setPerformUpdate(true);
+            task.setUnmatchingRule(UnmatchingRule.ASSIGN);
+            task.setMatchingRule(MatchingRule.UPDATE);
+            task.getFilters().put(AnyTypeKind.GROUP.name(),
+                    SyncopeClient.getGroupSearchConditionBuilder().is("name").equalTo(groupTO.getName()).query());
+
+            response = taskService.create(task);
+            PushTaskTO push = getObject(response.getLocation(), TaskService.class, PushTaskTO.class);
+            assertNotNull(push);
+
+            // execute the new task
+            TaskExecTO pushExec = execProvisioningTask(taskService, push.getKey(), 50, false);
+            assertEquals(PropagationTaskExecStatus.SUCCESS, PropagationTaskExecStatus.valueOf(pushExec.getStatus()));
+        } finally {
+            groupService.delete(groupTO.getKey());
+            if (newResourceTO != null) {
+                resourceService.delete(resourceName);
+            }
+        }
+    }
+
+    @Test
+    public void issueSYNCOPE648() {
+        // 1. Create Push Task
+        PushTaskTO task = new PushTaskTO();
+        task.setName("Test create Push");
+        task.setActive(true);
+        task.setResource(RESOURCE_NAME_LDAP);
+        task.getFilters().put(AnyTypeKind.USER.name(),
+                SyncopeClient.getUserSearchConditionBuilder().is("username").equalTo("_NO_ONE_").query());
+        task.getFilters().put(AnyTypeKind.GROUP.name(),
+                SyncopeClient.getGroupSearchConditionBuilder().is("name").equalTo("citizen").query());
+        task.setMatchingRule(MatchingRule.IGNORE);
+        task.setUnmatchingRule(UnmatchingRule.IGNORE);
+
+        Response response = taskService.create(task);
+        PushTaskTO actual = getObject(response.getLocation(), TaskService.class, PushTaskTO.class);
+        assertNotNull(actual);
+
+        // 2. Create notification
+        NotificationTO notification = new NotificationTO();
+        notification.setTraceLevel(TraceLevel.FAILURES);
+        notification.getEvents().add("[PushTask]:[group]:[resource-ldap]:[matchingrule_ignore]:[SUCCESS]");
+        notification.getEvents().add("[PushTask]:[group]:[resource-ldap]:[unmatchingrule_ignore]:[SUCCESS]");
+
+        notification.getStaticRecipients().add("issueyncope648@syncope.apache.org");
+        notification.setSelfAsRecipient(false);
+        notification.setRecipientAttrName("email");
+        notification.setRecipientAttrType(IntMappingType.UserPlainSchema);
+
+        notification.setSender("syncope648@syncope.apache.org");
+        String subject = "Test notification";
+        notification.setSubject(subject);
+        notification.setTemplate("optin");
+        notification.setActive(true);
+
+        Response responseNotification = notificationService.create(notification);
+        notification = getObject(responseNotification.getLocation(), NotificationService.class, NotificationTO.class);
+        assertNotNull(notification);
+
+        execProvisioningTask(taskService, actual.getKey(), 50, false);
+
+        NotificationTaskTO taskTO = findNotificationTaskBySender("syncope648@syncope.apache.org");
+        assertNotNull(taskTO);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/17d5d892/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RESTITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RESTITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RESTITCase.java
new file mode 100644
index 0000000..30183fd
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RESTITCase.java
@@ -0,0 +1,148 @@
+/*
+ * 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 static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.io.InputStream;
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.patch.GroupPatch;
+import org.apache.syncope.common.lib.patch.StringReplacePatchItem;
+import org.apache.syncope.common.lib.patch.UserPatch;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.ProvisioningResult;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.rest.api.Preference;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.AnyTypeClassService;
+import org.apache.syncope.common.rest.api.service.GroupService;
+import org.apache.syncope.common.rest.api.service.UserService;
+import org.apache.syncope.fit.AbstractITCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class RESTITCase extends AbstractITCase {
+
+    @Test
+    public void noContent() throws IOException {
+        SyncopeClient noContentclient = clientFactory.create(ADMIN_UNAME, ADMIN_PWD);
+        GroupService noContentService = noContentclient.prefer(GroupService.class, Preference.RETURN_NO_CONTENT);
+
+        GroupTO group = GroupITCase.getSampleTO("noContent");
+
+        Response response = noContentService.create(group);
+        assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());
+        assertEquals(Preference.RETURN_NO_CONTENT.toString(), response.getHeaderString(RESTHeaders.PREFERENCE_APPLIED));
+        assertEquals(StringUtils.EMPTY, org.apache.commons.io.IOUtils.toString((InputStream) response.getEntity()));
+
+        group = getObject(response.getLocation(), GroupService.class, GroupTO.class);
+        assertNotNull(group);
+
+        GroupPatch groupPatch = new GroupPatch();
+        groupPatch.setKey(group.getKey());
+        groupPatch.getPlainAttrs().add(attrAddReplacePatch("badge", "xxxxxxxxxx"));
+
+        response = noContentService.update(groupPatch);
+        assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
+        assertEquals(Preference.RETURN_NO_CONTENT.toString(), response.getHeaderString(RESTHeaders.PREFERENCE_APPLIED));
+        assertEquals(StringUtils.EMPTY, org.apache.commons.io.IOUtils.toString((InputStream) response.getEntity()));
+
+        response = noContentService.delete(group.getKey());
+        assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
+        assertEquals(Preference.RETURN_NO_CONTENT.toString(), response.getHeaderString(RESTHeaders.PREFERENCE_APPLIED));
+        assertEquals(StringUtils.EMPTY, org.apache.commons.io.IOUtils.toString((InputStream) response.getEntity()));
+    }
+
+    @Test
+    public void ifMatch() {
+        UserTO userTO = userService.create(UserITCase.getUniqueSampleTO("ifmatch@syncope.apache.org"), true).
+                readEntity(new GenericType<ProvisioningResult<UserTO>>() {
+                }).getAny();
+        assertNotNull(userTO);
+        assertNotNull(userTO.getKey());
+
+        EntityTag etag = adminClient.getLatestEntityTag(userService);
+        assertNotNull(etag);
+        assertTrue(StringUtils.isNotBlank(etag.getValue()));
+
+        UserPatch userPatch = new UserPatch();
+        userPatch.setKey(userTO.getKey());
+        userPatch.setUsername(new StringReplacePatchItem.Builder().value(userTO.getUsername() + "XX").build());
+        userTO = userService.update(userPatch).readEntity(new GenericType<ProvisioningResult<UserTO>>() {
+        }).getAny();
+        assertTrue(userTO.getUsername().endsWith("XX"));
+        EntityTag etag1 = adminClient.getLatestEntityTag(userService);
+        assertFalse(etag.getValue().equals(etag1.getValue()));
+
+        UserService ifMatchService = adminClient.ifMatch(UserService.class, etag);
+        userPatch.setUsername(new StringReplacePatchItem.Builder().value(userTO.getUsername() + "YY").build());
+        try {
+            ifMatchService.update(userPatch);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.ConcurrentModification, e.getType());
+        }
+
+        userTO = userService.read(userTO.getKey());
+        assertTrue(userTO.getUsername().endsWith("XX"));
+    }
+
+    @Test
+    public void defaultContentType() {
+        // manualy instantiate SyncopeClient so that media type can be set to */*
+        SyncopeClientFactoryBean factory = new SyncopeClientFactoryBean().setAddress(ADDRESS);
+        SyncopeClient client = new SyncopeClient(
+                MediaType.WILDCARD_TYPE,
+                factory.getRestClientFactoryBean(),
+                factory.getExceptionMapper(),
+                ADMIN_UNAME,
+                ADMIN_PWD,
+                false);
+
+        // perform operation
+        AnyTypeClassService service = client.getService(AnyTypeClassService.class);
+        service.list();
+
+        // check that */* was actually sent
+        MultivaluedMap<String, String> requestHeaders = WebClient.client(service).getHeaders();
+        assertEquals(MediaType.WILDCARD, requestHeaders.getFirst(HttpHeaders.ACCEPT));
+
+        // check that application/json was received
+        String contentType = WebClient.client(service).getResponse().getHeaderString(HttpHeaders.CONTENT_TYPE);
+        assertTrue(contentType.startsWith(MediaType.APPLICATION_JSON));
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/17d5d892/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
new file mode 100644
index 0000000..c2b27df
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
@@ -0,0 +1,188 @@
+/*
+ * 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.Response;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.policy.AccountPolicyTO;
+import org.apache.syncope.common.lib.to.RealmTO;
+import org.apache.syncope.common.lib.policy.DefaultAccountRuleConf;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.rest.api.service.RealmService;
+import org.apache.syncope.fit.AbstractITCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class RealmITCase extends AbstractITCase {
+
+    private RealmTO getRealm(final String fullPath) {
+        return IterableUtils.find(realmService.list(fullPath), new Predicate<RealmTO>() {
+
+            @Override
+            public boolean evaluate(final RealmTO object) {
+                return fullPath.equals(object.getFullPath());
+            }
+        });
+    }
+
+    @Test
+    public void list() {
+        List<RealmTO> realms = realmService.list();
+        assertNotNull(realms);
+        assertFalse(realms.isEmpty());
+        for (RealmTO realm : realms) {
+            assertNotNull(realm);
+        }
+
+        try {
+            realmService.list("a name");
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.InvalidPath, e.getType());
+        }
+    }
+
+    @Test
+    public void createUpdate() {
+        final RealmTO realm = new RealmTO();
+        realm.setName("last");
+
+        // 1. create
+        Response response = realmService.create("/even/two", realm);
+        RealmTO[] actuals = getObject(response.getLocation(), RealmService.class, RealmTO[].class);
+        assertNotNull(actuals);
+        assertTrue(actuals.length > 0);
+        RealmTO actual = actuals[0];
+        assertNotNull(actual.getKey());
+        assertEquals("last", actual.getName());
+        assertEquals("/even/two/last", actual.getFullPath());
+        assertEquals(actual.getParent(), getRealm("/even/two").getKey(), 0);
+        assertNull(realm.getAccountPolicy());
+        assertNull(realm.getPasswordPolicy());
+
+        // 2. update setting policies
+        actual.setAccountPolicy(6L);
+        actual.setPasswordPolicy(4L);
+        realmService.update(actual);
+
+        actual = getRealm(actual.getFullPath());
+        assertNotNull(actual.getAccountPolicy());
+        assertNotNull(actual.getPasswordPolicy());
+
+        // 3. update changing parent
+        actual.setParent(getRealm("/odd").getKey());
+        realmService.update(actual);
+
+        actual = getRealm("/odd/last");
+        assertNotNull(actual);
+        assertEquals("/odd/last", actual.getFullPath());
+
+        assertEquals(1, IterableUtils.countMatches(realmService.list(), new Predicate<RealmTO>() {
+
+            @Override
+            public boolean evaluate(final RealmTO object) {
+                return realm.getName().equals(object.getName());
+            }
+        }));
+
+        // 4. create under invalid path
+        try {
+            realmService.create("a name", realm);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.InvalidPath, e.getType());
+        }
+
+        // 5. attempt to create duplicate
+        try {
+            realmService.create("/odd", realm);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.DataIntegrityViolation, e.getType());
+        }
+    }
+
+    @Test
+    public void deletingAccountPolicy() {
+        // 1. create account policy
+        AccountPolicyTO policy = new AccountPolicyTO();
+        policy.setDescription("deletingAccountPolicy");
+
+        DefaultAccountRuleConf ruleConf = new DefaultAccountRuleConf();
+        ruleConf.setMinLength(3);
+        ruleConf.setMaxLength(8);
+        policy.getRuleConfs().add(ruleConf);
+
+        policy = createPolicy(policy);
+        assertNotNull(policy);
+
+        // 2. create realm with policy assigned
+        RealmTO realm = new RealmTO();
+        realm.setName("withppolicy");
+        realm.setAccountPolicy(policy.getKey());
+
+        Response response = realmService.create(SyncopeConstants.ROOT_REALM, realm);
+        RealmTO[] actuals = getObject(response.getLocation(), RealmService.class, RealmTO[].class);
+        assertNotNull(actuals);
+        assertTrue(actuals.length > 0);
+        RealmTO actual = actuals[0];
+        assertEquals(policy.getKey(), actual.getAccountPolicy(), 0);
+
+        // 3. remove policy
+        policyService.delete(policy.getKey());
+
+        // 4. verify
+        actual = getRealm(actual.getFullPath());
+        assertNull(actual.getAccountPolicy());
+    }
+
+    @Test
+    public void delete() {
+        RealmTO realm = new RealmTO();
+        realm.setName("deletable");
+
+        Response response = realmService.create("/even/two", realm);
+        RealmTO[] actuals = getObject(response.getLocation(), RealmService.class, RealmTO[].class);
+        assertNotNull(actuals);
+        assertTrue(actuals.length > 0);
+        RealmTO actual = actuals[0];
+
+        realmService.delete(actual.getFullPath());
+
+        try {
+            realmService.list(actual.getFullPath());
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.NotFound, e.getType());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/17d5d892/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RelationshipTypeITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RelationshipTypeITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RelationshipTypeITCase.java
new file mode 100644
index 0000000..bcf0b23
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RelationshipTypeITCase.java
@@ -0,0 +1,94 @@
+/*
+ * 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.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.RelationshipTypeTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.rest.api.service.RelationshipTypeService;
+import org.apache.syncope.fit.AbstractITCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class RelationshipTypeITCase extends AbstractITCase {
+
+    @Test
+    public void read() {
+        RelationshipTypeTO otherType = relationshipTypeService.read("inclusion");
+        assertNotNull(otherType);
+        assertEquals("inclusion", otherType.getKey());
+    }
+
+    @Test
+    public void list() {
+        List<RelationshipTypeTO> list = relationshipTypeService.list();
+        assertFalse(list.isEmpty());
+    }
+
+    @Test
+    public void crud() {
+        RelationshipTypeTO newType = new RelationshipTypeTO();
+        newType.setKey("new type");
+        newType.setDescription("description");
+
+        Response response = relationshipTypeService.create(newType);
+        assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatusInfo().getStatusCode());
+
+        newType = getObject(response.getLocation(), RelationshipTypeService.class, RelationshipTypeTO.class);
+        assertNotNull(newType);
+        assertEquals("description", newType.getDescription());
+
+        newType.setDescription("new description");
+        relationshipTypeService.update(newType);
+
+        newType = relationshipTypeService.read(newType.getKey());
+        assertNotNull(newType);
+        assertEquals("new description", newType.getDescription());
+
+        relationshipTypeService.delete(newType.getKey());
+
+        try {
+            relationshipTypeService.read(newType.getKey());
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.NotFound, e.getType());
+        }
+    }
+
+    @Test
+    public void createInvalidName() {
+        RelationshipTypeTO newType = new RelationshipTypeTO();
+        newType.setKey("membership");
+        try {
+            relationshipTypeService.create(newType);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.InvalidRelationshipType, e.getType());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/17d5d892/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReportITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReportITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReportITCase.java
new file mode 100644
index 0000000..98ab976
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReportITCase.java
@@ -0,0 +1,303 @@
+/*
+ * 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 static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import org.apache.commons.io.IOUtils;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.report.UserReportletConf;
+import org.apache.syncope.common.lib.to.BulkActionResult;
+import org.apache.syncope.common.lib.to.ReportExecTO;
+import org.apache.syncope.common.lib.to.ReportTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.ReportExecExportFormat;
+import org.apache.syncope.common.lib.types.ReportExecStatus;
+import org.apache.syncope.common.rest.api.beans.BulkExecDeleteQuery;
+import org.apache.syncope.common.rest.api.beans.ExecuteQuery;
+import org.apache.syncope.common.rest.api.service.ReportService;
+import org.apache.syncope.fit.AbstractITCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class ReportITCase extends AbstractITCase {
+
+    private ReportTO createReport(final ReportTO report) {
+        Response response = reportService.create(report);
+        assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatusInfo().getStatusCode());
+        return getObject(response.getLocation(), ReportService.class, ReportTO.class);
+    }
+
+    @Test
+    public void getReportletClasses() {
+        Set<String> reportlets = syncopeService.info().getReportlets();
+        assertNotNull(reportlets);
+        assertFalse(reportlets.isEmpty());
+    }
+
+    @Test
+    public void list() {
+        List<ReportTO> reports = reportService.list();
+        assertNotNull(reports);
+        assertFalse(reports.isEmpty());
+        for (ReportTO report : reports) {
+            assertNotNull(report);
+        }
+    }
+
+    @Test
+    public void read() {
+        ReportTO reportTO = reportService.read(1L);
+
+        assertNotNull(reportTO);
+        assertNotNull(reportTO.getExecutions());
+        assertFalse(reportTO.getExecutions().isEmpty());
+    }
+
+    @Test
+    public void create() {
+        ReportTO report = new ReportTO();
+        report.setName("testReportForCreate" + getUUIDString());
+        report.getReportletConfs().add(new UserReportletConf("first"));
+        report.getReportletConfs().add(new UserReportletConf("second"));
+
+        report = createReport(report);
+        assertNotNull(report);
+
+        ReportTO actual = reportService.read(report.getKey());
+        assertNotNull(actual);
+
+        assertEquals(actual, report);
+    }
+
+    @Test
+    public void update() {
+        ReportTO report = new ReportTO();
+        report.setName("testReportForUpdate" + getUUIDString());
+
+        report.getReportletConfs().add(new UserReportletConf("first"));
+        report.getReportletConfs().add(new UserReportletConf("second"));
+
+        report = createReport(report);
+        assertNotNull(report);
+        assertEquals(2, report.getReportletConfs().size());
+
+        report.getReportletConfs().add(new UserReportletConf("last"));
+
+        reportService.update(report);
+        ReportTO updated = reportService.read(report.getKey());
+        assertNotNull(updated);
+        assertEquals(3, updated.getReportletConfs().size());
+    }
+
+    @Test
+    public void delete() {
+        ReportTO report = new ReportTO();
+        report.setName("testReportForDelete" + getUUIDString());
+        report.getReportletConfs().add(new UserReportletConf("first"));
+        report.getReportletConfs().add(new UserReportletConf("second"));
+
+        report = createReport(report);
+        assertNotNull(report);
+
+        reportService.delete(report.getKey());
+
+        try {
+            reportService.read(report.getKey());
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(Response.Status.NOT_FOUND, e.getType().getResponseStatus());
+        }
+    }
+
+    private Long execute(final Long reportKey) {
+        ReportExecTO execution = reportService.execute(new ExecuteQuery.Builder().key(reportKey).build());
+        assertNotNull(execution);
+
+        int i = 0;
+        int maxit = 50;
+
+        ReportTO reportTO;
+
+        // wait for report execution completion (executions incremented)
+        do {
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException e) {
+            }
+
+            reportTO = reportService.read(reportKey);
+
+            assertNotNull(reportTO);
+            assertNotNull(reportTO.getExecutions());
+
+            i++;
+        } while (reportTO.getExecutions().isEmpty()
+                || (!ReportExecStatus.SUCCESS.name().equals(reportTO.getExecutions().get(0).getStatus()) && i < maxit));
+        assertEquals(ReportExecStatus.SUCCESS.name(), reportTO.getExecutions().get(0).getStatus());
+
+        return reportTO.getExecutions().get(0).getKey();
+    }
+
+    private void checkExport(final Long execId, final ReportExecExportFormat fmt) throws IOException {
+        Response response = reportService.exportExecutionResult(execId, fmt);
+        assertNotNull(response);
+        assertEquals(Response.Status.OK.getStatusCode(), response.getStatusInfo().getStatusCode());
+        assertNotNull(response.getHeaderString(HttpHeaders.CONTENT_DISPOSITION));
+        assertTrue(response.getHeaderString(HttpHeaders.CONTENT_DISPOSITION).
+                endsWith("." + fmt.name().toLowerCase()));
+
+        Object entity = response.getEntity();
+        assertTrue(entity instanceof InputStream);
+        assertFalse(IOUtils.toString((InputStream) entity, SyncopeConstants.DEFAULT_ENCODING).isEmpty());
+    }
+
+    @Test
+    public void executeAndExport() throws IOException {
+        ReportTO reportTO = reportService.read(1L);
+        reportTO.setKey(0L);
+        reportTO.setName("executeAndExport" + getUUIDString());
+        reportTO.setActive(false);
+        reportTO.getExecutions().clear();
+        reportTO = createReport(reportTO);
+        assertNotNull(reportTO);
+
+        try {
+            execute(reportTO.getKey());
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.Scheduling, e.getType());
+            assertTrue(e.getElements().iterator().next().contains("active"));
+        }
+
+        reportTO.setActive(true);
+        reportService.update(reportTO);
+
+        long execId = execute(reportTO.getKey());
+
+        checkExport(execId, ReportExecExportFormat.XML);
+        checkExport(execId, ReportExecExportFormat.HTML);
+        checkExport(execId, ReportExecExportFormat.PDF);
+        checkExport(execId, ReportExecExportFormat.RTF);
+        checkExport(execId, ReportExecExportFormat.CSV);
+    }
+
+    @Test
+    public void deleteExecutions() {
+        Date start = new Date();
+        try {
+            Thread.sleep(1000);
+        } catch (InterruptedException e) {
+        }
+
+        ReportTO reportTO = reportService.read(1L);
+        reportTO.setKey(0L);
+        reportTO.setName("deleteExecutions" + getUUIDString());
+        reportTO.getExecutions().clear();
+        reportTO = createReport(reportTO);
+        assertNotNull(reportTO);
+
+        Long execId = execute(reportTO.getKey());
+        assertNotNull(execId);
+
+        try {
+            Thread.sleep(1000);
+        } catch (InterruptedException e) {
+        }
+        Date end = new Date();
+
+        BulkActionResult result = reportService.deleteExecutions(
+                new BulkExecDeleteQuery.Builder().key(reportTO.getKey()).startedAfter(start).endedBefore(end).build());
+        assertNotNull(result);
+
+        assertEquals(1, result.getResults().size());
+        assertEquals(execId.toString(), result.getResults().keySet().iterator().next());
+        assertEquals(BulkActionResult.Status.SUCCESS, result.getResults().entrySet().iterator().next().getValue());
+    }
+
+    @Test
+    public void issueSYNCOPE43() {
+        ReportTO reportTO = new ReportTO();
+        reportTO.setName("issueSYNCOPE43" + getUUIDString());
+        reportTO.setActive(true);
+        reportTO = createReport(reportTO);
+        assertNotNull(reportTO);
+
+        ReportExecTO execution = reportService.execute(new ExecuteQuery.Builder().key(reportTO.getKey()).build());
+        assertNotNull(execution);
+
+        int maxit = 50;
+        do {
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException e) {
+            }
+
+            reportTO = reportService.read(reportTO.getKey());
+
+            maxit--;
+        } while (reportTO.getExecutions().isEmpty() && maxit > 0);
+
+        assertEquals(1, reportTO.getExecutions().size());
+    }
+
+    @Test
+    public void issueSYNCOPE102() throws IOException {
+        // Create
+        ReportTO reportTO = reportService.read(1L);
+        reportTO.setKey(0L);
+        reportTO.setName("issueSYNCOPE102" + getUUIDString());
+        reportTO = createReport(reportTO);
+        assertNotNull(reportTO);
+
+        // Execute (multiple requests)
+        for (int i = 0; i < 10; i++) {
+            ReportExecTO execution = reportService.execute(new ExecuteQuery.Builder().key(reportTO.getKey()).build());
+            assertNotNull(execution);
+        }
+
+        // Wait for one execution
+        int maxit = 50;
+        do {
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException e) {
+            }
+
+            reportTO = reportService.read(reportTO.getKey());
+
+            maxit--;
+        } while (reportTO.getExecutions().isEmpty() && maxit > 0);
+        assertFalse(reportTO.getExecutions().isEmpty());
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/17d5d892/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
new file mode 100644
index 0000000..e9e50ce
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
@@ -0,0 +1,697 @@
+/*
+ * 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.security.AccessControlException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.ws.rs.core.Response;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Transformer;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.BulkAction;
+import org.apache.syncope.common.lib.to.ConnObjectTO;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.MappingItemTO;
+import org.apache.syncope.common.lib.to.MappingTO;
+import org.apache.syncope.common.lib.to.PagedConnObjectTOResult;
+import org.apache.syncope.common.lib.to.ProvisionTO;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.ConnConfPropSchema;
+import org.apache.syncope.common.lib.types.ConnConfProperty;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.common.rest.api.beans.ConnObjectTOListQuery;
+import org.apache.syncope.common.rest.api.service.ResourceService;
+import org.identityconnectors.framework.common.objects.ObjectClass;
+import org.apache.syncope.fit.AbstractITCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class ResourceITCase extends AbstractITCase {
+
+    private ResourceTO buildResourceTO(final String resourceName) {
+        ResourceTO resourceTO = new ResourceTO();
+
+        resourceTO.setKey(resourceName);
+        resourceTO.setConnector(102L);
+
+        ProvisionTO provisionTO = new ProvisionTO();
+        provisionTO.setAnyType(AnyTypeKind.USER.name());
+        provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
+        resourceTO.getProvisions().add(provisionTO);
+
+        MappingTO mapping = new MappingTO();
+        provisionTO.setMapping(mapping);
+
+        MappingItemTO item = new MappingItemTO();
+        item.setExtAttrName("userId");
+        item.setIntAttrName("userId");
+        item.setIntMappingType(IntMappingType.UserPlainSchema);
+        item.setPurpose(MappingPurpose.BOTH);
+        mapping.add(item);
+
+        item = new MappingItemTO();
+        item.setExtAttrName("username");
+        item.setIntAttrName("fullname");
+        item.setIntMappingType(IntMappingType.UserKey);
+        item.setPurpose(MappingPurpose.BOTH);
+        mapping.setConnObjectKeyItem(item);
+
+        item = new MappingItemTO();
+        item.setExtAttrName("fullname");
+        item.setIntAttrName("cn");
+        item.setIntMappingType(IntMappingType.UserPlainSchema);
+        item.setConnObjectKey(false);
+        item.setPurpose(MappingPurpose.BOTH);
+        mapping.add(item);
+
+        return resourceTO;
+    }
+
+    @Test
+    public void getPropagationActionsClasses() {
+        Set<String> actions = syncopeService.info().getPropagationActions();
+        assertNotNull(actions);
+        assertFalse(actions.isEmpty());
+    }
+
+    @Test
+    public void create() {
+        String resourceName = RESOURCE_NAME_CREATE;
+        ResourceTO resourceTO = buildResourceTO(resourceName);
+
+        Response response = resourceService.create(resourceTO);
+        ResourceTO actual = getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
+        assertNotNull(actual);
+
+        // check for existence
+        actual = resourceService.read(resourceName);
+        assertNotNull(actual);
+    }
+
+    @Test
+    public void createOverridingProps() {
+        String resourceName = "overriding-conn-conf-target-resource-create";
+        ResourceTO resourceTO = new ResourceTO();
+
+        ProvisionTO provisionTO = new ProvisionTO();
+        provisionTO.setAnyType(AnyTypeKind.USER.name());
+        provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
+        resourceTO.getProvisions().add(provisionTO);
+
+        MappingTO mapping = new MappingTO();
+        provisionTO.setMapping(mapping);
+
+        MappingItemTO item = new MappingItemTO();
+        item.setExtAttrName("uid");
+        item.setIntAttrName("userId");
+        item.setIntMappingType(IntMappingType.UserPlainSchema);
+        item.setPurpose(MappingPurpose.BOTH);
+        mapping.add(item);
+
+        item = new MappingItemTO();
+        item.setExtAttrName("username");
+        item.setIntAttrName("fullname");
+        item.setIntMappingType(IntMappingType.UserKey);
+        item.setConnObjectKey(true);
+        item.setPurpose(MappingPurpose.BOTH);
+        mapping.setConnObjectKeyItem(item);
+
+        item = new MappingItemTO();
+        item.setExtAttrName("fullname");
+        item.setIntAttrName("cn");
+        item.setIntMappingType(IntMappingType.UserPlainSchema);
+        item.setConnObjectKey(false);
+        item.setPurpose(MappingPurpose.BOTH);
+        mapping.add(item);
+
+        resourceTO.setKey(resourceName);
+        resourceTO.setConnector(102L);
+
+        ConnConfProperty prop = new ConnConfProperty();
+        ConnConfPropSchema schema = new ConnConfPropSchema();
+        schema.setType("java.lang.String");
+        schema.setName("endpoint");
+        schema.setRequired(true);
+        prop.setSchema(schema);
+        prop.getValues().add("http://invalidurl/");
+
+        Set<ConnConfProperty> connectorConfigurationProperties = new HashSet<>(Arrays.asList(prop));
+        resourceTO.getConfOverride().addAll(connectorConfigurationProperties);
+
+        Response response = resourceService.create(resourceTO);
+        ResourceTO actual = getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
+        assertNotNull(actual);
+
+        // check the existence
+        actual = resourceService.read(resourceName);
+        assertNotNull(actual);
+    }
+
+    @Test
+    public void createWithSingleMappingItem() {
+        String resourceName = RESOURCE_NAME_CREATE_SINGLE;
+        ResourceTO resourceTO = new ResourceTO();
+        resourceTO.setKey(resourceName);
+        resourceTO.setConnector(102L);
+
+        ProvisionTO provisionTO = new ProvisionTO();
+        provisionTO.setAnyType(AnyTypeKind.USER.name());
+        provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
+        resourceTO.getProvisions().add(provisionTO);
+
+        MappingTO mapping = new MappingTO();
+        provisionTO.setMapping(mapping);
+
+        MappingItemTO item = new MappingItemTO();
+        item.setIntMappingType(IntMappingType.UserKey);
+        item.setExtAttrName("userId");
+        item.setConnObjectKey(true);
+        item.setPurpose(MappingPurpose.PROPAGATION);
+        mapping.setConnObjectKeyItem(item);
+
+        provisionTO = new ProvisionTO();
+        provisionTO.setAnyType(AnyTypeKind.GROUP.name());
+        provisionTO.setObjectClass(ObjectClass.GROUP_NAME);
+        resourceTO.getProvisions().add(provisionTO);
+
+        mapping = new MappingTO();
+        provisionTO.setMapping(mapping);
+        item = new MappingItemTO();
+        item.setIntMappingType(IntMappingType.GroupKey);
+        item.setExtAttrName("groupId");
+        item.setConnObjectKey(true);
+        item.setPurpose(MappingPurpose.SYNCHRONIZATION);
+        mapping.setConnObjectKeyItem(item);
+
+        Response response = resourceService.create(resourceTO);
+        ResourceTO actual = getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
+
+        assertNotNull(actual);
+        assertNotNull(actual.getProvision(AnyTypeKind.USER.name()).getMapping());
+        assertNotNull(actual.getProvision(AnyTypeKind.USER.name()).getMapping().getItems());
+        assertNotNull(actual.getProvision(AnyTypeKind.GROUP.name()).getMapping());
+        assertNotNull(actual.getProvision(AnyTypeKind.GROUP.name()).getMapping().getItems());
+        assertEquals(MappingPurpose.SYNCHRONIZATION,
+                actual.getProvision(AnyTypeKind.GROUP.name()).getMapping().getConnObjectKeyItem().getPurpose());
+        assertEquals(MappingPurpose.PROPAGATION,
+                actual.getProvision(AnyTypeKind.USER.name()).getMapping().getConnObjectKeyItem().getPurpose());
+    }
+
+    @Test
+    public void createWithInvalidMapping() {
+        String resourceName = RESOURCE_NAME_CREATE_WRONG;
+        ResourceTO resourceTO = new ResourceTO();
+        resourceTO.setKey(resourceName);
+        resourceTO.setConnector(102L);
+
+        ProvisionTO provisionTO = new ProvisionTO();
+        provisionTO.setAnyType(AnyTypeKind.USER.name());
+        provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
+        resourceTO.getProvisions().add(provisionTO);
+
+        MappingTO mapping = new MappingTO();
+        provisionTO.setMapping(mapping);
+
+        MappingItemTO item = new MappingItemTO();
+        item.setIntMappingType(IntMappingType.UserKey);
+        item.setExtAttrName("userId");
+        item.setConnObjectKey(true);
+        mapping.setConnObjectKeyItem(item);
+
+        item = new MappingItemTO();
+        item.setIntMappingType(IntMappingType.UserPlainSchema);
+        item.setExtAttrName("email");
+        // missing intAttrName ...
+        mapping.add(item);
+
+        try {
+            createResource(resourceTO);
+            fail("Create should not have worked");
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.RequiredValuesMissing, e.getType());
+            assertEquals("intAttrName", e.getElements().iterator().next());
+        }
+    }
+
+    @Test(expected = SyncopeClientException.class)
+    public void createWithoutExtAttr() {
+        String resourceName = RESOURCE_NAME_CREATE_WRONG;
+        ResourceTO resourceTO = new ResourceTO();
+        resourceTO.setKey(resourceName);
+        resourceTO.setConnector(102L);
+
+        ProvisionTO provisionTO = new ProvisionTO();
+        provisionTO.setAnyType(AnyTypeKind.USER.name());
+        provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
+        resourceTO.getProvisions().add(provisionTO);
+
+        MappingTO mapping = new MappingTO();
+        provisionTO.setMapping(mapping);
+
+        MappingItemTO item = new MappingItemTO();
+        item.setIntMappingType(IntMappingType.UserKey);
+        item.setExtAttrName("userId");
+        item.setConnObjectKey(true);
+        mapping.setConnObjectKeyItem(item);
+
+        item = new MappingItemTO();
+        item.setIntMappingType(IntMappingType.UserPlainSchema);
+        item.setIntAttrName("usernane");
+        // missing extAttrName ...
+        mapping.add(item);
+
+        createResource(resourceTO);
+    }
+
+    @Test
+    public void createWithPasswordPolicy() {
+        String resourceName = "res-with-password-policy";
+        ResourceTO resourceTO = new ResourceTO();
+        resourceTO.setKey(resourceName);
+        resourceTO.setConnector(102L);
+        resourceTO.setPasswordPolicy(4L);
+
+        ProvisionTO provisionTO = new ProvisionTO();
+        provisionTO.setAnyType(AnyTypeKind.USER.name());
+        provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
+        resourceTO.getProvisions().add(provisionTO);
+
+        MappingTO mapping = new MappingTO();
+        provisionTO.setMapping(mapping);
+
+        MappingItemTO item = new MappingItemTO();
+        item.setExtAttrName("userId");
+        item.setIntAttrName("userId");
+        item.setIntMappingType(IntMappingType.UserPlainSchema);
+        item.setConnObjectKey(true);
+        item.setPurpose(MappingPurpose.BOTH);
+        mapping.setConnObjectKeyItem(item);
+
+        Response response = resourceService.create(resourceTO);
+        ResourceTO actual = getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
+        assertNotNull(actual);
+
+        // check the existence
+        actual = resourceService.read(resourceName);
+        assertNotNull(actual);
+        assertNotNull(actual.getPasswordPolicy());
+        assertEquals(4L, (long) actual.getPasswordPolicy());
+    }
+
+    @Test
+    public void updateWithException() {
+        try {
+            ResourceTO resourceTO = new ResourceTO();
+            resourceTO.setKey("resourcenotfound");
+            resourceService.update(resourceTO);
+
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(Response.Status.NOT_FOUND, e.getType().getResponseStatus());
+        }
+    }
+
+    @Test
+    public void update() {
+        String resourceName = RESOURCE_NAME_UPDATE;
+        ResourceTO resourceTO = new ResourceTO();
+        resourceTO.setKey(resourceName);
+        resourceTO.setConnector(101L);
+
+        ProvisionTO provisionTO = new ProvisionTO();
+        provisionTO.setAnyType(AnyTypeKind.USER.name());
+        provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
+        resourceTO.getProvisions().add(provisionTO);
+
+        MappingTO mapping = new MappingTO();
+        provisionTO.setMapping(mapping);
+
+        // Update with an existing and already assigned mapping
+        MappingItemTO item = new MappingItemTO();
+        item.setKey(112L);
+        item.setExtAttrName("test3");
+        item.setIntAttrName("fullname");
+        item.setIntMappingType(IntMappingType.UserPlainSchema);
+        item.setPurpose(MappingPurpose.BOTH);
+        mapping.add(item);
+
+        // Update defining new mappings
+        for (int i = 4; i < 6; i++) {
+            item = new MappingItemTO();
+            item.setExtAttrName("test" + i);
+            item.setIntAttrName("fullname");
+            item.setIntMappingType(IntMappingType.UserPlainSchema);
+            item.setPurpose(MappingPurpose.BOTH);
+            mapping.add(item);
+        }
+        item = new MappingItemTO();
+        item.setExtAttrName("username");
+        item.setIntAttrName("fullname");
+        item.setIntMappingType(IntMappingType.UserKey);
+        item.setConnObjectKey(true);
+        item.setPurpose(MappingPurpose.BOTH);
+        mapping.setConnObjectKeyItem(item);
+
+        resourceService.update(resourceTO);
+        ResourceTO actual = resourceService.read(resourceTO.getKey());
+        assertNotNull(actual);
+
+        // check for existence
+        Collection<MappingItemTO> mapItems = actual.getProvision(AnyTypeKind.USER.name()).getMapping().getItems();
+        assertNotNull(mapItems);
+        assertEquals(4, mapItems.size());
+    }
+
+    @Test
+    public void deleteWithException() {
+        try {
+            resourceService.delete("resourcenotfound");
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(Response.Status.NOT_FOUND, e.getType().getResponseStatus());
+        }
+    }
+
+    @Test
+    public void updateResetSyncToken() {
+        // create resource with sync token
+        String resourceName = RESOURCE_NAME_RESETSYNCTOKEN + getUUIDString();
+        ResourceTO pre = buildResourceTO(resourceName);
+
+        pre.getProvision(AnyTypeKind.USER.name()).setSyncToken("test");
+        resourceService.create(pre);
+
+        pre.getProvision(AnyTypeKind.USER.name()).setSyncToken(null);
+        resourceService.update(pre);
+        ResourceTO actual = resourceService.read(pre.getKey());
+        // check that the synctoken has been reset
+        assertNull(actual.getProvision(AnyTypeKind.USER.name()).getSyncToken());
+    }
+
+    @Test
+    public void delete() {
+        String resourceName = "tobedeleted";
+
+        ResourceTO resource = buildResourceTO(resourceName);
+        Response response = resourceService.create(resource);
+        ResourceTO actual = getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
+        assertNotNull(actual);
+
+        resourceService.delete(resourceName);
+
+        try {
+            resourceService.read(resourceName);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(Response.Status.NOT_FOUND, e.getType().getResponseStatus());
+        }
+    }
+
+    @Test
+    public void list() {
+        List<ResourceTO> actuals = resourceService.list();
+        assertNotNull(actuals);
+        assertFalse(actuals.isEmpty());
+        for (ResourceTO resourceTO : actuals) {
+            assertNotNull(resourceTO);
+        }
+    }
+
+    @Test
+    public void read() {
+        ResourceTO resource = resourceService.read(RESOURCE_NAME_DBVIRATTR);
+        assertNotNull(resource);
+
+        ProvisionTO provision = resource.getProvision(AnyTypeKind.USER.name());
+        assertNotNull(provision);
+        assertFalse(provision.getMapping().getItems().isEmpty());
+        assertFalse(provision.getMapping().getLinkingItems().isEmpty());
+    }
+
+    @Test
+    public void issueSYNCOPE323() {
+        ResourceTO actual = resourceService.read(RESOURCE_NAME_TESTDB);
+        assertNotNull(actual);
+
+        try {
+            createResource(actual);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(Response.Status.CONFLICT, e.getType().getResponseStatus());
+            assertEquals(ClientExceptionType.EntityExists, e.getType());
+        }
+
+        actual.setKey(null);
+        try {
+            createResource(actual);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(Response.Status.BAD_REQUEST, e.getType().getResponseStatus());
+            assertEquals(ClientExceptionType.RequiredValuesMissing, e.getType());
+        }
+    }
+
+    @Test
+    public void bulkAction() {
+        resourceService.create(buildResourceTO("forBulk1"));
+        resourceService.create(buildResourceTO("forBulk2"));
+
+        assertNotNull(resourceService.read("forBulk1"));
+        assertNotNull(resourceService.read("forBulk2"));
+
+        final BulkAction bulkAction = new BulkAction();
+        bulkAction.setType(BulkAction.Type.DELETE);
+
+        bulkAction.getTargets().add(String.valueOf("forBulk1"));
+        bulkAction.getTargets().add(String.valueOf("forBulk2"));
+
+        resourceService.bulk(bulkAction);
+
+        try {
+            resourceService.read("forBulk1");
+            fail();
+        } catch (SyncopeClientException e) {
+        }
+
+        try {
+            resourceService.read("forBulk2");
+            fail();
+        } catch (SyncopeClientException e) {
+        }
+    }
+
+    @Test
+    public void anonymous() {
+        ResourceService unauthenticated = clientFactory.create().getService(ResourceService.class);
+        try {
+            unauthenticated.list();
+            fail();
+        } catch (AccessControlException e) {
+            assertNotNull(e);
+        }
+
+        ResourceService anonymous = clientFactory.create(ANONYMOUS_UNAME, ANONYMOUS_KEY).
+                getService(ResourceService.class);
+        assertFalse(anonymous.list().isEmpty());
+    }
+
+    @Test
+    public void listConnObjects() {
+        List<Long> groupKeys = new ArrayList<>();
+        for (int i = 0; i < 10; i++) {
+            GroupTO group = GroupITCase.getSampleTO("group");
+            group.getResources().add(RESOURCE_NAME_LDAP);
+            group = createGroup(group).getAny();
+            groupKeys.add(group.getKey());
+        }
+
+        int totalRead = 0;
+        Set<String> read = new HashSet<>();
+        try {
+            ConnObjectTOListQuery.Builder builder = new ConnObjectTOListQuery.Builder().size(10);
+            PagedConnObjectTOResult list;
+            do {
+                list = null;
+
+                boolean succeeded = false;
+                // needed because ApacheDS seems to randomly fail when searching with cookie
+                for (int i = 0; i < 5 && !succeeded; i++) {
+                    try {
+                        list = resourceService.listConnObjects(
+                                RESOURCE_NAME_LDAP,
+                                AnyTypeKind.GROUP.name(),
+                                builder.build());
+                        succeeded = true;
+                    } catch (SyncopeClientException e) {
+                        assertEquals(ClientExceptionType.ConnectorException, e.getType());
+                    }
+                }
+                assertNotNull(list);
+
+                totalRead += list.getResult().size();
+                CollectionUtils.collect(list.getResult(), new Transformer<ConnObjectTO, String>() {
+
+                    @Override
+                    public String transform(final ConnObjectTO input) {
+                        return input.getPlainAttrMap().get("__NAME__").getValues().get(0);
+                    }
+                }, read);
+
+                if (list.getPagedResultsCookie() != null) {
+                    builder.pagedResultsCookie(list.getPagedResultsCookie());
+                }
+            } while (list.getPagedResultsCookie() != null);
+
+            assertEquals(totalRead, read.size());
+            assertTrue(totalRead >= 10);
+        } finally {
+            for (Long key : groupKeys) {
+                groupService.delete(key);
+            }
+        }
+    }
+
+    @Test
+    public void issueSYNCOPE360() {
+        final String name = "SYNCOPE360-" + getUUIDString();
+        resourceService.create(buildResourceTO(name));
+
+        ResourceTO resource = resourceService.read(name);
+        assertNotNull(resource);
+        assertNotNull(resource.getProvision(AnyTypeKind.USER.name()).getMapping());
+
+        resource.getProvision(AnyTypeKind.USER.name()).setMapping(null);
+        resourceService.update(resource);
+
+        resource = resourceService.read(name);
+        assertNotNull(resource);
+        assertNull(resource.getProvision(AnyTypeKind.USER.name()).getMapping());
+    }
+
+    @Test
+    public void issueSYNCOPE368() {
+        final String name = "SYNCOPE368-" + getUUIDString();
+
+        ResourceTO resourceTO = new ResourceTO();
+
+        resourceTO.setKey(name);
+        resourceTO.setConnector(105L);
+
+        ProvisionTO provisionTO = new ProvisionTO();
+        provisionTO.setAnyType(AnyTypeKind.GROUP.name());
+        provisionTO.setObjectClass(ObjectClass.GROUP_NAME);
+        resourceTO.getProvisions().add(provisionTO);
+
+        MappingTO mapping = new MappingTO();
+        provisionTO.setMapping(mapping);
+
+        MappingItemTO item = new MappingItemTO();
+        item.setIntMappingType(IntMappingType.GroupName);
+        item.setExtAttrName("cn");
+        item.setPurpose(MappingPurpose.BOTH);
+        mapping.setConnObjectKeyItem(item);
+
+        item = new MappingItemTO();
+        item.setIntMappingType(IntMappingType.GroupOwnerSchema);
+        item.setExtAttrName("owner");
+        item.setPurpose(MappingPurpose.BOTH);
+        mapping.add(item);
+
+        resourceTO = createResource(resourceTO);
+        assertNotNull(resourceTO);
+        assertEquals(2, resourceTO.getProvision(AnyTypeKind.GROUP.name()).getMapping().getItems().size());
+    }
+
+    @Test
+    public void issueSYNCOPE418() {
+        try {
+            resourceService.create(
+                    buildResourceTO("http://schemas.examples.org/security/authorization/organizationUnit"));
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.InvalidExternalResource, e.getType());
+
+            assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidName.name()));
+        }
+    }
+
+    @Test
+    public void issueSYNCOPE493() {
+        // create resource with attribute mapping set to NONE and check its propagation
+        String resourceName = RESOURCE_NAME_CREATE_NONE;
+        ResourceTO resourceTO = new ResourceTO();
+        resourceTO.setKey(resourceName);
+        resourceTO.setConnector(102L);
+
+        ProvisionTO provisionTO = new ProvisionTO();
+        provisionTO.setAnyType(AnyTypeKind.USER.name());
+        provisionTO.setObjectClass(ObjectClass.ACCOUNT_NAME);
+        resourceTO.getProvisions().add(provisionTO);
+
+        MappingTO mapping = new MappingTO();
+        provisionTO.setMapping(mapping);
+
+        MappingItemTO item = new MappingItemTO();
+        item.setIntMappingType(IntMappingType.UserKey);
+        item.setExtAttrName("userId");
+        item.setConnObjectKey(true);
+        item.setPurpose(MappingPurpose.PROPAGATION);
+        mapping.setConnObjectKeyItem(item);
+
+        MappingItemTO item2 = new MappingItemTO();
+        item2.setIntMappingType(IntMappingType.UserPlainSchema);
+        item2.setConnObjectKey(false);
+        item2.setIntAttrName("gender");
+        item2.setExtAttrName("gender");
+        item2.setPurpose(MappingPurpose.NONE);
+        mapping.add(item2);
+
+        Response response = resourceService.create(resourceTO);
+        ResourceTO actual = getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
+
+        assertNotNull(actual);
+        assertNotNull(actual.getProvision(AnyTypeKind.USER.name()).getMapping());
+        assertNotNull(actual.getProvision(AnyTypeKind.USER.name()).getMapping().getItems());
+        assertEquals(MappingPurpose.PROPAGATION,
+                actual.getProvision(AnyTypeKind.USER.name()).getMapping().getConnObjectKeyItem().getPurpose());
+        for (MappingItemTO itemTO : actual.getProvision(AnyTypeKind.USER.name()).getMapping().getItems()) {
+            if ("gender".equals(itemTO.getIntAttrName())) {
+                assertEquals(MappingPurpose.NONE, itemTO.getPurpose());
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/17d5d892/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RoleITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RoleITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RoleITCase.java
new file mode 100644
index 0000000..19adfd3
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RoleITCase.java
@@ -0,0 +1,143 @@
+/*
+ * 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 static org.junit.Assert.fail;
+
+import java.util.List;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.StandardEntitlement;
+import org.apache.syncope.common.rest.api.service.RoleService;
+import org.apache.syncope.fit.AbstractITCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class RoleITCase extends AbstractITCase {
+
+    public static RoleTO getSampleRoleTO(final String name) {
+        RoleTO role = new RoleTO();
+        role.setKey(name + getUUIDString());
+        role.getRealms().add("/even");
+        role.getEntitlements().add(StandardEntitlement.LOG_SET_LEVEL);
+
+        return role;
+    }
+
+    @Test
+    public void list() {
+        List<RoleTO> roleTOs = roleService.list();
+        assertNotNull(roleTOs);
+        assertFalse(roleTOs.isEmpty());
+        for (RoleTO instance : roleTOs) {
+            assertNotNull(instance);
+        }
+    }
+
+    @Test
+    public void read() {
+        RoleTO roleTO = roleService.read("Search for realm evenTwo");
+        assertNotNull(roleTO);
+        assertTrue(roleTO.getEntitlements().contains(StandardEntitlement.USER_READ));
+    }
+
+    @Test
+    public void create() {
+        RoleTO role = new RoleTO();
+        role.getRealms().add(SyncopeConstants.ROOT_REALM);
+        role.getRealms().add("/even/two");
+        role.getEntitlements().add(StandardEntitlement.LOG_LIST);
+        role.getEntitlements().add(StandardEntitlement.LOG_SET_LEVEL);
+
+        try {
+            createRole(role);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.InvalidRole, e.getType());
+        }
+
+        role.setKey("new" + getUUIDString());
+        role = createRole(role);
+        assertNotNull(role);
+    }
+
+    @Test
+    public void update() {
+        RoleTO role = getSampleRoleTO("update");
+        role = createRole(role);
+        assertNotNull(role);
+
+        assertFalse(role.getEntitlements().contains(StandardEntitlement.WORKFLOW_TASK_LIST));
+        assertFalse(role.getRealms().contains("/even/two"));
+
+        role.getEntitlements().add(StandardEntitlement.WORKFLOW_TASK_LIST);
+        role.getRealms().add("/even/two");
+
+        roleService.update(role);
+
+        role = roleService.read(role.getKey());
+        assertTrue(role.getEntitlements().contains(StandardEntitlement.WORKFLOW_TASK_LIST));
+        assertTrue(role.getRealms().contains("/even/two"));
+    }
+
+    @Test
+    public void delete() {
+        RoleTO role = getSampleRoleTO("delete");
+        Response response = roleService.create(role);
+
+        RoleTO actual = getObject(response.getLocation(), RoleService.class, RoleTO.class);
+        assertNotNull(actual);
+
+        roleService.delete(actual.getKey());
+
+        try {
+            roleService.read(actual.getKey());
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.NotFound, e.getType());
+        }
+    }
+
+    @Test
+    public void dynMembership() {
+        assertTrue(userService.read(4L).getDynRoles().isEmpty());
+
+        RoleTO role = getSampleRoleTO("dynMembership");
+        role.setDynMembershipCond("cool==true");
+        Response response = roleService.create(role);
+        role = getObject(response.getLocation(), RoleService.class, RoleTO.class);
+        assertNotNull(role);
+
+        assertTrue(userService.read(4L).getDynRoles().contains(role.getKey()));
+
+        role.setDynMembershipCond("cool==false");
+        roleService.update(role);
+
+        assertTrue(userService.read(4L).getDynGroups().isEmpty());
+    }
+}