001: package U2.T2;
002:
003: import U2.T2.Obj.*;
004: import U2.T2.Msg.*;
005: import java.util.*;
006: import java.io.*;
007: import java.util.logging.*;
008: import java.lang.reflect.*;
009:
010: /**
011: * Provides T2's <b>main regression API</b>. An instance of this class
012: * is a regression engine. When created, it will load saved executions
013: * of the given target class. Running the engine will replay the
014: * executions.
015: */
016: public class Regression {
017:
018: protected Pool pool;
019: protected Class CUT;
020: Method classINV;
021: // the traces to regress:
022: protected LinkedList<Trace> traces = new LinkedList<Trace>();
023: protected int maxShowDepth = 5;
024:
025: // Logger:
026: private static Logger logger = Logger.getLogger(Regression.class
027: .getName());
028:
029: /**
030: * Create a regression engine. C is the target class. Upon
031: * creation, saved executions of C will be loaded. Currently this
032: * is assumed to be in the file C.tr.
033: *
034: * @param p The object pool which will be used by the engine; this
035: * should be exactly the same pool used to generate the loaded
036: * executions.
037: *
038: * @param showdepth Maximum object depth shown when showing
039: * objects in the report.
040: */
041: public Regression(Class C, Pool p, int showdepth)
042: throws T2Exception {
043: pool = p;
044: CUT = C;
045: maxShowDepth = showdepth;
046: try {
047: classINV = CUT.getMethod("classinv", (Class[]) null);
048: // check if it is of the right type, if not ignore :
049: if (classINV.getReturnType() != Boolean.TYPE
050: || !Modifier.isPublic(classINV.getModifiers()))
051: classINV = null;
052: } catch (Exception e) {
053: classINV = null;
054: }
055: traces = Trace.load(CUT);
056: }
057:
058: /**
059: * This will run the regression engine on the loaded executions
060: * (see {@link Regression Regression}).
061: */
062: public void runMe(PrintStream out) {
063:
064: Object targetObj = null;
065: Trace.ExecResult stepResult = null;
066:
067: Trace violatingTrace = null;
068:
069: MAINLOOP: // break as soon as a violation is found
070:
071: for (Trace sigma : traces) {
072:
073: if (sigma == null)
074: continue;
075: if (sigma.creation == null)
076: continue;
077:
078: pool.reset();
079:
080: // create the target object:
081: try {
082: stepResult = Trace.MkTargetObject(pool, sigma.creation,
083: classINV);
084: } catch (InvocationTargetException e) {
085: violatingTrace = sigma;
086: break MAINLOOP;
087: }
088: if (stepResult.isViolating()) {
089: violatingTrace = sigma;
090: break MAINLOOP;
091: }
092: targetObj = pool.get(sigma.indexOfTargetObj);
093:
094: // now iterate over the steps in the trace:
095: for (Trace.TraceStep step : sigma.trace) {
096:
097: stepResult = Trace
098: .exec(pool, targetObj, step, classINV);
099: if (stepResult.isViolating()) {
100: violatingTrace = sigma;
101: break MAINLOOP;
102: }
103: }
104: }
105:
106: if (violatingTrace != null) {
107: System.out.println("\n** VIOLATION FOUND!");
108: violatingTrace.report(pool, classINV, out);
109: } else
110: out.println("\n** NO violation found!");
111: }
112:
113: /**
114: * This static method is a <b>main Regression API</b>; it will
115: * implicitly create a regression engine targeting the class C,
116: * and run it. It is just the combination of the constructor
117: * Regression followed by runMe.
118: *
119: * @param pool It is important to pass the same type of pool as was used to
120: * produce the loaded traces.
121: *
122: * @param out The default output stream to which report will be sent.
123: */
124: public static void regress(Class C, Pool pool, PrintStream out,
125: int showdepth)
126:
127: throws T2Exception {
128: Regression R = null;
129: R = new Regression(C, pool, showdepth);
130: R.runMe(out);
131: }
132:
133: /**
134: * This is a <b>main Regression API</A>; almost as the other regress.
135: * It will however internally catch exeception and error, and log
136: * appropriate messages. The name of the target class is passed as a string,
137: * along with other options (currently not implemented yet). The report is
138: * by default sent to the console.
139: *
140: * @see Regression#regress(Class,Pool,PrintStream,int)
141: *
142: */
143: public static void regress(Pool pool, String[] args) {
144:
145: if (args.length <= 0)
146: return;
147:
148: // Get the target class (CUT):
149: Class CUT = null;
150: try {
151: CUT = Class.forName(args[0]);
152: }
153:
154: catch (Exception e) {
155: logger.log(Level.SEVERE,
156: "\n## ABORT. RG fails to get class " + args[0]);
157: return;
158: }
159:
160: // Unleasing the regression engine:
161: try {
162: regress(CUT, pool, System.out, 5);
163: } catch (Throwable e) {
164: StringWriter st = new StringWriter();
165: PrintWriter pw = new PrintWriter(st);
166: e.printStackTrace(pw);
167: pw.flush();
168: logger.log(Level.SEVERE, e.getMessage() + "\n"
169: + "Strack trace:\n" + st.toString());
170: }
171:
172: }
173:
174: }
|