using Azimuth; using System; using System.Collections.Generic; using UnitTestSharp; namespace Annulus.UnitTests { public class HexSegmentTests : TestFixture { public static readonly HexLayout PointyLayout = new HexLayout(HexOrientation.PointyTop, size: 10, Vector.Zero); public static List Walk(HexLayout layout, Vector from, Vector to) { var returnMe = new List(); foreach (HexIndex hex in new HexSegment(layout, from, to)) { returnMe.Add(hex); } return returnMe; } public class CtorTests : TestFixture { public void ANotANumberPoint_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new HexSegment(PointyLayout, new Vector(double.NaN, 0), Vector.Zero); } public void AnInfinitePoint_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new HexSegment(PointyLayout, Vector.Zero, new Vector(0, double.PositiveInfinity)); } } public class EnumeratorTests : TestFixture { public void WithinOneHex_YieldsThatHexOnce() { var hex = new HexIndex(2, 1); Vector center = PointyLayout.Center(hex); CheckEqual(new[] { hex }, Walk(PointyLayout, center, center + new Vector(1, 1))); } public void AtOnePoint_YieldsTheHexUnderIt() { var hex = new HexIndex(-3, 4); Vector center = PointyLayout.Center(hex); CheckEqual(new[] { hex }, Walk(PointyLayout, center, center)); } public void ThroughTheCentersOfHexesInARow_YieldsEachInTurn() { var expected = new[] { new HexIndex(0, 0), new HexIndex(1, 0), new HexIndex(2, 0), new HexIndex(3, 0) }; CheckEqual(expected, Walk(PointyLayout, PointyLayout.Center(expected[0]), PointyLayout.Center(expected[3]))); } public void ThroughTheCentersAlongEachDirection_YieldsEachHexInTurn() { var layouts = new[] { new HexLayout(HexOrientation.PointyTop, size: 1.5, origin: new Vector(4, -8)), new HexLayout(HexOrientation.FlatTop, size: 2.5, origin: new Vector(-3, 6)), }; foreach (HexLayout layout in layouts) { var start = new HexIndex(-2, 3); for (int direction = 0; direction < HexDirections.Count; ++direction) { HexIndex first = HexLayoutTests.NeighborOf(layout, start, direction); HexIndex second = HexLayoutTests.NeighborOf(layout, first, direction); HexIndex third = HexLayoutTests.NeighborOf(layout, second, direction); CheckEqual(new[] { start, first, second, third }, Walk(layout, layout.Center(start), layout.Center(third))); } } } public void AlongSlantedEdges_AlternatesBetweenTwoRows() { Vector low = new Vector(0, 7.5); Vector high = PointyLayout.Center(new HexIndex(2, 0)) + new Vector(0, 7.5); var expected = new[] { new HexIndex(0, 0), new HexIndex(0, 1), new HexIndex(1, 0), new HexIndex(1, 1), new HexIndex(2, 0), }; CheckEqual(expected, Walk(PointyLayout, low, high)); } public void AlongSlantedEdges_ReversingTheEndsReversesTheHexes() { Vector low = new Vector(0, 7.5); Vector high = PointyLayout.Center(new HexIndex(2, 0)) + new Vector(0, 7.5); List forward = Walk(PointyLayout, low, high); forward.Reverse(); CheckEqual(forward, Walk(PointyLayout, high, low)); } public void ThroughTwoCornersAlongAnEdge_StillWalksNeighborToNeighbor() { var start = new HexIndex(0, 0); var end = new HexIndex(1, 1); List hexes = Walk(PointyLayout, PointyLayout.Center(start), PointyLayout.Center(end)); CheckEqual(start, hexes[0]); CheckEqual(end, hexes[hexes.Count - 1]); for (int i = 1; i < hexes.Count; ++i) { CheckEqual(1, hexes[i - 1].DistanceTo(hexes[i])); } } public void ForeachAllocatesNothing() { Vector from = PointyLayout.Center(new HexIndex(0, 0)) + new Vector(0, 7.5); Vector to = PointyLayout.Center(new HexIndex(9, -4)) + new Vector(3, 2); int count = 0; foreach (HexIndex hex in PointyLayout.HexesAlong(from, to)) { count += hex.Q; } long before = GC.GetAllocatedBytesForCurrentThread(); for (int i = 0; i < 100; ++i) { foreach (HexIndex hex in PointyLayout.HexesAlong(from, to)) { count += hex.Q; } } long allocated = GC.GetAllocatedBytesForCurrentThread() - before; CheckEqual(0L, allocated); Check(count != 0); } } } }