1   /*
2   * E-nspire Gemini.
3   * A Java and AspectJ based framework that enables transparent 
4   * bidirectional relationships between Plain Old Java Objects.
5   * 
6   * Copyright (C) 2005 Dragan Djuric
7   * 
8   * This program is free software; you can redistribute it and/or
9   * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  * 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21  * 
22  * Contact the author at dragand@dev.java.net
23  */
24  package com.enspire.gemini.bidirectional;
25  
26  import java.util.Collection;
27  import java.util.Iterator;
28  import java.util.LinkedList;
29  import java.util.List;
30  import java.util.ListIterator;
31  
32  import org.jmock.Mock;
33  
34  import com.enspire.collections.decorator.CollectionDecorator;
35  import com.enspire.collections.decorator.ListDecoratorTest;
36  import com.enspire.gemini.RelationshipUpdater;
37  
38  /***
39   * TODO To change the template for this generated type comment go to
40   * Window - Preferences - Java - Code Style - Code Templates
41   *
42   * @author Dragan Djuric <dragand@dev.java.net>
43   **/
44  public class BidirectionalListTest extends ListDecoratorTest {
45  
46      private BidirectionalList testBidirectionalList;
47  
48      private Mock mockRelationshipUpdater;
49      private Object owner;
50      private String oppositeName = "name";
51  
52      
53      /***
54       * Creates a decorated decorated to test.
55       * @param l a decorated that is being decorated
56       * @return new bean to test
57       */
58      protected CollectionDecorator createTestedCollection(Collection c) {
59          return new BidirectionalList();
60      }
61      
62      /***
63       * @return Returns the mockRelationshipUpdater.
64       */
65      public Mock getMockRelationshipUpdater() {
66          return mockRelationshipUpdater;
67      }
68      
69      /***
70       * @return Returns the owner.
71       */
72      public Object getOwner() {
73          return owner;
74      }
75  
76      /***
77       * @see junit.framework.TestCase#setUp()
78       */
79      protected void setUp() throws Exception {
80          super.setUp();
81          owner = new Object();
82          testBidirectionalList = 
83                  (BidirectionalList)getTestedCollection();
84          mockRelationshipUpdater = new Mock(RelationshipUpdater.class);
85          testBidirectionalList.setOppositeName(oppositeName);
86          RelationshipUpdater relationshipUpdater = 
87                  (RelationshipUpdater)mockRelationshipUpdater.proxy();
88          testBidirectionalList.setRelationshipUpdater(relationshipUpdater);
89          testBidirectionalList.setOwner(owner);
90          getMockDecorated().expects(once()).method("isEmpty").will(returnValue(true));
91          testBidirectionalList.setPropertyValue(getDecorated());
92      }
93      
94      /***
95       * @see com.enspire.collections.decorator.ListDecoratorTest#testAdd()
96       */
97      
98      public void testAdd() {
99          testBidirectionalList.setPropertyValue(new LinkedList());
100         Object object = new Object();
101         mockRelationshipUpdater.expects(once()).method("set").
102                 with(same(object), same(oppositeName), same(owner));
103         assertTrue("The add method of decoratedList collection should be invoked.", //$NON-NLS-1$
104                 testBidirectionalList.add(object));
105     }
106     
107     public void testAddExisting() {
108         testBidirectionalList.setPropertyValue(new LinkedList());
109         Object object = new Object();
110         mockRelationshipUpdater.expects(once()).method("set").
111                 with(same(object), same(oppositeName), same(owner));
112         assertTrue("object should be added and relationshipUpdater.set invoked.", //$NON-NLS-1$
113                 testBidirectionalList.add(object));
114         assertFalse("object should NOT be added and relationshipUpdater.set NOT invoked.", //$NON-NLS-1$
115                 testBidirectionalList.add(object));
116     }
117     
118     public void testAddUpdaterThrowsException() {
119         testBidirectionalList.setPropertyValue(new LinkedList());
120         Object object = new Object();
121         mockRelationshipUpdater.expects(once()).method("set").
122                 with(same(object), same(oppositeName), same(owner)).will(
123                 throwException(new RuntimeException()));
124         try {
125             testBidirectionalList.add(object);
126             fail("RuntimeException should be thrown.");
127         } catch(RuntimeException e) {
128             assertFalse("object should not be added.", 
129                     testBidirectionalList.contains(object));
130         }        
131     }
132     
133     /***
134      * @see com.enspire.collections.decorator.ListDecoratorTest#testAddIndexed)
135      */
136     
137     public void testAddIndexed() {
138         testBidirectionalList.setPropertyValue(new LinkedList());
139         Object object = new Object();
140         int index = 0;
141         mockRelationshipUpdater.expects(once()).method("set").
142                 with(same(object), same(oppositeName), same(owner));
143         testBidirectionalList.add(index, object);
144         assertSame("The add method of decoratedList collection should be invoked.", //$NON-NLS-1$
145                 object, testBidirectionalList.get(index));
146     }
147     
148     /***
149      * @see com.enspire.collections.decorator.ListDecoratorTest#testAddAll()
150      */
151     
152     public void testAddAll() {
153         testBidirectionalList.setPropertyValue(new LinkedList());
154         Collection coll = new LinkedList();
155         Object ok0 = new Object();
156         Object ok1 = new Object();
157         coll.add(ok0);
158         coll.add(ok1);
159         mockRelationshipUpdater.expects(once()).method("set").
160                 with(same(ok0), same(oppositeName), same(owner));
161         mockRelationshipUpdater.expects(once()).method("set").
162                 with(same(ok1), same(oppositeName), same(owner));
163         assertTrue("coll elements should be added.", 
164                 testBidirectionalList.addAll(coll));
165     }
166 
167     public void testAddAllUpdaterThrowsException() {
168         testBidirectionalList.setPropertyValue(new LinkedList());
169         Collection coll = new LinkedList();
170         Object ok = new Object();
171         Object wrong = new Object();
172         coll.add(ok);
173         coll.add(wrong);
174         mockRelationshipUpdater.expects(once()).method("set").
175                 with(same(ok), same(oppositeName), same(owner));
176         mockRelationshipUpdater.expects(once()).method("unset").
177                 with(same(ok), same(oppositeName), same(owner));
178         mockRelationshipUpdater.expects(once()).method("set").
179                 with(same(wrong), same(oppositeName), same(owner)).will(
180                         throwException(new RuntimeException()));
181         try {
182             testBidirectionalList.addAll(coll);
183             fail("RuntimeException should be thrown.");
184         } catch(RuntimeException e) {
185             assertFalse("ok should not be added.", 
186                     testBidirectionalList.contains(ok));
187             assertFalse("wrong should not be added.", 
188                     testBidirectionalList.contains(ok));
189         }    
190     }
191     
192     /***
193      * @see com.enspire.collections.decorator.ListDecoratorTest#testAddAll()
194      */
195     
196     public void testAddAllIndexed() {
197         testBidirectionalList.setPropertyValue(new LinkedList());
198         Collection coll = new LinkedList();
199         int index = 0;
200         Object ok0 = new Object();
201         Object ok1 = new Object();
202         coll.add(ok0);
203         coll.add(ok1);
204         mockRelationshipUpdater.expects(once()).method("set").
205                 with(same(ok0), same(oppositeName), same(owner));
206         mockRelationshipUpdater.expects(once()).method("set").
207                 with(same(ok1), same(oppositeName), same(owner));
208         testBidirectionalList.addAll(index, coll);
209         assertEquals("coll elements should be added.", 
210                 ok0, testBidirectionalList.get(index));
211         assertEquals("coll elements should be added.", 
212                 ok1, testBidirectionalList.get(index + 1));
213     }
214     
215     /***
216      * @see com.enspire.collections.decorator.ListDecoratorTest#testRemove()
217      */
218     
219     public void testRemove() {
220         List unidirectional = new LinkedList();
221         testBidirectionalList.setPropertyValue(unidirectional);
222         Object object = new Object();
223         unidirectional.add(object);
224         mockRelationshipUpdater.expects(once()).method("unset").
225                 with(same(object), same(oppositeName), same(owner));
226         assertTrue("The remove method of decoratedList collection should be invoked.", //$NON-NLS-1$
227                 testBidirectionalList.remove(object));
228     }
229     
230     public void testRemoveNonExisting() {
231         testBidirectionalList.setPropertyValue(new LinkedList());
232         Object object = new Object();
233         assertFalse("object should NOT be removed and relationshipUpdater.unset NOT invoked.", //$NON-NLS-1$
234                 testBidirectionalList.remove(object));
235     }
236     
237     public void testRemoveUpdaterThrowsException() {
238         List unidirectional = new LinkedList();
239         testBidirectionalList.setPropertyValue(unidirectional);
240         Object object = new Object();
241         unidirectional.add(object);
242         mockRelationshipUpdater.expects(once()).method("unset").
243                 with(same(object), same(oppositeName), same(owner)).will(
244                 throwException(new RuntimeException()));
245         try {
246             testBidirectionalList.remove(object);
247             fail("RuntimeException should be thrown.");
248         } catch(RuntimeException e) {
249             assertTrue("object should not be removed.", 
250                     testBidirectionalList.contains(object));
251         }        
252     }
253     
254     /***
255      * @see com.enspire.collections.decorator.ListDecoratorTest#testRemoveAll()
256      */
257     
258     public void testRemoveAll() {
259         List unidirectional = new LinkedList();
260         testBidirectionalList.setPropertyValue(unidirectional);
261         Collection coll = new LinkedList();
262         Object ok0 = new Object();
263         Object ok1 = new Object();
264         unidirectional.add(ok0);
265         unidirectional.add(ok1);
266         coll.add(ok0);
267         coll.add(ok1);
268         mockRelationshipUpdater.expects(once()).method("unset").
269                 with(same(ok0), same(oppositeName), same(owner));
270         mockRelationshipUpdater.expects(once()).method("unset").
271                 with(same(ok1), same(oppositeName), same(owner));
272         assertTrue("coll elements should be removed.", 
273                 testBidirectionalList.removeAll(coll));
274     }
275 
276     public void testRemoveAllUpdaterThrowsException() {
277         List unidirectional = new LinkedList();
278         testBidirectionalList.setPropertyValue(unidirectional);
279         Collection coll = new LinkedList();
280         Object ok = new Object();
281         Object wrong = new Object();
282         unidirectional.add(ok);
283         unidirectional.add(wrong);
284         coll.add(ok);
285         coll.add(wrong);
286         mockRelationshipUpdater.expects(once()).method("unset").
287                 with(same(ok), same(oppositeName), same(owner));
288         mockRelationshipUpdater.expects(once()).method("set").
289                 with(same(ok), same(oppositeName), same(owner));
290         mockRelationshipUpdater.expects(once()).method("unset").
291                 with(same(wrong), same(oppositeName), same(owner)).will(
292                         throwException(new RuntimeException()));
293         try {
294             testBidirectionalList.removeAll(coll);
295             fail("RuntimeException should be thrown.");
296         } catch(RuntimeException e) {
297             assertTrue("ok should not be removed.", 
298                     testBidirectionalList.contains(ok));
299             assertTrue("wrong should not be removed.", 
300                     testBidirectionalList.contains(ok));
301         }    
302     }
303     
304     /***
305      * Tests <code>retainAll()</code> method.
306      */
307     public void testRetainAll() {
308         try {
309             testBidirectionalList.retainAll(null);
310             fail("The operation should throw an exception, it is unsupported.");
311         } catch (UnsupportedOperationException e) {
312             assertTrue("retainAll() is not supported.", true);
313         }
314     }
315     
316     /***
317      * Tests <code>clear()</code> method.
318      */
319     public void testClear() {
320         try {
321             testBidirectionalList.clear();
322             fail("The operation should throw an exception, it is unsupported.");
323         } catch (UnsupportedOperationException e) {
324             assertTrue("clear() is not supported.", true);
325         }
326     }
327     
328     /***
329      * Tests <code>contains()</code> method.
330      */
331     public void testContains() {
332         Object object = new Object();
333         assertFalse("The contains method of decoratedList should be invoked.",
334                  testBidirectionalList.contains(object)); //$NON-NLS-1$
335     }
336     
337     public void testContainsAll() {
338         testBidirectionalList.setPropertyValue(new LinkedList());
339         Collection coll = new LinkedList();
340         Object ok0 = new Object();
341         Object ok1 = new Object();
342         coll.add(ok0);
343         coll.add(ok1);
344         mockRelationshipUpdater.expects(once()).method("set").
345                 with(same(ok0), same(oppositeName), same(owner));
346         mockRelationshipUpdater.expects(once()).method("set").
347                 with(same(ok1), same(oppositeName), same(owner));
348         assertTrue("coll elements should be added.", 
349                 testBidirectionalList.addAll(coll));
350         assertTrue("testBidirectionalCollection should contain coll elements.",
351                 testBidirectionalList.containsAll(coll));
352     }
353     
354     /***
355      * Tests <code>iterator()</code> method.
356      */
357     public void testIterator() {
358         testBidirectionalList.setPropertyValue(new LinkedList());
359         Object object = new Object();
360         mockRelationshipUpdater.expects(once()).method("set").
361                 with(same(object), same(oppositeName), same(owner));
362         mockRelationshipUpdater.expects(once()).method("unset").
363                 with(same(object), same(oppositeName), same(owner));
364         testBidirectionalList.add(object);
365         Iterator it = testBidirectionalList.iterator();
366         it.next();
367         it.remove();
368     }
369 
370     /***
371      * @see com.enspire.collections.decorator.ListDecoratorTest#testAddIndexed)
372      */
373     
374     public void testRemoveIndexed() {
375         testBidirectionalList.setPropertyValue(new LinkedList());
376         Object object = new Object();
377         int index = 0;
378         mockRelationshipUpdater.expects(once()).method("set").
379                 with(same(object), same(oppositeName), same(owner));
380         testBidirectionalList.add(index, object);
381         assertSame("object should be set at index position.", //$NON-NLS-1$
382                 object, testBidirectionalList.get(index));
383         mockRelationshipUpdater.expects(once()).method("unset").
384                 with(same(object), same(oppositeName), same(owner));
385         testBidirectionalList.remove(index);
386         assertTrue("testBidirectionalList should be empty.", //$NON-NLS-1$
387                 testBidirectionalList.isEmpty());
388     }
389     
390     /***
391      * Tests <code>listIterator()</code> method.
392      */
393     public void testListIterator() {
394         testBidirectionalList.setPropertyValue(new LinkedList());
395         Object object = new Object();
396         mockRelationshipUpdater.expects(once()).method("set").
397                 with(same(object), same(oppositeName), same(owner));
398         mockRelationshipUpdater.expects(once()).method("unset").
399                 with(same(object), same(oppositeName), same(owner));
400         testBidirectionalList.add(object);
401         ListIterator it = testBidirectionalList.listIterator();
402         it.next();
403         it.remove();
404     }
405 
406     /***
407      * Tests <code>listIterator()</code> method.
408      */
409     public void testListIteratorIndexed() {
410         testBidirectionalList.setPropertyValue(new LinkedList());
411         Object object = new Object();
412         mockRelationshipUpdater.expects(once()).method("set").
413                 with(same(object), same(oppositeName), same(owner));
414         mockRelationshipUpdater.expects(once()).method("unset").
415                 with(same(object), same(oppositeName), same(owner));
416         testBidirectionalList.add(object);
417         ListIterator it = testBidirectionalList.listIterator(0);
418         it.next();
419         it.remove();
420     }
421     
422     /***
423      * Tests <code>set()</code> method.
424      */
425     public void testSet() {
426         testBidirectionalList.setPropertyValue(new LinkedList());
427         Object oldObject = new Object();
428         Object object = new Object();
429         int index = 0;
430         
431         mockRelationshipUpdater.expects(once()).method("set").
432                 with(same(oldObject), same(oppositeName), same(owner));
433         testBidirectionalList.add(index, oldObject);
434         assertSame("object should be set at index position.", //$NON-NLS-1$
435                 oldObject, testBidirectionalList.get(index));
436         mockRelationshipUpdater.expects(once()).method("unset").
437                 with(same(oldObject), same(oppositeName), same(owner));
438         
439         mockRelationshipUpdater.expects(once()).method("set").
440                 with(same(object), same(oppositeName), same(owner));
441         testBidirectionalList.set(index, object);
442         
443         assertEquals("testBidirectionalList should contain object at index position.", //$NON-NLS-1$
444                 object, testBidirectionalList.get(index));
445         assertEquals("testBidirectionalList should contain only object.", //$NON-NLS-1$
446                 1, testBidirectionalList.size());
447     }
448     
449     /***
450      * Tests <code>set()</code> method.
451      */
452     public void testSetThrowsException() {
453         testBidirectionalList.setPropertyValue(new LinkedList());
454         Object oldObject = new Object();
455         Object object = new Object();
456         int index = 0;
457         
458         mockRelationshipUpdater.expects(once()).method("set").
459                 with(same(oldObject), same(oppositeName), same(owner));
460         testBidirectionalList.add(index, oldObject);
461         assertSame("object should be set at index position.", //$NON-NLS-1$
462                 oldObject, testBidirectionalList.get(index));
463         mockRelationshipUpdater.expects(once()).method("unset").
464                 with(same(oldObject), same(oppositeName), same(owner));
465         
466         mockRelationshipUpdater.expects(once()).method("set").
467                 with(same(object), same(oppositeName), same(owner)).
468                 will(throwException(new RuntimeException()));
469         mockRelationshipUpdater.expects(once()).method("set").
470                 with(same(oldObject), same(oppositeName), same(owner));
471         try {
472             testBidirectionalList.set(index, object);
473             fail("The exception should have been thrown.");
474         }catch(RuntimeException e) {
475             assertEquals("testBidirectionalList should contain object at index position.", //$NON-NLS-1$
476                     oldObject, testBidirectionalList.get(index));
477             assertEquals("testBidirectionalList should contain only object.", //$NON-NLS-1$
478                     1, testBidirectionalList.size());
479         }
480         
481         
482         
483     }
484 }