/// <summary> /// If type is an interface, returns all concrete implementing classes /// else if type is an abstract class, returns all concrete extending classes /// </summary> /// <param name="psd"></param> /// <param name="type"></param> /// <param name="extendingClasses"></param> /// <returns></returns> public static bool TryGetExtendingClasses(PexMeStaticDatabase psd, TypeEx type, out IIndexable <TypeDefinition> extendingClasses) { //load inheritance hierarchies if not already done psd.LoadInheritanceHierarchies(); extendingClasses = null; TypeStore ts; if (!psd.TypeDictionary.TryGetValue(type.Definition, out ts)) { return(false); } SafeSet <TypeDefinition> extendingClassesSet = new SafeSet <TypeDefinition>(); CollectAllExtendingClasses(ts, extendingClassesSet); if (extendingClassesSet.Count == 0) { return(false); } var extendingClassesList = new SafeList <TypeDefinition>(); foreach (var tdef in extendingClassesSet) { extendingClassesList.Add(tdef); } extendingClasses = extendingClassesList; return(true); }
public Connection(IMessageBus newMessageBus, IJsonSerializer jsonSerializer, string baseSignal, string connectionId, IEnumerable<string> signals, IEnumerable<string> groups, ITraceManager traceManager, IAckHandler ackHandler, IPerformanceCounterWriter performanceCounterWriter) { _bus = newMessageBus; _serializer = jsonSerializer; _baseSignal = baseSignal; _connectionId = connectionId; _signals = new HashSet<string>(signals); _groups = new SafeSet<string>(groups); _traceSource = new Lazy<TraceSource>(() => traceManager["SignalR.Connection"]); _ackHandler = ackHandler; var counters = performanceCounterWriter; _msgsRecTotalCounter = counters.GetCounter(PerformanceCounters.ConnectionMessagesReceivedTotal); _msgsRecPerSecCounter = counters.GetCounter(PerformanceCounters.ConnectionMessagesReceivedPerSec); _msgsSentTotalCounter = counters.GetCounter(PerformanceCounters.ConnectionMessagesSentTotal); _msgsSentPerSecCounter = counters.GetCounter(PerformanceCounters.ConnectionMessagesSentPerSec); }
/// <summary> /// Function that retrieves associated method store /// </summary> /// <param name="pms"></param> /// <param name="ms"></param> /// <returns></returns> public static bool TryGetFieldStore(IPexComponent host, PersistentFieldStore pfs, out FieldStore fs) { fs = new FieldStore(); bool bresult = MethodOrFieldAnalyzer.TryGetFieldFromPersistentStringForm(host, pfs.FieldName, out fs.FieldName); SafeDebug.Assume(bresult, "Failed to get field from the persistent store"); fs.FieldValues.AddRange(pfs.FieldValues); //TODO: Performance can be improved via caching over here foreach (var mname in pfs.ReadMethods) { Method m; bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, mname, out m); SafeDebug.Assume(bresult, "Failed to get method from persistent string form "); fs.ReadMethods.Add(m); } foreach (var typeex in pfs.WriteMethods.Keys) { SafeSet<Method> wmethods = new SafeSet<Method>(); TypeEx typeEx; bresult = MethodOrFieldAnalyzer.TryGetTypeExFromPersistentStringForm(host, typeex, out typeEx); SafeDebug.Assume(bresult, "Failed to get type from persistent string form " + typeex); fs.WriteMethods.Add(typeEx, wmethods); HashSet<string> methods; bresult = pfs.WriteMethods.TryGetValue(typeex, out methods); SafeDebug.Assume(bresult, "Failed to get associated set of methods for a type " + typeex); foreach (var m in methods) { Method method; bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, m, out method); SafeDebug.Assume(bresult, "Failed to get method from string form " + m); wmethods.Add(method); } } foreach (var m in pfs.ModificationTypeDictionary.Keys) { var value = pfs.ModificationTypeDictionary[m]; Method method; bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, m, out method); SafeDebug.Assume(bresult, "Failed to get method from string form " + m); fs.ModificationTypeDictionary.Add(method, value); } foreach (var m in pfs.PreciseModificationTypeDictionary.Keys) { var value = pfs.PreciseModificationTypeDictionary[m]; Method method; bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, m, out method); SafeDebug.Assume(bresult, "Failed to get method from string form " + m); fs.PreciseModificationTypeDictionary.Add(method, value); } return true; }
/// <summary> /// Removes if there are any infeasible definitions /// </summary> private void RemoveInfeasibleDefs(DUCoverStore dcs) { //There are either zero or one definitions if (this.defDic.Count <= 1) { return; } SafeSet <FieldDefUseStore> infeasibleDefs = new SafeSet <FieldDefUseStore>(); foreach (var fdef in this.defDic.Keys) { var otherFDefOffsets = this.GetOtherDefOffsetsInMethod(fdef.Method, fdef); if (otherFDefOffsets.Count == 0) { continue; } if (HasRedefinition(dcs, fdef, otherFDefOffsets)) { infeasibleDefs.Add(fdef); } } this.defDic.RemoveRange(infeasibleDefs); }
public Connection(IMessageBus newMessageBus, IJsonSerializer jsonSerializer, string baseSignal, string connectionId, IEnumerable <string> signals, IEnumerable <string> groups, ITraceManager traceManager, IAckHandler ackHandler, IPerformanceCounterWriter performanceCounterWriter) { _bus = newMessageBus; _serializer = jsonSerializer; _baseSignal = baseSignal; _connectionId = connectionId; _signals = new HashSet <string>(signals); _groups = new SafeSet <string>(groups); _traceSource = new Lazy <TraceSource>(() => traceManager["SignalR.Connection"]); _ackHandler = ackHandler; var counters = performanceCounterWriter; _msgsRecTotalCounter = counters.GetCounter(PerformanceCounters.ConnectionMessagesReceivedTotal); _msgsRecPerSecCounter = counters.GetCounter(PerformanceCounters.ConnectionMessagesReceivedPerSec); _msgsSentTotalCounter = counters.GetCounter(PerformanceCounters.ConnectionMessagesSentTotal); _msgsSentPerSecCounter = counters.GetCounter(PerformanceCounters.ConnectionMessagesSentPerSec); }
/// <summary> /// Given a uncovered code location and the associated terms, this /// method infers factory method for that code location. /// /// Assumes that the uncovered branch is mainly due to an object creating issue /// </summary> /// <returns></returns> public bool TryInferFactoryMethod(UncoveredCodeLocationStore ucls, out SafeSet <Method> suggestedMethods) { SafeDebug.AssumeNotNull(ucls, "ucls"); if (ucls.AllFields.Count == 0) { this.host.Log.LogError(WikiTopics.MissingWikiTopic, "factoryguesser", "No information about involving fields in the uncovered branch"); suggestedMethods = null; return(false); } //Check whether the feature is currently supported FieldModificationType fmt = this.GetRequiredFieldModificationType(ucls); if (!(fmt == FieldModificationType.NON_NULL_SET || fmt == FieldModificationType.NULL_SET || fmt == FieldModificationType.INCREMENT || fmt == FieldModificationType.DECREMENT || fmt == FieldModificationType.FALSE_SET || fmt == FieldModificationType.TRUE_SET)) { this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "factoryguesser", "Format " + fmt.ToString() + " is not supported for suggesting factory methods"); suggestedMethods = null; return(false); } //Step 1: Get the exact type whose factory method is required for covering this branch. //Decided based on where there is a subsequent field which can be directly handled rather than the top field. //This step is moved to the place where the uncovered location is initially stored //Step 2: Decide which methods of this type should be invoked. Use a bottomup approach //for inferrinfg the exact method if (!this.GetTargetMethod(ucls, ucls.TargetField, out suggestedMethods)) { this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "factoryguesser", "Failed to retrieve the target method of field " + ucls.TargetField.FullName + " in type " + ucls.ExplorableType.FullName); suggestedMethods = null; return(false); } var sb = new StringBuilder(); foreach (var m in suggestedMethods) { sb.AppendLine(MethodOrFieldAnalyzer.GetMethodSignature(m)); } ucls.SuggestedMethodsforFactory = sb.ToString(); //Create a factory suggestion store. This is expected by the rest of the code. FactorySuggestionStore fss; if (!this.pmd.FactorySuggestionsDictionary.TryGetValue(ucls.ExplorableType.ToString(), out fss)) { fss = new FactorySuggestionStore(); fss.DeclaringType = ucls.ExplorableType.ToString(); this.pmd.FactorySuggestionsDictionary[ucls.ExplorableType.ToString()] = fss; } return(true); }
/// <summary> /// Function that retrieves associated method store /// </summary> /// <param name="pms"></param> /// <param name="ms"></param> /// <returns></returns> public static bool TryGetMethodStore(IPexComponent host, PersistentMethodStore pms, out MethodStore ms) { ms = new MethodStore(); bool bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, pms.methodName, out ms.methodName); SafeDebug.Assume(bresult, "Failed to get the method from persistent form " + pms.methodName); foreach (var fieldstr in pms.ReadFields) { Field field; bresult = MethodOrFieldAnalyzer.TryGetFieldFromPersistentStringForm(host, fieldstr, out field); SafeDebug.Assume(bresult, "Failed to get the field from persistent form " + fieldstr); ms.ReadFields.Add(field); } foreach (var fieldstr in pms.WriteFields) { Field field; bresult = MethodOrFieldAnalyzer.TryGetFieldFromPersistentStringForm(host, fieldstr, out field); SafeDebug.Assume(bresult, "Failed to get the field from persistent form " + fieldstr); ms.WriteFields.Add(field); } foreach (var typeexstr in pms.CallingMethods.Keys) { SafeSet<Method> wmethods = new SafeSet<Method>(); TypeEx typeEx; bresult = MethodOrFieldAnalyzer.TryGetTypeExFromPersistentStringForm(host, typeexstr, out typeEx); if (!bresult) { //No strict safedebugging cannot be added for calling methods since there //can be several dummy methods from Pex side continue; } ms.CallingMethods.Add(typeEx, wmethods); var methods = pms.CallingMethods[typeexstr]; foreach (var mstr in methods) { Method method; bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, mstr, out method); if (!bresult) continue; wmethods.Add(method); } } foreach (var calledMethodStr in pms.CalledMethods) { Method method; bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, calledMethodStr, out method); if (!bresult) continue; ms.CalledMethods.Add(method); } return true; }
public DiffSet(IEnumerable <T> items) { _reset = true; _addedItems = new HashSet <T>(items); _removedItems = new HashSet <T>(); // We don't want to re-enumerate items _items = new SafeSet <T>(_addedItems); }
/// <summary> /// Populates all pair-wise combinations of defs and uses identified through static analysis /// </summary> public void PopulateDUCoverTable() { DUCoverStore dcs = DUCoverStore.GetInstance(); SafeSet <FieldDefUseStore> allDefs = new SafeSet <FieldDefUseStore>(); allDefs.AddRange(this.DefDic.Keys); allDefs.AddRange(this.DefOrUseSet); SafeSet <FieldDefUseStore> allUses = new SafeSet <FieldDefUseStore>(); allUses.AddRange(this.UseDic.Keys); allUses.AddRange(this.DefOrUseSet); int numInfeasible = 0; //Compute pair-wise combinations foreach (var defEntry in allDefs) { foreach (var useEntry in allUses) { //Ignore the trivial entries that involve just a combination of setter and getter methods if (defEntry.Method.ShortName.StartsWith("set_") && useEntry.Method.ShortName.StartsWith("get_")) { continue; } if (!this.IsFeasibleDUCoverEntry(dcs, defEntry, useEntry)) { numInfeasible++; continue; } DUCoverStoreEntry dcse = new DUCoverStoreEntry(this.fd, defEntry.Method, defEntry.Offset, useEntry.Method, useEntry.Offset); if (defEntry.UnknownSideEffectMethod != null) { dcse.Def_UnknownSideEffectMethod = defEntry.UnknownSideEffectMethod; dcse.DefUnsure = true; } if (useEntry.UnknownSideEffectMethod != null) { dcse.Use_UnknownSideEffectMethod = useEntry.UnknownSideEffectMethod; dcse.UseUnsure = true; } if (!this.duCoverageTable.ContainsKey(dcse)) { this.duCoverageTable[dcse] = 0; } } } //Clear all the cached entries. this.feasibilityDicCache.Clear(); logger.Debug("Detected infeasible du-pairs for field " + this.fd.FullName + "(" + numInfeasible + ")"); }
/// <summary> /// Includes filtering of the methods based on desired format /// </summary> /// <returns></returns> public bool TryGetFilteredWriteMethods(Field field, TypeEx declaringType, FieldModificationType desiredfmt, out SafeSet <Method> writeMethods) { //Check in the predefined store before proceeding if (PreDefinedMethodEffects.TryGetWriteMethods(this, field, desiredfmt, out writeMethods)) { SafeSet <Method> newWriteMethods = new SafeSet <Method>(); GetCallingMethods(field, declaringType, writeMethods, newWriteMethods); //Filter those methods whose actual types are abstract SafeSet <Method> returnMethods = new SafeSet <Method>(); foreach (Method m in writeMethods) { TypeEx declType; if (m.TryGetDeclaringType(out declType) && !declType.IsAbstract && !declType.IsInterface) { returnMethods.Add(m); } } foreach (Method m in newWriteMethods) { TypeEx declType; if (m.TryGetDeclaringType(out declType) && !declType.IsAbstract && !declType.IsInterface) { returnMethods.Add(m); } } writeMethods.Clear(); writeMethods.AddRange(returnMethods); return(true); } //Identify those method that directly modify this field if (!TryGetWriteMethods(field, declaringType, out writeMethods)) { return(false); } //C# supports properties. In that case, the property setter can also //be a viable method. add property setter and its callers also Property property; if (MethodOrFieldAnalyzer.TryGetPropertyModifyingField(this, declaringType, field, out property)) { if (property.IsVisible(VisibilityContext.Exported)) { writeMethods.Add(property.Setter); } var newWriteMethods = new SafeSet <Method>(); GetCallingMethods(field, declaringType, writeMethods, newWriteMethods); writeMethods.AddRange(newWriteMethods); } writeMethods = FilterWriteMethodsOfUpdateType(field, desiredfmt, writeMethods); return(true); }
protected override void AfterRun(IPexPathComponent host, object data) { Term[] pathConditions = new Term[] {}; IList <Term> conditions = null; IList <CodeLocation> locations = null; SafeSet <Method> trackingMethods = null; var database = host.GetService <IssueTrackDatabase>(); var unInstrumentedMethods = database.UnInstrumentedMethods; log = database.SimpleLog; foreach (var unInstrumentedMethod in unInstrumentedMethods) { var controller = new ResultTracer(host, unInstrumentedMethod.Method, log); log.AppendLine("try tracking " + unInstrumentedMethod.Method.FullName); log.AppendLine("*****************************************************"); using (IEngine trackingEngine = host.PathServices.TrackingEngineFactory.CreateTrackingEngine(controller)) { trackingEngine.GetService <IPexTrackingDriver>().Run(); pathConditions = Enumerable.ToArray(controller.PathConditions); conditions = controller.Conditions; locations = controller.Locations; trackingMethods = controller.TrackingMethods; } PexLog(host, "ResultTracing", prettyPrintPathCondition(host, pathConditions)); // log.AppendLine("condition: " + prettyPrintPathCondition(host, pathConditions)); PexLog(host, "tracking methods", trackingMethods.Select(x => x.FullName)); for (int i = 0; i < conditions.Count; i++) { var condition = conditions[i]; using (var extractor = new ResultTrackConditionExtractor(host.ExplorationServices.TermManager)) { extractor.VisitTerm(default(TVoid), condition); if (extractor.Method == null) { host.Log.Dump("method", "not in branch", "null"); continue; } PexLog(host, "method", extractor.Method.FullName); PexLog(host, "offset", extractor.CallerOffset.ToString("x")); PexLog(host, "location", extractor.Location.ToString()); var method = extractor.Signature as Method; PexLog(host, "signature", method.FullName); log.AppendLine("found method: " + method.FullName + " in branch " + locations[i]); if (!host.GetService <IssueTrackDatabase>().UninstrumentedMethodInBranch.ContainsKey(locations[i])) { host.GetService <IssueTrackDatabase>().UninstrumentedMethodInBranch.Add(locations[i], method); } } } PexLog(host, "location", locations.Select(x => x.ToString())); log.AppendLine("*****************************************************"); } log.AppendLine("========================="); }
/// <summary> /// Generates nested command files. Ignores if there are any PUTs in /// pmd.PendingExplorationMethods since those methods can cause cycles. /// </summary> /// <param name="allSuggestedNewPUTs"></param> /// <param name="cmdfile"></param> private void GenerateNestedCommandFile(SafeSet <Method> allSuggestedNewPUTs, string cmdfile) { using (StreamWriter sw = new StreamWriter(cmdfile)) { foreach (var newput in allSuggestedNewPUTs) { var newputsig = MethodOrFieldAnalyzer.GetMethodSignature(newput); sw.WriteLine(PUTGenerator.PUTGenerator.GeneratePUTCommand(newput)); } } }
/// <summary> /// Filters out covered code locations /// </summary> public void FilterOutCoveredCodeLocations() { //Finding out covered locations //Also Finding out other locations in system libraries //that do not contribute to increase in the covered. Those //libraries should also be removed var coveredLocations = new SafeSet <UncoveredCodeLocationStoreList>(); foreach (var uclStoreList in this.UncoveredLocationDictionary.Values) { var cl = uclStoreList.Location; if (this.IsBranchOffsetCoveredInMethod(cl.Method, cl.Offset)) { coveredLocations.Add(uclStoreList); } else { //Check whether the uncoverd location is in system library var currAssembly = this.Services.CurrentAssembly.Assembly.Assembly; bool bDeleteUCList = true; foreach (var ucstore in uclStoreList.StoreList) { //Check the CUTMethodCall sequence in the ucstore to decide //whether to continue with this foreach (var method in ucstore.CUTMethodCallSequence) { var methoddef = method.Definition; if (methoddef.Module.Assembly == currAssembly && !this.AreAllOffsetsCoveredInMethod(method)) { bDeleteUCList = false; break; } } if (!bDeleteUCList) { break; } } if (bDeleteUCList) { coveredLocations.Add(uclStoreList); } } } foreach (var covered in coveredLocations) { var key = UncoveredCodeLocationStore.GetKey(covered.Location.ToString(), covered.ExplorableType, covered.TermIndex); this.UncoveredLocationDictionary.Remove(key); } }
/// <summary> /// Generates a put for an uncovered DUCoverStoreEntry /// </summary> /// <param name="dcse"></param> public void GeneratePUT(DUCoverStoreEntry dcse) { //Check whether the TypeEx of field, and both the methods is same. If not raise warning TypeEx fieldTypeEx; if (!dcse.Field.TryGetDeclaringType(out fieldTypeEx)) { logger.Warn("Failed to get the declaring type of the field " + dcse.Field.FullName); return; } TypeEx defMethodEx; if (!dcse.DefMethod.TryGetDeclaringType(out defMethodEx)) { logger.Warn("Failed to get the declaring type of the method " + dcse.DefMethod.FullName); return; } TypeEx useMethodEx; if (!dcse.UseMethod.TryGetDeclaringType(out useMethodEx)) { logger.Warn("Failed to get the declaring type of the method " + dcse.UseMethod.FullName); return; } if (!fieldTypeEx.Equals(defMethodEx) || !defMethodEx.Equals(useMethodEx)) { logger.Warn("All declaring types of field, def-method, and use-method should be same for generating PUT. Condition failed for " + dcse.ToString()); return; } try { string putgenerated = ""; SafeSet <string> existingPUTs; if (!this.PUTDictionary.TryGetValue(fieldTypeEx.FullName, out existingPUTs)) { existingPUTs = new SafeSet <string>(); this.PUTDictionary[fieldTypeEx.FullName] = existingPUTs; } existingPUTs.Add(putgenerated); } catch (Exception ex) { logger.ErrorException("Failed to generate PUT for " + dcse.ToString() + " " + ex.Message, ex); } }
public Connection(IMessageBus messageBus, IJsonSerializer jsonSerializer, string baseSignal, string connectionId, IEnumerable<string> signals, IEnumerable<string> groups, ITraceManager traceManager) { _messageBus = messageBus; _serializer = jsonSerializer; _baseSignal = baseSignal; _connectionId = connectionId; _signals = new HashSet<string>(signals); _groups = new SafeSet<string>(groups); _trace = traceManager; }
public Connection(INewMessageBus newMessageBus, IJsonSerializer jsonSerializer, string baseSignal, string connectionId, IEnumerable <string> signals, IEnumerable <string> groups, ITraceManager traceManager) { _bus = newMessageBus; _serializer = jsonSerializer; _baseSignal = baseSignal; _connectionId = connectionId; _signals = new HashSet <string>(signals); _groups = new SafeSet <string>(groups); _traceSource = new Lazy <TraceSource>(() => traceManager["SignalR.Connection"]); }
public Connection(INewMessageBus newMessageBus, IJsonSerializer jsonSerializer, string baseSignal, string connectionId, IEnumerable<string> signals, IEnumerable<string> groups, ITraceManager traceManager) { _bus = newMessageBus; _serializer = jsonSerializer; _baseSignal = baseSignal; _connectionId = connectionId; _signals = new HashSet<string>(signals); _groups = new SafeSet<string>(groups); _traceSource = new Lazy<TraceSource>(() => traceManager["SignalR.Connection"]); }
public Connection(IMessageBus messageBus, IJsonSerializer jsonSerializer, string baseSignal, string connectionId, IEnumerable <string> signals, IEnumerable <string> groups, ITraceManager traceManager) { _messageBus = messageBus; _serializer = jsonSerializer; _baseSignal = baseSignal; _connectionId = connectionId; _signals = new HashSet <string>(signals); _groups = new SafeSet <string>(groups); _trace = traceManager; }
/// <summary> /// recursively collects all extending classes /// </summary> /// <param name="ts"></param> private static void CollectAllExtendingClasses(TypeStore ts, SafeSet <TypeDefinition> extendingClasses) { if (extendingClasses.Contains(ts.Type)) { return; } foreach (var innerts in ts.ExtendingTypes) { if (!innerts.Type.IsAbstract && !innerts.Type.IsInterface) { extendingClasses.Add(innerts.Type); } CollectAllExtendingClasses(innerts, extendingClasses); } }
protected double EvaluateArithmeticModel(ref IArithmeticModel model) { double distance = 0.0; double fitnessValue = 0.0; Term innerTerm; SafeSet <Term> visited = new SafeSet <Term>(); this.fitnessEvaluations++; foreach (var variable in this.context.Variables) { foreach (var constraint in variable.Constraints) { if (!visited.Add(constraint)) { continue; } if (this.termManager.TryGetInnerLogicallyNegatedValue(constraint, out innerTerm)) { distance = EvaluateConstraint(ref model, innerTerm, true); } else { distance = EvaluateConstraint(ref model, constraint, false); } if (distance == Double.MaxValue) { fitnessValue = distance; break; } else { fitnessValue += distance; } } } visited.ClearAndTrim(); visited = null; return(fitnessValue); }
private void GetCallingMethods(Field field, TypeEx declaringType, SafeSet <Method> writeMethods, SafeSet <Method> newWriteMethods) { foreach (var writeM in writeMethods) { if (writeM.Definition.DeclaredVisibility != Visibility.Private || writeM.IsConstructor) { newWriteMethods.Add(writeM); continue; } //Get other calling methods within this type SafeSet <Method> localCM; if (this.TryGetCallingMethodsInType(writeM, field, declaringType, out localCM)) { newWriteMethods.AddRange(localCM); } } }
internal SafeSet <Method> FilterCallingMethodsBasedOnField(Method tmw, Field field, SafeSet <Method> callingMethods) { SafeSet <Method> filteredMethods = new SafeSet <Method>(); foreach (var callingm in callingMethods) { //Filter the calling method based on the field MethodBodyEx body; if (!callingm.TryGetBody(out body) || !body.HasInstructions) { continue; } int offset = 0; Instruction instruction; bool bContinueWithNextMethod = false; Field lastAccessedField = null; while (body.TryGetInstruction(offset, out instruction) && !bContinueWithNextMethod) { SafeDebug.AssumeNotNull(instruction, "instruction"); OpCode opCode = instruction.OpCode; if (opCode == OpCodes.Ldfld || opCode == OpCodes.Ldflda) { SafeDebug.Assume(opCode.OperandType == OperandType.InlineField, "opCode.OperandType == OperandType.InlineField"); lastAccessedField = instruction.Field; } else if (opCode == OpCodes.Call || opCode == OpCodes.Callvirt) { SafeDebug.Assume(opCode.OperandType == OperandType.InlineMethod, "opCode.OperandType == OperandType.InlineMethod"); Method methodinner = instruction.Method; if (methodinner == tmw && field == lastAccessedField) { filteredMethods.Add(callingm); bContinueWithNextMethod = true; } lastAccessedField = null; } offset = instruction.NextOffset; } } return(filteredMethods); }
protected internal Task Save(Message message) { var key = message.SignalKey; SafeSet<Message> list; if (!_items.TryGetValue(key, out list)) { list = new SafeSet<Message>(); _items.TryAdd(key, list); } list.Add(message); if (message.Id > _messageId) { lock (_idLocker) { if (message.Id > _messageId) { _messageId = message.Id; } } } return TaskAsyncHelper.Empty; }
public Connection(IMessageBus newMessageBus, IJsonSerializer jsonSerializer, string baseSignal, string connectionId, IEnumerable <string> signals, IEnumerable <string> groups, ITraceManager traceManager, IAckHandler ackHandler, IPerformanceCounterManager performanceCounterManager) { _bus = newMessageBus; _serializer = jsonSerializer; _baseSignal = baseSignal; _connectionId = connectionId; _signals = new HashSet <string>(signals, StringComparer.OrdinalIgnoreCase); _groups = new SafeSet <string>(groups); _traceSource = new Lazy <TraceSource>(() => traceManager["SignalR.Connection"]); _ackHandler = ackHandler; _counters = performanceCounterManager; }
public Connection(IMessageBus newMessageBus, IJsonSerializer jsonSerializer, string baseSignal, string connectionId, IEnumerable<string> signals, IEnumerable<string> groups, ITraceManager traceManager, IAckHandler ackHandler, IPerformanceCounterManager performanceCounterManager) { _bus = newMessageBus; _serializer = jsonSerializer; _baseSignal = baseSignal; _connectionId = connectionId; _signals = new HashSet<string>(signals, StringComparer.OrdinalIgnoreCase); _groups = new SafeSet<string>(groups); _traceSource = new Lazy<TraceSource>(() => traceManager["SignalR.Connection"]); _ackHandler = ackHandler; _counters = performanceCounterManager; }
/// <summary> /// Retrieves the write methods for a field, if exists from the predefined settings. /// </summary> public static bool TryGetWriteMethods(IPexComponent host, Field field, FieldModificationType desiredFmt, out SafeSet<Method> writeMethods) { if (!isPredefinedEffectsParsed) ParsePredefinedEffects(host); PreDefinedMethodEffectsStore pdme = new PreDefinedMethodEffectsStore(field, desiredFmt); PreDefinedMethodEffectsStore existingPdme; if (effectsStore.TryGetValue(pdme, out existingPdme)) { writeMethods = new SafeSet<Method>(); writeMethods.AddRange(existingPdme.suggestedmethodList); return true; } else { writeMethods = null; return false; } }
/// <summary> /// Makes a mapping relationship between a calling method and a called method /// </summary> /// <param name="callingMethod"></param> /// <param name="calledMethod"></param> public void AddMethodMapping(Method callingMethod, Method calledMethod) { //Updating the method store for calling methods MethodStore callingMethodStore = null; if (!methodDic.TryGetValue(callingMethod, out callingMethodStore)) { callingMethodStore = new MethodStore(); callingMethodStore.methodName = calledMethod; methodDic[callingMethod] = callingMethodStore; } callingMethodStore.CalledMethods.Add(calledMethod); //Updating the method store for called methods MethodStore calledMethodStore = null; if (!methodDic.TryGetValue(calledMethod, out calledMethodStore)) { calledMethodStore = new MethodStore(); calledMethodStore.methodName = calledMethod; methodDic[calledMethod] = calledMethodStore; } TypeEx callingMethodType; if (!callingMethod.TryGetDeclaringType(out callingMethodType)) { this.Log.LogError(WikiTopics.MissingWikiTopic, "methodmapping", "Failed to get the declared type for method " + calledMethod); return; } SafeSet <Method> localCallingMethods; if (!calledMethodStore.CallingMethods.TryGetValue(callingMethodType, out localCallingMethods)) { localCallingMethods = new SafeSet <Method>(); calledMethodStore.CallingMethods[callingMethodType] = localCallingMethods; } localCallingMethods.Add(callingMethod); }
/// <summary> /// Given a set of write methods, this method basically filters them out /// to create a new set. Also filters the method that belongs to the interface type /// </summary> /// <param name="field"></param> /// <param name="fieldModificationType"></param> /// <param name="writeMethods"></param> /// <returns></returns> private SafeSet <Method> FilterWriteMethodsOfUpdateType(Field field, FieldModificationType fieldModificationType, SafeSet <Method> writeMethods) { FieldStore fs; if (!this.FieldDictionary.TryGetValue(field, out fs)) { return(writeMethods); } SafeSet <Method> returnSet = new SafeSet <Method>(); foreach (var method in writeMethods) { //no need of methods in interfaces or abstract classes. TypeEx declType; if (method.TryGetDeclaringType(out declType) && (declType.IsAbstract || declType.IsInterface)) { continue; } //We currently allow unknown types FieldModificationType fmt; //Problem of static analysis impreciseness. If no modificuatui if (!fs.ModificationTypeDictionary.TryGetValue(method, out fmt)) { returnSet.Add(method); } if (fmt == fieldModificationType || fmt == FieldModificationType.UNKNOWN || fmt == FieldModificationType.METHOD_CALL) { returnSet.Add(method); } } return(returnSet); }
/// <summary> /// Retrieves the write methods for a field, if exists from the predefined settings. /// </summary> public static bool TryGetWriteMethods(IPexComponent host, Field field, FieldModificationType desiredFmt, out SafeSet <Method> writeMethods) { if (!isPredefinedEffectsParsed) { ParsePredefinedEffects(host); } PreDefinedMethodEffectsStore pdme = new PreDefinedMethodEffectsStore(field, desiredFmt); PreDefinedMethodEffectsStore existingPdme; if (effectsStore.TryGetValue(pdme, out existingPdme)) { writeMethods = new SafeSet <Method>(); writeMethods.AddRange(existingPdme.suggestedmethodList); return(true); } else { writeMethods = null; return(false); } }
/// <summary> /// Function that retrieves associated method store /// </summary> /// <param name="pms"></param> /// <param name="ms"></param> /// <returns></returns> public static bool TryGetMethodStore(IPexComponent host, PersistentMethodStore pms, out MethodStore ms) { ms = new MethodStore(); bool bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, pms.methodName, out ms.methodName); SafeDebug.Assume(bresult, "Failed to get the method from persistent form " + pms.methodName); foreach (var fieldstr in pms.ReadFields) { Field field; bresult = MethodOrFieldAnalyzer.TryGetFieldFromPersistentStringForm(host, fieldstr, out field); SafeDebug.Assume(bresult, "Failed to get the field from persistent form " + fieldstr); ms.ReadFields.Add(field); } foreach (var fieldstr in pms.WriteFields) { Field field; bresult = MethodOrFieldAnalyzer.TryGetFieldFromPersistentStringForm(host, fieldstr, out field); SafeDebug.Assume(bresult, "Failed to get the field from persistent form " + fieldstr); ms.WriteFields.Add(field); } foreach (var typeexstr in pms.CallingMethods.Keys) { SafeSet <Method> wmethods = new SafeSet <Method>(); TypeEx typeEx; bresult = MethodOrFieldAnalyzer.TryGetTypeExFromPersistentStringForm(host, typeexstr, out typeEx); if (!bresult) { //No strict safedebugging cannot be added for calling methods since there //can be several dummy methods from Pex side continue; } ms.CallingMethods.Add(typeEx, wmethods); var methods = pms.CallingMethods[typeexstr]; foreach (var mstr in methods) { Method method; bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, mstr, out method); if (!bresult) { continue; } wmethods.Add(method); } } foreach (var calledMethodStr in pms.CalledMethods) { Method method; bresult = MethodOrFieldAnalyzer.TryGetMethodFromPersistentStringForm(host, calledMethodStr, out method); if (!bresult) { continue; } ms.CalledMethods.Add(method); } return(true); }
private void GetCallingMethods(Field field, TypeEx declaringType, SafeSet<Method> writeMethods, SafeSet<Method> newWriteMethods) { foreach (var writeM in writeMethods) { if (writeM.Definition.DeclaredVisibility != Visibility.Private || writeM.IsConstructor) { newWriteMethods.Add(writeM); continue; } //Get other calling methods within this type SafeSet<Method> localCM; if (this.TryGetCallingMethodsInType(writeM, field, declaringType, out localCM)) { newWriteMethods.AddRange(localCM); } } }
/// <summary> /// recursively collects all extending classes /// </summary> /// <param name="ts"></param> private static void CollectAllExtendingClasses(TypeStore ts, SafeSet<TypeDefinition> extendingClasses) { if (extendingClasses.Contains(ts.Type)) return; foreach (var innerts in ts.ExtendingTypes) { if (!innerts.Type.IsAbstract && !innerts.Type.IsInterface) extendingClasses.Add(innerts.Type); CollectAllExtendingClasses(innerts, extendingClasses); } }
/// <summary> /// Computes method effects statically. All written fields of a method. /// Can be imprecise and conservative /// </summary> /// <param name="declaringType"></param> /// <param name="method"></param> /// <param name="effects"></param> /// <returns></returns> public static bool TryComputeMethodEffects(IPexComponent host, TypeEx declaringType, Method method, SafeSet <Method> visitedMethods, out MethodEffects effects) { SafeDebug.AssumeNotNull(declaringType, "declaringType"); SafeDebug.AssumeNotNull(method, "method"); try { if (visitedMethods == null) { visitedMethods = new SafeSet <Method>(); } if (visitedMethods.Contains(method)) { effects = null; return(false); } visitedMethods.Add(method); //Check whether this has been computed before var psd = host.GetService <IPexMeStaticDatabase>() as PexMeStaticDatabase; if (psd.MethodEffectsDic.TryGetValue(method.GlobalIndex, out effects)) { return(true); } var res = new SafeSet <string>(); var directSetFields = new SafeSet <string>(); var directCalledMethods = new SafeSet <Method>(); var returnFields = new SafeSet <Field>(); var modificationTypeDic = new SafeDictionary <string, FieldModificationType>(); var parameters = method.Parameters; MethodBodyEx body; if (!method.TryGetBody(out body) || !body.HasInstructions) { effects = null; return(false); } int callDepth = 0; int offset = 0; Instruction instruction; OpCode prevOpcode = OpCodes.Nop; //Stack for load instructions Field lastAccessedArrayField = null; Field lastAccessedField = null; while (body.TryGetInstruction(offset, out instruction)) { SafeDebug.AssumeNotNull(instruction, "instruction"); OpCode opCode = instruction.OpCode; if (LdcOpCodes.Contains(opCode)) { //topIsConstant = true; } else if (ConvOpCodes.Contains(opCode)) { // do not change topIsConstant } else { if (opCode == OpCodes.Stfld) { SafeDebug.Assume(opCode.OperandType == OperandType.InlineField, "opCode.OperandType == OperandType.InlineField"); Field field = instruction.Field; AddFieldToMethodEffects(host, declaringType, res, directSetFields, modificationTypeDic, prevOpcode, field, field.Type); } else if (opCode == OpCodes.Ldfld || opCode == OpCodes.Ldflda) { SafeDebug.Assume(opCode.OperandType == OperandType.InlineField, "opCode.OperandType == OperandType.InlineField"); Field accessedField = instruction.Field; if (accessedField.Type.Spec == TypeSpec.SzArray) { lastAccessedArrayField = accessedField; } else { lastAccessedField = accessedField; } } else if (StElemOpCodes.Contains(opCode)) { if (lastAccessedArrayField != null) { //Indicates that there is n array type modified AddFieldToMethodEffects(host, declaringType, res, directSetFields, modificationTypeDic, prevOpcode, lastAccessedArrayField, lastAccessedArrayField.Type); lastAccessedArrayField = null; } } else if (opCode == OpCodes.Call || opCode == OpCodes.Callvirt) { SafeDebug.Assume(opCode.OperandType == OperandType.InlineMethod, "opCode.OperandType == OperandType.InlineMethod"); Method methodinner = instruction.Method; SafeDebug.AssumeNotNull(method, "method"); directCalledMethods.Add(methodinner); TypeEx methodDeclaringType; //are these function calls are within the parent types if (methodinner.TryGetDeclaringType(out methodDeclaringType) && declaringType.IsAssignableTo(methodDeclaringType)) { MethodEffects methodEffects; if (TryComputeMethodEffects(host, methodDeclaringType, methodinner, visitedMethods, out methodEffects)) { res.AddRange(methodEffects.WrittenInstanceFields); foreach (var key in methodEffects.ModificationTypeDictionary.Keys) { modificationTypeDic[key] = methodEffects.ModificationTypeDictionary[key]; } directSetFields.AddRange(methodEffects.DirectSetterFields); if (methodEffects.CallDepth > callDepth) { callDepth = methodEffects.CallDepth; } } } else { //introducing heuristics for inter-procedural static analysis if (lastAccessedField != null && lastAccessedField.Type.IsReferenceType && !(methodinner.ShortName.StartsWith("Get") || methodinner.ShortName.StartsWith("get") || methodinner.ShortName.StartsWith("Set") || methodinner.ShortName.StartsWith("set"))) { AddFieldToMethodEffects(host, declaringType, res, directSetFields, modificationTypeDic, prevOpcode, lastAccessedField, lastAccessedField.Type); } } } else if (opCode == OpCodes.Ret) { if (instruction.Field != null) { returnFields.Add(instruction.Field); } } //topIsConstant = false; } prevOpcode = opCode; offset = instruction.NextOffset; } effects = new MethodEffects((IFiniteSet <string>)res, directSetFields, directCalledMethods, returnFields, modificationTypeDic, callDepth + 1); psd.MethodEffectsDic[method.GlobalIndex] = effects; return(true); } catch (Exception ex) { host.Log.LogErrorFromException(ex, WikiTopics.MissingWikiTopic, "methodeffects", "Failed to compute method effects for method " + method.FullName + "," + ex.Message); effects = null; return(false); } }
/// <summary> /// Given a set of write methods, this method basically filters them out /// to create a new set. Also filters the method that belongs to the interface type /// </summary> /// <param name="field"></param> /// <param name="fieldModificationType"></param> /// <param name="writeMethods"></param> /// <returns></returns> private SafeSet<Method> FilterWriteMethodsOfUpdateType(Field field, FieldModificationType fieldModificationType, SafeSet<Method> writeMethods) { FieldStore fs; if (!this.FieldDictionary.TryGetValue(field, out fs)) return writeMethods; SafeSet<Method> returnSet = new SafeSet<Method>(); foreach (var method in writeMethods) { //no need of methods in interfaces or abstract classes. TypeEx declType; if (method.TryGetDeclaringType(out declType) && (declType.IsAbstract || declType.IsInterface)) { continue; } //We currently allow unknown types FieldModificationType fmt; //Problem of static analysis impreciseness. If no modificuatui if (!fs.ModificationTypeDictionary.TryGetValue(method, out fmt)) returnSet.Add(method); if (fmt == fieldModificationType || fmt == FieldModificationType.UNKNOWN || fmt == FieldModificationType.METHOD_CALL) returnSet.Add(method); } return returnSet; }
public ProxyObservable() { _observers = new SafeSet <Needle <IObserver <T> > >(); }
private static TypeEx AddFieldToMethodEffects(IPexComponent host, TypeEx declaringType, SafeSet<Field> res, SafeSet<Field> directSetFields, SafeDictionary<Field, FieldModificationType> modificationTypeDic, OpCode prevOpcode, Field field, TypeEx fieldType) { SafeDebug.AssumeNotNull(field, "field"); SafeDebug.Assume(!field.IsStatic, "!field.IsStatic"); TypeEx fieldDeclaringType; //The following check ensures that the field belongs to this class //or its base classes if (field.TryGetDeclaringType(out fieldDeclaringType) && declaringType.IsAssignableTo(fieldDeclaringType)) { res.Add(field); var fieldTypeStr = fieldType.ToString(); if (fieldTypeStr == "System.Int32" || fieldTypeStr == "System.Int64" || fieldTypeStr == "System.Int16") { if (prevOpcode == OpCodes.Add) modificationTypeDic[field] = FieldModificationType.INCREMENT; else if (prevOpcode == OpCodes.Sub) modificationTypeDic[field] = FieldModificationType.DECREMENT; else host.Log.LogWarning(WikiTopics.MissingWikiTopic, "fieldmodificationtype", "Encountered unknown modification type for integer type " + prevOpcode); } else { if (field.Type.IsReferenceType) { if (prevOpcode == OpCodes.Ldnull) modificationTypeDic[field] = FieldModificationType.NULL_SET; else if (prevOpcode == OpCodes.Newarr || prevOpcode == OpCodes.Newobj) modificationTypeDic[field] = FieldModificationType.NON_NULL_SET; else host.Log.LogWarning(WikiTopics.MissingWikiTopic, "fieldmodificationtype", "Encountered unknown modification type for reference type " + prevOpcode); } else if (fieldTypeStr == "System.Boolean") { if (prevOpcode == OpCodes.Ldc_I4_0) modificationTypeDic[field] = FieldModificationType.FALSE_SET; else if (prevOpcode == OpCodes.Ldc_I4_1) modificationTypeDic[field] = FieldModificationType.TRUE_SET; else host.Log.LogWarning(WikiTopics.MissingWikiTopic, "fieldmodificationtype", "Encountered unknown modification type for boolean type " + prevOpcode); } } //A heuristic based approach for aliasing analysis for checking whether the field is directly //assigned any parameters if (LdArgOpCodes.Contains(prevOpcode)) directSetFields.Add(field); } return fieldDeclaringType; }
/// <summary> /// Compares current uncovered locations with the previous uncovered locations /// </summary> internal void AnalyzePreviousAndCurrentUncoveredLoc(string currPUTSignature, out HashSet<string> allGivenUpLocations, out HashSet<string> allCoveredLocations, out HashSet<string> newUncoveredLocations, out bool hasSomeCoveredLocation, out bool bAllAreNewLocations, out bool bNoneAreNewLocations) { hasSomeCoveredLocation = false; bAllAreNewLocations = true; bNoneAreNewLocations = true; var resolvedPrevLocations = new SafeSet<string>(); var bestFitnessValues = new SafeDictionary<string, int>(); //This dictionary is constructed since the FactorySuggestionStore is based //on declarting type not on the explorable type, which can be different allGivenUpLocations = new HashSet<string>(); allCoveredLocations = new HashSet<string>(); tempAllLocationStore = new SafeDictionary<string, PersistentUncoveredLocationStore>(); //All final suggested sequences of the current PUT var putspecificsequences = new List<MethodSignatureSequence>(); foreach (var fss in this.FactorySuggestionsDictionary.Values) { foreach (var codelockey in fss.locationStoreSpecificSequences.Keys) { var pucls = fss.locationStoreSpecificSequences[codelockey]; if (!pucls.IsDormat()) //Donot touch dormant persistent stores tempAllLocationStore[codelockey] = pucls; } foreach (var givenUpLocation in fss.PermanentFailedUncoveredLocations) allGivenUpLocations.Add(givenUpLocation); foreach (var coveredLocation in fss.SuccessfulCoveredLocations) allCoveredLocations.Add(coveredLocation); //MethodSignatureSequenceList mssl; //if (fss.FinalPUTSequences.TryGetValue(currPUTSignature, out mssl)) //{ // foreach (var seq in mssl.SequenceList) // { // if (!putspecificsequences.Contains(seq)) // putspecificsequences.Add(seq); // } //} } var failedLocations = new SafeSet<PersistentUncoveredLocationStore>(); //Traverse all uncovered locations foreach (var ucovLocList in this.UncoveredLocationDictionary.Values) { var locationStr = ucovLocList.Location.ToString(); var key = UncoveredCodeLocationStore.GetKey(ucovLocList.Location.ToString(), ucovLocList.ExplorableType.ToString(), ucovLocList.TermIndex); //Check whether there are any defect detecting sequences. If yes promote them //in the associated factory store foreach (var ucls in ucovLocList.StoreList) { if (ucls.IsADefectDetectingSequence) { var fss = this.FactorySuggestionsDictionary[ucls.ExplorableType.ToString()]; SafeDebug.AssumeNotNull(fss, "fss cannot be null"); fss.AddToDefectDetectingSequences(ucls.MethodCallSequence); } } if (allGivenUpLocations.Contains(key)) { //This location has been earlier given up. No need to deal with this resolvedPrevLocations.Add(key); this.Log.LogMessage(WikiTopics.MissingWikiTopic, "Location " + locationStr + " is ignored since it was already given up earlier!!!"); continue; } if (allCoveredLocations.Contains(key)) { //This location has been covered earlier. Ideally this case should not happen //resolvedPrevLocations.Add(key); this.Log.LogMessage(WikiTopics.MissingWikiTopic, "Location " + locationStr + " is previously covered, but can be reported since the caller could be different."); bAllAreNewLocations = false; //continue; } //Get the associated factory suggestion store if (tempAllLocationStore.ContainsKey(key)) { bAllAreNewLocations = false; var pucls = tempAllLocationStore[key]; resolvedPrevLocations.Add(key); //For some formats such as TRUE_SET, we do not need the fitness measure //If they are not covered in one attempt, they won't be covered any time if (ucovLocList.StoreList.Count > 0) { var fmt = ucovLocList.StoreList[0].DesiredFieldModificationType; if (!this.IsFitnessRequired(fmt)) { pucls.NumberOfUnsuccessfulAttempts = PexMeConstants.MAX_UNSUCCESSFUL_ATTEMPTS + 1; } } //Reached the threshold of number of attempts. So deleting this uncovered location forever if (pucls.NumberOfUnsuccessfulAttempts + 1 <= PexMeConstants.MAX_UNSUCCESSFUL_ATTEMPTS) { //Handle according to fitness value and drop the other methods that //acutally did not help increase the fitness value this.RemoveSuggestionsWithLowFitness(ucovLocList, tempAllLocationStore[key], putspecificsequences); this.Log.LogMessage(WikiTopics.MissingWikiTopic, "Location " + locationStr + " is resolved and is still uncovered in the new run " + "(fitness: " + pucls.Fitnessvalue + "), (Attempt: " + pucls.NumberOfUnsuccessfulAttempts + ")"); } else { this.Log.LogMessage(WikiTopics.MissingWikiTopic, "Location " + locationStr + " is resolved and but not making any process!!! Will be deleted forever"); //This pucls data will be deleted forever since it reached its max attempts without any progress failedLocations.Add(pucls); } } } //New locations that added to the factory suggestion store newUncoveredLocations = new HashSet<string>(); foreach (var ucovLocList in this.UncoveredLocationDictionary.Values) { var key = UncoveredCodeLocationStore.GetKey(ucovLocList.Location.ToString(), ucovLocList.ExplorableType.ToString(), ucovLocList.TermIndex); if (!resolvedPrevLocations.Contains(key)) { newUncoveredLocations.Add(key); this.Log.LogMessage(WikiTopics.MissingWikiTopic, "Location " + ucovLocList.Location.ToString() + " is newly added in the new run"); bNoneAreNewLocations = false; } } //Unresolved locations from the previous run. This means that these sequences //are either already covered or not covered due to some new exception... var unresolvedPrevLocations = new SafeSet<PersistentUncoveredLocationStore>(); var alreadyCoveredLocations = new SafeSet<PersistentUncoveredLocationStore>(); foreach (var fss in this.FactorySuggestionsDictionary.Values) { var allRemovedPUCLS = new List<PersistentUncoveredLocationStore>(); //Delete all failed locations if the suggested methods for this //failed location are all actually already explored. If not, place //them in pending status. Usually this case happens, if covering //the same location within the method is required by another location foreach (var pucls in failedLocations) { var key = UncoveredCodeLocationStore.GetKey(pucls.CodeLocation.ToString(), pucls.ExplorableType.ToString(), pucls.TermIndex); fss.RemoveUncoveredLocationStore(pucls, false, this); allRemovedPUCLS.Add(pucls); } foreach (var codelockey in fss.locationStoreSpecificSequences.Keys) { var tpucls = fss.locationStoreSpecificSequences[codelockey]; if (tpucls.IsDormat()) continue; if (allGivenUpLocations.Contains(codelockey)) { bAllAreNewLocations = false; unresolvedPrevLocations.Add(tpucls); this.Log.LogWarning(WikiTopics.MissingWikiTopic, "UncoveredLocation", "Location " + codelockey + " was already given up. Should not be reported again!!! Anyways, Deleting this location forever"); continue; } if (!resolvedPrevLocations.Contains(codelockey)) { //Check whether this location is covered based on the coverage if (tpucls.AlreadyCovered || this.IsPrevUncoveredLocationCovered(tpucls)) { alreadyCoveredLocations.Add(tpucls); this.Log.LogMessage(WikiTopics.MissingWikiTopic, "Location " + codelockey + " is successfully covered in the new run"); hasSomeCoveredLocation = true; } else { bAllAreNewLocations = false; unresolvedPrevLocations.Add(tpucls); this.Log.LogWarning(WikiTopics.MissingWikiTopic, "UncoveredLocation", "Location " + codelockey + " from the previous run is not found in the new run!!! Deleting this location forever"); } } } //Delete all unresolved locations as they won't be required anymore!!! foreach (var pucls in unresolvedPrevLocations) { fss.RemoveUncoveredLocationStore(pucls, false, this); allRemovedPUCLS.Add(pucls); } //Handle all removed PUCLS foreach (var pucls in allRemovedPUCLS) { var key = UncoveredCodeLocationStore.GetKey(pucls.CodeLocation, pucls.ExplorableType, pucls.TermIndex); fss.PermanentFailedUncoveredLocations.Add(key); if (!fss.TemporaryFailedUncoveredLocations.ContainsKey(key)) { //Are there any active uncovered locations if (this.AnyActiveUncoveredLocations()) fss.TemporaryFailedUncoveredLocations[key] = 1; else fss.TemporaryFailedUncoveredLocations[key] = PexMeConstants.MAX_UNCOVEREDLOC_ATTEMPTS; } } //Delete all the information regarding covered locations and upgrade their specific factory methods foreach (var pucls in alreadyCoveredLocations) { fss.RemoveUncoveredLocationStore(pucls, true, this); } alreadyCoveredLocations.Clear(); } }
/// <summary> /// Gets calling methods of a given called method on the given field in a given target type /// </summary> /// <returns></returns> public bool TryGetCallingMethodsInType(Method calledMethod, Field field, TypeEx targetType, out SafeSet<Method> callingMethods) { SafeDebug.AssumeNotNull(calledMethod, "method"); SafeDebug.AssumeNotNull(targetType, "type"); //Get the associated property of the field Property property; if (!MethodOrFieldAnalyzer.TryGetPropertyReadingField(this, targetType, field, out property)) { //TODO: error; } MethodStore mstore = null; if (this.MethodDictionary.TryGetValue(calledMethod, out mstore)) { if (mstore.CallingMethods.TryGetValue(targetType, out callingMethods)) return true; } //No method store found. create a fresh one if (mstore == null) { mstore = new MethodStore(); mstore.methodName = calledMethod; this.MethodDictionary[calledMethod] = mstore; } callingMethods = new SafeSet<Method>(); mstore.CallingMethods[targetType] = callingMethods; TypeEx calledMethodType; if (!calledMethod.TryGetDeclaringType(out calledMethodType)) { this.Log.LogError(WikiTopics.MissingWikiTopic, "callingmethods", "Failed to get the declaring type for the method " + calledMethod.FullName); return false; } //Needs to addess the array type issue over here. var targetdef = targetType.Definition; if (targetdef == null) { if (targetType.TypeKind != TypeKind.SzArrayElements) { this.Log.LogError(WikiTopics.MissingWikiTopic, "callingmethods", "The definition for the type " + targetType.FullName + " is null"); return false; } else { targetdef = targetType.ElementType.Definition; } } //Analyze each method in the given type to identify the calling methods //of the given method foreach (var typeMethod in targetdef.DeclaredInstanceMethods) { Method minstance = typeMethod.Instantiate(targetType.GenericTypeArguments, MethodOrFieldAnalyzer.GetGenericMethodParameters(this, typeMethod)); MethodEffects meffects; if (!MethodOrFieldAnalyzer.TryComputeMethodEffects(this, targetType, minstance, null, out meffects)) continue; //Check for a direct comparison if (meffects.DirectCalledMethods.Contains(calledMethod)) callingMethods.Add(minstance); else { //Use vtable lookup for addressing the abstract issues foreach (var dcallMethod in meffects.DirectCalledMethods) { if (dcallMethod.IsConstructor) continue; TypeEx dcallMethodType; if (dcallMethod.TryGetDeclaringType(out dcallMethodType)) { if (dcallMethodType == calledMethodType || !dcallMethodType.IsAbstract || !dcallMethodType.IsInterface) continue; if (!dcallMethodType.IsAssignableTo(calledMethodType) && !calledMethodType.IsAssignableTo(dcallMethodType)) continue; } try { var lookupMethod = calledMethodType.VTableLookup(dcallMethod); if (lookupMethod != null && calledMethod == lookupMethod) { callingMethods.Add(minstance); break; } } catch (Exception ex) { this.Log.LogWarningFromException(ex, WikiTopics.MissingWikiTopic, "vtablelookup", "Failed to perform vtablelookup for " + dcallMethod.FullName + " in type " + calledMethodType.FullName); } } } } //Check whether there are any private methods in calling methods. //If yes, replace them with their callers. if (!PexMeConstants.DISABLE_CALLING_METHODS_WITHIN_CLASS) { var newCallingMethods = new SafeSet<Method>(); foreach (var callingM in callingMethods) { if (callingM.Definition.DeclaredVisibility != Visibility.Private || callingM.IsConstructor) { newCallingMethods.Add(callingM); continue; } //Get other calling methods within this type SafeSet<Method> localCM; if (this.TryGetCallingMethodsInType(callingM, field, targetType, out localCM)) { newCallingMethods.AddRange(localCM); } } callingMethods.Clear(); callingMethods.AddRange(newCallingMethods); } //Needs to further analyze parent types TypeEx baseType = targetType.BaseType; if (baseType != null && baseType.FullName != "System.Object") //TODO: Avoid string comparisons. needs to figure out how to do that { SafeSet<Method> baseCallingMethods; TryGetCallingMethodsInType(calledMethod, field, baseType, out baseCallingMethods); callingMethods.AddRange(baseCallingMethods); } return true; }
/// <summary> /// Generates nested command files. Ignores if there are any PUTs in /// pmd.PendingExplorationMethods since those methods can cause cycles. /// </summary> /// <param name="allSuggestedNewPUTs"></param> /// <param name="cmdfile"></param> private void GenerateNestedCommandFile(SafeSet<Method> allSuggestedNewPUTs, string cmdfile) { using (StreamWriter sw = new StreamWriter(cmdfile)) { foreach (var newput in allSuggestedNewPUTs) { var newputsig = MethodOrFieldAnalyzer.GetMethodSignature(newput); sw.WriteLine(PUTGenerator.PUTGenerator.GeneratePUTCommand(newput)); } } }
/// <summary> /// Computes method effects statically. All written fields of a method. /// Can be imprecise and conservative /// </summary> /// <param name="declaringType"></param> /// <param name="method"></param> /// <param name="effects"></param> /// <returns></returns> public static bool TryComputeMethodEffects(IPexComponent host, TypeEx declaringType, Method method, SafeSet<Method> visitedMethods, out MethodEffects effects) { SafeDebug.AssumeNotNull(declaringType, "declaringType"); SafeDebug.AssumeNotNull(method, "method"); try { if (visitedMethods == null) visitedMethods = new SafeSet<Method>(); if (visitedMethods.Contains(method)) { effects = null; return false; } visitedMethods.Add(method); //Check whether this has been computed before var psd = host.GetService<IPexMeStaticDatabase>() as PexMeStaticDatabase; if (psd.MethodEffectsDic.TryGetValue(method.GlobalIndex, out effects)) return true; var res = new SafeSet<string>(); var directSetFields = new SafeSet<string>(); var directCalledMethods = new SafeSet<Method>(); var returnFields = new SafeSet<Field>(); var modificationTypeDic = new SafeDictionary<string, FieldModificationType>(); var parameters = method.Parameters; MethodBodyEx body; if (!method.TryGetBody(out body) || !body.HasInstructions) { effects = null; return false; } int callDepth = 0; int offset = 0; Instruction instruction; OpCode prevOpcode = OpCodes.Nop; //Stack for load instructions Field lastAccessedArrayField = null; Field lastAccessedField = null; while (body.TryGetInstruction(offset, out instruction)) { SafeDebug.AssumeNotNull(instruction, "instruction"); OpCode opCode = instruction.OpCode; if (LdcOpCodes.Contains(opCode)) { //topIsConstant = true; } else if (ConvOpCodes.Contains(opCode)) { // do not change topIsConstant } else { if (opCode == OpCodes.Stfld) { SafeDebug.Assume(opCode.OperandType == OperandType.InlineField, "opCode.OperandType == OperandType.InlineField"); Field field = instruction.Field; AddFieldToMethodEffects(host, declaringType, res, directSetFields, modificationTypeDic, prevOpcode, field, field.Type); } else if (opCode == OpCodes.Ldfld || opCode == OpCodes.Ldflda) { SafeDebug.Assume(opCode.OperandType == OperandType.InlineField, "opCode.OperandType == OperandType.InlineField"); Field accessedField = instruction.Field; if (accessedField.Type.Spec == TypeSpec.SzArray) { lastAccessedArrayField = accessedField; } else lastAccessedField = accessedField; } else if (StElemOpCodes.Contains(opCode)) { if (lastAccessedArrayField != null) { //Indicates that there is n array type modified AddFieldToMethodEffects(host, declaringType, res, directSetFields, modificationTypeDic, prevOpcode, lastAccessedArrayField, lastAccessedArrayField.Type); lastAccessedArrayField = null; } } else if (opCode == OpCodes.Call || opCode == OpCodes.Callvirt) { SafeDebug.Assume(opCode.OperandType == OperandType.InlineMethod, "opCode.OperandType == OperandType.InlineMethod"); Method methodinner = instruction.Method; SafeDebug.AssumeNotNull(method, "method"); directCalledMethods.Add(methodinner); TypeEx methodDeclaringType; //are these function calls are within the parent types if (methodinner.TryGetDeclaringType(out methodDeclaringType) && declaringType.IsAssignableTo(methodDeclaringType)) { MethodEffects methodEffects; if (TryComputeMethodEffects(host, methodDeclaringType, methodinner, visitedMethods, out methodEffects)) { res.AddRange(methodEffects.WrittenInstanceFields); foreach (var key in methodEffects.ModificationTypeDictionary.Keys) modificationTypeDic[key] = methodEffects.ModificationTypeDictionary[key]; directSetFields.AddRange(methodEffects.DirectSetterFields); if (methodEffects.CallDepth > callDepth) callDepth = methodEffects.CallDepth; } } else { //introducing heuristics for inter-procedural static analysis if (lastAccessedField != null && lastAccessedField.Type.IsReferenceType && !(methodinner.ShortName.StartsWith("Get") || methodinner.ShortName.StartsWith("get") || methodinner.ShortName.StartsWith("Set") || methodinner.ShortName.StartsWith("set"))) { AddFieldToMethodEffects(host, declaringType, res, directSetFields, modificationTypeDic, prevOpcode, lastAccessedField, lastAccessedField.Type); } } } else if (opCode == OpCodes.Ret) { if (instruction.Field != null) returnFields.Add(instruction.Field); } //topIsConstant = false; } prevOpcode = opCode; offset = instruction.NextOffset; } effects = new MethodEffects((IFiniteSet<string>)res, directSetFields, directCalledMethods, returnFields, modificationTypeDic, callDepth + 1); psd.MethodEffectsDic[method.GlobalIndex] = effects; return true; } catch (Exception ex) { host.Log.LogErrorFromException(ex, WikiTopics.MissingWikiTopic, "methodeffects", "Failed to compute method effects for method " + method.FullName + "," + ex.Message); effects = null; return false; } }
/// <summary> /// If type is an interface, returns all concrete implementing classes /// else if type is an abstract class, returns all concrete extending classes /// </summary> /// <param name="psd"></param> /// <param name="type"></param> /// <param name="extendingClasses"></param> /// <returns></returns> public static bool TryGetExtendingClasses(PexMeStaticDatabase psd, TypeEx type, out IIndexable<TypeDefinition> extendingClasses) { //load inheritance hierarchies if not already done psd.LoadInheritanceHierarchies(); extendingClasses = null; TypeStore ts; if (!psd.TypeDictionary.TryGetValue(type.Definition, out ts)) return false; SafeSet<TypeDefinition> extendingClassesSet = new SafeSet<TypeDefinition>(); CollectAllExtendingClasses(ts, extendingClassesSet); if (extendingClassesSet.Count == 0) return false; var extendingClassesList = new SafeList<TypeDefinition>(); foreach (var tdef in extendingClassesSet) { extendingClassesList.Add(tdef); } extendingClasses = extendingClassesList; return true; }
/// <summary> /// Filters out covered code locations /// </summary> public void FilterOutCoveredCodeLocations() { //Finding out covered locations //Also Finding out other locations in system libraries //that do not contribute to increase in the covered. Those //libraries should also be removed var coveredLocations = new SafeSet<UncoveredCodeLocationStoreList>(); foreach (var uclStoreList in this.UncoveredLocationDictionary.Values) { var cl = uclStoreList.Location; if (this.IsBranchOffsetCoveredInMethod(cl.Method, cl.Offset)) { coveredLocations.Add(uclStoreList); } else { //Check whether the uncoverd location is in system library var currAssembly = this.Services.CurrentAssembly.Assembly.Assembly; bool bDeleteUCList = true; foreach (var ucstore in uclStoreList.StoreList) { //Check the CUTMethodCall sequence in the ucstore to decide //whether to continue with this foreach (var method in ucstore.CUTMethodCallSequence) { var methoddef = method.Definition; if (methoddef.Module.Assembly == currAssembly && !this.AreAllOffsetsCoveredInMethod(method)) { bDeleteUCList = false; break; } } if (!bDeleteUCList) break; } if (bDeleteUCList) coveredLocations.Add(uclStoreList); } } foreach (var covered in coveredLocations) { var key = UncoveredCodeLocationStore.GetKey(covered.Location.ToString(), covered.ExplorableType, covered.TermIndex); this.UncoveredLocationDictionary.Remove(key); } }
/// <summary> /// Makes a mapping relationship between a calling method and a called method /// </summary> /// <param name="callingMethod"></param> /// <param name="calledMethod"></param> public void AddMethodMapping(Method callingMethod, Method calledMethod) { //Updating the method store for calling methods MethodStore callingMethodStore = null; if (!methodDic.TryGetValue(callingMethod, out callingMethodStore)) { callingMethodStore = new MethodStore(); callingMethodStore.methodName = calledMethod; methodDic[callingMethod] = callingMethodStore; } callingMethodStore.CalledMethods.Add(calledMethod); //Updating the method store for called methods MethodStore calledMethodStore = null; if(!methodDic.TryGetValue(calledMethod, out calledMethodStore)) { calledMethodStore = new MethodStore(); calledMethodStore.methodName = calledMethod; methodDic[calledMethod] = calledMethodStore; } TypeEx callingMethodType; if (!callingMethod.TryGetDeclaringType(out callingMethodType)) { this.Log.LogError(WikiTopics.MissingWikiTopic, "methodmapping", "Failed to get the declared type for method " + calledMethod); return; } SafeSet<Method> localCallingMethods; if (!calledMethodStore.CallingMethods.TryGetValue(callingMethodType, out localCallingMethods)) { localCallingMethods = new SafeSet<Method>(); calledMethodStore.CallingMethods[callingMethodType] = localCallingMethods; } localCallingMethods.Add(callingMethod); }
/// <summary> /// Gets the target method that need to be invoked for setting a field. /// Based on static analysis and later uses dynamic analysis for giving /// more priority to those methods that are identified through dynamic analysis also. /// </summary> /// <param name="ucls"></param> /// <param name="targetField"></param> /// <param name="declaringType"></param> /// <param name="targetMethods"></param> /// <returns></returns> private bool GetTargetMethod(UncoveredCodeLocationStore ucls, Field targetField, out SafeSet <Method> targetMethods) { targetMethods = new SafeSet <Method>(); int numfields = ucls.AllFields.Count; for (int count = 0; count < numfields; count++) { var field = ucls.AllFields[count]; //Get all write methods for this field SafeSet <Method> writeMethods = null; //Get the declaring type of the field. There are two possibilities of choosing //a declaring type: from the next field or the enclosing type TypeEx declaringType1 = null, declaringType2 = null; //If there is a parent field, the declaring type should //be upgraded to the type of the next field in the list, which could be //a sub-class of the actual declaring type if (count < numfields - 1) { var nextField = ucls.AllFields[count + 1]; declaringType1 = nextField.Type; } if (!MethodOrFieldAnalyzer.TryGetDeclaringTypeEx(this.host, field, out declaringType2)) { SafeDebug.AssumeNotNull(declaringType2, "declaringType"); } var declaringType = declaringType2; if (declaringType1 != null && declaringType1 != declaringType2) { declaringType = this.ChooseADeclaringType(declaringType1, declaringType2); } //Chosen declaringType should be a part of all field types stored //in UCLS. If not, there can be inheritance issues if (!ucls.AllFieldTypes.Contains(declaringType)) { //Find out the type to which declaringType is assignable and update it foreach (var tex in ucls.AllFieldTypes) { if (tex.IsAssignableTo(declaringType)) { declaringType = tex; break; } } } //For the first field, get all the methods that modify the field //using static analysis if (targetMethods.Count == 0) { //Try from static analysis store if (!this.psd.TryGetFilteredWriteMethods(field, declaringType, ucls.DesiredFieldModificationType, out writeMethods)) { this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "factoryguesser", "Failed to get write methods for the field " + field.FullName); return(false); } //Try from dynamic analysis //if (!this.pmd.FieldDictionary.TryGetValue(field.GlobalIndex, out fs)) targetMethods.AddRange(writeMethods); } else { //Get the callers of all methods in targetmethods SafeSet <Method> callerMethods = new SafeSet <Method>(); foreach (var tmw in targetMethods) { SafeSet <Method> callingMethods; //TODO: Performance improvements can be done here as we repeat the loops inside //the method for each method in targetMethods if (!this.psd.TryGetCallingMethodsInType(tmw, field, declaringType, out callingMethods)) { this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "factoryguesser", SafeString.Format("Failed to get calling methods of {0} through static and dynamic analysis", tmw)); continue; } //Filter the called methods based on field to avoid //unnecessary additional methods SafeSet <Method> subcallingMethods = this.psd.FilterCallingMethodsBasedOnField(tmw, field, callingMethods); if (callingMethods.Count > 0 && subcallingMethods.Count == 0) { this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "callingmethods", "Failed to filter calling methods based on field, adding all methods"); subcallingMethods.AddRange(callingMethods); } //Check in dynamic analysis portion //if (!this.pmd.MethodDictionary.TryGetValue(tmw.GlobalIndex, out mstore)) //{ //} //else // callingMethods = mstore.CallingMethods[declaringType]; callerMethods.AddRange(subcallingMethods); } //All caller methods in the parent type targetMethods = callerMethods; } //Our objective is to search for the methods that belong to our target field. //Stop traversal once the desired method is found if (field == targetField) { break; } } return(true); }
/// <summary> /// Includes filtering of the methods based on desired format /// </summary> /// <returns></returns> public bool TryGetFilteredWriteMethods(Field field, TypeEx declaringType, FieldModificationType desiredfmt, out SafeSet<Method> writeMethods) { //Check in the predefined store before proceeding if (PreDefinedMethodEffects.TryGetWriteMethods(this, field, desiredfmt, out writeMethods)) { SafeSet<Method> newWriteMethods = new SafeSet<Method>(); GetCallingMethods(field, declaringType, writeMethods, newWriteMethods); //Filter those methods whose actual types are abstract SafeSet<Method> returnMethods = new SafeSet<Method>(); foreach (Method m in writeMethods) { TypeEx declType; if (m.TryGetDeclaringType(out declType) && !declType.IsAbstract && !declType.IsInterface) { returnMethods.Add(m); } } foreach (Method m in newWriteMethods) { TypeEx declType; if (m.TryGetDeclaringType(out declType) && !declType.IsAbstract && !declType.IsInterface) { returnMethods.Add(m); } } writeMethods.Clear(); writeMethods.AddRange(returnMethods); return true; } //Identify those method that directly modify this field if (!TryGetWriteMethods(field, declaringType, out writeMethods)) return false; //C# supports properties. In that case, the property setter can also //be a viable method. add property setter and its callers also Property property; if (MethodOrFieldAnalyzer.TryGetPropertyModifyingField(this, declaringType, field, out property)) { if (property.IsVisible(VisibilityContext.Exported)) writeMethods.Add(property.Setter); var newWriteMethods = new SafeSet<Method>(); GetCallingMethods(field, declaringType, writeMethods, newWriteMethods); writeMethods.AddRange(newWriteMethods); } writeMethods = FilterWriteMethodsOfUpdateType(field, desiredfmt, writeMethods); return true; }
/// <summary> /// Compares current uncovered locations with the previous uncovered locations /// </summary> internal void AnalyzePreviousAndCurrentUncoveredLoc(string currPUTSignature, out HashSet <string> allGivenUpLocations, out HashSet <string> allCoveredLocations, out HashSet <string> newUncoveredLocations, out bool hasSomeCoveredLocation, out bool bAllAreNewLocations, out bool bNoneAreNewLocations) { hasSomeCoveredLocation = false; bAllAreNewLocations = true; bNoneAreNewLocations = true; var resolvedPrevLocations = new SafeSet <string>(); var bestFitnessValues = new SafeDictionary <string, int>(); //This dictionary is constructed since the FactorySuggestionStore is based //on declarting type not on the explorable type, which can be different allGivenUpLocations = new HashSet <string>(); allCoveredLocations = new HashSet <string>(); tempAllLocationStore = new SafeDictionary <string, PersistentUncoveredLocationStore>(); //All final suggested sequences of the current PUT var putspecificsequences = new List <MethodSignatureSequence>(); foreach (var fss in this.FactorySuggestionsDictionary.Values) { foreach (var codelockey in fss.locationStoreSpecificSequences.Keys) { var pucls = fss.locationStoreSpecificSequences[codelockey]; if (!pucls.IsDormat()) //Donot touch dormant persistent stores { tempAllLocationStore[codelockey] = pucls; } } foreach (var givenUpLocation in fss.PermanentFailedUncoveredLocations) { allGivenUpLocations.Add(givenUpLocation); } foreach (var coveredLocation in fss.SuccessfulCoveredLocations) { allCoveredLocations.Add(coveredLocation); } //MethodSignatureSequenceList mssl; //if (fss.FinalPUTSequences.TryGetValue(currPUTSignature, out mssl)) //{ // foreach (var seq in mssl.SequenceList) // { // if (!putspecificsequences.Contains(seq)) // putspecificsequences.Add(seq); // } //} } var failedLocations = new SafeSet <PersistentUncoveredLocationStore>(); //Traverse all uncovered locations foreach (var ucovLocList in this.UncoveredLocationDictionary.Values) { var locationStr = ucovLocList.Location.ToString(); var key = UncoveredCodeLocationStore.GetKey(ucovLocList.Location.ToString(), ucovLocList.ExplorableType.ToString(), ucovLocList.TermIndex); //Check whether there are any defect detecting sequences. If yes promote them //in the associated factory store foreach (var ucls in ucovLocList.StoreList) { if (ucls.IsADefectDetectingSequence) { var fss = this.FactorySuggestionsDictionary[ucls.ExplorableType.ToString()]; SafeDebug.AssumeNotNull(fss, "fss cannot be null"); fss.AddToDefectDetectingSequences(ucls.MethodCallSequence); } } if (allGivenUpLocations.Contains(key)) { //This location has been earlier given up. No need to deal with this resolvedPrevLocations.Add(key); this.Log.LogMessage(WikiTopics.MissingWikiTopic, "Location " + locationStr + " is ignored since it was already given up earlier!!!"); continue; } if (allCoveredLocations.Contains(key)) { //This location has been covered earlier. Ideally this case should not happen //resolvedPrevLocations.Add(key); this.Log.LogMessage(WikiTopics.MissingWikiTopic, "Location " + locationStr + " is previously covered, but can be reported since the caller could be different."); bAllAreNewLocations = false; //continue; } //Get the associated factory suggestion store if (tempAllLocationStore.ContainsKey(key)) { bAllAreNewLocations = false; var pucls = tempAllLocationStore[key]; resolvedPrevLocations.Add(key); //For some formats such as TRUE_SET, we do not need the fitness measure //If they are not covered in one attempt, they won't be covered any time if (ucovLocList.StoreList.Count > 0) { var fmt = ucovLocList.StoreList[0].DesiredFieldModificationType; if (!this.IsFitnessRequired(fmt)) { pucls.NumberOfUnsuccessfulAttempts = PexMeConstants.MAX_UNSUCCESSFUL_ATTEMPTS + 1; } } //Reached the threshold of number of attempts. So deleting this uncovered location forever if (pucls.NumberOfUnsuccessfulAttempts + 1 <= PexMeConstants.MAX_UNSUCCESSFUL_ATTEMPTS) { //Handle according to fitness value and drop the other methods that //acutally did not help increase the fitness value this.RemoveSuggestionsWithLowFitness(ucovLocList, tempAllLocationStore[key], putspecificsequences); this.Log.LogMessage(WikiTopics.MissingWikiTopic, "Location " + locationStr + " is resolved and is still uncovered in the new run " + "(fitness: " + pucls.Fitnessvalue + "), (Attempt: " + pucls.NumberOfUnsuccessfulAttempts + ")"); } else { this.Log.LogMessage(WikiTopics.MissingWikiTopic, "Location " + locationStr + " is resolved and but not making any process!!! Will be deleted forever"); //This pucls data will be deleted forever since it reached its max attempts without any progress failedLocations.Add(pucls); } } } //New locations that added to the factory suggestion store newUncoveredLocations = new HashSet <string>(); foreach (var ucovLocList in this.UncoveredLocationDictionary.Values) { var key = UncoveredCodeLocationStore.GetKey(ucovLocList.Location.ToString(), ucovLocList.ExplorableType.ToString(), ucovLocList.TermIndex); if (!resolvedPrevLocations.Contains(key)) { newUncoveredLocations.Add(key); this.Log.LogMessage(WikiTopics.MissingWikiTopic, "Location " + ucovLocList.Location.ToString() + " is newly added in the new run"); bNoneAreNewLocations = false; } } //Unresolved locations from the previous run. This means that these sequences //are either already covered or not covered due to some new exception... var unresolvedPrevLocations = new SafeSet <PersistentUncoveredLocationStore>(); var alreadyCoveredLocations = new SafeSet <PersistentUncoveredLocationStore>(); foreach (var fss in this.FactorySuggestionsDictionary.Values) { var allRemovedPUCLS = new List <PersistentUncoveredLocationStore>(); //Delete all failed locations if the suggested methods for this //failed location are all actually already explored. If not, place //them in pending status. Usually this case happens, if covering //the same location within the method is required by another location foreach (var pucls in failedLocations) { var key = UncoveredCodeLocationStore.GetKey(pucls.CodeLocation.ToString(), pucls.ExplorableType.ToString(), pucls.TermIndex); fss.RemoveUncoveredLocationStore(pucls, false, this); allRemovedPUCLS.Add(pucls); } foreach (var codelockey in fss.locationStoreSpecificSequences.Keys) { var tpucls = fss.locationStoreSpecificSequences[codelockey]; if (tpucls.IsDormat()) { continue; } if (allGivenUpLocations.Contains(codelockey)) { bAllAreNewLocations = false; unresolvedPrevLocations.Add(tpucls); this.Log.LogWarning(WikiTopics.MissingWikiTopic, "UncoveredLocation", "Location " + codelockey + " was already given up. Should not be reported again!!! Anyways, Deleting this location forever"); continue; } if (!resolvedPrevLocations.Contains(codelockey)) { //Check whether this location is covered based on the coverage if (tpucls.AlreadyCovered || this.IsPrevUncoveredLocationCovered(tpucls)) { alreadyCoveredLocations.Add(tpucls); this.Log.LogMessage(WikiTopics.MissingWikiTopic, "Location " + codelockey + " is successfully covered in the new run"); hasSomeCoveredLocation = true; } else { bAllAreNewLocations = false; unresolvedPrevLocations.Add(tpucls); this.Log.LogWarning(WikiTopics.MissingWikiTopic, "UncoveredLocation", "Location " + codelockey + " from the previous run is not found in the new run!!! Deleting this location forever"); } } } //Delete all unresolved locations as they won't be required anymore!!! foreach (var pucls in unresolvedPrevLocations) { fss.RemoveUncoveredLocationStore(pucls, false, this); allRemovedPUCLS.Add(pucls); } //Handle all removed PUCLS foreach (var pucls in allRemovedPUCLS) { var key = UncoveredCodeLocationStore.GetKey(pucls.CodeLocation, pucls.ExplorableType, pucls.TermIndex); fss.PermanentFailedUncoveredLocations.Add(key); if (!fss.TemporaryFailedUncoveredLocations.ContainsKey(key)) { //Are there any active uncovered locations if (this.AnyActiveUncoveredLocations()) { fss.TemporaryFailedUncoveredLocations[key] = 1; } else { fss.TemporaryFailedUncoveredLocations[key] = PexMeConstants.MAX_UNCOVEREDLOC_ATTEMPTS; } } } //Delete all the information regarding covered locations and upgrade their specific factory methods foreach (var pucls in alreadyCoveredLocations) { fss.RemoveUncoveredLocationStore(pucls, true, this); } alreadyCoveredLocations.Clear(); } }
/// <summary> /// Gets the set of write methods associated with a field in the given type /// </summary> /// <param name="field"></param> /// <returns></returns> public bool TryGetWriteMethods(Field field, TypeEx declaringType, out SafeSet<Method> writeMethods) { SafeDebug.AssumeNotNull(field, "field"); SafeDebug.AssumeNotNull(declaringType, "declaringType"); //Declaring type should include defintinion if (declaringType == null || declaringType.Definition == null) { this.Log.LogWarning(WikiTopics.MissingWikiTopic, "WriteMethods", "Missing definition for the declaring type " + declaringType.FullName); writeMethods = null; return false; } FieldStore fs; if (this.FieldDictionary.TryGetValue(field, out fs)) { if (fs.WriteMethods.TryGetValue(declaringType, out writeMethods)) return true; else { writeMethods = new SafeSet<Method>(); fs.WriteMethods[declaringType] = writeMethods; } } else { fs = new FieldStore(); fs.FieldName = field; writeMethods = new SafeSet<Method>(); fs.WriteMethods[declaringType] = writeMethods; this.FieldDictionary[field] = fs; } foreach (MethodDefinition instanceMethod in declaringType.Definition.DeclaredInstanceMethods) { //Ignore abstract methods if (instanceMethod.IsAbstract) continue; //If the DISABLE_CALLING_METHODS_WITHIN_CLASS is set to true, then private methods need not be considered //since they will be filtered out. if (PexMeConstants.DISABLE_CALLING_METHODS_WITHIN_CLASS && instanceMethod.DeclaredVisibility == Visibility.Private) continue; Method method = instanceMethod.Instantiate(declaringType.GenericTypeArguments, MethodOrFieldAnalyzer.GetGenericMethodParameters(this, instanceMethod)); MethodEffects me; if (!MethodOrFieldAnalyzer.TryComputeMethodEffects(this, declaringType, method, null, out me)) { this.Log.LogWarning(WikiTopics.MissingWikiTopic, "methodeffects", "Failed to get the method effects for method " + method); continue; } if (me.WrittenInstanceFields.Contains(field.ShortName)) { writeMethods.Add(method); } FieldModificationType fmt; if (me.ModificationTypeDictionary.TryGetValue(field.ShortName, out fmt)) { fs.ModificationTypeDictionary[method] = fmt; } } //Check whether there are any private methods in calling methods. //If yes, replace them with their callers. if (!PexMeConstants.DISABLE_CALLING_METHODS_WITHIN_CLASS) { var newWriteMethods = new SafeSet<Method>(); GetCallingMethods(field, declaringType, writeMethods, newWriteMethods); writeMethods.Clear(); writeMethods.AddRange(newWriteMethods); } TypeEx baseType = declaringType.BaseType; if (baseType != null && baseType.FullName != "System.Object") { SafeSet<Method> innerWriteMethods; this.TryGetWriteMethods(field, baseType, out innerWriteMethods); if (innerWriteMethods != null) writeMethods.AddRange(innerWriteMethods); } return true; }
public Fact() { _tupleComparer = TupleEqualityComparer <T> .Default; _data = new SafeSet <Tuple <T> >(_tupleComparer); }
internal SafeSet<Method> FilterCallingMethodsBasedOnField(Method tmw, Field field, SafeSet<Method> callingMethods) { SafeSet<Method> filteredMethods = new SafeSet<Method>(); foreach (var callingm in callingMethods) { //Filter the calling method based on the field MethodBodyEx body; if (!callingm.TryGetBody(out body) || !body.HasInstructions) { continue; } int offset = 0; Instruction instruction; bool bContinueWithNextMethod = false; Field lastAccessedField = null; while (body.TryGetInstruction(offset, out instruction) && !bContinueWithNextMethod) { SafeDebug.AssumeNotNull(instruction, "instruction"); OpCode opCode = instruction.OpCode; if (opCode == OpCodes.Ldfld || opCode == OpCodes.Ldflda) { SafeDebug.Assume(opCode.OperandType == OperandType.InlineField, "opCode.OperandType == OperandType.InlineField"); lastAccessedField = instruction.Field; } else if (opCode == OpCodes.Call || opCode == OpCodes.Callvirt) { SafeDebug.Assume(opCode.OperandType == OperandType.InlineMethod, "opCode.OperandType == OperandType.InlineMethod"); Method methodinner = instruction.Method; if (methodinner == tmw && field == lastAccessedField) { filteredMethods.Add(callingm); bContinueWithNextMethod = true; } lastAccessedField = null; } offset = instruction.NextOffset; } } return filteredMethods; }
/// <summary> /// Helps guess factory methods for each uncovered condition /// </summary> private void GuessFactorymethods(out SafeSet<Method> allNewSuggestedPUTs, string currPUTSignature, out bool bHasSomeCoveredLocation, out bool bAllAreNewLocations, out bool bNoneAreNewLocations) { PexMeFactoryGuesser pfg = new PexMeFactoryGuesser(this.host); HashSet<string> allGivenUpLocations, allCoveredLocations, newUnCoveredLocations; //Analyze the current uncovered and previously uncovered locations this.pmd.AnalyzePreviousAndCurrentUncoveredLoc(currPUTSignature, out allGivenUpLocations, out allCoveredLocations, out newUnCoveredLocations, out bHasSomeCoveredLocation, out bAllAreNewLocations, out bNoneAreNewLocations); allNewSuggestedPUTs = new SafeSet<Method>(); //Iterate through each uncovered location foreach (var ucovLocList in pmd.UncoveredLocationDictionary.Values) { //TODO: Classify the uncovered locations into different groups //Because, it can happen that a single code location can have multiple terms which //cannot be merged together. if (ucovLocList.StoreList.Count == 0) continue; //Check whether this location is earlier attempted and is failed. no //need to try this location again FactorySuggestionStore fss = null; string key = null; if (this.pmd.FactorySuggestionsDictionary.TryGetValue(ucovLocList.ExplorableType, out fss)) { key = UncoveredCodeLocationStore.GetKey(ucovLocList.Location.ToString(), ucovLocList.ExplorableType, ucovLocList.TermIndex); //A fix to keep track of uncovered locations in system libraries if (TargetBranchAnalyzer.IsUncoveredLocationInSystemLib(ucovLocList.Location)) { fss.UncoveredSystemLibLocations.Add(key); } if (allGivenUpLocations.Contains(key)) continue; //Already covered locations can be reported again due to different PUTs or different call sites //if (allCoveredLocations.Contains(key)) // continue; if (fss.PermanentFailedUncoveredLocations.Contains(key)) continue; //if (fss.SuccessfulCoveredLocations.Contains(key)) // continue; } //A single element of ucovLoc is sufficient here var ucovLoc = ucovLocList.StoreList[0]; if (!pfg.TryInferFactoryMethod(ucovLoc, out ucovLoc.SuggestedMethodSetforFactory)) { this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "postprocessor", "Failed to suggest factory methods for uncovered location " + ucovLoc.ToString() + " -> Adding to permanent failed locations"); if (fss != null && key != null) fss.PermanentFailedUncoveredLocations.Add(key); continue; } //If a suggested method is not yet explored, add it to all new suggested method if (ucovLoc.SuggestedMethodSetforFactory != null) { foreach (var suggestedm in ucovLoc.SuggestedMethodSetforFactory) { if (suggestedm.IsConstructor) continue; //Check if this is ever explored by this process by getting associated PUT Method pexmethod; bool bretval = PUTGenerator.PUTGenerator.TryRetrievePUT(this.pmd, this.currAssembly, suggestedm, out pexmethod); if (!bretval) { //The suggested method is out of scope of current library and //no need to explore it explicitly continue; } //Ignore self suggestions if (pexmethod == this.pmd.CurrentPUTMethod) continue; var signature = MethodOrFieldAnalyzer.GetMethodSignature(pexmethod); if (this.pmd.AllExploredMethods.Contains(signature)) continue; if (this.pmd.PendingExplorationMethods.Contains(signature)) { this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "Nested PUTs", "Ignoring the nested PUT due to cycle detection " + signature); continue; } allNewSuggestedPUTs.Add(pexmethod); } } } }
/// <summary> /// Adds a monitored field to the database. Updates two kinds of hashmaps /// a. Field to Method mapper, which gives what the methods modifying a given field /// b. Method to Field mapper, which gives what fields are modified by each method (later used to identify a minimized set of methods) /// </summary> /// <param name="tm"></param> /// <param name="method"></param> /// <param name="f"></param> /// <param name="indices"></param> /// <param name="fieldValue"></param> public void AddMonitoredField(TermManager tm, Method method, Field f, Term[] indices, Term fieldValue, Term initialValue) { string arrayIndex = ""; using (PexMeTermRewriter pexmeRewriter = new PexMeTermRewriter(tm)) { fieldValue = pexmeRewriter.VisitTerm(default(TVoid), fieldValue); //update the field value to accomodate array-type field //if (indices.Length == 0) //not an array-type field if (indices.Length == 1) //is an array-type field { arrayIndex = " at index of " + indices[0].UniqueIndex.ToString(); } if(initialValue != null) initialValue = pexmeRewriter.VisitTerm(default(TVoid), initialValue); } //Updating the method store MethodStore ms; if(!methodDic.TryGetValue(method, out ms)) { ms = new MethodStore(); ms.methodName = method; methodDic[method] = ms; } ms.WriteFields.Add(f); //TODO: Gather information of read fields //Updating the field store FieldStore fs; if (!fieldDic.TryGetValue(f, out fs)) { fs = new FieldStore(); fs.FieldName = f; fieldDic[f] = fs; } TypeEx declaringType; if (!method.TryGetDeclaringType(out declaringType)) { this.Log.LogError(WikiTopics.MissingWikiTopic, "monitorfield", "Failed to get the declaring type for the method " + method.FullName); return; } SafeSet<Method> writeMethods; if (!fs.WriteMethods.TryGetValue(declaringType, out writeMethods)) { writeMethods = new SafeSet<Method>(); fs.WriteMethods[declaringType] = writeMethods; } writeMethods.Add(method); var sb = new SafeStringBuilder(); var swriter = new TermSExpWriter(tm, new SafeStringWriter(sb), true, false); swriter.Write(fieldValue); sb.Append(arrayIndex); int value; if (tm.TryGetI4Constant(fieldValue, out value)) { int initialval; if (initialValue != null) tm.TryGetI4Constant(initialValue, out initialval); else initialval = 0; sb.Append(" constant value: " + value); if (f.Type.ToString() != "System.Boolean") { if (value < initialval) fs.ModificationTypeDictionary[method] = FieldModificationType.DECREMENT; else if (value > initialval) { fs.ModificationTypeDictionary[method] = FieldModificationType.INCREMENT; if (value == initialval + 1) fs.PreciseModificationTypeDictionary[method] = FieldModificationType.INCREMENT_ONE; } else fs.ModificationTypeDictionary[method] = FieldModificationType.UNKNOWN; } else { if (value == 0) fs.ModificationTypeDictionary[method] = FieldModificationType.FALSE_SET; else fs.ModificationTypeDictionary[method] = FieldModificationType.TRUE_SET; } } else if (tm.IsDefaultValue(fieldValue)) { if (initialValue != null && !tm.IsDefaultValue(initialValue)) fs.ModificationTypeDictionary[method] = FieldModificationType.NULL_SET; else fs.ModificationTypeDictionary[method] = FieldModificationType.UNKNOWN; sb.Append(" null reference "); } else { if (initialValue == null) fs.ModificationTypeDictionary[method] = FieldModificationType.NON_NULL_SET; else fs.ModificationTypeDictionary[method] = FieldModificationType.UNKNOWN; sb.Append(" not-null reference "); } fs.FieldValues.Add(sb.ToString()); }
public static TypeEx AddFieldToMethodEffects(IPexComponent host, TypeEx declaringType, SafeSet<string> res, SafeSet<string> directSetFields, SafeDictionary<string, FieldModificationType> modificationTypeDic, OpCode prevOpcode, Field field, TypeEx fieldType) { SafeDebug.AssumeNotNull(field, "field"); SafeDebug.Assume(!field.IsStatic, "!field.IsStatic"); TypeEx fieldDeclaringType; //The following check ensures that the field belongs to this class //or its base classes if (field.TryGetDeclaringType(out fieldDeclaringType) && declaringType.IsAssignableTo(fieldDeclaringType)) { res.Add(field.ShortName); FieldModificationType fmt = FieldModificationType.UNKNOWN; if (fieldType == SystemTypes.Int32 || fieldType == SystemTypes.Int64 || fieldType == SystemTypes.Int16) { if (prevOpcode == OpCodes.Add) fmt = FieldModificationType.INCREMENT; else if (prevOpcode == OpCodes.Sub) fmt = FieldModificationType.DECREMENT; else if (prevOpcode == OpCodes.Call || prevOpcode == OpCodes.Calli || prevOpcode == OpCodes.Callvirt) fmt = FieldModificationType.METHOD_CALL; else host.Log.LogWarning(WikiTopics.MissingWikiTopic, "fieldmodificationtype", "Encountered unknown modification type for integer type " + prevOpcode); } else { if (field.Type.IsReferenceType) { if (prevOpcode == OpCodes.Ldnull) fmt = FieldModificationType.NULL_SET; else if (prevOpcode == OpCodes.Newarr || prevOpcode == OpCodes.Newobj) fmt = FieldModificationType.NON_NULL_SET; else if (LdArgOpCodes.Contains(prevOpcode)) fmt = FieldModificationType.NON_NULL_SET; else { fmt = FieldModificationType.METHOD_CALL; //A method call is invoked on this field, which updates this field } } else if (fieldType == SystemTypes.Bool) { if (prevOpcode == OpCodes.Ldc_I4_0) fmt = FieldModificationType.FALSE_SET; else if (prevOpcode == OpCodes.Ldc_I4_1) fmt = FieldModificationType.TRUE_SET; else host.Log.LogWarning(WikiTopics.MissingWikiTopic, "fieldmodificationtype", "Encountered unknown modification type for boolean type " + prevOpcode); } } //Store the value of fmt. Sometimes, the same field //can be modified in different ways within the method, for example //setting a boolean field to both true or false. In that case, the modification //type is left as unknown FieldModificationType prevFMT; if (modificationTypeDic.TryGetValue(field.ShortName, out prevFMT)) { //There is some entry for this field if (prevFMT != FieldModificationType.UNKNOWN && prevFMT != fmt) { modificationTypeDic[field.ShortName] = FieldModificationType.UNKNOWN; } } else { modificationTypeDic[field.ShortName] = fmt; } //A heuristic based approach for aliasing analysis for checking whether the field is directly //assigned any parameters if (LdArgOpCodes.Contains(prevOpcode)) directSetFields.Add(field.ShortName); } return fieldDeclaringType; }
/// <summary> /// Adds a monitored field to the database. Updates two kinds of hashmaps /// a. Field to Method mapper, which gives what the methods modifying a given field /// b. Method to Field mapper, which gives what fields are modified by each method (later used to identify a minimized set of methods) /// </summary> /// <param name="tm"></param> /// <param name="method"></param> /// <param name="f"></param> /// <param name="indices"></param> /// <param name="fieldValue"></param> public void AddMonitoredField(TermManager tm, Method method, Field f, Term[] indices, Term fieldValue, Term initialValue) { string arrayIndex = ""; using (PexMeTermRewriter pexmeRewriter = new PexMeTermRewriter(tm)) { fieldValue = pexmeRewriter.VisitTerm(default(TVoid), fieldValue); //update the field value to accomodate array-type field //if (indices.Length == 0) //not an array-type field if (indices.Length == 1) //is an array-type field { arrayIndex = " at index of " + indices[0].UniqueIndex.ToString(); } if (initialValue != null) { initialValue = pexmeRewriter.VisitTerm(default(TVoid), initialValue); } } //Updating the method store MethodStore ms; if (!methodDic.TryGetValue(method, out ms)) { ms = new MethodStore(); ms.methodName = method; methodDic[method] = ms; } ms.WriteFields.Add(f); //TODO: Gather information of read fields //Updating the field store FieldStore fs; if (!fieldDic.TryGetValue(f, out fs)) { fs = new FieldStore(); fs.FieldName = f; fieldDic[f] = fs; } TypeEx declaringType; if (!method.TryGetDeclaringType(out declaringType)) { this.Log.LogError(WikiTopics.MissingWikiTopic, "monitorfield", "Failed to get the declaring type for the method " + method.FullName); return; } SafeSet <Method> writeMethods; if (!fs.WriteMethods.TryGetValue(declaringType, out writeMethods)) { writeMethods = new SafeSet <Method>(); fs.WriteMethods[declaringType] = writeMethods; } writeMethods.Add(method); var sb = new SafeStringBuilder(); var swriter = new TermSExpWriter(tm, new SafeStringWriter(sb), true, false); swriter.Write(fieldValue); sb.Append(arrayIndex); int value; if (tm.TryGetI4Constant(fieldValue, out value)) { int initialval; if (initialValue != null) { tm.TryGetI4Constant(initialValue, out initialval); } else { initialval = 0; } sb.Append(" constant value: " + value); if (f.Type.ToString() != "System.Boolean") { if (value < initialval) { fs.ModificationTypeDictionary[method] = FieldModificationType.DECREMENT; } else if (value > initialval) { fs.ModificationTypeDictionary[method] = FieldModificationType.INCREMENT; if (value == initialval + 1) { fs.PreciseModificationTypeDictionary[method] = FieldModificationType.INCREMENT_ONE; } } else { fs.ModificationTypeDictionary[method] = FieldModificationType.UNKNOWN; } } else { if (value == 0) { fs.ModificationTypeDictionary[method] = FieldModificationType.FALSE_SET; } else { fs.ModificationTypeDictionary[method] = FieldModificationType.TRUE_SET; } } } else if (tm.IsDefaultValue(fieldValue)) { if (initialValue != null && !tm.IsDefaultValue(initialValue)) { fs.ModificationTypeDictionary[method] = FieldModificationType.NULL_SET; } else { fs.ModificationTypeDictionary[method] = FieldModificationType.UNKNOWN; } sb.Append(" null reference "); } else { if (initialValue == null) { fs.ModificationTypeDictionary[method] = FieldModificationType.NON_NULL_SET; } else { fs.ModificationTypeDictionary[method] = FieldModificationType.UNKNOWN; } sb.Append(" not-null reference "); } fs.FieldValues.Add(sb.ToString()); }
/// <summary> /// Populates all pair-wise combinations of defs and uses identified through static analysis /// </summary> public void PopulateDUCoverTable() { DUCoverStore dcs = DUCoverStore.GetInstance(); SafeSet<FieldDefUseStore> allDefs = new SafeSet<FieldDefUseStore>(); allDefs.AddRange(this.DefDic.Keys); allDefs.AddRange(this.DefOrUseSet); SafeSet<FieldDefUseStore> allUses = new SafeSet<FieldDefUseStore>(); allUses.AddRange(this.UseDic.Keys); allUses.AddRange(this.DefOrUseSet); int numInfeasible = 0; //Compute pair-wise combinations foreach (var defEntry in allDefs) { foreach (var useEntry in allUses) { //Ignore the trivial entries that involve just a combination of setter and getter methods if (defEntry.Method.ShortName.StartsWith("set_") && useEntry.Method.ShortName.StartsWith("get_")) continue; if (!this.IsFeasibleDUCoverEntry(dcs, defEntry, useEntry)) { numInfeasible++; continue; } DUCoverStoreEntry dcse = new DUCoverStoreEntry(this.fd, defEntry.Method, defEntry.Offset, useEntry.Method, useEntry.Offset); if (defEntry.UnknownSideEffectMethod != null) { dcse.Def_UnknownSideEffectMethod = defEntry.UnknownSideEffectMethod; dcse.DefUnsure = true; } if (useEntry.UnknownSideEffectMethod != null) { dcse.Use_UnknownSideEffectMethod = useEntry.UnknownSideEffectMethod; dcse.UseUnsure = true; } if(!this.duCoverageTable.ContainsKey(dcse)) this.duCoverageTable[dcse] = 0; } } //Clear all the cached entries. this.feasibilityDicCache.Clear(); logger.Debug("Detected infeasible du-pairs for field " + this.fd.FullName + "(" + numInfeasible + ")"); }
/// <summary> /// Helps guess factory methods for each uncovered condition /// </summary> private void GuessFactorymethods(out SafeSet <Method> allNewSuggestedPUTs, string currPUTSignature, out bool bHasSomeCoveredLocation, out bool bAllAreNewLocations, out bool bNoneAreNewLocations) { PexMeFactoryGuesser pfg = new PexMeFactoryGuesser(this.host); HashSet <string> allGivenUpLocations, allCoveredLocations, newUnCoveredLocations; //Analyze the current uncovered and previously uncovered locations this.pmd.AnalyzePreviousAndCurrentUncoveredLoc(currPUTSignature, out allGivenUpLocations, out allCoveredLocations, out newUnCoveredLocations, out bHasSomeCoveredLocation, out bAllAreNewLocations, out bNoneAreNewLocations); allNewSuggestedPUTs = new SafeSet <Method>(); //Iterate through each uncovered location foreach (var ucovLocList in pmd.UncoveredLocationDictionary.Values) { //TODO: Classify the uncovered locations into different groups //Because, it can happen that a single code location can have multiple terms which //cannot be merged together. if (ucovLocList.StoreList.Count == 0) { continue; } //Check whether this location is earlier attempted and is failed. no //need to try this location again FactorySuggestionStore fss = null; string key = null; if (this.pmd.FactorySuggestionsDictionary.TryGetValue(ucovLocList.ExplorableType, out fss)) { key = UncoveredCodeLocationStore.GetKey(ucovLocList.Location.ToString(), ucovLocList.ExplorableType, ucovLocList.TermIndex); //A fix to keep track of uncovered locations in system libraries if (TargetBranchAnalyzer.IsUncoveredLocationInSystemLib(ucovLocList.Location)) { fss.UncoveredSystemLibLocations.Add(key); } if (allGivenUpLocations.Contains(key)) { continue; } //Already covered locations can be reported again due to different PUTs or different call sites //if (allCoveredLocations.Contains(key)) // continue; if (fss.PermanentFailedUncoveredLocations.Contains(key)) { continue; } //if (fss.SuccessfulCoveredLocations.Contains(key)) // continue; } //A single element of ucovLoc is sufficient here var ucovLoc = ucovLocList.StoreList[0]; if (!pfg.TryInferFactoryMethod(ucovLoc, out ucovLoc.SuggestedMethodSetforFactory)) { this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "postprocessor", "Failed to suggest factory methods for uncovered location " + ucovLoc.ToString() + " -> Adding to permanent failed locations"); if (fss != null && key != null) { fss.PermanentFailedUncoveredLocations.Add(key); } continue; } //If a suggested method is not yet explored, add it to all new suggested method if (ucovLoc.SuggestedMethodSetforFactory != null) { foreach (var suggestedm in ucovLoc.SuggestedMethodSetforFactory) { if (suggestedm.IsConstructor) { continue; } //Check if this is ever explored by this process by getting associated PUT Method pexmethod; bool bretval = PUTGenerator.PUTGenerator.TryRetrievePUT(this.pmd, this.currAssembly, suggestedm, out pexmethod); if (!bretval) { //The suggested method is out of scope of current library and //no need to explore it explicitly continue; } //Ignore self suggestions if (pexmethod == this.pmd.CurrentPUTMethod) { continue; } var signature = MethodOrFieldAnalyzer.GetMethodSignature(pexmethod); if (this.pmd.AllExploredMethods.Contains(signature)) { continue; } if (this.pmd.PendingExplorationMethods.Contains(signature)) { this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "Nested PUTs", "Ignoring the nested PUT due to cycle detection " + signature); continue; } allNewSuggestedPUTs.Add(pexmethod); } } } }
public static TypeEx AddFieldToMethodEffects(IPexComponent host, TypeEx declaringType, SafeSet <string> res, SafeSet <string> directSetFields, SafeDictionary <string, FieldModificationType> modificationTypeDic, OpCode prevOpcode, Field field, TypeEx fieldType) { SafeDebug.AssumeNotNull(field, "field"); SafeDebug.Assume(!field.IsStatic, "!field.IsStatic"); TypeEx fieldDeclaringType; //The following check ensures that the field belongs to this class //or its base classes if (field.TryGetDeclaringType(out fieldDeclaringType) && declaringType.IsAssignableTo(fieldDeclaringType)) { res.Add(field.ShortName); FieldModificationType fmt = FieldModificationType.UNKNOWN; if (fieldType == SystemTypes.Int32 || fieldType == SystemTypes.Int64 || fieldType == SystemTypes.Int16) { if (prevOpcode == OpCodes.Add) { fmt = FieldModificationType.INCREMENT; } else if (prevOpcode == OpCodes.Sub) { fmt = FieldModificationType.DECREMENT; } else if (prevOpcode == OpCodes.Call || prevOpcode == OpCodes.Calli || prevOpcode == OpCodes.Callvirt) { fmt = FieldModificationType.METHOD_CALL; } else { host.Log.LogWarning(WikiTopics.MissingWikiTopic, "fieldmodificationtype", "Encountered unknown modification type for integer type " + prevOpcode); } } else { if (field.Type.IsReferenceType) { if (prevOpcode == OpCodes.Ldnull) { fmt = FieldModificationType.NULL_SET; } else if (prevOpcode == OpCodes.Newarr || prevOpcode == OpCodes.Newobj) { fmt = FieldModificationType.NON_NULL_SET; } else if (LdArgOpCodes.Contains(prevOpcode)) { fmt = FieldModificationType.NON_NULL_SET; } else { fmt = FieldModificationType.METHOD_CALL; //A method call is invoked on this field, which updates this field } } else if (fieldType == SystemTypes.Bool) { if (prevOpcode == OpCodes.Ldc_I4_0) { fmt = FieldModificationType.FALSE_SET; } else if (prevOpcode == OpCodes.Ldc_I4_1) { fmt = FieldModificationType.TRUE_SET; } else { host.Log.LogWarning(WikiTopics.MissingWikiTopic, "fieldmodificationtype", "Encountered unknown modification type for boolean type " + prevOpcode); } } } //Store the value of fmt. Sometimes, the same field //can be modified in different ways within the method, for example //setting a boolean field to both true or false. In that case, the modification //type is left as unknown FieldModificationType prevFMT; if (modificationTypeDic.TryGetValue(field.ShortName, out prevFMT)) { //There is some entry for this field if (prevFMT != FieldModificationType.UNKNOWN && prevFMT != fmt) { modificationTypeDic[field.ShortName] = FieldModificationType.UNKNOWN; } } else { modificationTypeDic[field.ShortName] = fmt; } //A heuristic based approach for aliasing analysis for checking whether the field is directly //assigned any parameters if (LdArgOpCodes.Contains(prevOpcode)) { directSetFields.Add(field.ShortName); } } return(fieldDeclaringType); }
/// <summary> /// Removes if there are any infeasible definitions /// </summary> private void RemoveInfeasibleDefs(DUCoverStore dcs) { //There are either zero or one definitions if (this.defDic.Count <= 1) return; SafeSet<FieldDefUseStore> infeasibleDefs = new SafeSet<FieldDefUseStore>(); foreach (var fdef in this.defDic.Keys) { var otherFDefOffsets = this.GetOtherDefOffsetsInMethod(fdef.Method, fdef); if (otherFDefOffsets.Count == 0) continue; if (HasRedefinition(dcs, fdef, otherFDefOffsets)) infeasibleDefs.Add(fdef); } this.defDic.RemoveRange(infeasibleDefs); }