Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into nuget_logic_cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
dupdob committed Oct 21, 2024
2 parents 39553d5 + d1a9ade commit 0fc10c5
Show file tree
Hide file tree
Showing 29 changed files with 1,723 additions and 61 deletions.
2 changes: 2 additions & 0 deletions docs/mutations.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ Do you have a suggestion for a (new) mutator? Feel free to create an [issue](htt
| `ElementAt()` | `'\0'` |
| `ElementAtOrDefault()` | `'\0'` |
| `EndsWith()` | `StartsWith()` |
| `IndexOf()` | `LastIndexOf()` |
| `LastIndexOf()` | `IndexOf()` |
| `PadLeft()` | `PadRight()` |
| `PadRight()` | `PadLeft()` |
| `StartsWith()` | `EndsWith()` |
Expand Down
108 changes: 108 additions & 0 deletions docs/regex-mutations.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,111 @@ Stryker supports a variety of regular expression mutators, which are listed belo
| `(?!abc)` | `(?=abc)` |
| `(?<=abc)` | `(?<!abc)` |
| `(?<!abc)` | `(?<=abc)` |

## Character class mutators

### CharClassChildRemoval

Remove a child of a character class.

| Original | Mutated |
|----------|---------|
| `[abc]` | `[bc]` |
| `[abc]` | `[ac]` |
| `[abc]` | `[ab]` |

### CharClassAnyChar

Change a character class to a character class which matches any character.

| Original | Mutated |
|----------|----------|
| `[abc]` | `[\w\W]` |

### CharClassRangeModification

Change the high and low of a range by one in both directions if possible.

| Original | Mutated |
|----------|---------|
| `[b-y]` | `[a-y]` |
| `[b-y]` | `[c-y]` |
| `[b-y]` | `[b-z]` |
| `[b-y]` | `[b-x]` |

## Predefined character class mutators

### PredefCharClassNullification

Remove the backslash from a predefined character class such as `\w`.

| Original | Mutated |
|----------|---------|
| `\d` | `d` |
| `\D` | `D` |
| `\s` | `s` |
| `\S` | `S` |
| `\w` | `w` |
| `\W` | `W` |

### PredefCharClassAnyChar

Change a predefined character class to a character class containing the predefined one and its
negation.

| Original | Mutated |
|----------|----------|
| `\d` | `[\d\D]` |
| `\D` | `[\D\d]` |
| `\s` | `[\s\S]` |
| `\S` | `[\S\s]` |
| `\w` | `[\w\W]` |
| `\W` | `[\W\w]` |

### UnicodeCharClassNegation

Flips the sign of a Unicode character class.

| Original | Mutated |
|-------------|-------------|
| `\p{Alpha}` | `\P{Alpha}` |
| `\P{Alpha}` | `\p{Alpha}` |

## Quantifier mutators

### QuantifierShortModification

Treat the shorthand quantifiers (`?`, `*`, `+`) as their corresponding range quantifier
variant (`{0,1}`, `{0,}`, `{1,}`), and applies other mutations to the new node.

| Original | Mutated |
|----------|------------|
| `abc?` | `abc{1,1}` |
| `abc?` | `abc{0,0}` |
| `abc?` | `abc{0,2}` |
| `abc*` | `abc{1,}` |
| `abc+` | `abc{0,}` |
| `abc+` | `abc{2,}` |

### QuantifierReluctantAddition

Change greedy quantifiers to reluctant quantifiers.

| Original | Mutated |
|-------------|--------------|
| `abc?` | `abc??` |
| `abc*` | `abc*?` |
| `abc+` | `abc+?` |
| `abc{9}` | `abc{9}?` |
| `abc{9,}` | `abc{9,}?` |
| `abc{9,13}` | `abc{9,13}?` |

## Group-related construct mutators

### GroupToNCGroup

Change a normal group to a non-capturing group.

| Original | Mutated |
|----------|-----------|
| `(abc)` | `(?:abc)` |
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ public int Subtract(int first, int second)
}

[TestMethod]
public void CompilingProcessTests_ShouldSupportReferenceAliases()
public void CompilingProcessTests_ShouldSupportPackageReferenceAliases()
{
var syntaxTree = CSharpSyntaxTree.ParseText(@"
extern alias Texte;
using System;
extern alias TestAlias;
using TestAlias::System;
namespace ExampleProject
{
Expand All @@ -97,16 +97,31 @@ public int Subtract(int first, int second)
properties: new Dictionary<string, string>()
{
{ "TargetDir", "" },
{ "AssemblyName", "AssemblyName"},
{ "TargetFileName", "TargetFileName.dll"},
{ "AssemblyName", "AssemblyName" },
{ "TargetFileName", "TargetFileName.dll" },
},
// add a reference to system so the example code can compile
references: new[] { typeof(object).Assembly.Location, $"Texte={typeof(StringBuilder).Assembly.Location}" }
references: new[] { typeof(object).Assembly.Location },
packageReferences: new ReadOnlyDictionary<string, IReadOnlyDictionary<string, string>>(
new Dictionary<string, IReadOnlyDictionary<string, string>>
{
{
typeof(object).Assembly.GetName().Name,
new ReadOnlyDictionary<string, string>(
new Dictionary<string, string>
{
{ "Aliases", "TestAlias" }
}
)
}
}
)
).Object
}
};
var rollbackProcessMock = new Mock<ICSharpRollbackProcess>(MockBehavior.Strict);


var target = new CsharpCompilingProcess(input, rollbackProcessMock.Object);

using (var ms = new MemoryStream())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ void TestMethod() {
"String Method Mutation (Replace ToLowerInvariant() with ToUpperInvariant())")]
[DataRow("testString.PadLeft(10)", "PadRight", "String Method Mutation (Replace PadLeft() with PadRight())")]
[DataRow("testString.PadRight(10)", "PadLeft", "String Method Mutation (Replace PadRight() with PadLeft())")]
[DataRow("testString.LastIndexOf(c)", "IndexOf", "String Method Mutation (Replace LastIndexOf() with IndexOf())")]
[DataRow("testString.IndexOf(c)", "LastIndexOf", "String Method Mutation (Replace IndexOf() with LastIndexOf())")]
public void ShouldMutateStringMethods(string expression, string mutatedMethod, string expectedDisplayName)
{
var (semanticModel, expressionSyntax) = CreateSemanticModelFromExpression(expression);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,26 @@ public static IEnumerable<MetadataReference> LoadReferences(this IAnalyzerResult
{
foreach (var reference in analyzerResult.References)
{
if (reference.Contains('='))
var referenceFileNameWithoutExtension = Path.GetFileNameWithoutExtension(reference);
string packageWithAlias = null;

if (analyzerResult.PackageReferences is not null)
{
// Check for any matching package reference with an alias using LINQ
packageWithAlias = analyzerResult.PackageReferences
.Where(pr => pr.Key == referenceFileNameWithoutExtension && pr.Value.ContainsKey("Aliases"))
.Select(pr => pr.Value["Aliases"])
.FirstOrDefault();
}

if (packageWithAlias is not null)
{
// we have an alias
var split = reference.Split('=');
var aliases = split[0].Split(',');
yield return MetadataReference.CreateFromFile(split[1]).WithAliases(aliases);
// Return the reference with the alias
yield return MetadataReference.CreateFromFile(reference).WithAliases(new[] { packageWithAlias });
}
else
{
// If no alias is found, return the reference without aliases
yield return MetadataReference.CreateFromFile(reference);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
Expand Down Expand Up @@ -63,6 +63,8 @@ private static string GetReplacement(string identifier) =>
"ToLowerInvariant" => "ToUpperInvariant",
"PadLeft" => "PadRight",
"PadRight" => "PadLeft",
"IndexOf" => "LastIndexOf",
"LastIndexOf" => "IndexOf",
_ => null
};

Expand Down
Loading

0 comments on commit 0fc10c5

Please sign in to comment.