/// <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);
        }
Пример #2
0
        /// <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);
                    }
                }
            }
        }
Пример #3
0
        /// <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;
            }
        }