Пример #1
0
        /// <summary>
        /// Checks whether any previously uncovered locations are covered in this new run
        /// </summary>
        internal void CheckForNewlyCoveredLocations()
        {
            foreach (var fss in this.FactorySuggestionsDictionary.Values)
            {
                foreach (var pucls in fss.locationStoreSpecificSequences.Values)
                {
                    if (pucls.IsDormat())
                    {
                        continue;
                    }

                    if (!pucls.AlreadyCovered && this.IsPrevUncoveredLocationCovered(pucls))
                    {
                        //this.Log.LogMessage("debug", "Covered the location: " + pucls.CodeLocation.ToString());
                        //StringBuilder sb = new StringBuilder();
                        //foreach (Method m in this.LastExecutedMethodCallSequence)
                        //{
                        //   sb.Append(m.ToString() + "\n");
                        //}
                        //this.Log.LogMessage("debug", "Sequence recorded: " + sb.ToString());

                        pucls.HitSequence = new MethodSignatureSequence();
                        foreach (Method m in this.LastExecutedFactoryMethodCallSequence)
                        {
                            pucls.HitSequence.Sequence.Add(MethodOrFieldAnalyzer.GetMethodSignature(m));
                        }
                        pucls.AlreadyCovered = true;
                    }
                }
            }
        }
        /// <summary>
        /// Includes filtering of the methods based on desired format
        /// </summary>
        /// <returns></returns>
        public bool TryGetFilteredWriteMethods(Field field, TypeEx declaringType, FieldModificationType desiredfmt, out SafeSet <Method> writeMethods)
        {
            //Check in the predefined store before proceeding
            if (PreDefinedMethodEffects.TryGetWriteMethods(this, field, desiredfmt, out writeMethods))
            {
                SafeSet <Method> newWriteMethods = new SafeSet <Method>();
                GetCallingMethods(field, declaringType, writeMethods, newWriteMethods);

                //Filter those methods whose actual types are abstract
                SafeSet <Method> returnMethods = new SafeSet <Method>();
                foreach (Method m in writeMethods)
                {
                    TypeEx declType;
                    if (m.TryGetDeclaringType(out declType) && !declType.IsAbstract && !declType.IsInterface)
                    {
                        returnMethods.Add(m);
                    }
                }

                foreach (Method m in newWriteMethods)
                {
                    TypeEx declType;
                    if (m.TryGetDeclaringType(out declType) && !declType.IsAbstract && !declType.IsInterface)
                    {
                        returnMethods.Add(m);
                    }
                }

                writeMethods.Clear();
                writeMethods.AddRange(returnMethods);
                return(true);
            }

            //Identify those method that directly modify this field
            if (!TryGetWriteMethods(field, declaringType, out writeMethods))
            {
                return(false);
            }

            //C# supports properties. In that case, the property setter can also
            //be a viable method. add property setter and its callers also
            Property property;

            if (MethodOrFieldAnalyzer.TryGetPropertyModifyingField(this, declaringType, field, out property))
            {
                if (property.IsVisible(VisibilityContext.Exported))
                {
                    writeMethods.Add(property.Setter);
                }

                var newWriteMethods = new SafeSet <Method>();
                GetCallingMethods(field, declaringType, writeMethods, newWriteMethods);
                writeMethods.AddRange(newWriteMethods);
            }

            writeMethods = FilterWriteMethodsOfUpdateType(field, desiredfmt, writeMethods);
            return(true);
        }
Пример #3
0
        /// <summary>
        /// Gets a method store from a method signature
        /// </summary>
        /// <param name="msignature"></param>
        /// <param name="ms"></param>
        /// <returns></returns>
        public bool TryGetMethodStoreFromSignature(string msignature, out MethodStore ms)
        {
            foreach (var key in this.MethodDictionary.Keys)
            {
                string keysig = MethodOrFieldAnalyzer.GetMethodSignature(key);
                if (keysig == msignature)
                {
                    ms = this.MethodDictionary[key];
                    return(true);
                }
            }

            ms = null;
            return(false);
        }
Пример #4
0
        /// <summary>
        /// Accepts a method and returns the persistent string form "assemblyname#typename#methodsignature" of the method.
        /// </summary>
        /// <param name="method"></param>
        /// <returns></returns>
        public static string GetPersistentStringFormOfMethod(Method m)
        {
            var            assemblyname = m.Definition.Module.Assembly.Location;
            string         typename;
            TypeDefinition typedef = null;

            if (!m.Definition.TryGetDeclaringType(out typedef))
            {
                SafeDebug.AssumeNotNull(typedef, "Type definition is empty");
                typename = PexMeConstants.PexMeDummyTypeName;
            }
            else
            {
                typename = typedef.FullName;
            }

            var signature = MethodOrFieldAnalyzer.GetMethodSignature(m);

            return(assemblyname + PexMeConstants.PexMePersistenceFormSeparator
                   + typename + PexMeConstants.PexMePersistenceFormSeparator + signature);
        }
Пример #5
0
        /// <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>
        /// Checks whether a given method is an observer or not
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        public bool IsAnObserver(Method method)
        {
            TypeEx declaringType;

            if (!method.TryGetDeclaringType(out declaringType))
            {
                return(false);
            }

            MethodEffects me;

            if (!MethodOrFieldAnalyzer.TryComputeMethodEffects(this, declaringType, method,
                                                               null, out me))
            {
                return(false);
            }

            if (me.WrittenInstanceFields.Count == 0)
            {
                return(true);
            }

            return(false);
        }
Пример #7
0
        /// <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);
            }
        }
        /// <summary>
        /// Loads all inheritance hierarchies in the current library
        /// into TypeDictionary in the form of a tree suitable for traversal.
        /// </summary>
        public void LoadInheritanceHierarchies()
        {
            if (isInheritanceHierarchyLoaded)
            {
                return;
            }

            isInheritanceHierarchyLoaded = true;
            AssemblyEx currAssembly = this.Services.CurrentAssembly.Assembly.Assembly;

            foreach (var tdef in currAssembly.TypeDefinitions)
            {
                TypeStore currTypeStore;
                if (!this.TypeDictionary.TryGetValue(tdef, out currTypeStore))
                {
                    currTypeStore = new TypeStore(tdef);
                    this.TypeDictionary.Add(tdef, currTypeStore);
                }
                var baseType = tdef.BaseTypeDefinition;

                //This restricts our implementation to a single assembly for time being.
                if (baseType != null && baseType.Module.Assembly == currAssembly)
                {
                    TypeStore baseTypeStore;
                    if (!this.TypeDictionary.TryGetValue(baseType, out baseTypeStore))
                    {
                        baseTypeStore = new TypeStore(baseType);
                        this.TypeDictionary.Add(baseType, baseTypeStore);
                    }
                    baseTypeStore.ExtendingTypes.Add(currTypeStore);
                }

                try
                {
                    var typeEx = tdef.Instantiate(MethodOrFieldAnalyzer.GetGenericTypeParameters(this, tdef));
                    if (typeEx != null)
                    {
                        foreach (var ifTypeEx in typeEx.DeclaredInterfaces)
                        {
                            var parentIfDef = ifTypeEx.Definition;
                            if (parentIfDef.Module.Assembly != currAssembly)
                            {
                                continue;
                            }

                            TypeStore ifTypeStore;
                            if (!this.TypeDictionary.TryGetValue(parentIfDef, out ifTypeStore))
                            {
                                ifTypeStore = new TypeStore(parentIfDef);
                                this.TypeDictionary.Add(parentIfDef, ifTypeStore);
                            }
                            ifTypeStore.ExtendingTypes.Add(currTypeStore);
                        }
                    }
                }
                catch (Exception ex)
                {
                    this.Log.LogWarningFromException(ex, WikiTopics.MissingWikiTopic, "InheritanceLoader",
                                                     "Failed to instantiate class " + tdef.FullName.ToString());
                }
            }
        }
        /// <summary>
        /// Gets the set of write methods associated with a field in the given type
        /// </summary>
        /// <param name="field"></param>
        /// <returns></returns>
        public bool TryGetWriteMethods(Field field, TypeEx declaringType, out SafeSet <Method> writeMethods)
        {
            SafeDebug.AssumeNotNull(field, "field");
            SafeDebug.AssumeNotNull(declaringType, "declaringType");

            //Declaring type should include defintinion
            if (declaringType == null || declaringType.Definition == null)
            {
                this.Log.LogWarning(WikiTopics.MissingWikiTopic, "WriteMethods",
                                    "Missing definition for the declaring type " + declaringType.FullName);
                writeMethods = null;
                return(false);
            }

            FieldStore fs;

            if (this.FieldDictionary.TryGetValue(field, out fs))
            {
                if (fs.WriteMethods.TryGetValue(declaringType, out writeMethods))
                {
                    return(true);
                }
                else
                {
                    writeMethods = new SafeSet <Method>();
                    fs.WriteMethods[declaringType] = writeMethods;
                }
            }
            else
            {
                fs           = new FieldStore();
                fs.FieldName = field;
                writeMethods = new SafeSet <Method>();
                fs.WriteMethods[declaringType] = writeMethods;
                this.FieldDictionary[field]    = fs;
            }

            foreach (MethodDefinition instanceMethod in declaringType.Definition.DeclaredInstanceMethods)
            {
                //Ignore abstract methods
                if (instanceMethod.IsAbstract)
                {
                    continue;
                }

                //If the DISABLE_CALLING_METHODS_WITHIN_CLASS is set to true, then private methods need not be considered
                //since they will be filtered out.
                if (PexMeConstants.DISABLE_CALLING_METHODS_WITHIN_CLASS && instanceMethod.DeclaredVisibility == Visibility.Private)
                {
                    continue;
                }

                Method        method = instanceMethod.Instantiate(declaringType.GenericTypeArguments, MethodOrFieldAnalyzer.GetGenericMethodParameters(this, instanceMethod));
                MethodEffects me;

                if (!MethodOrFieldAnalyzer.TryComputeMethodEffects(this, declaringType, method, null, out me))
                {
                    this.Log.LogWarning(WikiTopics.MissingWikiTopic, "methodeffects",
                                        "Failed to get the method effects for method " + method);
                    continue;
                }

                if (me.WrittenInstanceFields.Contains(field.ShortName))
                {
                    writeMethods.Add(method);
                }

                FieldModificationType fmt;
                if (me.ModificationTypeDictionary.TryGetValue(field.ShortName, out fmt))
                {
                    fs.ModificationTypeDictionary[method] = fmt;
                }
            }

            //Check whether there are any private methods in calling methods.
            //If yes, replace them with their callers.
            if (!PexMeConstants.DISABLE_CALLING_METHODS_WITHIN_CLASS)
            {
                var newWriteMethods = new SafeSet <Method>();
                GetCallingMethods(field, declaringType, writeMethods, newWriteMethods);

                writeMethods.Clear();
                writeMethods.AddRange(newWriteMethods);
            }

            TypeEx baseType = declaringType.BaseType;

            if (baseType != null && baseType.FullName != "System.Object")
            {
                SafeSet <Method> innerWriteMethods;
                this.TryGetWriteMethods(field, baseType, out innerWriteMethods);
                if (innerWriteMethods != null)
                {
                    writeMethods.AddRange(innerWriteMethods);
                }
            }

            return(true);
        }
Пример #10
0
        /// <summary>
        /// Gets calling methods of a given called method on the given field in a given target type
        /// </summary>
        /// <returns></returns>
        public bool TryGetCallingMethodsInType(Method calledMethod, Field field, TypeEx targetType, out SafeSet <Method> callingMethods)
        {
            SafeDebug.AssumeNotNull(calledMethod, "method");
            SafeDebug.AssumeNotNull(targetType, "type");

            //Get the associated property of the field
            Property property;

            if (!MethodOrFieldAnalyzer.TryGetPropertyReadingField(this, targetType, field, out property))
            {
                //TODO: error;
            }

            MethodStore mstore = null;

            if (this.MethodDictionary.TryGetValue(calledMethod, out mstore))
            {
                if (mstore.CallingMethods.TryGetValue(targetType, out callingMethods))
                {
                    return(true);
                }
            }

            //No method store found. create a fresh one
            if (mstore == null)
            {
                mstore            = new MethodStore();
                mstore.methodName = calledMethod;
                this.MethodDictionary[calledMethod] = mstore;
            }

            callingMethods = new SafeSet <Method>();
            mstore.CallingMethods[targetType] = callingMethods;
            TypeEx calledMethodType;

            if (!calledMethod.TryGetDeclaringType(out calledMethodType))
            {
                this.Log.LogError(WikiTopics.MissingWikiTopic, "callingmethods",
                                  "Failed to get the declaring type for the method " + calledMethod.FullName);
                return(false);
            }

            //Needs to addess the array type issue over here.
            var targetdef = targetType.Definition;

            if (targetdef == null)
            {
                if (targetType.TypeKind != TypeKind.SzArrayElements)
                {
                    this.Log.LogError(WikiTopics.MissingWikiTopic, "callingmethods",
                                      "The definition for the type " + targetType.FullName + " is null");
                    return(false);
                }
                else
                {
                    targetdef = targetType.ElementType.Definition;
                }
            }

            //Analyze each method in the given type to identify the calling methods
            //of the given method
            foreach (var typeMethod in targetdef.DeclaredInstanceMethods)
            {
                Method minstance = typeMethod.Instantiate(targetType.GenericTypeArguments, MethodOrFieldAnalyzer.GetGenericMethodParameters(this, typeMethod));

                MethodEffects meffects;
                if (!MethodOrFieldAnalyzer.TryComputeMethodEffects(this, targetType, minstance, null, out meffects))
                {
                    continue;
                }

                //Check for a direct comparison
                if (meffects.DirectCalledMethods.Contains(calledMethod))
                {
                    callingMethods.Add(minstance);
                }
                else
                {
                    //Use vtable lookup for addressing the abstract issues
                    foreach (var dcallMethod in meffects.DirectCalledMethods)
                    {
                        if (dcallMethod.IsConstructor)
                        {
                            continue;
                        }

                        TypeEx dcallMethodType;
                        if (dcallMethod.TryGetDeclaringType(out dcallMethodType))
                        {
                            if (dcallMethodType == calledMethodType || !dcallMethodType.IsAbstract || !dcallMethodType.IsInterface)
                            {
                                continue;
                            }

                            if (!dcallMethodType.IsAssignableTo(calledMethodType) && !calledMethodType.IsAssignableTo(dcallMethodType))
                            {
                                continue;
                            }
                        }

                        try
                        {
                            var lookupMethod = calledMethodType.VTableLookup(dcallMethod);
                            if (lookupMethod != null && calledMethod == lookupMethod)
                            {
                                callingMethods.Add(minstance);
                                break;
                            }
                        }
                        catch (Exception ex)
                        {
                            this.Log.LogWarningFromException(ex, WikiTopics.MissingWikiTopic,
                                                             "vtablelookup", "Failed to perform vtablelookup for " + dcallMethod.FullName + " in type " + calledMethodType.FullName);
                        }
                    }
                }
            }

            //Check whether there are any private methods in calling methods.
            //If yes, replace them with their callers.
            if (!PexMeConstants.DISABLE_CALLING_METHODS_WITHIN_CLASS)
            {
                var newCallingMethods = new SafeSet <Method>();
                foreach (var callingM in callingMethods)
                {
                    if (callingM.Definition.DeclaredVisibility != Visibility.Private || callingM.IsConstructor)
                    {
                        newCallingMethods.Add(callingM);
                        continue;
                    }

                    //Get other calling methods within this type
                    SafeSet <Method> localCM;
                    if (this.TryGetCallingMethodsInType(callingM, field, targetType, out localCM))
                    {
                        newCallingMethods.AddRange(localCM);
                    }
                }

                callingMethods.Clear();
                callingMethods.AddRange(newCallingMethods);
            }

            //Needs to further analyze parent types
            TypeEx baseType = targetType.BaseType;

            if (baseType != null && baseType.FullName != "System.Object")   //TODO: Avoid string comparisons. needs to figure out how to do that
            {
                SafeSet <Method> baseCallingMethods;
                TryGetCallingMethodsInType(calledMethod, field, baseType, out baseCallingMethods);
                callingMethods.AddRange(baseCallingMethods);
            }

            return(true);
        }