# Linux x64
- ${{ if eq(parameters.platform, 'Linux_x64') }}:
- - ${{ if eq(parameters.jobParameters.interpreter, '') }}:
+ - ${{ if and(eq(parameters.jobParameters.interpreter, ''), ne(parameters.jobParameters.isSingleFile, true)) }}:
- ${{ if and(eq(parameters.jobParameters.testScope, 'outerloop'), eq(parameters.jobParameters.runtimeFlavor, 'mono')) }}:
- (Centos.8.Amd64.Open)Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix-20201229003624-c1bf759
- RedHat.7.Amd64.Open
- Ubuntu.1804.Amd64.Open
- SLES.15.Amd64.Open
- (Fedora.30.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-30-helix-20200512010621-4f8cef7
- - ${{ if eq(parameters.jobParameters.interpreter, 'true') }}:
+ - ${{ if or(eq(parameters.jobParameters.interpreter, 'true'), eq(parameters.jobParameters.isSingleFile, true)) }}:
# Limiting interp runs as we don't need as much coverage.
- Debian.9.Amd64.Open
# .NETFramework
- ${{ if eq(parameters.jobParameters.framework, 'net48') }}:
- Windows.10.Amd64.Client19H1.Open
-
+
# AllConfigurations
- ${{ if eq(parameters.jobParameters.framework, 'allConfigurations') }}:
- Windows.10.Amd64.Server19H1.Open
eq(variables['monoContainsChange'], true),
eq(variables['isFullMatrix'], true))
+# Build and test libraries under single-file publishing
+- template: /eng/pipelines/common/platform-matrix.yml
+ parameters:
+ jobTemplate: /eng/pipelines/common/global-build-job.yml
+ helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
+ buildConfig: Release
+ platforms:
+ - windows_x64
+ - Linux_x64
+ jobParameters:
+ testGroup: innerloop
+ isFullMatrix: ${{ variables.isFullMatrix }}
+ isSingleFile: true
+ nameSuffix: SingleFile
+ buildArgs: -s clr+libs+libs.tests -c $(_BuildConfig) /p:TestSingleFile=true /p:ArchiveTests=true
+ timeoutInMinutes: 120
+ # extra steps, run tests
+ extraStepsTemplate: /eng/pipelines/libraries/helix.yml
+ extraStepsParameters:
+ creator: dotnet-bot
+ testRunNamePrefixSuffix: SingleFile_$(_BuildConfig)
+
#
# Build the whole product using Mono and run runtime tests
#
--- /dev/null
+<Project>
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+
+ <BundleDir>$([MSBuild]::NormalizeDirectory('$(OutDir)', 'publish'))</BundleDir>
+ <RunScriptOutputPath>$([MSBuild]::NormalizePath('$(BundleDir)', '$(RunScriptOutputName)'))</RunScriptOutputPath>
+ <RuntimeIdentifier>$(PackageRID)</RuntimeIdentifier>
+
+ <RunScriptCommand Condition="'$(TargetOS)' == 'windows'">$(AssemblyName).exe</RunScriptCommand>
+ <RunScriptCommand Condition="'$(TargetOS)' != 'windows'">chmod +rwx $(AssemblyName) && ./$(AssemblyName)</RunScriptCommand>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <PublishSingleFile>true</PublishSingleFile>
+ <UseAppHost>true</UseAppHost>
+ <SelfContained>true</SelfContained>
+ <SingleFileHostSourcePath>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'coreclr', '$(TargetOS).$(TargetArchitecture).$(Configuration)', 'corehost'))/singlefilehost</SingleFileHostSourcePath>
+ <SingleFileHostSourcePath Condition="'$(TargetOS)' == 'windows'">$(SingleFileHostSourcePath).exe</SingleFileHostSourcePath>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Compile Include="$(CommonTestPath)SingleFileTestRunner\SingleFileTestRunner.cs"
+ Link="Common\SingleFileTestRunner\SingleFileTestRunner.cs" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="xunit.runner.utility" Version="$(XUnitVersion)" />
+ </ItemGroup>
+
+ <Target Name="__ExcludeAssembliesFromSingleFile"
+ Inputs="%(ResolvedFileToPublish.Identity)"
+ Outputs="__NewResolvedFiles"
+ BeforeTargets="_ComputeFilesToBundle">
+ <PropertyGroup>
+ <__Identity>%(ResolvedFileToPublish.Identity)</__Identity>
+ <__FileName>%(ResolvedFileToPublish.Filename)%(ResolvedFileToPublish.Extension)</__FileName>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <__NewResolvedFiles Include="@(ResolvedFileToPublish)">
+ <ExcludeFromSingleFile Condition="'%(__ExcludeFromBundle.Identity)' == '$(__FileName)'">true</ExcludeFromSingleFile>
+ </__NewResolvedFiles>
+ </ItemGroup>
+ </Target>
+
+ <Target Name="__UpdateExcludedAssembliesFromSingleFile"
+ Inputs="ExcludeFromSingleFile"
+ Outputs="ResolvedFileToPublish"
+ DependsOnTargets="ComputeResolvedFilesToPublishList"
+ BeforeTargets="_ComputeFilesToBundle">
+ <ItemGroup>
+ <ResolvedFileToPublish Remove="@(ResolvedFileToPublish)" />
+ <ResolvedFileToPublish Include="@(__NewResolvedFiles)" />
+ </ItemGroup>
+ </Target>
+
+ <Target Name="PublishTestAsSingleFile"
+ Condition="'$(IsCrossTargetingBuild)' != 'true'"
+ AfterTargets="Build"
+ DependsOnTargets="Publish;ArchiveTests" />
+
+</Project>
<!-- For browser we need to hook up the target with DependsOnTargets in PublishTestAsSelfContained
because we do a Publish which runs after Build, if we run after PrepareForRun we would generated
an empty zip because we haven't published the selfcontained app. -->
- <ArchiveTestsAfterTargets Condition="'$(TargetOS)' == 'Browser'" />
+ <ArchiveTestsAfterTargets Condition="'$(TargetOS)' == 'Browser' or '$(TestSingleFile)' == 'true'" />
</PropertyGroup>
<!-- Archive test binaries. -->
<PropertyGroup>
<_ZipSourceDirectory>$(OutDir)</_ZipSourceDirectory>
- <_ZipSourceDirectory Condition="'$(TargetOS)' == 'Browser'">$(BundleDir)</_ZipSourceDirectory>
+ <_ZipSourceDirectory Condition="'$(TargetOS)' == 'Browser' or '$(TestSingleFile)' == 'true'">$(BundleDir)</_ZipSourceDirectory>
</PropertyGroup>
<MakeDir Directories="$(TestArchiveTestsDir)" />
</Target>
<Import Project="$(MSBuildThisFileDirectory)tests.mobile.targets" Condition="'$(TargetsMobile)' == 'true'" />
+ <Import Project="$(MSBuildThisFileDirectory)tests.singlefile.targets" Condition="'$(TestSingleFile)' == 'true'" />
<Import Project="$(MSBuildThisFileDirectory)xunit\xunit.targets" Condition="'$(TestFramework)' == 'xunit'" />
<!-- Main test targets -->
<Target Name="Test" DependsOnTargets="$(TestDependsOn)" />
-
+
<Import Project="$(MSBuildThisFileDirectory)outerBuild.targets" Condition="'$(IsCrossTargetingBuild)' == 'true'" />
</Project>
<UseXunitExcludesTxtFile Condition="'$(TargetOS)' == 'Android' or '$(TargetOS)' == 'iOS' or '$(TargetOS)' == 'iOSSimulator' or '$(TargetOS)' == 'tvOS' or '$(TargetOS)' == 'tvOSSimulator'">true</UseXunitExcludesTxtFile>
</PropertyGroup>
- <PropertyGroup Condition="'$(TargetsMobile)' != 'true'">
+ <PropertyGroup Condition="'$(TargetsMobile)' != 'true' and '$(TestSingleFile)' != 'true'">
<_depsFileArgument Condition="'$(GenerateDependencyFile)' == 'true'">--depsfile $(AssemblyName).deps.json</_depsFileArgument>
<RunScriptCommand Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'">"$(RunScriptHost)" exec --runtimeconfig $(AssemblyName).runtimeconfig.json $(_depsFileArgument) xunit.console.dll</RunScriptCommand>
<RunScriptCommand Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">xunit.console.exe</RunScriptCommand>
<XunitExcludesTxtFileContent>$(_withoutCategories.Replace(';', '%0dcategory='))</XunitExcludesTxtFileContent>
</PropertyGroup>
- <ItemGroup>
+ <ItemGroup Condition="'$(TestSingleFile)' != 'true'">
<PackageReference Include="Microsoft.DotNet.XUnitConsoleRunner"
Version="$(MicrosoftDotNetXUnitConsoleRunnerVersion)"
Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'" />
<PackageReference Include="Microsoft.DotNet.XUnitExtensions" Version="$(MicrosoftDotNetXUnitExtensionsVersion)" />
</ItemGroup>
- <ItemGroup Condition="'$(ArchiveTests)' != 'true' AND '$(PublishingTestsRun)' != 'true'">
+ <ItemGroup Condition="'$(ArchiveTests)' != 'true' and '$(PublishingTestsRun)' != 'true' and '$(TestSingleFile)' != 'true'">
<!-- Microsoft.Net.Test.Sdk brings a lot of assemblies with it. To reduce helix payload submission size we disable it on CI. -->
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkVersion)" />
<PackageReference Include="xunit.runner.visualstudio" Version="$(XUnitRunnerVisualStudioVersion)" GeneratePathProperty="true" />
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#nullable disable
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.Loader;
+using System.Threading.Tasks;
+using System.Xml.Linq;
+using Xunit;
+using Xunit.Abstractions;
+using Xunit.Sdk;
+
+public class SingleFileTestRunner : XunitTestFramework
+{
+ private SingleFileTestRunner(IMessageSink messageSink)
+ : base(messageSink) { }
+
+ public static int Main(string[] args)
+ {
+ var asm = typeof(SingleFileTestRunner).Assembly;
+ Console.WriteLine("Running assembly:" + asm.FullName);
+
+ var diagnosticSink = new ConsoleDiagnosticMessageSink();
+ var testsFinished = new TaskCompletionSource();
+ var testSink = new TestMessageSink();
+ var summarySink = new DelegatingExecutionSummarySink(testSink,
+ () => false,
+ (completed, summary) => Console.WriteLine($"Tests run: {summary.Total}, Errors: {summary.Errors}, Failures: {summary.Failed}, Skipped: {summary.Skipped}. Time: {TimeSpan.FromSeconds((double)summary.Time).TotalSeconds}s"));
+ var resultsXmlAssembly = new XElement("assembly");
+ var resultsSink = new DelegatingXmlCreationSink(summarySink, resultsXmlAssembly);
+
+ testSink.Execution.TestSkippedEvent += args => { Console.WriteLine($"[SKIP] {args.Message.Test.DisplayName}"); };
+ testSink.Execution.TestFailedEvent += args => { Console.WriteLine($"[FAIL] {args.Message.Test.DisplayName}{Environment.NewLine}{Xunit.ExceptionUtility.CombineMessages(args.Message)}{Environment.NewLine}{Xunit.ExceptionUtility.CombineStackTraces(args.Message)}"); };
+
+ testSink.Execution.TestAssemblyFinishedEvent += args =>
+ {
+ Console.WriteLine($"Finished {args.Message.TestAssembly.Assembly}{Environment.NewLine}");
+ testsFinished.SetResult();
+ };
+
+ var xunitTestFx = new SingleFileTestRunner(diagnosticSink);
+ var asmInfo = Reflector.Wrap(asm);
+ var asmName = asm.GetName();
+
+ var discoverySink = new TestDiscoverySink();
+ var discoverer = xunitTestFx.CreateDiscoverer(asmInfo);
+ discoverer.Find(false, discoverySink, TestFrameworkOptions.ForDiscovery());
+ discoverySink.Finished.WaitOne();
+ XunitFilters filters = new XunitFilters();
+ filters.ExcludedTraits.Add("category", new List<string> { "failing" });
+ var filteredTestCases = discoverySink.TestCases.Where(filters.Filter).ToList();
+ var executor = xunitTestFx.CreateExecutor(asmName);
+ executor.RunTests(filteredTestCases, resultsSink, TestFrameworkOptions.ForExecution());
+
+ resultsSink.Finished.WaitOne();
+
+ var failed = resultsSink.ExecutionSummary.Failed > 0 || resultsSink.ExecutionSummary.Errors > 0;
+ return failed ? 1 : 0;
+ }
+}
+
+internal class ConsoleDiagnosticMessageSink : IMessageSink
+{
+ public bool OnMessage(IMessageSinkMessage message)
+ {
+ if (message is IDiagnosticMessage diagnosticMessage)
+ {
+ return true;
+ }
+ return false;
+ }
+}
<WasmFilesToIncludeFromPublishDir Include="$(AssemblyName).dll" />
<WasmFilesToIncludeFromPublishDir Include="$(AssemblyName).pdb" />
</ItemGroup>
+ <ItemGroup>
+ <!-- Assemblies that should be excluded from the bundle -->
+ <__ExcludeFromBundle Include="TestAssembly.dll" />
+ </ItemGroup>
</Project>
<TestPackages Condition="'$(TestPackages)' == ''">false</TestPackages>
<TestTrimming Condition="'$(TestTrimming)' == ''">false</TestTrimming>
</PropertyGroup>
-
+
<!-- Projects that don't support code coverage measurement. -->
<ItemGroup Condition="'$(Coverage)' == 'true'">
<ProjectExclusions Include="$(CommonTestPath)Common.Tests.csproj" />
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Net.NameResolution\tests\UnitTests\System.Net.NameResolution.Unit.Tests.csproj" />
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Net.NetworkInformation\tests\FunctionalTests\System.Net.NetworkInformation.Functional.Tests.csproj" />
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Net.Ping\tests\FunctionalTests\System.Net.Ping.Functional.Tests.csproj" />
-
+
<!-- https://github.com/dotnet/runtime/issues/49191 -->
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Net.Quic\tests\FunctionalTests\System.Net.Quic.Functional.Tests.csproj" />
-
+
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Net.Requests\tests\System.Net.Requests.Tests.csproj" />
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Net.Security\tests\FunctionalTests\System.Net.Security.Tests.csproj" />
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Net.Sockets\tests\FunctionalTests\System.Net.Sockets.Tests.csproj" />
-
+
<!-- https://github.com/dotnet/runtime/issues/49192-->
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Net.WebClient\tests\System.Net.WebClient.Tests.csproj" />
-
+
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Net.WebSockets\tests\System.Net.WebSockets.Tests.csproj" />
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Net.WebSockets.Client\tests\System.Net.WebSockets.Client.Tests.csproj" />
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Numerics.Tensors\tests\System.Numerics.Tensors.Tests.csproj" />
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Threading.Timer/tests/System.Threading.Timer.Tests.csproj" />
</ItemGroup>
+ <ItemGroup Condition="'$(TestSingleFile)' == 'true'">
+ <!-- Run only a small randomly chosen set of passing test suites -->
+ <ProjectExclusions Include="$(MSBuildThisFileDirectory)*\tests\**\*.Tests.csproj" />
+ <ProjectExclusions Remove="$(MSBuildThisFileDirectory)System.Collections\tests\System.Collections.Tests.csproj" />
+ </ItemGroup>
+
<ItemGroup>
<ProjectReference Include="$(MSBuildThisFileDirectory)*\tests\**\*.Tests.csproj"
Exclude="@(ProjectExclusions)"
<ProjectReference Include="$(RepoRoot)\src\tests\FunctionalTests\tvOS\**\*.Test.csproj"
BuildInParallel="false" />
</ItemGroup>
-
+
<ItemGroup Condition="'$(ArchiveTests)' == 'true' and '$(TargetOS)' == 'Android'">
<ProjectReference Include="$(MonoProjectRoot)sample\Android\AndroidSampleApp.csproj"
BuildInParallel="false" />
Exclude="$(RepoRoot)\src\tests\FunctionalTests\Android\Device_Emulator\AOT\Android.Device_Emulator.Aot.Test.csproj"
BuildInParallel="false" />
</ItemGroup>
-
+
<ItemGroup Condition="'$(ArchiveTests)' == 'true' and '$(TargetOS)' == 'Browser'">
<ProjectReference Include="$(MonoProjectRoot)sample\wasm\**\*.Sample.csproj"
BuildInParallel="false" />