Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Refine test discovery and partition during test build with new target #17331

Closed
wants to merge 2 commits into from
Closed
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
7 changes: 5 additions & 2 deletions build-test.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ REM See https://github.com/Microsoft/msbuild/issues/2993

set __SkipPackageRestore=false
set __SkipTargetingPackBuild=false
set __BuildLoopCount=2
set __BuildLoopCount=3
set __TestGroupToBuild=1

if %__Priority% GTR 0 (set __BuildLoopCount=16&set __TestGroupToBuild=2)
Expand All @@ -301,7 +301,8 @@ for /l %%G in (1, 1, %__BuildLoopCount%) do (
set __msbuildErr=/flp2:ErrorsOnly;LogFile="%__BuildErr%";Append=!__AppendToLog!

set TestBuildSlice=%%G
call "%__ProjectDir%\run.cmd" build -Project=%__ProjectDir%\tests\build.proj -MsBuildLog=!__msbuildLog! -MsBuildWrn=!__msbuildWrn! -MsBuildErr=!__msbuildErr! %__RunArgs% %__BuildAgainstPackagesArg% %__unprocessedBuildArgs%
set "__ExtraTestParameters=/p:TestBuildSlice=!TestBuildSlice! /p:__SkipPackageRestore=!__SkipPackageRestore! /p:__SkipTargetingPackBuild=!__SkipTargetingPackBuild!"
call "%__ProjectDir%\run.cmd" build -Project=%__ProjectDir%\tests\build.proj -MsBuildLog=!__msbuildLog! -MsBuildWrn=!__msbuildWrn! -MsBuildErr=!__msbuildErr! %__RunArgs% %__BuildAgainstPackagesArg% !__unprocessedBuildArgs! -ExtraTestParameters="!__ExtraTestParameters!"

if errorlevel 1 (
echo %__MsgPrefix%Error: build failed. Refer to the build log files for details:
Expand All @@ -316,6 +317,8 @@ for /l %%G in (1, 1, %__BuildLoopCount%) do (
set __AppendToLog=true
)

set __unprocessedBuildArgs=!__LocalUnprocessedBuildArgs!

REM Prepare the Test Drop
REM Cleans any NI from the last run
powershell -NoProfile "Get-ChildItem -path %__TestWorkingDir% -Include '*.ni.*' -Recurse -Force | Remove-Item -force"
Expand Down
6 changes: 6 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,12 @@
"valueType": "passThrough",
"values": [],
"defaultValue": ""
},
"ExtraTestParameters": {
"description": "Extra parameters will be passed to the selected test build command.",
"valueType": "passThrough",
"values": [],
"defaultValue": ""
}
},
"commands": {
Expand Down
73 changes: 73 additions & 0 deletions tests/scripts/dirs.proj.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<!--
***********************************************************************************************

WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
created a backup copy. Incorrect changes to this file will make it
impossible to load or build coreclr test projects from the command-line or the IDE.

dirs.proj.xml file contains template used for generating coreclr/tests/src/dir.proj project and
any changes made in this file require running generatedirsproj command in this directory to regenerate
dirs.proj project

Copyright (C) Microsoft Corporation. All rights reserved.
***********************************************************************************************
-->
<Project ToolsVersion="15.0" DefaultTargets="Build" InitialTargets="VerifyBuildTools" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="dir.props" />

<Target Name="VerifyBuildTools"
Inputs="$(BuildToolsTargetInputs)"
Outputs="$(BuildToolsTargetOutputs)"
>
<Error Condition="!Exists('$(BuildToolsInstallSemaphore)')"
Text="The build tools have not been installed. Please run buildtest.cmd from the root of the repo at least once to get the tools installed." />

<!-- If we enter this target at all then the inputs are newer then the outputs so give a warning. -->
<Warning Text="Looks like there may be an update to the build tools. Please run buildtest.cmd from the root of the repo to refresh the build tools." />
</Target>

<Target Name="ResolveDisabledProjects" BeforeTargets="BuildAllProjects" >
<ItemGroup Label="DisabledProjectsItemGroup">
<DisabledProjects Include="TestWrappers*\**\*.csproj" />
<DisabledProjects Include="*\**\cs_template.csproj" />
<DisabledProjects Include="Common\Coreclr.TestWrapper\Coreclr.TestWrapper.csproj" Condition="('$(BuildTestsAgainstPackages)' != 'true') And ('$(BuildOS)' == 'Windows_NT')" />
<DisabledProjects Include="Common\Desktop.Coreclr.TestWrapper\Desktop.Coreclr.TestWrapper.csproj" Condition="('$(BuildTestsAgainstPackages)' == 'true') Or ('$(BuildOS)' != 'Windows_NT')" />
<DisabledProjects Include="Common\test_runtime\test_runtime.csproj" />
<DisabledProjects Include="Common\test_dependencies\test_dependencies.csproj" />
<DisabledProjects Include="Common\build_against_pkg_dependencies\build_against_pkg_dependencies.csproj" />
<DisabledProjects Include="Common\targeting_pack_ref\targeting_pack_ref.csproj" />
<DisabledProjects Include="Common\external\external.csproj" />
<DisabledProjects Include="Common\PerfHarness\PerfHarness.csproj" />
<DisabledProjects Include="GC\Performance\Framework\GCPerfTestFramework.csproj" />
<DisabledProjects Include="JIT\superpmi\superpmicollect.csproj" Condition="('$(BuildTestsAgainstPackages)' == 'true') Or ('$(BuildOS)' != 'Windows_NT')" />
<DisabledProjects Include="JIT\config\**" />
<DisabledProjects Include="Performance\performance.csproj" />
<DisabledProjects Include="Performance\Scenario\JitBench\unofficial_dotnet\JitBench.csproj" /> <!-- no official build support for SDK-style netcoreapp2.0 projects -->
<DisabledProjects Include="Loader\classloader\generics\regressions\DD117522\Test.csproj" />
<DisabledProjects Include="Loader\classloader\generics\GenericMethods\VSW491668.csproj" /> <!-- issue 5501 -->
</ItemGroup>

<!-- Unix builds do not support groups and slices -->
<ItemGroup Condition="$(__BuildOS) != 'Windows_NT'">
<Project Include="*\**\*.csproj" Exclude="@(DisabledProjects)">
<AdditionalProperties>OSGroup=$(OSGroup)</AdditionalProperties>
</Project>
<Project Include="*\**\*.ilproj" Exclude="@(DisabledProjects)">
<AdditionalProperties>OSGroup=$(OSGroup)</AdditionalProperties>
</Project>
</ItemGroup>

<!-- Test build is divided in slices which can be created within Test Group
Priority 0 tests are build using Test Group 1 with 2 subgroups or slices -->

<!--{{{TestGroupProjects}}}-->

</Target>

<Import Project="..\dir.traversal.targets" />

<!-- Override clean from dir.traversal.targets and just remove the full BinDir -->
<Target Name="Clean">
<RemoveDir Directories="$(BinDir)" />
</Target>
</Project>
9 changes: 9 additions & 0 deletions tests/scripts/generatedirsproj.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@echo off

if not defined VS150COMNTOOLS (
echo This script has to be run from Visual Studio 2017 developer command prompt
exit /b 1
)

csi -r:"%VS150COMNTOOLS%..\..\MSBuild\15.0\Bin\Microsoft.Build.dll" -r:"%VS150COMNTOOLS%..\..\MSBuild\15.0\Bin\Microsoft.Build.Framework.dll" -r:"%VS150COMNTOOLS%..\..\MSBuild\15.0\Bin\Microsoft.Build.Tasks.Core.dll" -r:"%VS150COMNTOOLS%..\..\MSBuild\15.0\Bin\Microsoft.Build.Utilities.Core.dll" generatedirsproj.csx
exit /b %ERRORLEVEL%
208 changes: 208 additions & 0 deletions tests/scripts/generatedirsproj.csx
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
using System.IO;
using Microsoft.Build.Construction;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Framework;
using Microsoft.Build.Tasks;
using Microsoft.Build.Utilities;

var start = DateTime.UtcNow;
var projectTemplateName = "dirs.proj.xml";
var outputProjectPath = "..\\src\\dirs.proj";

Console.WriteLine();
Console.WriteLine($" Starting generation of {Path.GetFullPath(outputProjectPath)} project");
Console.WriteLine();

// Prepare and run CreateItem task to glob project files
var projTempl = ProjectRootElement.Open(projectTemplateName);
CreateItem task = new CreateItem();

task.Include = new ITaskItem[]
{
new TaskItem(@"..\src\**\*.csproj"),
new TaskItem(@"..\src\**\*.ilproj")
};

ProjectTargetElement disabledTarget = null;
foreach(var target in projTempl.Targets)
{
if (target.Name == "ResolveDisabledProjects")
{
disabledTarget = target;
break;
}
}

Dictionary<string, string> conditionalExcludes = new Dictionary<string, string>();
if (disabledTarget != null)
{
foreach(var itemsGroup in disabledTarget.ItemGroups)
{
if (itemsGroup.Label == "DisabledProjectsItemGroup")
{
List<ProjectItemElement> items = new List<ProjectItemElement>(itemsGroup.Items);
for(int i = 0; i < items.Count; )
{
if (!String.IsNullOrEmpty(items[i].Condition))
{
conditionalExcludes.Add(items[i].Include, items[i].Condition);
items.RemoveAt(i);
continue;
}
i++;
}
}
}
}

task.Exclude = new ITaskItem[]
{
new TaskItem(@"..\src\TestWrappers*\**\*.csproj"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like duplicating these sets of excluded test projects. We should figure out a way to share.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am working on more comprehensive fix which will address @AndyAyersMS feedback and will include fix to the above duplication of excluded test projects

new TaskItem(@"..\src\**\cs_template.csproj"),
new TaskItem(@"..\src\Common\test_runtime\test_runtime.csproj"),
new TaskItem(@"..\src\Common\test_dependencies\test_dependencies.csproj"),
new TaskItem(@"..\src\Common\build_against_pkg_dependencies\build_against_pkg_dependencies.csproj"),
new TaskItem(@"..\src\Common\targeting_pack_ref\targeting_pack_ref.csproj"),
new TaskItem(@"..\src\Common\external\external.csproj"),
new TaskItem(@"..\src\Common\PerfHarness\PerfHarness.csproj"),
new TaskItem(@"..\src\GC\Performance\Framework\GCPerfTestFramework.csproj"),
new TaskItem(@"..\src\JIT\config\**"),
new TaskItem(@"..\src\Performance\performance.csproj"),
new TaskItem(@"..\src\Performance\Scenario\JitBench\unofficial_dotnet\JitBench.csproj"),
new TaskItem(@"..\src\Loader\classloader\generics\regressions\DD117522\Test.csproj"),
new TaskItem(@"..\src\Loader\classloader\generics\GenericMethods\VSW491668.csproj"),
};

var result = task.Execute();
Console.WriteLine($" Task CreateItem success: {result}");
if (!result) return 1;

List<string> innerLoopProjList = new List<string>(3200);
List<string> outerLoopProjList = new List<string>(task.Include.Length);
foreach(ITaskItem include in task.Include)
{
var path = include.GetMetadata("FullPath");
ProjectRootElement projRoot = ProjectRootElement.Open(path);
ProjectPropertyElement priorityElement = null;
foreach(var projProperty in projRoot.Properties)
{
if (projProperty.Name == "CLRTestPriority")
{
priorityElement = projProperty;
break;
}
}

if (priorityElement == null || priorityElement.Value == "0")
{
innerLoopProjList.Add(path);
outerLoopProjList.Add(path);
}
else if (priorityElement.Value == "1")
{
outerLoopProjList.Add(path);
}
}

innerLoopProjList.Sort();
outerLoopProjList.Sort();

Console.WriteLine();
Console.WriteLine($" Number of included outer loop projects: {outerLoopProjList.Count}");
Console.WriteLine($" Number of included inner loop projects: {innerLoopProjList.Count}");
Console.WriteLine($" Number of conditionally excluded projects: {conditionalExcludes.Count}");
Console.WriteLine($" Number of unconditionally excluded projects: {task.Exclude.Length}");
Console.WriteLine();

using (var reader = new StreamReader(projectTemplateName))
using (var writer = new StreamWriter(outputProjectPath, false, Encoding.UTF8))
{
string line = null;
do
{
line = reader.ReadLine();
writer.WriteLine(line);
} while (!line.StartsWith("************"));

writer.WriteLine();
writer.WriteLine("WARNING This file is generated by running coreclr/tests/scripts/generatedirsproj.cmd script.");
writer.WriteLine(" Do not modify this file directly as the changes will be overwritten by code generator.");
writer.WriteLine(" To change it's content modify coreclr/tests/scripts/dirs.proj.xml template");
writer.WriteLine(" or coreclr/tests/scripts/generatedirsproj.csx C# script and run generatedirsproj.cmd script");
writer.WriteLine();
writer.WriteLine("ADDING NEW TEST PROJECT");
writer.WriteLine();
writer.WriteLine(" Create ilproj or csproj under coreclr/tests/src directory tree and regenerate dirs.proj");
writer.WriteLine(" project file by running generatedirsproj.cmd from coreclr/tests/scripts/ directory using");
writer.WriteLine(" Visual Studio 2017 developer command prompt.");
writer.WriteLine(line);

do
{
line = reader.ReadLine();
} while (!line.StartsWith("-->"));

writer.WriteLine(line);

line = reader.ReadLine();
while(!line.StartsWith("<!--{{{TestGroupProjects}}}-->"))
{
writer.WriteLine(line);
line = reader.ReadLine();
}

int innerSliceSize = (innerLoopProjList.Count + (innerLoopProjList.Count % 3)) / 3;
Console.WriteLine($" Genereting inner loop slices with size: {innerSliceSize}");
for (int i = 0, j = 1; i < innerLoopProjList.Count; i += innerSliceSize, j++)
{
writer.WriteLine($" <ItemGroup Condition=\"$(__BuildOS) == 'Windows_NT' And $(__TestGroupToBuild) == '1' And $(TestBuildSlice) == '{j}'\">");
for(int k = i; k < (i + innerSliceSize) && k < innerLoopProjList.Count; k++)
{
string key = innerLoopProjList[k].Split(new []{"tests\\src\\"}, 2, StringSplitOptions.None)[1];
if (conditionalExcludes.ContainsKey(key))
{
writer.WriteLine($" <Project Condition=\"{conditionalExcludes[key]}\" Include=\"{key}\" >");
}
else
{
writer.WriteLine($" <Project Include=\"{key}\" >");
}
writer.WriteLine($" <AdditionalProperties>OSGroup=$(OSGroup)</AdditionalProperties>");
writer.WriteLine($" </Project>");
}
writer.WriteLine($" </ItemGroup>\n");
}

int outerSliceSize = (outerLoopProjList.Count + (outerLoopProjList.Count % 16)) / 16;
Console.WriteLine($" Genereting outer loop slices with size: {outerSliceSize}");
for (int i = 0, j = 1; i < outerLoopProjList.Count; i += outerSliceSize, j++)
{
writer.WriteLine($" <ItemGroup Condition=\"$(__BuildOS) == 'Windows_NT' And $(__TestGroupToBuild) == '2' And $(TestBuildSlice) == '{j}'\">");
for(int k = i; k < (i + outerSliceSize) && k < outerLoopProjList.Count; k++)
{
string key = outerLoopProjList[k].Split(new string[]{"tests\\src\\"}, 2, StringSplitOptions.None)[1];
if (conditionalExcludes.ContainsKey(key))
{
writer.WriteLine($" <Project Condition=\"{conditionalExcludes[key]}\" Include=\"{key}\" >");
}
else
{
writer.WriteLine($" <Project Include=\"{key}\" >");
}
writer.WriteLine($" <AdditionalProperties>OSGroup=$(OSGroup)</AdditionalProperties>");
writer.WriteLine($" </Project>");
}
writer.WriteLine($" </ItemGroup>");
}

line = reader.ReadLine();
while(line != null)
{
writer.WriteLine(line);
line = reader.ReadLine();
}
}

Console.WriteLine();
Console.WriteLine($" Finished generating of {Path.GetFullPath(outputProjectPath)} project");
Console.WriteLine($" Time Elapsed {DateTime.UtcNow.Subtract(start)}");
Loading