Skip to content

Add package source mappings unit-tests #44649

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Nov 6, 2024

Conversation

NikolaMilosavljevic
Copy link
Member

Fixes dotnet/source-build#4706

This PR adds unit-tests for package source mappings task and introduces a new test project for common, shared, tests.

Some interesting details:

  • Using Array.Sort to get a stable output of Directory.GetFiles which is not guaranteed to return a sorted output. This helps with unit-tests.
  • Some assembly references, like nuget.* are used from SDK, which is necessary due to
    <!--
    Use some assemblies from the SDK, instead of package references. This ensures they match what's
    found when the task is loaded by the SDK's MSBuild.
    Reference NuGet assemblies, except a command line assembly that causes warnings such as:
    MSB3277: Found conflicts between different versions of "System.Collections" that could not be resolved.
    -->
    <ItemGroup>
    <SdkAssembly Include="$([MSBuild]::NormalizePath('$(NetCoreRoot)', 'sdk', '$(NETCoreSdkVersion)', 'Newtonsoft.Json.dll'));
    $([MSBuild]::NormalizeDirectory('$(NetCoreRoot)', 'sdk', '$(NETCoreSdkVersion)'))NuGet.*.dll"
    Exclude="$([MSBuild]::NormalizePath('$(NetCoreRoot)', 'sdk', '$(NETCoreSdkVersion)', 'NuGet.CommandLine.XPlat.dll'))" />
    </ItemGroup>
    and the need to use the same dependencies in unit-test assembly, as the task assembly. This still shows a warning when running source-build tests, as there other versions of nuget.* restored from source-build feeds. Therefore a NoWarn is needed for MSB3277.
  • 9 tests cover all unified-build and source-build scenarios, including a special SBRP repo build and unified-build without local sources (i.e. arcade repo).

@NikolaMilosavljevic NikolaMilosavljevic requested review from a team as code owners November 5, 2024 17:40
@ghost ghost added Area-Infrastructure untriaged Request triage from a team member labels Nov 5, 2024
Comment on lines 6 to 11
<!--
Required while we're using direct SDK assembly references in
$(RepositoryEngineeringDir)tools/Directory.Build.props for all tools projects
including Microsoft.DotNet.UnifiedBuild.Tasks.
-->
<NoWarn>$(NoWarn);MSB3277</NoWarn>
Copy link
Member

Choose a reason for hiding this comment

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

Can you please elaborate on this? I'm unsure why this is necessary.

Copy link
Member Author

@NikolaMilosavljevic NikolaMilosavljevic Nov 5, 2024

Choose a reason for hiding this comment

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

Without it I am getting the following warning/error:

/src/git/dotnet/.dotnet/sdk/9.0.100-rc.2.24474.11/Microsoft.Common.CurrentVersion.targets(2413,5): error MSB3277: There was a conflict between "NuGet.Frameworks, Version=5.11.0.10, Culture=neutral, PublicKeyToken=31bf3856ad364e35" and "NuGet.Frameworks, Version=6.12.0.115, Culture=neutral, PublicKeyToken=31bf3856ad364e35". [/src/git/dotnet/test/Microsoft.DotNet.Tests/Microsoft.DotNet.Tests.csproj]

Version 6.12.0.115 is referenced from SDK via ReferencePath. Version 5.11.0.10 was discovered in NuGet cache. I'm not 100% sure why this is happening.


string modifiedNugetConfig = Path.Combine(PackageSourceMappingsSetup.PackageSourceMappingsRoot, nugetConfigFilename);
Directory.CreateDirectory(Path.GetDirectoryName(modifiedNugetConfig)!);
File.Copy(originalNugetConfig, modifiedNugetConfig, true);
Copy link
Member

Choose a reason for hiding this comment

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

Are we doing all this in the source tree? Tests shouldn't mutate the source tree. Instead we usually call the create temp directory API to get a temp file / folder.

Copy link
Member Author

Choose a reason for hiding this comment

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

This is in test's temp folder, not in source tree.

Copy link
Member

@ViktorHofer ViktorHofer Nov 5, 2024

Choose a reason for hiding this comment

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

Are you sure? Isn't this under <cwd>/PackageSourceMappingsTests?

Copy link
Member Author

Choose a reason for hiding this comment

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

cwd is the app's root, i.e. artifacts/bin/Microsoft.DotNet.Tests/Release/

Copy link
Member

@ViktorHofer ViktorHofer Nov 5, 2024

Choose a reason for hiding this comment

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

Right and that's not a location that we should write to, if I'm not mistaken. In runtime most/all our tests use a temp location. @jkotas probably knows more about the why.

Copy link
Member Author

Choose a reason for hiding this comment

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

It's an easy fix, so I'll update this.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed with 6337002


// Unified build - with existing mappings - online
[Fact]
public void UnifiedBuildWithMappings()
Copy link
Member

Choose a reason for hiding this comment

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

I think we should avoid the "UnifiedBuild" naming here. This is simply a "BuildWithMappings". UnifiedBuild is "the" way to build in the VMR.

Copy link
Member Author

Choose a reason for hiding this comment

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

Makes sense - will fix.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed with f13f4f1

[Fact]
public void UnifiedBuildWithMappings()
{
string[] sources = ["source-built-arcade", "source-built-runtime", "net-sdk-supporting-feed"];
Copy link
Member

Choose a reason for hiding this comment

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

Consider utilizing constants for the sources to provide "stronger" typing to help avoid human error.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, not sure why I didn't do that. Will fix.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed with f13f4f1

RunTest(nugetConfigFilename, useOnlineFeeds, sources);
}

private static void RunTest(string nugetConfigFilename, bool useOnlineFeeds, string[] sources, string[]? customSources = null, bool sourceBuild = true)
Copy link
Member

Choose a reason for hiding this comment

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

Having an optional boolean parameter defaulted to true is an antipattern. Either default it to false or negate the name.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thought about this as well and will fix it.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed with f13f4f1

File.WriteAllText(nugetConfigFile, fileContents);
}

private static void TokenizeLocalNugetConfigFeeds(string nugetConfigFile)
Copy link
Member

Choose a reason for hiding this comment

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

What is the different with this method versus UpdateNugetConfigTokens? The implementations appear identical.

Copy link
Member Author

Choose a reason for hiding this comment

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

One is replacing key with value, the other replacing value with key.

This was a result of refactoring, but I stopped too soon. I will refactor this further.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed with f13f4f1

private static readonly object myLock = new();
private Dictionary<string, string>? localTokenSourceMappings;

public static readonly string PackageSourceMappingsRoot = Path.Combine(Directory.GetCurrentDirectory(), nameof(PackageSourceMappingsTests));
Copy link
Member

Choose a reason for hiding this comment

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

How does this work it you run the tests multiple times without "cleaning"? Should this be a unique name?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I have a fix for this, will always use a new temp folder.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed with 6337002

private readonly string PrebuiltSource = Path.Combine(PackageSourceMappingsRoot, "prebuilt");
private readonly string SourceBuildReferencePackagesSource = Path.Combine(PackageSourceMappingsRoot, "source-build-reference-package-cache");

public readonly string SourceBuildReferencePackagesRepoDir = Path.Combine(PackageSourceMappingsRoot, "sbrpDir");
Copy link
Member

Choose a reason for hiding this comment

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

Why the Dir suffix?

Copy link
Member Author

Choose a reason for hiding this comment

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

No reason, really. It represents test SBRP repo directory. I'll remove the suffix.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed with f13f4f1


// Source build tests - with and without mappings - online and offline
[Theory]
[InlineData("sb-online.config", true)]
Copy link
Member

Choose a reason for hiding this comment

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

I personally think it would help to name the NuGet.configs with a consistent explicit naming pattern. Specifically I think it would help to call our noMappings in the files. This is similar in nature how you have both online/offline in the name versus implying a default if not specified.

Copy link
Member Author

Choose a reason for hiding this comment

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

Makes sense - will update.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed with f13f4f1

[Fact]
public void UnifiedBuildNoMappings()
{
string[] sources = ["source-built-arcade", "source-built-runtime", "net-sdk-supporting-feed"];
Copy link
Member

Choose a reason for hiding this comment

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

This test's implementation appears identical to UnifiedBuildWithMappings except for the config file. For the SourceBuildTests you utilized a theory. Why not the same here? Overall, I wonder if a single Theory wouldn't make the tests simpler.

Copy link
Member Author

Choose a reason for hiding this comment

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

Will fix - thanks! I missed collapsing these two tests into a common Theory.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed with f13f4f1

I have not tried to merge all tests into a single Theory. While possible, I feel that it would not bring much value, and make inline data harder to manage.

@@ -0,0 +1,242 @@
using System.Collections.Generic;
Copy link
Member

Choose a reason for hiding this comment

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

Hmm this file is missing a license header. I think we are missing a rule in the editorconfig in the VMR.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed with f13f4f1

{
private static PackageSourceMappingsSetup? instance;
private static readonly object myLock = new();
private Dictionary<string, string>? localTokenSourceMappings;
Copy link
Member

Choose a reason for hiding this comment

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

I find it better to separate the static versus instance members as it helps the readability.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed with f51cb51

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Infrastructure untriaged Request triage from a team member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement unit-tests for UpdateNuGetConfigPackageSourcesMappings task
3 participants