Add testing utilities

These are pretty rudimentary and I'd like to expand them, but I don't know that I'll need them for future days, so I'll solve that problem if I need to later.
This commit is contained in:
2021-12-18 16:21:07 -06:00
parent fd0fd238f7
commit fd1a93fa10
2 changed files with 96 additions and 82 deletions

124
src/18.cs
View File

@ -95,20 +95,26 @@ internal class Day18 : Day
} }
} }
public static bool testing;
[Conditional("DEBUG")] [Conditional("DEBUG")]
private static void DoTests() private static void DoTests()
{ {
testing = true;
DoExplodeTests(); DoExplodeTests();
DoSplitTests(); DoSplitTests();
DoMagnitudeTests(); DoMagnitudeTests();
DoAddTests(); DoAddTests();
DoReduceTests(); DoReduceTests();
DoPart1Tests(); DoPart1Tests();
testing = false;
} }
private static void DoExplodeTests() private static void DoExplodeTests()
{ {
Logger.Log("<underline>test: explode<r>"); Util.StartTestSet("explode");
var tests = new List<string>() var tests = new List<string>()
{ {
"[[[[[9,8],1],2],3],4]", "[[[[[9,8],1],2],3],4]",
@ -134,15 +140,13 @@ internal class Day18 : Day
for (int i = 0; i < tests.Count; i++) for (int i = 0; i < tests.Count; i++)
{ {
Logger.Log($"<magenta>1.{(i + 1)}<r>"); Util.StartTest($"1.{(i + 1)}");
SFNum test = ParseSFNum(tests[i]); SFNum test = ParseSFNum(tests[i]);
SFNum result = ParseSFNum(exploded[i]); SFNum result = ParseSFNum(exploded[i]);
var didExplode = CheckExplodes(test); var didExplode = CheckExplodes(test);
if (!didExplode || test.ToString() != result.ToString())
{ Util.TestCondition(() => didExplode && test.ToString() == result.ToString());
throw new Exception();
}
Logger.Log("<green>✓<r>");
} }
var twoStepTests = new List<string>() var twoStepTests = new List<string>()
@ -156,26 +160,19 @@ internal class Day18 : Day
for (int i = 0; i < twoStepTests.Count; i++) for (int i = 0; i < twoStepTests.Count; i++)
{ {
Logger.Log($"<magenta>2.{(i + 1)}<r>"); Util.StartTest($"2.{(i + 1)}");
SFNum test = ParseSFNum(twoStepTests[i]); SFNum test = ParseSFNum(twoStepTests[i]);
SFNum result = ParseSFNum(twoStepExploded[i]); SFNum result = ParseSFNum(twoStepExploded[i]);
var didExplode = CheckExplodes(test); var didExplode = CheckExplodes(test);
if (!didExplode) Util.TestCondition(() => didExplode, false);
{
throw new Exception();
}
didExplode = CheckExplodes(test); didExplode = CheckExplodes(test);
if (!didExplode || test.ToString() != result.ToString()) Util.TestCondition(() => didExplode || test.ToString() != result.ToString());
{
throw new Exception();
}
Logger.Log("<green>✓<r>");
} }
} }
private static void DoSplitTests() private static void DoSplitTests()
{ {
Logger.Log("<underline>test: split<r>"); Util.StartTestSet("split");
var tests = new List<string>() var tests = new List<string>()
{ {
"[[[[0,7],4],[15,[0,13]]],[1,1]]", "[[[[0,7],4],[15,[0,13]]],[1,1]]",
@ -191,22 +188,17 @@ internal class Day18 : Day
for (int i = 0; i < tests.Count; i++) for (int i = 0; i < tests.Count; i++)
{ {
Logger.Log($"<magenta>{(i + 1)}<r>"); Util.StartTest($"{(i + 1)}");
SFNum test = ParseSFNum(tests[i]); SFNum test = ParseSFNum(tests[i]);
SFNum result = ParseSFNum(split[i]); SFNum result = ParseSFNum(split[i]);
var didSplit = CheckSplits(test); var didSplit = CheckSplits(test);
if (!didSplit || test.ToString() != result.ToString()) Util.TestCondition(() => didSplit && test.ToString() == result.ToString());
{
throw new Exception();
}
// todo: add tests verifying owners are correct
Logger.Log("<green>✓<r>");
} }
} }
private static void DoMagnitudeTests() private static void DoMagnitudeTests()
{ {
Logger.Log("<underline>test: magnitude<r>"); Util.StartTestSet("magnitude");
var tests = new List<string>() var tests = new List<string>()
{ {
"[9,1]", "[9,1]",
@ -234,20 +226,16 @@ internal class Day18 : Day
for (int i = 0; i < tests.Count; i++) for (int i = 0; i < tests.Count; i++)
{ {
Logger.Log($"<magenta>{(i + 1)}<r>"); Util.StartTest($"{(i + 1)}");
SFNum test = ParseSFNum(tests[i]); SFNum test = ParseSFNum(tests[i]);
var magnitude = test.Magnitude; var magnitude = test.Magnitude;
if (magnitude != magnitudes[i]) Util.TestCondition(() => magnitude == magnitudes[i]);
{
throw new Exception();
}
Logger.Log("<green>✓<r>");
} }
} }
private static void DoAddTests() private static void DoAddTests()
{ {
Logger.Log("<underline>test: add<r>"); Util.StartTest("add");
var tests = new List<List<string>>() var tests = new List<List<string>>()
{ {
new() new()
@ -263,28 +251,21 @@ internal class Day18 : Day
for (int i = 0; i < tests.Count; i++) for (int i = 0; i < tests.Count; i++)
{ {
Logger.Log($"<magenta>{(i + 1)}<r>"); Util.StartTest($"{(i + 1)}");
SFNum test = ParseSFNum(tests[i][0]); SFNum test = ParseSFNum(tests[i][0]);
for (int j = 1; j < tests[i].Count; j++) for (int j = 1; j < tests[i].Count; j++)
{ {
test = Add(test, ParseSFNum(tests[i][j])); test = Add(test, ParseSFNum(tests[i][j]));
} }
SFNum result = ParseSFNum(results[i]); SFNum result = ParseSFNum(results[i]);
if (test.ToString() != result.ToString()) Util.TestCondition(() => test.ToString() == result.ToString(), false);
{ Util.TestCondition(() => result.leftNum!.owner == result && result.rightNum!.owner == result);
throw new Exception();
}
if (result.leftNum!.owner != result || result.rightNum!.owner != result)
{
throw new Exception();
}
Logger.Log("<green>✓<r>");
} }
} }
private static void DoReduceTests() private static void DoReduceTests()
{ {
Logger.Log("<underline>test: reduce<r>"); Util.StartTestSet("reduce");
var tests = new List<string>() var tests = new List<string>()
{ {
"[[[[[4,3],4],4],[7,[[8,4],9]]],[1,1]]", "[[[[[4,3],4],4],[7,[[8,4],9]]],[1,1]]",
@ -296,21 +277,17 @@ internal class Day18 : Day
for (int i = 0; i < tests.Count; i++) for (int i = 0; i < tests.Count; i++)
{ {
Logger.Log($"<magenta>{(i + 1)}<r>"); Util.StartTest($"{(i + 1)}");
SFNum test = ParseSFNum(tests[i]); SFNum test = ParseSFNum(tests[i]);
SFNum result = ParseSFNum(results[i]); SFNum result = ParseSFNum(results[i]);
Reduce(test); Reduce(test);
if (test.ToString() != result.ToString()) Util.TestCondition(() => test.ToString() == result.ToString());
{
throw new Exception();
}
Logger.Log("<green>✓<r>");
} }
} }
private static void DoPart1Tests() private static void DoPart1Tests()
{ {
Logger.Log("<underline>test: add+reduce<r>"); Util.StartTestSet("add+reduce");
var vals = new List<List<SFNum>>() var vals = new List<List<SFNum>>()
{ {
new() new()
@ -407,7 +384,7 @@ internal class Day18 : Day
for (int i = 0; i < vals.Count; i++) for (int i = 0; i < vals.Count; i++)
{ {
Logger.Log($"<magenta>{(i + 1)}<r>"); Util.StartTest($"{(i + 1)}");
SFNum curr = vals[i][0]; SFNum curr = vals[i][0];
for (int j = 1; j < vals[i].Count; j++) for (int j = 1; j < vals[i].Count; j++)
{ {
@ -415,12 +392,7 @@ internal class Day18 : Day
Reduce(curr); Reduce(curr);
} }
if (curr.ToString() != results[i].ToString()) Util.TestCondition(() => curr.ToString() == results[i].ToString());
{
Logger.Log($" expected: {results[i]}");
throw new Exception();
}
Logger.Log("<green>✓<r>");
} }
} }
@ -639,10 +611,11 @@ internal class Day18 : Day
private static void Explode(SFNum num) private static void Explode(SFNum num)
{ {
#if DEBUG if (testing)
{
num.exploding = true; num.exploding = true;
Logger.Log($"exploding: {num.Root}"); Logger.Log($"exploding: {num.Root}");
#endif }
var curr = num; var curr = num;
var last = num; var last = num;
@ -719,9 +692,10 @@ internal class Day18 : Day
num.owner.right = 0; num.owner.right = 0;
} }
#if DEBUG if (testing)
{
Logger.Log($" -> {num.Root}"); Logger.Log($" -> {num.Root}");
#endif }
num.owner = null; num.owner = null;
} }
@ -755,11 +729,13 @@ internal class Day18 : Day
private static bool Split(SFNum num) private static bool Split(SFNum num)
{ {
if (num.left != null && num.left >= 10) if (num.left != null && num.left >= 10)
{
if (testing)
{ {
num.splittingLeft = true; num.splittingLeft = true;
#if DEBUG
Logger.Log($"splitting: {num.Root}"); Logger.Log($"splitting: {num.Root}");
#endif }
num.leftNum = new() num.leftNum = new()
{ {
left = (int)Math.Floor((int)num.left / 2.0), left = (int)Math.Floor((int)num.left / 2.0),
@ -767,19 +743,24 @@ internal class Day18 : Day
owner = num, owner = num,
}; };
num.left = null; num.left = null;
if (testing)
{
num.splittingLeft = false; num.splittingLeft = false;
#if DEBUG
Logger.Log($" -> {num.Root}"); Logger.Log($" -> {num.Root}");
#endif }
return true; return true;
} }
if (num.right != null && num.right >= 10) if (num.right != null && num.right >= 10)
{
if (testing)
{ {
num.splittingRight = true; num.splittingRight = true;
#if DEBUG
Logger.Log($"splitting: {num.Root}"); Logger.Log($"splitting: {num.Root}");
#endif }
num.rightNum = new() num.rightNum = new()
{ {
left = (int)Math.Floor((int)num.right / 2.0), left = (int)Math.Floor((int)num.right / 2.0),
@ -787,10 +768,13 @@ internal class Day18 : Day
owner = num, owner = num,
}; };
num.right = null; num.right = null;
if (testing)
{
num.splittingRight = false; num.splittingRight = false;
#if DEBUG
Logger.Log($" -> {num.Root}"); Logger.Log($" -> {num.Root}");
#endif }
return true; return true;
} }

View File

@ -1,4 +1,5 @@
using System.Text; using System.Diagnostics;
using System.Text;
namespace aoc2021; namespace aoc2021;
@ -30,4 +31,33 @@ internal static class Util
return File.ReadAllLines(filename); return File.ReadAllLines(filename);
} }
internal static void StartTestSet(string name)
{
Logger.Log($"<underline>test: {name}<r>");
}
internal static void StartTest(string label)
{
Logger.Log($"<magenta>{label}<r>");
}
internal static void TestCondition(Func<bool> a, bool printResult = true)
{
if (a?.Invoke() == false)
{
Debug.Assert(false);
if (printResult)
{
Logger.Log("<red>x<r>");
}
}
else
{
if (printResult)
{
Logger.Log("<green>✓<r>");
}
}
}
} }