Permalink
Browse files

Use test assembly helpers methods as target's matching methods

Also removed unnecessary/inefficient 'force' step which prevented
to use some tests when a mutated method had tests that call it
directly (not via another method)

Change-Id: I3d4b72b2086bd7f76c4430f7c7d1ffcf05147307
  • Loading branch information...
1 parent bba6c36 commit a4c1a10e36b2d08a32108bb0066f573702bfe50f @TonyRoussel TonyRoussel committed Aug 3, 2016
@@ -1,4 +1,4 @@
-#region Copyright & licence
+#region Copyright & licence
// This file is part of NinjaTurtles.
//
@@ -131,9 +131,7 @@ public override bool Validate()
return false;
}
}
- _testMethods =
- GetMethodsNameWithAttributesFromAssembly(AssemblyDefinition.ReadAssembly(_testAssemblyLocation),
- new[] {"TestAttribute", "TestCaseAttribute"});
+ _testMethods = TestUtils.NUnit.GetTestsNameDictionnaryTranslation(AssemblyDefinition.ReadAssembly(_testAssemblyLocation));
if (_testMethods.Count == 0)
{
using (new OutputWriterErrorHighlight())
@@ -491,40 +489,5 @@ private bool RunAllMutationTestsInAssembly()
failures);
return tests > 0 && failures == 0;
}
-
- private IDictionary<string, string> GetMethodsNameWithAttributesFromAssembly(AssemblyDefinition assembly,
- IList<string> searchedAttributes)
- {
- var methodsWithAttributes = new Dictionary<string, string>();
- foreach (var type in assembly.MainModule.Types)
- GetMethodsNameWithAttributesFromType(type, searchedAttributes, methodsWithAttributes);
- return methodsWithAttributes;
- }
-
- private void GetMethodsNameWithAttributesFromType(TypeDefinition type, IList<string> searchedAttributes, IDictionary<string, string> matchingMethods)
- {
- foreach (var method in type.Methods)
- {
- if (!MethodHasAttributes(method, searchedAttributes))
- continue;
- var methodName = method.Name;
- var methodNunitName = String.Format("{0}.{1}", type.FullName.Replace("/", "+"), methodName);
- if (matchingMethods.ContainsKey(methodName))
- continue;
- matchingMethods.Add(methodName, methodNunitName);
- }
- if (type.NestedTypes == null)
- return;
- foreach (var nestedType in type.NestedTypes)
- GetMethodsNameWithAttributesFromType(nestedType, searchedAttributes, matchingMethods);
- }
-
- private static bool MethodHasAttributes(MethodDefinition method, IList<string> searchedAttributes)
- {
- var attributesTypes = method.CustomAttributes.Select(a => a.AttributeType).ToList();
- if (attributesTypes.Any(at => searchedAttributes.Contains(at.Name)))
- return true;
- return false;
- }
}
}
@@ -146,6 +146,7 @@ private List<MethodReference> MethodDiscovery()
_module.LoadDebugInformation();
var matchingMethods = new List<MethodReference>();
AddMethod(_method, matchingMethods);
+ FindAlternativeMethodsFromNUnitAssembly(_testAssembly, matchingMethods);
_originalOffsets = _method.Body.Instructions.Select(i => i.Offset).ToArray();
_report = new MutationTestingReport(_method);
return matchingMethods;
@@ -368,15 +369,11 @@ private void AddMethodsForInterfaces(MethodDefinition targetMethod, List<MethodR
}
}
- private ISet<string> GetMatchingTestsFromTree(MethodDefinition targetmethod, IList<MethodReference> matchingMethods, IDictionary<string, string> testMethods, bool force = false)
+ private ISet<string> GetMatchingTestsFromTree(MethodDefinition targetmethod, IList<MethodReference> matchingMethods, IDictionary<string, string> testMethods)
{
ISet<string> result = new HashSet<string>();
foreach (var type in _testAssembly.MainModule.Types)
- AddTestsForType(targetmethod, matchingMethods, force, type, testMethods, result);
- if (!force && result.Count == 0)
- {
- result = GetMatchingTestsFromTree(targetmethod, matchingMethods, testMethods, true);
- }
+ AddTestsForType(targetmethod, matchingMethods, type, testMethods, result);
if (result.Count == 0)
{
Console.WriteLine("No matching tests found.");
@@ -385,11 +382,11 @@ private ISet<string> GetMatchingTestsFromTree(MethodDefinition targetmethod, ILi
return result;
}
- private void AddTestsForType(MethodDefinition targetmethod, IList<MethodReference> matchingMethods, bool force, TypeDefinition type, IDictionary<string, string> testMethods, ISet<string> result)
+ private void AddTestsForType(MethodDefinition targetmethod, IList<MethodReference> matchingMethods, TypeDefinition type, IDictionary<string, string> testMethods, ISet<string> result)
{
- String targetType = targetmethod.DeclaringType.FullName;
+ var targetType = targetmethod.DeclaringType.FullName;
- foreach (MethodDefinition method in type.Methods.Where(m => m.HasBody))
+ foreach (var method in type.Methods.Where(m => m.HasBody))
{
var methodName = method.Name;
if (methodName.StartsWith("<"))
@@ -399,27 +396,22 @@ private void AddTestsForType(MethodDefinition targetmethod, IList<MethodReferenc
}
if (!testMethods.Keys.Contains(methodName))
continue;
- if (!force && !DoesMethodReferenceType(method, targetType))
- continue;
- if (!MethodCallTargetDirectOrIndirect(method, matchingMethods))
+ if (!DoesMethodReferenceType(method, targetType) && !AtLeastOneMethodIsCalledFromMethod(method, matchingMethods))
continue;
var methodFinalName = testMethods[methodName];
result.Add(methodFinalName);
}
if (type.NestedTypes == null)
return;
- foreach (TypeDefinition typeDefinition in type.NestedTypes)
- AddTestsForType(targetmethod, matchingMethods, force, typeDefinition, testMethods, result);
+ foreach (var typeDefinition in type.NestedTypes)
+ AddTestsForType(targetmethod, matchingMethods, typeDefinition, testMethods, result);
}
- private bool MethodCallTargetDirectOrIndirect(MethodDefinition methodDefinition, IList<MethodReference> matchingMethods)
+ private bool AtLeastOneMethodIsCalledFromMethod(MethodDefinition methodDefinition, IList<MethodReference> matchingMethods)
{
- foreach (Instruction instruction in methodDefinition.Body.Instructions)
+ foreach (var instruction in methodDefinition.Body.Instructions)
{
- if (!(instruction.OpCode == OpCodes.Call // Call method
- || instruction.OpCode == OpCodes.Callvirt // Call a method associated with an object
- || instruction.OpCode == OpCodes.Newobj // Allocate an uninitialized object or value type and call ctor
- || instruction.OpCode == OpCodes.Ldftn)) // Push a pointer to a method referenced by method, on the stack
+ if (!IsCallStatement(instruction))
continue;
var operandAsMethodReference = instruction.Operand as MethodReference;
if (operandAsMethodReference == null)
@@ -445,10 +437,7 @@ private static bool DoesMethodReferenceType(MethodDefinition method, string targ
bool typeUsed = false;
foreach (var instruction in method.Body.Instructions)
{
- if (instruction.OpCode == OpCodes.Call
- || instruction.OpCode == OpCodes.Callvirt
- || instruction.OpCode == OpCodes.Newobj
- || instruction.OpCode == OpCodes.Ldftn)
+ if (IsCallStatement(instruction))
{
var reference = (MethodReference)instruction.Operand;
var declaringType = reference.DeclaringType;
@@ -501,10 +490,7 @@ private void AddCallingMethodsForType(MethodReference targetMethod, List<MethodR
foreach (var method in type.Methods.Where(m => m.HasBody))
foreach (var instruction in method.Body.Instructions)
{
- if (instruction.OpCode == OpCodes.Call
- || instruction.OpCode == OpCodes.Callvirt
- || instruction.OpCode == OpCodes.Newobj
- || instruction.OpCode == OpCodes.Ldftn)
+ if (IsCallStatement(instruction))
{
var reference = (MethodReference)instruction.Operand;
if (_comparer.Equals(reference, targetMethod)
@@ -528,6 +514,32 @@ private void AddCallingMethodsForType(MethodReference targetMethod, List<MethodR
}
}
+ private void FindAlternativeMethodsFromNUnitAssembly(AssemblyDefinition assembly, List<MethodReference> matchingMethods)
+ {
+ var candidatesMethods = assembly.MainModule.Types.SelectMany(type => type.Methods.Where(m => m.HasBody && !TestUtils.Filtering.IsTestMethod(m))).ToList();
+ FindAlternativeMethodsFromCandidatesMethods(candidatesMethods, matchingMethods);
+ }
+
+ private void FindAlternativeMethodsFromCandidatesMethods(List<MethodDefinition> candidatesMethods, List<MethodReference> matchingMethods)
+ {
+ Func<MethodDefinition, bool> isNotRegisterAndIsAlternative = method => !matchingMethods.Contains(method) && AtLeastOneMethodIsCalledFromMethod(method, matchingMethods);
+
+ var currentAlternatives = candidatesMethods.Where(isNotRegisterAndIsAlternative);
+ while (currentAlternatives.Any())
+ {
+ matchingMethods.AddRange(currentAlternatives);
+ currentAlternatives = candidatesMethods.Where(isNotRegisterAndIsAlternative);
+ }
+ }
+
+ private static bool IsCallStatement(Instruction instruction)
+ {
+ return instruction.OpCode == OpCodes.Call
+ || instruction.OpCode == OpCodes.Callvirt
+ || instruction.OpCode == OpCodes.Newobj
+ || instruction.OpCode == OpCodes.Ldftn;
+ }
+
private class MethodReferenceComparer : IEqualityComparer<MethodReference>
{
public bool Equals(MethodReference x, MethodReference y)
@@ -641,6 +653,6 @@ public override void WriteReport(MutationTestingReport report, string fileName)
}
}
}
- }
+ }
}
@@ -113,6 +113,7 @@
<Compile Include="Reporting\SequencePoint.cs" />
<Compile Include="Reporting\SourceFile.cs" />
<Compile Include="Reporting\Line.cs" />
+ <Compile Include="TestUtils.cs" />
<Compile Include="Turtles\ArithmeticOperatorTurtle.cs" />
<Compile Include="MutantMetaData.cs" />
<Compile Include="Turtles\BranchConditionTurtle.cs" />
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Mono.Cecil;
+
+namespace NinjaTurtlesMutation
+{
+ public static class TestUtils
+ {
+ public static class Attributes
+ {
+ public static List<string> Tests = new List<string> {"TestAttribute", "TestCaseAttribute"};
+ }
+
+ public static class Filtering
+ {
+ public static bool IsTestMethod(MethodDefinition method)
+ {
+ return MethodHasAttributes(method, Attributes.Tests);
+ }
+ }
+
+ public static class NUnit
+ {
+ public static IDictionary<string, string> GetTestsNameDictionnaryTranslation(AssemblyDefinition assembly)
+ {
+ var methodsWithAttributes = new Dictionary<string, string>();
+ foreach (var type in assembly.MainModule.Types)
+ GetMethodsNameWithAttributesFromType(type, Attributes.Tests, methodsWithAttributes);
+ return methodsWithAttributes;
+ }
+
+ private static void GetMethodsNameWithAttributesFromType(TypeDefinition type, IList<string> searchedAttributes, IDictionary<string, string> matchingMethods)
+ {
+ foreach (var method in type.Methods)
+ {
+ if (!MethodHasAttributes(method, searchedAttributes))
+ continue;
+ var methodName = method.Name;
+ var methodNunitName = String.Format("{0}.{1}", type.FullName.Replace("/", "+"), methodName);
+ if (matchingMethods.ContainsKey(methodName))
+ continue;
+ matchingMethods.Add(methodName, methodNunitName);
+ }
+ if (type.NestedTypes == null)
+ return;
+ foreach (var nestedType in type.NestedTypes)
+ GetMethodsNameWithAttributesFromType(nestedType, searchedAttributes, matchingMethods);
+ }
+ }
+
+ private static bool MethodHasAttributes(MethodDefinition method, IEnumerable<string> searchedAttributes)
+ {
+ var attributesTypes = method.CustomAttributes.Select(a => a.AttributeType.Name).ToList();
+ return attributesTypes.Intersect(searchedAttributes).Any();
+ }
+ }
+}

0 comments on commit a4c1a10

Please sign in to comment.