/// <summary> /// Gets a persistent location store version of an uncovered location store /// </summary> /// <param name="ucls"></param> /// <returns></returns> public PersistentUncoveredLocationStore GetPersistentLocationstore(UncoveredCodeLocationStore ucls, out bool bNewlyCreated) { PersistentUncoveredLocationStore pucls; bNewlyCreated = false; var key = UncoveredCodeLocationStore.GetKey(ucls.Location.ToString(), ucls.ExplorableType.ToString(), ucls.TermIndex); if (!locationStoreSpecificSequences.TryGetValue(key, out pucls)) { pucls = new PersistentUncoveredLocationStore(ucls.Location, ucls.ExplorableType, ucls.TermIndex, ucls.Fitnessvalue, this); pucls.CodeLocation = ucls.Location.ToString(); locationStoreSpecificSequences[key] = pucls; bNewlyCreated = true; } return(pucls); }
/// <summary> /// Removes the uncovered location store. Mainly keeps the sequence /// that helped to cover the target location and drops all others /// </summary> /// <param name="pucls"></param> /// <param name="successful">Helps to distinguish between a removal during success and failure</param> internal void RemoveUncoveredLocationStore(PersistentUncoveredLocationStore pucls, bool successful, PexMeDynamicDatabase pmd) { var key = UncoveredCodeLocationStore.GetKey(pucls.CodeLocation, pucls.ExplorableType, pucls.TermIndex); this.locationStoreSpecificSequences.Remove(key); if (!successful) { return; } this.SuccessfulCoveredLocations.Add(key); this.PermanentFailedUncoveredLocations.Remove(key); this.TemporaryFailedUncoveredLocations.Remove(key); this.UncoveredSystemLibLocations.Remove(key); //Get the method associated with the current exploring PUT string methodcallname = PexMeConstants.DEFAULT_FINAL_SUGGESTION_STORE; Method assocMethod; if (PUTGenerator.PUTGenerator.TryRetrieveMethodCall(pmd.CurrentPUTMethod, out assocMethod)) methodcallname = MethodOrFieldAnalyzer.GetMethodSignature(assocMethod); //Get PUT independent sequence list MethodSignatureSequenceList putIndependentMssl; if (!this.FinalSuggestedMethodSequences.TryGetValue(methodcallname, out putIndependentMssl)) { putIndependentMssl = new MethodSignatureSequenceList(); this.FinalSuggestedMethodSequences.Add(methodcallname, putIndependentMssl); } //Also update the PUT specific sequences. These gets cleared once a //PUT is completely explored. var putsignature = MethodOrFieldAnalyzer.GetMethodSignature(pmd.CurrentPUTMethod); MethodSignatureSequenceList putSpecificMssl; if (!this.FinalPUTSequences.TryGetValue(putsignature, out putSpecificMssl)) { putSpecificMssl = new MethodSignatureSequenceList(); this.FinalPUTSequences.Add(putsignature, putSpecificMssl); } //Any Persistent Uncovered location store that is successfully //covered gets a hit sequence SafeDebug.AssumeNotNull(pucls.HitSequence, "pucls.HitSequence"); MethodSignatureSequence matchingseq; if (!FactorySuggestionStore.TryGetMatchingSequence(pucls.HitSequence, pucls.SuggestedMethodSequences, out matchingseq)) { //Failed to retrieve the hit sequence. However, a heuristic //can be used where there is only one suggested sequence if (pucls.SuggestedMethodSequences.Count == 1) { matchingseq = pucls.SuggestedMethodSequences[0]; putIndependentMssl.Add(matchingseq); putSpecificMssl.Add(matchingseq); } else { pmd.Log.LogWarning(WikiTopics.MissingWikiTopic, "SequenceMatch", "Failed to retrieve a matching sequence for a hit sequence, adding complete hit sequence " + pucls.HitSequence); var hitSubSequence = new MethodSignatureSequence(); foreach (var mhit in pucls.HitSequence.Sequence) { if (mhit.Contains("..ctor(")) //Don't add constructors continue; if (!mhit.Contains(this.DeclaringType)) //Ignore the method calls from other types continue; hitSubSequence.Sequence.Add(mhit); } //Add all sequences to final set of sequences for further usage. putIndependentMssl.Add(hitSubSequence); putSpecificMssl.Add(hitSubSequence); //this.UpgradeActiveULStores(putsignature, pucls.SuggestedMethodSequences); } } else { //Add all sequences to final set of sequences for further usage. putIndependentMssl.Add(matchingseq); putSpecificMssl.Add(matchingseq); //this.UpgradeActiveULStores(putsignature, matchingseq); } }
/// <summary> /// Gets a persistent location store version of an uncovered location store /// </summary> /// <param name="ucls"></param> /// <returns></returns> public PersistentUncoveredLocationStore GetPersistentLocationstore(UncoveredCodeLocationStore ucls, out bool bNewlyCreated) { PersistentUncoveredLocationStore pucls; bNewlyCreated = false; var key = UncoveredCodeLocationStore.GetKey(ucls.Location.ToString(), ucls.ExplorableType.ToString(), ucls.TermIndex); if (!locationStoreSpecificSequences.TryGetValue(key, out pucls)) { pucls = new PersistentUncoveredLocationStore(ucls.Location, ucls.ExplorableType, ucls.TermIndex, ucls.Fitnessvalue, this); pucls.CodeLocation = ucls.Location.ToString(); locationStoreSpecificSequences[key] = pucls; bNewlyCreated = true; } return pucls; }
/// <summary> /// Removes the uncovered location store. Mainly keeps the sequence /// that helped to cover the target location and drops all others /// </summary> /// <param name="pucls"></param> /// <param name="successful">Helps to distinguish between a removal during success and failure</param> internal void RemoveUncoveredLocationStore(PersistentUncoveredLocationStore pucls, bool successful, PexMeDynamicDatabase pmd) { var key = UncoveredCodeLocationStore.GetKey(pucls.CodeLocation, pucls.ExplorableType, pucls.TermIndex); this.locationStoreSpecificSequences.Remove(key); if (!successful) { return; } this.SuccessfulCoveredLocations.Add(key); this.PermanentFailedUncoveredLocations.Remove(key); this.TemporaryFailedUncoveredLocations.Remove(key); this.UncoveredSystemLibLocations.Remove(key); //Get the method associated with the current exploring PUT string methodcallname = PexMeConstants.DEFAULT_FINAL_SUGGESTION_STORE; Method assocMethod; if (PUTGenerator.PUTGenerator.TryRetrieveMethodCall(pmd.CurrentPUTMethod, out assocMethod)) { methodcallname = MethodOrFieldAnalyzer.GetMethodSignature(assocMethod); } //Get PUT independent sequence list MethodSignatureSequenceList putIndependentMssl; if (!this.FinalSuggestedMethodSequences.TryGetValue(methodcallname, out putIndependentMssl)) { putIndependentMssl = new MethodSignatureSequenceList(); this.FinalSuggestedMethodSequences.Add(methodcallname, putIndependentMssl); } //Also update the PUT specific sequences. These gets cleared once a //PUT is completely explored. var putsignature = MethodOrFieldAnalyzer.GetMethodSignature(pmd.CurrentPUTMethod); MethodSignatureSequenceList putSpecificMssl; if (!this.FinalPUTSequences.TryGetValue(putsignature, out putSpecificMssl)) { putSpecificMssl = new MethodSignatureSequenceList(); this.FinalPUTSequences.Add(putsignature, putSpecificMssl); } //Any Persistent Uncovered location store that is successfully //covered gets a hit sequence SafeDebug.AssumeNotNull(pucls.HitSequence, "pucls.HitSequence"); MethodSignatureSequence matchingseq; if (!FactorySuggestionStore.TryGetMatchingSequence(pucls.HitSequence, pucls.SuggestedMethodSequences, out matchingseq)) { //Failed to retrieve the hit sequence. However, a heuristic //can be used where there is only one suggested sequence if (pucls.SuggestedMethodSequences.Count == 1) { matchingseq = pucls.SuggestedMethodSequences[0]; putIndependentMssl.Add(matchingseq); putSpecificMssl.Add(matchingseq); } else { pmd.Log.LogWarning(WikiTopics.MissingWikiTopic, "SequenceMatch", "Failed to retrieve a matching sequence for a hit sequence, adding complete hit sequence " + pucls.HitSequence); var hitSubSequence = new MethodSignatureSequence(); foreach (var mhit in pucls.HitSequence.Sequence) { if (mhit.Contains("..ctor(")) //Don't add constructors { continue; } if (!mhit.Contains(this.DeclaringType)) //Ignore the method calls from other types { continue; } hitSubSequence.Sequence.Add(mhit); } //Add all sequences to final set of sequences for further usage. putIndependentMssl.Add(hitSubSequence); putSpecificMssl.Add(hitSubSequence); //this.UpgradeActiveULStores(putsignature, pucls.SuggestedMethodSequences); } } else { //Add all sequences to final set of sequences for further usage. putIndependentMssl.Add(matchingseq); putSpecificMssl.Add(matchingseq); //this.UpgradeActiveULStores(putsignature, matchingseq); } }
/// <summary> /// Checks whether there are any looping requireements based on looping threshold and enhances /// the sequence accordingly. Applies only for INCREMENT and DECREMENT field modification types /// </summary> /// <param name="pucls"></param> /// <param name="p"></param> private void CheckNEnhanceForLooping(PersistentUncoveredLocationStore pucls, int fitnessval, FieldModificationType fmt, SafeList<Field> culpritFields) { if (fmt != FieldModificationType.INCREMENT && fmt != FieldModificationType.DECREMENT) return; //Not even a single execution happened on this location. if (fitnessval == Int32.MaxValue) return; var field = culpritFields[0]; FieldStore fs; if (!this.pmd.FieldDictionary.TryGetValue(field, out fs)) return; Dictionary<string, Method> writeMethods = new Dictionary<string, Method>(); foreach (var mset in fs.WriteMethods.Values) { foreach (var m in mset) { var sig = MethodOrFieldAnalyzer.GetMethodSignature(m); writeMethods.Add(sig, m); } } foreach (var seq in pucls.SuggestedMethodSequences) { string loop_method; if (!this.IsEligibleForLooping(seq, field, writeMethods, fs, out loop_method)) continue; pucls.LoopingFeatureApplied = true; this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "LoopingFeature", "Applying looping feature on method: " + loop_method + " (" + (fitnessval - 1) + ")"); for (int count = 1; count < fitnessval; count++) seq.Sequence.Add(loop_method); } }
/// <summary> /// Check whether a previously uncovered location is covered now in this run /// </summary> public bool IsPrevUncoveredLocationCovered(PersistentUncoveredLocationStore pucls) { //retrieve the method MethodDefinition associatedMethod; if (!MethodOrFieldAnalyzer.TryGetMethodDefinition(this, pucls.AssemblyShortName, pucls.declaringTypeStr, pucls.MethodSignature, out associatedMethod)) { this.Log.LogWarning(WikiTopics.MissingWikiTopic, "serialization", "Failed to retrieve the method with signature " + pucls.MethodSignature); return false; } //Check whether the offset is covered in this method if (this.IsBranchOffsetCoveredInMethod(associatedMethod, pucls.Offset)) return true; return false; }
/// <summary> /// Targets to remove those sequences with low or the same fitness /// </summary> /// <param name="ucovLocList"></param> /// <param name="persistentUncoveredLocationStore"></param> private void RemoveSuggestionsWithLowFitness(UncoveredCodeLocationStoreList ucovLocList, PersistentUncoveredLocationStore pucls, List<MethodSignatureSequence> putspecificsequences) { pucls.NumberOfUnsuccessfulAttempts++; int bestFitness = pucls.Fitnessvalue; foreach (var ucovloc in ucovLocList.StoreList) { if (ucovloc.Fitnessvalue < bestFitness) bestFitness = ucovloc.Fitnessvalue; } var explorableType = ucovLocList.ExplorableType; var tempSuggestedSequences = new List<MethodSignatureSequence>(); tempSuggestedSequences.AddRange(pucls.SuggestedMethodSequences); //remove those suggestions that have lower fitness values foreach (var ucovloc in ucovLocList.StoreList) { //Get matching sequence from pucls MethodSignatureSequence matchingseq; if (!FactorySuggestionStore.TryGetMatchingSequence(ucovloc.MethodCallSequence, tempSuggestedSequences, out matchingseq)) { //This sequence is not there in our suggested sequence. This should have happened //due to the case that it came from other uncovered location stores, and is helping //the current store. if (ucovloc.Fitnessvalue <= bestFitness) { var mss = new MethodSignatureSequence(); foreach (var methodinucov in ucovloc.MethodCallSequence.Sequence) { if (methodinucov.Contains("..ctor(")) //Don't add constructors continue; if (!methodinucov.Contains(explorableType)) //Ignore the method calls from other types continue; mss.Sequence.Add(methodinucov); } if(mss.Sequence.Count > 0) pucls.SuggestedMethodSequences.Add(mss); } continue; } tempSuggestedSequences.Remove(matchingseq); if (ucovloc.Fitnessvalue > bestFitness) { //Previous sequence is of no use as it is leading to higher fitness value pucls.SuggestedMethodSequences.Remove(matchingseq); } } if (tempSuggestedSequences.Count != 0) { //Not all sequences are assigned fitness values. Raise warnings for other sequences this.Log.LogWarning(WikiTopics.MissingWikiTopic, "sequencematching", "Fitness values are not available for some previous sequences, Needs to handle this case!!!"); //Remove those suggestions whose fitness value is not evaluated at all. Ideally //this case should not happen. Needs additional debugging. //foreach (var seq in tempSuggestedSequences) // pucls.SuggestedMethodSequences.Remove(seq); } //Update the previous fitness value with the current. If there is any improvement in the fitness, reset the number //of unsuccessful attempts if (pucls.Fitnessvalue != bestFitness) { pucls.NumberOfUnsuccessfulAttempts = 0; pucls.Fitnessvalue = bestFitness; } }