Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions TUnit.Core/Attributes/TestData/MatrixDataSourceAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public sealed class MatrixDataSourceAttribute : UntypedDataSourceGeneratorAttrib

foreach (var row in GetMatrixValues(parameterInformation.Select(p => GetAllArguments(dataGeneratorMetadata, p))))
{
if (exclusions.Any(e => e.SequenceEqual(row)))
if (exclusions.Any(e => IsExcluded(e, row)))
{
continue;
}
Expand All @@ -47,10 +47,39 @@ public sealed class MatrixDataSourceAttribute : UntypedDataSourceGeneratorAttrib
}
}

private bool IsExcluded(object?[] exclusion, IEnumerable<object?> row)
{
var rowArray = row.ToArray();
if (exclusion.Length != rowArray.Length)
{
return false;
}

for (int i = 0; i < exclusion.Length; i++)
{
var exclusionValue = exclusion[i];
var rowValue = rowArray[i];

// Handle enum to underlying type conversion
if (exclusionValue != null && exclusionValue.GetType().IsEnum && rowValue != null)
{
exclusionValue = Convert.ChangeType(exclusionValue, Enum.GetUnderlyingType(exclusionValue.GetType()));
}

if (!Equals(exclusionValue, rowValue))
{
return false;
}
}

return true;
}

private object?[][] GetExclusions(IEnumerable<Attribute> attributes)
{
return attributes
.OfType<MatrixExclusionAttribute>()
.Where(x => x is MatrixExclusionAttribute)
.Cast<MatrixExclusionAttribute>()
.Select(x => x.Objects)
.ToArray();
}
Expand Down
51 changes: 51 additions & 0 deletions TUnit.TestProject/MatrixExclusionBugTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using TUnit.Core;

namespace TUnit.TestProject;

public enum Status
{
Draft,
Pending,
Published,
Archived,
Deleted
}

// This is what the user might expect to work - a custom exclusion attribute
public class MatrixExclusionStatusAttribute : MatrixExclusionAttribute
{
public MatrixExclusionStatusAttribute(Status status) : base(status)
{
}
}

public class MatrixExclusionBugTest
{
[Test]
[MatrixDataSource]
[MatrixExclusionStatus(Status.Draft)]
public async Task Should_Filter_By_Status(Status status)
{
// Should generate 4 tests (all statuses except Draft)
// If this test runs with Status.Draft, the bug is NOT fixed
if (status == Status.Draft)
{
throw new InvalidOperationException("Draft status should have been excluded but was not!");
}
await Task.CompletedTask;
}

[Test]
[MatrixDataSource]
[MatrixExclusion(Status.Draft)] // This should work with the base attribute
public async Task Should_Filter_By_Status_Base(Status status)
{
// Should generate 4 tests (all statuses except Draft)
// If this test runs with Status.Draft, the bug is NOT fixed
if (status == Status.Draft)
{
throw new InvalidOperationException("Draft status should have been excluded but was not!");
}
await Task.CompletedTask;
}
}
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "9.0.303",
"version": "9.0.302",
"rollForward": "latestFeature"
}
}
Loading