From 00d680375ae6af19c8b7c2f431170f122f45a9d5 Mon Sep 17 00:00:00 2001 From: Matt Edmondson Date: Sun, 31 May 2026 12:55:56 +1000 Subject: [PATCH] Exclude native C ABI shim from code coverage to fix CI test crash ForceDirectedLayout.Tests crashed the Microsoft dynamic code-coverage collector during teardown (System.Exception: Pipe was disconnected, process exit 0xE0434352, test-platform exit 7) on the .NET 10 CI runner. It is the only test assembly referencing code with [UnmanagedCallersOnly] native entry points (NativeExports); the coverage engine takes that path and crashes per the .NET 10 dynamic-native-instrumentation behavior change. Mark NativeExports with [ExcludeFromCodeCoverage] - those boundary methods are reachable only via native function pointers and cannot be exercised by managed tests anyway, so excluding them keeps the coverage instrumenter away from them while preserving coverage for the rest of the engine. (Disabling the coverage extension for the project is not viable: CI passes --coverage to every test app, so a project without the extension fails with an unknown-option error.) Also suppress two new SonarAnalyzer warnings with justifications: S1244 on Vec2D ==/Equals (exact equality is intentional for a blittable value type; a tolerance would break the Equals/GetHashCode contract) and S6640 on the unsafe NativeExports class (unsafe is required for C ABI pointer marshalling). --- ForceDirectedLayout/NativeExports.cs | 9 +++++++++ ForceDirectedLayout/Vec2D.cs | 3 +++ 2 files changed, 12 insertions(+) diff --git a/ForceDirectedLayout/NativeExports.cs b/ForceDirectedLayout/NativeExports.cs index 7751739..aadb12a 100644 --- a/ForceDirectedLayout/NativeExports.cs +++ b/ForceDirectedLayout/NativeExports.cs @@ -5,6 +5,7 @@ namespace ktsu.ForceDirectedLayout; using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -43,6 +44,14 @@ public static class LayoutResult /// /// All buffer parameters are caller-owned. The library writes into the buffer but never retains a pointer past the call return. /// +// Excluded from code coverage: these [UnmanagedCallersOnly] entry points are reachable only +// through native function pointers, never from managed code, so managed tests cannot exercise +// them. Excluding the type also keeps the coverage instrumenter away from UnmanagedCallersOnly +// method bodies - instrumenting them crashes the dynamic code-coverage collector on .NET 10 CI +// runners (the interprocess collector dies with "Pipe was disconnected" during report generation), +// which is what failed the ForceDirectedLayout.Tests run. +[ExcludeFromCodeCoverage(Justification = "C ABI boundary shim invoked only via native function pointers; uncoverable by managed tests and crashes the .NET 10 dynamic coverage collector when instrumented.")] +[SuppressMessage("Major Code Smell", "S6640:Make sure that using \"unsafe\" is safe here.", Justification = "The C ABI surface marshals raw caller-owned pointers across the native boundary; every pointer argument is null- and range-checked before use and never retained past the call.")] public static unsafe class NativeExports { [ThreadStatic] diff --git a/ForceDirectedLayout/Vec2D.cs b/ForceDirectedLayout/Vec2D.cs index 44eeda3..beb1cf2 100644 --- a/ForceDirectedLayout/Vec2D.cs +++ b/ForceDirectedLayout/Vec2D.cs @@ -5,6 +5,7 @@ namespace ktsu.ForceDirectedLayout; using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -73,12 +74,14 @@ public static Vec2D Zero public static Vec2D operator -(Vec2D v) => new(-v.X, -v.Y); /// + [SuppressMessage("Major Code Smell", "S1244:Floating point numbers should not be tested for equality", Justification = "Value-equality for a blittable vector requires exact component comparison; a tolerance would break the Equals/GetHashCode contract. Use a range check at call sites that need approximate equality.")] public static bool operator ==(Vec2D a, Vec2D b) => a.X == b.X && a.Y == b.Y; /// public static bool operator !=(Vec2D a, Vec2D b) => !(a == b); /// + [SuppressMessage("Major Code Smell", "S1244:Floating point numbers should not be tested for equality", Justification = "Value-equality for a blittable vector requires exact component comparison; a tolerance would break the Equals/GetHashCode contract. Use a range check at call sites that need approximate equality.")] public readonly bool Equals(Vec2D other) => X == other.X && Y == other.Y; ///