private static string GetModificationTypeStr(FieldModificationType fmt) { switch (fmt) { case FieldModificationType.DECREMENT: return("DECREMENT"); case FieldModificationType.INCREMENT: return("INCREMENT"); case FieldModificationType.INCREMENT_ONE: return("INCREMENT_ONE"); case FieldModificationType.NULL_SET: return("NULL_SET"); case FieldModificationType.NON_NULL_SET: return("NON_NULL_SET"); case FieldModificationType.UNKNOWN: return("UNKNOWN"); case FieldModificationType.TRUE_SET: return("TRUE_SET"); case FieldModificationType.FALSE_SET: return("FALSE_SET"); case FieldModificationType.METHOD_CALL: return("METHOD_CALL"); default: return("UNKNOWN"); } }
/// <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> /// 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); }
/// <summary> /// Gets textual form of modification type /// </summary> /// <param name="method"></param> /// <returns></returns> public static string GetPreciseModificationType(FieldStore fs, Method method) { if (!fs.PreciseModificationTypeDictionary.ContainsKey(method)) { return("UNKNOWN"); } FieldModificationType fmt = fs.PreciseModificationTypeDictionary[method]; return(GetModificationTypeStr(fmt)); }
/// <summary> /// Checks whether there are any looping requireements based on looping threshold and enhances /// the sequence accordingly. Applies only for INCREMENT and DECREMENT field modification types /// </summary> /// <param name="pucls"></param> /// <param name="p"></param> private void CheckNEnhanceForLooping(PersistentUncoveredLocationStore pucls, int fitnessval, FieldModificationType fmt, SafeList <Field> culpritFields) { if (fmt != FieldModificationType.INCREMENT && fmt != FieldModificationType.DECREMENT) { return; } //Not even a single execution happened on this location. if (fitnessval == Int32.MaxValue) { return; } var field = culpritFields[0]; FieldStore fs; if (!this.pmd.FieldDictionary.TryGetValue(field, out fs)) { return; } Dictionary <string, Method> writeMethods = new Dictionary <string, Method>(); foreach (var mset in fs.WriteMethods.Values) { foreach (var m in mset) { var sig = MethodOrFieldAnalyzer.GetMethodSignature(m); writeMethods.Add(sig, m); } } foreach (var seq in pucls.SuggestedMethodSequences) { string loop_method; if (!this.IsEligibleForLooping(seq, field, writeMethods, fs, out loop_method)) { continue; } pucls.LoopingFeatureApplied = true; this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "LoopingFeature", "Applying looping feature on method: " + loop_method + " (" + (fitnessval - 1) + ")"); for (int count = 1; count < fitnessval; count++) { seq.Sequence.Add(loop_method); } } }
/// <summary> /// Checks whether fitness strategy matters or not. Since, fitness /// is required only for integers, but not for all kinds of types such /// as boolean or non-null /// </summary> /// <returns></returns> private bool IsFitnessRequired(FieldModificationType fmt) { switch (fmt) { case FieldModificationType.INCREMENT: case FieldModificationType.DECREMENT: case FieldModificationType.INCREMENT_ONE: return(true); case FieldModificationType.FALSE_SET: case FieldModificationType.TRUE_SET: case FieldModificationType.NULL_SET: case FieldModificationType.NON_NULL_SET: return(false); default: return(false); } }
/// <summary> /// Retrieves the write methods for a field, if exists from the predefined settings. /// </summary> public static bool TryGetWriteMethods(IPexComponent host, Field field, FieldModificationType desiredFmt, out SafeSet<Method> writeMethods) { if (!isPredefinedEffectsParsed) ParsePredefinedEffects(host); PreDefinedMethodEffectsStore pdme = new PreDefinedMethodEffectsStore(field, desiredFmt); PreDefinedMethodEffectsStore existingPdme; if (effectsStore.TryGetValue(pdme, out existingPdme)) { writeMethods = new SafeSet<Method>(); writeMethods.AddRange(existingPdme.suggestedmethodList); return true; } else { writeMethods = null; return false; } }
/// <summary> /// Given a set of write methods, this method basically filters them out /// to create a new set. Also filters the method that belongs to the interface type /// </summary> /// <param name="field"></param> /// <param name="fieldModificationType"></param> /// <param name="writeMethods"></param> /// <returns></returns> private SafeSet <Method> FilterWriteMethodsOfUpdateType(Field field, FieldModificationType fieldModificationType, SafeSet <Method> writeMethods) { FieldStore fs; if (!this.FieldDictionary.TryGetValue(field, out fs)) { return(writeMethods); } SafeSet <Method> returnSet = new SafeSet <Method>(); foreach (var method in writeMethods) { //no need of methods in interfaces or abstract classes. TypeEx declType; if (method.TryGetDeclaringType(out declType) && (declType.IsAbstract || declType.IsInterface)) { continue; } //We currently allow unknown types FieldModificationType fmt; //Problem of static analysis impreciseness. If no modificuatui if (!fs.ModificationTypeDictionary.TryGetValue(method, out fmt)) { returnSet.Add(method); } if (fmt == fieldModificationType || fmt == FieldModificationType.UNKNOWN || fmt == FieldModificationType.METHOD_CALL) { returnSet.Add(method); } } return(returnSet); }
/// <summary> /// Parses each record and stores into internal dictionary /// </summary> /// <param name="assemblyname"></param> /// <param name="typename"></param> /// <param name="fieldname"></param> /// <param name="fmttype"></param> /// <param name="methodname"></param> private static void ParseRecord(IPexComponent host, string assemblyname, string typename, string fieldname, string fmttype, string methodname) { Field field; if (!MethodOrFieldAnalyzer.TryGetField(host, assemblyname, typename, fieldname, out field)) { host.Log.LogWarning(WikiTopics.MissingWikiTopic, "PredefinedEffects", "Failed to load field: " + fieldname); return; } FieldModificationType fmt = FieldStore.GetModificationTypeFromString(fmttype); Method method; if (!MethodOrFieldAnalyzer.TryGetMethod(host, assemblyname, typename, methodname, out method)) { host.Log.LogWarning(WikiTopics.MissingWikiTopic, "PredefinedEffects", "Failed to load method: " + methodname); return; } //storing into the effects store PreDefinedMethodEffectsStore pdme = new PreDefinedMethodEffectsStore(field, fmt); List <Method> suggestedMethods; PreDefinedMethodEffectsStore existingPdme; if (!effectsStore.TryGetValue(pdme, out existingPdme)) { suggestedMethods = new List <Method>(); pdme.suggestedmethodList = suggestedMethods; effectsStore.Add(pdme, pdme); } else { suggestedMethods = existingPdme.suggestedmethodList; } suggestedMethods.Add(method); }
/// <summary> /// Retrieves the write methods for a field, if exists from the predefined settings. /// </summary> public static bool TryGetWriteMethods(IPexComponent host, Field field, FieldModificationType desiredFmt, out SafeSet <Method> writeMethods) { if (!isPredefinedEffectsParsed) { ParsePredefinedEffects(host); } PreDefinedMethodEffectsStore pdme = new PreDefinedMethodEffectsStore(field, desiredFmt); PreDefinedMethodEffectsStore existingPdme; if (effectsStore.TryGetValue(pdme, out existingPdme)) { writeMethods = new SafeSet <Method>(); writeMethods.AddRange(existingPdme.suggestedmethodList); return(true); } else { writeMethods = null; return(false); } }
/// <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> /// Computes fitness values. TODO: handles only integer and boolean. Needs to be extended for other types /// </summary> /// <param name="field"></param> /// <param name="actual"></param> /// <param name="expected"></param> /// <param name="host"></param> /// <param name="fmt"></param> /// <param name="fitnessval"></param> public static void ComputeFitnessValue(Field field, FieldValueHolder actual, FieldValueHolder expected, IPexComponent host, out FieldModificationType fmt, out int fitnessval) { fitnessval = Int32.MaxValue; fmt = FieldModificationType.UNKNOWN; try { string fieldType = field.Type.ToString(); if (fieldType == "System.Int32") { fitnessval = Math.Abs(actual.intValue - expected.intValue); if (actual.intValue < expected.intValue) { fmt = FieldModificationType.INCREMENT; } else if (actual.intValue > expected.intValue) { fmt = FieldModificationType.DECREMENT; } return; } if (fieldType == "System.Boolean") { if (expected.boolValue) fmt = FieldModificationType.TRUE_SET; else fmt = FieldModificationType.FALSE_SET; return; } if (fieldType == "System.Int16") { fitnessval = Math.Abs(actual.shortValue - expected.shortValue); if (actual.shortValue < expected.shortValue) { fmt = FieldModificationType.INCREMENT; } else if (actual.shortValue > expected.shortValue) { fmt = FieldModificationType.DECREMENT; } return; } if (fieldType == "System.Int64") { fitnessval = (int)Math.Abs(actual.longValue - expected.longValue); if (actual.longValue < expected.longValue) { fmt = FieldModificationType.INCREMENT; } else if (actual.longValue > expected.longValue) { fmt = FieldModificationType.DECREMENT; } return; } if (field.Type.IsReferenceType) { if (expected.objValue == null) fmt = FieldModificationType.NULL_SET; else fmt = FieldModificationType.NON_NULL_SET; } host.Log.LogWarning(WikiTopics.MissingWikiTopic, "FitnexCompute", "Handles only integer and boolean types."); } catch (OverflowException ofe) { host.Log.LogCriticalFromException(ofe, WikiTopics.MissingWikiTopic, "FitnessMeasure", "Overflow error occurred while computing fitness values"); } }
/// <summary> /// Computes fitness values. TODO: handles only integer and boolean. Needs to be extended for other types /// </summary> /// <param name="field"></param> /// <param name="actual"></param> /// <param name="expected"></param> /// <param name="host"></param> /// <param name="fmt"></param> /// <param name="fitnessval"></param> public static void ComputeFitnessValue(Field field, FieldValueHolder actual, FieldValueHolder expected, IPexComponent host, out FieldModificationType fmt, out int fitnessval) { fitnessval = Int32.MaxValue; fmt = FieldModificationType.UNKNOWN; try { string fieldType = field.Type.ToString(); if (fieldType == "System.Int32") { fitnessval = Math.Abs(actual.intValue - expected.intValue); if (actual.intValue < expected.intValue) { fmt = FieldModificationType.INCREMENT; } else if (actual.intValue > expected.intValue) { fmt = FieldModificationType.DECREMENT; } return; } if (fieldType == "System.Boolean") { if (expected.boolValue) { fmt = FieldModificationType.TRUE_SET; } else { fmt = FieldModificationType.FALSE_SET; } return; } if (fieldType == "System.Int16") { fitnessval = Math.Abs(actual.shortValue - expected.shortValue); if (actual.shortValue < expected.shortValue) { fmt = FieldModificationType.INCREMENT; } else if (actual.shortValue > expected.shortValue) { fmt = FieldModificationType.DECREMENT; } return; } if (fieldType == "System.Int64") { fitnessval = (int)Math.Abs(actual.longValue - expected.longValue); if (actual.longValue < expected.longValue) { fmt = FieldModificationType.INCREMENT; } else if (actual.longValue > expected.longValue) { fmt = FieldModificationType.DECREMENT; } return; } if (field.Type.IsReferenceType) { if (expected.objValue == null) { fmt = FieldModificationType.NULL_SET; } else { fmt = FieldModificationType.NON_NULL_SET; } } host.Log.LogWarning(WikiTopics.MissingWikiTopic, "FitnexCompute", "Handles only integer and boolean types."); } catch (OverflowException ofe) { host.Log.LogCriticalFromException(ofe, WikiTopics.MissingWikiTopic, "FitnessMeasure", "Overflow error occurred while computing fitness values"); } }
/// <summary> /// public constructor /// </summary> /// <param name="type"></param> /// <param name="field"></param> /// <param name="fmt"></param> public PreDefinedMethodEffectsStore(Field field, FieldModificationType fmt) { this.field = field; this.fmt = fmt; }
private static string GetModificationTypeStr(FieldModificationType fmt) { switch (fmt) { case FieldModificationType.DECREMENT: return "DECREMENT"; case FieldModificationType.INCREMENT: return "INCREMENT"; case FieldModificationType.INCREMENT_ONE: return "INCREMENT_ONE"; case FieldModificationType.NULL_SET: return "NULL_SET"; case FieldModificationType.NON_NULL_SET: return "NON_NULL_SET"; case FieldModificationType.UNKNOWN: return "UNKNOWN"; case FieldModificationType.TRUE_SET: return "TRUE_SET"; case FieldModificationType.FALSE_SET: return "FALSE_SET"; case FieldModificationType.METHOD_CALL: return "METHOD_CALL"; default: return "UNKNOWN"; } }
/// <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; }
/// <summary> /// Given a set of write methods, this method basically filters them out /// to create a new set. Also filters the method that belongs to the interface type /// </summary> /// <param name="field"></param> /// <param name="fieldModificationType"></param> /// <param name="writeMethods"></param> /// <returns></returns> private SafeSet<Method> FilterWriteMethodsOfUpdateType(Field field, FieldModificationType fieldModificationType, SafeSet<Method> writeMethods) { FieldStore fs; if (!this.FieldDictionary.TryGetValue(field, out fs)) return writeMethods; SafeSet<Method> returnSet = new SafeSet<Method>(); foreach (var method in writeMethods) { //no need of methods in interfaces or abstract classes. TypeEx declType; if (method.TryGetDeclaringType(out declType) && (declType.IsAbstract || declType.IsInterface)) { continue; } //We currently allow unknown types FieldModificationType fmt; //Problem of static analysis impreciseness. If no modificuatui if (!fs.ModificationTypeDictionary.TryGetValue(method, out fmt)) returnSet.Add(method); if (fmt == fieldModificationType || fmt == FieldModificationType.UNKNOWN || fmt == FieldModificationType.METHOD_CALL) returnSet.Add(method); } return returnSet; }
public FloatModification(int field, float modification, bool idkbruh) : base(field) { _modification = modification; _type = idkbruh ? FieldModificationType.RealZeroToOne : FieldModificationType.Real; }
/// <summary> /// Checks whether there are any looping requireements based on looping threshold and enhances /// the sequence accordingly. Applies only for INCREMENT and DECREMENT field modification types /// </summary> /// <param name="pucls"></param> /// <param name="p"></param> private void CheckNEnhanceForLooping(PersistentUncoveredLocationStore pucls, int fitnessval, FieldModificationType fmt, SafeList<Field> culpritFields) { if (fmt != FieldModificationType.INCREMENT && fmt != FieldModificationType.DECREMENT) return; //Not even a single execution happened on this location. if (fitnessval == Int32.MaxValue) return; var field = culpritFields[0]; FieldStore fs; if (!this.pmd.FieldDictionary.TryGetValue(field, out fs)) return; Dictionary<string, Method> writeMethods = new Dictionary<string, Method>(); foreach (var mset in fs.WriteMethods.Values) { foreach (var m in mset) { var sig = MethodOrFieldAnalyzer.GetMethodSignature(m); writeMethods.Add(sig, m); } } foreach (var seq in pucls.SuggestedMethodSequences) { string loop_method; if (!this.IsEligibleForLooping(seq, field, writeMethods, fs, out loop_method)) continue; pucls.LoopingFeatureApplied = true; this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "LoopingFeature", "Applying looping feature on method: " + loop_method + " (" + (fitnessval - 1) + ")"); for (int count = 1; count < fitnessval; count++) seq.Sequence.Add(loop_method); } }
/// <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> /// OBSOLETE: /// </summary> /// <param name="termManager"></param> /// <param name="left"></param> /// <param name="right"></param> /// <param name="binOp"></param> /// <param name="bNegated"></param> /// <param name="culpritFields"></param> /// <param name="completeTerm"></param> /// <param name="fmt"></param> /// <param name="fitnessval"></param> private void handleNoConstantsInTerm(TermManager termManager, Term left, Term right, BinaryOperator binOp, bool bNegated, SafeList<Field> culpritFields, Term completeTerm, out FieldModificationType fmt, out int fitnessval) { fmt = FieldModificationType.UNKNOWN; //Term termUnderAnalysis = null; //Term otherTerm = null; //Field instanceField; //if (termManager.TryGetInstanceField(left, out instanceField) && culpritFields.Contains(instanceField)) //{ // termUnderAnalysis = left; // otherTerm = right; //} //else //{ // if (termManager.TryGetInstanceField(right, out instanceField)) // if (culpritFields.Contains(instanceField)) // { // termUnderAnalysis = right; // otherTerm = left; // } //} //if (termUnderAnalysis == null) // return; //object value; //if (termManager.TryGetObject(left, out value)) //{ // if (value == null && binOp == BinaryOperator.Ceq) // { // fmt = bNegated ? FieldModificationType.NON_NULL_SET : FieldModificationType.NULL_SET; // } // else if (value is int || value is Int16 || value is Int32 || value is Int64) // { // fmt = FieldModificationType.INCREMENT; //TODO: Needs to get actual values and decide based on that // } //} else if (termManager.TryGetObject(right, out value)) //{ // if (value == null && binOp == BinaryOperator.Ceq) // { // fmt = bNegated ? FieldModificationType.NON_NULL_SET : FieldModificationType.NULL_SET; // } // else if (value is int || value is Int16 || value is Int32 || value is Int64) // { // fmt = FieldModificationType.INCREMENT; //TODO: Needs to get actual values and decide based on that // } //} //TODO: A worst fix to proceed further fitnessval = Int32.MaxValue; if (culpritFields.Count == 0) return; var culprittype = culpritFields[0].Type; if (culprittype.IsReferenceType) fmt = FieldModificationType.NON_NULL_SET; else { var typestr = culprittype.ToString(); if (typestr == "System.Boolean") fmt = FieldModificationType.TRUE_SET; else if (typestr == "System.Int32" || typestr == "System.Int64" || typestr == "System.Int16") { SafeDictionary<Field, FieldValueHolder> fieldValues; //TermSolver.SolveTerm(this.ter, completeTerm, out fieldValues); fmt = FieldModificationType.INCREMENT; } } }
/// <summary> /// OBSOLETE: Handles a scenario where there is a term in the condition /// </summary> /// <param name="left"></param> /// <param name="right"></param> /// <param name="binOp"></param> /// <param name="fmt"></param> private void handleAConstantInTerm(TermManager termManager, Term left, Term right, BinaryOperator binOp, bool bNegated, SafeDictionary <Field, FieldValueHolder> fieldValues, Field culpritField, out FieldModificationType fmt, out int fitnessval) { fitnessval = Int32.MaxValue; fmt = FieldModificationType.UNKNOWN; Term non_constant_term = null; Term constant_term = null; bool bleftRightMaintainted = true; if (termManager.IsValue(left)) { non_constant_term = right; constant_term = left; bleftRightMaintainted = true; } else if (termManager.IsValue(right)) { non_constant_term = left; constant_term = right; bleftRightMaintainted = false; } int value; if (termManager.TryGetI4Constant(constant_term, out value)) { fmt = FieldModificationType.INCREMENT; FieldValueHolder fvh; if (fieldValues.TryGetValue(culpritField, out fvh)) { int non_constant_field_value = fvh.intValue; //TODO: Assuming that the fieldType is Int32 if (bleftRightMaintainted) { fitnessval = FitnessMeasure.ComputeFitnessValue(this.host, binOp, value, non_constant_field_value, bNegated); } else { fitnessval = FitnessMeasure.ComputeFitnessValue(this.host, binOp, non_constant_field_value, value, bNegated); } } else { this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "fitness measure", "Failed to retrieve value for field " + culpritField.ToString()); } } else if (termManager.IsDefaultValue(constant_term)) { if (binOp == BinaryOperator.Ceq) { if (culpritField.Type.ToString() == "System.Boolean") { fmt = bNegated ? FieldModificationType.TRUE_SET : FieldModificationType.FALSE_SET; } else { fmt = bNegated ? FieldModificationType.NON_NULL_SET : FieldModificationType.NULL_SET; } } } Term objectValue; ObjectProperty objectProperty; if (termManager.TryGetObjectProperty(constant_term, out objectValue, out objectProperty)) { //TODO??? How to handle this scenario? } }
/// <summary> /// Checks whether fitness strategy matters or not. Since, fitness /// is required only for integers, but not for all kinds of types such /// as boolean or non-null /// </summary> /// <returns></returns> private bool IsFitnessRequired(FieldModificationType fmt) { switch (fmt) { case FieldModificationType.INCREMENT: case FieldModificationType.DECREMENT: case FieldModificationType.INCREMENT_ONE: return true; case FieldModificationType.FALSE_SET: case FieldModificationType.TRUE_SET: case FieldModificationType.NULL_SET: case FieldModificationType.NON_NULL_SET: return false; default: return false; } }
/// <summary> /// OBSOLETE: /// </summary> /// <param name="termManager"></param> /// <param name="left"></param> /// <param name="right"></param> /// <param name="binOp"></param> /// <param name="bNegated"></param> /// <param name="culpritFields"></param> /// <param name="completeTerm"></param> /// <param name="fmt"></param> /// <param name="fitnessval"></param> private void handleNoConstantsInTerm(TermManager termManager, Term left, Term right, BinaryOperator binOp, bool bNegated, SafeList <Field> culpritFields, Term completeTerm, out FieldModificationType fmt, out int fitnessval) { fmt = FieldModificationType.UNKNOWN; //Term termUnderAnalysis = null; //Term otherTerm = null; //Field instanceField; //if (termManager.TryGetInstanceField(left, out instanceField) && culpritFields.Contains(instanceField)) //{ // termUnderAnalysis = left; // otherTerm = right; //} //else //{ // if (termManager.TryGetInstanceField(right, out instanceField)) // if (culpritFields.Contains(instanceField)) // { // termUnderAnalysis = right; // otherTerm = left; // } //} //if (termUnderAnalysis == null) // return; //object value; //if (termManager.TryGetObject(left, out value)) //{ // if (value == null && binOp == BinaryOperator.Ceq) // { // fmt = bNegated ? FieldModificationType.NON_NULL_SET : FieldModificationType.NULL_SET; // } // else if (value is int || value is Int16 || value is Int32 || value is Int64) // { // fmt = FieldModificationType.INCREMENT; //TODO: Needs to get actual values and decide based on that // } //} else if (termManager.TryGetObject(right, out value)) //{ // if (value == null && binOp == BinaryOperator.Ceq) // { // fmt = bNegated ? FieldModificationType.NON_NULL_SET : FieldModificationType.NULL_SET; // } // else if (value is int || value is Int16 || value is Int32 || value is Int64) // { // fmt = FieldModificationType.INCREMENT; //TODO: Needs to get actual values and decide based on that // } //} //TODO: A worst fix to proceed further fitnessval = Int32.MaxValue; if (culpritFields.Count == 0) { return; } var culprittype = culpritFields[0].Type; if (culprittype.IsReferenceType) { fmt = FieldModificationType.NON_NULL_SET; } else { var typestr = culprittype.ToString(); if (typestr == "System.Boolean") { fmt = FieldModificationType.TRUE_SET; } else if (typestr == "System.Int32" || typestr == "System.Int64" || typestr == "System.Int16") { SafeDictionary <Field, FieldValueHolder> fieldValues; //TermSolver.SolveTerm(this.ter, completeTerm, out fieldValues); fmt = FieldModificationType.INCREMENT; } } }
public static TypeEx AddFieldToMethodEffects(IPexComponent host, TypeEx declaringType, SafeSet <string> res, SafeSet <string> directSetFields, SafeDictionary <string, FieldModificationType> modificationTypeDic, OpCode prevOpcode, Field field, TypeEx fieldType) { SafeDebug.AssumeNotNull(field, "field"); SafeDebug.Assume(!field.IsStatic, "!field.IsStatic"); TypeEx fieldDeclaringType; //The following check ensures that the field belongs to this class //or its base classes if (field.TryGetDeclaringType(out fieldDeclaringType) && declaringType.IsAssignableTo(fieldDeclaringType)) { res.Add(field.ShortName); FieldModificationType fmt = FieldModificationType.UNKNOWN; if (fieldType == SystemTypes.Int32 || fieldType == SystemTypes.Int64 || fieldType == SystemTypes.Int16) { if (prevOpcode == OpCodes.Add) { fmt = FieldModificationType.INCREMENT; } else if (prevOpcode == OpCodes.Sub) { fmt = FieldModificationType.DECREMENT; } else if (prevOpcode == OpCodes.Call || prevOpcode == OpCodes.Calli || prevOpcode == OpCodes.Callvirt) { fmt = FieldModificationType.METHOD_CALL; } else { host.Log.LogWarning(WikiTopics.MissingWikiTopic, "fieldmodificationtype", "Encountered unknown modification type for integer type " + prevOpcode); } } else { if (field.Type.IsReferenceType) { if (prevOpcode == OpCodes.Ldnull) { fmt = FieldModificationType.NULL_SET; } else if (prevOpcode == OpCodes.Newarr || prevOpcode == OpCodes.Newobj) { fmt = FieldModificationType.NON_NULL_SET; } else if (LdArgOpCodes.Contains(prevOpcode)) { fmt = FieldModificationType.NON_NULL_SET; } else { fmt = FieldModificationType.METHOD_CALL; //A method call is invoked on this field, which updates this field } } else if (fieldType == SystemTypes.Bool) { if (prevOpcode == OpCodes.Ldc_I4_0) { fmt = FieldModificationType.FALSE_SET; } else if (prevOpcode == OpCodes.Ldc_I4_1) { fmt = FieldModificationType.TRUE_SET; } else { host.Log.LogWarning(WikiTopics.MissingWikiTopic, "fieldmodificationtype", "Encountered unknown modification type for boolean type " + prevOpcode); } } } //Store the value of fmt. Sometimes, the same field //can be modified in different ways within the method, for example //setting a boolean field to both true or false. In that case, the modification //type is left as unknown FieldModificationType prevFMT; if (modificationTypeDic.TryGetValue(field.ShortName, out prevFMT)) { //There is some entry for this field if (prevFMT != FieldModificationType.UNKNOWN && prevFMT != fmt) { modificationTypeDic[field.ShortName] = FieldModificationType.UNKNOWN; } } else { modificationTypeDic[field.ShortName] = fmt; } //A heuristic based approach for aliasing analysis for checking whether the field is directly //assigned any parameters if (LdArgOpCodes.Contains(prevOpcode)) { directSetFields.Add(field.ShortName); } } return(fieldDeclaringType); }
/// <summary> /// OBSOLETE: Handles a scenario where there is a term in the condition /// </summary> /// <param name="left"></param> /// <param name="right"></param> /// <param name="binOp"></param> /// <param name="fmt"></param> private void handleAConstantInTerm(TermManager termManager, Term left, Term right, BinaryOperator binOp, bool bNegated, SafeDictionary<Field, FieldValueHolder> fieldValues, Field culpritField, out FieldModificationType fmt, out int fitnessval) { fitnessval = Int32.MaxValue; fmt = FieldModificationType.UNKNOWN; Term non_constant_term = null; Term constant_term = null; bool bleftRightMaintainted = true; if (termManager.IsValue(left)) { non_constant_term = right; constant_term = left; bleftRightMaintainted = true; } else if (termManager.IsValue(right)) { non_constant_term = left; constant_term = right; bleftRightMaintainted = false; } int value; if (termManager.TryGetI4Constant(constant_term, out value)) { fmt = FieldModificationType.INCREMENT; FieldValueHolder fvh; if (fieldValues.TryGetValue(culpritField, out fvh)) { int non_constant_field_value = fvh.intValue; //TODO: Assuming that the fieldType is Int32 if (bleftRightMaintainted) fitnessval = FitnessMeasure.ComputeFitnessValue(this.host, binOp, value, non_constant_field_value, bNegated); else fitnessval = FitnessMeasure.ComputeFitnessValue(this.host, binOp, non_constant_field_value, value, bNegated); } else this.host.Log.LogWarning(WikiTopics.MissingWikiTopic, "fitness measure", "Failed to retrieve value for field " + culpritField.ToString()); } else if (termManager.IsDefaultValue(constant_term)) { if (binOp == BinaryOperator.Ceq) { if (culpritField.Type.ToString() == "System.Boolean") { fmt = bNegated ? FieldModificationType.TRUE_SET : FieldModificationType.FALSE_SET; } else fmt = bNegated ? FieldModificationType.NON_NULL_SET : FieldModificationType.NULL_SET; } } Term objectValue; ObjectProperty objectProperty; if (termManager.TryGetObjectProperty(constant_term, out objectValue, out objectProperty)) { //TODO??? How to handle this scenario? } }