From 6afc174a4f0b3b7c21df6d24e1b6a690a35e4100 Mon Sep 17 00:00:00 2001 From: Alessandro De Blasis Date: Thu, 26 Mar 2026 11:33:11 +0100 Subject: [PATCH] windows: remove .NET test infrastructure and CRT probe function The C# test suite and ghostty_crt_workaround_active() probe were unnecessary overhead. The DllMain workaround is harmless to keep (CRT init is ref-counted) and comments document when to remove it. test_dll_init.c remains as a standalone C reproducer. --- src/main_c.zig | 8 -- windows/Ghostty.Tests/Ghostty.Tests.csproj | 30 ------ windows/Ghostty.Tests/LibghosttyInitTests.cs | 98 -------------------- 3 files changed, 136 deletions(-) delete mode 100644 windows/Ghostty.Tests/Ghostty.Tests.csproj delete mode 100644 windows/Ghostty.Tests/LibghosttyInitTests.cs diff --git a/src/main_c.zig b/src/main_c.zig index a131de255..2f9e45b5f 100644 --- a/src/main_c.zig +++ b/src/main_c.zig @@ -64,14 +64,6 @@ pub const DllMain = if (builtin.os.tag == .windows and } }.handler else void; -// Probe export: returns 1 when the DllMain CRT workaround above is -// compiled in. The C# test suite checks for this symbol to detect when -// the workaround becomes redundant (when Zig fixes MSVC DLL CRT init). -// Remove this along with the DllMain block above. -pub export fn ghostty_crt_workaround_active() callconv(.c) c_int { - return if (builtin.os.tag == .windows and builtin.abi == .msvc) 1 else 0; -} - // Some comptime assertions that our C API depends on. comptime { // We allow tests to reference this file because we unit test diff --git a/windows/Ghostty.Tests/Ghostty.Tests.csproj b/windows/Ghostty.Tests/Ghostty.Tests.csproj deleted file mode 100644 index 632c025b9..000000000 --- a/windows/Ghostty.Tests/Ghostty.Tests.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - - net10.0 - latest - enable - enable - true - - - - - - - - - - - - - - - - diff --git a/windows/Ghostty.Tests/LibghosttyInitTests.cs b/windows/Ghostty.Tests/LibghosttyInitTests.cs deleted file mode 100644 index e57e13d55..000000000 --- a/windows/Ghostty.Tests/LibghosttyInitTests.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System.Runtime.InteropServices; - -[assembly: System.Runtime.CompilerServices.DisableRuntimeMarshalling] - -namespace Ghostty.Tests; - -/// -/// Tests that validate libghostty DLL initialization on Windows. -/// -/// Ghostty's main_c.zig declares a DllMain that calls __vcrt_initialize -/// and __acrt_initialize because Zig's _DllMainCRTStartup does not -/// initialize the MSVC C runtime for DLL targets. Without this, any C -/// library function (setlocale, glslang, oniguruma) crashes. -/// -/// See the probe test at the bottom for workaround tracking. -/// -[TestClass] -public partial class LibghosttyInitTests -{ - private const string LibName = "ghostty"; - - [StructLayout(LayoutKind.Sequential)] - private struct GhosttyInfo - { - public int BuildMode; - public nint Version; - public nuint VersionLen; - } - - [LibraryImport(LibName, EntryPoint = "ghostty_info")] - private static partial GhosttyInfo GhosttyInfoNative(); - - [LibraryImport(LibName, EntryPoint = "ghostty_crt_workaround_active")] - private static partial int GhosttyWorkaroundActive(); - - [TestMethod] - public void GhosttyInfo_Works() - { - // Baseline: ghostty_info uses only compile-time constants and - // does not depend on CRT state. This should always work. - var info = GhosttyInfoNative(); - - Assert.IsGreaterThan((nuint)0, info.VersionLen); - Assert.AreNotEqual(nint.Zero, info.Version); - } - - // NOTE: ghostty_init is validated by the C reproducer (test_dll_init.c) - // rather than a C# test because ghostty_init initializes global state - // (glslang, oniguruma, allocators) that crashes during test host - // teardown when the DLL is unloaded. The C reproducer handles this by - // exiting without FreeLibrary. The DLL unload ordering issue is - // separate from the CRT init fix. - - /// - /// PROBE TEST: Detects when our DllMain CRT workaround in main_c.zig - /// is removed, which should happen when Zig fixes _DllMainCRTStartup - /// for MSVC DLL targets. - /// - /// HOW IT WORKS: - /// ghostty_crt_workaround_active() returns 1 when the workaround is - /// compiled in (Windows MSVC), 0 on other platforms. This test - /// asserts that it returns 1. When it returns 0, the workaround was - /// removed. - /// - /// WHEN THIS TEST FAILS: - /// Someone removed the DllMain workaround from main_c.zig. - /// This is the expected outcome when Zig fixes the issue. - /// - /// Step 1: Run test_dll_init.c (the C reproducer) WITHOUT the - /// DllMain workaround. If ghostty_init returns 0, Zig - /// fixed it. Delete the DllMain block in main_c.zig, - /// ghostty_crt_workaround_active(), and this probe test. - /// - /// Step 2: If ghostty_init still crashes without the workaround, - /// restore the DllMain block in main_c.zig. - /// - /// Step 3: To unblock CI while investigating, skip this test: - /// dotnet test --filter "FullyQualifiedName!=Ghostty.Tests.LibghosttyInitTests.DllMainWorkaround_IsStillActive" - /// - /// UPSTREAM TRACKING (as of 2026-03-26): - /// No Zig issue tracks this exact gap. - /// Closest: Codeberg ziglang/zig #30936 (reimplement crt0 code). - /// Related GitHub issues: 7065, 11285, 19672 (link-time, not runtime). - /// - [TestMethod] - public void DllMainWorkaround_IsStillActive() - { - var active = GhosttyWorkaroundActive(); - Assert.AreEqual(1, active, - "ghostty_crt_workaround_active() returned 0. " + - "The DllMain CRT workaround in main_c.zig was removed or disabled. " + - "Run test_dll_init.c without the workaround to check if Zig fixed " + - "the issue. If ghostty_init works, delete the DllMain and this test. " + - "If it crashes, restore the DllMain. " + - "To skip this test: dotnet test --filter " + - "\"FullyQualifiedName!=Ghostty.Tests.LibghosttyInitTests.DllMainWorkaround_IsStillActive\""); - } -}