Adopt .NET naming and structure: CsMic.* namespaces, PascalCase projects and solution; update Coco namespace; update package id and NuGet publish target; adjust project refs and tests.
This commit is contained in:
parent
e84cce9fef
commit
0a67e6e2cc
24 changed files with 54 additions and 49 deletions
30
src/Tests/CsMic.Tests.csproj
Normal file
30
src/Tests/CsMic.Tests.csproj
Normal file
|
@ -0,0 +1,30 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
<RootNamespace>CsMic.Tests</RootNamespace>
|
||||
<AssemblyName>CsMic.Tests</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||
<PackageReference Include="NUnit" Version="4.2.2" />
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.3.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Core\CsMic.Core.csproj" />
|
||||
<ProjectReference Include="..\StandardLibrary\CsMic.StandardLibrary.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="NUnit.Framework" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
141
src/Tests/InputInterpreterTests.cs
Normal file
141
src/Tests/InputInterpreterTests.cs
Normal file
|
@ -0,0 +1,141 @@
|
|||
using System.Globalization;
|
||||
using CsMic;
|
||||
|
||||
namespace CsMic.Tests;
|
||||
|
||||
public class InputInterpreterTests
|
||||
{
|
||||
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("2.0e2", 200)]
|
||||
[TestCase("0xFF", 255)]
|
||||
[TestCase("1010b", 10)]
|
||||
[TestCase("0xFF*1010b", 2550)]
|
||||
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));
|
||||
}
|
||||
}
|
115
src/Tests/StdlibFunctionsTests.cs
Normal file
115
src/Tests/StdlibFunctionsTests.cs
Normal file
|
@ -0,0 +1,115 @@
|
|||
using CsMic;
|
||||
using CsMic.StandardLibrary;
|
||||
using NUnit.Framework;
|
||||
using CsMic.StandardLibrary.Functions;
|
||||
using System.Globalization;
|
||||
using System.Reflection.Metadata;
|
||||
|
||||
namespace CsMic.Tests;
|
||||
|
||||
public class StdlibFunctionsTests
|
||||
{
|
||||
private InputInterpreter _interp = null!;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;
|
||||
_interp = new InputInterpreter();
|
||||
Constants.Initialize(_interp);
|
||||
Functions.Initialize(_interp); ;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
[TestCase("abs(-1)", 1)]
|
||||
[TestCase("abs(0)", 0)]
|
||||
[TestCase("abs(2)", 2)]
|
||||
[TestCase("2 + abs(-1)", 3)]
|
||||
public void AbsoluteValue_Works(string expr, decimal expected)
|
||||
{
|
||||
var result = _interp.Interpret(expr);
|
||||
AssertSuccess(result, expected, _interp);
|
||||
}
|
||||
|
||||
[TestCase("abs(-3.5)", "3.5")]
|
||||
public void AbsoluteValue_Works_Decimal(string expr, string expectedStr)
|
||||
{
|
||||
var result = _interp.Interpret(expr);
|
||||
var expected = decimal.Parse(expectedStr, CultureInfo.InvariantCulture);
|
||||
AssertSuccess(result, expected, _interp);
|
||||
}
|
||||
|
||||
[TestCase("sign(5)", 1)]
|
||||
[TestCase("sign(0)", 1)]
|
||||
[TestCase("sign(-2)", -1)]
|
||||
[TestCase("2*sign(-3)", -2)]
|
||||
public void Sign_Works(string expr, decimal expected)
|
||||
{
|
||||
var result = _interp.Interpret(expr);
|
||||
AssertSuccess(result, expected, _interp);
|
||||
}
|
||||
|
||||
[TestCase("min(1,2)", 1)]
|
||||
[TestCase("min(2,1)", 1)]
|
||||
[TestCase("min(-3,4)", -3)]
|
||||
[TestCase("1 + min(3,4)", 4)]
|
||||
public void Min_Works(string expr, decimal expected)
|
||||
{
|
||||
var result = _interp.Interpret(expr);
|
||||
AssertSuccess(result, expected, _interp);
|
||||
}
|
||||
|
||||
[TestCase("min(2.5, 2.6)", "2.5")]
|
||||
public void Min_Works_Decimals(string expr, string expectedStr)
|
||||
{
|
||||
var result = _interp.Interpret(expr);
|
||||
var expected = decimal.Parse(expectedStr, CultureInfo.InvariantCulture);
|
||||
AssertSuccess(result, expected, _interp);
|
||||
}
|
||||
|
||||
[TestCase("max(1,2)", 2)]
|
||||
[TestCase("max(2,1)", 2)]
|
||||
[TestCase("max(-3,4)", 4)]
|
||||
[TestCase("1 + max(3,4)", 5)]
|
||||
public void Max_Works(string expr, decimal expected)
|
||||
{
|
||||
var result = _interp.Interpret(expr);
|
||||
AssertSuccess(result, expected, _interp);
|
||||
}
|
||||
|
||||
[TestCase("max(2.5, 2.6)", "2.6")]
|
||||
public void Max_Works_Decimals(string expr, string expectedStr)
|
||||
{
|
||||
var result = _interp.Interpret(expr);
|
||||
var expected = decimal.Parse(expectedStr, CultureInfo.InvariantCulture);
|
||||
AssertSuccess(result, expected, _interp);
|
||||
}
|
||||
|
||||
[TestCase("pi", "3.1415926535897931")]
|
||||
[TestCase("e", "2.7182818284590451")]
|
||||
[TestCase("tau", "6.2831853071795862")]
|
||||
[TestCase("phi", "1.6180339887498948")]
|
||||
[TestCase("goldenratio", "1.6180339887498948")]
|
||||
[TestCase("eurler", "0.5772156649015329")]
|
||||
[TestCase("omega", "0.5671432904097839")]
|
||||
public void Constants_AreAvailable(string expr, string expectedStr)
|
||||
{
|
||||
var result = _interp.Interpret(expr);
|
||||
var expected = decimal.Parse(expectedStr, CultureInfo.InvariantCulture);
|
||||
AssertSuccess(result, expected, _interp);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Constants_CanBeUsedInArithmetic()
|
||||
{
|
||||
AssertSuccess(_interp.Interpret("2*pi"), 6.2831853071795862m, _interp);
|
||||
AssertSuccess(_interp.Interpret("pi + e"), 5.8598744820488382m, _interp);
|
||||
AssertSuccess(_interp.Interpret("tau / pi"), 2m, _interp);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue