From e2881ae96bb4399864723aa46469c82379b03b32 Mon Sep 17 00:00:00 2001 From: Elinor Fung <47805090+elinor-fung@users.noreply.github.com> Date: Wed, 4 Mar 2020 23:32:44 -0800 Subject: [PATCH] Update error message on failing to find hostpolicy for self-contained (#33193) - Specify if the config wasn't found versus didn't have a framework - Show message for apphost (not just dotnet) --- .../corehost/cli/fxr/hostpolicy_resolver.cpp | 18 +++-- .../PortableAppActivation.cs | 72 ++++++++++++++++++- 2 files changed, 82 insertions(+), 8 deletions(-) diff --git a/src/installer/corehost/cli/fxr/hostpolicy_resolver.cpp b/src/installer/corehost/cli/fxr/hostpolicy_resolver.cpp index 3f0e9b791b5ec..049d61a62a5c4 100644 --- a/src/installer/corehost/cli/fxr/hostpolicy_resolver.cpp +++ b/src/installer/corehost/cli/fxr/hostpolicy_resolver.cpp @@ -299,17 +299,23 @@ bool hostpolicy_resolver::try_get_dir( // If it still couldn't be found, somebody upstack messed up. Flag an error for the "expected" location. trace::error(_X("A fatal error was encountered. The library '%s' required to execute the application was not found in '%s'."), LIBHOSTPOLICY_NAME, expected.c_str()); - if (mode == host_mode_t::muxer && !is_framework_dependent) + if ((mode == host_mode_t::muxer || mode == host_mode_t::apphost) && !is_framework_dependent) { - if (!pal::file_exists(get_app(fx_definitions).get_runtime_config().get_path())) + trace::error(_X("Failed to run as a self-contained app.")); + const pal::string_t config_file_name = get_app(fx_definitions).get_runtime_config().get_path(); + if (!pal::file_exists(config_file_name)) { - trace::error(_X("Failed to run as a self-contained app. If this should be a framework-dependent app, add the %s file specifying the appropriate framework."), - get_app(fx_definitions).get_runtime_config().get_path().c_str()); + trace::error(_X(" - The application was run as a self-contained app because '%s' was not found."), + config_file_name.c_str()); + trace::error(_X(" - If this should be a framework-dependent app, add the '%s' file and specify the appropriate framework."), + config_file_name.c_str()); } else if (get_app(fx_definitions).get_name().empty()) { - trace::error(_X("Failed to run as a self-contained app. If this should be a framework-dependent app, specify the appropriate framework in %s."), - get_app(fx_definitions).get_runtime_config().get_path().c_str()); + trace::error(_X(" - The application was run as a self-contained app because '%s' did not specify a framework."), + config_file_name.c_str()); + trace::error(_X(" - If this should be a framework-dependent app, specify the appropriate framework in '%s'."), + config_file_name.c_str()); } } return false; diff --git a/src/installer/test/HostActivation.Tests/PortableAppActivation.cs b/src/installer/test/HostActivation.Tests/PortableAppActivation.cs index cd3fc2dba0190..0c46e67de869e 100644 --- a/src/installer/test/HostActivation.Tests/PortableAppActivation.cs +++ b/src/installer/test/HostActivation.Tests/PortableAppActivation.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Microsoft.DotNet.Cli.Build; using Microsoft.DotNet.Cli.Build.Framework; using System; using System.Diagnostics; @@ -249,7 +250,7 @@ public void AppHost_FrameworkDependent_Succeeds() var appExe = fixture.TestProject.AppExe; File.Copy(sharedTestState.BuiltAppHost, appExe, overwrite: true); AppHostExtensions.BindAppHost(appExe); - + // Get the framework location that was built string builtDotnet = fixture.BuiltDotnet.BinPath; @@ -348,6 +349,61 @@ public void ComputedTPADoesntEndWithPathSeparator() .And.HaveStdErrMatching($"Property TRUSTED_PLATFORM_ASSEMBLIES = .*[^{Path.PathSeparator}]$", System.Text.RegularExpressions.RegexOptions.Multiline); } + [Theory] + [InlineData(true)] + [InlineData(false)] + public void MissingRuntimeConfig_Fails(bool useAppHost) + { + Command command; + if (useAppHost) + { + command = Command.Create(sharedTestState.MockApp.AppExe) + .DotNetRoot(sharedTestState.BuiltDotNet.BinPath); + } + else + { + command = sharedTestState.BuiltDotNet.Exec(sharedTestState.MockApp.AppDll); + } + + string hostPolicyName = RuntimeInformationExtensions.GetSharedLibraryFileNameForCurrentPlatform("hostpolicy"); + command.EnableTracingAndCaptureOutputs() + .MultilevelLookup(false) + .Execute() + .Should().Fail() + .And.HaveStdErrContaining($"The library '{hostPolicyName}' required to execute the application was not found") + .And.HaveStdErrContaining("Failed to run as a self-contained app") + .And.HaveStdErrContaining($"'{sharedTestState.MockApp.RuntimeConfigJson}' was not found"); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void MissingFrameworkInRuntimeConfig_Fails(bool useAppHost) + { + TestApp app = sharedTestState.MockApp.Copy(); + RuntimeConfig.FromFile(app.RuntimeConfigJson).Save(); + + Command command; + if (useAppHost) + { + command = Command.Create(app.AppExe) + .DotNetRoot(sharedTestState.BuiltDotNet.BinPath); + } + else + { + command = sharedTestState.BuiltDotNet.Exec(app.AppDll); + } + + string hostPolicyName = RuntimeInformationExtensions.GetSharedLibraryFileNameForCurrentPlatform("hostpolicy"); + command.EnableTracingAndCaptureOutputs() + .MultilevelLookup(false) + .Execute() + .Should().Fail() + .And.HaveStdErrContaining($"The library '{hostPolicyName}' required to execute the application was not found") + .And.HaveStdErrContaining("Failed to run as a self-contained app") + .And.HaveStdErrContaining($"'{app.RuntimeConfigJson}' did not specify a framework"); + } + [Theory] [InlineData(true)] [InlineData(false)] @@ -459,7 +515,7 @@ public void AppHost_GUI_FrameworkDependent_DisabledGUIErrors_DialogNotShown() var fixture = sharedTestState.PortableAppFixture_Built .Copy(); - + string appExe = fixture.TestProject.AppExe; File.Copy(sharedTestState.BuiltAppHost, appExe, overwrite: true); AppHostExtensions.BindAppHost(appExe); @@ -579,13 +635,18 @@ public class SharedTestState : IDisposable { public TestProjectFixture PortableAppFixture_Built { get; } public TestProjectFixture PortableAppFixture_Published { get; } + public RepoDirectoriesProvider RepoDirectories { get; } public string BuiltAppHost { get; } + public DotNetCli BuiltDotNet { get; } + + public TestApp MockApp { get; } public SharedTestState() { RepoDirectories = new RepoDirectoriesProvider(); BuiltAppHost = Path.Combine(RepoDirectories.HostArtifacts, RuntimeInformationExtensions.GetExeFileNameForCurrentPlatform("apphost")); + BuiltDotNet = new DotNetCli(RepoDirectories.BuiltDotnet); PortableAppFixture_Built = new TestProjectFixture("PortableApp", RepoDirectories) .EnsureRestored(RepoDirectories.CorehostPackages) @@ -594,12 +655,19 @@ public SharedTestState() PortableAppFixture_Published = new TestProjectFixture("PortableApp", RepoDirectories) .EnsureRestored(RepoDirectories.CorehostPackages) .PublishProject(); + + MockApp = new TestApp(SharedFramework.CalculateUniqueTestDirectory(Path.Combine(TestArtifact.TestArtifactsPath, "portableAppActivation")), "App"); + Directory.CreateDirectory(MockApp.Location); + File.WriteAllText(MockApp.AppDll, string.Empty); + File.Copy(BuiltAppHost, MockApp.AppExe); + AppHostExtensions.BindAppHost(MockApp.AppExe); } public void Dispose() { PortableAppFixture_Built.Dispose(); PortableAppFixture_Published.Dispose(); + MockApp.Dispose(); } } }