/// <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> /// 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> /// 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> /// Analyzes the currently implemented features and makes sure only relevant /// features that are implemented further are processed. /// </summary> /// <param name="ucls"></param> /// <returns></returns> private FieldModificationType GetRequiredFieldModificationType(UncoveredCodeLocationStore ucls) { return(ucls.DesiredFieldModificationType); }
/// <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> /// 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> /// 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> /// Adds a field to an unsuccessful code location. /// </summary> /// <param name="location"></param> /// <param name="fields"></param> public void AddFieldsOfUncoveredCodeLocations(CodeLocation location, SafeList <Field> fields, FieldModificationType fmt, Term condition, string terms, int fitnessval, TypeEx explorableType, SafeList <TypeEx> allFieldTypes) { //No need to process this location. if (fields.Count == 0) { return; } Field targetField; TypeEx declaringType; //This declaring type is considered as explorable type in the rest of the analysis if (!PexMeFactoryGuesser.GetTargetExplorableField(this, fields, out targetField, out declaringType)) { this.Log.LogError(WikiTopics.MissingWikiTopic, "factoryguesser", "Failed to retrieve the target field for uncovered location " + location.ToString()); return; } //Compare the declaring type and actual explorable type. //If there is a inheritance relation, use the actual one if (explorableType.IsAssignableTo(declaringType)) { declaringType = explorableType; } var uclskey = UncoveredCodeLocationStore.GetKey(location.ToString(), declaringType.ToString(), condition.UniqueIndex); UncoveredCodeLocationStoreList uclslist; if (!this.unCoveredLocationDic.TryGetValue(uclskey, out uclslist)) { uclslist = new UncoveredCodeLocationStoreList(); uclslist.Location = location; uclslist.ExplorableType = declaringType.ToString(); uclslist.TermIndex = condition.UniqueIndex; this.unCoveredLocationDic[uclskey] = uclslist; } var ucls = new UncoveredCodeLocationStore(); ucls.Location = location; ucls.ExplorableType = declaringType; ucls.TargetField = targetField; ucls.AllFields.AddRange(fields); ucls.AllFieldTypes.AddRange(allFieldTypes); ucls.TermIndex = condition.UniqueIndex; //add the sequence of method calls ucls.MethodCallSequence = new MethodSignatureSequence(); foreach (var m in this.LastExecutedFactoryMethodCallSequence) { ucls.MethodCallSequence.Sequence.Add(MethodOrFieldAnalyzer.GetMethodSignature(m)); } ucls.IsADefectDetectingSequence = this.DefectDetectingSequence; ucls.CUTMethodCallSequence = this.LastExecutedCUTMethodCallSequence; if (!uclslist.StoreList.Contains(ucls)) { ucls.TextualTerms.Add(terms); ucls.DesiredFieldModificationType = fmt; ucls.Fitnessvalue = fitnessval; uclslist.StoreList.Add(ucls); } }