Clover Coverage Report - perfectjpattern(Aggregated)
Coverage timestamp: Sat Feb 28 2009 14:35:07 CET
85   419   23   4.72
6   255   0.27   4.5
18     1.28  
4    
0.9% of code in this file is excluded from these metrics.
 
  TestSubject       Line # 39 75 1.1% 14 2 97.7% 0.97727275
  TestSubject.MyEventData       Line # 208 2 0% 2 0 100% 1.0
  TestSubject.TestStatusObserver       Line # 335 6 0% 5 1 92.3% 0.9230769
  TestSubject.TestProgressObserver       Line # 380 2 0% 2 0 100% 1.0
 
  (6)
 
1    //----------------------------------------------------------------------
2    //
3    // PerfectJPattern: "Design patterns are good but components are better!"
4    // TestSubject.java Copyright (c) 2009 Giovanni Azua Garcia
5    // bravegag@hotmail.com
6    //
7    // This program is free software; you can redistribute it and/or
8    // modify it under the terms of the GNU General Public License
9    // as published by the Free Software Foundation; either version 3
10    // of the License, or (at your option) any later version.
11    //
12    // This program is distributed in the hope that it will be useful,
13    // but WITHOUT ANY WARRANTY; without even the implied warranty of
14    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15    // GNU General Public License for more details.
16    //
17    // You should have received a copy of the GNU General Public License
18    // along with this program; if not, see <http://www.gnu.org/licenses/>.
19    //
20    //----------------------------------------------------------------------
21    package org.perfectjpattern.core.behavioral.observer;
22   
23    import java.util.*;
24   
25    import junit.framework.*;
26   
27    import org.perfectjpattern.core.api.behavioral.observer.*;
28    import org.perfectjpattern.core.api.behavioral.observer.data.*;
29    import org.perfectjpattern.core.behavioral.observer.data.*;
30    import org.slf4j.*;
31   
32    /**
33    * Test Suite for <code>Subject</code> implementation.
34    *
35    * @author <a href="mailto:bravegag@hotmail.com">Giovanni Azua</a>
36    * @version $Revision: 1.0 $ $Date: Jun 18, 2007 11:31:53 PM $
37    */
38    public final
 
39    class TestSubject
40    extends TestCase
41    {
42    //------------------------------------------------------------------------
43    // public
44    //------------------------------------------------------------------------
 
45  1 toggle @SuppressWarnings("unchecked")
46    public void
47    testFaultyObserverDetached()
48    {
49    // create a faulty Observer instance
50  1 IObserver<NullEventData> myObserver =
51    new IObserver<NullEventData>()
52    {
53    //----------------------------------------------------------------
 
54  1 toggle public void
55    update(NullEventData anEventData)
56    {
57    throw new RuntimeException("Sorry! I am faulty!");
58    }
59    };
60   
61    // create Subject instance, attach and notify
62  1 ISubject<NullEventData> mySubject = new Subject<NullEventData>();
63  1 mySubject.attach(myObserver);
64   
65  1 try
66    {
67  1 mySubject.notifyObservers(NullEventData.getInstance());
68    }
69    // CHECKSTYLE:OFF
70    catch (RuntimeException anException)
71    // CHECKSTYLE:ON
72    {
73  0 fail("Subject is not protected from faulty Observer instances");
74    }
75   
76  1 assertEquals("Subject did not automatically detach faulty Observers",
77    0, mySubject.size());
78    }
79   
80    //------------------------------------------------------------------------
81    /**
82    * Test that <code>IStatusData</code> notifications were properly sent to
83    * all registered <code>IObserver</code> instances.
84    */
 
85  1 toggle public void
86    testStatusObserver()
87    {
88  1 theLogger.debug("Running assertions ... ");
89   
90  1 assertEquals(
91    "First observer incorrectly received completion notifications.",
92    1, theFirstObserver.getSuccessCount());
93  1 assertEquals(
94    "First observer incorrectly received failure notifications.",
95    1, theFirstObserver.getFailureCount());
96   
97  1 assertEquals(
98    "Second observer incorrectly missed completion notifications.",
99    2, theSecondObserver.getSuccessCount());
100  1 assertEquals(
101    "Second observer incorrectly missed failure notifications.", 2,
102    theSecondObserver.getFailureCount());
103   
104  1 assertEquals(
105    "Third observer incorrectly missed completion notifications.",
106    2, theThirdObserver.getSuccessCount());
107  1 assertEquals(
108    "Third observer incorrectly missed failure notifications.", 2,
109    theThirdObserver.getFailureCount());
110   
111  1 theLogger.debug("Completed test");
112    }
113   
114    //------------------------------------------------------------------------
115    /**
116    * Test that <code>IProgressData</code> notifications were properly sent
117    * to all registered <code>IObserver</code> instances.
118    */
 
119  1 toggle public void
120    testProgressObserver()
121    {
122  1 theLogger.debug("Running assertions ... ");
123   
124  1 List<ProgressData> myExpectedProgress = Arrays
125    .asList(new ProgressData[] {
126    ProgressData.STARTED,
127    new ProgressData(Status.IN_PROGRESS,
128    "Testing in progress ...", 20),
129    new ProgressData(Status.IN_PROGRESS,
130    "Testing in progress ...", 40),
131    new ProgressData(Status.IN_PROGRESS,
132    "Testing in progress ...", 60),
133    new ProgressData(Status.IN_PROGRESS,
134    "Testing in progress ...", 80),
135    ProgressData.COMPLETED });
136   
137  1 int i = 0;
138  1 for (ProgressData myProgress : theFourthObserver.getProgress())
139    {
140  6 assertEquals("Invalid progress notification sequence.",
141    myExpectedProgress.get(i++), myProgress);
142    }
143   
144  1 theLogger.debug("Completed test");
145    }
146   
147    //------------------------------------------------------------------------
 
148  1 toggle @SuppressWarnings("unchecked")
149    public void
150    testClear()
151    {
152  1 theLogger.debug("Running assertions ... ");
153   
154  1 ISubject<NullEventData> mySubject = new Subject<NullEventData>();
155   
156    // attach an observer
157  1 mySubject.attach(new IObserver<NullEventData>()
158    {
159    //----------------------------------------------------------------
 
160  0 toggle public void
161    update(NullEventData anEventData)
162    {
163    // nothing to do
164    }
165    });
166   
167  1 assertEquals("Size method implemented incorrectly.", 1,
168    mySubject.size());
169   
170    // should empty the collection of observers
171  1 mySubject.clear();
172   
173  1 assertEquals("Clear method implemented incorrectly.", 0,
174    mySubject.size());
175   
176  1 theLogger.debug("Completed test");
177    }
178   
179    //------------------------------------------------------------------------
180    /**
181    * Test that <code>ISubject</code> keeps a correct number of
182    * <code>IObserver</code> attached.
183    */
 
184  1 toggle public void
185    testSize()
186    {
187  1 theLogger.debug("Running assertions ... ");
188   
189  1 assertEquals("Status Subject contains invalid amount of observers", 2,
190    theStatusSubject.size());
191  1 assertEquals("Progress Subject contains invalid amount of observers",
192    1, theProgressSubject.size());
193   
194  1 theLogger.debug("Completed test");
195    }
196   
197    //------------------------------------------------------------------------
198    /**
199    * Simple test of the Observer pattern
200    */
 
201  1 toggle @SuppressWarnings("unchecked")
202    public void
203    testSimple()
204    {
205  1 theLogger.debug("Started simple Observer usage test");
206   
207  1 theLogger.debug("Step #1 := Define Event data type");
 
208    class MyEventData implements IEventData
209    {
210    //----------------------------------------------------------------
 
211  1 toggle public
212    MyEventData(final String aValue)
213    {
214  1 theValue = aValue;
215    }
216   
217    //----------------------------------------------------------------
 
218  1 toggle public final String
219    getValue()
220    {
221  1 return theValue;
222    }
223   
224    //----------------------------------------------------------------
225    private final String theValue;
226    }
227   
228  1 theLogger.debug("Step #2 := Define Observer instance");
229  1 IObserver<MyEventData> myObserver = new IObserver<MyEventData>()
230    {
231    //----------------------------------------------------------------
 
232  1 toggle public void
233    update(MyEventData anEventData)
234    {
235  1 theLogger.debug("update call received with data: " +
236    anEventData.getValue());
237    }
238    };
239   
240  1 theLogger.debug("Step #3 := Create ISubject instance");
241  1 ISubject<MyEventData> mySubject = new Subject<MyEventData>();
242   
243  1 theLogger.debug("Step #4 := Attach Observer to Subject");
244  1 mySubject.attach(myObserver);
245   
246  1 theLogger.debug("Step #5 := Notify observers");
247  1 mySubject.notifyObservers(new MyEventData("Hello Observer!"));
248   
249  1 theLogger.debug("Completed test");
250    }
251   
252    //------------------------------------------------------------------------
253    // protected
254    //------------------------------------------------------------------------
 
255  6 toggle @Override
256    protected void
257    setUp()
258    throws Exception
259    {
260  6 super.setUp();
261   
262  6 theLogger.debug("Creating Observer pattern test fixture ... ");
263   
264    // fixture for the usage of the Observer Pattern
265  6 fixture();
266   
267  6 theLogger.debug("Completed Observer pattern test fixture.");
268    }
269   
270    //------------------------------------------------------------------------
271    // private
272    //------------------------------------------------------------------------
273    /**
274    * Example usage of the Observer Pattern.
275    */
 
276  6 toggle @SuppressWarnings("unchecked")
277    private void
278    fixture()
279    {
280    //
281    // Status notification example
282    //
283  6 theLogger.debug("Step #1 := Create ISubject instance.");
284  6 theStatusSubject = new Subject<StatusData>();
285   
286  6 theLogger.debug("Step #2 := Create IObserver instances.");
287  6 theFirstObserver = new TestStatusObserver();
288  6 theSecondObserver = new TestStatusObserver();
289  6 theThirdObserver = new TestStatusObserver();
290   
291  6 theLogger.debug("Step #3 := Attach IObserver to ISubject.");
292  6 theStatusSubject.attach(theFirstObserver, theSecondObserver,
293    theThirdObserver);
294   
295  6 theLogger.debug("Step #4 := Send notifications.");
296  6 theStatusSubject.notifyObservers(StatusData.FAILED);
297  6 theStatusSubject.notifyObservers(StatusData.COMPLETED);
298   
299  6 theLogger.debug("Eventually detach observers.");
300  6 theStatusSubject.detach(theFirstObserver);
301   
302  6 theLogger.debug("Send more notifications.");
303  6 theStatusSubject.notifyObservers(StatusData.FAILED);
304  6 theStatusSubject.notifyObservers(StatusData.COMPLETED);
305   
306    //
307    // Progress notification example
308    //
309  6 theLogger.debug("Step #1 := Create ISubject instance.");
310  6 theProgressSubject = new Subject<ProgressData>();
311   
312  6 theLogger.debug("Step #2 := Create IObserver instances.");
313  6 theFourthObserver = new TestProgressObserver();
314   
315  6 theLogger.debug("Step #3 := Attach IObserver to ISubject.");
316  6 theProgressSubject.attach(theFourthObserver);
317   
318  6 theLogger.debug("Step #4 := Send notifications.");
319  6 theProgressSubject.notifyObservers(ProgressData.STARTED);
320  30 for (int myI = 1; myI < 5; myI++)
321    {
322  24 theProgressSubject.notifyObservers(new ProgressData(
323    Status.IN_PROGRESS, "Testing in progress ...", 5, myI));
324    }
325  6 theProgressSubject.notifyObservers(ProgressData.COMPLETED);
326    }
327   
328    //------------------------------------------------------------------------
329    // inner classes
330    //------------------------------------------------------------------------
331    /**
332    * Concrete <code>IObserver&lt;StatusData&gt;</code> implementation.
333    */
334    private static final
 
335    class TestStatusObserver
336    implements IObserver<StatusData>
337    {
338    //---------------------------------------------------------------------
 
339  3 toggle public final int
340    getSuccessCount()
341    {
342  3 return theSuccessCount;
343    }
344   
345    //---------------------------------------------------------------------
 
346  3 toggle public final int
347    getFailureCount()
348    {
349  3 return theFailureCount;
350    }
351   
352    //---------------------------------------------------------------------
 
353  60 toggle public void
354    update(StatusData aStatusData)
355    {
356  60 if (Status.COMPLETED == aStatusData.getStatus())
357    {
358  30 theSuccessCount++;
359    }
360    else
361  30 if (Status.FAILED == aStatusData.getStatus())
362    {
363  30 theFailureCount++;
364    }
365    }
366   
367    //---------------------------------------------------------------------
368    // members
369    //---------------------------------------------------------------------
370    private int theFailureCount = 0;
371    private int theSuccessCount = 0;
372    }
373   
374    //------------------------------------------------------------------------
375    /**
376    * Example of concrete <code>IObserver&lt;ProgressData&gt;</code>
377    * implementation.
378    */
379    private static final
 
380    class TestProgressObserver
381    implements IObserver<ProgressData>
382    {
383    //---------------------------------------------------------------------
 
384  36 toggle public void
385    update(ProgressData aProgressData)
386    {
387  36 theProgress.add(aProgressData);
388    }
389   
390    //---------------------------------------------------------------------
 
391  1 toggle public final
392    Collection<ProgressData>
393    getProgress()
394    {
395  1 return theProgress;
396    }
397   
398    //---------------------------------------------------------------------
399    // members
400    //---------------------------------------------------------------------
401    private Collection<ProgressData> theProgress =
402    new ArrayList<ProgressData>();
403    }
404   
405    //------------------------------------------------------------------------
406    // members
407    //------------------------------------------------------------------------
408    private ISubject<StatusData> theStatusSubject = null;
409    private ISubject<ProgressData> theProgressSubject = null;
410    private TestStatusObserver theFirstObserver = null;
411    private TestStatusObserver theSecondObserver = null;
412    private TestStatusObserver theThirdObserver = null;
413    private TestProgressObserver theFourthObserver = null;
414   
415    /**
416    * Provides logging services for this class.
417    */
418    private final Logger theLogger = LoggerFactory.getLogger(this.getClass());
419    }