diff --git a/src/installer/corehost/cli/test/nativehost/comhost_test.cpp b/src/installer/corehost/cli/test/nativehost/comhost_test.cpp index 33fd9ba569044026a94811c0a78454a051c153e2..e8722f5535db03072fe4307767de87d22aa8dd71 100644 --- a/src/installer/corehost/cli/test/nativehost/comhost_test.cpp +++ b/src/installer/corehost/cli/test/nativehost/comhost_test.cpp @@ -124,4 +124,45 @@ bool comhost_test::concurrent(const pal::string_t &comhost_path, const pal::stri std::cout << ss.str(); return succeeded; +} + +bool comhost_test::errorinfo(const pal::string_t &comhost_path, const pal::string_t &clsid_str, int count) +{ + CLSID clsid; + std::vector clsidVect; + if (!get_clsid(clsid_str, &clsid, clsidVect)) + return false; + + comhost_exports comhost(comhost_path); + + for (int i = 0; i < count; ++i) + { + HRESULT hr = activate_class(comhost, clsid); + if (SUCCEEDED(hr)) + return false; + + IErrorInfo *ei = nullptr; + hr = ::GetErrorInfo(0, &ei); + if (FAILED(hr) || ei == nullptr) + { + std::cout << "IErrorInfo not set" << std::endl; + return false; + } + + BSTR errorDesc = nullptr; + hr = ei->GetDescription(&errorDesc); + if (FAILED(hr) || errorDesc == nullptr) + { + ei->Release(); + std::cout << "IErrorInfo description not set" << std::endl; + return false; + } + + std::wcout << errorDesc << std::endl; + + ::SysFreeString(errorDesc); + ei->Release(); + } + + return true; } \ No newline at end of file diff --git a/src/installer/corehost/cli/test/nativehost/comhost_test.h b/src/installer/corehost/cli/test/nativehost/comhost_test.h index 39d37af64c335343be3b7e4e06ee454ea9e468f4..adb44911e332ee21a59687be5bc9f57c557bf367 100644 --- a/src/installer/corehost/cli/test/nativehost/comhost_test.h +++ b/src/installer/corehost/cli/test/nativehost/comhost_test.h @@ -9,4 +9,6 @@ namespace comhost_test bool synchronous(const pal::string_t &comhost_path, const pal::string_t &clsid_str, int count); bool concurrent(const pal::string_t &comhost_path, const pal::string_t &clsid_str, int count); + + bool errorinfo(const pal::string_t &comhost_path, const pal::string_t &clsid_str, int count); } diff --git a/src/installer/corehost/cli/test/nativehost/nativehost.cpp b/src/installer/corehost/cli/test/nativehost/nativehost.cpp index 95b952f7e5c0bcfd86f779995696227dde89bb5c..d16b469c23556268bc616e7385ada3a5e55a75b1 100644 --- a/src/installer/corehost/cli/test/nativehost/nativehost.cpp +++ b/src/installer/corehost/cli/test/nativehost/nativehost.cpp @@ -300,6 +300,10 @@ int main(const int argc, const pal::char_t *argv[]) { success = comhost_test::concurrent(comhost_path, clsid_str, count); } + else if (pal::strcmp(scenario, _X("errorinfo")) == 0) + { + success = comhost_test::errorinfo(comhost_path, clsid_str, count); + } return success ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/src/installer/test/HostActivation.Tests/NativeHosting/Comhost.cs b/src/installer/test/HostActivation.Tests/NativeHosting/Comhost.cs index 8e5a39e296551de8c30a3eea27b66fd91a02e8cd..1ebc2cb4d7a7e13336836f293c4d78ad15d5c5ed 100644 --- a/src/installer/test/HostActivation.Tests/NativeHosting/Comhost.cs +++ b/src/installer/test/HostActivation.Tests/NativeHosting/Comhost.cs @@ -34,9 +34,7 @@ public void ActivateClass(int count, bool synchronous) string scenario = synchronous ? "synchronous" : "concurrent"; string args = $"comhost {scenario} {count} {sharedState.ComHostPath} {sharedState.ClsidString}"; CommandResult result = Command.Create(sharedState.NativeHostPath, args) - .CaptureStdErr() - .CaptureStdOut() - .EnvironmentVariable("COREHOST_TRACE", "1") + .EnableTracingAndCaptureOutputs() .EnvironmentVariable("DOTNET_ROOT", sharedState.ComLibraryFixture.BuiltDotnet.BinPath) .EnvironmentVariable("DOTNET_ROOT(x86)", sharedState.ComLibraryFixture.BuiltDotnet.BinPath) .Execute(); @@ -59,26 +57,57 @@ public void ActivateClass_IgnoreAppLocalHostFxr() return; } - var fixture = sharedState.ComLibraryFixture.Copy(); + using (var fixture = sharedState.ComLibraryFixture.Copy()) + { + File.WriteAllText(Path.Combine(fixture.TestProject.BuiltApp.Location, "hostfxr.dll"), string.Empty); + var comHostWithAppLocalFxr = Path.Combine( + fixture.TestProject.BuiltApp.Location, + $"{ fixture.TestProject.AssemblyName }.comhost.dll"); + + string args = $"comhost synchronous 1 {comHostWithAppLocalFxr} {sharedState.ClsidString}"; + CommandResult result = Command.Create(sharedState.NativeHostPath, args) + .EnableTracingAndCaptureOutputs() + .EnvironmentVariable("DOTNET_ROOT", fixture.BuiltDotnet.BinPath) + .EnvironmentVariable("DOTNET_ROOT(x86)", fixture.BuiltDotnet.BinPath) + .Execute(); + + result.Should().Pass() + .And.HaveStdOutContaining("New instance of Server created") + .And.HaveStdOutContaining($"Activation of {sharedState.ClsidString} succeeded.") + .And.HaveStdErrContaining("Using environment variable DOTNET_ROOT"); + } + } + + [Fact] + public void ActivateClass_ValidateIErrorInfoResult() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // COM activation is only supported on Windows + return; + } - File.WriteAllText(Path.Combine(fixture.TestProject.BuiltApp.Location, "hostfxr.dll"), string.Empty); - var comHostWithAppLocalFxr = Path.Combine( - fixture.TestProject.BuiltApp.Location, - $"{ fixture.TestProject.AssemblyName }.comhost.dll"); + using (var fixture = sharedState.ComLibraryFixture.Copy()) + { + string missingRuntimeConfig = Path.Combine(fixture.TestProject.BuiltApp.Location, + $"{ fixture.TestProject.AssemblyName }.runtimeconfig.json"); - string args = $"comhost synchronous 1 {comHostWithAppLocalFxr} {sharedState.ClsidString}"; - CommandResult result = Command.Create(sharedState.NativeHostPath, args) - .CaptureStdErr() - .CaptureStdOut() - .EnvironmentVariable("COREHOST_TRACE", "1") - .EnvironmentVariable("DOTNET_ROOT", fixture.BuiltDotnet.BinPath) - .EnvironmentVariable("DOTNET_ROOT(x86)", fixture.BuiltDotnet.BinPath) - .Execute(); + File.Delete(missingRuntimeConfig); - result.Should().Pass() - .And.HaveStdOutContaining("New instance of Server created") - .And.HaveStdOutContaining($"Activation of {sharedState.ClsidString} succeeded.") - .And.HaveStdErrContaining("Using environment variable DOTNET_ROOT"); + var comHost = Path.Combine( + fixture.TestProject.BuiltApp.Location, + $"{ fixture.TestProject.AssemblyName }.comhost.dll"); + + string args = $"comhost errorinfo 1 {comHost} {sharedState.ClsidString}"; + CommandResult result = Command.Create(sharedState.NativeHostPath, args) + .EnableTracingAndCaptureOutputs() + .EnvironmentVariable("DOTNET_ROOT", fixture.BuiltDotnet.BinPath) + .EnvironmentVariable("DOTNET_ROOT(x86)", fixture.BuiltDotnet.BinPath) + .Execute(); + + result.Should().Pass() + .And.HaveStdOutContaining($"The specified runtimeconfig.json [{missingRuntimeConfig}] does not exist"); + } } public class SharedTestState : SharedTestStateBase @@ -100,6 +129,7 @@ public SharedTestState() .EnsureRestored(RepoDirectories.CorehostPackages) .BuildProject(); + // [TODO] BEGIN - Remove once using .NET Core 3.0 to build tests ComHostPath = Path.Combine( ComLibraryFixture.TestProject.BuiltApp.Location, $"{ ComLibraryFixture.TestProject.AssemblyName }.comhost.dll"); @@ -118,6 +148,7 @@ public SharedTestState() } }; File.WriteAllText($"{ ComHostPath }.clsidmap", clsidMap.ToString()); + // [TODO] END - Remove once using .NET Core 3.0 to build tests } protected override void Dispose(bool disposing)