Skip to content
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

Switch LightupAppActivation tests to component tests targeting additional deps #78139

Merged
merged 2 commits into from
Nov 10, 2022
Merged
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

This file was deleted.

39 changes: 0 additions & 39 deletions src/installer/tests/Assets/TestProjects/LightupClient/Program.cs

This file was deleted.

This file was deleted.

21 changes: 0 additions & 21 deletions src/installer/tests/Assets/TestProjects/LightupLib/Program.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.IO;
using Microsoft.DotNet.Cli.Build;
using Microsoft.DotNet.Cli.Build.Framework;
using Xunit;

namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.DependencyResolution
{
public class AdditionalDeps : DependencyResolutionBase, IClassFixture<AdditionalDeps.SharedTestState>
{
private SharedTestState SharedState { get; }

// Shared state has a NetCoreApp with the two versions below
public const string NetCoreAppVersion = "4.1.1";
public const string NetCoreAppVersionPreview = "4.1.2-preview.2";

public AdditionalDeps(SharedTestState sharedState)
{
SharedState = sharedState;
}

// Additional deps can point to a directory. The host looks for deps.json files in:
// <additional_deps_dir>/shared/<fx_name>/<version>
// It uses the version closest to the framework version with a matching major/minor
// and equal or lesser patch, release or pre-release.
[Theory]
// exact match
[InlineData("4.1.1", new string[] { "4.1.0", "4.1.1" }, "4.1.1")]
[InlineData("4.1.2-preview.2", new string[] { "4.1.1", "4.1.2-preview.2" }, "4.1.2-preview.2")]
// lower patch version
[InlineData("4.1.1", new string[] { "4.1.0", "4.1.2-preview.1" }, "4.1.0")]
[InlineData("4.1.2-preview.2", new string[] { "4.1.1", "4.1.2" }, "4.1.1")]
// lower prerelease
[InlineData("4.1.1", new string[] { "4.1.0", "4.1.1-preview.1" }, "4.1.1-preview.1")]
[InlineData("4.1.2-preview.2", new string[] { "4.1.1", "4.1.2-preview.1" }, "4.1.2-preview.1")]
// no match
[InlineData("4.1.1", new string[] { "4.0.0", "4.1.2", "4.2.0" }, null)]
[InlineData("4.1.2-preview.2", new string[] { "4.0.0", "4.1.2", "4.2.0" }, null)]
public void DepsDirectory(string fxVersion, string[] versions, string usedVersion)
{
string additionalDepsDirectory = SharedFramework.CalculateUniqueTestDirectory(Path.Combine(SharedState.Location, "additionalDeps"));
using (TestArtifact artifact = new TestArtifact(additionalDepsDirectory))
{
string depsJsonName = Path.GetFileName(SharedState.AdditionalDepsComponent.DepsJson);
foreach (string version in versions)
{
string path = Path.Combine(additionalDepsDirectory, "shared", MicrosoftNETCoreApp, version);
Directory.CreateDirectory(path);
File.Copy(
SharedState.AdditionalDepsComponent.DepsJson,
Path.Combine(path, depsJsonName),
true);
}

TestApp app = SharedState.FrameworkReferenceApp;
if (fxVersion != NetCoreAppVersion)
{
// Make a copy of the app and update its framework version
app = SharedState.FrameworkReferenceApp.Copy();
RuntimeConfig.FromFile(app.RuntimeConfigJson)
.RemoveFramework(MicrosoftNETCoreApp)
.WithFramework(MicrosoftNETCoreApp, fxVersion)
.Save();
}

CommandResult result = SharedState.DotNetWithNetCoreApp.Exec(Constants.AdditionalDeps.CommandLineArgument, additionalDepsDirectory, app.AppDll)
.EnableTracingAndCaptureOutputs()
.Execute();

result.Should().Pass();
if (string.IsNullOrEmpty(usedVersion))
{
result.Should().HaveStdErrContaining($"No additional deps directory less than or equal to [{fxVersion}] found with same major and minor version.");
}
else
{
result.Should().HaveUsedAdditionalDeps(Path.Combine(additionalDepsDirectory, "shared", MicrosoftNETCoreApp, usedVersion, depsJsonName));
}
}
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public void DepsFile(bool dependencyExists)
{
string additionalLibName = SharedState.AdditionalDepsComponent.AssemblyName;
string additionalDepsFile = SharedState.AdditionalDepsComponent.DepsJson;

TestApp app = SharedState.FrameworkReferenceApp;
if (!dependencyExists)
{
// Make a copy of the app and delete the app-local dependency
app = SharedState.FrameworkReferenceApp.Copy();
File.Delete(Path.Combine(app.Location, $"{additionalLibName}.dll"));
}

CommandResult result = SharedState.DotNetWithNetCoreApp.Exec(Constants.AdditionalDeps.CommandLineArgument, additionalDepsFile, app.AppDll)
.EnableTracingAndCaptureOutputs()
.Execute(expectedToFail: !dependencyExists);

result.Should().HaveUsedAdditionalDeps(additionalDepsFile);
if (dependencyExists)
{
result.Should().Pass()
.And.HaveResolvedAssembly(Path.Combine(app.Location, $"{additionalLibName}.dll"));
}
else
{
result.Should().Fail()
.And.HaveStdErrContaining(
$"Error:{Environment.NewLine}" +
$" An assembly specified in the application dependencies manifest ({additionalLibName}.deps.json) was not found:" + Environment.NewLine +
$" package: \'{additionalLibName}\', version: \'1.0.0\'" + Environment.NewLine +
$" path: \'{additionalLibName}.dll\'");
}
}

[Fact]
public void InvalidJson()
{
string invalidDepsFile = Path.Combine(SharedState.Location, "invalid.deps.json");
try
{
File.WriteAllText(invalidDepsFile, "{");

SharedState.DotNetWithNetCoreApp.Exec(Constants.AdditionalDeps.CommandLineArgument, invalidDepsFile, SharedState.FrameworkReferenceApp.AppDll)
.EnableTracingAndCaptureOutputs()
.Execute(expectedToFail: true)
.Should().Fail()
.And.HaveUsedAdditionalDeps(invalidDepsFile)
.And.HaveStdErrContaining($"Error initializing the dependency resolver: An error occurred while parsing: {invalidDepsFile}");
}
finally
{
FileUtils.DeleteFileIfPossible(invalidDepsFile);
}
}

public class SharedTestState : DependencyResolutionBase.SharedTestStateBase
{
public DotNetCli DotNetWithNetCoreApp { get; }

public TestApp FrameworkReferenceApp { get; }

public TestApp AdditionalDepsComponent { get; }

public SharedTestState()
{
DotNetWithNetCoreApp = DotNet("WithNetCoreApp")
.AddMicrosoftNETCoreAppFrameworkMockCoreClr(NetCoreAppVersion)
.AddMicrosoftNETCoreAppFrameworkMockCoreClr(NetCoreAppVersionPreview)
.Build();

AdditionalDepsComponent = CreateComponentWithNoDependencies();

TestApp app = CreateFrameworkReferenceApp(MicrosoftNETCoreApp, NetCoreAppVersion);
FrameworkReferenceApp = NetCoreAppBuilder.PortableForNETCoreApp(app)
.WithProject(p => p.WithAssemblyGroup(null, g => g.WithMainAssembly()))
.Build(app);

// Copy dependency next to app
File.Copy(AdditionalDepsComponent.AppDll, Path.Combine(FrameworkReferenceApp.Location, $"{AdditionalDepsComponent.AssemblyName}.dll"));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ public static AndConstraint<CommandResultAssertions> NotHaveResolvedComponentDep
return assertion.NotHaveResolvedComponentDependencyContaining(native_search_paths, RelativePathsToAbsoluteAppPaths(path, app));
}

public static AndConstraint<CommandResultAssertions> HaveUsedAdditionalDeps(this CommandResultAssertions assertion, string depsFilePath)
{
return assertion.HaveStdErrContaining($"Using specified additional deps.json: '{depsFilePath}'");
}

private static string GetAppMockPropertyValue(CommandResultAssertions assertion, string propertyName) =>
GetMockPropertyValue(assertion, $"mock property[{propertyName}] = ");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,46 @@ protected override void RunTest(string testAssemblyName, string appAsmVersion, s
}
}

public class AdditionalDepsPerAssemblyVersionResolution :
PerAssemblyVersionResolutionBase,
IClassFixture<PerAssemblyVersionResolutionBase.SharedTestState>
{
public AdditionalDepsPerAssemblyVersionResolution(SharedTestState sharedState)
: base(sharedState)
{
}

protected override void RunTest(string testAssemblyName, string appAsmVersion, string appFileVersion, bool appWins)
{
using (TestApp additionalDependency = TestApp.CreateEmpty("additionalDeps"))
{
// Additional deps are treated as part of app dependencies.
// The result for whether the app wins should be the same whether the dependency is
// specified via additional deps or by the app itself.
NetCoreAppBuilder builder = NetCoreAppBuilder.PortableForNETCoreApp(additionalDependency)
.WithPackage(TestVersionsPackage, "1.0.0", lib => lib
.WithAssemblyGroup(null, g => g
.WithAsset(testAssemblyName + ".dll", rf => rf
.WithVersion(appAsmVersion, appFileVersion))));
builder.Build(additionalDependency);

TestApp app = SharedState.FrameworkReferenceApp.Copy();
string appTestAssemblyPath = Path.Combine(app.Location, $"{testAssemblyName}.dll");
File.WriteAllText(Path.Combine(app.Location, $"{testAssemblyName}.dll"), null);

string expectedTestAssemblyPath = appWins
? appTestAssemblyPath
: Path.Combine(SharedState.DotNetWithNetCoreApp.GreatestVersionSharedFxPath, $"{testAssemblyName}.dll");
SharedState.DotNetWithNetCoreApp.Exec(Constants.AdditionalDeps.CommandLineArgument, additionalDependency.DepsJson, app.AppDll)
.EnableTracingAndCaptureOutputs()
.Execute()
.Should().Pass()
.And.HaveUsedAdditionalDeps(additionalDependency.DepsJson)
.And.HaveResolvedAssembly(expectedTestAssemblyPath);
}
}
}

public class ComponentPerAssemblyVersionResolution :
PerAssemblyVersionResolutionBase,
IClassFixture<PerAssemblyVersionResolutionBase.SharedTestState>
Expand Down
Loading