Skip to content

Commit

Permalink
Incorrect coverage for methods returning IAsyncEnumerable in generic …
Browse files Browse the repository at this point in the history
…classes (#1430)
  • Loading branch information
daveMueller authored Jan 19, 2023
1 parent 72d5ee2 commit 04b82c2
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 3 deletions.
1 change: 1 addition & 0 deletions Documentation/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased

### Fixed
-Incorrect coverage for methods returning IAsyncEnumerable in generic classes [#1383](https://github.com/coverlet-coverage/coverlet/issues/1383)
-Allign published nuget package version to github release version [#1413](https://github.com/coverlet-coverage/coverlet/issues/1413)
-Sync nuget and github release versions [#1122](https://github.com/coverlet-coverage/coverlet/issues/1122)

Expand Down
6 changes: 4 additions & 2 deletions src/coverlet.core/Symbols/CecilSymbolHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -877,8 +877,10 @@ static bool DisposeCheck(List<Instruction> instructions, Instruction instruction

if (currentIndex >= 2 &&
instructions[currentIndex - 1].OpCode == OpCodes.Ldfld &&
instructions[currentIndex - 1].Operand is FieldDefinition field &&
IsCompilerGenerated(field) && field.FullName.EndsWith("__disposeMode") &&
(
(instructions[currentIndex - 1].Operand is FieldDefinition field && IsCompilerGenerated(field) && field.FullName.EndsWith("__disposeMode")) ||
(instructions[currentIndex - 1].Operand is FieldReference fieldRef && IsCompilerGenerated(fieldRef.Resolve()) && fieldRef.FullName.EndsWith("__disposeMode"))
) &&
(instructions[currentIndex - 2].OpCode == OpCodes.Ldarg ||
instructions[currentIndex - 2].OpCode == OpCodes.Ldarg_0))
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) Toni Solarin-Sodara
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Coverlet.Core.Samples.Tests;
using Xunit;

namespace Coverlet.Core.Tests
{
public partial class CoverageTests
{
[Fact]
public void GenericAsyncIterator()
{
string path = Path.GetTempFileName();
try
{
FunctionExecutor.Run(async (string[] pathSerialize) =>
{
CoveragePrepareResult coveragePrepareResult = await TestInstrumentationHelper.Run<GenericAsyncIterator<int>>(instance =>
{
List<int> res = ((Task<List<int>>)instance.Issue1383()).GetAwaiter().GetResult();
return Task.CompletedTask;
}, persistPrepareResultToFile: pathSerialize[0]);
return 0;
}, new string[] { path });

TestInstrumentationHelper.GetCoverageResult(path)
.Document("Instrumentation.GenericAsyncIterator.cs")
.AssertLinesCovered(BuildConfiguration.Debug, (13, 1), (14, 1), (20, 1), (21, 1), (22, 1))
.ExpectedTotalNumberOfBranches(BuildConfiguration.Debug, 0);
}
finally
{
File.Delete(path);
}
}
}
}
13 changes: 12 additions & 1 deletion test/coverlet.core.tests/Coverage/InstrumenterHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public static async Task<CoveragePrepareResult> Run<T>(Func<dynamic, Task> callM
IncludeFilters = (includeFilter is null ? defaultFilters(fileName) : includeFilter(fileName)).Concat(
new string[]
{
$"[{Path.GetFileNameWithoutExtension(fileName)}*]{typeof(T).FullName}*"
$"[{Path.GetFileNameWithoutExtension(fileName)}*]{GetTypeFullName<T>()}*"
}).ToArray(),
IncludeDirectories = Array.Empty<string>(),
ExcludeFilters = (excludeFilter is null ? defaultFilters(fileName) : excludeFilter(fileName)).Concat(new string[]
Expand Down Expand Up @@ -180,6 +180,17 @@ private static void SetTestContainer(string testModule = null, bool disableResto
return serviceCollection.BuildServiceProvider();
});
}

private static string GetTypeFullName<T>()
{
string name = typeof(T).FullName;
if (typeof(T).IsGenericType && name != null)
{
int index = name.IndexOf('`');
return index == -1 ? name : name[..index];
}
return name;
}
}

class CustomProcessExitHandler : IProcessExitHandler
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Remember to use full name because adding new using directives change line numbers

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Coverlet.Core.Samples.Tests
{
public class GenericAsyncIterator<T>
{
public async Task<List<int>> Issue1383()
{
var sequence = await CreateSequenceAsync().ToListAsync();
return sequence;
}


public async IAsyncEnumerable<int> CreateSequenceAsync()
{
await Task.CompletedTask;
yield return 5;
yield return 2;
}
}
}

0 comments on commit 04b82c2

Please sign in to comment.