Skip to content

IAsyncCleanableExtension::CleanupAsync method is called twice #6181

@filzrev

Description

@filzrev

Describe the bug

When MTP extension implements both ITestHostApplicationLifetime/IAsyncCleanableExtension.
IAsyncCleanableExtension::CleanupAsync method seems to be called twice.

It's confirmed it can reproduced on version 2.0.0-preview.25372.6.
And it also reproduced with version 1.7.2 (Using ITestApplicationLifecycleCallbacks)

Steps To Reproduce

1. Create console application
2. Reference Microsoft.Testing.Platform 2.0.0-preview.25372.6 package
3. Paste following test code and run console app

using Microsoft.Testing.Platform.Builder;
using Microsoft.Testing.Platform.Capabilities.TestFramework;
using Microsoft.Testing.Platform.Extensions;
using Microsoft.Testing.Platform.Extensions.Messages;
using Microsoft.Testing.Platform.Extensions.TestFramework;
using Microsoft.Testing.Platform.Extensions.TestHost;
using Microsoft.Testing.Platform.Requests;

namespace TestConsoleApp;

#pragma  warning disable TPEXP

internal class Program
{
    static async Task<int> Main(string[] args)
    {
        var builder = await TestApplication.CreateBuilderAsync(args);

        var testFramework = new DummyTestAdapter();
        builder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, _) => testFramework);

        var myExtension = new MyExtension(testFramework);

        builder.TestHost.AddTestHostApplicationLifetime(_ => myExtension);
        // builder.TestHost.AddDataConsumer(_ => myExtension);

        var app = await builder.BuildAsync();
        return await app.RunAsync();
    }
}

internal class MyExtension(IExtension extension) : ITestHostApplicationLifetime, IAsyncCleanableExtension
{
    public Task<bool> IsEnabledAsync() => extension.IsEnabledAsync();
    public string Uid => extension.Uid;
    public string Version => extension.Version;
    public string DisplayName => extension.DisplayName;
    public string Description => extension.Description;

    public Task BeforeRunAsync(CancellationToken cancellationToken)
    {
        Console.WriteLine("BeforeRunAsync");
        return Task.CompletedTask;
    }

    public Task AfterRunAsync(int exitCode, CancellationToken cancellation)
    {
        Console.WriteLine("AfterRunAsync");
        return Task.CompletedTask;
    }

    public Task CleanupAsync()
    {
        Console.WriteLine("CleanupAsync");
        return Task.CompletedTask;
    }
}

internal class DummyTestAdapter : ITestFramework, IDataProducer
{
    public Task<bool> IsEnabledAsync() => Task.FromResult(true);
    public string Uid => nameof(DummyTestAdapter);
    public string Version => string.Empty;
    public string DisplayName => string.Empty;
    public string Description => string.Empty;

    public Type[] DataTypesProduced => [typeof(TestNodeUpdateMessage)];
    public Task<CloseTestSessionResult> CloseTestSessionAsync(CloseTestSessionContext context) => Task.FromResult(new CloseTestSessionResult { IsSuccess = true });
    public Task<CreateTestSessionResult> CreateTestSessionAsync(CreateTestSessionContext context) => Task.FromResult(new CreateTestSessionResult { IsSuccess = true });

    public async Task ExecuteRequestAsync(ExecuteRequestContext context)
    {
        switch (context.Request)
        {
            case DiscoverTestExecutionRequest discoverRequest:
            case RunTestExecutionRequest runRequest:
                await Task.Yield();
                //await HandleRequest(context);
                break;
            default:
                break;
        }

        context.Complete();
    }
}

Expected behavior

CleanupAsync is expected to be called exactly once.
Because CleanupAsync method has no special note that
it may be called multiple times like Dispose/DisposeAsync.

Actual behavior

CleanupAsync log outputted twice..

Additional context

It seems to be disposed at following lines.

Additionally,
Following lines seems redundant because it checks same types.
https://github.com/microsoft/testfx/blob/v4.0.0-preview.25372.6/src/Platform/Microsoft.Testing.Platform/Hosts/CommonTestHost.cs#L246-L247

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions