// // Copyright (C) 2008 United States Government as represented by the // Administrator of the National Aeronautics and Space Administration // (NASA). All Rights Reserved. // // This software is distributed under the NASA Open Source Agreement // (NOSA), version 1.3. The NOSA has been approved by the Open Source // Initiative. See the file NOSA-1.3-JPF at the top of the distribution // directory tree for the complete NOSA document. // // THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY // KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT // LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO // SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR // A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT // THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT // DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE. // package gov.nasa.jpf.listener; import cmu.conditional.One; import gov.nasa.jpf.Config; import gov.nasa.jpf.JPF; import gov.nasa.jpf.PropertyListenerAdapter; import gov.nasa.jpf.annotation.JPFOption; import gov.nasa.jpf.report.ConsolePublisher; import gov.nasa.jpf.report.Publisher; import gov.nasa.jpf.report.PublisherExtension; import gov.nasa.jpf.search.Search; import gov.nasa.jpf.vm.ChoiceGenerator; import gov.nasa.jpf.vm.Instruction; import gov.nasa.jpf.vm.SystemState; import gov.nasa.jpf.vm.VM; import java.io.PrintWriter; /** * A lightweight listener to generate the error trace by printing * the program instructions at transition boundaries. The idea is to have * a shorter trace output that only shows the choices */ public class ErrorTraceGenerator extends PropertyListenerAdapter implements PublisherExtension { protected ChoiceGenerator<?>[] trace; @JPFOption(type = "Boolean", key = "etg.show_insn", defaultValue = "true", comment = "print instruction that caused CG") protected boolean showInsn = true; @JPFOption(type = "Boolean", key = "etg.show_loc", defaultValue = "true", comment = "print source location that caused CG") protected boolean showLoc = true; @JPFOption(type = "Boolean", key = "etg.show_src", defaultValue = "true", comment = "print source line that caused CG") protected boolean showSrc = true; public ErrorTraceGenerator(Config conf, JPF jpf) { jpf.addPublisherExtension(ConsolePublisher.class, this); showInsn = conf.getBoolean("etg.show_insn", showInsn); showSrc = conf.getBoolean("etg.show_src", showLoc); showLoc = conf.getBoolean("etg.show_loc", showSrc); } public void publishPropertyViolation (Publisher p){ PrintWriter pw = p.getOut(); p.publishTopicStart("error trace choices"); if (trace != null){ int i=0; for (ChoiceGenerator<?> cg : trace){ int tid = cg.getThreadInfo().getId(); Instruction insn; if (cg.getInsn() instanceof One) { insn = cg.getInsn().getValue(); } else { System.err.println("___________________________________________________"); System.err.println("[WARN] Get value of choice called: " + this); System.err.println("---------------------------------------------------"); // Let's wait for a NullPointerException insn = null; } if (!cg.isCascaded()){ pw.printf("#%2d [tid=%2d] ", i++, tid); } else { pw.print(" "); } pw.println(cg); if (!cg.isCascaded()){ if (showLoc){ String loc = insn.getFilePos(); if (loc == null){ loc = "[no file]"; } pw.print("\tat "); pw.print(loc); pw.print(" in "); pw.println( insn.getMethodInfo()); } if (showInsn) { pw.printf("\tinstruction: [pc=%d] %s\n", insn.getPosition(), insn); } if (showSrc) { String srcLine = insn.getSourceLine(); if (srcLine == null){ srcLine = "[no source]"; } else { srcLine = srcLine.trim(); } pw.print("\tsource: "); pw.println( srcLine); } } } } } @Override public void propertyViolated(Search search) { VM vm = search.getVM(); SystemState ss = vm.getSystemState(); trace = ss.getChoiceGenerators(); } }