/* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * * U.S. Government Rights - Commercial software. Government users * are subject to the Sun Microsystems, Inc. standard license agreement * and applicable provisions of the FAR and its supplements. * * Use is subject to license terms. * * This distribution may include materials developed by third parties. * Sun, Sun Microsystems, the Sun logo, Java and Project Identity * Connectors are trademarks or registered trademarks of Sun * Microsystems, Inc. or its subsidiaries in the U.S. and other * countries. * * UNIX is a registered trademark in the U.S. and other countries, * exclusively licensed through X/Open Company, Ltd. * * ----------- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common Development * and Distribution License(CDDL) (the License). You may not use this file * except in compliance with the License. * * You can obtain a copy of the License at * http://identityconnectors.dev.java.net/CDDLv1.0.html * See the License for the specific language governing permissions and * limitations under the License. * * When distributing the Covered Code, include this CDDL Header Notice in each * file and include the License file at identityconnectors/legal/license.txt. * If applicable, add the following below this CDDL Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * ----------- * * Portions Copyrighted 2012 ForgeRock Inc. * */ package org.forgerock.openicf.connectors.googleapps; import static org.testng.Assert.*; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import org.identityconnectors.common.logging.Log; import org.identityconnectors.common.security.GuardedString; import org.identityconnectors.framework.api.APIConfiguration; import org.identityconnectors.framework.api.ConnectorFacade; import org.identityconnectors.framework.api.ConnectorFacadeFactory; 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.ObjectClassInfo; import org.identityconnectors.framework.common.objects.OperationOptionsBuilder; import org.identityconnectors.framework.common.objects.PredefinedAttributes; import org.identityconnectors.framework.common.objects.Schema; 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.test.common.PropertyBag; import org.identityconnectors.test.common.TestHelpers; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** * Attempts to test the {@link GoogleAppsConnector} with the framework. * * @author $author$ * @version $Revision$ $Date$ */ public class GoogleAppsConnectorTests { /* * Example test properties. See the Javadoc of the TestHelpers class for the * location of the public and private configuration files. */ private static final PropertyBag properties = TestHelpers .getProperties(GoogleAppsConnector.class); // set up logging private static final Log LOGGER = Log.getLog(GoogleAppsConnectorTests.class); private GoogleAppsConfiguration config = null; // primary group to add a user to - init from config public static String testGroup = "openidm"; public static String testDomain = properties.getStringProperty("configuration.domain"); @BeforeClass public void setUp() { assertNotNull(properties); // // other setup work to do before running tests // config = new GoogleAppsConfiguration(); config.setConnectionUrl(properties.getStringProperty("configuration.connectionUrl")); config.setDomain(properties.getStringProperty("configuration.domain")); config.setLogin(properties.getStringProperty("configuration.login")); config.setPassword(properties.getProperty("configuration.password", GuardedString.class)); } @AfterClass public static void tearDown() { // // clean up resources // } @Test public void exampleTest1() { LOGGER.info("Running Test 1..."); getFacade().test(); // You can use TestHelpers to do some of the boilerplate work in running // a search // TestHelpers.search(theConnector, ObjectClass.ACCOUNT, filter, // handler, null); } @Test public void exampleTest2() { LOGGER.info("Running Test 2..."); // Another example using TestHelpers // List<ConnectorObject> results = // TestHelpers.searchToList(theConnector, ObjectClass.GROUP, filter); } protected ConnectorFacade getFacade() { ConnectorFacadeFactory factory = ConnectorFacadeFactory.getInstance(); // **test only** APIConfiguration impl = TestHelpers.createTestConfiguration(GoogleAppsConnector.class, config); return factory.newInstance(impl); } /** * * Test basic schema. There really isn't much to do here. We could test for * the name or type of a certain attribute but that seems self fulfilling * :-), and it means schema updates occur in two places (the schema, and * here). */ // @Ignore("Ignore for now so hudson build works") @Test public void testSchema() { Schema schema = getFacade().schema(); System.out.println("Schema information: " + schema.toString()); // Schema should not be null assertNotNull(schema); Set<ObjectClassInfo> objectInfos = schema.getObjectClassInfo(); assertNotNull(objectInfos); assertEquals(2, objectInfos.size()); // supports ACCOUNT and GROUP // todo: What else to test? } /** * Test basic CRUD operations * * Note on Google Apps: Once you delete an account, you must wait 5 days * before reusing the same account id. When designing tests we need to make * sure we do not trigger this condition. */ @Test public void XXtestCreateReadUpdateDeleteUser() { TestAccount tst = new TestAccount(); System.out.println("Creating test account " + tst.toString()); Set<Attribute> attrSet = tst.toAttributeSet(true); assertNotNull(attrSet); // create the account Uid uid = getFacade().create(ObjectClass.ACCOUNT, attrSet, null); assertNotNull(uid); assertEquals(uid.getUidValue(), tst.getAccountId()); // try second create of the same user - should fail try { Uid uid2 = getFacade().create(ObjectClass.ACCOUNT, attrSet, null); fail("Second create of the same user was supposed to fail. It did not "); } catch (Exception e) { // do nothing - expected. // todo: What specifically are we expecting? System.out.println("OK - Got an exception which we expected (ignore)"); } // search for the user we just created TestAccount test2 = fetchAccount(tst.getAccountId()); assertEquals(tst, test2); // test modification of the account // to test partial update we dont modify the given name String newFamily = "NewFamily"; // String newGiven = "NewGiven"; String password = "Newpassword"; tst.setFamilyName(newFamily); // tst.setGivenName(newGiven); tst.setPassword(password); // update the account getFacade().update(ObjectClass.ACCOUNT, uid, tst.toAttributeSet(true), null); // compare the two accounts to see if we got back what we expected test2 = fetchAccount(tst.getAccountId()); assertEquals(tst, test2); // test the group membership // ConnectorObject obj = fetchGroup(testGroup); // Attribute a = // obj.getAttributeByName(GoogleAppsConnector.ATTR_MEMBER_LIST); // assertTrue(a.getValue().contains(tst.getAccountId() + "@" + // testDomain)); // delete the test account getFacade().delete(ObjectClass.ACCOUNT, uid, null); } private ConnectorObject fetchConnectorObject(String id, ObjectClass clazz, String[] optionalAttrs) { Filter filter = FilterBuilder.equalTo(new Name(id)); OperationOptionsBuilder builder = new OperationOptionsBuilder(); builder.setAttributesToGet(Arrays.asList(optionalAttrs)); List<ConnectorObject> r = TestHelpers.searchToList(getFacade(), clazz, filter, builder.build()); if (r == null || r.size() < 1) { return null; } assertEquals(r.size(), 1); // should only be one ConnectorObject obj = r.get(0); System.out.println("Object fetched=" + obj); return obj; } private static final String accountOptionalAttrs[] = { GoogleAppsConnector.ATTR_NICKNAME_LIST, PredefinedAttributes.GROUPS_NAME, GoogleAppsConnector.ATTR_FAMILY_NAME }; private static final String groupOptionalAttrs[] = { GoogleAppsConnector.ATTR_MEMBER_LIST, GoogleAppsConnector.ATTR_OWNER_LIST, PredefinedAttributes.DESCRIPTION }; private TestAccount fetchAccount(String id) { return TestAccount.fromConnectorObject(fetchConnectorObject(id, ObjectClass.ACCOUNT, accountOptionalAttrs)); } private ConnectorObject fetchGroup(String id) { return fetchConnectorObject(id, ObjectClass.GROUP, groupOptionalAttrs); } /** * Test search for all users. * * Becuase we are using a public google apps accounts we don't know for sure * how many accounts will be returned - so we assume 1 or more is a * successs. There will alwayws be an admin account (i.e. at least one) * */ // @Test public void XXtestSearchAll() { Filter filter = null; // return all results List<ConnectorObject> r = TestHelpers.searchToList(getFacade(), ObjectClass.ACCOUNT, filter); assertNotNull(r); assertTrue(r.size() > 0); System.out.println("Google Apps accounts:" + r); } /** * Test nicknames. These are aliases for the user's email. * */ @Test public void XXtestNicknames() { int NUMBER_NICKS = 3; TestAccount test1 = new TestAccount(); String suffix = "n" + test1.getAccountId(); List<String> nicks = test1.getNicknames(); nicks.clear(); // create a few nicknames for (int i = 0; i < NUMBER_NICKS; ++i) { nicks.add("n" + i + suffix); } Uid uid = null; try { uid = getFacade().create(ObjectClass.ACCOUNT, test1.toAttributeSet(true), null); // read it back - did we get the same nicknames? TestAccount test2 = fetchAccount(test1.getAccountId()); assertEquals(test2.getNicknames().size(), NUMBER_NICKS); assertEquals(test1.getNicknames(), test2.getNicknames()); // try deleting a nickname - should have one less names String n = "n0" + suffix; nicks.remove(n); // update the account getFacade().update(ObjectClass.ACCOUNT, uid, test1.toAttributeSet(false), null); test2 = fetchAccount(test1.getAccountId()); assertEquals(NUMBER_NICKS - 1, test2.getNicknames().size()); assertFalse(test2.getNicknames().contains(n)); // add a new nick name in nicks.add("newnick" + suffix); // update the account getFacade().update(ObjectClass.ACCOUNT, uid, test1.toAttributeSet(false), null); test2 = fetchAccount(test1.getAccountId()); assertEquals(test2.getNicknames(), test1.getNicknames()); // now delete all the nicks nicks.clear(); // update the account getFacade().update(ObjectClass.ACCOUNT, uid, test1.toAttributeSet(false), null); test2 = fetchAccount(test1.getAccountId()); assertEquals(test2.getNicknames(), test1.getNicknames()); assertEquals(test2.getNicknames().size(), 0); } finally { // delete the test account getFacade().delete(ObjectClass.ACCOUNT, uid, null); } } @Test public void testGroups() { // create test group Uid gid = getFacade().create(ObjectClass.GROUP, makeGroupAttrs(testGroup, "testGroup", "test group dsecription", "", null), null); assertTrue(gid != null); Set<Attribute> attr = makeGroupAttrs(testGroup, "testGroup", "NEW DESCRIPTION", "", null); // update the description getFacade().update(ObjectClass.GROUP, gid, attr, null); // read it back ConnectorObject o = fetchGroup(testGroup); assertEquals(AttributeUtil.getAsStringValue(o .getAttributeByName(PredefinedAttributes.DESCRIPTION)), "NEW DESCRIPTION"); // add a user to the group TestAccount t1 = new TestAccount(); t1.getGroups().add(testGroup); Set<Attribute> attrSet = t1.toAttributeSet(true); // create the account Uid uid = getFacade().create(ObjectClass.ACCOUNT, attrSet, null); // fetch via group membership o = fetchGroup(testGroup); List<Object> users = o.getAttributeByName(GoogleAppsConnector.ATTR_MEMBER_LIST).getValue(); assertTrue(users.contains(t1.getAccountId() + "@" + testDomain)); // add a second user via group object TestAccount t2 = new TestAccount(); attrSet = t2.toAttributeSet(true); // create the account Uid uid2 = getFacade().create(ObjectClass.ACCOUNT, attrSet, null); List<String> ulist = new ArrayList<String>(); ulist.add(t2.getAccountId() + "@" + testDomain); attrSet = makeGroupAttrs(testGroup, "testGroup", "NEW DESCRIPTION", "", ulist); // should ADD user t2, and delete user t1 getFacade().update(ObjectClass.GROUP, gid, attrSet, null); // fetch via group membership o = fetchGroup(testGroup); users = o.getAttributeByName(GoogleAppsConnector.ATTR_MEMBER_LIST).getValue(); assertTrue(users.contains(t2.getAccountId() + "@" + testDomain)); assertEquals(users.size(), 1); // // delete user getFacade().delete(ObjectClass.ACCOUNT, uid, null); getFacade().delete(ObjectClass.ACCOUNT, uid2, null); // delete the group getFacade().delete(ObjectClass.GROUP, gid, null); } private Set<Attribute> makeGroupAttrs(String id, String name, String descrip, String perms, List<String> members) { Set<Attribute> attr = new HashSet<Attribute>(); attr.add(AttributeBuilder.build(Name.NAME, id)); attr.add(AttributeBuilder.build(PredefinedAttributes.DESCRIPTION, descrip)); attr.add(AttributeBuilder.build(GoogleAppsConnector.ATTR_GROUP_TEXT_NAME, name)); attr.add(AttributeBuilder.build(GoogleAppsConnector.ATTR_GROUP_PERMISSIONS, perms)); if (members != null) attr.add(AttributeBuilder.build(GoogleAppsConnector.ATTR_MEMBER_LIST, members)); return attr; } }