tests: Add NUnit suite for InputInterpreter.Interpret covering arithmetic, comparisons, variables, := binding, arrays, soft errors, and timing

Adds InputInterpreterTests with:

- Arithmetic cases including precedence, hex/binary, exponent.
- Comparisons yielding numeric booleans.
- Variable assignment (::) and persistence across calls; unknown variable soft error.
- Expression binding (:=) re-evaluated at use-time; invalid expression soft error.
- Array assignment (->) and indexing; out-of-range and index-expression scenarios.
- String literal used as expression soft error.
- Divide-by-zero soft error (no thrown exception).
- LastExecutionTime measured across calls.

Each test asserts both the return value and NumericValue/StringValue for consistency.
This commit is contained in:
Jordan Wages 2025-08-19 04:52:37 -05:00
commit 648bd3bad0

View file

@ -1,16 +1,139 @@
namespace tests using System.Globalization;
{ using csmic;
public class InputInterpreterTests
{
[SetUp]
public void Setup()
{
}
[Test] namespace tests;
public void Test1()
{ public class InputInterpreterTests
Assert.Pass(); {
} private InputInterpreter _interp = null!;
[SetUp]
public void Setup()
{
CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;
_interp = new InputInterpreter();
}
private static void AssertSuccess(decimal result, decimal expected, InputInterpreter interp)
{
Assert.That(result, Is.EqualTo(expected));
Assert.That(interp.NumericValue, Is.EqualTo(expected));
Assert.That(interp.StringValue, Is.EqualTo(string.Empty));
}
private static void AssertSoftError(decimal result, InputInterpreter interp)
{
Assert.That(result, Is.EqualTo(0m));
Assert.That(interp.NumericValue, Is.EqualTo(0m));
Assert.That(string.IsNullOrEmpty(interp.StringValue), Is.False);
}
[TestCase("2", 2)]
[TestCase("-5", -5)]
[TestCase("2+3*4", 14)]
[TestCase("(2+3)*4", 20)]
[TestCase("8/2", 4)]
[TestCase("7%4", 3)]
[TestCase("2^3", 8)]
[TestCase("1e2", 100)]
[TestCase("0xFF", 255)]
[TestCase("1010b", 10)]
public void Arithmetic_Works(string expr, decimal expected)
{
var result = _interp.Interpret(expr);
AssertSuccess(result, expected, _interp);
}
[TestCase("2==2", 1)]
[TestCase("2<3", 1)]
[TestCase("3<2", 0)]
[TestCase("2>=2", 1)]
[TestCase("2<=1", 0)]
public void Comparisons_YieldBooleanAsNumeric(string expr, decimal expected)
{
var result = _interp.Interpret(expr);
AssertSuccess(result, expected, _interp);
}
[Test]
public void Variables_AssignAndUse_PersistAcrossCalls()
{
AssertSuccess(_interp.Interpret("x :: 2"), 2, _interp);
AssertSuccess(_interp.Interpret("x+1"), 3, _interp);
AssertSuccess(_interp.Interpret("x :: 3"), 3, _interp);
AssertSuccess(_interp.Interpret("x+1"), 4, _interp);
}
[Test]
public void UnknownVariable_ProducesSoftError()
{
var result = _interp.Interpret("nope + 1");
AssertSoftError(result, _interp);
}
[Test]
public void ExpressionBinding_EvaluatesAtUseTime()
{
AssertSuccess(_interp.Interpret("num :: 2"), 2, _interp);
AssertSuccess(_interp.Interpret("exp := 1 + num"), 0, _interp); // assignment returns 0
AssertSuccess(_interp.Interpret("exp"), 3, _interp);
AssertSuccess(_interp.Interpret("num :: 3"), 3, _interp);
AssertSuccess(_interp.Interpret("exp"), 4, _interp);
}
[Test]
public void ExpressionBinding_InvalidExpression_ProducesSoftError()
{
_interp.Interpret("exp := bad + 1");
var result = _interp.Interpret("exp");
AssertSoftError(result, _interp);
}
[Test]
public void Arrays_AssignAndIndex()
{
AssertSuccess(_interp.Interpret("arr -> [1,2,3]"), 0, _interp); // array assignment returns 0
AssertSuccess(_interp.Interpret("arr[0]"), 1, _interp);
AssertSuccess(_interp.Interpret("arr[2]"), 3, _interp);
}
[Test]
public void Arrays_OutOfRange_ProducesSoftError()
{
_interp.Interpret("arr -> [1,2,3]");
var result = _interp.Interpret("arr[3]");
AssertSoftError(result, _interp);
}
[Test]
public void Arrays_IndexExpression_Works()
{
_interp.Interpret("arr -> [1,2,3]");
_interp.Interpret("i :: 1");
AssertSuccess(_interp.Interpret("arr[i+1]"), 3, _interp);
}
[Test]
public void StringLiteral_Alone_IsError()
{
var result = _interp.Interpret("\"hi\"");
AssertSoftError(result, _interp);
}
[Test]
public void DivideByZero_ProducesSoftError()
{
var result = _interp.Interpret("1/0");
AssertSoftError(result, _interp);
}
[Test]
public void LastExecutionTime_IsMeasured()
{
_interp.Interpret("2+2");
Assert.That(_interp.LastExecutionTime, Is.GreaterThanOrEqualTo(TimeSpan.Zero));
_interp.Interpret("3+3");
Assert.That(_interp.LastExecutionTime, Is.GreaterThanOrEqualTo(TimeSpan.Zero));
} }
} }