1 //----------------------------------------------------------------------
2 //
3 // PerfectJPattern: "Design patterns are good but components are better!"
4 // TestDelegator.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.extras.delegate;
22
23 import java.lang.reflect.*;
24
25 import junit.framework.*;
26
27 import org.perfectjpattern.core.api.extras.delegate.*;
28 import org.slf4j.*;
29
30 /**
31 * Test Suite for {@link Delegator} implementation.
32 * <br/><br/>
33 * <b>Notes</b>: Base source code implemented by Steve Lewis and Wilhelm
34 * Fitzpatrick and adapted to fit PerfectJPattern componentization
35 * criteria and code conventions.
36 *
37 * @see IDelegate
38 * @see IDelegator
39 * @see Delegator
40 * @see DynamicDelegator
41 *
42 * @author <a href="mailto:smlewis@lordjoe.com">Steve Lewis</a>
43 * @author <a href="mailto:wilhelmf@agileinformatics.com">Wilhelm
44 * Fitzpatrick</a>
45 * @author <a href="mailto:bravegag@hotmail.com">Giovanni Azua</a>
46 * @version $Revision: 2.0 $ $Date: Jun 24, 2007 11:16:36 AM $
47 */
48 @SuppressWarnings("unchecked")
49 public
50 class TestDelegator
51 extends TestCase
52 {
53 //------------------------------------------------------------------------
54 // public
55 //------------------------------------------------------------------------
56 public void
57 testIsSuitableMethod()
58 {
59 int myNoArguments = 1;
60 Method[] myPossibilities = AbstractDelegator.findMethod(IStringDisplay.
61 class, "doDisplay", myNoArguments);
62
63 Class myReturnClass = void.class;
64 Class[] myArguments = new Class[] {String.class };
65
66 AbstractDelegator<IStringDisplay> myDelegate = new Delegator<
67 IStringDisplay>(IStringDisplay.class);
68
69 assertTrue("AbstractDelegator.searchCandidateMethods() did not " +
70 "produce the expeted result.", myDelegate.isSuitableMethod(
71 myPossibilities[0], myReturnClass, myArguments));
72 }
73
74 //------------------------------------------------------------------------
75 public void
76 testSearchCandidateMethods()
77 {
78 int myNumberOfArguments = 1;
79 Method[] myPossibilities =
80 AbstractDelegator.findMethod(
81 IBadStringDisplay.class, "doDisplay", myNumberOfArguments);
82
83 assertEquals("AbstractDelegator.searchCandidateMethods() did not " +
84 "return the expected number of matches.", 1,
85 myPossibilities.length);
86
87 assertEquals("AbstractDelegator.searchCandidateMethods() did not " +
88 "find the right match.", "doDisplay",
89 myPossibilities[0].getName());
90 }
91
92 //------------------------------------------------------------------------
93 public void
94 testDelegateBuild()
95 {
96 try
97 {
98 // Target interface must have a single method
99 new Delegator<IBadStringDisplay>(IBadStringDisplay.class);
100 fail("Delegator multiple method interface was not rejected.");
101 }
102 catch (IllegalArgumentException anException)
103 {
104 // ok
105 }
106
107 try
108 {
109 // Target interface must have at least one method
110 new Delegator<IBadStringDisplay2>(IBadStringDisplay2.class);
111 fail("Delegator interface with no methods was not rejected.");
112 }
113 catch (IllegalArgumentException anException)
114 {
115 // ok
116 }
117 }
118
119 //------------------------------------------------------------------------
120 /**
121 * Test calls to <code>Delegator</code>
122 */
123 public void
124 testDelegator()
125 throws Exception
126 {
127 IDelegator<IStringDisplay> myDelegate =
128 new Delegator<IStringDisplay>(IStringDisplay.class);
129
130 Class1 myObject1 = new Class1();
131 Class2 myObject2 = new Class2();
132
133 IStringDisplay[] myItems = new IStringDisplay[3];
134 myItems[0] = myDelegate.build(myObject1, "show");
135 myItems[1] = myDelegate.build(myObject2, "display");
136 myItems[2] = myDelegate.build(Class3.class,
137 "staticDisplay");
138
139 for (int i = 0; i < myItems.length; i++)
140 {
141 IStringDisplay myItem = myItems[i];
142 myItem.doDisplay("test");
143 }
144
145 final int myIterationsCount = 10000;
146 timingTest(myItems, myObject1, myObject2, myIterationsCount);
147 }
148
149 //------------------------------------------------------------------------
150 /**
151 * Test calls to <code>Delegator</code>
152 */
153 public void
154 testDynamicDelegator()
155 throws Exception
156 {
157 IDelegator<IDelegate> myDelegator = new DynamicDelegator(Void.TYPE,
158 String.class);
159
160 Class1 myObject1 = new Class1();
161 Class2 myObject2 = new Class2();
162
163 IDelegate[] myDelegates = new IDelegate[3];
164 myDelegates[0] = myDelegator.build(myObject1, "show");
165 myDelegates[1] = myDelegator.build(myObject2, "display");
166
167 Class3.reset();
168 myDelegates[2] = myDelegator.build(Class3.class, "staticDisplay");
169
170 for (int i = 0; i < myDelegates.length; i++)
171 {
172 IDelegate myDelegate = myDelegates[i];
173 myDelegate.invoke("test");
174 }
175
176 assertEquals("Wrong calls count", 1, myObject1.getCount());
177 assertEquals("Wrong calls count", 1, myObject2.getCount());
178 assertEquals("Wrong calls count", 1, Class3.getCount());
179 }
180
181 //------------------------------------------------------------------------
182 /**
183 * Test of timing - note set iteration large i.e. 1000000 for reasonable
184 * results
185 */
186 public void
187 timingTest(IStringDisplay[] anItems, Class1 anObject1, Class2 anObject2,
188 int anIterations)
189 {
190 // Warm up hotspot
191 for (int i = 0; i < 100; i++)
192 {
193 for (int j = 0; j < anItems.length; j++)
194 {
195 IStringDisplay myItem = anItems[j];
196 myItem.doDisplay("test");
197 }
198
199 anObject1.show("test");
200 anObject2.display("test");
201 Class3.staticDisplay("test");
202 }
203
204 long myStart = System.currentTimeMillis();
205
206 for (int i = 0; i < anIterations; i++)
207 {
208 for (int j = 0; j < anItems.length; j++)
209 {
210 IStringDisplay myItem = anItems[j];
211 myItem.doDisplay("test");
212 }
213 }
214
215 long myEnd = System.currentTimeMillis();
216 double myDelegateTime = (myEnd - myStart) / 1000.;
217 double myPerIteration = (1000. * 1000. * myDelegateTime) / anIterations;
218
219 myStart = System.currentTimeMillis();
220
221 for (int myJ = 0; myJ < anIterations; myJ++)
222 {
223 anObject1.show("test");
224 anObject2.display("test");
225 Class3.staticDisplay("test");
226 }
227
228 myEnd = System.currentTimeMillis();
229
230 double myDirectTime = (myEnd - myStart) / 1000.;
231 double myPerCallIteration = (1000. * 1000. * myDirectTime) /
232 anIterations;
233
234 theLogger.debug("Ran '" + anIterations + "' iterations ");
235 theLogger.debug("Delegator Test took '" + myDelegateTime + "' secs");
236 theLogger.debug("per iteration '" + myPerIteration + " microsecs");
237 theLogger.debug("Direct Calls took '" + myDirectTime + " secs");
238 theLogger.debug("per iteration '" + myPerCallIteration + "' microsecs");
239 }
240
241 //------------------------------------------------------------------------
242 // inner classes
243 //------------------------------------------------------------------------
244 private static
245 interface
246 IStringDisplay
247 {
248 //--------------------------------------------------------------------
249 public void
250 doDisplay(String aValue);
251 }
252
253 //------------------------------------------------------------------------
254 private static
255 interface IBadStringDisplay
256 {
257 //--------------------------------------------------------------------
258 public void
259 doDisplay(String aValue);
260
261 //--------------------------------------------------------------------
262 public void
263 doDisplay2(String aValue);
264 }
265
266 //------------------------------------------------------------------------
267 private static
268 interface IBadStringDisplay2
269 {
270 // empty
271 }
272
273 //------------------------------------------------------------------------
274 private static
275 class Class1
276 {
277 //--------------------------------------------------------------------
278 public void
279 show(String aValue)
280 {
281 theCount++;
282 }
283
284 //--------------------------------------------------------------------
285 public int
286 getCount()
287 {
288 return theCount;
289 }
290
291 //--------------------------------------------------------------------
292 // members
293 //--------------------------------------------------------------------
294 private int theCount;
295 }
296
297 //------------------------------------------------------------------------
298 private static
299 class Class2
300 {
301 //--------------------------------------------------------------------
302 public void
303 display(String aValue)
304 {
305 theCount++;
306 }
307
308 //--------------------------------------------------------------------
309 public int
310 getCount()
311 {
312 return theCount;
313 }
314
315 //--------------------------------------------------------------------
316 // members
317 //--------------------------------------------------------------------
318 private int theCount;
319 }
320
321 //------------------------------------------------------------------------
322 // CHECKSTYLE:OFF
323 private final static
324 class Class3
325 // CHECKSTYLE:ON
326 {
327 //--------------------------------------------------------------------
328 public static void
329 staticDisplay(String aValue)
330 {
331 theCount++;
332 }
333
334 //--------------------------------------------------------------------
335 public static int
336 getCount()
337 {
338 return theCount;
339 }
340
341 //--------------------------------------------------------------------
342 public static void
343 reset()
344 {
345 theCount = 0;
346 }
347
348 //--------------------------------------------------------------------
349 // members
350 //--------------------------------------------------------------------
351 private static int theCount;
352 }
353
354 //------------------------------------------------------------------------
355 // members
356 //------------------------------------------------------------------------
357 /**
358 * Provides logging services for this class.
359 */
360 private final Logger theLogger = LoggerFactory.getLogger(this.getClass());
361 }