KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derbyTesting > functionTests > harness > MultiTest


1 /*
2
3    Derby - Class org.apache.derbyTesting.functionTests.harness.MultiTest
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to You under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derbyTesting.functionTests.harness;
23
24 import java.io.IOException JavaDoc;
25 import java.io.File JavaDoc;
26 import java.io.FileOutputStream JavaDoc;
27 import java.io.FileNotFoundException JavaDoc;
28 import java.io.InputStream JavaDoc;
29 import java.io.FileInputStream JavaDoc;
30 import java.io.BufferedInputStream JavaDoc;
31 import java.util.Vector JavaDoc;
32 import java.util.Enumeration JavaDoc;
33 import org.apache.derby.impl.tools.ij.*;
34
35 import org.apache.derby.iapi.tools.i18n.LocalizedResource;
36 import org.apache.derby.iapi.tools.i18n.LocalizedOutput;
37
38 /**
39  * MultiTest is a multiuser test harness. It
40  * runs multiple threads with differing scripts
41  * against an embedded server. For syntax see
42  * grammar.jj
43  *
44  * Tests are ended as soon as an unexpected error
45  * has occurred or after the specified test duration
46  * has transpired. The main loop ends by explicitly
47  * quitting (i.e. doing a System.exit()).
48  *
49  * Deprecated APIs: this test uses AppStreamWriter instead
50  * of the preferred AppStreamWriter. This is because utilMain()
51  * uses AppStreamWriter (deliberately, i think) so since
52  * that is called from this, there you have it.
53  */

54
55 public class MultiTest
56 {
57
58     private static final int MAX_WAIT_FOR_COMPLETION = 180;
59
60     private static mtTestSuite suite;
61     private static LocalizedOutput log;
62     private static String JavaDoc inputDir;
63     private static String JavaDoc outputDir;
64     private static String JavaDoc testName;
65
66
67     
68     public MultiTest () { };
69
70     public static void syntax()
71     {
72         System.out.println("Syntax:"
73                 +"\n\t <file>\t- the cmd file"
74                 +"\n\t[-o <dir>]\t-the output directory"
75                 +"\n\t[-i <dir>]\t-the input directory");
76     }
77
78     /**
79     ** Main loop
80     @exception IOException thrown on error
81     @exception ParseException thrown on error
82     @exception FileNotFoundException thrown on error
83     */

84     public static void main(String JavaDoc[] args)
85             throws IOException JavaDoc, ParseException, FileNotFoundException JavaDoc
86     {
87         String JavaDoc cmdFilePath;
88         InputStream JavaDoc in;
89         String JavaDoc cmdFile;
90         mtTester[] testers;
91         int i;
92         int max;
93
94         if ((cmdFile = util.getFileArg(args)) == null)
95         {
96             syntax();
97             return;
98         }
99
100         LocalizedResource.getInstance();
101
102         testName = getTestName(cmdFile);
103         inputDir = util.getArg("-i", args);
104         outputDir = util.getArg("-o", args);
105
106         /*
107         ** If cmdfile doesn't have a path, prepend
108         ** inputDir
109         */

110         cmdFilePath = ((inputDir != null) && (cmdFile.indexOf("/") == -1)) ?
111                 (inputDir + "/" + cmdFile) : cmdFile;
112         try
113         {
114             in = new BufferedInputStream JavaDoc(new FileInputStream JavaDoc(cmdFilePath),
115                                         utilMain.BUFFEREDFILESIZE);
116         } catch (FileNotFoundException JavaDoc e) {
117             System.out.println("MultiTest ERROR: config file not found: "+cmdFile);
118             return;
119         }
120         mtGrammar parser = new mtGrammar(in);
121         suite = parser.grammarStatement();
122         suite.setRoot(inputDir);
123         suite.init();
124     
125         log = openFile(outputDir, testName + ".log");
126
127         try
128         {
129             seqRunCases(suite.getInitCases(),
130                         "initialization",
131                         inputDir,
132                         outputDir);
133         } catch (ijFatalException e)
134         {
135             System.exit(1);
136         }
137
138         max = suite.getNumThreads();
139         System.out.println("...running with "+max+" threads");
140         testers = new mtTester[max];
141
142         // create the testers
143
for (i = 0; i < max; i++)
144         {
145             String JavaDoc tester = "Tester" + (i+1);
146             try
147             {
148                 LocalizedOutput out = openFile(outputDir, tester + ".out");
149                 testers[i] = new mtTester(tester, suite, out, log);
150             } catch (IOException JavaDoc e) {
151                 System.out.println("MultiTest ERROR: unable open output file "+e);
152                 return;
153             }
154         }
155
156         long duration = execTesters(testers);
157
158         log.println("");
159         log.println("test ran "+duration+" ms");
160         log.println("total memory is "+Runtime.getRuntime().totalMemory());
161         log.println("free memory is "+Runtime.getRuntime().freeMemory());
162         // Delete the .out files for Testers that did not report errors.
163
for (i = 0; i < max; i++)
164         {
165             if ( testers[i].noFailure() )
166             {
167                 log.println("Deleting " + "Tester" + (i+1) + ".out" + "(" + outputDir + ")");
168                 File JavaDoc out = new File JavaDoc(outputDir, "Tester" + (i+1) + ".out");
169                 out.delete();
170             }
171             else
172             {
173                 log.println("Tester" + (i+1) + " failed.");
174             }
175         }
176         
177         System.exit(0);
178     }
179
180     /*
181     **
182     ** NOTE ON OUT OF MEMORY PROBLEMS: in theory
183     ** when the VM runs out of memory an OutOfMemoryException
184     ** should be thrown by the runtime, but unfortunately, that
185     ** doesn't always seem to be the case. When running this
186     ** program the Testers just wind up hanging on memory
187     ** allocation if there is insufficient memory. To combat
188     ** this we try to manually stop each thread, but when
189     ** there is no memory, this doesn't seem to do anything
190     ** either. Also, we grab some memory up front and release
191     ** that after telling the threads to stop themselves.
192     */

193     private static long execTesters(mtTester[] testers)
194             throws FileNotFoundException JavaDoc, IOException JavaDoc
195     {
196         boolean interrupted = false;
197         boolean allWereAlive = true;
198         int i;
199         long duration = 0;
200         int max = testers.length;
201         Thread JavaDoc[] threads;
202         byte[] extraMemory;
203
204         // new thread group
205
ThreadGroup JavaDoc tg = new ThreadGroup JavaDoc("workers");
206         //tg.allowThreadSuspension(false);
207

208         // grab start time
209
long start = System.currentTimeMillis();
210         long runTime = suite.getTimeMillis();
211         System.out.println("...running duration "+suite.getTime());
212
213         // grab some memory to make stopping easier
214
extraMemory = new byte[4096];
215
216         threads = new Thread JavaDoc[max];
217         // run them
218
for (i = 0; i < max; i++)
219         {
220             threads[i] = new Thread JavaDoc(tg, testers[i]);
221             threads[i].start();
222         }
223
224         // loop sleeping 800ms a bite.
225
while (((duration = (System.currentTimeMillis() - start)) < runTime) &&
226                 (allWereAlive = allAlive(threads)) && (!interrupted))
227         {
228             try
229             {
230                 Thread.sleep(800L);
231             } catch (InterruptedException JavaDoc e)
232             {
233                 interrupted = true;
234             }
235         }
236
237         System.out.println("...stopping testers");
238
239
240         /*
241         ** Free up 2k of memory and garbage
242         ** collect. That should allow any
243         ** starved testers to stop themselves.
244         */

245         extraMemory = null;
246         System.gc();
247
248         /*
249         ** Now stop everyone. First ask them to
250         ** willingly stop. By calling mtTester.stop()
251         ** we prevent the testers from picking up the
252         ** next task.
253         */

254         for (i = 0; i < testers.length; i++)
255         {
256             testers[i].stop();
257         }
258
259         /*
260         ** Sleep 180 seconds, or until everyone
261         ** is done.
262         */

263         System.out.println("...waiting for testers to complete");
264         for (i = 0; i < MAX_WAIT_FOR_COMPLETION; i++)
265         {
266             try
267             {
268                 Thread.sleep((long)1000);
269             } catch (InterruptedException JavaDoc e)
270             {
271                 System.out.println("...Unexpected InterrupedException: "+e);
272             }
273             if (allDead(threads))
274             {
275                 break;
276             }
277         }
278
279         if (i == MAX_WAIT_FOR_COMPLETION)
280         {
281             log.println("WARNING: testers didn't die willingly, so I'm going to kill 'em.");
282             log.println("\tThis may result in connection resources that aren't cleaned up");
283             log.println("\t(e.g. you may see problems in the final script run with deadlocks).");
284         }
285     
286         /*
287         ** Now stop everyone that hasn't already stopped.
288         */

289         for (i = 0; i < MAX_WAIT_FOR_COMPLETION && (tg.isDestroyed() == false ); i++)
290         {
291
292             // can't really stop - deprecated because 'unsafe'. interrupt.
293
tg.interrupt();
294             try { Thread.sleep((long) 1000); } catch (InterruptedException JavaDoc e) {}
295
296             try
297             {
298                 tg.destroy();
299             } catch (IllegalThreadStateException JavaDoc e)
300             {
301                 log.println("...waiting for ThreadGroup.interrupt() to work its magic");
302                 try { Thread.sleep((long)1000); } catch (InterruptedException JavaDoc e2) {}
303                 continue;
304             }
305             break;
306         }
307
308         if (interrupted == true)
309         {
310             System.out.println("TEST CASE SUMMARY: run interrupted");
311         }
312         else if (allWereAlive == false)
313         {
314             System.out.println("TEST CASE SUMMARY: abnormal termination due to error(s)"+
315                 " -- see test log (./"+testName+"/"+testName+".log) for details ");
316         }
317         else
318         {
319             System.out.println("TEST CASE SUMMARY: normal termination");
320             if (i < MAX_WAIT_FOR_COMPLETION)
321             {
322                 try
323                 {
324                     seqRunCases(suite.getFinalCases(),
325                             "last checks",
326                             inputDir,
327                             outputDir);
328                 } catch (ijFatalException e)
329                 {
330                     System.out.println("...error running final test cases");
331                 }
332             }
333             else
334             {
335                 System.out.println("...timed out trying to kill all testers,\n" +
336                                 " skipping last scripts (if any). NOTE: the\n"+
337                                 " likely cause of the problem killing testers is\n"+
338                                 " probably not enough VM memory OR test cases that\n"+
339                                 " run for very long periods of time (so testers do not\n"+
340                                 " have a chance to notice stop() requests");
341             }
342         }
343
344         return duration;
345     }
346
347
348     /**
349     ** Search through the list of threads and see
350     ** if they are all alive.
351     */

352     public static boolean allAlive(Thread JavaDoc[] threads)
353     {
354         int i;
355         for (i = 0; i < threads.length; i++)
356         {
357             if (threads[i].isAlive() == false)
358                 break;
359         }
360         return (i == threads.length);
361     }
362
363     /**
364     ** Search through the list of threads and see
365     ** if they are all alive.
366     */

367     public static boolean allDead(Thread JavaDoc[] threads)
368     {
369         int i;
370         for (i = 0; i < threads.length; i++)
371         {
372             if (threads[i].isAlive() == true)
373                 break;
374         }
375         return (i == threads.length);
376     }
377
378     /**
379     ** Figure out the name of the log file and open
380     ** it
381     */

382     private static LocalizedOutput openFile(String JavaDoc dir, String JavaDoc fileName)
383             throws IOException JavaDoc
384     {
385         
386         java.io.File JavaDoc file = new java.io.File JavaDoc(dir, fileName);
387
388         return new LocalizedOutput(new FileOutputStream JavaDoc(file));
389     }
390     /**
391     ** Sequentially run scripts
392     */

393     private static void seqRunCases(Vector JavaDoc cases, String JavaDoc descr, String JavaDoc inputDir, String JavaDoc outputDir)
394         throws FileNotFoundException JavaDoc, IOException JavaDoc, ijFatalException
395     {
396         LocalizedOutput out;
397         BufferedInputStream JavaDoc in;
398         mtTestCase testCase;
399
400         if (cases == null)
401         {
402             System.out.println("...no "+descr+" being performed");
403             return;
404         }
405
406         Enumeration JavaDoc e = cases.elements();
407
408         while (e.hasMoreElements())
409         {
410             testCase = (mtTestCase)e.nextElement();
411             String JavaDoc testName = testCase.getFile();
412             System.out.println("...running "+descr+" via "+testName);
413             String JavaDoc logFileName =
414                 testName.substring(0, testName.lastIndexOf('.'));
415             out = openFile(outputDir, logFileName + ".out");
416             in = testCase.initialize(inputDir);
417             testCase.runMe(log, out, in);
418         }
419     }
420
421     /**
422     ** Given the command file, infer the test name.
423     ** Takes the portion of the file name between
424     ** the last '.' and the last '/'. e.g.
425     ** x/y/Name.suffix -> Name
426     **
427     */

428     private static String JavaDoc getTestName(String JavaDoc cmdFile)
429     {
430         int slash, dotSpot;
431
432         slash = cmdFile.lastIndexOf("/");
433         if (slash == -1)
434         {
435             slash = 0;
436         }
437
438         dotSpot = cmdFile.lastIndexOf(".");
439         if (dotSpot == -1)
440         {
441             dotSpot = cmdFile.length();
442         }
443         return cmdFile.substring(slash, dotSpot);
444
445     }
446 }
447
Popular Tags