From 158c2aa0edf7b246762fce6197af39948ab88f11 Mon Sep 17 00:00:00 2001
From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com>
Date: Wed, 13 Mar 2024 13:53:24 -0700
Subject: [PATCH] Create test project for Unified Build validation
---
.../VersionIdentifier.cs | 4 +-
.../eng/unifiedBuildvalidation.targets | 31 +++++
.../BaselineHelper.cs | 6 +-
.../DotNetHelper.cs | 22 ++--
.../SdkContentTests.cs | 107 +++++++++++++-----
.../Utilities.cs | 2 +-
.../Config.cs | 49 ++++++++
...Microsoft.DotNet.UnifiedBuild.Tests.csproj | 44 +++++++
.../SdkAssemblyVersionDiffExclusions.txt | 16 +++
.../assets/SdkFileDiffExclusions.txt | 24 ++++
.../MsftToSbSdkAssemblyVersions.diff | 1 +
.../assets/baselines/MsftToSbSdkFiles.diff | 43 +++++++
12 files changed, 303 insertions(+), 46 deletions(-)
create mode 100644 src/SourceBuild/content/eng/unifiedBuildvalidation.targets
create mode 100644 src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/Config.cs
create mode 100644 src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/Microsoft.DotNet.UnifiedBuild.Tests.csproj
create mode 100644 src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/assets/SdkAssemblyVersionDiffExclusions.txt
create mode 100644 src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/assets/SdkFileDiffExclusions.txt
create mode 100644 src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/assets/baselines/MsftToSbSdkAssemblyVersions.diff
create mode 100644 src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/assets/baselines/MsftToSbSdkFiles.diff
diff --git a/src/SourceBuild/content/eng/tools/tasks/Microsoft.DotNet.SourceBuild.Tasks.SdkArchiveDiff/VersionIdentifier.cs b/src/SourceBuild/content/eng/tools/tasks/Microsoft.DotNet.SourceBuild.Tasks.SdkArchiveDiff/VersionIdentifier.cs
index 2150a7211..38a3eafa8 100644
--- a/src/SourceBuild/content/eng/tools/tasks/Microsoft.DotNet.SourceBuild.Tasks.SdkArchiveDiff/VersionIdentifier.cs
+++ b/src/SourceBuild/content/eng/tools/tasks/Microsoft.DotNet.SourceBuild.Tasks.SdkArchiveDiff/VersionIdentifier.cs
@@ -215,7 +215,7 @@ public static class VersionIdentifier
/// Asset name without versions
public static string RemoveVersions(string assetName, string replacement = "")
{
- string[] pathSegments = assetName.Split('/');
+ string[] pathSegments = assetName.Split('/', '\\');
// Remove the version number from each segment, then join back together and
// remove any useless character sequences.
@@ -252,6 +252,6 @@ public static class VersionIdentifier
public static bool AreVersionlessEqual(string assetName1, string assetName2)
{
- return RemoveVersions(assetName1) == RemoveVersions(assetName2);
+ return RemoveVersions(assetName1, "{VERSION}") == RemoveVersions(assetName2, "{VERSION}");
}
}
diff --git a/src/SourceBuild/content/eng/unifiedBuildvalidation.targets b/src/SourceBuild/content/eng/unifiedBuildvalidation.targets
new file mode 100644
index 000000000..dc601450c
--- /dev/null
+++ b/src/SourceBuild/content/eng/unifiedBuildvalidation.targets
@@ -0,0 +1,31 @@
+
+
+
+ $([MSBuild]::NormalizeDirectory('$(RepoRoot)', 'test', 'Microsoft.DotNet.UnifiedBuild.Tests'))
+
+
+
+
+
+
+
+
+
+
+ normal
+
+
+
+
+
+
+
diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/BaselineHelper.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/BaselineHelper.cs
index 6b7c6f71a..a5ca6a154 100644
--- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/BaselineHelper.cs
+++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/BaselineHelper.cs
@@ -96,7 +96,7 @@ namespace Microsoft.DotNet.SourceBuild.SmokeTests
public static string RemoveVersions(string source)
{
// Remove version numbers for examples like "roslyn4.1", "net8.0", and "netstandard2.1".
- string pathSeparator = Regex.Escape(Path.DirectorySeparatorChar.ToString());
+ string pathSeparator = $"[{Regex.Escape(@"\")}|{Regex.Escape(@"/")}]";
string result = Regex.Replace(source, $@"{pathSeparator}(net|roslyn)[1-9]+\.[0-9]+{pathSeparator}", match =>
{
string wordPart = match.Groups[1].Value;
@@ -111,10 +111,10 @@ namespace Microsoft.DotNet.SourceBuild.SmokeTests
// - The version may have one or more release identifiers that begin with '.' or '-'
// - The version should end before a path separator, '.', '-', or '/'
Regex semanticVersionRegex = new(
- @"(?<=[./-])(0|[1-9]\d*)\.(0|[1-9]\d*)(\.(0|[1-9]\d*))+"
+ @"(?<=[./\\-])(0|[1-9]\d*)\.(0|[1-9]\d*)(\.(0|[1-9]\d*))+"
+ @"(((?:[-.]((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)))+"
+ @"(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?"
- + @"(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?(?=[/.-])");
+ + @"(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?(?=[/\\.-])");
return semanticVersionRegex.Replace(result, SemanticVersionPlaceholder);
}
diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetHelper.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetHelper.cs
index 291d492ed..c662eaf76 100644
--- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetHelper.cs
+++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/DotNetHelper.cs
@@ -43,16 +43,16 @@ internal class DotNetHelper
}
IsMonoRuntime = DetermineIsMonoRuntime(Config.DotNetDirectory);
- if (!Directory.Exists(ProjectsDirectory))
- {
- Directory.CreateDirectory(ProjectsDirectory);
- InitNugetConfig();
- }
+ // if (!Directory.Exists(ProjectsDirectory))
+ // {
+ // Directory.CreateDirectory(ProjectsDirectory);
+ // InitNugetConfig();
+ // }
- if (!Directory.Exists(PackagesDirectory))
- {
- Directory.CreateDirectory(PackagesDirectory);
- }
+ // if (!Directory.Exists(PackagesDirectory))
+ // {
+ // Directory.CreateDirectory(PackagesDirectory);
+ // }
}
}
@@ -105,7 +105,7 @@ internal class DotNetHelper
OutputHelper,
configureCallback: (process) => configureProcess(process, workingDirectory),
millisecondTimeout: millisecondTimeout);
-
+
if (expectedExitCode != null) {
ExecuteHelper.ValidateExitCode(executeResult, (int) expectedExitCode);
}
@@ -243,7 +243,7 @@ internal class DotNetHelper
{
throw validator.ValidationException;
}
- }
+ }
private static string GetBinLogOption(string projectName, string command, string? differentiator = null)
{
diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/SdkContentTests.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/SdkContentTests.cs
index 29bb7dbc5..d78b2e8e4 100644
--- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/SdkContentTests.cs
+++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/SdkContentTests.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.IO;
@@ -10,6 +11,7 @@ using System.IO.Enumeration;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
+using System.Threading.Tasks;
using Microsoft.Extensions.FileSystemGlobbing;
using Xunit;
using Xunit.Abstractions;
@@ -118,27 +120,33 @@ public class SdkContentTests : SdkTests
private Dictionary GetMsftSdkAssemblyVersions(
string msftSdkPath, Dictionary sbSdkAssemblyVersions)
{
- Dictionary msftSdkAssemblyVersions = new();
+ ConcurrentDictionary msftSdkAssemblyVersions = new();
+ var tasks = new List();
foreach ((string relativePath, _) in sbSdkAssemblyVersions)
{
- // Now we want to find the corresponding file that exists in the MSFT SDK.
- // We've already replaced version numbers with placeholders in the path.
- // So we can't directly use the relative path to find the corresponding file. Instead,
- // we need to replace the version placeholders with wildcards and find the path through path matching.
- string file = Path.Combine(msftSdkPath, relativePath);
- Matcher matcher = BaselineHelper.GetFileMatcherFromPath(relativePath);
-
- file = FindMatchingFilePath(msftSdkPath, matcher, relativePath);
-
- if (!File.Exists(file))
+ var t = Task.Run(() =>
{
- continue;
- }
+ // Now we want to find the corresponding file that exists in the MSFT SDK.
+ // We've already replaced version numbers with placeholders in the path.
+ // So we can't directly use the relative path to find the corresponding file. Instead,
+ // we need to replace the version placeholders with wildcards and find the path through path matching.
+ string file = Path.Combine(msftSdkPath, relativePath);
+ Matcher matcher = BaselineHelper.GetFileMatcherFromPath(relativePath);
- AssemblyName assemblyName = AssemblyName.GetAssemblyName(file);
- msftSdkAssemblyVersions.Add(BaselineHelper.RemoveVersions(relativePath), GetVersion(assemblyName));
+ file = FindMatchingFilePath(msftSdkPath, matcher, relativePath);
+
+ if (!File.Exists(file))
+ {
+ return;
+ }
+
+ AssemblyName assemblyName = AssemblyName.GetAssemblyName(file);
+ Assert.True(msftSdkAssemblyVersions.TryAdd(BaselineHelper.RemoveVersions(relativePath), GetVersion(assemblyName)));
+ });
+ tasks.Add(t);
}
- return msftSdkAssemblyVersions;
+ Task.WaitAll(tasks.ToArray());
+ return msftSdkAssemblyVersions.ToDictionary();
}
// It's known that assembly versions can be different between builds in their revision field. Disregard that difference
@@ -171,24 +179,65 @@ public class SdkContentTests : SdkTests
{
IEnumerable exclusionFilters = GetSdkDiffExclusionFilters(SourceBuildSdkType)
.Select(filter => filter.TrimStart("./".ToCharArray()));
- Dictionary sbSdkAssemblyVersions = new();
- foreach (string file in Directory.EnumerateFiles(sbSdkPath, "*", SearchOption.AllDirectories))
+ ConcurrentDictionary sbSdkAssemblyVersions = new();
+ List tasks = new List();
+ foreach (string dir in Directory.EnumerateDirectories(sbSdkPath, "*", SearchOption.AllDirectories).Append(sbSdkPath))
{
- string fileExt = Path.GetExtension(file);
- if (fileExt.Equals(".dll", StringComparison.OrdinalIgnoreCase) ||
- fileExt.Equals(".exe", StringComparison.OrdinalIgnoreCase))
+ var t = Task.Run(() =>
{
- AssemblyName assemblyName = AssemblyName.GetAssemblyName(file);
- string relativePath = Path.GetRelativePath(sbSdkPath, file);
- string normalizedPath = BaselineHelper.RemoveVersions(relativePath);
-
- if (!Utilities.IsFileExcluded(normalizedPath, exclusionFilters))
+ foreach (string file in Directory.EnumerateFiles(dir, "*", SearchOption.TopDirectoryOnly))
{
- sbSdkAssemblyVersions.Add(normalizedPath, GetVersion(assemblyName));
+ string fileExt = Path.GetExtension(file);
+ if (fileExt.Equals(".dll", StringComparison.OrdinalIgnoreCase) ||
+ fileExt.Equals(".exe", StringComparison.OrdinalIgnoreCase))
+ {
+ string relativePath = Path.GetRelativePath(sbSdkPath, file);
+ string normalizedPath = BaselineHelper.RemoveVersions(relativePath);
+ if (!Utilities.IsFileExcluded(normalizedPath, exclusionFilters))
+ {
+ try
+ {
+ AssemblyName assemblyName = AssemblyName.GetAssemblyName(file);
+ Assert.True(sbSdkAssemblyVersions.TryAdd(normalizedPath, GetVersion(assemblyName)));
+ }
+ catch (BadImageFormatException)
+ {
+ Console.WriteLine($"BadImageFormatException: {file}");
+ }
+ }
+ }
}
- }
+ });
+ tasks.Add(t);
}
- return sbSdkAssemblyVersions;
+ //foreach (string file in Directory.EnumerateFiles(sbSdkPath, "*", SearchOption.AllDirectories))
+ //{
+ // string fileExt = Path.GetExtension(file);
+ // if (fileExt.Equals(".dll", StringComparison.OrdinalIgnoreCase) ||
+ // fileExt.Equals(".exe", StringComparison.OrdinalIgnoreCase))
+ // {
+ // string relativePath = Path.GetRelativePath(sbSdkPath, file);
+ // string normalizedPath = BaselineHelper.RemoveVersions(relativePath);
+ // if (!Utilities.IsFileExcluded(normalizedPath, exclusionFilters))
+ // {
+ // var t = Task.Run(() =>
+ // {
+ // try
+ // {
+ // AssemblyName assemblyName = AssemblyName.GetAssemblyName(file);
+ // sbSdkAssemblyVersions.Add(normalizedPath, GetVersion(assemblyName));
+ // }
+ // catch (BadImageFormatException)
+ // {
+ // Console.WriteLine($"BadImageFormatException: {file}");
+ // }
+ // });
+ // tasks.Add(t);
+ // }
+ // }
+ //}
+ Task.WaitAll(tasks.ToArray());
+ return sbSdkAssemblyVersions.ToDictionary();
}
private void WriteTarballFileList(string? tarballPath, string outputFileName, bool isPortable, string sdkType)
diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Utilities.cs b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Utilities.cs
index 228a65a61..55377b29a 100644
--- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Utilities.cs
+++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/Utilities.cs
@@ -23,7 +23,7 @@ public static class Utilities
/// Returns whether the given file path is excluded by the given exclusions using glob file matching.
///
public static bool IsFileExcluded(string filePath, IEnumerable exclusions) =>
- GetMatchingFileExclusions(filePath, exclusions, exclusion => exclusion).Any();
+ GetMatchingFileExclusions(filePath.Replace('\\', '/'), exclusions, exclusion => exclusion).Any();
public static IEnumerable GetMatchingFileExclusions(string filePath, IEnumerable exclusions, Func getExclusionExpression) =>
exclusions.Where(exclusion => FileSystemName.MatchesSimpleExpression(getExclusionExpression(exclusion), filePath));
diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/Config.cs b/src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/Config.cs
new file mode 100644
index 000000000..25aff9d34
--- /dev/null
+++ b/src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/Config.cs
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.IO;
+
+namespace Microsoft.DotNet.SourceBuild.SmokeTests;
+
+internal static class Config
+{
+ public const string DotNetDirectoryEnv = "UNIFIED_BUILD_VALIDATION_DOTNET_DIR";
+ public const string IncludeArtifactsSizeEnv = "UNIFIED_BUILD_VALIDATION_INCLUDE_ARTIFACTSSIZE";
+ public const string MsftSdkTarballPathEnv = "UNIFIED_BUILD_VALIDATION_MSFT_SDK_TARBALL_PATH";
+ public const string PoisonReportPathEnv = "UNIFIED_BUILD_VALIDATION_POISON_REPORT_PATH";
+ public const string PortableRidEnv = "UNIFIED_BUILD_VALIDATION_PORTABLE_RID";
+ public const string PrereqsPathEnv = "UNIFIED_BUILD_VALIDATION_PREREQS_PATH";
+ public const string CustomPackagesPathEnv = "UNIFIED_BUILD_VALIDATION_CUSTOM_PACKAGES_PATH";
+ public const string SdkTarballPathEnv = "UNIFIED_BUILD_VALIDATION_SDK_TARBALL_PATH";
+ public const string SourceBuiltArtifactsPathEnv = "UNIFIED_BUILD_VALIDATION_SOURCEBUILT_ARTIFACTS_PATH";
+ public const string TargetRidEnv = "UNIFIED_BUILD_VALIDATION_TARGET_RID";
+ public const string WarnSdkContentDiffsEnv = "UNIFIED_BUILD_VALIDATION_WARN_SDK_CONTENT_DIFFS";
+ public const string WarnLicenseScanDiffsEnv = "UNIFIED_BUILD_VALIDATION_WARN_LICENSE_SCAN_DIFFS";
+ public const string RunningInCIEnv = "UNIFIED_BUILD_VALIDATION_RUNNING_IN_CI";
+ public const string LicenseScanPathEnv = "UNIFIED_BUILD_VALIDATION_LICENSE_SCAN_PATH";
+
+ public static string DotNetDirectory { get; } =
+ Environment.GetEnvironmentVariable(DotNetDirectoryEnv) ?? Path.Combine(Directory.GetCurrentDirectory(), ".dotnet");
+ public static string? MsftSdkTarballPath { get; } = Environment.GetEnvironmentVariable(MsftSdkTarballPathEnv);
+ public static string PortableRid { get; } = Environment.GetEnvironmentVariable(PortableRidEnv) ??
+ throw new InvalidOperationException($"'{Config.PortableRidEnv}' must be specified");
+ public static string? PrereqsPath { get; } = Environment.GetEnvironmentVariable(PrereqsPathEnv);
+ public static string? CustomPackagesPath { get; } = Environment.GetEnvironmentVariable(CustomPackagesPathEnv);
+ public static string? SdkTarballPath { get; } = Environment.GetEnvironmentVariable(SdkTarballPathEnv);
+ public static string? SourceBuiltArtifactsPath { get; } = Environment.GetEnvironmentVariable(SourceBuiltArtifactsPathEnv);
+ public static string TargetRid { get; } = Environment.GetEnvironmentVariable(TargetRidEnv) ??
+ throw new InvalidOperationException($"'{Config.TargetRidEnv}' must be specified");
+ public static string TargetArchitecture { get; } = TargetRid.Split('-')[1];
+ public static bool WarnOnSdkContentDiffs { get; } =
+ bool.TryParse(Environment.GetEnvironmentVariable(WarnSdkContentDiffsEnv), out bool warnOnSdkContentDiffs) && warnOnSdkContentDiffs;
+ public static bool WarnOnLicenseScanDiffs { get; } =
+ bool.TryParse(Environment.GetEnvironmentVariable(WarnLicenseScanDiffsEnv), out bool warnOnLicenseScanDiffs) && warnOnLicenseScanDiffs;
+
+ // Indicates whether the tests are being run in the context of a CI pipeline
+ public static bool RunningInCI { get; } =
+ bool.TryParse(Environment.GetEnvironmentVariable(RunningInCIEnv), out bool runningInCI) && runningInCI;
+
+ public static string? LicenseScanPath { get; } = Environment.GetEnvironmentVariable(LicenseScanPathEnv);
+}
diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/Microsoft.DotNet.UnifiedBuild.Tests.csproj b/src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/Microsoft.DotNet.UnifiedBuild.Tests.csproj
new file mode 100644
index 000000000..a7830912f
--- /dev/null
+++ b/src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/Microsoft.DotNet.UnifiedBuild.Tests.csproj
@@ -0,0 +1,44 @@
+
+
+
+ net9.0
+ enable
+ false
+ $(DefaultExcludesInProjectFolder);assets/**/*
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/assets/SdkAssemblyVersionDiffExclusions.txt b/src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/assets/SdkAssemblyVersionDiffExclusions.txt
new file mode 100644
index 000000000..1b5390e2a
--- /dev/null
+++ b/src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/assets/SdkAssemblyVersionDiffExclusions.txt
@@ -0,0 +1,16 @@
+# Contains the list of files whose assembly versions are to be excluded from comparison between the MSFT & SB SDK.
+# These exclusions only take effect if the assembly version of the file in the SB SDK is equal to or greater than
+# the version in the MSFT SDK. If the version is less, the file will show up in the results as this is not a scenario
+# that is valid for shipping.
+#
+# This list is processed using FileSystemName.MatchesSimpleExpression
+#
+# Examples
+# 'folder/*' matches 'folder/' and 'folder/abc'
+# 'folder/?*' matches 'folder/abc' but not 'folder/'
+#
+# We do not want to filter-out folder entries, therefore, we should use: '?*' and not just '*'
+
+./sdk/x.y.z/TestHostNetFramework/x64/msdia140.dll
+./sdk/x.y.z/TestHostNetFramework/x86/msdia140.dll
+./sdk/x.y.z/datacollector.dll
diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/assets/SdkFileDiffExclusions.txt b/src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/assets/SdkFileDiffExclusions.txt
new file mode 100644
index 000000000..efe2bec15
--- /dev/null
+++ b/src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/assets/SdkFileDiffExclusions.txt
@@ -0,0 +1,24 @@
+# This list is processed using FileSystemName.MatchesSimpleExpression
+#
+# Format
+# {msft|sb}, [# comment]
+# msft = Microsoft built SDK
+# sb = source-built SDK
+#
+# Examples
+# 'folder/*' matches 'folder/' and 'folder/abc'
+# 'folder/?*' matches 'folder/abc' but not 'folder/'
+
+msft,./sdk/x.y.z/TestHostNetFramework/x64/msdia140.dll
+msft,./sdk/x.y.z/TestHostNetFramework/x86/msdia140.dll
+msft,./sdk/x.y.z/datacollector.dll
+
+sb,./sdk/x.y.z/TestHostNetFramework/x64/msdia140.dll
+sb,./sdk/x.y.z/TestHostNetFramework/x86/msdia140.dll
+sb,./sdk/x.y.z/datacollector.dll
+
+msft,./sdk/x.y.z/Containers/containerize/*
+sb,./sdk/x.y.z/Containers/containerize/*
+
+msft,./sdk/x.y.z/Containers/tasks/net472/*
+sb,./sdk/x.y.z/Containers/tasks/net472/*
diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/assets/baselines/MsftToSbSdkAssemblyVersions.diff b/src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/assets/baselines/MsftToSbSdkAssemblyVersions.diff
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/assets/baselines/MsftToSbSdkAssemblyVersions.diff
@@ -0,0 +1 @@
+
diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/assets/baselines/MsftToSbSdkFiles.diff b/src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/assets/baselines/MsftToSbSdkFiles.diff
new file mode 100644
index 000000000..745589d6b
--- /dev/null
+++ b/src/SourceBuild/content/test/Microsoft.DotNet.UnifiedBuild.Tests/assets/baselines/MsftToSbSdkFiles.diff
@@ -0,0 +1,43 @@
+diff --git a/msftSdkFiles.txt b/sbSdkFiles.txt
+index ------------
+--- a/msftSdkFiles.txt
++++ b/sbSdkFiles.txt
+@@ ------------ @@
+ ./packs/Microsoft.AspNetCore.App.Ref/x.y.z/ref\netx.y\System.Security.Cryptography.Xml.xml
+ ./packs/Microsoft.AspNetCore.App.Ref/x.y.z/ref\netx.y\System.Threading.RateLimiting.dll
+ ./packs/Microsoft.AspNetCore.App.Ref/x.y.z/ref\netx.y\System.Threading.RateLimiting.xml
+-./packs/Microsoft.NETCore.App.Host.linux-x64/
+-./packs/Microsoft.NETCore.App.Host.linux-x64/x.y.z/
+-./packs/Microsoft.NETCore.App.Host.linux-x64/x.y.z/runtimes/
+-./packs/Microsoft.NETCore.App.Host.linux-x64/x.y.z/runtimes/linux-x64/
+-./packs/Microsoft.NETCore.App.Host.linux-x64/x.y.z/runtimes/linux-x64/native/
+-./packs/Microsoft.NETCore.App.Host.linux-x64/x.y.z/runtimes/linux-x64/native/apphost
+-./packs/Microsoft.NETCore.App.Host.linux-x64/x.y.z/runtimes/linux-x64/native/coreclr_delegates.h
+-./packs/Microsoft.NETCore.App.Host.linux-x64/x.y.z/runtimes/linux-x64/native/hostfxr.h
+-./packs/Microsoft.NETCore.App.Host.linux-x64/x.y.z/runtimes/linux-x64/native/libnethost.a
+-./packs/Microsoft.NETCore.App.Host.linux-x64/x.y.z/runtimes/linux-x64/native/libnethost.so
+-./packs/Microsoft.NETCore.App.Host.linux-x64/x.y.z/runtimes/linux-x64/native/nethost.h
+-./packs/Microsoft.NETCore.App.Host.linux-x64/x.y.z/runtimes/linux-x64/native/singlefilehost
++./packs/Microsoft.NETCore.App.Host.banana-rid/
++./packs/Microsoft.NETCore.App.Host.banana-rid/x.y.z/
++./packs/Microsoft.NETCore.App.Host.banana-rid/x.y.z/runtimes/
++./packs/Microsoft.NETCore.App.Host.banana-rid/x.y.z/runtimes/banana-rid/
++./packs/Microsoft.NETCore.App.Host.banana-rid/x.y.z/runtimes/banana-rid/native/
++./packs/Microsoft.NETCore.App.Host.banana-rid/x.y.z/runtimes/banana-rid/native/apphost
++./packs/Microsoft.NETCore.App.Host.banana-rid/x.y.z/runtimes/banana-rid/native/coreclr_delegates.h
++./packs/Microsoft.NETCore.App.Host.banana-rid/x.y.z/runtimes/banana-rid/native/hostfxr.h
++./packs/Microsoft.NETCore.App.Host.banana-rid/x.y.z/runtimes/banana-rid/native/libnethost.a
++./packs/Microsoft.NETCore.App.Host.banana-rid/x.y.z/runtimes/banana-rid/native/libnethost.so
++./packs/Microsoft.NETCore.App.Host.banana-rid/x.y.z/runtimes/banana-rid/native/nethost.h
++./packs/Microsoft.NETCore.App.Host.banana-rid/x.y.z/runtimes/banana-rid/native/singlefilehost
+ ./packs/Microsoft.NETCore.App.Ref/
+ ./packs/Microsoft.NETCore.App.Ref/x.y.z/
+ ./packs/Microsoft.NETCore.App.Ref/x.y.z/analyzers/
+@@ ------------ @@
+ ./sdk/x.y.z/DotnetTools/dotnet-watch/x.y.z/tools\netx.y\any/runtimes/win/lib/
+ ./sdk/x.y.z/DotnetTools/dotnet-watch/x.y.z/tools\netx.y\any/runtimes/win/lib\netx.y\
+ ./sdk/x.y.z/DotnetTools/dotnet-watch/x.y.z/tools\netx.y\any/runtimes/win/lib\netx.y\System.Diagnostics.EventLog.dll
+-./sdk/x.y.z/DotnetTools/dotnet-watch/x.y.z/tools\netx.y\any/runtimes/win/lib\netx.y\System.Diagnostics.EventLog.Messages.dll
+ ./sdk/x.y.z/DotnetTools/dotnet-watch/x.y.z/tools\netx.y\any/runtimes/win/lib\netx.y\System.Security.Cryptography.Pkcs.dll
+ ./sdk/x.y.z/DotnetTools/dotnet-watch/x.y.z/tools\netx.y\any/runtimes/win/lib\netx.y\System.Windows.Extensions.dll
+ ./sdk/x.y.z/DotnetTools/dotnet-watch/x.y.z/tools\netx.y\any/System.CodeDom.dll
\ No newline at end of file