001: /*
002: * Speedo: an implementation of JDO compliant personality on top of JORM
003: * generic I/O sub-system. Copyright (C) 2001-2004 France Telecom R&D
004: *
005: * This library is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU Lesser General Public License as published by the
007: * Free Software Foundation; either version 2 of the License, or (at your
008: * option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful, but WITHOUT
011: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
012: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
013: * for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public License
016: * along with this library; if not, write to the Free Software Foundation,
017: * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: *
019: * Release: 1.0
020: *
021: * Created on 2004-03-04 @author fmillevi@yahoo.com
022: *
023: */
024: package org.objectweb.speedo.j2eedo;
025:
026: import java.io.BufferedReader;
027: import java.io.PrintWriter;
028: import java.io.StringReader;
029: import java.io.StringWriter;
030: import java.util.ArrayList;
031: import java.util.Collections;
032: import java.util.HashMap;
033: import java.util.Hashtable;
034: import java.util.Iterator;
035: import java.util.List;
036:
037: import javax.jdo.JDOException;
038: import javax.jdo.JDOFatalException;
039: import javax.jdo.PersistenceManager;
040:
041: import org.objectweb.speedo.SpeedoTestHelper;
042: import org.objectweb.speedo.j2eedo.bo.DatabaseImpl;
043: import org.objectweb.speedo.j2eedo.common.PMHolder;
044: import org.objectweb.speedo.j2eedo.common.TraceTime;
045: import org.objectweb.util.monolog.Monolog;
046: import org.objectweb.util.monolog.api.BasicLevel;
047:
048: /**
049: * This class implements Junit test case. All the defined tests are launched in
050: * a standalone mode (it means test performing without an J2EE deployement)
051: *
052: * @author fmillevi@yahoo.com
053: */
054: public class TestJ2eedoApplication extends SpeedoTestHelper {
055:
056: /**
057: * define the application prefix parameters <code>JEEDO_LOG_NAME</code>
058: */
059: public final static String JEEDO_LOG_NAME = org.objectweb.speedo.SpeedoTestHelper.LOG_NAME
060: + ".j2eedo";
061:
062: protected final String SIMPLETEST = getLoggerName() + ".simpleTest";
063: protected final String THREAD = getLoggerName() + ".thread";
064: protected final String LOOP = getLoggerName() + ".loop";
065: protected final String TIMEOUT = getLoggerName() + ".timeout";
066: protected final String NBOFREAD = getLoggerName() + ".read";
067: protected final String NBOFWRITE = getLoggerName() + ".write";
068:
069: protected boolean simpleTestOnly = false;
070: protected int nbThread = -1;
071: protected int nbTx = -1;
072: protected long timeout = -1;
073: protected int nbOfRead = -1;
074: protected int nbOfWrite = -1;
075:
076: protected List methodsList = null;
077:
078: private static boolean dataReset = false;
079:
080: /**
081: * Sets up the test fixture. (Called before every test case method.) This
082: * method
083: * <ul>
084: * <li>registers each action,</li>
085: * <li>Set the default action list method</li>
086: * <li>Initializes the database content.</li>
087: * </ul>
088: *
089: * @see org.objectweb.speedo.j2eedo.bo.DatabaseImpl
090: */
091: protected void setUp() {
092: GenerateListOfActionToBeDone generateMethod = new GenerateListOfActionToBeDone();
093:
094: try {
095: for (int i = 0; i < DatabaseImpl.actionArray.length; i++) {
096: // register method doing something
097: generateMethod
098: .registerMethod(
099: DatabaseImpl.actionArray[i],
100: DatabaseImpl.actionWeightArray[i][DatabaseImpl.READ],
101: DatabaseImpl.actionWeightArray[i][DatabaseImpl.WRITE]);
102: }
103: // set the action list
104: this .methodsList = generateMethod.mergeWriteReadMethodList(
105: Integer.getInteger(NBOFWRITE, 1).intValue(),
106: Integer.getInteger(NBOFREAD, 3).intValue());
107: } catch (Exception e) {
108: e.printStackTrace();
109: }
110:
111: PMHolder pmHolder = new PMHolder(getPMF());
112: try {
113: synchronized (JEEDO_LOG_NAME) {
114: if (!TestJ2eedoApplication.dataReset) {
115: TestJ2eedoApplication.dataReset = true;
116: logger
117: .log(BasicLevel.INFO,
118: "Resetting initial data for the new test...");
119: DatabaseImpl.initTestData(pmHolder);
120: logger.log(BasicLevel.INFO,
121: "Initial test data have been created.");
122: }
123: }
124: } catch (JDOException e) {
125: e.printStackTrace(System.out);
126: fail("Setup of initial test data throws an JDO Exception"
127: + e);
128: } catch (Exception e) {
129: e.printStackTrace(System.out);
130: fail("Setup of initial test data throws an Exception" + e);
131: }
132: }
133:
134: /**
135: * Tears down the test fixture. (Called after every test case method.)
136: */
137: protected void tearDown() {
138: //Nothing to do yet
139: }
140:
141: /**
142: * This constructor gets the parameters and resets the default list of
143: * methods to be called
144: *
145: * @see org.objectweb.speedo.j2eedo.bo.DatabaseImpl
146: * @param s
147: * is the class name
148: */
149: public TestJ2eedoApplication(String s) {
150: super (s);
151: this .simpleTestOnly = Boolean.getBoolean(SIMPLETEST);
152: this .nbThread = Integer.getInteger(THREAD, 1).intValue();
153: this .nbTx = Integer.getInteger(LOOP, 1).intValue();
154: this .timeout = Long.getLong(TIMEOUT, 3600000).longValue();
155: this .nbOfRead = Integer.getInteger(NBOFREAD, 3).intValue();
156: this .nbOfWrite = Integer.getInteger(NBOFWRITE, 1).intValue();
157:
158: System.out.println(SIMPLETEST + "=" + simpleTestOnly);
159: System.out.println(THREAD + "=" + nbThread);
160: System.out.println(LOOP + "=" + nbTx);
161: System.out.println(TIMEOUT + "=" + timeout);
162: System.out.println(NBOFREAD + "=" + nbOfRead);
163: System.out.println(NBOFWRITE + "=" + nbOfWrite);
164:
165: loggerFactory = Monolog.monologFactory;
166: logger = loggerFactory.getLogger(getLoggerName());
167:
168: this .methodsList = null;
169: }
170:
171: /**
172: * This sub class provides the list of the methods having to be called
173: * while taking regarding the rate between the reading and writing defined
174: * by the two parameters <br>- rankOfRead : number of read methods to be
175: * called <br>- rankOfWrite : number of write methods to be called <br>
176: *
177: * @author fmillevi@yahoo.com
178: */
179: public class GenerateListOfActionToBeDone {
180: /**
181: * The constant <code>MAX_WEIGHT</code> defines relative maximum
182: * weight used by the methods registerMethodXXX . Its values is 5
183: */
184: public final static int MAX_WEIGHT = 5;
185: /**
186: * The constant <code>MIN_WEIGHT</code> defines relative minimum
187: * weight used by the methods registerMethodXXX . Its values is -1
188: */
189: public final static int MIN_WEIGHT = 1;
190:
191: private int totalWriteWeight = 0;
192: private int totalReadWeight = 0;
193:
194: private List readAndWriteActionList = null;
195: private List writeOnlyActionList = null;
196: private List readOnlyActionList = null;
197: HashMap readAndWriteAction4ReadMap = null;
198: HashMap readAndWriteAction4WriteMap = null;
199: HashMap readOnlyActionMap = null;
200: HashMap writeOnlyActionMap = null;
201:
202: /**
203: * This method populates the list of action according the weight of
204: * each method : The less a method is weighted, the more frequent this
205: * method is in the list
206: *
207: * @param map
208: * is the current map storing the method names with the
209: * read/write weight
210: * @param list
211: * is the current list of method populated according the
212: * weight of each method
213: */
214: private int computeList(HashMap map, List list) {
215: if (null == map || 0 == map.size())
216: return 0;
217:
218: Iterator listOfMethod = map.keySet().iterator();
219: int totalWeight = 0;
220: int nbEntries = 0;
221: while (listOfMethod.hasNext()) {
222: String method = (String) listOfMethod.next();
223: int weight = ((Integer) map.get(method)).intValue();
224: int nbOfEntry = Math.round(MAX_WEIGHT * MAX_WEIGHT
225: / weight);
226: for (int i = 0; i < nbOfEntry; i++) {
227: list.add(method);
228: nbEntries++;
229: totalWeight += weight;
230: }
231: }
232: logger.log(BasicLevel.DEBUG, nbEntries + " entries added");
233: return totalWeight;
234: }
235:
236: /**
237: * generate the list of write taking care of the write weight
238: *
239: * @throws Exception
240: * when no method are register in the map
241: */
242: private void computeReadMethodList() throws Exception {
243: try {
244: this .readOnlyActionList = new ArrayList();
245: this .totalReadWeight = computeList(
246: this .readOnlyActionMap, this .readOnlyActionList);
247: } catch (Exception e) {
248: throw new Exception(
249: "Can not compute Write Method List", e);
250: }
251: }
252:
253: /**
254: * generate the list of write taking care of the write weight
255: *
256: * @throws Exception
257: * when no method are register in the map
258: */
259: private void computeReadWriteMethodList() throws Exception {
260: try {
261: this .readAndWriteActionList = new ArrayList();
262:
263: int nbRead = computeList(
264: this .readAndWriteAction4ReadMap,
265: this .readAndWriteActionList);
266:
267: int nbWrite = computeList(
268: this .readAndWriteAction4WriteMap,
269: this .readAndWriteActionList);
270:
271: this .totalWriteWeight = nbWrite;
272: this .totalReadWeight = nbRead;
273:
274: } catch (Exception e) {
275: throw new Exception(
276: "Can not compute Write Method List", e);
277: }
278: }
279:
280: /**
281: * generate the list of write taking care of the write weight
282: *
283: * @throws Exception
284: * when no method are register in the map
285: */
286: private void computeWriteMethodList() throws Exception {
287: try {
288: this .writeOnlyActionList = new ArrayList();
289: this .totalWriteWeight = computeList(
290: this .writeOnlyActionMap,
291: this .writeOnlyActionList);
292: } catch (Exception e) {
293: throw new Exception(
294: "Can not compute Write Method List", e);
295: }
296: }
297:
298: /**
299: * This method populates the list Read/Write Methods according the Read
300: * methoded registered
301: *
302: * @param nbOfWrite
303: * @param nbOfRead
304: * @return the list of methods to be called
305: * @throws Exception
306: * when no method are register in the map and when
307: * parameters are null or <0
308: */
309: public List mergeWriteReadMethodList(int nbOfWrite, int nbOfRead)
310: throws Exception {
311: if (0 >= (nbOfWrite + nbOfRead)
312: || 0 > (nbOfWrite * nbOfRead))
313: throw new Exception("Parameters nbOfRead (" + nbOfRead
314: + ") and nbOfWrite (" + nbOfWrite
315: + ") are not correct.");
316:
317: logger
318: .log(BasicLevel.DEBUG,
319: "Generate the actions list according registered actions read/write weight");
320: List list1 = new ArrayList();
321:
322: this .computeReadWriteMethodList();
323: list1.addAll(this .readAndWriteActionList);
324:
325: this .computeReadMethodList();
326: this .computeWriteMethodList();
327:
328: list1.addAll(this .writeOnlyActionList);
329:
330: if (logger.isLoggable(BasicLevel.DEBUG)) {
331: Iterator iter = null;
332: int nbActions = 0;
333: iter = this .readOnlyActionList.iterator();
334: for (nbActions = 0; iter.hasNext(); nbActions++)
335: iter.next();
336: logger.log(BasicLevel.DEBUG, nbActions
337: + " read only actions (total weight:"
338: + this .totalReadWeight + ")");
339: iter = this .writeOnlyActionList.iterator();
340: for (nbActions = 0; iter.hasNext(); nbActions++)
341: iter.next();
342: logger.log(BasicLevel.DEBUG, nbActions
343: + " write only actions (total weight:"
344: + this .totalWriteWeight + ")");
345: iter = this .readAndWriteActionList.iterator();
346: for (nbActions = 0; iter.hasNext(); nbActions++)
347: iter.next();
348: logger.log(BasicLevel.DEBUG, nbActions
349: + " read & write only actions");
350: }
351:
352: Iterator iter = list1.iterator();
353: int weightRead = 0;
354: int weightWrite = 0;
355: String method;
356: while (iter.hasNext()) {
357: method = (String) iter.next();
358: if (this .readOnlyActionMap.containsKey(method))
359: weightRead += ((Integer) this .readOnlyActionMap
360: .get(method)).intValue();
361: else if (this .writeOnlyActionMap.containsKey(method))
362: weightWrite += ((Integer) this .writeOnlyActionMap
363: .get(method)).intValue();
364: else {
365: weightRead += ((Integer) this .readAndWriteAction4ReadMap
366: .get(method)).intValue();
367: weightWrite += ((Integer) this .readAndWriteAction4WriteMap
368: .get(method)).intValue();
369: }
370: }
371:
372: List list = new ArrayList();
373: if (0 == nbOfWrite) {
374: list.addAll(this .readOnlyActionList);
375: } else if (0 == nbOfRead) {
376: list.addAll(this .writeOnlyActionList);
377: } else {
378: int nbRead2BeAdd = nbOfRead * weightWrite / nbOfWrite
379: - weightRead;
380: if (0 >= nbRead2BeAdd)
381: nbRead2BeAdd = 1;
382: logger.log(BasicLevel.DEBUG,
383: "Before merge Read only methods : \nnbRead "
384: + weightRead
385: + "\nnbWrite "
386: + weightWrite
387: + "\nnbRead2BeAdd "
388: + nbRead2BeAdd
389: + "\nAddList:"
390: + (float) nbRead2BeAdd
391: / (float) this .totalReadWeight
392: + "\t#:"
393: + Math.round((float) nbRead2BeAdd
394: / (float) totalReadWeight)
395: + " *(" + this .totalReadWeight + ")");
396:
397: if (nbRead2BeAdd < this .totalReadWeight) {
398: for (int j = 0; j < Math
399: .round((float) totalReadWeight
400: / (float) nbRead2BeAdd); j++)
401: list.addAll(list1);
402: list.addAll(this .readOnlyActionList);
403: } else {
404: list.addAll(list1);
405: for (int j = 0; j < Math.round((float) nbRead2BeAdd
406: / (float) totalReadWeight); j++)
407: list.addAll(this .readOnlyActionList);
408: }
409: }
410: if (logger.isLoggable(BasicLevel.DEBUG)) {
411: weightRead = 0;
412: weightWrite = 0;
413: int nbCalls = 0;
414: iter = list.iterator();
415: while (iter.hasNext()) {
416: method = (String) iter.next();
417: nbCalls++;
418: if (this .readOnlyActionMap.containsKey(method))
419: weightRead += ((Integer) this .readOnlyActionMap
420: .get(method)).intValue();
421: else if (this .writeOnlyActionMap
422: .containsKey(method))
423: weightWrite += ((Integer) this .writeOnlyActionMap
424: .get(method)).intValue();
425: else {
426: weightRead += ((Integer) this .readAndWriteAction4ReadMap
427: .get(method)).intValue();
428: weightWrite += ((Integer) this .readAndWriteAction4WriteMap
429: .get(method)).intValue();
430: }
431: }
432: logger.log(BasicLevel.DEBUG,
433: "The action list is set : \nnbRead "
434: + weightRead
435: + "\nnbWrite "
436: + weightWrite
437: + "\n\tGoal rate : "
438: + nbOfRead
439: + "/"
440: + nbOfWrite
441: + "="
442: + ((nbOfWrite != 0) ? Float
443: .toString((float) nbOfRead
444: / (float) nbOfWrite)
445: : "NaN")
446: + "\n\tRate:"
447: + ((weightWrite != 0) ? Float
448: .toString((float) weightRead
449: / (float) weightWrite)
450: : "NaN") + " in " + nbCalls
451: + " calls");
452: }
453:
454: return list;
455: }
456:
457: /**
458: * Register a method having write an read job
459: *
460: * @param name
461: * is the action's name
462: * @param readWeight
463: * is the relative read weight defined between MIN_WEIGHT
464: * and MAX_WEIGHT or setted to 0 (zero)
465: * @param writeWeight
466: * is the relative write weight defined between MIN_WEIGHT
467: * and MAX_WEIGHT or setted to 0 (zero)
468: * @throws Exception
469: * when the weights are not defined between the max and the
470: * min value or setted to 0 (zero). Both weight parameters
471: * can not be setted to 0
472: * @see #MAX_WEIGHT
473: * @see #MIN_WEIGHT
474: */
475: public void registerMethod(String name, int readWeight,
476: int writeWeight) throws Exception {
477: if (name.equals(DatabaseImpl.PARAMETER_PING))
478: return;
479: if (0 == readWeight)
480: this .registerMethodWrite(name, writeWeight);
481: else if (0 == writeWeight)
482: this .registerMethodRead(name, readWeight);
483: else
484: registerMethodReadWrite(name, readWeight, writeWeight);
485: }
486:
487: /**
488: * Register a method having write an read job
489: *
490: * @param name
491: * is the action's name
492: * @param readWeight
493: * is the relatif weight for read
494: * @param writeWeight
495: * is the relatif weight for write
496: * @throws Exception
497: * when the weights are not in the max and the min value
498: */
499: private void registerMethodReadWrite(String name,
500: int readWeight, int writeWeight) throws Exception {
501: if (null == this .readAndWriteAction4ReadMap)
502: this .readAndWriteAction4ReadMap = new HashMap();
503: if (null == this .readAndWriteAction4WriteMap)
504: this .readAndWriteAction4WriteMap = new HashMap();
505:
506: if (readWeight > GenerateListOfActionToBeDone.MAX_WEIGHT
507: || readWeight < GenerateListOfActionToBeDone.MIN_WEIGHT
508: || writeWeight > GenerateListOfActionToBeDone.MAX_WEIGHT
509: || writeWeight < GenerateListOfActionToBeDone.MIN_WEIGHT)
510: throw new Exception(
511: "Can not register this method : the weight must be defined between "
512: + GenerateListOfActionToBeDone.MIN_WEIGHT
513: + " and "
514: + GenerateListOfActionToBeDone.MAX_WEIGHT);
515: this .readAndWriteAction4ReadMap.put(name, new Integer(
516: readWeight));
517: this .readAndWriteAction4WriteMap.put(name, new Integer(
518: writeWeight));
519: }
520:
521: /**
522: * Register a method having read job
523: *
524: * @param name is the Method's name
525: * @param weight is relatif weight for read
526: * @throws Exception
527: * when the weights are not in the max and the min value
528: */
529: private void registerMethodRead(String name, int weight)
530: throws Exception {
531: if (null == this .readOnlyActionMap)
532: this .readOnlyActionMap = new HashMap();
533:
534: if (weight > GenerateListOfActionToBeDone.MAX_WEIGHT
535: || weight < GenerateListOfActionToBeDone.MIN_WEIGHT)
536: throw new Exception(
537: "Can not register this method : the weight must be defined between "
538: + GenerateListOfActionToBeDone.MIN_WEIGHT
539: + " and "
540: + GenerateListOfActionToBeDone.MAX_WEIGHT);
541: this .readOnlyActionMap.put(name, new Integer(weight));
542: }
543:
544: /**
545: * Register a method having write job
546: *
547: * @param name is the Method's name
548: * @param weight is relatif weight for write
549: * @throws Exception
550: * when the weights are not in the max and the min value
551: */
552: private void registerMethodWrite(String name, int weight)
553: throws Exception {
554: if (null == this .writeOnlyActionMap)
555: this .writeOnlyActionMap = new HashMap();
556:
557: this .totalWriteWeight += weight;
558:
559: if (weight > GenerateListOfActionToBeDone.MAX_WEIGHT
560: || weight < GenerateListOfActionToBeDone.MIN_WEIGHT)
561: throw new Exception(
562: "Can not register this method : the weight must be defined between "
563: + GenerateListOfActionToBeDone.MIN_WEIGHT
564: + " and "
565: + GenerateListOfActionToBeDone.MAX_WEIGHT);
566: this .writeOnlyActionMap.put(name, new Integer(weight));
567: }
568:
569: /**
570: * Empty Constructor - reset all values
571: */
572: public GenerateListOfActionToBeDone() {
573: this .readOnlyActionList = null;
574: this .writeOnlyActionList = null;
575: this .readAndWriteAction4ReadMap = null;
576: this .readAndWriteAction4WriteMap = null;
577: this .readOnlyActionMap = null;
578: this .writeOnlyActionMap = null;
579: this .totalWriteWeight = 0;
580: this .totalReadWeight = 0;
581: }
582:
583: }
584:
585: /**
586: * Returns the current log name
587: *
588: * @see org.objectweb.speedo.SpeedoTestHelper#getLoggerName()
589: */
590: protected String getLoggerName() {
591: return JEEDO_LOG_NAME;
592: }
593:
594: private final static Hashtable needTransactionArray = new Hashtable();
595:
596: protected String performMethod(String action) throws Exception,
597: JDOException, JDOFatalException {
598: PMHolder pmHolder = new PMHolder(getPMF());
599:
600: String returnStr = null;
601: boolean needTrans;
602: PersistenceManager pm = null;
603:
604: if (!needTransactionArray.containsKey(action)) {
605: int k = 0;
606: for (; !DatabaseImpl.actionArray[k].equals(action)
607: && k < DatabaseImpl.actionWeightArray.length; k++)
608: ;
609:
610: if (0 == DatabaseImpl.actionWeightArray[k][DatabaseImpl.WRITE])
611: needTransactionArray.put(action, new Boolean(false));
612: else
613: needTransactionArray.put(action, new Boolean(true));
614: }
615: needTrans = ((Boolean) needTransactionArray.get(action))
616: .booleanValue();
617: needTrans = true;
618: if (needTrans) {
619: pm = pmHolder.getPersistenceManager();
620: pm.currentTransaction().begin();
621: }
622: try {
623: returnStr = DatabaseImpl.instance.doAction(action, false,
624: pmHolder);
625: } catch (JDOFatalException e) {
626: if (pm != null && !pm.isClosed()
627: && pm.currentTransaction().isActive()) {
628: pm.currentTransaction().rollback();
629: }
630: throw e;
631: } finally {
632: if (pm != null && !pm.isClosed()
633: && pm.currentTransaction().isActive()) {
634: pm.currentTransaction().commit();
635: }
636: if (needTrans) {
637: pmHolder.closePersistenceManager();
638: }
639: }
640: return returnStr;
641: }
642:
643: protected void perform() {
644: final int _nbTx = this .nbTx;
645: final List _methodsList = this .methodsList;
646: this .displayTestParameters();
647:
648: //------------ Create thread for each tasks ------------//
649: Thread[] ts = new Thread[nbThread];
650:
651: for (int thread = 0; thread < nbThread; thread++) {
652: ts[thread] = new Thread(new Runnable() {
653: public void run() {
654: TraceTime traceTime = new TraceTime();
655: String action = null;
656: Iterator iter = null;
657:
658: for (int j = 0, i = 0; i < _nbTx; i++) {
659: traceTime.startTask(Thread.currentThread()
660: .getName()
661: + ".loop." + i);
662: logger.log(BasicLevel.INFO, "Start loop " + i);
663: Collections.shuffle(_methodsList);
664: iter = _methodsList.iterator();
665: boolean deadLock = false;
666: String returnStr;
667: while (iter.hasNext()) {
668: if (0 == (j++ % 100.0)) {
669: logger.log(BasicLevel.INFO, j
670: + " actions called...");
671: }
672: action = (String) iter.next();
673: // check if the action need to start a transaction
674: logger.log(BasicLevel.DEBUG,
675: "Calls method:" + action);
676: deadLock = true;
677: while (deadLock) {
678: deadLock = false;
679: try {
680: returnStr = performMethod(action);
681: logger.log(BasicLevel.DEBUG,
682: "The method " + action
683: + " returns:\n"
684: + returnStr);
685: } catch (JDOFatalException e) {
686: logger
687: .log(
688: BasicLevel.INFO,
689: "The method "
690: + action
691: + " throws a JDO Fatal Exception");
692: deadLock = true;
693: } catch (Exception e) {
694: logger
695: .log(
696: BasicLevel.ERROR,
697: "The method "
698: + action
699: + " throws an exception ",
700: e);
701: fail("The method "
702: + action
703: + " throws JDO an exception "
704: + e.getMessage());
705: }
706: }
707: }
708: }
709: traceTime.endTask();
710: logger.log(BasicLevel.INFO,
711: "End of thread loops : "
712: + traceTime.report());
713: }
714: });
715: }
716:
717: //-------------- Launch all threads ------------//
718: for (int thread = 0; thread < nbThread; thread++) {
719: ts[thread].start();
720: }
721:
722: try {
723: //------------ wait threads ------------//
724: for (int thread = 0; thread < nbThread; thread++) {
725: ts[thread].join(timeout);
726: if (ts[thread].isAlive()) {
727: logger
728: .log(
729: BasicLevel.WARN,
730: "Thread "
731: + ts[thread].getName()
732: + " is not finished after the delay, it could be blocked");
733: ts[thread].interrupt();
734: fail("Thread " + ts[thread] + " is blocked!");
735: }
736: }
737: } catch (InterruptedException e) {
738: fail(e.getMessage());
739: }
740: // display the current status of data
741: try {
742: String str = DatabaseImpl.instance.doAction("", false,
743: new PMHolder(getPMF()));
744: logger.log(BasicLevel.DEBUG, str);
745: } catch (Exception e) {
746: logger.log(BasicLevel.ERROR, "Error occurs : ", e);
747: }
748:
749: }
750:
751: /**
752: * this method logs the current test method called and the differents
753: * parameters values.
754: */
755: protected void displayTestParameters() {
756: if (!logger.isLoggable(BasicLevel.INFO))
757: return;
758: // display the calling method
759: Throwable t = new Throwable();
760: StringWriter sw = new StringWriter();
761: PrintWriter pw = new PrintWriter(sw);
762: t.printStackTrace(pw);
763: String input = sw.getBuffer().toString();
764: StringReader sr = new StringReader(input);
765: BufferedReader br = new BufferedReader(sr);
766: try {
767: String line;
768: br.readLine(); // Exception name
769: while (true) {
770: line = br.readLine();
771: int paren = line.indexOf('(');
772: line = line.substring(0, paren);
773: int period = line.lastIndexOf('.');
774: line = line.substring(period + 1);
775: if (line.indexOf("test") != 0)
776: continue;
777: break;
778: }
779: logger.log(BasicLevel.INFO, "The test is : " + line);
780: } catch (Exception e) {
781: }
782:
783: logger
784: .log(BasicLevel.INFO,
785: "The test is launch with the parameters : \nNumber of threads: "
786: + this .nbThread
787: + "\nNumber of actions list loop: "
788: + this .nbTx + "\ntime out (ms): "
789: + this .timeout
790: + "\nnb of read proportion: "
791: + this .nbOfRead
792: + "\nnb of write proportion: "
793: + this .nbOfWrite);
794:
795: int nbCalls = 0;
796: String method;
797: HashMap actionsWeight = new HashMap();
798: Iterator iter = this .methodsList.iterator();
799: int count = -1;
800: while (iter.hasNext()) {
801: method = (String) iter.next();
802: nbCalls++;
803: if (actionsWeight.containsKey(method)) {
804: count = ((Integer) actionsWeight.get(method))
805: .intValue() + 1;
806: actionsWeight.remove(method);
807: actionsWeight.put(method, new Integer(count));
808: } else {
809: actionsWeight.put(method, new Integer(1));
810: }
811: }
812: logger.log(BasicLevel.INFO,
813: "Action list {action1=count, action2=count ...}: "
814: + actionsWeight + "\nTotal number of calls: "
815: + nbCalls);
816: }
817:
818: /**
819: * This method calls action of the DatabaseImpl class according the default
820: * parameters :
821: * <ul>
822: * <li>Default action list set by the setup method</li>
823: * <li>Test through J2EE calls</li>
824: * </ul>
825: */
826: public void testSimple() {
827: this .perform();
828: }
829:
830: /**
831: * This method calls none writing action of the DatabaseImpl class.
832: */
833: public void _testReadOnly() {
834: if (this .simpleTestOnly)
835: return;
836: // Create a new list of methods
837: GenerateListOfActionToBeDone generateMethod = new GenerateListOfActionToBeDone();
838:
839: try {
840: for (int i = 0; i < DatabaseImpl.actionArray.length; i++) {
841: if (0 == DatabaseImpl.actionWeightArray[i][DatabaseImpl.WRITE])
842: generateMethod
843: .registerMethod(
844: DatabaseImpl.actionArray[i],
845: DatabaseImpl.actionWeightArray[i][DatabaseImpl.READ],
846: DatabaseImpl.actionWeightArray[i][DatabaseImpl.WRITE]);
847: }
848: this .nbOfRead = 1;
849: this .nbOfWrite = 0;
850: this .methodsList = generateMethod.mergeWriteReadMethodList(
851: this .nbOfWrite, this .nbOfRead);
852: } catch (Exception e) {
853: e.printStackTrace();
854: }
855: this .perform();
856: }
857:
858: /**
859: * This method calls none deleting action of the DatabaseImpl class.
860: */
861: public void _testIncreaseDatabaseSize() {
862: if (this .simpleTestOnly)
863: return;
864: // Create a new list of methods
865: GenerateListOfActionToBeDone generateMethod = new GenerateListOfActionToBeDone();
866:
867: try {
868: for (int i = 0; i < DatabaseImpl.actionArray.length; i++) {
869: if (!(DatabaseImpl.actionArray[i]
870: .equalsIgnoreCase(DatabaseImpl.PARAMETER_MERGE_DEPARTMENT))
871: && !(DatabaseImpl.actionArray[i]
872: .equalsIgnoreCase(DatabaseImpl.PARAMETER_REM_PROJECT))
873: && !(DatabaseImpl.actionArray[i]
874: .equalsIgnoreCase(DatabaseImpl.PARAMETER_REM_EMPLOYEE)))
875: generateMethod
876: .registerMethod(
877: DatabaseImpl.actionArray[i],
878: DatabaseImpl.actionWeightArray[i][DatabaseImpl.READ],
879: DatabaseImpl.actionWeightArray[i][DatabaseImpl.WRITE]);
880: }
881: this .methodsList = generateMethod.mergeWriteReadMethodList(
882: this .nbOfWrite, this .nbOfRead);
883: } catch (Exception e) {
884: e.printStackTrace();
885: }
886: this.perform();
887: }
888: }
|