/// <summary> /// Adds a default method-call sequence that represents the first execution /// of the PUT /// </summary> internal void AddDefaultSequence(PexMeDynamicDatabase pmd, MethodSignatureSequence defaultSeq) { //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); putIndependentMssl.Add(defaultSeq); } //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); putSpecificMssl.Add(defaultSeq); } }
/// <summary> /// Gets a MethodSignatureSequenceList for each putmethod. If one does not exist, /// creates a fresh one /// </summary> /// <param name="putmethod"></param> /// <returns></returns> public bool TryGetListFromFinalSuggestedSequences(Method putmethod, out MethodSignatureSequenceList mssl) { mssl = null; Method assocMethod; if (!PUTGenerator.PUTGenerator.TryRetrieveMethodCall(putmethod, out assocMethod)) { return(false); } var methodcallname = MethodOrFieldAnalyzer.GetMethodSignature(assocMethod); if (!this.FinalSuggestedMethodSequences.TryGetValue(methodcallname, out mssl)) { mssl = new MethodSignatureSequenceList(); this.FinalSuggestedMethodSequences.Add(methodcallname, mssl); } return(true); }
/// <summary> /// Re-activates this PUT; /// </summary> /// <param name="?"></param> /// <returns></returns> public bool ActivateFromDormant(string putname) { if (this.associatedPUTName == putname) { bDormant = false; var newSequenceList = new List <MethodSignatureSequence>(); //Re-activate based on the snapshot of sequences taken. MethodSignatureSequenceList mssl; if (!this.parentfss.FinalPUTSequences.TryGetValue(putname, out mssl)) { return(true); } if (this.putSeqSnapshot == null) { this.putSeqSnapshot = new MethodSignatureSequenceList(); } foreach (var seq in mssl.SequenceList) { if (this.putSeqSnapshot.SequenceList.Contains(seq)) { continue; } //A new sequence is detected after this uncovered location store went to dormant stage MethodSignatureSequence newMs = new MethodSignatureSequence(); newMs.Sequence.AddRange(seq.Sequence); this.SuggestedMethodSequences.Add(newMs); } return(true); } return(false); }
/// <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> /// Adds a default method-call sequence that represents the first execution /// of the PUT /// </summary> internal void AddDefaultSequence(PexMeDynamicDatabase pmd, MethodSignatureSequence defaultSeq) { //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); putIndependentMssl.Add(defaultSeq); } //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); putSpecificMssl.Add(defaultSeq); } }
/// <summary> /// Gets a MethodSignatureSequenceList for each putmethod. If one does not exist, /// creates a fresh one /// </summary> /// <param name="putmethod"></param> /// <returns></returns> public bool TryGetListFromFinalSuggestedSequences(Method putmethod, out MethodSignatureSequenceList mssl) { mssl = null; Method assocMethod; if (!PUTGenerator.PUTGenerator.TryRetrieveMethodCall(putmethod, out assocMethod)) return false; var methodcallname = MethodOrFieldAnalyzer.GetMethodSignature(assocMethod); if (!this.FinalSuggestedMethodSequences.TryGetValue(methodcallname, out mssl)) { mssl = new MethodSignatureSequenceList(); this.FinalSuggestedMethodSequences.Add(methodcallname, mssl); } return true; }
/// <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> /// Updates all sequences in uncovered location stores with new suggestions that /// are also stored within the PUT itself /// </summary> private void UpdateUncoveredLocationsWithNewSuggestions(string currPUTSignature) { //Iterate through each uncovered location foreach (var ucovLocList in this.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; if (!this.pmd.FactorySuggestionsDictionary.TryGetValue(ucovLocList.ExplorableType, out fss)) { this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "UncoveredLocations", "Failed to retrieve factory suggestion store for explorable type " + ucovLocList.ExplorableType); continue; } MethodSignatureSequenceList putspecificlist; if (!fss.FinalPUTSequences.TryGetValue(currPUTSignature, out putspecificlist)) putspecificlist = new MethodSignatureSequenceList(); var ucovLoc = ucovLocList.StoreList[0]; //If a suggested method is not yet explored, add it to all new suggested method if (ucovLoc.SuggestedMethodSetforFactory != null) { //Prepare new sequences with the suggested method var newmssl = new MethodSignatureSequenceList(); foreach (var suggestedm in ucovLoc.SuggestedMethodSetforFactory) { //Get all the pre-requisite sequences for this suggested method var suggestedmsig = MethodOrFieldAnalyzer.GetMethodSignature(suggestedm); MethodSignatureSequenceList mssl; fss.FinalSuggestedMethodSequences.TryGetValue(suggestedmsig, out mssl); if (mssl == null || mssl.SequenceList.Count == 0) { var tempmss = new MethodSignatureSequence(); tempmss.Sequence.Add(suggestedmsig); newmssl.SequenceList.Add(tempmss); } else { //Make a new sequence from the suggested method and its pre-requisite foreach (var seq in mssl.SequenceList) { var tempmss = new MethodSignatureSequence(); tempmss.Sequence.AddRange(seq.Sequence); tempmss.Sequence.Add(suggestedmsig); newmssl.SequenceList.Add(tempmss); } } } //Add all these suggestions to the uncovered location store itself bool bNewlyCreated = false; var pucls = fss.GetPersistentLocationstore(ucovLoc, out bNewlyCreated); pucls.UpdateSuggestedMethodSequences(newmssl, putspecificlist); //Check whether any looping is required. If a method //is repeated more than 3 times, in a sequence, we consider //it as a looping requirement. This is only a heuristic based. if (!PexMeConstants.IGNORE_LOOP_FEATURE && !pucls.LoopingFeatureApplied) { this.CheckNEnhanceForLooping(pucls, pucls.Fitnessvalue, ucovLoc.DesiredFieldModificationType, ucovLoc.AllFields); } //Check for the number of sequences in this pucls. If they //exceed the limit, delete the sequences if ((pucls.SuggestedMethodSequences.Count - fss.FinalSuggestedMethodSequences.Values.Count) > PexMeConstants.MAX_ALLOWED_SEQUENCES) { fss.RemoveUncoveredLocationStore(pucls, false, this.pmd); var key = UncoveredCodeLocationStore.GetKey(pucls.CodeLocation, pucls.ExplorableType, pucls.TermIndex); fss.PermanentFailedUncoveredLocations.Add(key); fss.TemporaryFailedUncoveredLocations.Add(key, PexMeConstants.MAX_UNCOVEREDLOC_ATTEMPTS); this.pmd.Log.LogWarning(WikiTopics.MissingWikiTopic, "uncoveredlocation", @"Sequences for uncovered location " + pucls.CodeLocation + "crossed the threshold " + PexMeConstants.MAX_ALLOWED_SEQUENCES + ", Deleted forever"); } } } //Add default sequences to the newly created factory suggestion stores foreach (var ucovLocList in this.pmd.UncoveredLocationDictionary.Values) { if (ucovLocList.StoreList.Count == 0) continue; FactorySuggestionStore fss; if (!this.pmd.FactorySuggestionsDictionary.TryGetValue(ucovLocList.ExplorableType, out fss)) continue; var ucovLoc = ucovLocList.StoreList[0]; if (fss.BCreatedNow) { fss.BCreatedNow = false; var mss = new MethodSignatureSequence(); var explorableType = ucovLocList.ExplorableType; 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); } fss.AddDefaultSequence(this.pmd, mss); } } }
/// <summary> /// Takes a new sequence list and updates the existing sequence list /// with the new list /// </summary> /// <param name="mssl"></param> public void UpdateSuggestedMethodSequences(MethodSignatureSequenceList mssl, MethodSignatureSequenceList putSpecificList) { var newSuggesedMethodSequences = new List <MethodSignatureSequence>(); if (this.SuggestedMethodSequences.Count == 0) { //A fresh location. //Make up new sequences with the known list if (putSpecificList.SequenceList.Count == 0) { foreach (var suggestedm in mssl.SequenceList) { MethodSignatureSequence newMS = new MethodSignatureSequence(); newMS.Sequence.AddRange(suggestedm.Sequence); newSuggesedMethodSequences.Add(newMS); } } else { foreach (var pseq in putSpecificList.SequenceList) { foreach (var suggestedm in mssl.SequenceList) { MethodSignatureSequence newMS = new MethodSignatureSequence(); newMS.Sequence.AddRange(pseq.Sequence); foreach (var method in suggestedm.Sequence) { if (!method.Contains("..ctor(")) { newMS.Sequence.Add(method); } } if (!newSuggesedMethodSequences.Contains(newMS)) { newSuggesedMethodSequences.Add(newMS); } } } } } else { //Once the looping feature is applied, there is no point in updating the sequences if (!this.LoopingFeatureApplied) { //Merge and make up the new list foreach (var pseq in this.SuggestedMethodSequences) { foreach (var suggestedm in mssl.SequenceList) { MethodSignatureSequence newMS = new MethodSignatureSequence(); newMS.Sequence.AddRange(pseq.Sequence); foreach (var method in suggestedm.Sequence) { if (!method.Contains("..ctor(")) { newMS.Sequence.Add(method); } } if (!newSuggesedMethodSequences.Contains(newMS)) { newSuggesedMethodSequences.Add(newMS); } } } } else { newSuggesedMethodSequences = this.SuggestedMethodSequences; } } this.SuggestedMethodSequences = newSuggesedMethodSequences; }
/// <summary> /// Takes a new sequence list and updates the existing sequence list /// with the new list /// </summary> /// <param name="mssl"></param> public void UpdateSuggestedMethodSequences(MethodSignatureSequenceList mssl, MethodSignatureSequenceList putSpecificList) { var newSuggesedMethodSequences = new List<MethodSignatureSequence>(); if (this.SuggestedMethodSequences.Count == 0) { //A fresh location. //Make up new sequences with the known list if (putSpecificList.SequenceList.Count == 0) { foreach (var suggestedm in mssl.SequenceList) { MethodSignatureSequence newMS = new MethodSignatureSequence(); newMS.Sequence.AddRange(suggestedm.Sequence); newSuggesedMethodSequences.Add(newMS); } } else { foreach (var pseq in putSpecificList.SequenceList) { foreach (var suggestedm in mssl.SequenceList) { MethodSignatureSequence newMS = new MethodSignatureSequence(); newMS.Sequence.AddRange(pseq.Sequence); foreach (var method in suggestedm.Sequence) { if(!method.Contains("..ctor(")) newMS.Sequence.Add(method); } if(!newSuggesedMethodSequences.Contains(newMS)) newSuggesedMethodSequences.Add(newMS); } } } } else { //Once the looping feature is applied, there is no point in updating the sequences if (!this.LoopingFeatureApplied) { //Merge and make up the new list foreach (var pseq in this.SuggestedMethodSequences) { foreach (var suggestedm in mssl.SequenceList) { MethodSignatureSequence newMS = new MethodSignatureSequence(); newMS.Sequence.AddRange(pseq.Sequence); foreach (var method in suggestedm.Sequence) { if (!method.Contains("..ctor(")) newMS.Sequence.Add(method); } if(!newSuggesedMethodSequences.Contains(newMS)) newSuggesedMethodSequences.Add(newMS); } } } else newSuggesedMethodSequences = this.SuggestedMethodSequences; } this.SuggestedMethodSequences = newSuggesedMethodSequences; }
/// <summary> /// Re-activates this PUT; /// </summary> /// <param name="?"></param> /// <returns></returns> public bool ActivateFromDormant(string putname) { if (this.associatedPUTName == putname) { bDormant = false; var newSequenceList = new List<MethodSignatureSequence>(); //Re-activate based on the snapshot of sequences taken. MethodSignatureSequenceList mssl; if (!this.parentfss.FinalPUTSequences.TryGetValue(putname, out mssl)) return true; if (this.putSeqSnapshot == null) this.putSeqSnapshot = new MethodSignatureSequenceList(); foreach (var seq in mssl.SequenceList) { if (this.putSeqSnapshot.SequenceList.Contains(seq)) continue; //A new sequence is detected after this uncovered location store went to dormant stage MethodSignatureSequence newMs = new MethodSignatureSequence(); newMs.Sequence.AddRange(seq.Sequence); this.SuggestedMethodSequences.Add(newMs); } return true; } return false; }