Source Code Cross Referenced for RndEngine.java in  » Testing » TT » U2 » T2 » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Testing » TT » U2.T2 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package U2.T2;
002:
003:        import U2.T2.Obj.*;
004:        import U2.T2.Msg.*;
005:        import U2.T2.Reflection.*;
006:        import java.util.*;
007:        import java.io.*;
008:        import java.util.logging.*;
009:        import java.lang.reflect.*;
010:        import jargs.gnu.CmdLineParser;
011:
012:        /**
013:         * Implements test engine for random testing; it provides the T2's
014:         * <b>main testing API</b>. 
015:         *
016:         * <p>An instance of this class is a test engine. When given a target
017:         * class to test, an engine randomly generates executions, and also
018:         * randomly generates objects needed as parameters for method called
019:         * during the executions. The executions are checked against the class
020:         * invariant of the target class and its other specifications if
021:         * present.
022:         *
023:         *
024:         * <h3>What is being checked?</h3>
025:         *
026:         * <p>An instance of this class is a test engine. An engine generates
027:         * executions, looking for <u>violations</u>. Executions leading to
028:         * violations are reported and can be saved for regression. These are
029:         * the kinds of violations checked by the engine:
030:
031:         * <ol> 
032:         *
033:         * <p><li>INTERNAL error. When a method of the target object raises an
034:         * Error, which is not an AssertionError, or RuntimeException.
035:         *
036:         * <p><li>ASSERTION violation. When a method (or its specification)
037:         * raises an AssertionError, which is not marked by "PRE". If it is
038:         * marked by PRE then its pre-condition is not met, in which case the
039:         * execution will be discarded.
040:         *
041:         * <p><li>CLASSINV violation. This happens when the state after a step
042:         * in an execution violates the class invariant.
043:         *
044:         * <p>Exception thrown by the class invariant will be considered as
045:         * false. If it throws an unchecked exception, the engine will give a
046:         * warning.
047:         *
048:         * </ol>
049:         *
050:         * @see U2.T2.Engine
051:         */
052:        public class RndEngine extends Engine {
053:
054:            /**
055:             * The base domain used by the engine.
056:             */
057:            protected BaseDomain baseDomain;
058:
059:            /**
060:             * A random generator.
061:             */
062:            protected Random rnd;
063:
064:            /**
065:             * In the current implementation the number of relevant checks is
066:             * a bit difficult to count; so we count instead the number of
067:             * irrelevant checks.
068:             */
069:            protected int numOfIrrelevantChecks = 0;
070:
071:            /**
072:             * Specify a maximum on the length of every generated mkVal
073:             * sequence. Default is 4.
074:             */
075:            protected int maxMkValSeqDepth = 4;
076:
077:            // More option parameters:
078:
079:            /**
080:             * The probability to do field update rather than method call.
081:             * Default is 0.1.
082:             */
083:            protected float chooseFieldUpdateProb = (float) 0.1;
084:
085:            /**
086:             * When trying to generate an instance of C, and one cannot be
087:             * found in the base domain, and the engine decided not to look in
088:             * the pool (hence generating a fresh one), this is the
089:             * probability of generating null. If less or equal to null, then
090:             * generating null in this way will be surpressed.
091:             */
092:            protected float generateNullProb = (float) 0.1;
093:
094:            /**
095:             * The probability that when a new execution is to be generated,
096:             * the target object will be picked from the pool rather than
097:             * created fresh with a constructor. Default is 0.7. 
098:             */
099:            protected float pickTargetObjFromPoolProb = (float) 0.7;
100:
101:            /**
102:             * The probability for chosing to pass the target object as a
103:             * parameter rather than as a receiver object. Default is 0.4. 
104:             */
105:            protected float passTObjAsParamProb = (float) 0.4;
106:
107:            /**
108:             * Maximum collection and array length (along each dimension). The
109:             * default is 4.
110:             */
111:            protected int maxArrayLength = 5;
112:
113:            /**
114:             * Maximum depth when showing objects in reporting. That is,
115:             * subobjects at deeper than this depth will not be shown. The
116:             * default is 5.
117:             */
118:            protected int maxShowDepth = 5;
119:
120:            /**
121:             * Collected execution traces. Violating executions are collected
122:             * here, but future versions may add random traces to be
123:             * collected. When the engine is finished, collected traces are
124:             * saved and can be reloaded and replayed by a regression engine.
125:             */
126:            protected LinkedList<Trace> collectedTraces;
127:
128:            /**
129:             * An interface map used by the engine. The map lists interfaces,
130:             * and for each possible concrete classes (currently juts one)
131:             * that implement it. When the engine needs to generate an
132:             * instance of an interface I, it first look it up in this
133:             * interface map. If the map says it has implementations, one
134:             * (say, C) will be selected and the engine will then proceed by
135:             * trying to generate an instance of C instead.
136:             */
137:            protected InterfaceMap interfaceMap;
138:
139:            // Constructors, fields, and methods that are considered to take
140:            // part as interaction points to CUT. For now they are simply
141:            // CUT's non-private constructors and methods:
142:
143:            private List<Constructor> consIPs;
144:            private List<Field> fieldsIPs;
145:            private List<Method> methodsIPs;
146:            // methods that can accept CUT in their parameters:
147:            private List<Method> methodsCanAcceptCUTinParam;
148:            // methods that can accept CUT as their receiver:
149:            private List<Method> methodsCanAcceptCUTinRec;
150:
151:            // specifications found in CUT:
152:            private Method classINV;
153:            // class invariants of the supper-classes; currently not used. INCOMPLETE
154:            private Method[] supperINV;
155:            private HashMap<Method, Method> methodSpecs;
156:
157:            // The type of the elements of collections. Whenever the engine
158:            // has to create a collection, it needs to know the type of its
159:            // elements; however due to Java's type erasure this info is not
160:            // available via reflection. FOR NOW we'll pass this info via the
161:            // top level option, and store it in this variable. This is NOT a
162:            // generic solution. It only works for collection, and applies
163:            // globally. That is, the engine simply assumes that all
164:            // collections it has to generate will have this type of elements.
165:            private Class TYVAR0 = null;
166:
167:            // Logger:
168:            private static Logger logger = Logger.getLogger("U2.T2");
169:
170:            /** 
171:             * Check if a given class is of the right kind (e.g. it is not an interface)
172:             * to be checked with this engine. It the class is not of the right, 
173:             * messages will also be logged.
174:             */
175:            public static boolean doesTargetClassConform(Class C) {
176:
177:                String name = C.getSimpleName();
178:
179:                if (C == null) {
180:                    logger.log(Level.WARNING, Message.mk(Message.PROBLEM,
181:                            "Null is passed as the target class."));
182:                    return false;
183:                }
184:                if (Modifier.isAbstract(C.getModifiers())) {
185:                    logger.log(Level.WARNING, Message.mk(Message.PROBLEM,
186:                            "Target class " + name + " is abstract."));
187:                    return false;
188:                }
189:                if (C.isInterface()) {
190:                    logger.log(Level.WARNING, Message.mk(Message.PROBLEM,
191:                            "Target class " + name + " is an interface."));
192:                    return false;
193:                }
194:                if (ReflUtil.getPubCons(C).size() <= 0) {
195:                    logger.log(Level.WARNING, Message.mk(Message.PROBLEM,
196:                            "Target class " + name
197:                                    + " has no public constructor."));
198:                    return false;
199:
200:                }
201:                // ELSE:
202:                return true;
203:            }
204:
205:            /**
206:             * Create a test engine, with C as the target class, using the
207:             * given pool, base domain, and interface map. 
208:             */
209:            public RndEngine(Class C, Pool p, BaseDomain dom, InterfaceMap imap) {
210:
211:                if (!doesTargetClassConform(C)) {
212:
213:                    Message.throwT2Error(T2Error.ABORT,
214:                            "An instance of RndEngine cannot be created.");
215:                }
216:
217:                rnd = new Random();
218:                pool = p;
219:                baseDomain = dom;
220:                CUT = C;
221:                interfaceMap = imap;
222:
223:                try {
224:                    classINV = CUT.getMethod("classinv", (Class[]) null);
225:                    // check if it is of the right type, if not ignore :
226:                    if (classINV.getReturnType() != Boolean.TYPE
227:                            || !Modifier.isPublic(classINV.getModifiers()))
228:                        classINV = null;
229:                } catch (Exception e) {
230:                    classINV = null;
231:                }
232:
233:                if (classINV == null)
234:                    logger.log(Level.WARNING, Message.mk(Message.PROBLEM, C
235:                            .getName()
236:                            + " does not specify a class invariant."));
237:
238:                collectedTraces = new LinkedList<Trace>();
239:
240:                consIPs = Engine.getConsIPs(C);
241:                fieldsIPs = Engine.getFieldsIPs(C);
242:                methodsIPs = Engine.getMethsIPs(C);
243:                methodSpecs = Engine.mk_specMap(C, methodsIPs);
244:
245:                // open access to aux_laststep hook, if provided by CUT:
246:                try {
247:                    Field aux_laststep_field = C
248:                            .getDeclaredField("aux_laststep");
249:                    if (aux_laststep_field.getType().getName().equals(
250:                            "java.lang.String"))
251:                        aux_laststep_field.setAccessible(true);
252:                } catch (Exception e) {
253:                }
254:
255:                methodsCanAcceptCUTinParam = new LinkedList<Method>();
256:                methodsCanAcceptCUTinRec = new LinkedList<Method>();
257:
258:                for (Method m : methodsIPs) {
259:
260:                    if (ReflUtil.canAcceptAsParameter(CUT, m))
261:                        methodsCanAcceptCUTinParam.add(m);
262:                    if (!Modifier.isStatic(m.getModifiers()))
263:                        methodsCanAcceptCUTinRec.add(m);
264:                }
265:            }
266:
267:            /**
268:             * A method to construct a mk_val step.
269:             */
270:            private Trace.MkValStep MK_VAL_STEP(Class C, int depth) {
271:
272:                // System.out.print(".") ;
273:
274:                // If C is in the base domain, always generate it, even if the
275:                // depth exceeds max:
276:
277:                Object[] r = baseDomain.rndGET(C);
278:                if (r != null)
279:                    return new Trace.CONST(r[0], null);
280:
281:                // If it is not base, and max depth is exceeded, then return
282:                // null:
283:                if (depth >= maxMkValSeqDepth)
284:
285:                    return (new Trace.CONST(null, C));
286:
287:                // Consult the interface map first:
288:                Class C_implementation = interfaceMap.getImplementation(C);
289:                if (C_implementation != null)
290:                    return MK_VAL_STEP(C_implementation, depth);
291:
292:                // If C is class "Object", replace it with TYVAR0 if defined,
293:                // else with CUT:
294:                if (C.getName().equals("java.lang.Object")) {
295:                    if (TYVAR0 != null)
296:                        return MK_VAL_STEP(TYVAR0, depth);
297:                    else
298:                        return MK_VAL_STEP(CUT, depth);
299:                }
300:
301:                // Else pick from the pool or generate fresh:
302:
303:                if (rnd.nextFloat() <= pickTargetObjFromPoolProb) {
304:
305:                    // Deciding to pick the target object from the pool:
306:                    Integer index = pool.rndGetIndex(C);
307:
308:                    if (index != null)
309:                        return new Trace.REF(index);
310:                }
311:
312:                // ELSE we have to generate a fresh object
313:
314:                // To generate null:
315:                if (generateNullProb > 0 && rnd.nextFloat() <= generateNullProb)
316:                    return (new Trace.CONST(null, C));
317:
318:                // If C is an array, linkedlist, or hashset, then make
319:                // one. Currently the maximum size is 4.
320:                Class ClassCollection = null;
321:                try {
322:                    ClassCollection = Class.forName("java.util.Collection");
323:                } catch (Exception e) {
324:                }
325:                if (C.isArray()
326:                        || (!C.isInterface() && ClassCollection
327:                                .isAssignableFrom(C))) {
328:
329:                    Class elemType = null;
330:                    if (C.isArray())
331:                        elemType = C.getComponentType();
332:                    else
333:                    // Deciding the element type of the collection; for
334:                    // now we'll defaul it to TYVAR0 if it is not
335:                    // null. TYVAR0 can be set via top level option. If it
336:                    // is null, we'll default to CUT:
337:                    if (TYVAR0 != null)
338:                        elemType = TYVAR0;
339:                    else
340:                        elemType = CUT;
341:
342:                    int size = rnd.nextInt(maxArrayLength);
343:                    Trace.MkValStep[] elems = new Trace.MkValStep[size];
344:                    for (int i = 0; i < size; i++)
345:                        elems[i] = MK_VAL_STEP(elemType, depth + 1);
346:
347:                    String collectionType = Trace.ARRAY;
348:                    if (!C.isArray())
349:                        collectionType = C.getName();
350:                    return new Trace.CREATE_COLLECTION_LIKE(collectionType,
351:                            elemType, size, elems);
352:                }
353:
354:                // else, creating a fresh object from a constructor.
355:
356:                List<Constructor> constructors = null;
357:                if (C == CUT)
358:                    constructors = consIPs;
359:                else
360:                    constructors = ReflUtil.getPubCons(C);
361:
362:                if (constructors.isEmpty()) // C has no constructor! Would just return null:
363:
364:                    return (new Trace.CONST(null, C));
365:                // ELSE:
366:                Constructor chosenConstructor = constructors.get(rnd
367:                        .nextInt(constructors.size()));
368:                Class[] paramTypes = chosenConstructor.getParameterTypes();
369:                Trace.MkValStep[] params = new Trace.MkValStep[paramTypes.length];
370:
371:                for (int i = 0; i < paramTypes.length; i++)
372:
373:                    params[i] = MK_VAL_STEP(paramTypes[i], depth + 1);
374:
375:                return
376:
377:                (new Trace.CREATE_TARGET_OBJECT(chosenConstructor, params,
378:                // note that it is
379:                        // important that the
380:                        // index is set to -1
381:                        // here:
382:                        -1));
383:
384:            }
385:
386:            /**
387:             * Same as MK_VAL_STEP, but this should create a non-null
388:             * object. Currently implemented by repeatedly trying MK_VAL_STEP
389:             * until it obtains non-null. So it may not terminate. 
390:             */
391:            private Trace.MkValStep MK_NONNULL_VAL_STEP(Class C, int depth) {
392:
393:                Trace.MkValStep step = MK_VAL_STEP(C, depth);
394:                while ((step instanceof  Trace.CONST && ((Trace.CONST) step)
395:                        .isNull())
396:                        || (step instanceof  Trace.REF && (pool
397:                                .get(((Trace.REF) step).getIndex()) == null)))
398:
399:                    step = MK_VAL_STEP(C, depth);
400:
401:                return step;
402:            }
403:
404:            private static <T> T getRndElem(Random rnd, List<T> s) {
405:                if (s.isEmpty())
406:                    return null;
407:                else
408:                    return s.get(rnd.nextInt(s.size()));
409:            }
410:
411:            /**
412:             * A method to construct a step of an execution trace.
413:             */
414:            private Trace.TraceStep TRACE_STEP(int indexOfTargetObj) {
415:
416:                if (rnd.nextFloat() <= chooseFieldUpdateProb
417:                        && fieldsIPs.size() > 0) {
418:
419:                    Field chosen = getRndElem(rnd, fieldsIPs);
420:
421:                    return (new Trace.UPDATE_FIELD(chosen, MK_VAL_STEP(chosen
422:                            .getType(), 0)));
423:                }
424:
425:                // else the step is a method call:
426:
427:                Method method = getRndElem(rnd, methodsCanAcceptCUTinRec);
428:
429:                // if the method has a specification, replace it with its
430:                // specification:
431:                if (methodSpecs.containsKey(method))
432:                    method = methodSpecs.get(method);
433:
434:                int whichParam = -1;
435:
436:                Class[] paramTypes = method.getParameterTypes();
437:
438:                if (rnd.nextFloat() <= passTObjAsParamProb
439:                        && methodsCanAcceptCUTinParam.size() > 0) {
440:
441:                    // Deciding to pass target object as parameter instead 
442:
443:                    method = getRndElem(rnd, methodsCanAcceptCUTinParam);
444:
445:                    paramTypes = method.getParameterTypes();
446:
447:                    LinkedList<Integer> possiblePlaces = new LinkedList<Integer>();
448:                    for (int i = 0; i < paramTypes.length; i++)
449:                        if (paramTypes[i].isAssignableFrom(CUT))
450:                            possiblePlaces.add(i);
451:                    whichParam = getRndElem(rnd, possiblePlaces);
452:
453:                }
454:
455:                Trace.MkValStep[] params = new Trace.MkValStep[paramTypes.length];
456:
457:                for (int i = 0; i < params.length; i++) {
458:
459:                    // note that i>=0, so if whichParam=-1 the guard is false
460:                    // anyway:
461:                    if (i == whichParam)
462:                        params[i] = new Trace.REF(indexOfTargetObj);
463:
464:                    else
465:                        params[i] = MK_VAL_STEP(paramTypes[i], 0);
466:
467:                }
468:
469:                if (Modifier.isStatic(method.getModifiers()))
470:
471:                    return (new Trace.CALL_METHOD(method, null, params));
472:
473:                // else, if method is not static:
474:
475:                Trace.MkValStep receiver = null;
476:
477:                if (whichParam < 0)
478:                    receiver = new Trace.REF(indexOfTargetObj);
479:
480:                else
481:                    receiver = MK_NONNULL_VAL_STEP(method.getDeclaringClass(),
482:                            0);
483:
484:                return (new Trace.CALL_METHOD(method, receiver, params));
485:
486:            }
487:
488:            /**
489:             * The method to run the engine (that is, to run an automated
490:             * random testing). 
491:             */
492:            public void runMe() {
493:
494:                Trace sigma = null;
495:                Trace.TraceStep step = null;
496:                int depth = 0; // the length of sigma
497:                Trace.ExecResult stepResult = null;
498:                boolean invOk = true;
499:
500:                if (maxExecLength <= 0)
501:                    return;
502:
503:                while (numOfSteps < maxNumOfSteps
504:                        && numOfViolations < maxNumViolations) {
505:
506:                    // numOfSteps is now actually number of iterations:
507:                    numOfSteps++;
508:
509:                    if (depth >= maxExecLength) { // max depth exceeded, reset sigma:
510:                        depth = 0;
511:                        sigma = null;
512:                        continue;
513:                    }
514:                    // ELSE:
515:
516:                    if (sigma == null) { // create the target object first:
517:                        // don't forget to reset the pool !!
518:                        pool.reset();
519:                        sigma = new Trace();
520:                        sigma.creation = MK_NONNULL_VAL_STEP(CUT, 0);
521:                        try {
522:                            stepResult = Trace.MkTargetObject(pool,
523:                                    sigma.creation, classINV);
524:                            sigma.indexOfTargetObj = ((Trace.CREATE_TARGET_OBJECT) sigma.creation).indexOfNewObject;
525:
526:                        } catch (InvocationTargetException e) {
527:                            // creation fails, discard: 
528:                            depth = 0;
529:                            sigma = null;
530:                            continue;
531:                        }
532:                        // so the creation was successful:
533:                        numOfExecs++;
534:                    } else {
535:                        step = TRACE_STEP(sigma.indexOfTargetObj);
536:                        sigma.trace.add(step);
537:                        stepResult = Trace.exec(pool, pool
538:                                .get(sigma.indexOfTargetObj), step, classINV);
539:                    }
540:
541:                    if (stepResult.isReqViolating()) {
542:                        numOfViolations++;
543:                        sigma.classification = Trace.VIOLATING_TRACE;
544:                        // record the trace, then clear sigma:
545:                        collectedTraces.add(sigma);
546:                        depth = 0;
547:                        sigma = null;
548:                        continue;
549:                    }
550:                    if (stepResult.isAsmViolating()) {
551:                        // irrelavant step
552:                        numOfIrrelevantChecks++;
553:                        // discarding sigma:
554:                        depth = 0;
555:                        sigma = null;
556:                        continue;
557:                    }
558:                    // Else the step was OK.
559:                    depth++;
560:                }
561:                // end of main loop
562:            }
563:
564:            private static final String lineHsep1 = "----------------------------------------------------";
565:
566:            /**
567:             * To report violating executions found by the engine. 
568:             */
569:            public void report(PrintStream out) {
570:
571:                out.println("");
572:                if (numOfViolations <= 0)
573:                    out.println("** NO violation found.");
574:                else
575:                    out.println("** " + numOfViolations + " VIOLATIONS found.");
576:                out.println(lineHsep1);
577:                out.println("** total attempted execution steps : "
578:                        + numOfSteps);
579:                out.println("** total generated executions      : "
580:                        + numOfExecs);
581:                out.println("** number of irrelevant checks     : "
582:                        + numOfIrrelevantChecks);
583:                out.println(lineHsep1);
584:                out.println("");
585:                if (numOfViolations > 0) {
586:                    int i = 1;
587:                    for (Trace trace : collectedTraces) {
588:                        if (trace.classification != Trace.VIOLATING_TRACE)
589:                            continue;
590:                        // ELSE it is a violating trace:
591:                        // Show.show(trace) ;
592:                        out.println("");
593:                        out.println("** Violating trace [" + i + "] :");
594:                        trace.report(pool, classINV, out);
595:                        i++;
596:                    }
597:                }
598:            }
599:
600:            private void reportOptions(PrintStream out) {
601:                out.println(lineHsep1);
602:                out.println("** Engine CONFIGURATION:");
603:                out.println("** Max. number of steps : " + maxNumOfSteps);
604:                out.println("** Max. execution depth : " + maxExecLength);
605:                out.println("** Max. object depth (on creation) : "
606:                        + maxMkValSeqDepth);
607:                out
608:                        .println("** Max. array/collection size : "
609:                                + maxArrayLength);
610:                if (chooseFieldUpdateProb < 0)
611:                    out.println("** Field update disabled.");
612:                else
613:                    out.println("** Prob. of updating field : "
614:                            + chooseFieldUpdateProb);
615:                if (generateNullProb < 0)
616:                    out.println("** Auto generation of NULL disabled.");
617:                else
618:                    out.println("** Prob. of auto generation of NULL : "
619:                            + generateNullProb);
620:                if (passTObjAsParamProb < 0)
621:                    out
622:                            .println("** Passing target object as parameter disabled.");
623:                else
624:                    out
625:                            .println("** Prob. of passing target obj as parameter : "
626:                                    + passTObjAsParamProb);
627:                out.println("** Prob. of trying pool before constuctor : "
628:                        + pickTargetObjFromPoolProb);
629:                out.println("** CUT           : " + CUT.getName());
630:                if (TYVAR0 == null)
631:                    out.println("** TYVAR0        : " + CUT.getName());
632:                else
633:                    out.println("** TYVAR0        : " + TYVAR0.getName());
634:                out.println("** Pool          : " + pool.getClass().getName());
635:                out.println("** Base domain   : "
636:                        + baseDomain.getClass().getName());
637:                out.println("** Interface map : "
638:                        + interfaceMap.getClass().getName());
639:                out.println(lineHsep1);
640:            }
641:
642:            /**
643:             * A <b>main Testing API</b>; this static method will unleash
644:             * random testing on a given target class. Internally the method
645:             * creates a default test engine and uses it to test the class
646:             * C. Options can be passed to customize the engine; then the
647:             * engine is run. Violating executions will be reported and saved
648:             * in the file C.tr. The method terminates if the underlying test
649:             * engine throws a T2Error.
650:             *
651:             * @param C The class to test. Passing null will print the usage info to the console.
652:             * @param p An object pool to be used by the testing engine.
653:             * @param dom A base domain to be used by the engine.
654:             * @param out The (default) printstream to which the engine will send report.
655:             * @param options Options to configure the engine before running
656:             * it; see the source code of printUsage in this class to see
657:             * available options.
658:             *
659:             */
660:            public static void RndTest(Class C, Pool p, BaseDomain dom,
661:                    InterfaceMap imap, PrintStream out, String[] options)
662:
663:            throws T2Exception {
664:
665:                if (C == null) {
666:                    printUsage(out);
667:                    return;
668:                }
669:
670:                out.println("\n" + Message.GREET);
671:                try {
672:                    out.println("** Creating test engine ...");
673:                    RndEngine E = new RndEngine(C, p, dom, imap);
674:                    E.configureOptions(options);
675:                    E.reportOptions(out);
676:                    out.println("** Testing " + C.getSimpleName() + " ...");
677:                    long time = System.currentTimeMillis();
678:                    E.runMe();
679:                    time = System.currentTimeMillis() - time;
680:                    out.println("** Time elapsed: " + time + " ms");
681:                    E.report(out);
682:                    if (E.collectedTraces.size() > 0) {
683:                        out.println("** Saving traces...");
684:                        Trace.save(C, E.collectedTraces);
685:                        /*
686:                        out.println("** Loading traces...") ;
687:                        try {
688:                        	LinkedList<Trace> savedTraces = E.load(C.getSimpleName()) ;
689:                        	out.println("\n\n** REGRESSING the traces.") ;
690:                        	for (Trace trace : savedTraces) {
691:                        		out.println("\n*******") ;
692:                        		trace.simulate(p) ;
693:                        	} ;
694:                        }
695:                        catch(IOException e) { } ;
696:                         */
697:                    }
698:                    out.println("** DONE.");
699:                } catch (CmdLineParser.OptionException e) {
700:                    printUsage(out);
701:                }
702:            }
703:
704:            /**
705:             * A <b>main Testing API</b>; almost as the other RndTest. However, 
706:             * this one internally catches exceptions and logs the corresponding 
707:             * messages and tracestack. Report will be sent by default to the console.
708:             *
709:             * @param args List of options, including the name of the target class; 
710:             * the latter has to be the first in the list; if the list is empty, 
711:             * help
712:             * 
713:             * @see RndEngine#RndTest(Class,Pool,BaseDomain,InterfaceMap,
714:             * 					      PrintStream,String[])
715:             *
716:             */
717:
718:            public static void RndTest(Pool p, BaseDomain dom,
719:                    InterfaceMap imap, String[] args) {
720:                Class CUT = null;
721:
722:                // Get the target class (CUT):
723:                if (args.length > 0)
724:
725:                    // System.out.println("## " + args[0]) ;
726:
727:                    try {
728:                        CUT = Class.forName(args[0]);
729:                    } catch (Exception e) {
730:                        logger.log(Level.SEVERE,
731:                                "\n## ABORT. T2 fails to get class " + args[0]);
732:                        return;
733:                    }
734:
735:                // Unleash the test engine:
736:
737:                // System.out.println("## " + CUT.getName()) ;
738:
739:                try {
740:                    RndTest(CUT, p, dom, imap, System.out, args);
741:                } catch (Throwable e) {
742:                    StringWriter st = new StringWriter();
743:                    PrintWriter pw = new PrintWriter(st);
744:                    e.printStackTrace(pw);
745:                    pw.flush();
746:                    logger.log(Level.SEVERE, e.getMessage() + "\n"
747:                            + "Strack trace:\n" + st.toString());
748:                }
749:            }
750:
751:            /**
752:             * Short descriptions of available options.
753:             */
754:            protected static String[] optionsShortDesc = {
755:                    "  -l int  Maximum execution depth.",
756:                    "  -d int  Maximum object depth (at the creation).",
757:                    "  -n int Maximum number of execution steps afterwhich RT2 stops.",
758:                    "  -v int  Maximum number of violations afterwhich RT2 stops.",
759:                    "  --elemty=name  The name of the type of elements of Collections.",
760:                    "  --pubonly      Limit the test to public methods members.",
761:                    "  --ownclassonly Limit the test to members declared by the target class.",
762:                    "  --nullprob=value  The probability to generate null. Use negative value to surpress." };
763:
764:            /**
765:             * We'll have to filter methodsCanAcceptCUTinParam again, to take
766:             * into account the elemty option.
767:             */
768:            private boolean canAcceptCUTAsParameter(Method m) {
769:                Class[] paramTypes = m.getParameterTypes();
770:                boolean found = false;
771:                for (int i = 0; i < paramTypes.length && !found; i++)
772:
773:                    found = paramTypes[i].isAssignableFrom(CUT)
774:                            && (TYVAR0 == null || !paramTypes[i].getName()
775:                                    .equals("java.lang.Object"));
776:
777:                return found;
778:            }
779:
780:            /**
781:             * Utiltity to configure the engine from options passed as command
782:             * line arguments. 
783:             */
784:            private void configureOptions(String[] args)
785:                    throws CmdLineParser.OptionException {
786:                if (args == null)
787:                    return;
788:                CmdLineParser parser = new CmdLineParser();
789:                CmdLineParser.Option execLengthO = parser.addIntegerOption('l',
790:                        "lenexec");
791:                CmdLineParser.Option objDepthO = parser.addIntegerOption('d',
792:                        "depthobj");
793:                CmdLineParser.Option maxNumOfStepsO = parser.addIntegerOption(
794:                        'n', "nmax");
795:                CmdLineParser.Option maxNumOfViolO = parser.addIntegerOption(
796:                        'v', "violmax");
797:                CmdLineParser.Option typeOfColElementO = parser
798:                        .addStringOption("elemty");
799:                CmdLineParser.Option pubOnlyO = parser
800:                        .addBooleanOption("pubonly");
801:                CmdLineParser.Option ownClassOnlyO = parser
802:                        .addBooleanOption("ownclassonly");
803:                CmdLineParser.Option nullProbO = parser
804:                        .addDoubleOption("nullprob");
805:
806:                parser.parse(args);
807:
808:                // String [] otherArgs = parser.getRemainingArgs(); 
809:                // 
810:                // if (otherArgs == null || otherArgs.length<=0) 
811:                // throw new CmdLineParser.OptionException() ;
812:
813:                maxNumOfSteps = (Integer) parser.getOptionValue(maxNumOfStepsO,
814:                        maxNumOfSteps);
815:
816:                maxExecLength = (Integer) parser.getOptionValue(execLengthO,
817:                        maxExecLength);
818:
819:                maxNumViolations = (Integer) parser.getOptionValue(
820:                        maxNumOfViolO, maxNumViolations);
821:
822:                maxMkValSeqDepth = (Integer) parser.getOptionValue(objDepthO,
823:                        maxMkValSeqDepth);
824:
825:                if (typeOfColElementO != null)
826:
827:                    try {
828:                        TYVAR0 = Class.forName((String) parser
829:                                .getOptionValue(typeOfColElementO));
830:                        LinkedList<Method> toBeRemoved = new LinkedList<Method>();
831:                        for (Method m : methodsCanAcceptCUTinParam)
832:                            if (!canAcceptCUTAsParameter(m))
833:                                toBeRemoved.add(m);
834:                        for (Method m : toBeRemoved)
835:                            methodsCanAcceptCUTinParam.remove(m);
836:                    }
837:
838:                    catch (Exception e) {
839:                    }
840:
841:                // debug:
842:                // for (Method m : methodsCanAcceptCUTinParam) System.out.println(">>" + m.getName()) ;
843:
844:                if (pubOnlyO != null) {
845:                    ReflUtil.removeNonPubMethods(methodsIPs);
846:                    ReflUtil.removeNonPubMethods(methodsCanAcceptCUTinParam);
847:                    ReflUtil.removeNonPubMethods(methodsCanAcceptCUTinRec);
848:                    ReflUtil.removeNonPubFields(fieldsIPs);
849:                    ReflUtil.removeNonPubCons(consIPs);
850:                }
851:
852:                if (ownClassOnlyO != null) {
853:                    ReflUtil.removeNonCMethods(methodsIPs, CUT);
854:                    ReflUtil.removeNonCMethods(methodsCanAcceptCUTinParam, CUT);
855:                    ReflUtil.removeNonCMethods(methodsCanAcceptCUTinRec, CUT);
856:                    ReflUtil.removeNonCFields(fieldsIPs, CUT);
857:                }
858:
859:                double p = (Double) parser.getOptionValue(nullProbO,
860:                        (double) generateNullProb);
861:                generateNullProb = (float) p;
862:
863:            }
864:
865:            /**
866:             * Print usage help to the console.
867:             */
868:            public static void printUsage(PrintStream out) {
869:                out.println("");
870:                out.println(lineHsep1);
871:                out.println("USAGE.");
872:                out.println("");
873:                out.println("   java  ...  RT2  CUT  Option*");
874:                out.println("");
875:                out.println(lineHsep1);
876:                out.println("");
877:                out.println("...: java options, e.g. class path.");
878:                out.println("CUT: the name of the target class.");
879:                out.println("");
880:                out.println("Available options:");
881:                out.println("");
882:                for (int i = 0; i < optionsShortDesc.length; i++)
883:                    out.println(optionsShortDesc[i]);
884:                out.println(lineHsep1);
885:            }
886:
887:            /**
888:             * Just for testing this class.
889:             */
890:            static public void main(String[] args) {
891:
892:                String[] options = { "U2.T2.Engine" };
893:
894:                RndTest(new Pool(), new BaseDomain0(), new InterfaceMap0(),
895:                        options);
896:
897:                options[0] = "U2.T2.MyPerson";
898:
899:                RndTest(new Pool(), new BaseDomain0(), new InterfaceMap0(),
900:                        options);
901:
902:            }
903:
904:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.