Skip to content

Commit

Permalink
Allow runtimeconfig StartupHooks and Environment StartupHooks to both…
Browse files Browse the repository at this point in the history
… be present (#61461)

Allow both env. variable `DOTNET_STARTUP_HOOKS` and the `.runtimeconfig.json` property `STARTUP_HOOKS` to be specified at the same time. The new behavior is to concatenate the two lists, with the env. variable content going first.
  • Loading branch information
tomdegoede authored Nov 19, 2021
1 parent 649e14b commit 6d9edd4
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 6 deletions.
59 changes: 59 additions & 0 deletions src/installer/tests/HostActivation.Tests/StartupHooks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class StartupHooks : IClassFixture<StartupHooks.SharedTestState>
{
private SharedTestState sharedTestState;
private string startupHookVarName = "DOTNET_STARTUP_HOOKS";
private string startupHookRuntimeConfigName = "STARTUP_HOOKS";
private string startupHookSupport = "System.StartupHookProvider.IsSupported";

public StartupHooks(StartupHooks.SharedTestState fixture)
Expand Down Expand Up @@ -105,6 +106,64 @@ public void Muxer_activation_of_Multiple_StartupHooks_Succeeds()
.And.HaveStdOutContaining("Hello World");
}

[Fact]
public void Muxer_activation_of_RuntimeConfig_StartupHook_Succeeds()
{
var fixture = sharedTestState.PortableAppFixture.Copy();
var dotnet = fixture.BuiltDotnet;
var appDll = fixture.TestProject.AppDll;

var startupHookFixture = sharedTestState.StartupHookFixture.Copy();
var startupHookDll = startupHookFixture.TestProject.AppDll;

RuntimeConfig.FromFile(fixture.TestProject.RuntimeConfigJson)
.WithProperty(startupHookRuntimeConfigName, startupHookDll)
.Save();

// RuntimeConfig defined startup hook
dotnet.Exec(appDll)
.CaptureStdOut()
.CaptureStdErr()
.Execute()
.Should().Pass()
.And.HaveStdOutContaining("Hello from startup hook!")
.And.HaveStdOutContaining("Hello World");
}

[Fact]
public void Muxer_activation_of_RuntimeConfig_And_Environment_StartupHooks_SucceedsInExpectedOrder()
{
var fixture = sharedTestState.PortableAppFixture.Copy();
var dotnet = fixture.BuiltDotnet;
var appDll = fixture.TestProject.AppDll;

var startupHookFixture = sharedTestState.StartupHookFixture.Copy();
var startupHookDll = startupHookFixture.TestProject.AppDll;

RuntimeConfig.FromFile(fixture.TestProject.RuntimeConfigJson)
.WithProperty(startupHookRuntimeConfigName, startupHookDll)
.Save();

var startupHook2Fixture = sharedTestState.StartupHookWithDependencyFixture.Copy();
var startupHook2Dll = startupHook2Fixture.TestProject.AppDll;

// include any char to counter output from other threads such as in #57243
const string wildcardPattern = @"[\r\n\s.]*";

// RuntimeConfig and Environment startup hooks in expected order
dotnet.Exec(appDll)
.EnvironmentVariable(startupHookVarName, startupHook2Dll)
.CaptureStdOut()
.CaptureStdErr()
.Execute()
.Should().Pass()
.And.HaveStdOutMatching("Hello from startup hook with dependency!" +
wildcardPattern +
"Hello from startup hook!" +
wildcardPattern +
"Hello World");
}

// Empty startup hook variable
[Fact]
public void Muxer_activation_of_Empty_StartupHook_Variable_Succeeds()
Expand Down
17 changes: 11 additions & 6 deletions src/native/corehost/hostpolicy/hostpolicy_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,11 +281,16 @@ int hostpolicy_context_t::initialize(hostpolicy_init_t &hostpolicy_init, const a
pal::string_t startup_hooks;
if (pal::getenv(_X("DOTNET_STARTUP_HOOKS"), &startup_hooks))
{
if (!coreclr_properties.add(common_property::StartUpHooks, startup_hooks.c_str()))
const pal::char_t *config_startup_hooks;
if (coreclr_properties.try_get(common_property::StartUpHooks, &config_startup_hooks))
{
log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::StartUpHooks));
return StatusCode::LibHostDuplicateProperty;
// env startup hooks shoold have precedence over config startup hooks
// therefore append config_startup_hooks AFTER startup_hooks
startup_hooks.push_back(PATH_SEPARATOR);
startup_hooks.append(config_startup_hooks);
}

coreclr_properties.add(common_property::StartUpHooks, startup_hooks.c_str());
}

// Single-File Bundle Probe
Expand All @@ -297,7 +302,7 @@ int hostpolicy_context_t::initialize(hostpolicy_init_t &hostpolicy_init, const a

if (!coreclr_properties.add(common_property::BundleProbe, ptr_stream.str().c_str()))
{
log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::StartUpHooks));
log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::BundleProbe));
return StatusCode::LibHostDuplicateProperty;
}
}
Expand All @@ -312,7 +317,7 @@ int hostpolicy_context_t::initialize(hostpolicy_init_t &hostpolicy_init, const a

if (!coreclr_properties.add(common_property::PInvokeOverride, ptr_stream.str().c_str()))
{
log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::StartUpHooks));
log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::PInvokeOverride));
return StatusCode::LibHostDuplicateProperty;
}
}
Expand All @@ -321,7 +326,7 @@ int hostpolicy_context_t::initialize(hostpolicy_init_t &hostpolicy_init, const a
#if defined(HOSTPOLICY_EMBEDDED)
if (!coreclr_properties.add(common_property::HostPolicyEmbedded, _X("true")))
{
log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::StartUpHooks));
log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::HostPolicyEmbedded));
return StatusCode::LibHostDuplicateProperty;
}
#endif
Expand Down

0 comments on commit 6d9edd4

Please sign in to comment.