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  
30  import org.jmock.Mock;
31  
32  import com.enspire.collections.decorator.CollectionDecorator;
33  import com.enspire.collections.decorator.CollectionDecoratorTest;
34  import com.enspire.gemini.RelationshipUpdater;
35  
36  /***
37   * TODO To change the template for this generated type comment go to
38   * Window - Preferences - Java - Code Style - Code Templates
39   *
40   * @author Dragan Djuric <dragand@dev.java.net>
41   **/
42  public class BidirectionalCollectionTest extends CollectionDecoratorTest {
43  
44      private BidirectionalCollection testBidirectionalCollection;
45  
46      private Mock mockRelationshipUpdater;
47      private Object owner;
48      private String oppositeName = "name";
49  
50      
51      /***
52       * Creates a decorated decorated to test.
53       * @param c a decorated that is being decorated
54       * @return new bean to test
55       */
56      protected CollectionDecorator createTestedCollection(Collection c) {
57          return new BidirectionalCollection();        
58      }
59      
60      /***
61       * @return Returns the mockRelationshipUpdater.
62       */
63      public Mock getMockRelationshipUpdater() {
64          return mockRelationshipUpdater;
65      }
66      
67      /***
68       * @return Returns the owner.
69       */
70      public Object getOwner() {
71          return owner;
72      }
73  
74      /***
75       * @see junit.framework.TestCase#setUp()
76       */
77      protected void setUp() throws Exception {
78          super.setUp();
79          owner = new Object();
80          testBidirectionalCollection = 
81                  (BidirectionalCollection)getTestedCollection();
82          mockRelationshipUpdater = new Mock(RelationshipUpdater.class);
83          testBidirectionalCollection.setOppositeName(oppositeName);
84          RelationshipUpdater relationshipUpdater = 
85                  (RelationshipUpdater)mockRelationshipUpdater.proxy();
86          testBidirectionalCollection.setRelationshipUpdater(relationshipUpdater);
87          testBidirectionalCollection.setOwner(owner);
88          getMockDecorated().expects(once()).method("isEmpty").will(returnValue(true));
89          testBidirectionalCollection.setPropertyValue(getDecorated());
90      }
91      
92      /***
93       * @see com.enspire.collections.decorator.CollectionDecoratorTest#testAdd()
94       */
95      
96      public void testAdd() {
97          testBidirectionalCollection.setPropertyValue(new LinkedList());
98          Object object = new Object();
99          mockRelationshipUpdater.expects(once()).method("set").
100                 with(same(object), same(oppositeName), same(owner));
101         assertTrue("The add method of decoratedCollection collection should be invoked.", //$NON-NLS-1$
102                 testBidirectionalCollection.add(object));
103     }
104     
105     public void testAddExisting() {
106         testBidirectionalCollection.setPropertyValue(new LinkedList());
107         Object object = new Object();
108         mockRelationshipUpdater.expects(once()).method("set").
109                 with(same(object), same(oppositeName), same(owner));
110         assertTrue("object should be added and relationshipUpdater.set invoked.", //$NON-NLS-1$
111                 testBidirectionalCollection.add(object));
112         assertFalse("object should NOT be added and relationshipUpdater.set NOT invoked.", //$NON-NLS-1$
113                 testBidirectionalCollection.add(object));
114     }
115     
116     public void testAddUpdaterThrowsException() {
117         testBidirectionalCollection.setPropertyValue(new LinkedList());
118         Object object = new Object();
119         mockRelationshipUpdater.expects(once()).method("set").
120                 with(same(object), same(oppositeName), same(owner)).will(
121                 throwException(new RuntimeException()));
122         try {
123             testBidirectionalCollection.add(object);
124             fail("RuntimeException should be thrown.");
125         } catch(RuntimeException e) {
126             assertFalse("object should not be added.", 
127                     testBidirectionalCollection.contains(object));
128         }        
129     }
130     
131     /***
132      * @see com.enspire.collections.decorator.CollectionDecoratorTest#testAddAll()
133      */
134     
135     public void testAddAll() {
136         testBidirectionalCollection.setPropertyValue(new LinkedList());
137         Collection coll = new LinkedList();
138         Object ok0 = new Object();
139         Object ok1 = new Object();
140         coll.add(ok0);
141         coll.add(ok1);
142         mockRelationshipUpdater.expects(once()).method("set").
143                 with(same(ok0), same(oppositeName), same(owner));
144         mockRelationshipUpdater.expects(once()).method("set").
145                 with(same(ok1), same(oppositeName), same(owner));
146         assertTrue("coll elements should be added.", 
147                 testBidirectionalCollection.addAll(coll));
148     }
149 
150     public void testAddAllUpdaterThrowsException() {
151         testBidirectionalCollection.setPropertyValue(new LinkedList());
152         Collection coll = new LinkedList();
153         Object ok = new Object();
154         Object wrong = new Object();
155         coll.add(ok);
156         coll.add(wrong);
157         mockRelationshipUpdater.expects(once()).method("set").
158                 with(same(ok), same(oppositeName), same(owner));
159         mockRelationshipUpdater.expects(once()).method("unset").
160                 with(same(ok), same(oppositeName), same(owner));
161         mockRelationshipUpdater.expects(once()).method("set").
162                 with(same(wrong), same(oppositeName), same(owner)).will(
163                         throwException(new RuntimeException()));
164         try {
165             testBidirectionalCollection.addAll(coll);
166             fail("RuntimeException should be thrown.");
167         } catch(RuntimeException e) {
168             assertFalse("ok should not be added.", 
169                     testBidirectionalCollection.contains(ok));
170             assertFalse("wrong should not be added.", 
171                     testBidirectionalCollection.contains(ok));
172         }    
173     }
174     
175     /***
176      * @see com.enspire.collections.decorator.CollectionDecoratorTest#testRemove()
177      */
178     
179     public void testRemove() {
180         Collection unidirectional = new LinkedList();
181         testBidirectionalCollection.setPropertyValue(unidirectional);
182         Object object = new Object();
183         unidirectional.add(object);
184         mockRelationshipUpdater.expects(once()).method("unset").
185                 with(same(object), same(oppositeName), same(owner));
186         assertTrue("The remove method of decoratedCollection collection should be invoked.", //$NON-NLS-1$
187                 testBidirectionalCollection.remove(object));
188     }
189     
190     public void testRemoveNonExisting() {
191         testBidirectionalCollection.setPropertyValue(new LinkedList());
192         Object object = new Object();
193         assertFalse("object should NOT be removed and relationshipUpdater.unset NOT invoked.", //$NON-NLS-1$
194                 testBidirectionalCollection.remove(object));
195     }
196     
197     public void testRemoveUpdaterThrowsException() {
198         Collection unidirectional = new LinkedList();
199         testBidirectionalCollection.setPropertyValue(unidirectional);
200         Object object = new Object();
201         unidirectional.add(object);
202         mockRelationshipUpdater.expects(once()).method("unset").
203                 with(same(object), same(oppositeName), same(owner)).will(
204                 throwException(new RuntimeException()));
205         try {
206             testBidirectionalCollection.remove(object);
207             fail("RuntimeException should be thrown.");
208         } catch(RuntimeException e) {
209             assertTrue("object should not be removed.", 
210                     testBidirectionalCollection.contains(object));
211         }        
212     }
213     
214     /***
215      * @see com.enspire.collections.decorator.CollectionDecoratorTest#testRemoveAll()
216      */
217     
218     public void testRemoveAll() {
219         Collection unidirectional = new LinkedList();
220         testBidirectionalCollection.setPropertyValue(unidirectional);
221         Collection coll = new LinkedList();
222         Object ok0 = new Object();
223         Object ok1 = new Object();
224         unidirectional.add(ok0);
225         unidirectional.add(ok1);
226         coll.add(ok0);
227         coll.add(ok1);
228         mockRelationshipUpdater.expects(once()).method("unset").
229                 with(same(ok0), same(oppositeName), same(owner));
230         mockRelationshipUpdater.expects(once()).method("unset").
231                 with(same(ok1), same(oppositeName), same(owner));
232         assertTrue("coll elements should be removed.", 
233                 testBidirectionalCollection.removeAll(coll));
234     }
235 
236     public void testRemoveAllUpdaterThrowsException() {
237         Collection unidirectional = new LinkedList();
238         testBidirectionalCollection.setPropertyValue(unidirectional);
239         Collection coll = new LinkedList();
240         Object ok = new Object();
241         Object wrong = new Object();
242         unidirectional.add(ok);
243         unidirectional.add(wrong);
244         coll.add(ok);
245         coll.add(wrong);
246         mockRelationshipUpdater.expects(once()).method("unset").
247                 with(same(ok), same(oppositeName), same(owner));
248         mockRelationshipUpdater.expects(once()).method("set").
249                 with(same(ok), same(oppositeName), same(owner));
250         mockRelationshipUpdater.expects(once()).method("unset").
251                 with(same(wrong), same(oppositeName), same(owner)).will(
252                         throwException(new RuntimeException()));
253         try {
254             testBidirectionalCollection.removeAll(coll);
255             fail("RuntimeException should be thrown.");
256         } catch(RuntimeException e) {
257             assertTrue("ok should not be removed.", 
258                     testBidirectionalCollection.contains(ok));
259             assertTrue("wrong should not be removed.", 
260                     testBidirectionalCollection.contains(ok));
261         }    
262     }
263     
264     /***
265      * Tests <code>retainAll()</code> method.
266      */
267     public void testRetainAll() {
268         try {
269             testBidirectionalCollection.retainAll(null);
270             fail("The operation should throw an exception, it is unsupported.");
271         } catch (UnsupportedOperationException e) {
272             assertTrue("retainAll() is not supported.", true);
273         }
274     }
275     
276     /***
277      * Tests <code>clear()</code> method.
278      */
279     public void testClear() {
280         try {
281             testBidirectionalCollection.clear();
282             fail("The operation should throw an exception, it is unsupported.");
283         } catch (UnsupportedOperationException e) {
284             assertTrue("clear() is not supported.", true);
285         }
286     }
287     
288     /***
289      * Tests <code>contains()</code> method.
290      */
291     public void testContains() {
292         Object object = new Object();
293         assertFalse("The contains method of decoratedCollection collection should be " + //$NON-NLS-1$
294                 "invoked.", testBidirectionalCollection.contains(object)); //$NON-NLS-1$
295     }
296     
297     public void testContainsAll() {
298         testBidirectionalCollection.setPropertyValue(new LinkedList());
299         Collection coll = new LinkedList();
300         Object ok0 = new Object();
301         Object ok1 = new Object();
302         coll.add(ok0);
303         coll.add(ok1);
304         mockRelationshipUpdater.expects(once()).method("set").
305                 with(same(ok0), same(oppositeName), same(owner));
306         mockRelationshipUpdater.expects(once()).method("set").
307                 with(same(ok1), same(oppositeName), same(owner));
308         assertTrue("coll elements should be added.", 
309                 testBidirectionalCollection.addAll(coll));
310         assertTrue("testBidirectionalCollection should contain coll elements.",
311                 testBidirectionalCollection.containsAll(coll));
312     }
313 
314     /***
315      * Tests <code>iterator()</code> method.
316      */
317     public void testIterator() {
318         testBidirectionalCollection.setPropertyValue(new LinkedList());
319         Object object = new Object();
320         mockRelationshipUpdater.expects(once()).method("set").
321                 with(same(object), same(oppositeName), same(owner));
322         mockRelationshipUpdater.expects(once()).method("unset").
323                 with(same(object), same(oppositeName), same(owner));
324         testBidirectionalCollection.add(object);
325         Iterator it = testBidirectionalCollection.iterator();
326         it.next();
327         it.remove();
328     }
329 
330 }