View Javadoc

1   /*
2    * ====================
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4    * 
5    * Copyright 2008-2009 Sun Microsystems, Inc. All rights reserved.     
6    * 
7    * The contents of this file are subject to the terms of the Common Development 
8    * and Distribution License("CDDL") (the "License").  You may not use this file 
9    * except in compliance with the License.
10   * 
11   * You can obtain a copy of the License at 
12   * http://IdentityConnectors.dev.java.net/legal/license.txt
13   * See the License for the specific language governing permissions and limitations 
14   * under the License. 
15   * 
16   * When distributing the Covered Code, include this CDDL Header Notice in each file
17   * and include the License file at identityconnectors/legal/license.txt.
18   * If applicable, add the following below this CDDL Header, with the fields 
19   * enclosed by brackets [] replaced by your own identifying information: 
20   * "Portions Copyrighted [year] [name of copyright owner]"
21   * ====================
22   */
23  package org.identityconnectors.framework.impl.api;
24  
25  import static org.testng.AssertJUnit.assertEquals;
26  import static org.testng.AssertJUnit.assertTrue;
27  import org.testng.annotations.Test;
28  import org.testng.annotations.BeforeMethod;
29  import org.testng.AssertJUnit;
30  import static org.identityconnectors.framework.common.objects.ObjectClass.ACCOUNT;
31  import java.util.HashSet;
32  import java.util.List;
33  import java.util.Set;
34  
35  import org.identityconnectors.common.CollectionUtil;
36  import org.identityconnectors.common.security.GuardedString;
37  import org.identityconnectors.framework.api.APIConfiguration;
38  import org.identityconnectors.framework.api.ConnectorFacade;
39  import org.identityconnectors.framework.api.ConnectorFacadeFactory;
40  import org.identityconnectors.framework.api.operations.APIOperation;
41  import org.identityconnectors.framework.api.operations.GetApiOp;
42  import org.identityconnectors.framework.api.operations.SearchApiOp;
43  import org.identityconnectors.framework.api.operations.UpdateApiOp;
44  import org.identityconnectors.framework.common.objects.Attribute;
45  import org.identityconnectors.framework.common.objects.AttributeBuilder;
46  import org.identityconnectors.framework.common.objects.AttributeUtil;
47  import org.identityconnectors.framework.common.objects.ConnectorObject;
48  import org.identityconnectors.framework.common.objects.Name;
49  import org.identityconnectors.framework.common.objects.ObjectClass;
50  import org.identityconnectors.framework.common.objects.ResultsHandler;
51  import org.identityconnectors.framework.common.objects.ScriptContextBuilder;
52  import org.identityconnectors.framework.common.objects.Uid;
53  import org.identityconnectors.framework.spi.Configuration;
54  import org.identityconnectors.framework.spi.Connector;
55  import org.identityconnectors.mockconnector.MockAllOpsConnector;
56  import org.identityconnectors.mockconnector.MockConfiguration;
57  import org.identityconnectors.mockconnector.MockConnector;
58  import org.identityconnectors.mockconnector.MockUpdateConnector;
59  import org.identityconnectors.mockconnector.MockConnector.Call;
60  import org.identityconnectors.test.common.TestHelpers;
61  
62  
63  public class ConnectorFacadeTests {
64  
65      // =======================================================================
66      // Setup/Tear down
67      // =======================================================================
68      @BeforeMethod
69  	public void setup() {
70          // always reset the call patterns..
71          MockConnector.reset();
72      }
73  
74      // =======================================================================
75      // Helper Methods
76      // =======================================================================
77      private interface TestOperationPattern {
78          /**
79           * Simple call back to make the 'facade' calls.
80           */
81          public void makeCall(ConnectorFacade facade);
82  
83          /**
84           * Given the list of calls determine if they match expected values based
85           * on the calls made in the {@link #makeCall(ConnectorFacade)} method.
86           */
87          public void checkCalls(List<MockConnector.Call> calls);
88      }
89  
90      /**
91       * Test the pattern of the common operations.
92       * 
93       * @throws ClassNotFoundException
94       */
95      @Test(enabled = false)
96  	private void testCallPattern(TestOperationPattern pattern) {
97          testCallPattern(pattern, MockAllOpsConnector.class);
98      }
99  
100     @Test(enabled = false)
101 	private void testCallPattern(TestOperationPattern pattern,
102             Class<? extends Connector> clazz) {
103         Configuration config = new MockConfiguration(false);
104         ConnectorFacadeFactory factory = ConnectorFacadeFactory.getInstance();
105         // **test only**
106         APIConfiguration impl = TestHelpers.createTestConfiguration(clazz, config);
107         ConnectorFacade facade;
108         facade = factory.newInstance(impl);
109         // make the call on the connector facade..
110         pattern.makeCall(facade);
111         // check the call structure..
112         List<MockConnector.Call> calls = MockConnector.getCallPattern();
113         // check the call pattern..
114         assertEquals("init", calls.remove(0).getMethodName());
115         pattern.checkCalls(calls);
116         assertEquals("dispose", calls.remove(0).getMethodName());
117         assertTrue(calls.isEmpty());
118     }
119 
120     // =======================================================================
121     // Tests
122     // =======================================================================
123     /**
124      * Tests that if an SPI operation is not implemented that the API will throw
125      * an {@link UnsupportedOperationException}.
126      */
127     @Test(expectedExceptions = UnsupportedOperationException.class)
128     public void unsupportedOperationTest() {
129         Configuration config = new MockConfiguration(false);
130         Class<? extends Connector> clazz = MockConnector.class;
131         ConnectorFacadeFactory factory = ConnectorFacadeFactory.getInstance();
132         APIConfiguration impl = TestHelpers.createTestConfiguration(clazz,
133                 config);
134         ConnectorFacade facade;
135         facade = factory.newInstance(impl);
136         facade.authenticate(ObjectClass.ACCOUNT, "fadf", new GuardedString("fadsf".toCharArray()),null);
137     }
138     
139     @Test
140     public void runScriptOnConnectorCallPattern() {
141         testCallPattern(new TestOperationPattern() {
142             public void makeCall(ConnectorFacade facade) {
143                 facade.runScriptOnConnector(
144                         new ScriptContextBuilder("lang","script").build(), 
145                         null);
146             }
147 
148             public void checkCalls(List<Call> calls) {
149                 assertEquals("runScriptOnConnector", calls.remove(0).getMethodName());
150             }
151         });
152     }
153     
154     @Test
155     public void runScriptOnResourceCallPattern() {
156         testCallPattern(new TestOperationPattern() {
157             public void makeCall(ConnectorFacade facade) {
158                 facade.runScriptOnResource(
159                         new ScriptContextBuilder("lang","script").build(), 
160                         null);
161             }
162 
163             public void checkCalls(List<Call> calls) {
164                 assertEquals("runScriptOnResource", calls.remove(0).getMethodName());
165             }
166         });
167     }
168 
169     /**
170      * Test the call pattern to get the schema.
171      */
172     @Test
173     public void schemaCallPattern() {
174         testCallPattern(new TestOperationPattern() {
175             public void makeCall(ConnectorFacade facade) {
176                 facade.schema();
177             }
178 
179             public void checkCalls(List<Call> calls) {
180                 assertEquals("schema", calls.remove(0).getMethodName());
181             }
182         });
183     }
184 
185     @Test
186     public void authenticateCallPattern() {
187         testCallPattern(new TestOperationPattern() {
188             public void makeCall(ConnectorFacade facade) {
189                 facade.authenticate(ObjectClass.ACCOUNT, "dfadf", new GuardedString("fadfkj".toCharArray()),null);
190             }
191 
192             public void checkCalls(List<Call> calls) {
193                 assertEquals("authenticate", calls.remove(0).getMethodName());
194             }
195         });
196     }
197 
198     @Test
199     public void resolveUsernameCallPattern() {
200         testCallPattern(new TestOperationPattern() {
201             public void makeCall(ConnectorFacade facade) {
202                 facade.resolveUsername(ObjectClass.ACCOUNT, "dfadf", null);
203             }
204 
205             public void checkCalls(List<Call> calls) {
206                 assertEquals("resolveUsername", calls.remove(0).getMethodName());
207             }
208         });
209     }
210 
211     @Test
212     public void createCallPattern() {
213         testCallPattern(new TestOperationPattern() {
214             public void makeCall(ConnectorFacade facade) {
215                 Set<Attribute> attrs = CollectionUtil.<Attribute>newReadOnlySet();
216                 facade.create(ObjectClass.ACCOUNT,attrs,null);
217             }
218 
219             public void checkCalls(List<Call> calls) {
220                 assertEquals("create", calls.remove(0).getMethodName());
221             }
222         });
223     }
224     
225     @Test( expectedExceptions = NullPointerException.class )
226     public void createWithOutObjectClassPattern() {
227         testCallPattern(new TestOperationPattern() {
228             public void makeCall(ConnectorFacade facade) {
229                 Set<Attribute> attrs = new HashSet<Attribute>();
230                 facade.create(null,attrs,null);
231             }
232             public void checkCalls(List<Call> calls) {
233                 AssertJUnit.fail("Should not get here..");
234             }
235         });
236     }
237     
238     @Test( expectedExceptions = IllegalArgumentException.class )
239     public void createDuplicatAttributesPattern() {
240         testCallPattern(new TestOperationPattern() {
241             public void makeCall(ConnectorFacade facade) {
242                 Set<Attribute> attrs = new HashSet<Attribute>();
243                 attrs.add(AttributeBuilder.build("abc", 1));
244                 attrs.add(AttributeBuilder.build("abc", 2));
245                 facade.create(ObjectClass.ACCOUNT,attrs,null);
246             }
247             public void checkCalls(List<Call> calls) {
248                 AssertJUnit.fail("Should not get here..");
249             }
250         });
251     }
252 
253     @Test
254     public void updateCallPattern() {
255         testCallPattern(new TestOperationPattern() {
256             public void makeCall(ConnectorFacade facade) {
257                 Set<Attribute> attrs = new HashSet<Attribute>();
258                 attrs.add(AttributeBuilder.build("accountid"));
259                 facade.update(ObjectClass.ACCOUNT, newUid(0), attrs, null);
260             }
261 
262             public void checkCalls(List<Call> calls) {
263                 assertEquals("update", calls.remove(0).getMethodName());
264             }
265         });
266     }
267 
268     @Test
269     public void deleteCallPattern() {
270         testCallPattern(new TestOperationPattern() {
271             public void makeCall(ConnectorFacade facade) {
272                 facade.delete(ObjectClass.ACCOUNT, newUid(0),null);
273             }
274 
275             public void checkCalls(List<Call> calls) {
276                 assertEquals("delete", calls.remove(0).getMethodName());
277             }
278         });
279     }
280 
281     @Test
282     public void searchCallPattern() {
283         testCallPattern(new TestOperationPattern() {
284             public void makeCall(ConnectorFacade facade) {
285                 // create an empty results handler..
286                 ResultsHandler rh = new ResultsHandler() {
287                     public boolean handle(ConnectorObject obj) {
288                         return true;
289                     }
290                 };
291                 // call the search method..
292                 facade.search(ObjectClass.ACCOUNT, null, rh, null);
293             }
294 
295             public void checkCalls(List<Call> calls) {
296                 assertEquals("createFilterTranslator", calls.remove(0).getMethodName());
297                 assertEquals("executeQuery", calls.remove(0).getMethodName());
298             }
299         });
300     }
301 
302     @Test
303     public void getCallPattern() {
304         testCallPattern(new TestOperationPattern() {
305             public void makeCall(ConnectorFacade facade) {
306                 // create an empty results handler..
307                 // call the search method..
308                 facade.getObject(ObjectClass.ACCOUNT, newUid(0), null);
309             }
310 
311             public void checkCalls(List<Call> calls) {
312                 assertEquals("createFilterTranslator", calls.remove(0).getMethodName());
313                 assertEquals("executeQuery", calls.remove(0).getMethodName());
314             }
315         });
316     }
317     
318     @Test
319     public void testOpCallPattern() {
320         testCallPattern(new TestOperationPattern() {
321             public void makeCall(ConnectorFacade facade) {
322                 facade.test();
323             }
324 
325             public void checkCalls(List<Call> calls) {
326                 assertEquals("test", calls.remove(0).getMethodName());
327             }
328         });
329     }
330     
331     @Test
332     public void updateMergeTests() {
333         Attribute expected, actual;
334         Configuration config = new MockConfiguration(false);
335         ConnectorFacadeFactory factory = ConnectorFacadeFactory.getInstance();
336         Class<? extends Connector> clazz = MockUpdateConnector.class;
337         // **test only**
338         APIConfiguration impl = TestHelpers.createTestConfiguration(clazz, config);
339         impl.setTimeout(GetApiOp.class, APIOperation.NO_TIMEOUT);
340         impl.setTimeout(UpdateApiOp.class, APIOperation.NO_TIMEOUT);
341         impl.setTimeout(SearchApiOp.class, APIOperation.NO_TIMEOUT);
342         ConnectorFacade facade = factory.newInstance(impl);
343         // sniff test to make sure we can get an object..
344         ConnectorObject obj = facade.getObject(ACCOUNT, newUid(1), null);
345         assertEquals(newUid(1), obj.getUid());
346         // ok lets add an attribute that doesn't exist..
347         final String ADDED = "somthing to add to the object";
348         final String ATTR_NAME = "added";
349         Set<Attribute> addAttrSet;
350         addAttrSet = CollectionUtil.newSet(obj.getAttributes());
351         addAttrSet.add(AttributeBuilder.build(ATTR_NAME, ADDED));
352         Name name = obj.getName();
353         addAttrSet.remove(name);
354         Uid uid = facade.addAttributeValues(ACCOUNT, obj.getUid(), AttributeUtil.filterUid(addAttrSet), null);
355         // get back the object and see if there are the same..
356         addAttrSet.add(name);
357         ConnectorObject addO = new ConnectorObject(ACCOUNT, addAttrSet);
358         obj = facade.getObject(ObjectClass.ACCOUNT, newUid(1), null);
359         assertEquals(addO, obj);
360         // attempt to add on to an existing attribute..
361         addAttrSet.remove(name);
362         uid = facade.addAttributeValues(ACCOUNT, obj.getUid(), AttributeUtil.filterUid(addAttrSet), null);
363         // get the object back out and check on it..
364         obj = facade.getObject(ObjectClass.ACCOUNT, uid, null);
365         expected = AttributeBuilder.build(ATTR_NAME, ADDED, ADDED);
366         actual = obj.getAttributeByName(ATTR_NAME);
367         assertEquals(expected, actual);
368         // attempt to delete a value from an attribute..
369         Set<Attribute> deleteAttrs = CollectionUtil.newSet(addO.getAttributes());
370         deleteAttrs.remove(name);
371         uid = facade.removeAttributeValues(ACCOUNT, addO.getUid(), AttributeUtil.filterUid(deleteAttrs), null);
372         obj = facade.getObject(ObjectClass.ACCOUNT, uid, null);
373         expected = AttributeBuilder.build(ATTR_NAME, ADDED);
374         actual = obj.getAttributeByName(ATTR_NAME);
375         assertEquals(expected, actual);
376         // attempt to delete an attribute that doesn't exist..
377         Set<Attribute> nonExist = new HashSet<Attribute>();
378         nonExist.add(newUid(1));
379         nonExist.add(AttributeBuilder.build("does not exist", "asdfe"));
380         uid = facade.removeAttributeValues(ACCOUNT, addO.getUid(), AttributeUtil.filterUid(nonExist), null);
381         obj = facade.getObject(ObjectClass.ACCOUNT, newUid(1), null);
382         assertTrue(obj.getAttributeByName("does not exist") == null);
383     }
384     
385     static Uid newUid(int id) {
386         return new Uid(Integer.toString(id));
387     }
388 }