using System; using System.Reflection; namespace Amphora.UnitTests { public readonly struct BlockedCell { public readonly int X; public readonly int Y; public readonly string Blocker; public BlockedCell(int x, int y, string blocker) { this.X = x; this.Y = y; this.Blocker = blocker; } } public class BlockedCellKind : FailureKind { public static readonly BlockedCellKind Instance = new BlockedCellKind(); private BlockedCellKind() : base("Amphora.UnitTests.BlockedCell") { } protected override void Pack(in BlockedCell payload, out object reference, out long bits) { reference = payload.Blocker; bits = ((long)payload.X << 32) | (uint)payload.Y; } protected override BlockedCell Unpack(object reference, long bits) { return new BlockedCell(x: (int)(bits >> 32), y: (int)bits, blocker: (string)reference); } protected override string Describe(in BlockedCell payload, object context) { return $"{context} can't reach ({payload.X}, {payload.Y}) past {payload.Blocker}."; } } public class HeapRefKind : MessageFailureKind { public HeapRefKind() : base("Amphora.UnitTests.HeapRef", "Holds a heap object.") { } public override bool CanSerializeReference(object reference) { return true; } } public static class FailureTestKinds { public static readonly MessageFailureKind Unreachable = new MessageFailureKind("Amphora.UnitTests.Unreachable", "That can't be reached."); public static readonly BlockedCell Wall = new BlockedCell(x: -3, y: 7, blocker: "a wall"); } public static class FlatLayout { public static FieldInfo[] InstanceFields(Type type) { return type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); } public static bool IsFlat(FieldInfo field) { Type type = field.FieldType; return !type.IsValueType || type.IsPrimitive || type.IsEnum; } } public static class Allocations { // Assigned by measured actions, so the JIT can't drop the work as unused. public static Status StatusSink; public static StatusOr StatusOrSink; public static object ObjectSink; public static ulong IdSink; public static BlockedCell PayloadSink; public static long During(Action action) { // Once first, so JIT compilation isn't counted. action(); long before = GC.GetAllocatedBytesForCurrentThread(); for (int i = 0; i < 100; ++i) { action(); } return GC.GetAllocatedBytesForCurrentThread() - before; } } }