diff --git a/src/Stryker.Core/Stryker.Core.UnitTest/Mutants/CsharpMutantOrchestratorTests.cs b/src/Stryker.Core/Stryker.Core.UnitTest/Mutants/CsharpMutantOrchestratorTests.cs index 78551548c6..1fed4d24c0 100644 --- a/src/Stryker.Core/Stryker.Core.UnitTest/Mutants/CsharpMutantOrchestratorTests.cs +++ b/src/Stryker.Core/Stryker.Core.UnitTest/Mutants/CsharpMutantOrchestratorTests.cs @@ -6,14 +6,14 @@ using Stryker.Core.Options; using Xunit; -namespace Stryker.Core.UnitTest.Mutants +namespace Stryker.Core.UnitTest.Mutants; + +public class CsharpMutantOrchestratorTests : MutantOrchestratorTestsBase { - public class CsharpMutantOrchestratorTests : MutantOrchestratorTestsBase + [Fact] + public void ShouldNotMutateEmptyInterfaces() { - [Fact] - public void ShouldNotMutateEmptyInterfaces() - { - var source = @"using System; + var source = @"using System; using System.Collections.Generic; using System.Text; namespace StrykerNet.UnitTest.Mutants.TestResources @@ -26,7 +26,7 @@ interface TestClass } }"; - var expected = @"using System; + var expected = @"using System; using System.Collections.Generic; using System.Text; namespace StrykerNet.UnitTest.Mutants.TestResources @@ -38,13 +38,13 @@ interface TestClass void MethodA(); } }"; - ShouldMutateSourceToExpected(source, expected); - } + ShouldMutateSourceToExpected(source, expected); + } - [Fact] - public void ShouldMutateDefaultImplementationInterfaces() - { - var source = @"using System; + [Fact] + public void ShouldMutateDefaultImplementationInterfaces() + { + var source = @"using System; using System.Collections.Generic; using System.Text; namespace StrykerNet.UnitTest.Mutants.TestResources @@ -59,7 +59,7 @@ void MethodA() { } }"; - var expected = @"using System; + var expected = @"using System; using System.Collections.Generic; using System.Text; namespace StrykerNet.UnitTest.Mutants.TestResources @@ -73,99 +73,99 @@ void MethodA() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ }} } }"; - ShouldMutateSourceToExpected(source, expected); - } + ShouldMutateSourceToExpected(source, expected); + } - [Fact] - public void ShouldMutateBlockStatements() + [Fact] + public void ShouldMutateBlockStatements() + { + var options = new StrykerOptions { - var options = new StrykerOptions - { - MutationLevel = MutationLevel.Complete, - OptimizationMode = OptimizationModes.CoverageBasedTest, - }; - _target = new CsharpMutantOrchestrator(new MutantPlacer(_injector), options: options); + MutationLevel = MutationLevel.Complete, + OptimizationMode = OptimizationModes.CoverageBasedTest, + }; + _target = new CsharpMutantOrchestrator(new MutantPlacer(_injector), options: options); - string source = @"private void Move() + string source = @"private void Move() { ; }"; - string expected = @"private void Move() + string expected = @"private void Move() {if(StrykerNamespace.MutantControl.IsActive(0)){}else { ; }}"; - ShouldMutateSourceInClassToExpected(source, expected); + ShouldMutateSourceInClassToExpected(source, expected); - source = @"private int Move() + source = @"private int Move() { ; }"; - expected = @"private int Move() + expected = @"private int Move() {if(StrykerNamespace.MutantControl.IsActive(1)){}else { ; }}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldAddReturnDefaultToOperator() - { - string source = @"public static string operator+ (TestClass value, TestClass other) + [Fact] + public void ShouldAddReturnDefaultToOperator() + { + string source = @"public static string operator+ (TestClass value, TestClass other) { while(true) return value; }"; - string expected = @"public static string operator+ (TestClass value, TestClass other) + string expected = @"public static string operator+ (TestClass value, TestClass other) {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ while((StrykerNamespace.MutantControl.IsActive(2)?!(true):(StrykerNamespace.MutantControl.IsActive(1)?false:true))) return value; }return default(string);}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldAddReturnDefaultToArrowExpressionOperator() - { - string source = - @"public static int operator+ (TestClass value, TestClass other) => Sub(out var x, """")?1:2;"; - string expected = - @"public static int operator+ (TestClass value, TestClass other) {if(StrykerNamespace.MutantControl.IsActive(0)){return!(Sub(out var x, """"))?1:2;}else{return Sub(out var x, (StrykerNamespace.MutantControl.IsActive(1)?""Stryker was here!"":""""))?1:2;}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + [Fact] + public void ShouldAddReturnDefaultToArrowExpressionOperator() + { + string source = + @"public static int operator+ (TestClass value, TestClass other) => Sub(out var x, """")?1:2;"; + string expected = + @"public static int operator+ (TestClass value, TestClass other) {if(StrykerNamespace.MutantControl.IsActive(0)){return!(Sub(out var x, """"))?1:2;}else{return Sub(out var x, (StrykerNamespace.MutantControl.IsActive(1)?""Stryker was here!"":""""))?1:2;}}"; + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldNotAddReturnDefaultToDestructor() - { - var source = @"~TestClass(){;}"; - var expected = @"~TestClass(){if(StrykerNamespace.MutantControl.IsActive(0)){}else{;}}"; + [Fact] + public void ShouldNotAddReturnDefaultToDestructor() + { + var source = @"~TestClass(){;}"; + var expected = @"~TestClass(){if(StrykerNamespace.MutantControl.IsActive(0)){}else{;}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldProperlyMutatePrefixUnitaryExpressionStatement() - { - const string Source = @"void Method(int x) {++x;}"; - const string Expected = @"void Method(int x) {if(StrykerNamespace.MutantControl.IsActive(0)){}else{if(StrykerNamespace.MutantControl.IsActive(1)){;}else{if(StrykerNamespace.MutantControl.IsActive(2)){--x;}else{++x;}}}}}"; + [Fact] + public void ShouldProperlyMutatePrefixUnitaryExpressionStatement() + { + const string Source = @"void Method(int x) {++x;}"; + const string Expected = @"void Method(int x) {if(StrykerNamespace.MutantControl.IsActive(0)){}else{if(StrykerNamespace.MutantControl.IsActive(1)){;}else{if(StrykerNamespace.MutantControl.IsActive(2)){--x;}else{++x;}}}}}"; - ShouldMutateSourceInClassToExpected(Source, Expected); - } + ShouldMutateSourceInClassToExpected(Source, Expected); + } - [Fact] - public void ShouldMutateExpressionBodiedLocalFunction() - { - string source = @"void TestMethod(){ + [Fact] + public void ShouldMutateExpressionBodiedLocalFunction() + { + string source = @"void TestMethod(){ int SomeMethod() => (true && SomeOtherMethod(out var x)) ? x : 5; }"; - string expected = @"void TestMethod(){if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + string expected = @"void TestMethod(){if(StrykerNamespace.MutantControl.IsActive(0)){}else{ int SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(1)){return!((true && SomeOtherMethod(out var x)) )? x : 5;}else{if(StrykerNamespace.MutantControl.IsActive(2)){return(true || SomeOtherMethod(out var x)) ? x : 5;}else{return ((StrykerNamespace.MutantControl.IsActive(3)?false:true )&& SomeOtherMethod(out var x)) ? x : 5;}}};}} }"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void IfStatementsShouldBeNested() - { - string source = @"void TestMethod() + [Fact] + public void IfStatementsShouldBeNested() + { + string source = @"void TestMethod() { int i = 0; if (i + 8 == 8) @@ -200,7 +200,7 @@ private bool Out(out string test) { return true; }"; - string expected = @"void TestMethod() + string expected = @"void TestMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{if(StrykerNamespace.MutantControl.IsActive(19)){ int i = 0; if (i + 8 == 8) @@ -294,13 +294,13 @@ private bool Out(out string test) return (StrykerNamespace.MutantControl.IsActive(23)?false:true); }return default(bool);}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldNotLeakMutationsToNextMethodOrProperty() - { - string source = @"public static class ExampleExtension + [Fact] + public void ShouldNotLeakMutationsToNextMethodOrProperty() + { + string source = @"public static class ExampleExtension { private static string[] tabs = { ""tab1"", ""tab2""}; @@ -316,7 +316,7 @@ public List Collection } } }"; - string expected = @"public static class ExampleExtension + string expected = @"public static class ExampleExtension { private static string[] tabs = { (StrykerNamespace.MutantControl.IsActive(1)?"""":""tab1""), (StrykerNamespace.MutantControl.IsActive(2)?"""":""tab2"")}; @@ -339,13 +339,13 @@ public List Collection } }"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldNotMutateWhenDeclaration() - { - string source = @"void TestMethod() + [Fact] + public void ShouldNotMutateWhenDeclaration() + { + string source = @"void TestMethod() { int i = 0; var result = Out(out var test) ? test : """"; @@ -354,7 +354,7 @@ private bool Out(out string test) { return true; }"; - string expected = @"void TestMethod() + string expected = @"void TestMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{if(StrykerNamespace.MutantControl.IsActive(1)){ int i = 0; var result = !(Out(out var test) )? test : """"; @@ -378,13 +378,13 @@ private bool Out(out string test) } "; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateWhenDeclarationInInnerScope() - { - string source = @"void TestMethod() + [Fact] + public void ShouldMutateWhenDeclarationInInnerScope() + { + string source = @"void TestMethod() { int i = 0; var result = Out(i, (x) => { int.TryParse(""3"", out int y); return x == y;} ) ? i.ToString() : """"; @@ -394,7 +394,7 @@ private bool Out(int test, Funclambda ) return true; } "; - string expected = @"void TestMethod() + string expected = @"void TestMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ int i = 0; var result = (StrykerNamespace.MutantControl.IsActive(1)?!(Out(i, (x) => { int.TryParse(""3"", out int y); return x == y;} ) ):Out(i, (x) => {if(StrykerNamespace.MutantControl.IsActive(2)){}else{ int.TryParse((StrykerNamespace.MutantControl.IsActive(3)?"""":""3""), out int y); return (StrykerNamespace.MutantControl.IsActive(4)?x != y:x == y);} return default;}) )? i.ToString() : (StrykerNamespace.MutantControl.IsActive(5)?""Stryker was here!"":""""); @@ -411,50 +411,50 @@ private bool Out(int test, Func lambda) return default(bool); }"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateWhenDeclarationInInnerScopeInExpressionForm() - { - var source = @"void TestMethod() + [Fact] + public void ShouldMutateWhenDeclarationInInnerScopeInExpressionForm() + { + var source = @"void TestMethod() { int i = 0; var result = Out(i, (x) => int.TryParse(""3"", out int y) ? true : false); } "; - var expected = @"void TestMethod() + var expected = @"void TestMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ int i = 0; var result = Out(i, (x) => {if(StrykerNamespace.MutantControl.IsActive(1)){return!(int.TryParse(""3"", out int y) )? true : false;}else{return int.TryParse((StrykerNamespace.MutantControl.IsActive(2)?"""":""3""), out int y) ? (StrykerNamespace.MutantControl.IsActive(3)?false:true ): (StrykerNamespace.MutantControl.IsActive(4)?true:false);}}); }} "; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateLambdaAndAddDefaultReturn() - { - var source = @"void TestMethod() + [Fact] + public void ShouldMutateLambdaAndAddDefaultReturn() + { + var source = @"void TestMethod() { int i = 0; var result = Out(i, (x) => {if (x>2) return false; i++;}); } "; - var expected = @"void TestMethod() + var expected = @"void TestMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ int i = 0; var result = Out(i, (x) => {if(StrykerNamespace.MutantControl.IsActive(1)){}else{if ((StrykerNamespace.MutantControl.IsActive(4)?!(x>2):(StrykerNamespace.MutantControl.IsActive(3)?x>=2:(StrykerNamespace.MutantControl.IsActive(2)?x<2:x>2)))) return (StrykerNamespace.MutantControl.IsActive(5)?true:false); if(StrykerNamespace.MutantControl.IsActive(6)){;}else{if(StrykerNamespace.MutantControl.IsActive(7)){i--;}else{i++;}}}return default;});}} "; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateInsideStringDeclarationInsideLocalFunction() - { - var source = @"void TestMethod() + [Fact] + public void ShouldMutateInsideStringDeclarationInsideLocalFunction() + { + var source = @"void TestMethod() { string SomeLocalFunction() { @@ -462,7 +462,7 @@ string SomeLocalFunction() return $""test{1 + test3}""; }; }"; - var expected = @"void TestMethod() + var expected = @"void TestMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else { string SomeLocalFunction() {if(StrykerNamespace.MutantControl.IsActive(1)){}else { @@ -472,60 +472,75 @@ string SomeLocalFunction() }return default(string);}; }}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateConditionalExpressionProperly() - { - var source = @"void TestMethod() + [Fact] + public void ShouldMutateConditionalExpressionProperly() + { + var source = @"void TestMethod() { string SomeLocalFunction() { return string.Empty?.All(x => !string.IsEmpty(x)); }; }"; - var expected = @"void TestMethod() + var expected = @"void TestMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else { string SomeLocalFunction() {if(StrykerNamespace.MutantControl.IsActive(1)){}else { - return (StrykerNamespace.MutantControl.IsActive(3)?string.Empty?.Any(x => !string.IsEmpty(x)):(StrykerNamespace.MutantControl.IsActive(2)?""Stryker was here!"":string.Empty)?.All(x => (StrykerNamespace.MutantControl.IsActive(4)?string.IsEmpty(x):!string.IsEmpty(x)))); }return default(string);}; + return (StrykerNamespace.MutantControl.IsActive(3)?string.Empty?.Any(x => !string.IsEmpty(x)):(StrykerNamespace.MutantControl.IsActive(2)?""Stryker was here!"":string.Empty)?.All(x => (StrykerNamespace.MutantControl.IsActive(4)?string.IsEmpty(x):!string.IsEmpty(x)))); }return default(string);}; }}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } + [Fact] + public void ShouldMutateConditionalMemberAccessProperly() + { + var source = @"void TestMethod() { + var labelNode = myAttribute?.ArgumentList.Arguments.First()?.Expression; + return test?.Other()?.Count; + }"; + var expected = @"void TestMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + var labelNode = (StrykerNamespace.MutantControl.IsActive(1)?myAttribute?.ArgumentList.Arguments.FirstOrDefault()?.Expression:myAttribute?.ArgumentList.Arguments.First()?.Expression); + return (StrykerNamespace.MutantControl.IsActive(2)? test?.Other()?.Sum:test?.Other()?.Count); + }}"; - [Fact] - public void ShouldMutateConditionalExpressionOnArrayDeclaration() - { - var source = - @"public static IEnumerable Foo() => new int[] { }.ToArray()!.Any(x => x==1)?.OrderBy(e => e).ToList();"; - var expected = - @"public static IEnumerable Foo() => (StrykerNamespace.MutantControl.IsActive(2)?new int[] { }.ToArray()!.Any(x => x==1)?.OrderByDescending(e => e).ToList():(StrykerNamespace.MutantControl.IsActive(0)?new int[] { }.ToArray()!.All(x => x==1):new int[] { }.ToArray()!.Any(x => (StrykerNamespace.MutantControl.IsActive(1)?x!=1:x==1)))?.OrderBy(e => e).ToList());"; + ShouldMutateSourceInClassToExpected(source, expected); + } + - ShouldMutateSourceInClassToExpected(source, expected); - } + [Fact] + public void ShouldMutateConditionalExpressionOnArrayDeclaration() + { + var source = + @"public static IEnumerable Foo() => new int[] { }.ToArray()!.Any(x => x==1)?.OrderBy(e => e).ToList();"; + var expected = + @"public static IEnumerable Foo() => (StrykerNamespace.MutantControl.IsActive(2)?new int[] { }.ToArray()!.Any(x => x==1)?.OrderByDescending(e => e).ToList():(StrykerNamespace.MutantControl.IsActive(0)?new int[] { }.ToArray()!.All(x => x==1):new int[] { }.ToArray()!.Any(x => (StrykerNamespace.MutantControl.IsActive(1)?x!=1:x==1)))?.OrderBy(e => e).ToList());"; - [Fact] - public void ShouldMutateSuppressNullableWarningExpressionOnArrayDeclaration() - { - var source = - @"public static void Foo(){ + ShouldMutateSourceInClassToExpected(source, expected); + } + + [Fact] + public void ShouldMutateSuppressNullableWarningExpressionOnArrayDeclaration() + { + var source = + @"public static void Foo(){ var employeePerson = group.First().Entitlement!.Employee.Person;}"; - var expected = - @"public static void Foo(){if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + var expected = + @"public static void Foo(){if(StrykerNamespace.MutantControl.IsActive(0)){}else{ var employeePerson = (StrykerNamespace.MutantControl.IsActive(1)?group.FirstOrDefault():group.First()).Entitlement!.Employee.Person;}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateChainedInvocation() - { - var source = - @"public string ExampleBugMethod() + [Fact] + public void ShouldMutateChainedInvocation() + { + var source = + @"public string ExampleBugMethod() { string someString = """"; return someString.Replace(""ab"", ""cd"") @@ -533,8 +548,8 @@ public void ShouldMutateChainedInvocation() .PadLeft(12) .Replace(""12"", ""34""); }"; - var expected = - @"public string ExampleBugMethod() + var expected = + @"public string ExampleBugMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ string someString = (StrykerNamespace.MutantControl.IsActive(1)?""Stryker was here!"":""""); return someString.Replace((StrykerNamespace.MutantControl.IsActive(2)?"""":""ab""), (StrykerNamespace.MutantControl.IsActive(3)?"""":""cd"")) @@ -543,251 +558,251 @@ public void ShouldMutateChainedInvocation() .Replace((StrykerNamespace.MutantControl.IsActive(6)?"""":""12""), (StrykerNamespace.MutantControl.IsActive(7)?"""":""34"")); }return default(string);}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateArrayInitializer() - { - string source = @"public int[] Foo(){ + [Fact] + public void ShouldMutateArrayInitializer() + { + string source = @"public int[] Foo(){ int[] test = { 1 }; }"; - string expected = - @"public int[] Foo(){if(StrykerNamespace.MutantControl.IsActive(0)){}else{if(StrykerNamespace.MutantControl.IsActive(1)){ + string expected = + @"public int[] Foo(){if(StrykerNamespace.MutantControl.IsActive(0)){}else{if(StrykerNamespace.MutantControl.IsActive(1)){ int[] test = {}; }else{ int[] test = { 1 }; }}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateArrayDeclarationAsReturnValue() - { - var source = @"public int[] Foo() => new int[] { 1 };"; - var expected = - @"public int[] Foo() => (StrykerNamespace.MutantControl.IsActive(0)?new int[] {}:new int[] { 1 });"; + [Fact] + public void ShouldMutateArrayDeclarationAsReturnValue() + { + var source = @"public int[] Foo() => new int[] { 1 };"; + var expected = + @"public int[] Foo() => (StrykerNamespace.MutantControl.IsActive(0)?new int[] {}:new int[] { 1 });"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateListCreation() - { - var source = @"public int[] Foo() => new List { 1 };"; - var expected = - @"public int[] Foo() => (StrykerNamespace.MutantControl.IsActive(0)?new List {}:new List { 1 });"; + [Fact] + public void ShouldMutateListCreation() + { + var source = @"public int[] Foo() => new List { 1 };"; + var expected = + @"public int[] Foo() => (StrykerNamespace.MutantControl.IsActive(0)?new List {}:new List { 1 });"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldNotMutateImplicitArrayCreationProperties() - { - string source = @"public int[] Foo() => new [] { 1 };"; - string expected = @"public int[] Foo() => new [] { 1 };"; + [Fact] + public void ShouldNotMutateImplicitArrayCreationProperties() + { + string source = @"public int[] Foo() => new [] { 1 };"; + string expected = @"public int[] Foo() => new [] { 1 };"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldNotMutateImplicitArrayCreation() - { - string source = "public static readonly int[] Foo = { 1 };"; - string expected = "public static readonly int[] Foo = { 1 };"; + [Fact] + public void ShouldNotMutateImplicitArrayCreation() + { + string source = "public static readonly int[] Foo = { 1 };"; + string expected = "public static readonly int[] Foo = { 1 };"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateProperties() - { - string source = @"private string text => ""Some"" + ""Text"";"; - string expected = - @"private string text => (StrykerNamespace.MutantControl.IsActive(0) ? """" : ""Some"") + (StrykerNamespace.MutantControl.IsActive(1) ? """" : ""Text"");"; + [Fact] + public void ShouldMutateProperties() + { + string source = @"private string text => ""Some"" + ""Text"";"; + string expected = + @"private string text => (StrykerNamespace.MutantControl.IsActive(0) ? """" : ""Some"") + (StrykerNamespace.MutantControl.IsActive(1) ? """" : ""Text"");"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateTupleDeclaration() - { - string source = @"public void TestMethod() { + [Fact] + public void ShouldMutateTupleDeclaration() + { + string source = @"public void TestMethod() { var (one, two) = (1 + 1, """"); }"; - string expected = @"public void TestMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + string expected = @"public void TestMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ var (one, two) = ((StrykerNamespace.MutantControl.IsActive(1)?1 - 1:1 + 1), (StrykerNamespace.MutantControl.IsActive(2)?""Stryker was here!"":"""")); } }"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldNotMutateConst() - { - string source = @"private const int x = 1 + 2;"; - string expected = @"private const int x = 1 + 2;"; + [Fact] + public void ShouldNotMutateConst() + { + string source = @"private const int x = 1 + 2;"; + string expected = @"private const int x = 1 + 2;"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateStackalloc() - { - string source = @"Span kindaUnrelated = stackalloc ushort[] { 0 };"; - string expected = - @"Span kindaUnrelated = (StrykerNamespace.MutantControl.IsActive(0)?stackalloc ushort[] {}:stackalloc ushort[] { 0 });"; + [Fact] + public void ShouldMutateStackalloc() + { + string source = @"Span kindaUnrelated = stackalloc ushort[] { 0 };"; + string expected = + @"Span kindaUnrelated = (StrykerNamespace.MutantControl.IsActive(0)?stackalloc ushort[] {}:stackalloc ushort[] { 0 });"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - /// - /// Verifies that EnumMemberDeclarationSyntax nodes are not mutated. - /// Mutating would introduce code like StrykerXGJbRBlHxqRdD9O.MutantControl.IsActive(0) ? One + 1 : One - 1 - /// Since enum members need to be constants, this mutated code would not compile and print a warning. - /// - [Fact] - public void ShouldNotMutateEnum() - { - string source = @"private enum Numbers { One = 1, Two = One + 1 }"; - string expected = @"private enum Numbers { One = 1, Two = One + 1 }"; + /// + /// Verifies that EnumMemberDeclarationSyntax nodes are not mutated. + /// Mutating would introduce code like StrykerXGJbRBlHxqRdD9O.MutantControl.IsActive(0) ? One + 1 : One - 1 + /// Since enum members need to be constants, this mutated code would not compile and print a warning. + /// + [Fact] + public void ShouldNotMutateEnum() + { + string source = @"private enum Numbers { One = 1, Two = One + 1 }"; + string expected = @"private enum Numbers { One = 1, Two = One + 1 }"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldNotMutateAttributes() - { - string source = @"[Obsolete(""thismustnotbemutated"")] + [Fact] + public void ShouldNotMutateAttributes() + { + string source = @"[Obsolete(""thismustnotbemutated"")] public void SomeMethod() {}"; - string expected = @"[Obsolete(""thismustnotbemutated"")] + string expected = @"[Obsolete(""thismustnotbemutated"")] public void SomeMethod() {}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateForWithIfStatementAndConditionalStatement() - { - string source = @"public void SomeMethod() { + [Fact] + public void ShouldMutateForWithIfStatementAndConditionalStatement() + { + string source = @"public void SomeMethod() { for (var i = 0; i < 10; i++) { } }"; - string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ if(StrykerNamespace.MutantControl.IsActive(3)){for (var i = 0; i < 10; i--) { } }else{for (var i = 0; (StrykerNamespace.MutantControl.IsActive(2)?i <= 10:(StrykerNamespace.MutantControl.IsActive(1)?i > 10:i < 10)); i++) { } }}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateForWithoutConditionWithIfStatementAndConditionalStatement() - { - var source = @"public void SomeMethod() { + [Fact] + public void ShouldMutateForWithoutConditionWithIfStatementAndConditionalStatement() + { + var source = @"public void SomeMethod() { for (var i = 0; ; i++) { } }"; - var expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + var expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ if(StrykerNamespace.MutantControl.IsActive(1)){for (var i = 0; ; i--) { } }else{for (var i = 0; ; i++) { } }}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateInitializersForWithoutConditionWithIfStatementAndConditionalStatement() - { - var source = @"public void SomeMethod() { + [Fact] + public void ShouldMutateInitializersForWithoutConditionWithIfStatementAndConditionalStatement() + { + var source = @"public void SomeMethod() { for (var i = Method(true); ; i++) { } }"; - var expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + var expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ if(StrykerNamespace.MutantControl.IsActive(2)){for (var i = Method(true); ; i--) { } }else{for (var i = Method((StrykerNamespace.MutantControl.IsActive(1)?false:true)); ; i++) { } }}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateComplexExpressionBodiedMethod() - { - string source = @"public int SomeMethod() => (true && SomeOtherMethod(out var x)) ? x : 5;"; - string expected = - @"public int SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){return!((true && SomeOtherMethod(out var x)) )? x : 5;}else{if(StrykerNamespace.MutantControl.IsActive(1)){return(true || SomeOtherMethod(out var x)) ? x : 5;}else{return ((StrykerNamespace.MutantControl.IsActive(2)?false:true )&& SomeOtherMethod(out var x)) ? x : 5;}}}"; + [Fact] + public void ShouldMutateComplexExpressionBodiedMethod() + { + string source = @"public int SomeMethod() => (true && SomeOtherMethod(out var x)) ? x : 5;"; + string expected = + @"public int SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){return!((true && SomeOtherMethod(out var x)) )? x : 5;}else{if(StrykerNamespace.MutantControl.IsActive(1)){return(true || SomeOtherMethod(out var x)) ? x : 5;}else{return ((StrykerNamespace.MutantControl.IsActive(2)?false:true )&& SomeOtherMethod(out var x)) ? x : 5;}}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateExpressionBodiedStaticConstructor() - { - string source = @"static Test() => (true && SomeOtherMethod(out var x)) ? x : 5;"; - string expected = - @"static Test() {using(new StrykerNamespace.MutantContext()){if(StrykerNamespace.MutantControl.IsActive(0)){!((true && SomeOtherMethod(out var x)) )? x : 5;}else{if(StrykerNamespace.MutantControl.IsActive(1)){(true || SomeOtherMethod(out var x)) ? x : 5;}else{((StrykerNamespace.MutantControl.IsActive(2)?false:true )&& SomeOtherMethod(out var x)) ? x : 5;}}}}}"; + [Fact] + public void ShouldMutateExpressionBodiedStaticConstructor() + { + string source = @"static Test() => (true && SomeOtherMethod(out var x)) ? x : 5;"; + string expected = + @"static Test() {using(new StrykerNamespace.MutantContext()){if(StrykerNamespace.MutantControl.IsActive(0)){!((true && SomeOtherMethod(out var x)) )? x : 5;}else{if(StrykerNamespace.MutantControl.IsActive(1)){(true || SomeOtherMethod(out var x)) ? x : 5;}else{((StrykerNamespace.MutantControl.IsActive(2)?false:true )&& SomeOtherMethod(out var x)) ? x : 5;}}}}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateInlineArrowFunction() - { - string source = @"public void SomeMethod() { + [Fact] + public void ShouldMutateInlineArrowFunction() + { + string source = @"public void SomeMethod() { int Add(int x, int y) => x + y; }"; - string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ int Add(int x, int y) => (StrykerNamespace.MutantControl.IsActive(1)?x - y:x + y); }}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateLambdaSecondParameter() - { - string source = @"public void SomeMethod() { + [Fact] + public void ShouldMutateLambdaSecondParameter() + { + string source = @"public void SomeMethod() { Action act = () => Console.WriteLine(1 + 1, 1 + 1); }"; - string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ Action act = () => Console.WriteLine((StrykerNamespace.MutantControl.IsActive(1)?1 - 1:1 + 1), (StrykerNamespace.MutantControl.IsActive(2)?1 - 1:1 + 1)); }}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateLinqMethods() - { - string source = @"public int TestLinq(int count){ + [Fact] + public void ShouldMutateLinqMethods() + { + string source = @"public int TestLinq(int count){ var list = Enumerable.Range(1, count); return list.Last(); }"; - string expected = @"public int TestLinq(int count){if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + string expected = @"public int TestLinq(int count){if(StrykerNamespace.MutantControl.IsActive(0)){}else{ var list = Enumerable.Range(1, count); return (StrykerNamespace.MutantControl.IsActive(1)?list.First():list.Last()); }return default(int);}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateComplexLinqMethods() - { - string source = @"private void Linq() + [Fact] + public void ShouldMutateComplexLinqMethods() + { + string source = @"private void Linq() { var array = new []{1, 2}; var alt1 = array.Count(x => x % 2 == 0); var alt2 = array.Min(); }"; - string expected = @"private void Linq() + string expected = @"private void Linq() {if(StrykerNamespace.MutantControl.IsActive(0)){}else { var array = new []{1, 2}; @@ -795,35 +810,35 @@ public void ShouldMutateComplexLinqMethods() var alt2 = (StrykerNamespace.MutantControl.IsActive(4)?array.Max():array.Min()); }}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateReturnStatements() - { - string source = @"private bool Move() + [Fact] + public void ShouldMutateReturnStatements() + { + string source = @"private bool Move() { return true; }"; - string expected = @"private bool Move() + string expected = @"private bool Move() {if(StrykerNamespace.MutantControl.IsActive(0)){}else { return (StrykerNamespace.MutantControl.IsActive(1)?false:true); }return default(bool);}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateWhileLoop() - { - string source = @"private void DummyLoop() + [Fact] + public void ShouldMutateWhileLoop() + { + string source = @"private void DummyLoop() { while (this.Move()) { int x = 2 + 3; } }"; - string expected = @"private void DummyLoop() + string expected = @"private void DummyLoop() {if(StrykerNamespace.MutantControl.IsActive(0)){}else { while ((StrykerNamespace.MutantControl.IsActive(1)?!(this.Move()):this.Move())) {if(StrykerNamespace.MutantControl.IsActive(2)){}else { @@ -831,34 +846,34 @@ public void ShouldMutateWhileLoop() } } }}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateAssignmentStatementsWithIfStatement() - { - string source = @"public void SomeMethod() { + [Fact] + public void ShouldMutateAssignmentStatementsWithIfStatement() + { + string source = @"public void SomeMethod() { var x = 0; x *= x + 2; }"; - string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ var x = 0; if(StrykerNamespace.MutantControl.IsActive(1)){ x /=x + 2; }else{ x *= (StrykerNamespace.MutantControl.IsActive(2)?x - 2:x + 2); }}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateRecursiveCoalescingAssignmentStatements() - { - string source = @"public void SomeMethod() { + [Fact] + public void ShouldMutateRecursiveCoalescingAssignmentStatements() + { + string source = @"public void SomeMethod() { List a = null; List b = null; a ??= b ??= new List(); }"; - string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ List a = null; List b = null; if(StrykerNamespace.MutantControl.IsActive(1)){ a = b ??= new List(); @@ -866,62 +881,62 @@ public void ShouldMutateRecursiveCoalescingAssignmentStatements() }else{ a ??= b ??= new List(); }}}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateRecursiveNullCoalescingStatements() - { - string source = @"public void SomeMethod() { + [Fact] + public void ShouldMutateRecursiveNullCoalescingStatements() + { + string source = @"public void SomeMethod() { List a = null; List b = null; List c = null; var d = a ?? b ?? c; }"; - string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ List a = null; List b = null; List c = null; var d = (StrykerNamespace.MutantControl.IsActive(3)?a :(StrykerNamespace.MutantControl.IsActive(2)?b ?? c:(StrykerNamespace.MutantControl.IsActive(1)?b ?? c ?? a :a ?? (StrykerNamespace.MutantControl.IsActive(6)?b :(StrykerNamespace.MutantControl.IsActive(5)?c:(StrykerNamespace.MutantControl.IsActive(4)?c ?? b :b ?? c)))))); }}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateIncrementStatementWithIfStatement() - { - string source = @"public void SomeMethod() { + [Fact] + public void ShouldMutateIncrementStatementWithIfStatement() + { + string source = @"public void SomeMethod() { var x = 0; x++; }"; - string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ var x = 0; if(StrykerNamespace.MutantControl.IsActive(1)){;}else{if(StrykerNamespace.MutantControl.IsActive(2)){ x--; }else{ x++; }}}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldNotMutateIfDisabledByComment() - { - string source = @"public void SomeMethod() { + [Fact] + public void ShouldNotMutateIfDisabledByComment() + { + string source = @"public void SomeMethod() { var x = 0; // Stryker disable all x++; x/=2; }"; - string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ var x = 0; // Stryker disable all x++; x/=2; }}"; - ShouldMutateSourceInClassToExpected(source, expected); - source = @"public void SomeMethod() { + ShouldMutateSourceInClassToExpected(source, expected); + source = @"public void SomeMethod() { var x = 0; { // Stryker disable all @@ -929,7 +944,7 @@ public void ShouldNotMutateIfDisabledByComment() } x/=2; }"; - expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(4)){}else{ + expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(4)){}else{ var x = 0; {if(StrykerNamespace.MutantControl.IsActive(5)){}else { // Stryker disable all @@ -938,27 +953,27 @@ public void ShouldNotMutateIfDisabledByComment() }if(StrykerNamespace.MutantControl.IsActive(8)){ x*=2; }else{ x/=2; }}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldNotMutateIfDisabledByCommentOnStaticFields() - { - var source = @" + [Fact] + public void ShouldNotMutateIfDisabledByCommentOnStaticFields() + { + var source = @" // Stryker disable all static string x = ""test"";"; - var expected = @" + var expected = @" // Stryker disable all static string x = StrykerNamespace.MutantContext.TrackValue(()=>""test"");"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldNotMutateIfDisabledByCommentAtMethodLevel() - { - string source = @" + [Fact] + public void ShouldNotMutateIfDisabledByCommentAtMethodLevel() + { + string source = @" // Stryker disable all : testing public void SomeMethod() { @@ -966,7 +981,7 @@ public void SomeMethod() x++; x/=2; }"; - string expected = @"// Stryker disable all : testing + string expected = @"// Stryker disable all : testing public void SomeMethod() { var x = 0; @@ -974,8 +989,8 @@ public void SomeMethod() x/=2; }"; - ShouldMutateSourceInClassToExpected(source, expected); - source = @"public void SomeMethod() + ShouldMutateSourceInClassToExpected(source, expected); + source = @"public void SomeMethod() { var x = 0; { @@ -984,7 +999,7 @@ public void SomeMethod() } x/=2; }"; - expected = @"public void SomeMethod() + expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(4)){}else{ var x = 0; {if(StrykerNamespace.MutantControl.IsActive(5)){}else { @@ -994,19 +1009,19 @@ public void SomeMethod() }if(StrykerNamespace.MutantControl.IsActive(8)){ x*=2; }else{ x/=2; }}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldNotMutateOneLineIfDisabledByComment() - { - string source = @"public void SomeMethod() { + [Fact] + public void ShouldNotMutateOneLineIfDisabledByComment() + { + string source = @"public void SomeMethod() { var x = 0; // Stryker disable once all x++; x/=2; }"; - string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ var x = 0; // Stryker disable once all x++; @@ -1014,20 +1029,20 @@ public void ShouldNotMutateOneLineIfDisabledByComment() }else{ x/=2; }}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldNotMutateOneLineIfDisabledAndEnabledByComment() - { - string source = @"public void SomeMethod() { + [Fact] + public void ShouldNotMutateOneLineIfDisabledAndEnabledByComment() + { + string source = @"public void SomeMethod() { var x = 0; // Stryker disable all x++; // Stryker restore all x/=2; }"; - string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ var x = 0; // Stryker disable all x++; @@ -1037,19 +1052,19 @@ public void ShouldNotMutateOneLineIfDisabledAndEnabledByComment() x/=2; }}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldNotMutateOneLineIfDisabledOnce() - { - string source = @"public void SomeMethod() { + [Fact] + public void ShouldNotMutateOneLineIfDisabledOnce() + { + string source = @"public void SomeMethod() { var x = 0; // Stryker disable once all x++; x/=2; }"; - string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ var x = 0; // Stryker disable Update , Statement : comment x++; @@ -1059,20 +1074,20 @@ public void ShouldNotMutateOneLineIfDisabledOnce() x/=2; }}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldNotMutateOneLineIfSpecificMutatorDisabled() - { - string source = @"public void SomeMethod() { + [Fact] + public void ShouldNotMutateOneLineIfSpecificMutatorDisabled() + { + string source = @"public void SomeMethod() { var x = 0; // Stryker disable Update , Statement : comment x++; // Stryker restore all x/=2; }"; - string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ var x = 0; // Stryker disable Update , Statement : comment x++; @@ -1082,27 +1097,27 @@ public void ShouldNotMutateOneLineIfSpecificMutatorDisabled() x/=2; }}}"; - ShouldMutateSourceInClassToExpected(source, expected); + ShouldMutateSourceInClassToExpected(source, expected); - _target.Mutants.Count.ShouldBe(4); - _target.Mutants.ElementAt(0).ResultStatus.ShouldBe(MutantStatus.Pending); - _target.Mutants.ElementAt(1).ResultStatus.ShouldBe(MutantStatus.Ignored); - _target.Mutants.ElementAt(1).ResultStatusReason.ShouldBe("comment"); - _target.Mutants.ElementAt(2).ResultStatus.ShouldBe(MutantStatus.Ignored); - _target.Mutants.ElementAt(2).ResultStatusReason.ShouldBe("comment"); - _target.Mutants.ElementAt(3).ResultStatus.ShouldBe(MutantStatus.Pending); - } + _target.Mutants.Count.ShouldBe(4); + _target.Mutants.ElementAt(0).ResultStatus.ShouldBe(MutantStatus.Pending); + _target.Mutants.ElementAt(1).ResultStatus.ShouldBe(MutantStatus.Ignored); + _target.Mutants.ElementAt(1).ResultStatusReason.ShouldBe("comment"); + _target.Mutants.ElementAt(2).ResultStatus.ShouldBe(MutantStatus.Ignored); + _target.Mutants.ElementAt(2).ResultStatusReason.ShouldBe("comment"); + _target.Mutants.ElementAt(3).ResultStatus.ShouldBe(MutantStatus.Pending); + } - [Fact] - public void ShouldNotMutateASubExpressionIfDisabledByComment() - { - string source = @"public void SomeMethod() { + [Fact] + public void ShouldNotMutateASubExpressionIfDisabledByComment() + { + string source = @"public void SomeMethod() { var x = 0; x/= // Stryker disable once all x +2; }"; - string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + string expected = @"public void SomeMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ var x = 0; if(StrykerNamespace.MutantControl.IsActive(1)){ x*=// Stryker disable once all x +2; @@ -1111,13 +1126,13 @@ public void ShouldNotMutateASubExpressionIfDisabledByComment() x +2; }}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateChainedMutations() - { - string source = @"public void Simple() + [Fact] + public void ShouldMutateChainedMutations() + { + string source = @"public void Simple() { object value = null; var flag1 = false; @@ -1126,7 +1141,7 @@ public void ShouldMutateChainedMutations() { } }"; - string expected = @"public void Simple() + string expected = @"public void Simple() {if(StrykerNamespace.MutantControl.IsActive(0)){}else { object value = null; var flag1 = (StrykerNamespace.MutantControl.IsActive(1)?true:false); @@ -1136,13 +1151,13 @@ public void ShouldMutateChainedMutations() } }}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateStatics() - { - string source = @"private static bool willMutateToFalse = true; + [Fact] + public void ShouldMutateStatics() + { + string source = @"private static bool willMutateToFalse = true; private static bool NoWorries => false; private static bool NoWorriesGetter @@ -1155,7 +1170,7 @@ static Mutator_Flag_MutatedStatics() int x = 0; var y = x++; }"; - string expected = @"private static bool willMutateToFalse = StrykerNamespace.MutantContext.TrackValue(()=>(StrykerNamespace.MutantControl.IsActive(0)?false:true)); + string expected = @"private static bool willMutateToFalse = StrykerNamespace.MutantContext.TrackValue(()=>(StrykerNamespace.MutantControl.IsActive(0)?false:true)); private static bool NoWorries => (StrykerNamespace.MutantControl.IsActive(1)?true:false); private static bool NoWorriesGetter @@ -1169,32 +1184,32 @@ static Mutator_Flag_MutatedStatics() var y = (StrykerNamespace.MutantControl.IsActive(5)?x--:x++); }}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldNotMutateDefaultValues() - { - string source = @"public void SomeMethod(bool option = true) {}"; - string expected = @"public void SomeMethod(bool option = true) {}"; + [Fact] + public void ShouldNotMutateDefaultValues() + { + string source = @"public void SomeMethod(bool option = true) {}"; + string expected = @"public void SomeMethod(bool option = true) {}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldInitializeOutVars() - { - string source = @"public void SomeMethod(out int x, out string text) { x = 1; text = ""hello"";}"; - string expected = @"public void SomeMethod(out int x, out string text) {{x= default(int);text= default(string);}if(StrykerNamespace.MutantControl.IsActive(0)){}else{ x = 1; text = (StrykerNamespace.MutantControl.IsActive(1)?"""":""hello""); + [Fact] + public void ShouldInitializeOutVars() + { + string source = @"public void SomeMethod(out int x, out string text) { x = 1; text = ""hello"";}"; + string expected = @"public void SomeMethod(out int x, out string text) {{x= default(int);text= default(string);}if(StrykerNamespace.MutantControl.IsActive(0)){}else{ x = 1; text = (StrykerNamespace.MutantControl.IsActive(1)?"""":""hello""); }}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateInsideLambda() - { - string source = @"private async Task GoodLuck() + [Fact] + public void ShouldMutateInsideLambda() + { + string source = @"private async Task GoodLuck() { await SendRequest(url, HttpMethod.Get, (request) => { @@ -1202,7 +1217,7 @@ await SendRequest(url, HttpMethod.Get, (request) => request.Headers.TryAddWithoutValidation(""Date"", date); }, ensureSuccessStatusCode: false); }"; - string expected = @"private async Task GoodLuck() + string expected = @"private async Task GoodLuck() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ if(StrykerNamespace.MutantControl.IsActive(1)){;}else{ await SendRequest(url, HttpMethod.Get, (request) => {if(StrykerNamespace.MutantControl.IsActive(2)){}else { @@ -1212,30 +1227,30 @@ await SendRequest(url, HttpMethod.Get, (request) => }}, ensureSuccessStatusCode: (StrykerNamespace.MutantControl.IsActive(8) ? true : false)); }}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void MutationsShouldHaveLinespan() - { - string source = @"void TestMethod() + [Fact] + public void MutationsShouldHaveLinespan() + { + string source = @"void TestMethod() { var test3 = 2 + 5; }"; - _target.Mutate(CSharpSyntaxTree.ParseText(source), null); - - var mutants = _target.GetLatestMutantBatch().ToList(); - mutants.Count.ShouldBe(2); - var blockLinespan = mutants.First().Mutation.OriginalNode.GetLocation().GetLineSpan(); - blockLinespan.StartLinePosition.Line.ShouldBe(1); - blockLinespan.EndLinePosition.Line.ShouldBe(3); - mutants.Last().Mutation.OriginalNode.GetLocation().GetLineSpan().StartLinePosition.Line.ShouldBe(2); - } + _target.Mutate(CSharpSyntaxTree.ParseText(source), null); + + var mutants = _target.GetLatestMutantBatch().ToList(); + mutants.Count.ShouldBe(2); + var blockLinespan = mutants.First().Mutation.OriginalNode.GetLocation().GetLineSpan(); + blockLinespan.StartLinePosition.Line.ShouldBe(1); + blockLinespan.EndLinePosition.Line.ShouldBe(3); + mutants.Last().Mutation.OriginalNode.GetLocation().GetLineSpan().StartLinePosition.Line.ShouldBe(2); + } - [Fact] - public void MutationsShouldHaveLinespan2() - { - string source = @"using System; + [Fact] + public void MutationsShouldHaveLinespan2() + { + string source = @"using System; using System.Collections.Generic; using System.Text; @@ -1249,79 +1264,79 @@ public static bool InvokeIfNotNull(this Action a) } } }"; - _target.Mutate(CSharpSyntaxTree.ParseText(source), null); + _target.Mutate(CSharpSyntaxTree.ParseText(source), null); - var mutants = _target.GetLatestMutantBatch().ToList(); - mutants.Count.ShouldBe(7); + var mutants = _target.GetLatestMutantBatch().ToList(); + mutants.Count.ShouldBe(7); - var blockLinespan = mutants.First().Mutation.OriginalNode.GetLocation().GetLineSpan(); - blockLinespan.StartLinePosition.Line.ShouldBe(9); - blockLinespan.EndLinePosition.Line.ShouldBe(11); - foreach (var mutant in mutants.Skip(1)) - { - mutant.Mutation.OriginalNode.GetLocation().GetLineSpan().StartLinePosition.Line.ShouldBe(10); - } + var blockLinespan = mutants.First().Mutation.OriginalNode.GetLocation().GetLineSpan(); + blockLinespan.StartLinePosition.Line.ShouldBe(9); + blockLinespan.EndLinePosition.Line.ShouldBe(11); + foreach (var mutant in mutants.Skip(1)) + { + mutant.Mutation.OriginalNode.GetLocation().GetLineSpan().StartLinePosition.Line.ShouldBe(10); } + } - [Fact] - public void ShouldAddReturnDefaultToMethods() - { - string source = @"bool TestMethod() + [Fact] + public void ShouldAddReturnDefaultToMethods() + { + string source = @"bool TestMethod() { while(true) return false; }"; - string expected = @"bool TestMethod() + string expected = @"bool TestMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ while((StrykerNamespace.MutantControl.IsActive(2)?!(true):(StrykerNamespace.MutantControl.IsActive(1)?false:true))) return (StrykerNamespace.MutantControl.IsActive(3)?true:false); }return default(bool);}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldAddReturnDefaultToConversion() - { - string source = @"public static explicit operator string(TestClass value) + [Fact] + public void ShouldAddReturnDefaultToConversion() + { + string source = @"public static explicit operator string(TestClass value) { while(true) return value; }"; - string expected = @"public static explicit operator string(TestClass value) + string expected = @"public static explicit operator string(TestClass value) {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ while((StrykerNamespace.MutantControl.IsActive(2)?!(true):(StrykerNamespace.MutantControl.IsActive(1)?false:true))) return value; }return default(string);}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldNotMutateConstDeclaration() - { - var source = @"void Test(){ + [Fact] + public void ShouldNotMutateConstDeclaration() + { + var source = @"void Test(){ const string text = ""a""+""b"";}"; - var expected = @"void Test(){if(StrykerNamespace.MutantControl.IsActive(0)){}else{ + var expected = @"void Test(){if(StrykerNamespace.MutantControl.IsActive(0)){}else{ const string text = ""a""+""b"";}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldAddReturnDefaultToAsyncMethods() - { - string source = @"public async Task TestMethod() + [Fact] + public void ShouldAddReturnDefaultToAsyncMethods() + { + string source = @"public async Task TestMethod() { while(true) return false; }"; - string expected = @"public async Task TestMethod() + string expected = @"public async Task TestMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ while((StrykerNamespace.MutantControl.IsActive(2)?!(true):(StrykerNamespace.MutantControl.IsActive(1)?false:true))) return (StrykerNamespace.MutantControl.IsActive(3)?true:false); }return default(bool);}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldAddReturnDefaultToIndexerGetter() - { - string source = @"public string this[string key] + [Fact] + public void ShouldAddReturnDefaultToIndexerGetter() + { + string source = @"public string this[string key] { get { return key; } }"; - string expected = @"public string this[string key] + string expected = @"public string this[string key] { get {if(StrykerNamespace.MutantControl.IsActive(0)){}else { @@ -1329,13 +1344,13 @@ public void ShouldAddReturnDefaultToIndexerGetter() } return default(string);} }"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldNotAddReturnDefaultToEnumerationMethods() - { - string source = @"public static IEnumerable Extracting(this IEnumerable enumerable, string propertyName) + [Fact] + public void ShouldNotAddReturnDefaultToEnumerationMethods() + { + string source = @"public static IEnumerable Extracting(this IEnumerable enumerable, string propertyName) { foreach (var o in enumerable) { @@ -1346,7 +1361,7 @@ public static IEnumerable Extracting(this IEnumerable enumerable) { yield break; }"; - string expected = @"public static IEnumerable Extracting(this IEnumerable enumerable, string propertyName) + string expected = @"public static IEnumerable Extracting(this IEnumerable enumerable, string propertyName) {if(StrykerNamespace.MutantControl.IsActive(0)){}else { foreach (var o in enumerable) {if(StrykerNamespace.MutantControl.IsActive(1)){}else { @@ -1357,75 +1372,75 @@ public static IEnumerable Extracting(this IEnumerable enumerable) {if(StrykerNamespace.MutantControl.IsActive(3)){}else { if(StrykerNamespace.MutantControl.IsActive(4)){;}else{ yield break; } }}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldAddReturnDefaultToAsyncWithFullNamespaceMethods() - { - string source = @"public async System.Threading.Tasks.Task TestMethod() + [Fact] + public void ShouldAddReturnDefaultToAsyncWithFullNamespaceMethods() + { + string source = @"public async System.Threading.Tasks.Task TestMethod() { while(true) return false; }"; - string expected = @"public async System.Threading.Tasks.Task TestMethod() + string expected = @"public async System.Threading.Tasks.Task TestMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ while((StrykerNamespace.MutantControl.IsActive(2)?!(true):(StrykerNamespace.MutantControl.IsActive(1)?false:true))) return (StrykerNamespace.MutantControl.IsActive(3)?true:false); }return default(bool);}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldNotAddReturnDefaultToAsyncTaskMethods() - { - string source = @"public async Task TestMethod() + [Fact] + public void ShouldNotAddReturnDefaultToAsyncTaskMethods() + { + string source = @"public async Task TestMethod() { ; }"; - string expected = @"public async Task TestMethod() + string expected = @"public async Task TestMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ ; }}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldNotAddReturnDefaultToMethodsWithReturnTypeVoid() - { - string source = @"void TestMethod() + [Fact] + public void ShouldNotAddReturnDefaultToMethodsWithReturnTypeVoid() + { + string source = @"void TestMethod() { ; }"; - string expected = @"void TestMethod() + string expected = @"void TestMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ ; }}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Theory] - [InlineData("{return 0;}")] - [InlineData("{return 1; throw Exception();}")] - [InlineData("{return 1;yield return 0;}")] - [InlineData("{return 1;yield break;}")] - [InlineData("{;}")] - public void ShouldNotAddReturnOnSomeBlocks(string code) - { - string source = @$" + [Theory] + [InlineData("{return 0;}")] + [InlineData("{return 1; throw Exception();}")] + [InlineData("{return 1;yield return 0;}")] + [InlineData("{return 1;yield break;}")] + [InlineData("{;}")] + public void ShouldNotAddReturnOnSomeBlocks(string code) + { + string source = @$" int TestMethod() // Stryker disable all {code}"; - ShouldMutateSourceInClassToExpected(source, source); - } + ShouldMutateSourceInClassToExpected(source, source); + } - [Fact] - public void ShouldSkipStringsInSwitchExpression() - { - string source = @"string TestMethod() + [Fact] + public void ShouldSkipStringsInSwitchExpression() + { + string source = @"string TestMethod() { return input switch { ""test"" => ""test"" }; }"; - string expected = @"string TestMethod() + string expected = @"string TestMethod() {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ return input switch { @@ -1433,72 +1448,72 @@ public void ShouldSkipStringsInSwitchExpression() ) }; }return default(string);} "; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateStaticConstructor() - { - var source = @" + [Fact] + public void ShouldMutateStaticConstructor() + { + var source = @" static string Value { get; } static TestClass() => Value = ""Hello, World!"";"; - var expected = @"static string Value { get; } + var expected = @"static string Value { get; } static TestClass() {using(new StrykerNamespace.MutantContext()){Value = (StrykerNamespace.MutantControl.IsActive(0)?"""":""Hello, World!""); }}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateStaticArrowConstructor() - { - var source = @" + [Fact] + public void ShouldMutateStaticArrowConstructor() + { + var source = @" static string Value { get; } static TestClass() {Value = ""Hello, World!"";}"; - var expected = @"static string Value { get; } + var expected = @"static string Value { get; } static TestClass() {using(new StrykerNamespace.MutantContext()){if(StrykerNamespace.MutantControl.IsActive(0)){}else{Value = (StrykerNamespace.MutantControl.IsActive(1)?"""":""Hello, World!""); } } } "; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateStaticPropertiesInArrowForm() - { - var source = @"class Test { + [Fact] + public void ShouldMutateStaticPropertiesInArrowForm() + { + var source = @"class Test { static string Value => """"; static TestClass(){}}"; - var expected = @"class Test { + var expected = @"class Test { static string Value => (StrykerNamespace.MutantControl.IsActive(0)?""Stryker was here!"":""""); static TestClass(){using(new StrykerNamespace.MutantContext()){}}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutatePropertiesInArrowFormEvenWithComplexConstruction() - { - var source = @"class Test { + [Fact] + public void ShouldMutatePropertiesInArrowFormEvenWithComplexConstruction() + { + var source = @"class Test { string Value {get => Out(out var x)? ""empty"": """";} static TestClass(){}}"; - var expected = @"class Test { + var expected = @"class Test { string Value {get {if(StrykerNamespace.MutantControl.IsActive(0)){return!(Out(out var x))? ""empty"": """";}else{return Out(out var x)? (StrykerNamespace.MutantControl.IsActive(1)?"""":""empty""): (StrykerNamespace.MutantControl.IsActive(2)?""Stryker was here!"":"""");}}} static TestClass(){using(new StrykerNamespace.MutantContext()){}}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutateStaticProperties() - { - var source = @" + [Fact] + public void ShouldMutateStaticProperties() + { + var source = @" static string Value { get { return ""TestDescription"";} @@ -1506,7 +1521,7 @@ static string Value } static TestClass(){}"; - var expected = @"static string Value + var expected = @"static string Value {get {if(StrykerNamespace.MutantControl.IsActive(0)){}else{ return (StrykerNamespace.MutantControl.IsActive(1)?"""":""TestDescription""); } return default(string); @@ -1515,51 +1530,51 @@ static string Value } }} static TestClass() { using (new StrykerNamespace.MutantContext()) { } }}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMarkStaticMutationStaticInPropertiesInitializer() - { - var source = @"class Test { + [Fact] + public void ShouldMarkStaticMutationStaticInPropertiesInitializer() + { + var source = @"class Test { static string Value {get;} = """";}"; - var expected = @"class Test { + var expected = @"class Test { static string Value {get;} = StrykerNamespace.MutantContext.TrackValue(()=>(StrykerNamespace.MutantControl.IsActive(0)?""Stryker was here!"":""""));}}}"; - ShouldMutateSourceInClassToExpected(source, expected); - _target.Mutants.Count.ShouldBe(1); - _target.Mutants.First().IsStaticValue.ShouldBeTrue(); - } + ShouldMutateSourceInClassToExpected(source, expected); + _target.Mutants.Count.ShouldBe(1); + _target.Mutants.First().IsStaticValue.ShouldBeTrue(); + } - [Fact] - public void ShouldMutateStaticPropertiesInArrowFormEvenWithComplexConstruction() - { - var source = @"class Test { + [Fact] + public void ShouldMutateStaticPropertiesInArrowFormEvenWithComplexConstruction() + { + var source = @"class Test { static string Value => Out(out var x)? ""empty"": """";}"; - var expected = @"class Test { + var expected = @"class Test { static string Value {get {if(StrykerNamespace.MutantControl.IsActive(0)){return!(Out(out var x))? ""empty"": """";}else{return Out(out var x)? (StrykerNamespace.MutantControl.IsActive(1)?"""":""empty""): (StrykerNamespace.MutantControl.IsActive(2)?""Stryker was here!"":"""");}}}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldMutatePropertiesAsArrowExpression() - { - var source = @"class Test { + [Fact] + public void ShouldMutatePropertiesAsArrowExpression() + { + var source = @"class Test { string Value => Generator(out var x) ? """" :""test""; }"; - var expected = @"class Test { + var expected = @"class Test { string Value {get{if(StrykerNamespace.MutantControl.IsActive(0)){return!(Generator(out var x) )? """" :""test"";}else{return Generator(out var x) ? (StrykerNamespace.MutantControl.IsActive(1)?""Stryker was here!"":"""" ):(StrykerNamespace.MutantControl.IsActive(2)?"""":""test"");}}} }"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - public void ShouldControlLocalDeclarationMutationAtTheBlockLevel() - { - var source = @"public static string FormatPrettyByte(Int64 value) + [Fact] + public void ShouldControlLocalDeclarationMutationAtTheBlockLevel() + { + var source = @"public static string FormatPrettyByte(Int64 value) { string[] SizeSuffixes = { ""bytes"", ""KB"", ""MB"", ""GB"" }; @@ -1570,7 +1585,7 @@ public void ShouldControlLocalDeclarationMutationAtTheBlockLevel() } "; - var expected = @"public static string FormatPrettyByte(Int64 value) + var expected = @"public static string FormatPrettyByte(Int64 value) {if(StrykerNamespace.MutantControl.IsActive(0)){}else{if(StrykerNamespace.MutantControl.IsActive(1)) { string[] SizeSuffixes = {}; @@ -1590,29 +1605,29 @@ public void ShouldControlLocalDeclarationMutationAtTheBlockLevel() } } return default(string);}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - // test for issue #1386 - public void ShouldNotLeakMutationsAcrossDefinitions() - { - var source = @"class Test { + [Fact] + // test for issue #1386 + public void ShouldNotLeakMutationsAcrossDefinitions() + { + var source = @"class Test { int GetId(string input) => int.TryParse(input, out var result) ? result : 0; string Value => Generator(out var x) ? """" :""test""; }"; - var expected = @"class Test { + var expected = @"class Test { int GetId(string input) {if(StrykerNamespace.MutantControl.IsActive(0)){return!(int.TryParse(input, out var result) )? result : 0;}else{return int.TryParse(input, out var result) ? result : 0;}} string Value {get{if(StrykerNamespace.MutantControl.IsActive(1)){return!(Generator(out var x) )? """" :""test"";}else{return Generator(out var x) ? (StrykerNamespace.MutantControl.IsActive(2)?""Stryker was here!"":"""" ):(StrykerNamespace.MutantControl.IsActive(3)?"""":""test"");}}}}}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); + } - [Fact] - // test for issue #1386 - public void ShouldHandleLocalFunctions() - { - var source = @" + [Fact] + // test for issue #1386 + public void ShouldHandleLocalFunctions() + { + var source = @" public string DoStuff(char myChar, int myInt) { if (TryGet(myChar, out int i)) @@ -1626,7 +1641,7 @@ private bool TryGet(char myChar, out int i) return true; }"; - var expected = @"public string DoStuff(char myChar, int myInt) + var expected = @"public string DoStuff(char myChar, int myInt) {if(StrykerNamespace.MutantControl.IsActive(0)){}else{if(StrykerNamespace.MutantControl.IsActive(1)) { if (!(TryGet(myChar, out int i))) {} @@ -1644,7 +1659,6 @@ private bool TryGet(char myChar, out int i) i = 0; return (StrykerNamespace.MutantControl.IsActive(3)?false:true); }return default(bool);}}}}"; - ShouldMutateSourceInClassToExpected(source, expected); - } + ShouldMutateSourceInClassToExpected(source, expected); } } diff --git a/src/Stryker.Core/Stryker.Core/Compiling/CSharpRollbackProcess.cs b/src/Stryker.Core/Stryker.Core/Compiling/CSharpRollbackProcess.cs index 7668bb9a80..d476cb8f9c 100644 --- a/src/Stryker.Core/Stryker.Core/Compiling/CSharpRollbackProcess.cs +++ b/src/Stryker.Core/Stryker.Core/Compiling/CSharpRollbackProcess.cs @@ -17,6 +17,7 @@ namespace Stryker.Core.Compiling public interface ICSharpRollbackProcess { CSharpRollbackProcessResult Start(CSharpCompilation compiler, ImmutableArray diagnostics, bool lastAttempt, bool devMode); + SyntaxTree CleanUpFile(SyntaxTree file); } /// @@ -39,7 +40,12 @@ public CSharpRollbackProcessResult Start(CSharpCompilation compiler, ImmutableAr var syntaxTreeMapping = compiler.SyntaxTrees.ToDictionary>(syntaxTree => syntaxTree, _ => new Collection()); foreach (var diagnostic in diagnostics.Where(x => x.Severity == DiagnosticSeverity.Error)) - { + { + if (diagnostic.Location.SourceTree == null) + { + Logger.LogWarning("General compilation error: {0}", diagnostic.GetMessage()); + continue; + } syntaxTreeMapping[diagnostic.Location.SourceTree].Add(diagnostic); } @@ -142,7 +148,7 @@ private static SyntaxNode FindEnclosingMember(SyntaxNode node) return currentNode; } } - // return the all file if not found + // return the whole file if not found return node.SyntaxTree.GetRoot(); } @@ -250,6 +256,32 @@ private Collection ScanForSuspiciousMutations(Diagnostic[] diagnosti return suspiciousMutations; } + // removes all mutation from a file + public SyntaxTree CleanUpFile(SyntaxTree file) + { + var rollbackRoot = file.GetRoot(); + var scan = ScanAllMutationsIfsAndIds(rollbackRoot); + var suspiciousMutations = new Collection(); + foreach (var mutant in scan.Where(mutant => !suspiciousMutations.Contains(mutant.Node))) + { + suspiciousMutations.Add(mutant.Node); + if (mutant.Id != -1) + { + RollBackedIds.Add(mutant.Id.Value); + } + } + // mark the broken mutation nodes to track + var trackedTree = rollbackRoot.TrackNodes(suspiciousMutations); + foreach (var brokenMutation in suspiciousMutations) + { + // find the mutated node in the new tree + var nodeToRemove = trackedTree.GetCurrentNode(brokenMutation); + // remove the mutated node using its MutantPlacer remove method and update the tree + trackedTree = trackedTree.ReplaceNode(nodeToRemove, MutantPlacer.RemoveMutant(nodeToRemove)); + } + return file.WithRootAndOptions(trackedTree, file.Options); + } + private string DisplayName(SyntaxNode initNode) => initNode switch { diff --git a/src/Stryker.Core/Stryker.Core/Compiling/CsharpCompilingProcess.cs b/src/Stryker.Core/Stryker.Core/Compiling/CsharpCompilingProcess.cs index 0c1efb5721..940523c74d 100644 --- a/src/Stryker.Core/Stryker.Core/Compiling/CsharpCompilingProcess.cs +++ b/src/Stryker.Core/Stryker.Core/Compiling/CsharpCompilingProcess.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Text; @@ -9,6 +11,7 @@ using Microsoft.CodeAnalysis.Emit; using Microsoft.Extensions.Logging; using Stryker.Core.Exceptions; +using Stryker.Core.Initialisation; using Stryker.Core.Initialisation.Buildalyzer; using Stryker.Core.Logging; using Stryker.Core.MutationTest; @@ -60,7 +63,7 @@ public CompilingProcessResult Compile(IEnumerable syntaxTrees, Strea // first try compiling var retryCount = 1; - (var rollbackProcessResult, var emitResult, retryCount) = TryCompilation(ilStream, symbolStream, compilation, null, false, retryCount); + (var rollbackProcessResult, var emitResult, retryCount) = TryCompilation(ilStream, symbolStream, ref compilation, null, false, retryCount); // If compiling failed and the error has no location, log and throw exception. if (!emitResult.Success && emitResult.Diagnostics.Any(diagnostic => diagnostic.Location == Location.None && diagnostic.Severity == DiagnosticSeverity.Error)) @@ -73,8 +76,8 @@ public CompilingProcessResult Compile(IEnumerable syntaxTrees, Strea for (var count = 1; !emitResult.Success && count < MaxAttempt; count++) { - // compilation did not succeed. let's compile a couple times more for good measure - (rollbackProcessResult, emitResult, retryCount) = TryCompilation(ilStream, symbolStream, rollbackProcessResult?.Compilation ?? compilation, emitResult, retryCount == MaxAttempt - 1, retryCount); + // compilation did not succeed. let's compile a couple of times more for good measure + (rollbackProcessResult, emitResult, retryCount) = TryCompilation(ilStream, symbolStream, ref compilation, emitResult, retryCount == MaxAttempt - 1, retryCount); } if (emitResult.Success) @@ -118,15 +121,16 @@ private CSharpCompilation RunSourceGenerators(IAnalyzerResult analyzerResult, Co .RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out var diagnostics); var errors = diagnostics.Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error && diagnostic.Location == Location.None).ToList(); - if (errors.Count > 0) + if (errors.Count == 0) { - foreach (var diagnostic in errors) - { - _logger.LogError("Failed to generate source code for mutated assembly: {0}", diagnostic); - } - throw new CompilationException("Source Generator Failure"); + return outputCompilation as CSharpCompilation; } - return outputCompilation as CSharpCompilation; + + foreach (var diagnostic in errors) + { + _logger.LogError("Failed to generate source code for mutated assembly: {0}", diagnostic); + } + throw new CompilationException("Source Generator Failure"); } private CSharpCompilation GetCSharpCompilation(IEnumerable syntaxTrees) @@ -147,43 +151,86 @@ private CSharpCompilation GetCSharpCompilation(IEnumerable syntaxTre private (CSharpRollbackProcessResult, EmitResult, int) TryCompilation( Stream ms, Stream symbolStream, - CSharpCompilation compilation, + ref CSharpCompilation compilation, EmitResult previousEmitResult, bool lastAttempt, int retryCount) { CSharpRollbackProcessResult rollbackProcessResult = null; - if (previousEmitResult != null) - { - // remove broken mutations - rollbackProcessResult = _rollbackProcess.Start(compilation, previousEmitResult.Diagnostics, lastAttempt, _options.DevMode); - compilation = rollbackProcessResult.Compilation; - } - - // reset the memoryStream - ms.SetLength(0); - symbolStream?.SetLength(0); - _logger.LogDebug("Trying compilation for the {retryCount} time.", ReadableNumber(retryCount)); var emitOptions = symbolStream == null ? null : new EmitOptions(false, DebugInformationFormat.PortablePdb, _input.SourceProjectInfo.AnalyzerResult.GetSymbolFileName()); - var emitResult = compilation.Emit( - ms, - symbolStream, - manifestResources: _input.SourceProjectInfo.AnalyzerResult.GetResources(_logger), - win32Resources: compilation.CreateDefaultWin32Resources( - true, // Important! - false, - null, - null), - options: emitOptions); + EmitResult emitResult = null; + var resourceDescriptions = _input.SourceProjectInfo.AnalyzerResult.GetResources(_logger); + while(emitResult == null) + { + if (previousEmitResult != null) + { + // remove broken mutations + rollbackProcessResult = _rollbackProcess.Start(compilation, previousEmitResult.Diagnostics, lastAttempt, _options.DevMode); + compilation = rollbackProcessResult.Compilation; + } + + // reset the memoryStreams + ms.SetLength(0); + symbolStream?.SetLength(0); + try + { + emitResult = compilation.Emit( + ms, + symbolStream, + manifestResources: resourceDescriptions, + win32Resources: compilation.CreateDefaultWin32Resources( + true, // Important! + false, + null, + null), + options: emitOptions); + } +#pragma warning disable S1696 // this catches an exception raised by the C# compiler + catch (NullReferenceException e) + { + _logger.LogError("Roslyn C# compiler raised an NullReferenceException. This is a known Roslyn's issue that may be triggered by invalid usage of conditional access expression."); + _logger.LogInformation(e, "Exception"); + _logger.LogError("Stryker will attempt to skip problematic files."); + compilation = ScanForCauseOfException(compilation); + EmbeddedResourcesGenerator.ResetCache(); + } + } + LogEmitResult(emitResult); return (rollbackProcessResult, emitResult, retryCount+1); } + private CSharpCompilation ScanForCauseOfException(CSharpCompilation compilation) + { + var syntaxTrees = compilation.SyntaxTrees; + // we add each file incrementally until it fails + foreach(var st in syntaxTrees) + { + var local = compilation.RemoveAllSyntaxTrees().AddSyntaxTrees(st); + try + { + using var ms = new MemoryStream(); + local.Emit( + ms, + manifestResources: _input.SourceProjectInfo.AnalyzerResult.GetResources(_logger), + options: null); + } + catch(Exception e) + { + _logger.LogError(e, "Failed to compile {0}", st.FilePath); + _logger.LogTrace("source code:\n {0}", st.GetText()); + syntaxTrees = syntaxTrees.Where(x => x != st).Append(_rollbackProcess.CleanUpFile(st)).ToImmutableArray(); + } + } + _logger.LogError("Please report an issue and provide the source code of the file that caused the exception for analysis."); + return compilation.RemoveAllSyntaxTrees().AddSyntaxTrees(syntaxTrees); + } + private void LogEmitResult(EmitResult result) { if (!result.Success) diff --git a/src/Stryker.Core/Stryker.Core/Initialisation/EmbeddedResourcesGenerator.cs b/src/Stryker.Core/Stryker.Core/Initialisation/EmbeddedResourcesGenerator.cs index 0906a98a98..7022c53b38 100644 --- a/src/Stryker.Core/Stryker.Core/Initialisation/EmbeddedResourcesGenerator.cs +++ b/src/Stryker.Core/Stryker.Core/Initialisation/EmbeddedResourcesGenerator.cs @@ -16,7 +16,12 @@ namespace Stryker.Core.Initialisation [ExcludeFromCodeCoverage] public static class EmbeddedResourcesGenerator { - private static readonly IDictionary> _resourceDescriptions = new Dictionary>(); + private static readonly Dictionary> _resourceDescriptions = new(); + + public static void ResetCache() + { + _resourceDescriptions.Clear(); + } public static IEnumerable GetManifestResources(string assemblyPath, string projectFilePath, string rootNamespace, IEnumerable embeddedResources) { @@ -31,7 +36,7 @@ public static IEnumerable GetManifestResources(string assem // Failed to load some or all resources from module, generate missing resources from disk if (module is not null && _resourceDescriptions[projectFilePath].Count() < embeddedResources.Count()) { - var missingEmbeddedResources = embeddedResources.Where(r => _resourceDescriptions[projectFilePath].Any(fr => GetResourceDescriptionInternalName(fr) == GenerateResourceName(r))); + var missingEmbeddedResources = embeddedResources.Where(r => _resourceDescriptions[projectFilePath].Any(fr => GetResourceDescriptionInternalName(fr.description) == GenerateResourceName(r))); _resourceDescriptions[projectFilePath] = _resourceDescriptions[projectFilePath].Concat(GenerateManifestResources(projectFilePath, rootNamespace, missingEmbeddedResources)); } @@ -42,9 +47,13 @@ public static IEnumerable GetManifestResources(string assem } } - foreach (var description in _resourceDescriptions.ContainsKey(projectFilePath) ? _resourceDescriptions[projectFilePath] : Enumerable.Empty()) + if (!_resourceDescriptions.TryGetValue(projectFilePath, out var resourcesDescription)) + { + yield break; + } + foreach (var description in resourcesDescription) { - yield return description; + yield return description.description; } } @@ -67,7 +76,7 @@ private static ModuleDefinition LoadModule(string assemblyPath) } } - private static IEnumerable ReadResourceDescriptionsFromModule(ModuleDefinition module) + private static IEnumerable<(ResourceDescription, object)> ReadResourceDescriptionsFromModule(ModuleDefinition module) { foreach (var moduleResource in module.Resources.Where(r => r.ResourceType == ResourceType.Embedded).Cast()) { @@ -80,26 +89,26 @@ private static IEnumerable ReadResourceDescriptionsFromModu resourceStream.Position = 0; shortLivedBackingStream.Position = 0; - yield return new ResourceDescription( + yield return (new ResourceDescription( moduleResource.Name, () => resourceStream, - moduleResource.IsPublic); + moduleResource.IsPublic), resourceStream); } } - private static IEnumerable GenerateManifestResources(string projectFilePath, string rootNamespace, IEnumerable embeddedResources) + private static IEnumerable<(ResourceDescription, object)> GenerateManifestResources(string projectFilePath, string rootNamespace, IEnumerable embeddedResources) { - var resources = new List(); + var resources = new List<(ResourceDescription, object)>(); foreach (var embeddedResource in embeddedResources) { var resourceFullFilename = Path.Combine(Path.GetDirectoryName(projectFilePath), embeddedResource); var resourceName = GenerateResourceName(embeddedResource); - resources.Add(new ResourceDescription( + resources.Add((new ResourceDescription( $"{rootNamespace}.{string.Join(".", resourceName.Split('\\'))}", () => ProvideResourceData(resourceFullFilename), - true)); + true), null)); } return resources; diff --git a/src/Stryker.Core/Stryker.Core/Mutants/CsharpMutantOrchestrator.cs b/src/Stryker.Core/Stryker.Core/Mutants/CsharpMutantOrchestrator.cs index fc36ddf506..ac0440b592 100644 --- a/src/Stryker.Core/Stryker.Core/Mutants/CsharpMutantOrchestrator.cs +++ b/src/Stryker.Core/Stryker.Core/Mutants/CsharpMutantOrchestrator.cs @@ -58,6 +58,8 @@ private static List BuildOrchestratorList() => new MemberAccessExpressionOrchestrator(), new MemberAccessExpressionOrchestrator(), new MemberAccessExpressionOrchestrator(), + new MemberAccessExpressionOrchestrator(t => t.IsKind(SyntaxKind.SuppressNullableWarningExpression)), + new ConditionalExpressionOrchestrator(), // ensure static constructs are marked properly new StaticFieldDeclarationOrchestrator(), new StaticConstructorOrchestrator(), diff --git a/src/Stryker.Core/Stryker.Core/Mutants/CsharpNodeOrchestrators/ConditionalExpressionOrchestrator.cs b/src/Stryker.Core/Stryker.Core/Mutants/CsharpNodeOrchestrators/ConditionalExpressionOrchestrator.cs new file mode 100644 index 0000000000..1a0605bbfd --- /dev/null +++ b/src/Stryker.Core/Stryker.Core/Mutants/CsharpNodeOrchestrators/ConditionalExpressionOrchestrator.cs @@ -0,0 +1,26 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Stryker.Core.Mutants.CsharpNodeOrchestrators; +internal class ConditionalExpressionOrchestrator :MemberAccessExpressionOrchestrator +{ + + protected override ExpressionSyntax OrchestrateChildrenMutation(ConditionalAccessExpressionSyntax node, SemanticModel semanticModel, + MutationContext context) + { + var mutated = node.ReplaceNodes(node.ChildNodes(), (original, _) => + { + if (original != node.WhenNotNull) + { + return context.Mutate(original, semanticModel); + } + // there must be some MemberBindingAccess in the chain, so we assume we are in a member access chain (no mutation injection) + var subContext = context.Enter(MutationControl.MemberAccess); + var result = subContext.Mutate(original, semanticModel); + subContext.Leave(); + return result; + + }); + return mutated; + } +} diff --git a/src/Stryker.Core/Stryker.Core/Mutants/CsharpNodeOrchestrators/ExpressionBodiedPropertyOrchestrator.cs b/src/Stryker.Core/Stryker.Core/Mutants/CsharpNodeOrchestrators/ExpressionBodiedPropertyOrchestrator.cs index e4278a260a..027514866c 100644 --- a/src/Stryker.Core/Stryker.Core/Mutants/CsharpNodeOrchestrators/ExpressionBodiedPropertyOrchestrator.cs +++ b/src/Stryker.Core/Stryker.Core/Mutants/CsharpNodeOrchestrators/ExpressionBodiedPropertyOrchestrator.cs @@ -39,9 +39,8 @@ protected override PropertyDeclarationSyntax OrchestrateChildrenMutation(Propert var children = node.ReplaceNodes(node.ChildNodes(), (original, _) => { var determinedContext = original == node.Initializer ? context.EnterStatic() : context; - return determinedContext.FindHandler(original).Mutate(original, semanticModel, determinedContext); + return determinedContext.Mutate(original, semanticModel); }); return children.WithInitializer(children.Initializer.WithValue(context.PlaceStaticContextMarker(children.Initializer.Value))); } - } diff --git a/src/Stryker.Core/Stryker.Core/Mutants/CsharpNodeOrchestrators/InvocationExpressionOrchestrator.cs b/src/Stryker.Core/Stryker.Core/Mutants/CsharpNodeOrchestrators/InvocationExpressionOrchestrator.cs index fd71eebdc5..837822b70f 100644 --- a/src/Stryker.Core/Stryker.Core/Mutants/CsharpNodeOrchestrators/InvocationExpressionOrchestrator.cs +++ b/src/Stryker.Core/Stryker.Core/Mutants/CsharpNodeOrchestrators/InvocationExpressionOrchestrator.cs @@ -5,20 +5,37 @@ namespace Stryker.Core.Mutants.CsharpNodeOrchestrators; -internal class InvocationExpressionOrchestrator: NodeSpecificOrchestrator +internal class InvocationExpressionOrchestrator: MemberAccessExpressionOrchestrator { - protected override ExpressionSyntax InjectMutations(InvocationExpressionSyntax sourceNode, ExpressionSyntax targetNode, SemanticModel semanticModel, MutationContext context) => context.InjectMutations(targetNode, sourceNode); - protected override MutationContext StoreMutations(InvocationExpressionSyntax node, IEnumerable mutations, MutationContext context) => - // if the expression contains a declaration, it must be controlled at the block level. + // if the invocation contains a declaration, it must be controlled at the block level. context.AddMutations(mutations, node.ArgumentList.ContainsDeclarations() ? MutationControl.Block : MutationControl.Expression); - protected override MutationContext PrepareContext(InvocationExpressionSyntax node, MutationContext context) => - // invocation with a member binding expression must be controlled at a higher expression level - base.PrepareContext(node, context.Enter(node.HasAMemberBindingExpression() ? MutationControl.MemberAccess : MutationControl.Expression)); - - protected override void RestoreContext(MutationContext context) => base.RestoreContext(context.Leave()); + protected override ExpressionSyntax OrchestrateChildrenMutation(InvocationExpressionSyntax node, SemanticModel semanticModel, + MutationContext context) + { + var mutated = node.ReplaceNodes(node.ChildNodes(), (original, _) => + { + if (original == node.Expression) + { + // we cannot mutate only the invoked method name, mutations must be controlled at the expression level + var subContext = context.Enter(MutationControl.MemberAccess); + var result = subContext.Mutate(original, semanticModel); + subContext.Leave(); + return result; + } + else + { + //The argument list can be freely mutated, + var subContext = context.Enter(MutationControl.Member); + var result = subContext.Mutate(original, semanticModel); + subContext.Leave(); + return result; + } + }); + return mutated; + } } diff --git a/src/Stryker.Core/Stryker.Core/Mutants/CsharpNodeOrchestrators/MemberAccessExpressionOrchestrator.cs b/src/Stryker.Core/Stryker.Core/Mutants/CsharpNodeOrchestrators/MemberAccessExpressionOrchestrator.cs index 3b6984e943..0c65fc869c 100644 --- a/src/Stryker.Core/Stryker.Core/Mutants/CsharpNodeOrchestrators/MemberAccessExpressionOrchestrator.cs +++ b/src/Stryker.Core/Stryker.Core/Mutants/CsharpNodeOrchestrators/MemberAccessExpressionOrchestrator.cs @@ -1,12 +1,27 @@ +using System; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Stryker.Core.Mutants.CsharpNodeOrchestrators; -internal class MemberAccessExpressionOrchestrator : NodeSpecificOrchestrator where T : ExpressionSyntax +internal class MemberAccessExpressionOrchestrator : NodeSpecificOrchestrator where T:ExpressionSyntax { - protected override bool CanHandle(T t) => t.Parent is MemberAccessExpressionSyntax or InvocationExpressionSyntax; + private readonly Func _predicate; - protected override MutationContext PrepareContext(T node, MutationContext context) => base.PrepareContext(node, context.Enter(MutationControl.MemberAccess)); + /// + /// Builds a MemberAccessExpressionOrchestrator instance + /// + /// optional predicate to control which nodes can be orchestrated + public MemberAccessExpressionOrchestrator(Func predicate = null) => _predicate = predicate; + + protected override bool CanHandle(T t) => _predicate==null || _predicate(t); + + protected override ExpressionSyntax InjectMutations(T sourceNode, ExpressionSyntax targetNode, SemanticModel semanticModel, MutationContext context) => context.InjectMutations(targetNode, sourceNode); + + protected override MutationContext PrepareContext(T node, MutationContext context) => + // we are at expression level, except if we are explicitly already in a member access chain + base.PrepareContext(node, context.Enter(context.CurrentControl != MutationControl.MemberAccess ? MutationControl.Expression : MutationControl.MemberAccess)); protected override void RestoreContext(MutationContext context) => base.RestoreContext(context.Leave()); + } diff --git a/src/Stryker.Core/Stryker.Core/Mutants/CsharpNodeOrchestrators/NodeSpecificOrchestrator.cs b/src/Stryker.Core/Stryker.Core/Mutants/CsharpNodeOrchestrators/NodeSpecificOrchestrator.cs index 148010402c..cfdb006690 100644 --- a/src/Stryker.Core/Stryker.Core/Mutants/CsharpNodeOrchestrators/NodeSpecificOrchestrator.cs +++ b/src/Stryker.Core/Stryker.Core/Mutants/CsharpNodeOrchestrators/NodeSpecificOrchestrator.cs @@ -79,7 +79,7 @@ internal class NodeSpecificOrchestrator : INodeOrchestrator where /// skip mutating the children node. protected virtual TBase OrchestrateChildrenMutation(TNode node, SemanticModel semanticModel, MutationContext context) => node.ReplaceNodes(node.ChildNodes(), - computeReplacementNode: (original, _) => context.FindHandler(original).Mutate(original, semanticModel, context)); + computeReplacementNode: (original, _) => context.Mutate(original, semanticModel)); /// /// Set up the mutation context before triggering mutation. diff --git a/src/Stryker.Core/Stryker.Core/Mutants/MutationContext.cs b/src/Stryker.Core/Stryker.Core/Mutants/MutationContext.cs index 0b5d16de46..913b61e0ab 100644 --- a/src/Stryker.Core/Stryker.Core/Mutants/MutationContext.cs +++ b/src/Stryker.Core/Stryker.Core/Mutants/MutationContext.cs @@ -60,6 +60,11 @@ private MutationContext(MutationContext parent) /// public bool HasLeftOverMutations => _mutation.HasPendingMutations(); + /// + /// Returns the current mutation control level + /// + public MutationControl CurrentControl => _mutation.CurrentControl; + /// /// Call this to generate mutations using active mutators. /// @@ -73,8 +78,9 @@ public IEnumerable GenerateMutantsForNode(SyntaxNode node, SemanticModel /// Find the appropriate node handler for the given node. /// /// handler for which to find an orchestrator. + /// /// A handler for this node. - public INodeOrchestrator FindHandler(SyntaxNode node) => _mainOrchestrator.GetHandler(node); + public SyntaxNode Mutate(SyntaxNode node, SemanticModel model) => _mainOrchestrator.GetHandler(node).Mutate(node, model, this); /// /// Call this to signal mutation occurs in static method or fields diff --git a/src/Stryker.Core/Stryker.Core/Mutants/MutationStore.cs b/src/Stryker.Core/Stryker.Core/Mutants/MutationStore.cs index 43c8d5a1de..28bf159212 100644 --- a/src/Stryker.Core/Stryker.Core/Mutants/MutationStore.cs +++ b/src/Stryker.Core/Stryker.Core/Mutants/MutationStore.cs @@ -60,6 +60,11 @@ internal class MutationStore /// public bool HasPendingMutations() => _pendingMutations.Count > 0 && _pendingMutations.Peek().Store.Count>0; + /// + /// Returns the current mutation control + /// + public MutationControl CurrentControl => _pendingMutations.Count > 0 ? _pendingMutations.Peek().Control : MutationControl.Member; + /// /// Enter a syntax level /// @@ -90,7 +95,7 @@ public void Leave() } else if (old.Store.Count > 0) { - Logger.LogError("Some mutations failed to be inserted, they are dropped."); + Logger.LogDebug("{0} mutation(s) could not be injected, they are dropped.", old.Store.Count); foreach (var mutant in old.Store) { mutant.ResultStatus = MutantStatus.CompileError; @@ -123,7 +128,7 @@ public bool StoreMutationsAtDesiredLevel(IEnumerable store, MutationCont controller.StoreMutations(store); return true; } - Logger.LogError($"There is no structure to control {store.Count()} mutations. They are dropped."); + Logger.LogDebug("There is no structure to control {0} mutations. They are dropped.", store.Count()); foreach (var mutant in store) { mutant.ResultStatus = MutantStatus.CompileError; diff --git a/src/Stryker.Core/Stryker.Core/TestRunners/VsTest/VsTestRunnerPool.cs b/src/Stryker.Core/Stryker.Core/TestRunners/VsTest/VsTestRunnerPool.cs index 4517fd10f2..240f61d120 100644 --- a/src/Stryker.Core/Stryker.Core/TestRunners/VsTest/VsTestRunnerPool.cs +++ b/src/Stryker.Core/Stryker.Core/TestRunners/VsTest/VsTestRunnerPool.cs @@ -154,10 +154,10 @@ private bool ConvertSingleResult(TestResult testResult, ISet seenTestCases var (key, value) = testResult.GetProperties().FirstOrDefault(x => x.Key.Id == CoverageCollector.PropertyName); var testCaseId = testResult.TestCase.Id; var unexpected = false; - var log = testResult.GetProperties().FirstOrDefault(x => x.Key.Id == CoverageCollector.Coveragelog).Value?.ToString(); + var log = testResult.GetProperties().FirstOrDefault(x => x.Key.Id == CoverageCollector.CoverageLog).Value?.ToString(); if (!string.IsNullOrEmpty(log)) { - _logger.LogError($"VsTestRunner: Coverage collector error: {log}."); + _logger.LogDebug("VsTestRunner: Coverage collector log: {0}.", log); } if (!Context.VsTests.ContainsKey(testCaseId)) diff --git a/src/Stryker.DataCollector/Stryker.DataCollector/CoverageCollector.cs b/src/Stryker.DataCollector/Stryker.DataCollector/CoverageCollector.cs index 9ce57e14dd..d60fd33794 100644 --- a/src/Stryker.DataCollector/Stryker.DataCollector/CoverageCollector.cs +++ b/src/Stryker.DataCollector/Stryker.DataCollector/CoverageCollector.cs @@ -36,7 +36,7 @@ public class CoverageCollector : InProcDataCollection public const string PropertyName = "Stryker.Coverage"; public const string OutOfTestsPropertyName = "Stryker.Coverage.OutOfTests"; - public const string Coveragelog = "CoverageLog"; + public const string CoverageLog = "CoverageLog"; public string MutantList => string.Join(",", _mutantTestedBy.Values.Distinct()); @@ -245,7 +245,7 @@ private void PublishCoverageData(DataCollectionContext dataCollectionContext) _dataSink.SendData(dataCollectionContext, PropertyName, ";"); if (!_reportFailure) { - _dataSink.SendData(dataCollectionContext, Coveragelog, $"Did not find type {_controlClassName}. This indicates Stryker failed to copy the mutated assembly for test."); + _dataSink.SendData(dataCollectionContext, CoverageLog, $"Did not find type {_controlClassName}. Mutated assembly may not be covered by any test."); _reportFailure = true; } return;