/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2014 ForgeRock AS. All Rights Reserved * * The contents of this file are subject to the terms * of the Common Development and Distribution License * (the License). You may not use this file except in * compliance with the License. * * You can obtain a copy of the License at * http://forgerock.org/license/CDDLv1.0.html * See the License for the specific language governing * permission and limitations under the License. * * When distributing Covered Code, include this CDDL * Header Notice in each file and include the License file * at http://forgerock.org/license/CDDLv1.0.html * If applicable, add the following below the CDDL Header, * with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" */ package org.forgerock.openicf.connectors; import static org.fest.assertions.api.Assertions.assertThat; import static org.forgerock.openicf.connectors.RESTTestBase.createConnectorFacade; import static org.mockito.Mockito.*; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.fest.assertions.core.Condition; import org.forgerock.openicf.connectors.scriptedcrest.ScriptedCRESTConnector; import org.forgerock.openicf.connectors.scriptedrest.ScriptedRESTConnector; import org.forgerock.openicf.misc.scriptedcommon.ScriptedConnectorBase; import org.identityconnectors.common.logging.Log; import org.identityconnectors.common.security.GuardedString; import org.identityconnectors.framework.api.ConnectorFacade; import org.identityconnectors.framework.common.objects.Attribute; import org.identityconnectors.framework.common.objects.AttributeBuilder; import org.identityconnectors.framework.common.objects.AttributeUtil; import org.identityconnectors.framework.common.objects.ConnectorObject; import org.identityconnectors.framework.common.objects.Name; import org.identityconnectors.framework.common.objects.ObjectClass; import org.identityconnectors.framework.common.objects.OperationOptionsBuilder; import org.identityconnectors.framework.common.objects.Schema; import org.identityconnectors.framework.common.objects.SyncDelta; import org.identityconnectors.framework.common.objects.SyncDeltaType; import org.identityconnectors.framework.common.objects.SyncResultsHandler; import org.identityconnectors.framework.common.objects.SyncToken; import org.identityconnectors.framework.common.objects.Uid; import org.identityconnectors.framework.common.objects.filter.Filter; import org.identityconnectors.framework.common.objects.filter.FilterBuilder; import org.identityconnectors.framework.impl.api.local.LocalConnectorFacadeImpl; import org.identityconnectors.test.common.TestHelpers; import org.testng.Assert; import org.testng.SkipException; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** * * @author Laszlo Hordos */ public class ScriptedRESTSampleTest { /** * Setup logging for the * {@link org.forgerock.openicf.connectors.ScriptedSQLConnectorTest}. */ private static final Log logger = Log.getLog(ScriptedRESTSampleTest.class); protected static final String REST_TEST_NAME = "REST_SAMPLE"; protected static final String CREST_TEST_NAME = "CREST_SAMPLE"; private ConnectorFacade facadeInstance; @BeforeClass public void setUp() throws Exception { String username = TestHelpers.getProperties(ScriptedConnectorBase.class, getTestName()) .getStringProperty("configuration.username"); if ("__configureme__".equals(username)) { throw new SkipException("REST Sample tests are skipped. Create private configuration!"); } } @Test public void validate() throws Exception { final ConnectorFacade facade = getFacade(); facade.validate(); } @Test public void testTest() throws Exception { final ConnectorFacade facade = getFacade(); facade.test(); } @Test public void testSchema() throws Exception { final ConnectorFacade facade = getFacade(); Schema schema = facade.schema(); Assert.assertEquals(schema.getObjectClassInfo().size(), 2); } @Test public void testAuthenticate() throws Exception { if (CREST_TEST_NAME.equals(getTestName())){ throw new SkipException("CREST Sample does not implement this operation"); } final ConnectorFacade facade = getFacade(); Set<Attribute> createAttributes = createUserAttributes(1, "Bob", "Fleming"); createAttributes.add(AttributeBuilder.build("password", "Passw0rd")); Uid uid = facade.create(ObjectClass.ACCOUNT, createAttributes, null); try { facade.authenticate(ObjectClass.ACCOUNT, "fleming", new GuardedString("Passw0rd" .toCharArray()), null); } finally { if (null != uid) { facade.delete(ObjectClass.ACCOUNT, uid, null); } } } @Test public void testCreateUpdateDeleteUser() throws Exception { final ConnectorFacade facade = getFacade(); Set<Attribute> expectedAttributes = createUserAttributes(1, "John", "Doe"); Set<Attribute> createAttributes = new HashSet<Attribute>(expectedAttributes); createAttributes.add(AttributeBuilder.build("password", "Passw0rd")); Uid uid = facade.create(ObjectClass.ACCOUNT, createAttributes, null); ConnectorObject co = facade.getObject(ObjectClass.ACCOUNT, uid, null); assertThat(AttributeUtil.filterUid(co.getAttributes())).containsAll(expectedAttributes); Filter filter = FilterBuilder.and(FilterBuilder.startsWith(AttributeBuilder.build( "telephoneNumber", "555")), FilterBuilder.equalTo(AttributeBuilder.build( "familyName", "Doe"))); assertThat(TestHelpers.searchToList(facade, ObjectClass.ACCOUNT, filter)).hasSize(1); Set<Attribute> updateAttributes = new HashSet<Attribute>(); for (Attribute attr : expectedAttributes) { if (attr.is("givenName")) { updateAttributes.add(AttributeBuilder.build("givenName", "Johny")); } else { updateAttributes.add(attr); } } uid = facade.update(ObjectClass.ACCOUNT, co.getUid(), updateAttributes, null); co = facade.getObject(ObjectClass.ACCOUNT, uid, null); assertThat(AttributeUtil.filterUid(co.getAttributes())).containsAll(updateAttributes); //Test query-all OperationOptionsBuilder builder = new OperationOptionsBuilder(); builder.setAttributesToGet(Uid.NAME); assertThat(TestHelpers.searchToList(facade, ObjectClass.ACCOUNT, null, builder.build())) .isNotEmpty(); assertThat(TestHelpers.searchToList(facade, ObjectClass.ACCOUNT, null, null)).isNotEmpty(); facade.delete(ObjectClass.ACCOUNT, uid, null); Assert.assertNull(facade.getObject(ObjectClass.ACCOUNT, uid, null)); } @Test(dependsOnMethods = { "testCreateUpdateDeleteUser" }) public void testCreateUpdateDeleteGroup() throws Exception { final ConnectorFacade facade = getFacade(); Set<Attribute> createAttributes = createGroupAttributes("Sample_Test_Group"); Uid uid = facade.create(ObjectClass.GROUP, createAttributes, null); ConnectorObject co = facade.getObject(ObjectClass.GROUP, uid, null); assertThat( TestHelpers.searchToList(facade, ObjectClass.GROUP, FilterBuilder .equalTo(AttributeBuilder.build("displayName", "Sample_Test_Group")))) .hasSize(1); assertThat(AttributeUtil.filterUid(co.getAttributes())).containsAll(createAttributes); Set<Attribute> expectedAttributes = createUserAttributes(1, "Group", "member"); expectedAttributes.add(AttributeBuilder.build("password", "Passw0rd")); Uid memberUid = facade.create(ObjectClass.ACCOUNT, expectedAttributes, null); Set<Attribute> updateAttributes = new HashSet<Attribute>(); for (Attribute attr : createAttributes) { if (attr.is("members")) { Map<String, Object> member = new HashMap<String, Object>(1); member.put("_id", "member"); updateAttributes.add(AttributeBuilder.build("members", member)); } else { updateAttributes.add(attr); } } uid = facade.update(ObjectClass.GROUP, co.getUid(), updateAttributes, null); co = facade.getObject(ObjectClass.GROUP, uid, null); assertThat(AttributeUtil.filterUid(co.getAttributes())).containsAll(updateAttributes); facade.delete(ObjectClass.GROUP, uid, null); Assert.assertNull(facade.getObject(ObjectClass.GROUP, uid, null)); facade.delete(ObjectClass.ACCOUNT, memberUid, null); } @Test(dependsOnMethods = { "testCreateUpdateDeleteGroup" }) public void testSync() throws Exception { final ConnectorFacade facade = getFacade(); SyncToken userToken = facade.getLatestSyncToken(ObjectClass.ACCOUNT); assertThat(Integer.parseInt((String) userToken.getValue())).isGreaterThan(3); SyncToken groupToken = facade.getLatestSyncToken(ObjectClass.GROUP); assertThat(Integer.parseInt((String) groupToken.getValue())).isGreaterThan(3); Set<Attribute> createAttributes = createUserAttributes(1, "John", "Doe"); Uid uid = facade.create(ObjectClass.ACCOUNT, createAttributes, null); final List<SyncDelta> deltas = new LinkedList<SyncDelta>(); facade.sync(ObjectClass.ACCOUNT, new SyncToken(0), new SyncResultsHandler() { public boolean handle(SyncDelta delta) { deltas.add(delta); return true; } }, null); assertThat(deltas).areAtLeast(1, new Condition<SyncDelta>() { public boolean matches(SyncDelta value) { return value.getDeltaType().equals(SyncDeltaType.CREATE); } }).areAtLeast(1, new Condition<SyncDelta>() { public boolean matches(SyncDelta value) { return value.getDeltaType().equals(SyncDeltaType.UPDATE); } }).areAtLeast(1, new Condition<SyncDelta>() { public boolean matches(SyncDelta value) { return value.getDeltaType().equals(SyncDeltaType.DELETE); } }); final SyncResultsHandler handler = mock(SyncResultsHandler.class); when(handler.handle(any(SyncDelta.class))).thenReturn(true); facade.sync(ObjectClass.GROUP, new SyncToken(0), handler, null); verify(handler, atLeast(3)).handle(any(SyncDelta.class)); facade.delete(ObjectClass.ACCOUNT, uid, null); } private Set<Attribute> createUserAttributes(int index, String firstName, String lastName) { Set<Attribute> createAttributes = new HashSet<Attribute>(); createAttributes.add(new Name(lastName.toLowerCase())); createAttributes.add(AttributeBuilder.build("givenName", firstName)); createAttributes.add(AttributeBuilder.build("familyName", lastName)); createAttributes.add(AttributeBuilder.build("displayName", firstName + " " + lastName)); createAttributes.add(AttributeBuilder.build("emailAddress", lastName.toLowerCase() + "@example.com")); createAttributes.add(AttributeBuilder.build("telephoneNumber", "555-1234-" + index)); return createAttributes; } private Set<Attribute> createGroupAttributes(String name) { Set<Attribute> createAttributes = new HashSet<Attribute>(); createAttributes.add(new Name(name.toLowerCase())); createAttributes.add(AttributeBuilder.build("displayName", name.toLowerCase())); return createAttributes; } protected String getTestName(){ return REST_TEST_NAME; } protected ConnectorFacade getFacade() { return getFacade(getTestName()); } protected ConnectorFacade getFacade(String environment) { if (null == facadeInstance) { if (CREST_TEST_NAME.equals(environment)) { facadeInstance = createConnectorFacade(ScriptedCRESTConnector.class, environment); } else { facadeInstance = createConnectorFacade(ScriptedRESTConnector.class, environment); } } return facadeInstance; } @AfterClass public synchronized void afterClass() { ((LocalConnectorFacadeImpl) facadeInstance).dispose(); facadeInstance = null; } }