1 package org.apache.jcs.engine;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.IOException;
23 import java.io.Serializable;
24
25 import junit.extensions.ActiveTestSuite;
26 import junit.framework.Test;
27 import junit.framework.TestCase;
28
29 import org.apache.jcs.engine.behavior.ICacheElement;
30 import org.apache.jcs.engine.behavior.ICacheListener;
31
32 /***
33 * This test case is designed to makes sure there are no deadlocks in the event
34 * queue. The time to live should be set to a very short interval to make a
35 * deadlock more likely.
36 *
37 * @author Aaron Smuts
38 */
39 public class EventQueueConcurrentLoadTest
40 extends TestCase
41 {
42
43 private static CacheEventQueue queue = null;
44
45 private static CacheListenerImpl listen = null;
46
47 private int maxFailure = 3;
48
49 private int waitBeforeRetry = 100;
50
51
52 private int idleTime = 2;
53
54 /***
55 * Constructor for the TestDiskCache object.
56 *
57 * @param testName
58 */
59 public EventQueueConcurrentLoadTest( String testName )
60 {
61 super( testName );
62 }
63
64 /***
65 * Main method passes this test to the text test runner.
66 *
67 * @param args
68 */
69 public static void main( String args[] )
70 {
71 String[] testCaseName = { EventQueueConcurrentLoadTest.class.getName() };
72 junit.textui.TestRunner.main( testCaseName );
73 }
74
75 /***
76 * A unit test suite for JUnit
77 *
78 * @return The test suite
79 */
80 public static Test suite()
81 {
82
83 ActiveTestSuite suite = new ActiveTestSuite();
84
85 suite.addTest( new EventQueueConcurrentLoadTest( "testRunPutTest1" )
86 {
87 public void runTest()
88 throws Exception
89 {
90 this.runPutTest( 200, 200 );
91 }
92 } );
93
94 suite.addTest( new EventQueueConcurrentLoadTest( "testRunPutTest2" )
95 {
96 public void runTest()
97 throws Exception
98 {
99 this.runPutTest( 1200, 1400 );
100 }
101 } );
102
103 suite.addTest( new EventQueueConcurrentLoadTest( "testRunRemoveTest1" )
104 {
105 public void runTest()
106 throws Exception
107 {
108 this.runRemoveTest( 2200 );
109 }
110 } );
111
112 suite.addTest( new EventQueueConcurrentLoadTest( "testStopProcessing1" )
113 {
114 public void runTest()
115 throws Exception
116 {
117 this.runStopProcessingTest();
118 }
119 } );
120
121 suite.addTest( new EventQueueConcurrentLoadTest( "testRunPutTest4" )
122 {
123 public void runTest()
124 throws Exception
125 {
126 this.runPutTest( 5200, 6600 );
127 }
128 } );
129
130 suite.addTest( new EventQueueConcurrentLoadTest( "testRunRemoveTest2" )
131 {
132 public void runTest()
133 throws Exception
134 {
135 this.runRemoveTest( 5200 );
136 }
137 } );
138
139 suite.addTest( new EventQueueConcurrentLoadTest( "testStopProcessing2" )
140 {
141 public void runTest()
142 throws Exception
143 {
144 this.runStopProcessingTest();
145 }
146 } );
147
148 suite.addTest( new EventQueueConcurrentLoadTest( "testRunPutDelayTest" )
149 {
150 public void runTest()
151 throws Exception
152 {
153 this.runPutDelayTest( 100, 6700 );
154 }
155 } );
156
157 return suite;
158 }
159
160 /***
161 * Test setup. Create the static queue to be used by all tests
162 */
163 public void setUp()
164 {
165 listen = new CacheListenerImpl();
166 queue = new CacheEventQueue( listen, 1L, "testCache1", maxFailure, waitBeforeRetry );
167
168 queue.setWaitToDieMillis( idleTime );
169 }
170
171 /***
172 * Adds put events to the queue.
173 *
174 * @param end
175 * @param expectedPutCount
176 * @throws Exception
177 */
178 public void runPutTest( int end, int expectedPutCount )
179 throws Exception
180 {
181 for ( int i = 0; i <= end; i++ )
182 {
183 CacheElement elem = new CacheElement( "testCache1", i + ":key", i + "data" );
184 queue.addPutEvent( elem );
185 }
186
187 while ( !queue.isEmpty() )
188 {
189 synchronized ( this )
190 {
191 System.out.println( "queue is still busy, waiting 250 millis" );
192 this.wait( 250 );
193 }
194 }
195 System.out.println( "queue is empty, comparing putCount" );
196
197
198
199 assertTrue( "The put count [" + listen.putCount + "] is below the expected minimum threshold ["
200 + expectedPutCount + "]", listen.putCount >= ( expectedPutCount - 1 ) );
201
202 }
203
204 /***
205 * Add remove events to the event queue.
206 *
207 * @param end
208 * @throws Exception
209 */
210 public void runRemoveTest( int end )
211 throws Exception
212 {
213 for ( int i = 0; i <= end; i++ )
214 {
215 queue.addRemoveEvent( i + ":key" );
216 }
217
218 }
219
220 /***
221 * Add remove events to the event queue.
222 *
223 * @throws Exception
224 */
225 public void runStopProcessingTest()
226 throws Exception
227 {
228 queue.stopProcessing();
229 }
230
231 /***
232 * Test putting and a delay. Waits until queue is empty to start.
233 *
234 * @param end
235 * @param expectedPutCount
236 * @throws Exception
237 */
238 public void runPutDelayTest( int end, int expectedPutCount )
239 throws Exception
240 {
241 while ( !queue.isEmpty() )
242 {
243 synchronized ( this )
244 {
245 System.out.println( "queue is busy, waiting 250 millis to begin" );
246 this.wait( 250 );
247 }
248 }
249 System.out.println( "queue is empty, begin" );
250
251
252 CacheElement elem = new CacheElement( "testCache1", "a:key", "adata" );
253 queue.addPutEvent( elem );
254
255 for ( int i = 0; i <= end; i++ )
256 {
257 synchronized ( this )
258 {
259 if ( i % 2 == 0 )
260 {
261 this.wait( idleTime );
262 }
263 else
264 {
265 this.wait( idleTime / 2 );
266 }
267 }
268 CacheElement elem2 = new CacheElement( "testCache1", i + ":key", i + "data" );
269 queue.addPutEvent( elem2 );
270 }
271
272 while ( !queue.isEmpty() )
273 {
274 synchronized ( this )
275 {
276 System.out.println( "queue is still busy, waiting 250 millis" );
277 this.wait( 250 );
278 }
279 }
280 System.out.println( "queue is empty, comparing putCount" );
281
282 Thread.sleep( 1000 );
283
284
285
286 assertTrue( "The put count [" + listen.putCount + "] is below the expected minimum threshold ["
287 + expectedPutCount + "]", listen.putCount >= ( expectedPutCount - 1 ) );
288
289 }
290
291 /***
292 * This is a dummy cache listener to use when testing the event queue.
293 */
294 private class CacheListenerImpl
295 implements ICacheListener
296 {
297
298 /***
299 * <code>putCount</code>
300 */
301 protected int putCount = 0;
302
303 /***
304 * <code>removeCount</code>
305 */
306 protected int removeCount = 0;
307
308
309
310
311
312
313 public void handlePut( ICacheElement item )
314 throws IOException
315 {
316 synchronized ( this )
317 {
318 putCount++;
319 }
320 }
321
322
323
324
325
326
327
328 public void handleRemove( String cacheName, Serializable key )
329 throws IOException
330 {
331 synchronized ( this )
332 {
333 removeCount++;
334 }
335
336 }
337
338
339
340
341
342
343 public void handleRemoveAll( String cacheName )
344 throws IOException
345 {
346
347
348 }
349
350
351
352
353
354
355 public void handleDispose( String cacheName )
356 throws IOException
357 {
358
359
360 }
361
362
363
364
365
366
367 public void setListenerId( long id )
368 throws IOException
369 {
370
371
372 }
373
374
375
376
377
378
379 public long getListenerId()
380 throws IOException
381 {
382
383 return 0;
384 }
385
386 }
387 }