// // Copyright (C) 2006 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.report; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import cmu.conditional.ChoiceFactory; import de.fosd.typechef.featureexpr.FeatureExprFactory; import gov.nasa.jpf.Config; import gov.nasa.jpf.Error; import gov.nasa.jpf.util.Left; import gov.nasa.jpf.vm.ClassInfo; import gov.nasa.jpf.vm.ClassLoaderInfo; import gov.nasa.jpf.vm.Instruction; import gov.nasa.jpf.vm.MethodInfo; import gov.nasa.jpf.vm.Path; import gov.nasa.jpf.vm.Step; import gov.nasa.jpf.vm.ThreadInfo; import gov.nasa.jpf.vm.Transition; import gov.nasa.jpf.vm.VM; import gov.nasa.jpf.vm.va.StackHandlerFactory; public class ConsolePublisher extends Publisher { // output destinations String fileName; FileOutputStream fos; String port; // the various degrees of information for program traces protected boolean showCG; protected boolean showSteps; protected boolean showLocation; protected boolean showSource; protected boolean showMethod; protected boolean showCode; public ConsolePublisher(Config conf, Reporter reporter) { super(conf, reporter); // options controlling the output destination fileName = conf.getString("report.console.file"); port = conf.getString("report.console.port"); // options controlling what info should be included in a trace showCG = conf.getBoolean("report.console.show_cg", true); showSteps = conf.getBoolean("report.console.show_steps", true); showLocation = conf.getBoolean("report.console.show_location", true); showSource = conf.getBoolean("report.console.show_source", true); showMethod = conf.getBoolean("report.console.show_method", false); showCode = conf.getBoolean("report.console.show_code", false); } public String getName() { return "console"; } protected void openChannel(){ if (fileName != null) { try { fos = new FileOutputStream(fileName); out = new PrintWriter( fos); } catch (FileNotFoundException x) { // fall back to System.out } } else if (port != null) { // <2do> } if (out == null){ out = new PrintWriter(System.out, true); } } protected void closeChannel() { if (fos != null){ out.close(); } } public void publishTopicStart (String topic) { out.println(); out.print("====================================================== "); out.println(topic); } public void publishTopicEnd (String topic) { // nothing here } public void publishStart() { super.publishStart(); if (startItems.length > 0){ // only report if we have output for this phase publishTopicStart("search started: " + formatDTG(reporter.getStartDate())); } } public void publishFinished() { super.publishFinished(); if (finishedItems.length > 0){ // only report if we have output for this phase publishTopicStart("search finished: " + formatDTG(reporter.getFinishedDate())); } } protected void publishJPF() { // out.println(reporter.getJPFBanner()); // out.println(); out.println(" VarexJ v1.0 (" + FeatureExprFactory.dflt().getClass().getSimpleName().substring(0, 3) + ", " + ChoiceFactory.getCurrent() + ", " + StackHandlerFactory.getCurrent() + ")"); out.println(); } protected void publishDTG() { out.println("started: " + reporter.getStartDate()); } protected void publishUser() { out.println("user: " + reporter.getUser()); } protected void publishJPFConfig() { publishTopicStart("JPF configuration"); TreeMap<Object,Object> map = conf.asOrderedMap(); Set<Map.Entry<Object,Object>> eSet = map.entrySet(); for (Object src : conf.getSources()){ out.print("property source: "); out.println(conf.getSourceName(src)); } out.println("properties:"); for (Map.Entry<Object,Object> e : eSet) { out.println(" " + e.getKey() + "=" + e.getValue()); } } protected void publishPlatform() { publishTopicStart("platform"); out.println("hostname: " + reporter.getHostName()); out.println("arch: " + reporter.getArch()); out.println("os: " + reporter.getOS()); out.println("java: " + reporter.getJava()); } protected void publishSuT() { publishTopicStart("system under test"); out.println( reporter.getSuT()); } protected void publishError() { Error e = reporter.getCurrentError(); publishTopicStart("error " + e.getId()); out.println(e.getDescription()); String s = e.getDetails(); if (s != null) { out.println(s); } } protected void publishConstraint() { String constraint = reporter.getLastSearchConstraint(); publishTopicStart("search constraint"); out.println(constraint); // not much info here yet } protected void publishResult() { List<Error> errors = reporter.getErrors(); publishTopicStart("results"); if (errors.isEmpty()) { out.println("no errors detected"); } else { for (Error e : errors) { out.print("error #"); out.print(e.getId()); out.print(": "); out.print(e.getDescription()); String s = e.getDetails(); if (s != null) { s = s.replace('\n', ' '); s = s.replace('\t', ' '); s = s.replace('\r', ' '); out.print(" \""); if (s.length() > 50){ out.print(s.substring(0,50)); out.print("..."); } else { out.print(s); } out.print('"'); } out.println(); } } } /** * this is done as part of the property violation reporting, i.e. * we have an error */ protected void publishTrace() { Path path = reporter.getPath(); int i=0; if (path.size() == 0) { return; // nothing to publish } publishTopicStart("trace " + reporter.getCurrentErrorId()); for (Transition t : path) { out.print("------------------------------------------------------ "); out.println("transition #" + i++ + " thread: " + t.getThreadIndex()); if (showCG){ out.println(t.getChoiceGenerator()); } if (showSteps) { String lastLine = null; MethodInfo lastMi = null; int nNoSrc=0; for (Step s : t) { if (showSource) { String line = s.getLineString(); if (line != null) { if (!line.equals(lastLine)) { if (nNoSrc > 0){ out.println(" [" + nNoSrc + " insn w/o sources]"); } out.print(" "); if (showLocation) { out.print(Left.format(s.getLocationString(),30)); out.print(" : "); } out.println(line.trim()); nNoSrc = 0; } } else { // no source nNoSrc++; } lastLine = line; } if (showCode) { Instruction insn = s.getInstruction(); if (showMethod){ MethodInfo mi = insn.getMethodInfo(); if (mi != lastMi) { ClassInfo mci = mi.getClassInfo(); out.print(" "); if (mci != null) { out.print(mci.getName()); out.print("."); } out.println(mi.getUniqueName()); lastMi = mi; } } out.print(" "); out.println(insn); } } if (showSource && !showCode && (nNoSrc > 0)) { out.println(" [" + nNoSrc + " insn w/o sources]"); } } } } protected void publishOutput() { Path path = reporter.getPath(); if (path.size() == 0) { return; // nothing to publish } publishTopicStart("output " + reporter.getCurrentErrorId()); if (path.hasOutput()) { for (Transition t : path) { String s = t.getOutput(); if (s != null){ out.print(s); } } } else { out.println("no output"); } } protected void publishSnapshot() { VM vm = reporter.getVM(); // not so nice - we have to delegate this since it's using a lot of internals, and is also // used in debugging publishTopicStart("snapshot " + reporter.getCurrentErrorId()); if (vm.getPathLength() > 0) { vm.printLiveThreadStatus(out); } else { out.println("initial program state"); } } public static final String STATISTICS_TOPIC = "statistics"; // this is useful if somebody wants to monitor progress from a specialized ConsolePublisher public synchronized void printStatistics (PrintWriter pw){ publishTopicStart( STATISTICS_TOPIC); printStatistics( pw, reporter); } // this can be used outside a publisher, to show the same info public static void printStatistics (PrintWriter pw, Reporter reporter){ Statistics stat = reporter.getStatistics(); pw.println("elapsed time: " + formatHMS(reporter.getElapsedTime())); pw.println("elapsed time ms: " + reporter.getElapsedTime()); pw.println("states: new=" + stat.newStates + ",visited=" + stat.visitedStates + ",backtracked=" + stat.backtracked + ",end=" + stat.endStates); pw.println("search: maxDepth=" + stat.maxDepth + ",constraints=" + stat.constraints); pw.println("choice generators: thread=" + stat.threadCGs + " (signal=" + stat.signalCGs + ",lock=" + stat.monitorCGs + ",sharedRef=" + stat.sharedAccessCGs + ",threadApi=" + stat.threadApiCGs + ",reschedule=" + stat.breakTransitionCGs + "), data=" + stat.dataCGs); pw.println("heap: " + "new=" + stat.nNewObjects + ",released=" + stat.nReleasedObjects + ",maxLive=" + stat.maxLiveObjects + ",gcCycles=" + stat.gcCycles); pw.println("instructions: " + ThreadInfo.insertDots((int)stat.insns)); long elepsedTime = reporter.getElapsedTime()/1000l; if (elepsedTime == 0) { pw.println("instructions/s: more than " + ThreadInfo.insertDots((int)(stat.insns))); } else { pw.println("instructions/s: " + ThreadInfo.insertDots((int)(stat.insns/elepsedTime))); } pw.println("max memory: " + (stat.maxUsed >> 20) + "MB"); pw.println("loaded code: classes=" + ClassLoaderInfo.getNumberOfLoadedClasses() + ",methods=" + MethodInfo.getNumberOfLoadedMethods()); // createOutput(reporter.getElapsedTime(), stat.visitedStates,(stat.maxUsed >> 20), stat.insns); } /** * TODO add command line option to activate this code * * Add the result to an output file */ @SuppressWarnings("unused") private static void createOutput(long time, long visitedStates, long mb, long insns) { File results = new File("VarexJ.csv"); if (!results.exists()) { try { results.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } System.out.println("write results to " + results + " " + time); try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(results, true)))) { out.print(time); out.print(';'); out.print(visitedStates); out.print(';'); out.print(mb); out.print(';'); out.print(insns); out.println(); } catch (IOException e) { e.printStackTrace(); } } public void publishStatistics() { printStatistics(out); } }