/// <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 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); } }