/* * 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.misc.scriptedcommon; import static org.fest.assertions.api.Assertions.*; import static org.forgerock.openicf.connectors.RESTTestBase.createConnectorFacade; import static org.identityconnectors.framework.common.objects.filter.FilterBuilder.*; import static org.identityconnectors.framework.common.objects.filter.FilterBuilder.not; import java.math.BigDecimal; import java.math.BigInteger; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.MissingResourceException; import java.util.Set; import org.forgerock.openicf.connectors.groovy.ScriptedConnector; import org.identityconnectors.common.CollectionUtil; import org.identityconnectors.common.logging.Log; import org.identityconnectors.common.security.GuardedByteArray; import org.identityconnectors.common.security.GuardedString; import org.identityconnectors.framework.api.ConnectorFacade; import org.identityconnectors.framework.common.exceptions.AlreadyExistsException; import org.identityconnectors.framework.common.exceptions.ConfigurationException; import org.identityconnectors.framework.common.exceptions.ConnectionBrokenException; import org.identityconnectors.framework.common.exceptions.ConnectionFailedException; import org.identityconnectors.framework.common.exceptions.ConnectorException; import org.identityconnectors.framework.common.exceptions.ConnectorIOException; import org.identityconnectors.framework.common.exceptions.ConnectorSecurityException; import org.identityconnectors.framework.common.exceptions.InvalidAttributeValueException; import org.identityconnectors.framework.common.exceptions.InvalidCredentialException; import org.identityconnectors.framework.common.exceptions.InvalidPasswordException; import org.identityconnectors.framework.common.exceptions.OperationTimeoutException; import org.identityconnectors.framework.common.exceptions.PasswordExpiredException; import org.identityconnectors.framework.common.exceptions.PermissionDeniedException; import org.identityconnectors.framework.common.exceptions.PreconditionFailedException; import org.identityconnectors.framework.common.exceptions.PreconditionRequiredException; import org.identityconnectors.framework.common.exceptions.RetryableException; import org.identityconnectors.framework.common.exceptions.UnknownUidException; 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.PredefinedAttributes; import org.identityconnectors.framework.common.objects.ResultsHandler; import org.identityconnectors.framework.common.objects.Schema; import org.identityconnectors.framework.common.objects.ScriptContextBuilder; import org.identityconnectors.framework.common.objects.SearchResult; import org.identityconnectors.framework.common.objects.SortKey; 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.impl.api.local.LocalConnectorFacadeImpl; import org.identityconnectors.test.common.TestHelpers; import org.identityconnectors.test.common.ToListResultsHandler; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import groovy.json.JsonSlurper; public class ScriptedConnectorTest { /** * Setup logging for the {@link ScriptedConnectorTest}. */ private static final Log logger = Log.getLog(ScriptedConnectorTest.class); protected static final String TEST_NAME = "GROOVY"; private static final ObjectClass TEST = new ObjectClass("__TEST__"); private static final ObjectClass SAMPLE = new ObjectClass("__SAMPLE__"); private static final ObjectClass UNKNOWN = new ObjectClass("__UNKNOWN__"); private ConnectorFacade facade; // ======================================================================= // Authenticate Operation Test // ======================================================================= @Test(expectedExceptions = ConnectorSecurityException.class) public void testAuthenticate1() throws Exception { getFacade(TEST_NAME).authenticate(TEST, "TEST1", new GuardedString("Passw0rd".toCharArray()), null); } @Test(expectedExceptions = InvalidCredentialException.class) public void testAuthenticate2() throws Exception { getFacade(TEST_NAME).authenticate(TEST, "TEST2", new GuardedString("Passw0rd".toCharArray()), null); } @Test(expectedExceptions = InvalidPasswordException.class) public void testAuthenticate3() throws Exception { getFacade(TEST_NAME).authenticate(TEST, "TEST3", new GuardedString("Passw0rd".toCharArray()), null); } @Test(expectedExceptions = PermissionDeniedException.class) public void testAuthenticate4() throws Exception { getFacade(TEST_NAME).authenticate(TEST, "TEST4", new GuardedString("Passw0rd".toCharArray()), null); } @Test(expectedExceptions = PasswordExpiredException.class) public void testAuthenticate5() throws Exception { getFacade(TEST_NAME).authenticate(TEST, "TEST5", new GuardedString("Passw0rd".toCharArray()), null); } @Test(expectedExceptions = UnknownUidException.class) public void testAuthenticate7() throws Exception { getFacade(TEST_NAME).authenticate(TEST, "TEST7", new GuardedString("Passw0rd".toCharArray()), null); } @Test(expectedExceptions = UnsupportedOperationException.class) public void testAuthenticateUnsupportedObjectClass() throws Exception { Assert.assertEquals(getFacade(TEST_NAME).authenticate(UNKNOWN, "TESTOK1", new GuardedString("Passw0rd".toCharArray()), null).getUidValue(), "TESTOK1"); } @Test public void testAuthenticateOK() throws Exception { Assert.assertEquals(getFacade(TEST_NAME).authenticate(TEST, "TESTOK1", new GuardedString("Passw0rd".toCharArray()), null).getUidValue(), "TESTOK1"); } @Test public void testAuthenticateEmpty() throws Exception { getFacade(TEST_NAME).authenticate(TEST, "TESTOK2", new GuardedString("".toCharArray()), null); } @Test(expectedExceptions = ConnectorException.class) public void testAuthenticateNotEmpty() throws Exception { getFacade(TEST_NAME).authenticate(TEST, "TESTOK2", new GuardedString("NOT_EMPTY".toCharArray()), null); } // ======================================================================= // Create Operation Test // ======================================================================= @Test public void testCreate() throws Exception { createTestUser("Foo"); } @Test(expectedExceptions = AlreadyExistsException.class) public void testCreate1() throws Exception { Set<Attribute> createAttributes = getTestConnectorObject("TEST1"); ConnectorFacade facade = getFacade(TEST_NAME); facade.create(TEST, createAttributes, null); } @Test(expectedExceptions = InvalidAttributeValueException.class) public void testCreate2() throws Exception { Set<Attribute> createAttributes = getTestConnectorObject("TEST2"); ConnectorFacade facade = getFacade(TEST_NAME); facade.create(TEST, createAttributes, null); } @Test(expectedExceptions = IllegalArgumentException.class) public void testCreate3() throws Exception { Set<Attribute> createAttributes = getTestConnectorObject("TEST3"); ConnectorFacade facade = getFacade(TEST_NAME); facade.create(TEST, createAttributes, null); } @Test(expectedExceptions = RetryableException.class) public void testCreateTest4() throws Exception { Set<Attribute> createAttributes = getTestConnectorObject("TEST4"); ConnectorFacade facade = getFacade(TEST_NAME); facade.create(TEST, createAttributes, null); } @Test public void testCreateTest5() throws Exception { Set<Attribute> createAttributes = getTestConnectorObject("TEST5"); ConnectorFacade facade = getFacade(TEST_NAME); Uid uid = facade.create(TEST, createAttributes, null); Assert.assertEquals(uid.getUidValue(), "TEST5"); } @Test public void testCreateTestRunAs() throws Exception { Set<Attribute> createAttributes = getTestConnectorObject("TEST5"); ConnectorFacade facade = getFacade(TEST_NAME); OperationOptionsBuilder builder = new OperationOptionsBuilder(); builder.setRunAsUser("admin"); builder.setRunWithPassword(new GuardedString("Passw0rd".toCharArray())); Uid uid = facade.create(TEST, createAttributes, builder.build()); Assert.assertEquals(uid.getUidValue(), "TEST5"); } @Test(expectedExceptions = ConnectorSecurityException.class) public void testCreateTestRunAsFailed() throws Exception { Set<Attribute> createAttributes = getTestConnectorObject("TEST5"); ConnectorFacade facade = getFacade(TEST_NAME); OperationOptionsBuilder builder = new OperationOptionsBuilder(); builder.setRunAsUser("admin"); builder.setRunWithPassword(new GuardedString("_FAKE_".toCharArray())); Uid uid = facade.create(TEST, createAttributes, builder.build()); Assert.assertEquals(uid.getUidValue(), "TEST5"); } @Test(expectedExceptions = OperationTimeoutException.class) public void testCreateTimeOut() throws Exception { Set<Attribute> createAttributes = getTestConnectorObject("TIMEOUT"); getFacade(TEST_NAME).create(TEST, createAttributes, null); Assert.fail(); } @Test(expectedExceptions = UnsupportedOperationException.class) public void testCreateUnsupportedObjectClass() throws Exception { Set<Attribute> createAttributes = getTestConnectorObject("TEST5"); getFacade(TEST_NAME).create(UNKNOWN, createAttributes, null); } // ======================================================================= // Delete Operation Test // ======================================================================= @Test(expectedExceptions = UnknownUidException.class) public void testDelete1() throws Exception { ConnectorFacade facade = getFacade(TEST_NAME); facade.delete(TEST, new Uid("TEST1"), null); } @Test(expectedExceptions = PreconditionFailedException.class) public void testDelete4() throws Exception { ConnectorFacade facade = getFacade(TEST_NAME); facade.delete(TEST, new Uid("TEST4"), null); } @Test(expectedExceptions = PreconditionRequiredException.class) public void testDelete5() throws Exception { ConnectorFacade facade = getFacade(TEST_NAME); facade.delete(TEST, new Uid("TEST5"), null); } @Test(expectedExceptions = OperationTimeoutException.class) public void testDeleteTimeOut() throws Exception { getFacade(TEST_NAME).delete(TEST, new Uid("TIMEOUT"), null); Assert.fail(); } @Test(expectedExceptions = ConfigurationException.class) public void testDeleteCEException() throws Exception { getFacade(TEST_NAME).delete(TEST, new Uid("TESTEX_CE"), null); Assert.fail(); } @Test(expectedExceptions = ConnectionBrokenException.class) public void testDeleteCBException() throws Exception { getFacade(TEST_NAME).delete(TEST, new Uid("TESTEX_CB"), null); Assert.fail(); } @Test(expectedExceptions = ConnectionFailedException.class) public void testDeleteCFException() throws Exception { getFacade(TEST_NAME).delete(TEST, new Uid("TESTEX_CF"), null); Assert.fail(); } @Test(expectedExceptions = ConnectorException.class) public void testDeleteCException() throws Exception { getFacade(TEST_NAME).delete(TEST, new Uid("TESTEX_C"), null); Assert.fail(); } @Test(expectedExceptions = ConnectorIOException.class) public void testDeleteCIOException() throws Exception { getFacade(TEST_NAME).delete(TEST, new Uid("TESTEX_CIO"), null); Assert.fail(); } @Test(expectedExceptions = OperationTimeoutException.class) public void testDeleteOTException() throws Exception { getFacade(TEST_NAME).delete(TEST, new Uid("TESTEX_OT"), null); Assert.fail(); } @Test(expectedExceptions = UnsupportedOperationException.class) public void testDeleteUnsupportedObjectClass() throws Exception { getFacade(TEST_NAME).delete(UNKNOWN, new Uid("001"), null); } // ======================================================================= // ResolveUsername Operation Test // ======================================================================= @Test public void testResolveUsername1() throws Exception { ConnectorFacade facade = getFacade(TEST_NAME); Uid uidAfter = facade.resolveUsername(ObjectClass.ACCOUNT, "TESTOK1", null); Assert.assertEquals(uidAfter.getUidValue(), "123"); } @Test(expectedExceptions = UnknownUidException.class) public void testResolveUsername2() throws Exception { ConnectorFacade facade = getFacade(TEST_NAME); facade.resolveUsername(ObjectClass.ACCOUNT, "NON_EXIST", null); } @Test(expectedExceptions = UnsupportedOperationException.class) public void testResolveUsername3() throws Exception { ConnectorFacade facade = getFacade(TEST_NAME); facade.resolveUsername(UNKNOWN, "NON_EXIST", null); } // ======================================================================= // Schema Operation Test // ======================================================================= @Test public void testSchema1() throws Exception { ConnectorFacade facade = getFacade(TEST_NAME); Schema schema = facade.schema(); Assert.assertNotNull(schema.findObjectClassInfo("__TEST__")); } // ======================================================================= // ScriptOnConnector Operation Test // ======================================================================= @Test public void testScriptOnConnector() throws Exception { ConnectorFacade facade = getFacade(TEST_NAME); ScriptContextBuilder builder = new ScriptContextBuilder(); builder.setScriptLanguage("Groovy"); builder.setScriptText("return uid"); Uid uid = new Uid("foo", "12345"); builder.addScriptArgument("uid", uid); Assert.assertEquals(facade.runScriptOnConnector(builder.build(), null), uid); } @Test(expectedExceptions = ConnectorException.class, expectedExceptionsMessageRegExp = "No argument has arrived.") public void testScriptOnConnectorArgFail() throws Exception { ConnectorFacade facade = getFacade(TEST_NAME); ScriptContextBuilder builder = new ScriptContextBuilder(); builder.setScriptLanguage("Groovy"); builder.setScriptText("try{return loginName}catch(MissingPropertyException e){throw new Exception(\"No argument has arrived.\")}"); facade.runScriptOnConnector(builder.build(), null); } // ======================================================================= // ScriptOnResource Operation Test // ======================================================================= @Test public void testScriptOnResource() throws Exception { ConnectorFacade facade = getFacade(TEST_NAME); ScriptContextBuilder builder = new ScriptContextBuilder(); builder.setScriptLanguage("Groovy"); builder.setScriptText("return arg"); builder.addScriptArgument("arg01", true); builder.addScriptArgument("arg02", "String"); assertThat((Map) facade.runScriptOnResource(builder.build(), null)).contains( entry("arg01", true), entry("arg02", "String")); } @Test(expectedExceptions = ConnectorException.class, expectedExceptionsMessageRegExp = "No argument has arrived.") public void testScriptOnResourceArgFail() throws Exception { ConnectorFacade facade = getFacade(TEST_NAME); ScriptContextBuilder builder = new ScriptContextBuilder(); builder.setScriptLanguage("Groovy"); builder.setScriptText("try{return loginName}catch(MissingPropertyException e){throw new Exception(\"No argument has arrived.\")}"); facade.runScriptOnResource(builder.build(), null); } @Test(expectedExceptions = InvalidAttributeValueException.class) public void testScriptOnResourceFail() throws Exception { ConnectorFacade facade = getFacade(TEST_NAME); ScriptContextBuilder builder = new ScriptContextBuilder(); builder.setScriptLanguage("BASH"); builder.setScriptText("test"); Assert.assertEquals(facade.runScriptOnResource(builder.build(), null), true); } // ======================================================================= // Get Operation Test // ======================================================================= @Test public void testGet() throws Exception { ConnectorObject co = getFacade(TEST_NAME).getObject(TEST, new Uid("ANY"), null); Assert.assertEquals(co.getUid().getUidValue(), "ANY"); Assert.assertEquals(co.getName().getNameValue(), "ANY"); Assert.assertEquals(co.getObjectClass(), TEST); assertThat(co.getAttributeByName("attributeString").getValue()).describedAs( "attributeString").containsOnly("retipipiter"); assertThat(co.getAttributeByName("attributeStringMultivalue").getValue()).describedAs( "attributeStringMultivalue").containsOnly("value1", "value2"); assertThat(co.getAttributeByName("attributelongp").getValue()) .describedAs("attributelongp").containsOnly(11l); assertThat(co.getAttributeByName("attributelongpMultivalue").getValue()).describedAs( "attributelongpMultivalue").containsOnly(12l, 13l); assertThat(co.getAttributeByName("attributeLong").getValue()).describedAs("attributeLong") .containsOnly(14l); assertThat(co.getAttributeByName("attributeLongMultivalue").getValue()).describedAs( "attributeLongMultivalue").containsOnly(15l, 16l); assertThat(co.getAttributeByName("attributechar").getValue()).describedAs("attributechar") .containsOnly('a'); assertThat(co.getAttributeByName("attributecharMultivalue").getValue()).describedAs( "attributecharMultivalue").containsOnly('b', 'c'); assertThat(co.getAttributeByName("attributeCharacter").getValue()).describedAs( "attributeCharacter").containsOnly('d'); assertThat(co.getAttributeByName("attributeCharacterMultivalue").getValue()).describedAs( "attributeCharacterMultivalue").containsOnly('e', 'f'); assertThat(co.getAttributeByName("attributedoublep").getValue()).describedAs( "attributedoublep").containsOnly(Double.MIN_NORMAL); assertThat(co.getAttributeByName("attributedoublepMultivalue").getValue()).describedAs( "attributedoublepMultivalue").containsOnly(Double.MIN_VALUE, Double.MAX_VALUE); assertThat(co.getAttributeByName("attributeDouble").getValue()).describedAs( "attributeDouble").containsOnly(17D); assertThat(co.getAttributeByName("attributeDoubleMultivalue").getValue()).describedAs( "attributeDoubleMultivalue").containsOnly(18D, 19D); assertThat(co.getAttributeByName("attributefloatp").getValue()).describedAs( "attributefloatp").containsOnly(20F); assertThat(co.getAttributeByName("attributefloatpMultivalue").getValue()).describedAs( "attributefloatpMultivalue").containsOnly(21F, 22F); assertThat(co.getAttributeByName("attributeFloat").getValue()) .describedAs("attributeFloat").containsOnly(23F); assertThat(co.getAttributeByName("attributeFloatMultivalue").getValue()).describedAs( "attributeFloatMultivalue").containsOnly(24F, 25F); assertThat(co.getAttributeByName("attributeint").getValue()).describedAs("attributeint") .containsOnly(26); assertThat(co.getAttributeByName("attributeintMultivalue").getValue()).describedAs( "attributeintMultivalue").containsOnly(27, 28); assertThat(co.getAttributeByName("attributeInteger").getValue()).describedAs( "attributeInteger").containsOnly(29); assertThat(co.getAttributeByName("attributeIntegerMultivalue").getValue()).describedAs( "attributeIntegerMultivalue").containsOnly(30, 31); assertThat(co.getAttributeByName("attributebooleanp").getValue()).describedAs( "attributebooleanp").containsOnly(true); assertThat(co.getAttributeByName("attributebooleanpMultivalue").getValue()).describedAs( "attributebooleanpMultivalue").containsOnly(true, false); assertThat(co.getAttributeByName("attributeBoolean").getValue()).describedAs( "attributeBoolean").containsOnly(false); assertThat(co.getAttributeByName("attributeBooleanMultivalue").getValue()).describedAs( "attributeBooleanMultivalue").containsOnly(true, false); assertThat(co.getAttributeByName("attributebytep").getValue()) .describedAs("attributebytep").containsOnly((byte) 48); assertThat(co.getAttributeByName("attributebytepMultivalue").getValue()).describedAs( "attributebytepMultivalue").containsOnly((byte) 49, (byte) 50); assertThat(co.getAttributeByName("attributeByte").getValue()).describedAs("attributeByte") .containsOnly((byte) 51); assertThat(co.getAttributeByName("attributeByteMultivalue").getValue()).describedAs( "attributeByteMultivalue").containsOnly((byte) 52, (byte) 53); assertThat(co.getAttributeByName("attributeByteArray").getValue()).describedAs( "attributeByteArray").containsOnly( new Object[] { "array".getBytes(Charset.forName("UTF-8")) }); assertThat(co.getAttributeByName("attributeByteArrayMultivalue").getValue()).describedAs( "attributeByteArrayMultivalue").containsOnly( "item1".getBytes(Charset.forName("UTF-8")), "item2".getBytes(Charset.forName("UTF-8"))); assertThat(co.getAttributeByName("attributeBigDecimal").getValue()).describedAs( "attributeBigDecimal").containsOnly(BigDecimal.ONE); assertThat(co.getAttributeByName("attributeBigDecimalMultivalue").getValue()).describedAs( "attributeBigDecimalMultivalue").containsOnly(BigDecimal.ZERO, BigDecimal.TEN); assertThat(co.getAttributeByName("attributeBigInteger").getValue()).describedAs( "attributeBigInteger").containsOnly(BigInteger.ONE); assertThat(co.getAttributeByName("attributeBigIntegerMultivalue").getValue()).describedAs( "attributeBigIntegerMultivalue").containsOnly(BigInteger.ZERO, BigInteger.TEN); assertThat(co.getAttributeByName("attributeGuardedByteArray").getValue()).describedAs( "attributeGuardedByteArray").containsOnly( new GuardedByteArray("array".getBytes(Charset.forName("UTF-8")))); assertThat(co.getAttributeByName("attributeGuardedByteArrayMultivalue").getValue()) .describedAs("attributeGuardedByteArrayMultivalue").containsOnly( new GuardedByteArray("item1".getBytes(Charset.forName("UTF-8"))), new GuardedByteArray("item2".getBytes(Charset.forName("UTF-8")))); assertThat(co.getAttributeByName("attributeGuardedString").getValue()).describedAs( "attributeGuardedString").containsOnly(new GuardedString("secret".toCharArray())); assertThat(co.getAttributeByName("attributeGuardedStringMultivalue").getValue()) .describedAs("attributeGuardedStringMultivalue").containsOnly( new GuardedString("secret1".toCharArray()), new GuardedString("secret2".toCharArray())); assertThat(co.getAttributeByName("attributeMap").getValue()).describedAs("attributeMap") .containsOnly(createAssertMap(42)); assertThat(co.getAttributeByName("attributeMapMultivalue").getValue()).describedAs( "attributeMapMultivalue").containsOnly(createAssertMap(42), createAssertMap(43)); } private Map<String, Object> createAssertMap(int n) { Map<String, Object> result = new HashMap<String, Object>(6); result.put("string", "String"); result.put("number", n); result.put("trueOrFalse", true); result.put("nullValue", null); result.put("collection", Arrays.asList("item1", "item2")); Map<String, Object> o = new HashMap<String, Object>(2); o.put("key1", "value1"); o.put("key2", "value2"); result.put("object", o); return result; } // ======================================================================= // Search Operation Test // ======================================================================= @Test public void testFilterTranslator() throws Exception { Filter left = startsWith(AttributeBuilder.build("attributeString", "reti")); left = and(left, contains(AttributeBuilder.build("attributeString", "pipi"))); left = and(left, endsWith(AttributeBuilder.build("attributeString", "ter"))); Filter right = lessThanOrEqualTo(AttributeBuilder.build("attributeInteger", 42)); right = or(right, lessThan(AttributeBuilder.build("attributeFloat", Float.MAX_VALUE))); right = or(right, greaterThanOrEqualTo(AttributeBuilder.build("attributeDouble", Double.MIN_VALUE))); right = or(right, greaterThan(AttributeBuilder.build("attributeLong", Long.MIN_VALUE))); right = and(right, not(equalTo(AttributeBuilder.build("attributeByte", new Byte("33"))))); ToListResultsHandler handler = new ToListResultsHandler(); SearchResult result = getFacade(TEST_NAME).search(TEST, and(left, right), handler, null); Assert.assertEquals(handler.getObjects().size(), 10); Assert.assertNotNull(result.getPagedResultsCookie()); Map queryMap = (Map) new JsonSlurper().parseText(result.getPagedResultsCookie()); assertThat(queryMap).contains(entry("operation", "AND")); left = and(left, containsAllValues(AttributeBuilder.build("attributeStringMultivalue", "value1", "value2"))); try { handler = new ToListResultsHandler(); getFacade(TEST_NAME).search(TEST, and(left, right), handler, null); fail("containsAllValues should raise exception if not implemented"); } catch (UnsupportedOperationException e) { /* expected */ Assert.assertEquals(e.getMessage(), "ContainsAllValuesFilter transformation is not supported"); } } @Test public void testSearch() throws Exception { ConnectorObject co = getFacade(TEST_NAME).getObject(SAMPLE, new Uid("1"), null); Assert.assertNotNull(co); } @Test public void testSearchAttributes() throws Exception { OperationOptionsBuilder builder = new OperationOptionsBuilder(); builder.setAttributesToGet("attributeString", "attributeMap"); getFacade(TEST_NAME).search(TEST, null, new ResultsHandler() { public boolean handle(ConnectorObject connectorObject) { Assert.assertEquals(connectorObject.getAttributes().size(), 4); return true; } }, builder.build()); } @Test public void testSearch1() throws Exception { ConnectorFacade search = getFacade(TEST_NAME); List<ConnectorObject> result = TestHelpers.searchToList(search, new ObjectClass("__EMPTY__"), null); Assert.assertTrue(result.isEmpty()); } @Test public void testSearch2() throws Exception { ConnectorFacade search = getFacade(TEST_NAME); for (int i = 0; i < 100; i++) { Set<Attribute> co = getTestConnectorObject(String.format("TESTS%05d", i)); co.add(AttributeBuilder.build("sortKey", i)); search.create(ObjectClass.ACCOUNT, co, null); } OperationOptionsBuilder builder = new OperationOptionsBuilder(); builder.setPageSize(10); builder.setSortKeys(new SortKey("sortKey", false)); SearchResult result = null; final Set<ConnectorObject> resultSet = new HashSet<ConnectorObject>(); int pageIndex = 0; while ((result = search.search(ObjectClass.ACCOUNT, startsWith(AttributeBuilder.build(Name.NAME, "TESTS")), new ResultsHandler() { private int index = 101; public boolean handle(ConnectorObject connectorObject) { Integer idx = AttributeUtil.getIntegerValue(connectorObject .getAttributeByName("sortKey")); Assert.assertTrue(idx < index); index = idx; return resultSet.add(connectorObject); } }, builder.build())).getPagedResultsCookie() != null) { builder = new OperationOptionsBuilder(builder.build()); builder.setPagedResultsCookie(result.getPagedResultsCookie()); Assert.assertEquals(resultSet.size(), 10 * ++pageIndex); } Assert.assertEquals(pageIndex, 9); Assert.assertEquals(resultSet.size(), 100); } @Test(expectedExceptions = UnsupportedOperationException.class) public void testSearchUnsupportedObjectClass() throws Exception { getFacade(TEST_NAME).getObject(UNKNOWN, new Uid("1"), null); } // ======================================================================= // Sync Operation Test // ======================================================================= @DataProvider public Object[][] SyncObjectClassProvider() { return new Object[][] { { ObjectClass.ACCOUNT }, { TEST } }; } @Test(dataProvider = "SyncObjectClassProvider") public void testSyncNull(ObjectClass objectClass) throws Exception { final List<SyncDelta> result = new ArrayList<SyncDelta>(); SyncToken lastToken = getFacade(TEST_NAME).sync(objectClass, new SyncToken(5), new SyncResultsHandler() { public boolean handle(SyncDelta delta) { return result.add(delta); } }, null); Assert.assertEquals(lastToken.getValue(), 10); Assert.assertTrue(result.isEmpty()); } @Test(dataProvider = "SyncObjectClassProvider") public void testSync(ObjectClass objectClass) throws Exception { final ConnectorFacade facade = getFacade(TEST_NAME); final List<SyncDelta> result = new ArrayList<SyncDelta>(); SyncToken lastToken = facade.sync(objectClass, new SyncToken(0), new SyncResultsHandler() { public boolean handle(SyncDelta delta) { return result.add(delta); } }, null); Assert.assertEquals(lastToken.getValue(), 1); Assert.assertEquals(result.size(), 1); SyncDelta delta = result.remove(0); Assert.assertEquals(delta.getDeltaType(), SyncDeltaType.CREATE); Assert.assertEquals(delta.getObject().getAttributes().size(), 44); lastToken = facade.sync(objectClass, lastToken, new SyncResultsHandler() { public boolean handle(SyncDelta delta) { return result.add(delta); } }, null); Assert.assertEquals(lastToken.getValue(), 2); Assert.assertEquals(result.size(), 1); delta = result.remove(0); Assert.assertEquals(delta.getDeltaType(), SyncDeltaType.UPDATE); lastToken = facade.sync(objectClass, lastToken, new SyncResultsHandler() { public boolean handle(SyncDelta delta) { return result.add(delta); } }, null); Assert.assertEquals(lastToken.getValue(), 3); Assert.assertEquals(result.size(), 1); delta = result.remove(0); Assert.assertEquals(delta.getDeltaType(), SyncDeltaType.CREATE_OR_UPDATE); lastToken = facade.sync(objectClass, lastToken, new SyncResultsHandler() { public boolean handle(SyncDelta delta) { return result.add(delta); } }, null); Assert.assertEquals(lastToken.getValue(), 4); Assert.assertEquals(result.size(), 1); delta = result.remove(0); Assert.assertEquals(delta.getDeltaType(), SyncDeltaType.UPDATE); Assert.assertEquals(delta.getPreviousUid().getUidValue(), "001"); lastToken = facade.sync(objectClass, lastToken, new SyncResultsHandler() { public boolean handle(SyncDelta delta) { return result.add(delta); } }, null); Assert.assertEquals(lastToken.getValue(), 5); Assert.assertEquals(result.size(), 1); delta = result.remove(0); Assert.assertEquals(delta.getDeltaType(), SyncDeltaType.DELETE); lastToken = facade.sync(objectClass, lastToken, new SyncResultsHandler() { public boolean handle(SyncDelta delta) { return result.add(delta); } }, null); Assert.assertEquals(lastToken.getValue(), 10); Assert.assertTrue(result.isEmpty()); lastToken = facade.sync(objectClass, lastToken, new SyncResultsHandler() { public boolean handle(SyncDelta delta) { return result.add(delta); } }, null); Assert.assertEquals(lastToken.getValue(), 17); Assert.assertEquals(result.size(), 4); result.clear(); lastToken = facade.sync(ObjectClass.GROUP, new SyncToken(10), new SyncResultsHandler() { public boolean handle(SyncDelta delta) { return result.add(delta); } }, null); Assert.assertEquals(lastToken.getValue(), 16); Assert.assertEquals(result.size(), 3); } @Test public void testSyncAll() throws Exception { final ConnectorFacade facade = getFacade(TEST_NAME); final List<SyncDelta> result = new ArrayList<SyncDelta>(); SyncToken lastToken = facade.sync(ObjectClass.ALL, new SyncToken(0), new SyncResultsHandler() { public boolean handle(SyncDelta delta) { return result.add(delta); } }, null); Assert.assertEquals(lastToken.getValue(), 17); Assert.assertEquals(result.size(), 7); int index = 10; for (SyncDelta delta : result) { Assert.assertEquals(index++, delta.getToken().getValue()); if (((Integer) delta.getToken().getValue()) % 2 == 0) { Assert.assertEquals(delta.getObject().getObjectClass(), ObjectClass.ACCOUNT); } else { Assert.assertEquals(delta.getObject().getObjectClass(), ObjectClass.GROUP); } } } @Test public void testSyncSample() throws Exception { final ConnectorFacade facade = getFacade(TEST_NAME); final List<SyncDelta> result = new ArrayList<SyncDelta>(); SyncToken lastToken = facade.sync(SAMPLE, new SyncToken(0), new SyncResultsHandler() { public boolean handle(SyncDelta delta) { return result.add(delta); } }, null); Assert.assertEquals(lastToken.getValue(), "SAMPLE"); Assert.assertEquals(result.size(), 2); } @Test public void testSyncToken() throws Exception { final ConnectorFacade facade = getFacade(TEST_NAME); SyncToken lastToken = facade.getLatestSyncToken(ObjectClass.ACCOUNT); Assert.assertEquals(lastToken.getValue(), 17); lastToken = facade.getLatestSyncToken(ObjectClass.GROUP); Assert.assertEquals(lastToken.getValue(), 16); lastToken = facade.getLatestSyncToken(ObjectClass.ALL); Assert.assertEquals(lastToken.getValue(), 17); lastToken = facade.getLatestSyncToken(TEST); Assert.assertEquals(lastToken.getValue(), 0); lastToken = facade.getLatestSyncToken(SAMPLE); Assert.assertEquals(lastToken.getValue(), "ANY OBJECT"); } @Test(expectedExceptions = UnsupportedOperationException.class) public void testSyncUnsupportedObjectClass() throws Exception { getFacade(TEST_NAME).sync(UNKNOWN, new SyncToken(0), new SyncResultsHandler() { public boolean handle(SyncDelta delta) { return true; } }, null); } @Test(expectedExceptions = UnsupportedOperationException.class) public void testSyncTokenUnsupportedObjectClass() throws Exception { getFacade(TEST_NAME).getLatestSyncToken(UNKNOWN); } // ======================================================================= // Test Operation Test // ======================================================================= @Test public void validate() throws Exception { final ConnectorFacade facade = getFacade(TEST_NAME); facade.validate(); } @Test public void testCustomConfiguration() throws Exception { createConnectorFacade(ScriptedConnector.class, "TEST").test(); } @Test(expectedExceptions = MissingResourceException.class) public void testTest() throws Exception { ConnectorFacade facade = getFacade(TEST_NAME); facade.test(); } // ======================================================================= // Update Operation Test // ======================================================================= @Test public void testUpdate() throws Exception { Uid uid = createTestUser("TESTOK01"); Set<Attribute> updateAttributes = new HashSet<Attribute>(1); updateAttributes.add(AttributeBuilder.build("email", "foo@example.com")); uid = getFacade(TEST_NAME).update(ObjectClass.ACCOUNT, uid, updateAttributes, null); } @Test(expectedExceptions = PreconditionFailedException.class) public void testUpdateMVCCNOK1() throws Exception { Uid uid = createTestUser("TESTMVCCNOK01"); Set<Attribute> updateAttributes = new HashSet<Attribute>(1); updateAttributes.add(AttributeBuilder.build("email", "foo@example.com")); Assert.assertNotNull(uid.getRevision()); getFacade(TEST_NAME).update(ObjectClass.ACCOUNT, new Uid(uid.getUidValue(), "NOK"), updateAttributes, null); } @Test(expectedExceptions = PreconditionRequiredException.class) public void testUpdateMVCCNOK2() throws Exception { Uid uid = createTestUser("TESTMVCCNOK02"); Set<Attribute> updateAttributes = new HashSet<Attribute>(1); updateAttributes.add(new Name("TEST")); updateAttributes.add(AttributeBuilder.build("email", "foo@example.com")); Assert.assertNotNull(uid.getRevision()); getFacade(TEST_NAME).update(ObjectClass.ACCOUNT, new Uid(uid.getUidValue()), updateAttributes, null); } @Test(expectedExceptions = InvalidAttributeValueException.class, expectedExceptionsMessageRegExp = "Expecting non null value") public void testUpdateFailEmpty() throws Exception { Uid uid = createTestUser("FAIL01"); Set<Attribute> updateAttributes = new HashSet<Attribute>(1); updateAttributes.add(AttributeBuilder.build("email")); uid = getFacade(TEST_NAME).update(ObjectClass.ACCOUNT, uid, updateAttributes, null); fail("Connector operation should fail"); } @Test(expectedExceptions = InvalidAttributeValueException.class, expectedExceptionsMessageRegExp = "Expecting Boolean value") public void testUpdateFailType() throws Exception { Uid uid = createTestUser("FAIL02"); Set<Attribute> updateAttributes = new HashSet<Attribute>(1); updateAttributes.add(AttributeBuilder.build("active", "true")); uid = getFacade(TEST_NAME).update(ObjectClass.ACCOUNT, uid, updateAttributes, null); fail("Connector operation should fail"); } @Test(expectedExceptions = InvalidAttributeValueException.class, expectedExceptionsMessageRegExp = "Expecting single value") public void testUpdateFailMulti() throws Exception { Uid uid = createTestUser("FAIL03"); Set<Attribute> updateAttributes = new HashSet<Attribute>(1); updateAttributes.add(AttributeBuilder.build("userName", "name1", "name2")); uid = getFacade(TEST_NAME).update(ObjectClass.ACCOUNT, uid, updateAttributes, null); fail("Connector operation should fail"); } @Test(expectedExceptions = InvalidAttributeValueException.class, expectedExceptionsMessageRegExp = "Try update non modifiable attribute") public void testUpdateFailReadOnly() throws Exception { Uid uid = createTestUser("FAIL04"); Set<Attribute> updateAttributes = new HashSet<Attribute>(1); updateAttributes.add(AttributeBuilder.build("lastModified", "newValue")); uid = getFacade(TEST_NAME).update(ObjectClass.ACCOUNT, uid, updateAttributes, null); fail("Connector operation should fail"); } @Test(expectedExceptions = OperationTimeoutException.class) public void testUpdateTimeOut() throws Exception { getFacade(TEST_NAME).update(TEST, new Uid("TIMEOUT"), CollectionUtil.newSet(AttributeBuilder.build("null")), null); Assert.fail(); } @Test(expectedExceptions = UnsupportedOperationException.class) public void testUpdateUnsupportedObjectClass() throws Exception { Set<Attribute> updateAttributes = new HashSet<Attribute>(1); updateAttributes.add(AttributeBuilder.build("email", "foo@example.com")); getFacade(TEST_NAME).update(UNKNOWN, new Uid("TESTOK1"), updateAttributes, null); } protected Uid createTestUser(String username) { Set<Attribute> createAttributes = getTestConnectorObject(username); ConnectorFacade facade = getFacade(TEST_NAME); Uid uid = facade.create(ObjectClass.ACCOUNT, createAttributes, null); Assert.assertNotNull(uid); ConnectorObject co = facade.getObject(ObjectClass.ACCOUNT, uid, null); Assert.assertEquals(co.getUid(), uid); return uid; } protected Set<Attribute> getTestConnectorObject(String name) { Set<Attribute> createAttributes = new HashSet<Attribute>(); createAttributes.add(new Name(name)); createAttributes.add(AttributeBuilder.build("userName", name)); createAttributes.add(AttributeBuilder.build("email", name + "@example.com")); createAttributes.add(AttributeBuilder.buildEnabled(true)); createAttributes.add(AttributeBuilder.build("firstName", "John")); createAttributes.add(AttributeBuilder.build("sn", name.toUpperCase())); createAttributes.add(AttributeBuilder.buildPassword("Passw0rd".toCharArray())); createAttributes.add(AttributeBuilder .build(PredefinedAttributes.DESCRIPTION, "Description")); createAttributes.add(AttributeBuilder.build("groups", "group1", "group2")); return createAttributes; } protected ConnectorFacade getFacade(String environment) { if (null == facade) { facade = createConnectorFacade(ScriptedConnector.class, environment); } return facade; } @AfterClass public synchronized void afterClass() { ((LocalConnectorFacadeImpl) facade).dispose(); facade = null; } }