Skip to content
Open
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
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
<PackageVersion Include="Microsoft.TestPlatform.TranslationLayer" Version="$(MicrosoftNETTestSdkVersion)" />
<PackageVersion Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.6.240923002" />
<PackageVersion Include="OpenTelemetry" Version="1.12.0" />
<PackageVersion Include="Polyfill" Version="9.0.0-beta.14" />
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="$(SystemThreadingTasksExtensionsVersion)" />
</ItemGroup>
Expand Down
25 changes: 13 additions & 12 deletions TestFx.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<File Path="global.json" />
<File Path="Nuget.config" />
</Folder>
<Folder Name="/Solution Items/eng/" Id="5450f9c7-f297-9839-c636-5c9c04a5ba28">
<Folder Name="/Solution Items/eng/">
<File Path="eng/AfterSolutionBuild.targets" />
<File Path="eng/Analyzers.props" />
<File Path="eng/Build.props" />
Expand All @@ -23,21 +23,22 @@
<File Path="eng/Versions.props" />
<File Path="eng/write-release-notes.ps1" />
</Folder>
<Folder Name="/Solution Items/eng/TestingPlatformRunner/" Id="a7b54d83-9a9c-527b-00f3-bda998e116c9">
<Folder Name="/Solution Items/eng/TestingPlatformRunner/">
<File Path="eng/TestingPlatformRunner/TestingPlatform.Runner.targets" />
<File Path="eng/TestingPlatformRunner/TestingPlatformRunner.targets" />
</Folder>
<Folder Name="/src/">
<File Path="src/.editorconfig" />
<File Path="src/Directory.Build.props" />
</Folder>
<Folder Name="/src/1 - Platform and Extensions/" Id="4272bbd9-efdb-ae85-3883-a1ab2fbd20bd">
<Folder Name="/src/1 - Platform and Extensions/">
<File Path="src/Platform/Directory.Build.props" />
<Project Path="src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/Microsoft.Testing.Extensions.AzureDevOpsReport.csproj" />
<Project Path="src/Platform/Microsoft.Testing.Extensions.CrashDump/Microsoft.Testing.Extensions.CrashDump.csproj" />
<Project Path="src/Platform/Microsoft.Testing.Extensions.HangDump/Microsoft.Testing.Extensions.HangDump.csproj" />
<Project Path="src/Platform/Microsoft.Testing.Extensions.HotReload/Microsoft.Testing.Extensions.HotReload.csproj" />
<Project Path="src/Platform/Microsoft.Testing.Extensions.MSBuild/Microsoft.Testing.Extensions.MSBuild.csproj" />
<Project Path="src/Platform/Microsoft.Testing.Extensions.OpenTelemetry/Microsoft.Testing.Extensions.OpenTelemetry.csproj" Id="88c15bf6-622e-4b3c-bdbb-fe20e5ac4f45" />
<Project Path="src/Platform/Microsoft.Testing.Extensions.Retry/Microsoft.Testing.Extensions.Retry.csproj" />
<Project Path="src/Platform/Microsoft.Testing.Extensions.Telemetry/Microsoft.Testing.Extensions.Telemetry.csproj" />
<Project Path="src/Platform/Microsoft.Testing.Extensions.TrxReport.Abstractions/Microsoft.Testing.Extensions.TrxReport.Abstractions.csproj" />
Expand All @@ -46,16 +47,16 @@
<Project Path="src/Platform/Microsoft.Testing.Platform.MSBuild/Microsoft.Testing.Platform.MSBuild.csproj" />
<Project Path="src/Platform/Microsoft.Testing.Platform/Microsoft.Testing.Platform.csproj" />
</Folder>
<Folder Name="/src/2 - Adapter/" Id="f7cf448e-306d-5d9b-7166-fa7205a8989c">
<Folder Name="/src/2 - Adapter/">
<Project Path="src/Adapter/MSTest.Engine/MSTest.Engine.csproj" />
<Project Path="src/Adapter/MSTest.TestAdapter/MSTest.TestAdapter.csproj" />
<Project Path="src/Adapter/MSTestAdapter.PlatformServices/MSTestAdapter.PlatformServices.csproj" />
</Folder>
<Folder Name="/src/3 - TestFramework/" Id="f28cc185-255f-b581-6ed3-c247f7096eb1">
<Folder Name="/src/3 - TestFramework/">
<Project Path="src/TestFramework/TestFramework.Extensions/TestFramework.Extensions.csproj" />
<Project Path="src/TestFramework/TestFramework/TestFramework.csproj" />
</Folder>
<Folder Name="/src/4 - Analyzers/" Id="9c73ee5c-ce16-2586-eb05-df3b4306d351">
<Folder Name="/src/4 - Analyzers/">
<Project Path="src/Analyzers/MSTest.Analyzers.CodeFixes/MSTest.Analyzers.CodeFixes.csproj" />
<Project Path="src/Analyzers/MSTest.Analyzers.Package/MSTest.Analyzers.Package.csproj">
<BuildDependency Project="src/Analyzers/MSTest.GlobalConfigsGenerator/MSTest.GlobalConfigsGenerator.csproj" />
Expand All @@ -64,7 +65,7 @@
<Project Path="src/Analyzers/MSTest.GlobalConfigsGenerator/MSTest.GlobalConfigsGenerator.csproj" />
<Project Path="src/Analyzers/MSTest.SourceGeneration/MSTest.SourceGeneration.csproj" />
</Folder>
<Folder Name="/src/5 - Package/" Id="87d92690-a0c0-3299-b302-eb18ebf7ffb3">
<Folder Name="/src/5 - Package/">
<Project Path="src/Package/MSTest.Sdk/MSTest.Sdk.csproj" />
<Project Path="src/Package/MSTest/MSTest.csproj" />
</Folder>
Expand All @@ -73,14 +74,14 @@
<File Path="test/Directory.Build.props" />
<File Path="test/Directory.Build.targets" />
</Folder>
<Folder Name="/test/IntegrationTests/" Id="334eb2cc-8f21-7cba-1333-4c64d82c9f9a">
<Folder Name="/test/IntegrationTests/">
<Project Path="test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests.csproj" />
<Project Path="test/IntegrationTests/MSTest.Acceptance.IntegrationTests/MSTest.Acceptance.IntegrationTests.csproj" />
<Project Path="test/IntegrationTests/MSTest.IntegrationTests/MSTest.IntegrationTests.csproj" />
<Project Path="test/IntegrationTests/MSTest.VstestConsoleWrapper.IntegrationTests/MSTest.VstestConsoleWrapper.IntegrationTests.csproj" />
<Project Path="test/IntegrationTests/PlatformServices.Desktop.IntegrationTests/PlatformServices.Desktop.IntegrationTests.csproj" />
</Folder>
<Folder Name="/test/IntegrationTests/TestAssets/" Id="05959510-e531-ecb6-7089-da3b202e43db">
<Folder Name="/test/IntegrationTests/TestAssets/">
<File Path="test/IntegrationTests/TestAssets/Directory.Build.targets" />
<Project Path="test/IntegrationTests/TestAssets/ClsTestProject/ClsTestProject.csproj" />
<Project Path="test/IntegrationTests/TestAssets/DataRowTestProject/DataRowTestProject.csproj" />
Expand Down Expand Up @@ -110,15 +111,15 @@
<Project Path="test/IntegrationTests/TestAssets/TestProject/TestProjectForDiscovery.csproj" />
<Project Path="test/IntegrationTests/TestAssets/TimeoutTestProject/TimeoutTestProject.csproj" />
</Folder>
<Folder Name="/test/Performance/" Id="5e428a24-a249-2472-0469-8a6e9a79c114">
<Folder Name="/test/Performance/">
<Project Path="test/Performance/MSTest.Performance.Runner/MSTest.Performance.Runner.csproj" />
</Folder>
<Folder Name="/test/TestUtilities/" Id="f47f7890-75b5-78d9-9d83-447eee1edf9f">
<Folder Name="/test/TestUtilities/">
<Project Path="test/Utilities/Automation.CLI/Automation.CLI.csproj" />
<Project Path="test/Utilities/Microsoft.Testing.TestInfrastructure/Microsoft.Testing.TestInfrastructure.csproj" />
<Project Path="test/Utilities/TestFramework.ForTestingMSTest/TestFramework.ForTestingMSTest.csproj" />
</Folder>
<Folder Name="/test/UnitTests/" Id="afae3f01-5c40-22b5-606d-a848a5891b0a">
<Folder Name="/test/UnitTests/">
<Project Path="test/UnitTests/Microsoft.Testing.Extensions.UnitTests/Microsoft.Testing.Extensions.UnitTests.csproj" />
<Project Path="test/UnitTests/Microsoft.Testing.Extensions.VSTestBridge.UnitTests/Microsoft.Testing.Extensions.VSTestBridge.UnitTests.csproj" />
<Project Path="test/UnitTests/Microsoft.Testing.Platform.MSBuild.UnitTests/Microsoft.Testing.Platform.MSBuild.UnitTests.csproj" />
Expand Down
2 changes: 2 additions & 0 deletions samples/Playground/Playground.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@
<ProjectReference Include="$(RepoRoot)src\Analyzers\MSTest.Analyzers\MSTest.Analyzers.csproj" PrivateAssets="all" ReferenceOutputAssembly="false" OutputItemType="Analyzer" />
<PackageReference Include="StreamJsonRpc" />
<ProjectReference Include="$(RepoRoot)src\Platform\Microsoft.Testing.Extensions.Telemetry\Microsoft.Testing.Extensions.Telemetry.csproj" />
<ProjectReference Include="$(RepoRoot)src\Platform\Microsoft.Testing.Extensions.OpenTelemetry\Microsoft.Testing.Extensions.OpenTelemetry.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" VersionOverride="$(MicrosoftNETTestSdkVersion)" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" VersionOverride="1.12.0" />
</ItemGroup>

<ItemGroup>
Expand Down
25 changes: 24 additions & 1 deletion samples/Playground/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,22 @@
using Microsoft.Testing.Platform.Extensions.TestFramework;
using Microsoft.Testing.Platform.Extensions.TestHostControllers;
using Microsoft.Testing.Platform.Messages;

#if NETCOREAPP
using Microsoft.Testing.Platform.ServerMode.IntegrationTests.Messages.V100;

using MSTest.Acceptance.IntegrationTests.Messages.V100;
#endif

using Microsoft.Testing.Extensions;
using Microsoft.Testing.Platform.Services;
using Microsoft.Testing.Platform.TestHost;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;

namespace Playground;

public class Program
Expand All @@ -38,13 +47,27 @@ public static async Task<int> Main(string[] args)
// testApplicationBuilder.RegisterTestFramework(_ => new TestFrameworkCapabilities(), (_, _) => new DummyAdapter());

// Custom test host controller extension
// testApplicationBuilder.TestHostControllers.AddProcessLifetimeHandler(s => new OutOfProc(s.GetMessageBus()));
testApplicationBuilder.TestHostControllers.AddProcessLifetimeHandler(s => new OutOfProc(s.GetMessageBus()));

// Enable Trx
// testApplicationBuilder.AddTrxReportProvider();

// Enable Telemetry
// testApplicationBuilder.AddAppInsightsTelemetryProvider();

// Enable OTel
testApplicationBuilder.AddOpenTelemetryProvider(
tracing =>
{
tracing.AddTestingPlatformInstrumentation();
tracing.AddOtlpExporter();
},
metrics =>
{
metrics.AddTestingPlatformInstrumentation();
metrics.AddOtlpExporter();
});

using ITestApplication testApplication = await testApplicationBuilder.BuildAsync();
return await testApplication.RunAsync();
}
Expand Down
2 changes: 2 additions & 0 deletions samples/Playground/Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public class TestClass
[DynamicData(nameof(Data))]
public void Test3(int a, int b)
{
Thread.Sleep(5000);
Assert.IsPositive(a);
}

public static IEnumerable<(int A, int B)> Data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Microsoft.Testing.Platform.OutputDevice;
using Microsoft.Testing.Platform.Requests;
using Microsoft.Testing.Platform.Services;
using Microsoft.Testing.Platform.Telemetry;

namespace Microsoft.Testing.Extensions.Hosting;

Expand All @@ -28,12 +29,12 @@ private static bool IsHotReloadEnabled(IEnvironment environment)
=> environment.GetEnvironmentVariable(EnvironmentVariableConstants.DOTNET_WATCH) == "1"
|| environment.GetEnvironmentVariable(EnvironmentVariableConstants.TESTINGPLATFORM_HOTRELOAD_ENABLED) == "1";

public override async Task ExecuteRequestAsync(ITestFramework testFrameworkAdapter, TestExecutionRequest request,
public override async Task ExecuteRequestAsync(ITestFramework testFramework, TestExecutionRequest request,
IMessageBus messageBus, CancellationToken cancellationToken)
{
if (!_isHotReloadEnabled)
{
await base.ExecuteRequestAsync(testFrameworkAdapter, request, messageBus, cancellationToken).ConfigureAwait(false);
await base.ExecuteRequestAsync(testFramework, request, messageBus, cancellationToken).ConfigureAwait(false);
return;
}

Expand All @@ -44,16 +45,21 @@ public override async Task ExecuteRequestAsync(ITestFramework testFrameworkAdapt
while (await hotReloadHandler.ShouldRunAsync(executionCompleted?.Task, cancellationToken).ConfigureAwait(false))
{
executionCompleted = new();
using SemaphoreSlim requestSemaphore = new(1);
var hotReloadOutputDevice = ServiceProvider.GetPlatformOutputDevice() as IHotReloadPlatformOutputDevice;
if (hotReloadOutputDevice is not null)
{
await hotReloadOutputDevice.DisplayBeforeHotReloadSessionStartAsync(cancellationToken).ConfigureAwait(false);
}

await testFrameworkAdapter.ExecuteRequestAsync(new(request, messageBus, new SemaphoreSlimRequestCompleteNotifier(requestSemaphore), cancellationToken)).ConfigureAwait(false);
IPlatformOpenTelemetryService? otelService = ServiceProvider.GetPlatformOTelService();
using (IActivity? testFrameworkActivity = otelService?.StartActivity("TestFramework", testFramework.ToOTelTags()))
{
using SemaphoreSlim requestSemaphore = new(1);
otelService?.TestFrameworkActivity = testFrameworkActivity;
await testFramework.ExecuteRequestAsync(new(request, messageBus, new SemaphoreSlimRequestCompleteNotifier(requestSemaphore), cancellationToken)).ConfigureAwait(false);
await requestSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
}

await requestSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
await ServiceProvider.GetBaseMessageBus().DrainDataAsync().ConfigureAwait(false);
if (hotReloadOutputDevice is not null)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Microsoft.Testing.Platform.Telemetry;

namespace Microsoft.Testing.Extensions.OpenTelemetry;

internal sealed class ActivityWrapper(Activity activity) : IActivity
{
public string? Id => activity.Id;

public IActivity SetTag(string key, object? value)
{
activity.SetTag(key, value);
return this;
}

public void Dispose() => activity.Dispose();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
M:System.String.IsNullOrEmpty(System.String); Use 'TAString.IsNullOrEmpty' instead
M:System.String.IsNullOrWhiteSpace(System.String); Use 'TAString.IsNullOrWhiteSpace' instead
M:System.Diagnostics.Debug.Assert(System.Boolean); Use 'RoslynDebug.Assert' instead
M:System.Diagnostics.Debug.Assert(System.Boolean,System.String); Use 'RoslynDebug.Assert' instead
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Diagnostics.Metrics;

using Microsoft.Testing.Platform.Telemetry;

namespace Microsoft.Testing.Extensions.OpenTelemetry;

internal sealed class CounterWrapper<T> : ICounter<T>
where T : struct
{
private readonly Counter<T> _counter;

public CounterWrapper(Counter<T> counter)
=> _counter = counter
?? throw new ArgumentNullException(nameof(counter));

public void Add(T delta) => _counter.Add(delta);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Diagnostics.Metrics;

using Microsoft.Testing.Platform.Telemetry;

namespace Microsoft.Testing.Extensions.OpenTelemetry;

internal sealed class HistogramWrapper<T> : IHistogram<T>
where T : struct
{
private readonly Histogram<T> _histogram;

public HistogramWrapper(Histogram<T> histogram)
=> _histogram = histogram
?? throw new ArgumentNullException(nameof(histogram));

public void Record(T value)
=> _histogram.Record(value);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.0;$(MicrosoftTestingTargetFrameworks)</TargetFrameworks>
</PropertyGroup>

<!-- NuGet properties -->
<PropertyGroup>
<PackageDescription>
<![CDATA[Microsoft Testing is a set of platform, framework and protocol intended to make it possible to run any test on any target or device.

This package provides Open Telemetry for the platform.]]>
</PackageDescription>
</PropertyGroup>

<ItemGroup>
<InternalsVisibleTo Include="Microsoft.Testing.Extensions.UnitTests" Key="$(VsPublicKey)" />
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" Key="$(MoqPublicKey)" />
</ItemGroup>

<ItemGroup>
<AdditionalFiles Include="BannedSymbols.txt" />
<AdditionalFiles Include="PublicAPI/PublicAPI.Shipped.txt" />
<AdditionalFiles Include="PublicAPI/PublicAPI.Unshipped.txt" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="OpenTelemetry" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="$(RepoRoot)src\Platform\Microsoft.Testing.Platform\Microsoft.Testing.Platform.csproj" />
</ItemGroup>

<ItemGroup>
<Using Include="Polyfills" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Diagnostics.Metrics;

using Microsoft.Testing.Platform.Telemetry;

namespace Microsoft.Testing.Extensions.OpenTelemetry;

internal sealed class OpenTelemetryPlatformService : IPlatformOpenTelemetryService
{
internal const string ActivitySourceName = "Microsoft.Testing.Platform";
internal const string MeterName = "Microsoft.Testing.Platform";

private readonly ActivitySource _activitySource = new(ActivitySourceName, PlatformVersion.Version);
private readonly Meter _meter = new(MeterName, PlatformVersion.Version);

public IActivity? TestFrameworkActivity { get; set; }

public IActivity? StartActivity([CallerMemberName] string name = "", IEnumerable<KeyValuePair<string, object?>>? tags = null, string? parentId = null, DateTimeOffset startTime = default)
=> _activitySource.StartActivity(name, ActivityKind.Internal, tags: tags, startTime: startTime, parentId: parentId) is Activity activity
? new ActivityWrapper(activity)
: null;

public ICounter<T> CreateCounter<T>(string name, string? unit = null, string? description = null, IEnumerable<KeyValuePair<string, object?>>? tags = null)
where T : struct
=> new CounterWrapper<T>(_meter.CreateCounter<T>(name, unit, description, tags!));

public IHistogram<T> CreateHistogram<T>(string name, string? unit = null, string? description = null, IEnumerable<KeyValuePair<string, object?>>? tags = null)
where T : struct
=> new HistogramWrapper<T>(_meter.CreateHistogram<T>(name, unit, description, tags));

public void Dispose()
=> _activitySource.Dispose();
}
Loading