comparison graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java @ 18485:e3c95cbbb50c

Truffle Instrumentation: major API revision, based around the Probe and Instrument classes; add Instrumentable API for language implementors, with most details automated; reimplemented to handle AST splitting automatically; more JUnit tests.
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Sun, 23 Nov 2014 16:07:23 -0800
parents dc2e000bed40
children 128586040207
comparison
equal deleted inserted replaced
18484:e97e1f07a3d6 18485:e3c95cbbb50c
34 import org.junit.runner.manipulation.*; 34 import org.junit.runner.manipulation.*;
35 import org.junit.runner.notification.*; 35 import org.junit.runner.notification.*;
36 import org.junit.runners.*; 36 import org.junit.runners.*;
37 import org.junit.runners.model.*; 37 import org.junit.runners.model.*;
38 38
39 import com.oracle.truffle.api.*; 39 import com.oracle.truffle.api.frame.*;
40 import com.oracle.truffle.api.instrument.*; 40 import com.oracle.truffle.api.instrument.*;
41 import com.oracle.truffle.api.instrument.impl.*;
42 import com.oracle.truffle.api.nodes.*;
41 import com.oracle.truffle.api.source.*; 43 import com.oracle.truffle.api.source.*;
44 import com.oracle.truffle.sl.factory.*;
42 import com.oracle.truffle.sl.nodes.instrument.*; 45 import com.oracle.truffle.sl.nodes.instrument.*;
46 import com.oracle.truffle.sl.nodes.local.*;
43 import com.oracle.truffle.sl.parser.*; 47 import com.oracle.truffle.sl.parser.*;
44 import com.oracle.truffle.sl.runtime.*; 48 import com.oracle.truffle.sl.runtime.*;
45 import com.oracle.truffle.sl.test.instrument.SLInstrumentTestRunner.InstrumentTestCase; 49 import com.oracle.truffle.sl.test.instrument.SLInstrumentTestRunner.InstrumentTestCase;
46 50
47 /** 51 /**
83 87
84 private final List<InstrumentTestCase> testCases; 88 private final List<InstrumentTestCase> testCases;
85 89
86 public SLInstrumentTestRunner(Class<?> testClass) throws InitializationError { 90 public SLInstrumentTestRunner(Class<?> testClass) throws InitializationError {
87 super(testClass); 91 super(testClass);
92 final SLStandardASTProber prober = new SLStandardASTProber();
93 Probe.registerASTProber(prober);
88 try { 94 try {
89 testCases = createTests(testClass); 95 testCases = createTests(testClass);
90 } catch (IOException e) { 96 } catch (IOException e) {
91 throw new InitializationError(e); 97 throw new InitializationError(e);
98 } finally {
99 Probe.unregisterASTProber(prober);
92 } 100 }
93 } 101 }
94 102
95 @Override 103 @Override
96 protected List<InstrumentTestCase> getChildren() { 104 protected List<InstrumentTestCase> getChildren() {
195 // TODO Current tests are hard-coded, automate this eventually 203 // TODO Current tests are hard-coded, automate this eventually
196 notifier.fireTestStarted(testCase.name); 204 notifier.fireTestStarted(testCase.name);
197 205
198 ByteArrayOutputStream out = new ByteArrayOutputStream(); 206 ByteArrayOutputStream out = new ByteArrayOutputStream();
199 PrintStream printer = new PrintStream(out); 207 PrintStream printer = new PrintStream(out);
208 final ASTProber prober = new SLStandardASTProber();
209 Probe.registerASTProber(prober);
200 try { 210 try {
201 // We use the name of the file to determine what visitor to attach to it. 211 // We use the name of the file to determine what visitor to attach to it.
202 if (testCase.baseName.endsWith(ASSIGNMENT_VALUE_SUFFIX)) { 212 if (testCase.baseName.endsWith(ASSIGNMENT_VALUE_SUFFIX)) {
203 // Set up the execution context for Simple and register our two listeners 213 // Set up the execution context for Simple and register our two listeners
204 slContext = new SLContext(new BufferedReader(new StringReader(testCase.testInput)), printer); 214 slContext = SLContextFactory.create(new BufferedReader(new StringReader(testCase.testInput)), printer);
205 215
206 final Source source = Source.fromText(readAllLines(testCase.path), testCase.sourceName); 216 final Source source = Source.fromText(readAllLines(testCase.path), testCase.sourceName);
207 Parser.parseSL(slContext, source); 217 Parser.parseSL(slContext, source);
208 List<SLFunction> functionList = slContext.getFunctionRegistry().getFunctions(); 218
209 219 // Attach an instrument to every probe tagged as an assignment
210 // Since only functions can be global in SL, this guarantees that we instrument 220 for (Probe probe : Probe.findProbesTaggedAs(StandardSyntaxTag.ASSIGNMENT)) {
211 // everything of interest. Parsing must occur before accepting the visitors since 221 SLPrintAssigmentValueReciever slPrintAssigmentValueReceiver = new SLPrintAssigmentValueReciever(printer);
212 // the visitor which creates our instrumentation points expects a complete AST. 222 probe.attach(Instrument.create(slPrintAssigmentValueReceiver, "SL print assignment value"));
213
214 for (SLFunction function : functionList) {
215 RootCallTarget rootCallTarget = function.getCallTarget();
216 if (rootCallTarget != null) {
217 rootCallTarget.getRootNode().accept(new SLInstrumenter());
218 }
219 }
220
221 // We iterate over all tags the SLInsturmenter tagged as assignments and attach our
222 // test instrument to those.
223 for (Probe probe : slContext.findProbesTaggedAs(StandardSyntaxTag.ASSIGNMENT)) {
224 if (probe.isTaggedAs(StandardSyntaxTag.ASSIGNMENT)) {
225 probe.addInstrument(new SLPrintAssigmentValueInstrument(printer));
226 }
227 } 223 }
228 224
229 SLFunction main = slContext.getFunctionRegistry().lookup("main"); 225 SLFunction main = slContext.getFunctionRegistry().lookup("main");
230 main.getCallTarget().call(); 226 main.getCallTarget().call();
231 } else { 227 } else {
235 String actualOutput = new String(out.toByteArray()); 231 String actualOutput = new String(out.toByteArray());
236 Assert.assertEquals(testCase.expectedOutput, actualOutput); 232 Assert.assertEquals(testCase.expectedOutput, actualOutput);
237 } catch (Throwable ex) { 233 } catch (Throwable ex) {
238 notifier.fireTestFailure(new Failure(testCase.name, ex)); 234 notifier.fireTestFailure(new Failure(testCase.name, ex));
239 } finally { 235 } finally {
236 Probe.unregisterASTProber(prober);
240 notifier.fireTestFinished(testCase.name); 237 notifier.fireTestFinished(testCase.name);
241 } 238 }
242 239
243 } 240 }
244 241
270 @Override 267 @Override
271 public String describe() { 268 public String describe() {
272 return "Filter contains " + pattern; 269 return "Filter contains " + pattern;
273 } 270 }
274 } 271 }
272
273 /**
274 * This sample instrument receiver provides prints the value of an assignment (after the
275 * assignment is complete) to the {@link PrintStream} specified in the constructor. This
276 * instrument can only be attached to a wrapped {@link SLWriteLocalVariableNode}, but provides
277 * no guards to protect it from being attached elsewhere.
278 */
279 public final class SLPrintAssigmentValueReciever extends DefaultEventReceiver {
280
281 private PrintStream output;
282
283 public SLPrintAssigmentValueReciever(PrintStream output) {
284 this.output = output;
285 }
286
287 @Override
288 public void returnValue(Node node, VirtualFrame frame, Object result) {
289 output.println(result);
290 }
291 }
292
275 } 293 }