001: package org.hansel;
002:
003: import java.util.HashMap;
004: import java.util.List;
005: import java.util.Map;
006: import java.util.Vector;
007:
008: import junit.framework.AssertionFailedError;
009: import junit.framework.TestResult;
010: import junit.framework.TestSuite;
011:
012: import org.hansel.probes.ACmpBranchProbe;
013: import org.hansel.probes.BinaryBranchProbe;
014: import org.hansel.probes.MethodProbe;
015: import org.hansel.probes.NullCmpBranchProbe;
016: import org.hansel.probes.ProbeFilter;
017: import org.hansel.probes.SelectProbe;
018: import org.hansel.probes.UnaryBranchProbe;
019: import org.junit.runner.Description;
020: import org.junit.runner.notification.Failure;
021: import org.junit.runner.notification.RunNotifier;
022:
023: /**
024: * This class contains a table of currently active Probes.
025: * It implements the singleton pattern.
026: *
027: * @author Niklas Mehner
028: */
029: public class ProbeTable extends TestSuite {
030: /** Singleton instance of the ProbeTable. */
031: private static ProbeTable table;
032:
033: /** List containing currently active probes. */
034: private List<Probe> probes;
035:
036: private Map<ProbeData, Probe> probeMap;
037:
038: private boolean displayStatistics;
039:
040: private ProbeFilter probeFilter;
041:
042: public ProbeTable(ProbeFilter probeFilter) {
043: super ("Coverage Test");
044: this .probes = new Vector<Probe>();
045: this .probeMap = new HashMap<ProbeData, Probe>();
046: this .displayStatistics = false;
047: this .probeFilter = probeFilter;
048: }
049:
050: public void setDisplayStatistics(boolean display) {
051: this .displayStatistics = display;
052: }
053:
054: public int addProbe(Probe probe) {
055: // getCached should be called, before adding
056: // a new probe.
057: if (probeMap.containsKey(probe.getProbeData())) {
058: throw new IllegalStateException("Duplicate probe.");
059: }
060:
061: probes.add(probe);
062: probeMap.put(probe.getProbeData(), probe);
063:
064: if ((probeFilter == null)
065: || !probeFilter.filter(probe.getProbeData())) {
066: addTest(probe);
067: }
068:
069: return probes.size() - 1;
070: }
071:
072: public Probe getCached(ProbeData pd) {
073: return (Probe) probeMap.get(pd);
074: }
075:
076: public void hit(int index) {
077: ((MethodProbe) getProbe(index)).hit();
078: }
079:
080: /**
081: * This is the method inserted by the instrumentation, to
082: * record execution of a given probe.
083: * @param index Index of the probe.
084: */
085: public static void hitMethod(int index) {
086: getProbeTable().hit(index);
087: }
088:
089: public void hitB(int condition, int index) {
090: ((UnaryBranchProbe) getProbe(index)).hit(condition);
091: }
092:
093: public static void hitBranch(int condition, int index) {
094: getProbeTable().hitB(condition, index);
095: }
096:
097: public void hit(int n, int m, int index) {
098: ((BinaryBranchProbe) getProbe(index)).hit(n, m);
099: }
100:
101: public static void hitBranch(int n, int m, int index) {
102: getProbeTable().hit(n, m, index);
103: }
104:
105: public void hit(Object obj1, Object obj2, int index) {
106: ((ACmpBranchProbe) getProbe(index)).hit(obj1, obj2);
107: }
108:
109: public static void hitBranch(Object obj1, Object obj2, int index) {
110: getProbeTable().hit(obj1, obj2, index);
111: }
112:
113: public void hit(Object obj, int index) {
114: ((NullCmpBranchProbe) getProbe(index)).hit(obj);
115: }
116:
117: public static void hitBranch(Object obj, int index) {
118: getProbeTable().hit(obj, index);
119: }
120:
121: public void hit(int value, int index) {
122: ((SelectProbe) getProbe(index)).hit(value);
123: }
124:
125: public static void hitSelect(int value, int index) {
126: getProbeTable().hit(value, index);
127: }
128:
129: /**
130: * Returns the index for the next probe. The index of a probe has to be
131: * unique, because it is used to identify the probe, when a call to
132: * ProbeTable.hit(index) is made by the instrumented code.
133: * @return Index for the next probe.
134: */
135: public int getProbeIndex() {
136: return probes.size();
137: }
138:
139: /**
140: * Return the probe for a given index.
141: * @param index Index of the probe.
142: * @return Probe.
143: */
144: private Probe getProbe(int index) {
145: return (Probe) probes.get(index);
146: }
147:
148: public void run(TestResult result) {
149: // Only add coverage problems, if the test did not cause
150: // any other errors/failures.
151: if ((result.errorCount() == 0) && (result.failureCount() == 0)) {
152: super .run(result);
153:
154: int covered = getCovered();
155: int count = getSize();
156: if (displayStatistics && (covered != count)) {
157: String msg = "Coverage Test failed: Only " + covered
158: + " of " + count + " probes covered.";
159: result.addFailure(this , new AssertionFailedError(msg));
160: }
161: } else {
162: result.startTest(this );
163:
164: String msg = "Coverage Failure: No coverage test performed, "
165: + "because test failed.";
166: result.addFailure(this , new AssertionFailedError(msg));
167: result.endTest(this );
168: }
169:
170: // Clear the probe table
171: clear();
172: }
173:
174: public void addProbeDescriptions(Description coverageDesc)
175: throws ClassNotFoundException {
176: for (Probe probe : probes) {
177: coverageDesc.addChild(probe.getDescription());
178: }
179: }
180:
181: public void run(RunNotifier result,
182: Description coverageDescription, boolean hasErrors)
183: throws ClassNotFoundException {
184: // Only add coverage problems, if the test did not cause
185: // any other errors/failures.
186: if (!hasErrors) {
187: int covered = getCovered();
188: int count = getSize();
189: for (Probe probe : probes) {
190: probe.run(result, coverageDescription);
191: }
192: if (displayStatistics && (covered != count)) {
193: String msg = "Coverage Test failed: Only " + covered
194: + " of " + count + " probes covered.";
195: result.fireTestFailure(new Failure(coverageDescription,
196: new AssertionFailedError(msg)));
197: }
198: } else {
199: String msg = "Coverage Failure: No coverage test performed, "
200: + "because test failed.";
201: result.fireTestFailure(new Failure(coverageDescription,
202: new AssertionFailedError(msg)));
203: }
204:
205: // Clear the probe table
206: clear();
207: }
208:
209: public static void setProbeTable(ProbeTable pt) {
210: table = pt;
211: }
212:
213: /**
214: * Returns the singleton instance of the ProbeTable.
215: * @return ProbeTable.
216: */
217: public static ProbeTable getProbeTable() {
218: return table;
219: }
220:
221: public void clear() {
222: probes.clear();
223: }
224:
225: public int getSize() {
226: return probes.size();
227: }
228:
229: public int getCovered() {
230: int covered = 0;
231: for (int i = 0; i < probes.size(); i++) {
232: Probe probe = (Probe) probes.get(i);
233: if (!probe.coverageFailure()) {
234: covered++;
235: }
236: }
237:
238: return covered;
239: }
240:
241: }
|