// Given a set of candidate procedures, find out which of them can be reached public HashSet <string> iterateComputation(PersistentCBAProgram program, HashSet <string> candidates) { var ret = new HashSet <string>(); // Instrument the program. // instrument() sets labelProcMap var newProg = instrument(program, candidates); var verifier = getVerifier(); verifier.run(newProg); // Nothing more can be covered if (verifier.success) { return(ret); } // All these guys were covered foreach (var trace in verifier.traces) { // trace.getProcs().Iter(s => ret.Add(s)); ret.UnionWith(trace.getProcs()); } ret = HashSetExtras <string> .Intersection(ret, candidates); Log.WriteLine(Log.Normal, string.Format("Coverage: Got {0} traces and {1} procs", verifier.traces.Count, ret.Count)); return(ret); }
// Return the set of all procs called from "proc" private HashSet <string> getAllTransitiveSucc(string proc) { var visited = new HashSet <string>(); var frontier = new HashSet <string>(); frontier.Add(proc); while (frontier.Any()) { visited.UnionWith(frontier); var newfrontier = new HashSet <string>(); foreach (var str in frontier) { if (!succEdges.ContainsKey(str)) { continue; } newfrontier.UnionWith(succEdges[str]); } frontier = HashSetExtras <string> .Difference(newfrontier, visited); } return(visited); }
// Does "from" call any proc in "to"? public bool calls(string from, HashSet <string> to) { if (!succEdges.ContainsKey(from)) { return(false); } return(HashSetExtras <string> .Intersection(succEdges[from], to).Count > 0); }
// Given a set of candidate procedures, find out which of them lie // on an error path. This function is iterated until it returns the // empty set or the whole set of candidates public HashSet <string> iterateComputation(PersistentCBAProgram program, HashSet <string> candidates) { var ret = new HashSet <string>(); // Instrument the program. // instrument() sets labelProcMap var newProg = instrument(program, candidates); CommandLineOptions.Clo.ProverCCLimit = 5; var verifier = getVerifier(); verifier.run(newProg); if (verifier.success) { return(ret); } foreach (var trace in verifier.traces) { // Find the failing assert -- it must be in main var blkName = trace.Blocks.Last().blockName; if (labelProcMap.ContainsKey(blkName)) { ret.Add(labelProcMap[blkName]); } } foreach (var trace in verifier.traces) { // trace.getProcs().Iter(s => ret.Add(s)); ret.UnionWith(trace.getProcs()); } ret = HashSetExtras <string> .Intersection(ret, candidates); Log.WriteLine(Log.Normal, string.Format("EP: Got {0} traces and {1} procs", verifier.traces.Count, ret.Count)); return(ret); }
public virtual VarSet Intersection(VarSet second) { return(new VarSet(HashSetExtras <Duple <string, string> > .Intersection(values, second.values))); }
public virtual VarSet Difference(VarSet second) { return(new VarSet(HashSetExtras <Duple <string, string> > .Difference(values, second.values))); }
// Does "from" call any proc in "to" transitively public bool callsTransitive(string from, HashSet <string> to) { return(HashSetExtras <string> .Intersection(getAllTransitiveSucc(from), to).Count > 0); }
public override CBAProgram runCBAPass(CBAProgram p) { procsOnEP = new HashSet <string>(); var nameImplMap = BoogieUtil.nameImplMapping(p); // Set of all procedures (with an implementation) var allProcs = new HashSet <string>(); foreach (var tp in nameImplMap) { allProcs.Add(tp.Key); } var verifier = getVerifier(); // Run verification, gather traces verifier.run(input); // Set verification result success = verifier.success; traces = verifier.traces; // Now, compute the error projection if (verifier.success) { ErrorProjection = allProcs; return(null); } // Look at all procedures that lie on the error trace foreach (var trace in verifier.traces) { procsOnEP.UnionWith(trace.getProcs()); } Log.WriteLine(Log.Normal, string.Format("EP: Got {0} traces and {1} procs", verifier.traces.Count, procsOnEP.Count)); // Just make sure that we inlcude main here (probably not necessary) procsOnEP.Add(p.mainProcName); // Have we already covered all of the program? if (procsOnEP.Equals(allProcs)) { ErrorProjection = new HashSet <string>(); return(null); } // Iterate and try to force the verifier to return paths in // different procedures var done = false; do { var moreProcs = iterateComputation(input as PersistentCBAProgram, HashSetExtras <string> .Difference(allProcs, procsOnEP)); if (moreProcs.Count == 0) { done = true; } else { procsOnEP.UnionWith(moreProcs); if (procsOnEP.Equals(allProcs)) { done = true; } } } while (!done); ErrorProjection = HashSetExtras <string> .Difference(allProcs, procsOnEP); return(null); }
public override CBAProgram runCBAPass(CBAProgram p) { // Run verification, gather traces var verifier = getVerifier(); verifier.run(input); // Set verification result success = verifier.success; traces = verifier.traces; // Now compute coverage, provided error was not reached if (!verifier.success) { return(null); } // Gather procedure names var nameImplMap = BoogieUtil.nameImplMapping(p); var allProcs = new HashSet <string>(); foreach (var tp in nameImplMap) { allProcs.Add(tp.Key); } procsNotCovered = new HashSet <string>(); procsNotCovered.UnionWith(allProcs); procsNotCovered.Remove(p.mainProcName); // Iterate and gather procedures that can be reached int oldProverLimit = CommandLineOptions.Clo.ProverCCLimit; var done = false; do { // Set the number of traces returned by boogie in one shot CommandLineOptions.Clo.ProverCCLimit = procsNotCovered.Count(); var covered = iterateComputation(input as PersistentCBAProgram, procsNotCovered); if (covered.Count == 0) { done = true; } else { procsNotCovered = HashSetExtras <string> .Difference(procsNotCovered, covered); if (!procsNotCovered.Any()) { done = true; } } } while (!done); CommandLineOptions.Clo.ProverCCLimit = oldProverLimit; return(null); }