From 15932fb9aae10d656b6b798742c828a06bc0b524 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Tue, 10 May 2022 00:59:36 +0200 Subject: [PATCH] DebugTools.Assert(bool, string) does not allocate if string is a format string anymore. --- Robust.Shared/Utility/DebugTools.cs | 42 +++++++++++++++++++ .../Shared/Utility/DebugTools_Test.cs | 26 ++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 Robust.UnitTesting/Shared/Utility/DebugTools_Test.cs diff --git a/Robust.Shared/Utility/DebugTools.cs b/Robust.Shared/Utility/DebugTools.cs index d6af16480..1297ae141 100644 --- a/Robust.Shared/Utility/DebugTools.cs +++ b/Robust.Shared/Utility/DebugTools.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Runtime.CompilerServices; using JetBrains.Annotations; namespace Robust.Shared.Utility @@ -46,6 +47,21 @@ namespace Robust.Shared.Utility throw new DebugAssertException(message); } + /// + /// An assertion that will an exception if the + /// is not true. + /// + /// Condition that must be true. + /// Exception message. + [Conditional("DEBUG")] + [AssertionMethod] + public static void Assert([AssertionCondition(AssertionConditionType.IS_TRUE)] + bool condition, [InterpolatedStringHandlerArgument("condition")] ref AssertInterpolatedStringHandler message) + { + if (!condition) + throw new DebugAssertException(message.ToStringAndClear()); + } + /// /// An assertion that will an exception if the /// is . @@ -86,6 +102,32 @@ namespace Robust.Shared.Utility { Debugger.Break(); } + + [InterpolatedStringHandler] + public ref struct AssertInterpolatedStringHandler + { + private DefaultInterpolatedStringHandler _handler; + + public AssertInterpolatedStringHandler(int literalLength, int formattedCount, bool condition, out bool shouldAppend) + { + if (condition) + { + shouldAppend = false; + _handler = default; + } + else + { + shouldAppend = true; + _handler = new DefaultInterpolatedStringHandler(literalLength, formattedCount); + } + } + + public string ToStringAndClear() => _handler.ToStringAndClear(); + public override string ToString() => _handler.ToString(); + public void AppendLiteral(string value) => _handler.AppendLiteral(value); + public void AppendFormatted(T value) => _handler.AppendFormatted(value); + public void AppendFormatted(T value, string? format) => _handler.AppendFormatted(value, format); + } } [Virtual] diff --git a/Robust.UnitTesting/Shared/Utility/DebugTools_Test.cs b/Robust.UnitTesting/Shared/Utility/DebugTools_Test.cs new file mode 100644 index 000000000..cade6592a --- /dev/null +++ b/Robust.UnitTesting/Shared/Utility/DebugTools_Test.cs @@ -0,0 +1,26 @@ +using System; +using System.Diagnostics; +using NUnit.Framework; +using Robust.Shared.Utility; + +namespace Robust.UnitTesting.Shared.Utility; + +[TestFixture] +[Parallelizable(ParallelScope.All)] +[TestOf(typeof(DebugTools))] +public sealed class DebugTools_Test +{ + [Test] + [TestCase(true, 5)] + [Conditional("DEBUG")] + public void TestAssertFormatNoAlloc(bool check, int val) + { + var allocA = GC.GetAllocatedBytesForCurrentThread(); + + DebugTools.Assert(check, $"Oops: {val}"); + + var allocB = GC.GetAllocatedBytesForCurrentThread(); + + Assert.That(allocB, Is.EqualTo(allocA)); + } +}