KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > de > susebox > jtopas > TestMultithreadTokenizerProperties


1 /*
2  * TestMultithreadTokenizerProperties.java: JUnit test for TokenizerProperties implementations
3  *
4  * Copyright (C) 2002 Heiko Blau
5  *
6  * This file belongs to the JTopas test suite.
7  * The JTopas test suite is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by the
9  * Free Software Foundation; either version 2.1 of the License, or (at your option)
10  * any later version.
11  *
12  * This software is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.
15  * See the GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License along
18  * with the JTopas test suite. If not, write to the
19  *
20  * Free Software Foundation, Inc.
21  * 59 Temple Place, Suite 330,
22  * Boston, MA 02111-1307
23  * USA
24  *
25  * or check the Internet: http://www.fsf.org
26  *
27  * The JTopas test suite uses the test framework JUnit by Kent Beck and Erich Gamma.
28  * You should have received a copy of their JUnit licence agreement along with
29  * the JTopas test suite.
30  *
31  * We do NOT provide the JUnit archive junit.jar nessecary to compile and run
32  * our tests, since we assume, that You either have it already or would like
33  * to get the current release Yourself.
34  * Please visit either:
35  * http://sourceforge.net/projects/junit
36  * or
37  * http://junit.org
38  * to obtain JUnit.
39  *
40  * Contact:
41  * email: heiko@susebox.de
42  */

43
44 package de.susebox.jtopas;
45
46 //-----------------------------------------------------------------------------
47
// Imports
48
//
49
import java.util.Iterator JavaDoc;
50 import java.util.Random JavaDoc;
51 import java.util.Map JavaDoc;
52 import java.util.HashMap JavaDoc;
53 import java.util.Collections JavaDoc;
54
55 import junit.framework.Test;
56 import junit.framework.TestCase;
57 import junit.framework.TestSuite;
58 import junit.framework.Assert;
59
60 import de.susebox.java.lang.ExtRuntimeException;
61 import de.susebox.jtopas.spi.DataProvider;
62 import de.susebox.jtopas.spi.KeywordHandler;
63 import de.susebox.jtopas.spi.SequenceHandler;
64 import de.susebox.jtopas.spi.PatternHandler;
65 import de.susebox.jtopas.spi.WhitespaceHandler;
66 import de.susebox.jtopas.spi.SeparatorHandler;
67
68 import de.susebox.TestUtilities;
69
70 //-----------------------------------------------------------------------------
71
// Class TestMultithreadTokenizerProperties
72
//
73

74 /**<p>
75  * This class tests the implementations of {@link TokenizerProperties}.
76  *</p>
77  *
78  * @see TokenizerProperties
79  * @see TokenizerPropertyListener
80  * @author Heiko Blau
81  */

82 public class TestMultithreadTokenizerProperties
83   extends TestCase
84   implements TokenizerPropertyListener, DataProvider {
85   
86   //---------------------------------------------------------------------------
87
// main method
88
//
89

90   /**
91    * call this method to invoke the tests.
92    */

93   public static void main(String JavaDoc[] args) {
94     String JavaDoc[] tests = { TestMultithreadTokenizerProperties.class.getName() };
95
96     TestUtilities.run(tests, args);
97   }
98   
99
100   //---------------------------------------------------------------------------
101
// suite method
102
//
103

104   /**
105    * Implementation of the JUnit method <code>suite</code>. For each set of test
106    * properties one or more tests are instantiated.
107    *
108    * @return a test suite
109    */

110   public static Test suite() {
111     TestSuite suite = new TestSuite(TestMultithreadTokenizerProperties.class.getName());
112     
113     suite.addTest(new TestMultithreadTokenizerProperties("testParallelModification"));
114     return suite;
115   }
116   
117   
118   //---------------------------------------------------------------------------
119
// Constructor
120
//
121

122   /**
123    * Default constructor. Standard input {@link java.lang.System#in} is used
124    * to construct the input stream reader.
125    */

126   public TestMultithreadTokenizerProperties(String JavaDoc test) {
127     super(test);
128   }
129
130   
131   //---------------------------------------------------------------------------
132
// Fixture setup and release
133
//
134

135     /**
136      * Sets up the fixture, for example, open a network connection.
137      * This method is called before a test is executed.
138      */

139   protected void setUp() throws Exception JavaDoc {
140     _properties = new StandardTokenizerProperties();
141     _properties.addTokenizerPropertyListener(this);
142     _eventRecord = new HashMap JavaDoc(101);
143     // _eventRecord = new HashMap(101);
144
}
145
146   
147     /**
148      * Tears down the fixture, for example, close a network connection.
149      * This method is called after a test is executed.
150      */

151     protected void tearDown() throws Exception JavaDoc {}
152
153   
154   //---------------------------------------------------------------------------
155
// test cases
156
//
157

158   /**
159    * Testing generic methods.
160    */

161   public void testParallelModification() throws Throwable JavaDoc {
162     System.out.println("Number of threads: " + _numberOfThreads);
163     System.out.println("Test duration (s): " + _duration);
164
165     Random JavaDoc random = new Random JavaDoc();
166     StringBuffer JavaDoc[] active = new StringBuffer JavaDoc[_numberOfThreads];
167     String JavaDoc[] last = new String JavaDoc[_numberOfThreads];
168     Runner[] runner = new Runner[_numberOfThreads];
169     Thread JavaDoc[] thread = new Thread JavaDoc[_numberOfThreads];
170     long start = System.currentTimeMillis();
171
172     // Create resources
173
for (int index = 0; index < _numberOfThreads; ++index) {
174       active[index] = new StringBuffer JavaDoc("0");
175       runner[index] = new Runner(this, random.nextInt(_testProperties.length - 1), 2, active[index]);
176       thread[index] = new Thread JavaDoc(runner[index]);
177     }
178       
179     // start threads and check actions
180
try {
181       for (int index = 0; index < _numberOfThreads; ++index) {
182         thread[index].start();
183       }
184
185       while (System.currentTimeMillis() - start < _duration * 1000) {
186         synchronized(this) {
187           try {
188             wait(3000);
189           } catch (InterruptedException JavaDoc ex) {}
190         }
191
192         // print activity
193
for (int index = 0; index < _numberOfThreads; ++index) {
194           System.out.println(System.currentTimeMillis() + ": Activity at runner " + index + ": " + active[index]);
195           last[index] = active[index].toString();
196         }
197       }
198       
199       // stop the threads
200
for (int index = 0; index < _numberOfThreads; ++index) {
201         runner[index].stop();
202       }
203       Thread.sleep(5000);
204
205       
206       // check activity
207
for (int index = 0; index < _numberOfThreads; ++index) {
208         String JavaDoc activity = active[index].toString();
209         
210         assertTrue("No good activity at runner " + index + ": " + activity,
211                     new Integer JavaDoc(activity).intValue() > (600 / _numberOfThreads) * _duration);
212       }
213       
214     } finally {
215       for (int index = 0; index < _numberOfThreads; ++index) {
216         thread[index] = null;
217       }
218     }
219   }
220   
221   
222   //---------------------------------------------------------------------------
223
// TokenizerPropertyListener implementation
224
//
225

226   /**
227    * Event handler method. The given {@link TokenizerPropertyEvent} parameter
228    * contains the nessecary information about the property change.
229    *
230    * @param event the {@link TokenizerPropertyEvent} that describes the change
231    */

232   public void propertyChanged(TokenizerPropertyEvent event) {
233     TokenizerProperty prop = event.getProperty();
234     String JavaDoc name = Thread.currentThread().getName();
235
236     switch (event.getType()) {
237     case TokenizerPropertyEvent.PROPERTY_MODIFIED:
238       assertTrue("Modified non-existing property " + prop, _eventRecord.containsKey(prop));
239       assertTrue("Property does not exist: " + prop, _properties.propertyExists(prop));
240       break;
241
242     case TokenizerPropertyEvent.PROPERTY_ADDED:
243       assertTrue("Added existing property " + prop, _eventRecord.put(prop, prop) == null);
244       assertTrue("Property does not exist: " + prop, _properties.propertyExists(prop));
245       break;
246
247     case TokenizerPropertyEvent.PROPERTY_REMOVED:
248       assertTrue("Removed not added property " + prop, _eventRecord.remove(prop) != null);
249       assertTrue("Property still exists: " + prop, ! _properties.propertyExists(prop));
250       break;
251     }
252   }
253   
254   /**
255    * See {@link de.susebox.jtopas.spi.DataProvider} for details.
256    *
257    * @return the character buffer to read data from
258    */

259   public char[] getData() {
260     return _currData;
261   }
262
263   /**
264    * See {@link de.susebox.jtopas.spi.DataProvider} for details.
265    *
266    * @return a copy of the valid data of this {@link DataProvider}
267    * @see #getData
268    */

269   public char[] getDataCopy() {
270     char[] dst = new char[_currDataLength];
271     
272     System.arraycopy(_currData, _currStartPos, dst, 0, _currDataLength);
273     return dst;
274   }
275   
276   /**
277    * See {@link de.susebox.jtopas.spi.DataProvider} for details.
278    *
279    * @param testChar check this character
280    * @return <code>true</code> if the given character is a separator,
281    * <code>false</code> otherwise
282    */

283   public int getLength() {
284     return _currDataLength;
285   }
286   
287   /**
288    * See {@link de.susebox.jtopas.spi.DataProvider} for details.
289    *
290    * @return index in the character array returned by {@link #getData}, where data starts
291    */

292   public int getStartPosition() {
293     return _currStartPos;
294   }
295   
296   /**
297    * See {@link de.susebox.jtopas.spi.DataProvider#getCharAt} for details.
298    *
299    * @param index an index between 0 and {@link #getLength}
300    * @return the character at the given index;
301    */

302   public char getCharAt(int index) {
303     return _currData[_currStartPos + index];
304   }
305   
306   
307   //---------------------------------------------------------------------------
308
// class members
309
//
310
protected static int _numberOfThreads = 20;
311   protected static int _duration = 60;
312   
313   protected static final TokenizerProperty[] _testProperties = {
314     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "k1" } ),
315     new TokenizerProperty(Token.STRING, new String JavaDoc[] { "\"", "\"", "\\" } ),
316     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { ">>>" }, new Object JavaDoc() ),
317     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { ">>" } ),
318     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "k2" }, new Object JavaDoc(), Flags.F_NO_CASE),
319     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "k3" }, new Object JavaDoc(), Flags.F_NO_CASE),
320     new TokenizerProperty(Token.LINE_COMMENT, new String JavaDoc[] { "//" } ),
321     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { "<<" }, new Object JavaDoc() ),
322     new TokenizerProperty(Token.BLOCK_COMMENT, new String JavaDoc[] { "/**", "*/" }, new Object JavaDoc()),
323     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { "+=" } ),
324     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "H1" }, null, Flags.F_NO_CASE),
325     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "H2" }, null, Flags.F_NO_CASE),
326     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "H3" }, null, Flags.F_NO_CASE),
327     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { "-=" }, new Object JavaDoc() ),
328     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { "*=" } ),
329     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { "**=" } ),
330     new TokenizerProperty(Token.LINE_COMMENT, new String JavaDoc[] { "#" }, new Object JavaDoc() ),
331     new TokenizerProperty(Token.LINE_COMMENT, new String JavaDoc[] { "rem" }, null, Flags.F_NO_CASE),
332     new TokenizerProperty(Token.BLOCK_COMMENT, new String JavaDoc[] { "/*", "*/" } ),
333     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { "++" } ),
334     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { "+++" }, new Object JavaDoc() ),
335     new TokenizerProperty(Token.BLOCK_COMMENT, new String JavaDoc[] { "{{", "}}" }, new Object JavaDoc()),
336     new TokenizerProperty(Token.BLOCK_COMMENT, new String JavaDoc[] { "[startBlockComment]", "[endBlockComment]" }, null, Flags.F_NO_CASE),
337     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { "**" } ),
338     new TokenizerProperty(Token.BLOCK_COMMENT, new String JavaDoc[] { "<!--", "-->" } ),
339     new TokenizerProperty(Token.STRING, new String JavaDoc[] { "'", "'", "\\" } ),
340     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { ":=" } ),
341     new TokenizerProperty(Token.PATTERN, new String JavaDoc[] { "[+\\-]?[0-9]+\\.?[0-9]*" }, new Object JavaDoc()),
342     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "if" }, new Object JavaDoc() ),
343     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "then" }, new Object JavaDoc() ),
344     new TokenizerProperty(Token.PATTERN, new String JavaDoc[] { "[A-Z_][A-Z0-9_]*" }, new Object JavaDoc(), Flags.F_NO_CASE),
345     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "while" }, new Object JavaDoc() ),
346     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { "!=" }, new Object JavaDoc()),
347     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "loop" }, new Object JavaDoc() ),
348     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "class" }, new Object JavaDoc() ),
349     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "interface" }, new Object JavaDoc() ),
350     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { "<>" }, new Object JavaDoc()),
351     new TokenizerProperty(Token.LINE_COMMENT, new String JavaDoc[] { "--" }, new Object JavaDoc() ),
352     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "synchronized" }, new Object JavaDoc() ),
353     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "final" } ),
354     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "implements" } ),
355     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "int" } ),
356     new TokenizerProperty(Token.STRING, new String JavaDoc[] { "''", "''", "''" }, new Object JavaDoc() ),
357     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "boolean" } ),
358     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "void" } ),
359     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "do" } ),
360     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "HREF" }, null, Flags.F_NO_CASE),
361     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "FONT" }, null, Flags.F_NO_CASE),
362     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { "." } ),
363     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { "{" } ),
364     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { "}" } ),
365     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "import" } ),
366     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "package" } ),
367     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "static" } ),
368     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "try" }, new Object JavaDoc() ),
369     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "catch" }, new Object JavaDoc() ),
370     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { "/" } ),
371     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { "/=" } ),
372     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "table" }, null, Flags.F_NO_CASE),
373     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "span" }, null, Flags.F_NO_CASE),
374     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { "[" } ),
375     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "layer" }, null, Flags.F_NO_CASE),
376     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { "]" } ),
377     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "STYLE" }, null, Flags.F_NO_CASE),
378     new TokenizerProperty(Token.KEYWORD, new String JavaDoc[] { "image" }, null, Flags.F_NO_CASE),
379     new TokenizerProperty(Token.SPECIAL_SEQUENCE, new String JavaDoc[] { "+" } )
380   };
381   
382
383   //---------------------------------------------------------------------------
384
// Members
385
//
386
protected Map JavaDoc _eventRecord = null;
387   protected TokenizerProperties _properties = null;
388   private char[] _currData = new char[8192];
389   private int _currStartPos = 0;
390   private int _currDataLength = 0;
391
392
393   //---------------------------------------------------------------------------
394
// inner classes
395
//
396

397   /**
398    * Thread for TokenizerProperties manipulation
399    */

400   class Runner implements Runnable JavaDoc {
401
402     /**
403      * Constructor taking the {@link TokenizerProperties} instance to work, an array
404      * of {@link TokenizerProperty} objects to add and remove from the <code>TokenizerProperties</code>
405      * object and a step interval for the entries in the property array.
406      */

407     public Runner(TestMultithreadTokenizerProperties parent, int start, int step, StringBuffer JavaDoc activity) {
408       _parent = parent;
409       _start = start;
410       _activity = activity;
411       if ((_step = step) < 1) {
412         _step = 1;
413       }
414     }
415
416     /**
417      * When an object implementing interface <code>Runnable</code> is used
418      * to create a thread, starting the thread causes the object's
419      * <code>run</code> method to be called in that separately executing
420      * thread.
421      * <p>
422      * The general contract of the method <code>run</code> is that it may
423      * take any action whatsoever.
424      *
425      * @see java.lang.Thread#run()
426      */

427     public void run() {
428       Thread JavaDoc thread = Thread.currentThread();
429       String JavaDoc name = thread.getName();
430       int counter = _start;
431
432       try {
433         while (Thread.currentThread() == thread && ! _stop) {
434           synchronized(this) {
435             long start = System.currentTimeMillis();
436             int index = counter % _parent._testProperties.length;
437             TokenizerProperty prop = _parent._testProperties[index];
438
439             // add or remove a property
440
// System.out.println(name + ": checking " + prop);
441
if (_parent._properties.propertyExists(prop)) {
442               _parent._properties.removeProperty(prop);
443             } else {
444               _parent._properties.addProperty(prop);
445             }
446
447             // check duration
448
long duration = System.currentTimeMillis() - start;
449             if (duration > 5000) {
450               _parent.assertTrue(name + ": waited too long: " + duration, false);
451               break;
452             }
453
454             // increase counter
455
counter += _step;
456
457             // signal activity
458
long value = Long.parseLong(_activity.toString());
459             _activity.setLength(0);
460             _activity.append(value + 1);
461
462             // pause a little bit
463
try {
464               wait(1);
465             } catch (InterruptedException JavaDoc ex) {}
466           }
467         }
468       } catch (Throwable JavaDoc t) {
469         t.printStackTrace();
470       }
471       System.out.println(name + ": exiting. Activity: " + _activity);
472     }
473
474     /**
475      * Signal the thread to stop
476      */

477     public void stop() {
478       synchronized(this) {
479         _stop = true;
480       }
481     }
482
483
484     //---------------------------------------------------------------------------
485
// Members
486
//
487
private TestMultithreadTokenizerProperties _parent = null;
488     private int _start = 0;
489     private int _step = 0;
490     private boolean _stop = false;
491     private StringBuffer JavaDoc _activity = null;
492   }
493 }
494
495
Popular Tags