Skip to content

Commit

Permalink
Add automated tester
Browse files Browse the repository at this point in the history
  • Loading branch information
WNP78 committed Oct 18, 2022
1 parent c70f867 commit 456babc
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 0 deletions.
31 changes: 31 additions & 0 deletions Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@
case "help":
ShowHelp();
return;
case "test":
if (args.Length != 3)
{
Console.WriteLine("test requires two arguments");
}

RunTest(args[1], args[2]);
return;
default:
Console.WriteLine($"Unknown command {command}");
return;
Expand Down Expand Up @@ -89,6 +97,29 @@ void Run(string arg)
Console.WriteLine($"Finished in {steps} steps");
}

void RunTest(string test, string file)
{
Interpreter.InterpreterState state;

try
{
state = Interpreter.LoadFromAssembler(Assembler.Assemble(new FileInfo(file)));
}
catch (Exception e)
{
Console.WriteLine($"Assembly failed: {e}");
return;
}

if (!Test.Tests.TryGetValue(test, out var testFunc))
{
Console.WriteLine($"No such test {test}");
return;
}

testFunc(state);
}

void Debug(string arg)
{
Interpreter.InterpreterState state;
Expand Down
88 changes: 88 additions & 0 deletions Tester.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
namespace NetLMC;
using System.Reflection;

public static class Tester
{
public enum Result
{
PASS,
FAIL,
CRASH,
};

public struct ExpectedAction
{
public bool isInput;
public int value;
}

[System.Serializable]
private class TesterException : System.Exception
{
public TesterException() { }
public TesterException(string message) : base(message) { }
public TesterException(string message, System.Exception inner) : base(message, inner) { }
protected TesterException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}

private class ValidatorInterface : IInterface
{
private readonly IEnumerator<ExpectedAction> actions;

public ValidatorInterface(IEnumerable<ExpectedAction> action)
{
this.actions = action.GetEnumerator();
}

public ValidatorInterface(IEnumerator<ExpectedAction> action)
{
this.actions = action;
}

public int Input()
{
if (!actions.MoveNext() || !actions.Current.isInput) { throw new TesterException("Unexpected input request."); }

return actions.Current.value;
}

public void Output(int v)
{
if (!actions.MoveNext() || actions.Current.isInput) { throw new TesterException("Unexpected output"); }

if (actions.Current.value != v) { throw new TesterException($"Output {v} != expected {actions.Current.value}"); }
}

public void DebugLog(string _) { }

public void CheckDone()
{
if (actions.MoveNext()) { throw new TesterException("Unexpected end of program."); }
}
}

public static Result RunTest(IEnumerator<ExpectedAction> actions, ref Interpreter.InterpreterState state)
{
var iface = new ValidatorInterface(actions);
try
{
Interpreter.Run(ref state, iface);
iface.CheckDone();
}
catch (TesterException)
{
return Result.FAIL;
}
catch
{
return Result.CRASH;
}

return Result.PASS;
}

public static ExpectedAction In(int v) => new() { isInput = true, value = v };
public static ExpectedAction Out(int v) => new() { isInput = false, value = v };
}
66 changes: 66 additions & 0 deletions Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
namespace NetLMC;

public static class Test
{
public static readonly Dictionary<string, Action<Interpreter.InterpreterState>> Tests = new()
{
{ "Polynomial", TestAllPolynomials },
};

public static IEnumerator<Tester.ExpectedAction> Polynomial(int a, int b, int c, int x)
{
yield return Tester.In(a);
yield return Tester.In(b);
yield return Tester.In(c);
yield return Tester.In(x);
yield return Tester.Out(Math.Clamp(a + b*x + c*x*x, 0, 999));
}

public static void TestAllPolynomials(Interpreter.InterpreterState inState)
{
long totalPass = 0, totalFail = 0, totalCrash = 0;
object ioLock = new();

Parallel.For(0, 1000, (int x, ParallelLoopState parallelState) =>
{
long total = totalPass + totalFail + totalCrash;
lock (ioLock)
{
Console.WriteLine($"Done: {total}, Pass: {totalPass}, Remain: {1_000_000_000_000 - total}");
}
long numPass = 0, numFail = 0, numCrash = 0;
var state = inState;
for (int a = 0; a < 1000; a++)
{
for (int b = 0; b < 1000; b++)
{
for (int c = 0; c < 1000; c++)
{
state.pc = 0;
state.calc = 0;
var res = Tester.RunTest(Polynomial(a, b, c, x), ref state);
switch (res)
{
case Tester.Result.PASS:
numPass++;
break;
case Tester.Result.FAIL:
numFail++;
break;
case Tester.Result.CRASH:
numCrash++;
break;
}
}
}
}
Interlocked.Add(ref totalPass, numPass);
Interlocked.Add(ref totalFail, numFail);
Interlocked.Add(ref totalCrash, numCrash);
});

Console.WriteLine($"Pass: {totalPass}, Fail: {totalFail}, Crash: {totalCrash}");
}
}

0 comments on commit 456babc

Please sign in to comment.