diff --git a/tests/Lua.Tests/BitwiseLibraryReviewTests.cs b/tests/Lua.Tests/BitwiseLibraryTests.cs similarity index 98% rename from tests/Lua.Tests/BitwiseLibraryReviewTests.cs rename to tests/Lua.Tests/BitwiseLibraryTests.cs index caece965..9018f266 100644 --- a/tests/Lua.Tests/BitwiseLibraryReviewTests.cs +++ b/tests/Lua.Tests/BitwiseLibraryTests.cs @@ -2,7 +2,7 @@ namespace Lua.Tests; -public class BitwiseLibraryReviewTests +public class BitwiseLibraryTests { static LuaState CreateState() { diff --git a/tests/Lua.Tests/CompilerConstantBoundaryTests.cs b/tests/Lua.Tests/CompilerConstantBoundaryTests.cs new file mode 100644 index 00000000..b8a413ba --- /dev/null +++ b/tests/Lua.Tests/CompilerConstantBoundaryTests.cs @@ -0,0 +1,32 @@ +using System.Text; +using Lua.CodeAnalysis.Syntax; +using Lua.CodeAnalysis.Syntax.Nodes; +using Lua.Platforms; +using Lua.Runtime; +using Lua.Standard; + +namespace Lua.Tests; + +public class CompilerConstantBoundaryTests +{ + [Test] + public async Task ConstantBeyondBxUsesLoadKxAndRoundTrips() + { + using var state = LuaState.Create(); + var source = new StringBuilder("local x\n"); + for (var i = 0; i <= Instruction.MaxArgBx + 1; i++) + source.Append("x=").Append(i).Append('\n'); + source.Append("return x"); + var closure = state.Load(source.ToString(), "large-constants"); + Assert.That(closure.Proto.Code.ToArray().Any(i => i.OpCode == OpCode.LoadKX), Is.True); + Assert.That( + (await state.ExecuteAsync(closure))[0].Read(), + Is.EqualTo(Instruction.MaxArgBx + 1) + ); + var restored = state.Load(closure.Proto.ToBytecode(), "large-constants-roundtrip"); + Assert.That( + (await state.ExecuteAsync(restored))[0].Read(), + Is.EqualTo(Instruction.MaxArgBx + 1) + ); + } +} diff --git a/tests/Lua.Tests/CompilerReviewTests.cs b/tests/Lua.Tests/CompilerTests.cs similarity index 81% rename from tests/Lua.Tests/CompilerReviewTests.cs rename to tests/Lua.Tests/CompilerTests.cs index 3e0b1ebb..b8587e54 100644 --- a/tests/Lua.Tests/CompilerReviewTests.cs +++ b/tests/Lua.Tests/CompilerTests.cs @@ -9,7 +9,7 @@ namespace Lua.Tests; [TestFixture(LuaStringMode.Utf16)] [TestFixture(LuaStringMode.Bytes)] -public class CompilerReviewTests(LuaStringMode stringMode) +public class CompilerTests(LuaStringMode stringMode) { LuaState CreateState() { @@ -127,27 +127,3 @@ public async Task SyntaxDepthFailureRestoresCounter() Assert.That((await state.DoStringAsync("return 42"))[0].Read(), Is.EqualTo(42)); } } - -public class CompilerConstantBoundaryTests -{ - [Test] - public async Task ConstantBeyondBxUsesLoadKxAndRoundTrips() - { - using var state = LuaState.Create(); - var source = new StringBuilder("local x\n"); - for (var i = 0; i <= Instruction.MaxArgBx + 1; i++) - source.Append("x=").Append(i).Append('\n'); - source.Append("return x"); - var closure = state.Load(source.ToString(), "large-constants"); - Assert.That(closure.Proto.Code.ToArray().Any(i => i.OpCode == OpCode.LoadKX), Is.True); - Assert.That( - (await state.ExecuteAsync(closure))[0].Read(), - Is.EqualTo(Instruction.MaxArgBx + 1) - ); - var restored = state.Load(closure.Proto.ToBytecode(), "large-constants-roundtrip"); - Assert.That( - (await state.ExecuteAsync(restored))[0].Read(), - Is.EqualTo(Instruction.MaxArgBx + 1) - ); - } -} diff --git a/tests/Lua.Tests/ConversionLibraryReviewTests.cs b/tests/Lua.Tests/ConversionLibraryReviewTests.cs deleted file mode 100644 index d5870267..00000000 --- a/tests/Lua.Tests/ConversionLibraryReviewTests.cs +++ /dev/null @@ -1,70 +0,0 @@ -using Lua.Standard; - -namespace Lua.Tests; - -public class ConversionLibraryReviewTests -{ - static LuaState CreateState() - { - var state = LuaState.Create(); - state.OpenStandardLibraries(); - return state; - } - - [TestCase(-0.0)] - [TestCase(-1d)] - [TestCase(-1.5)] - [TestCase(1e20)] - [TestCase(-1e20)] - [TestCase(double.Epsilon)] - [TestCase(-double.Epsilon)] - [TestCase(double.PositiveInfinity)] - [TestCase(double.NegativeInfinity)] - [TestCase(double.NaN)] - public async Task ModfKeepsDoubleRangeAndSignedFractionalZero(double number) - { - using var state = CreateState(); - var values = await state.CallAsync( - state.Environment["math"].Read()["modf"], - [number] - ); - var integral = values[0].Read(); - var fraction = values[1].Read(); - if (double.IsNaN(number)) - { - Assert.That(double.IsNaN(integral) && double.IsNaN(fraction), Is.True); - return; - } - Assert.That( - BitConverter.DoubleToInt64Bits(integral), - Is.EqualTo(BitConverter.DoubleToInt64Bits(Math.Truncate(number))) - ); - if (double.IsInfinity(number) || number == Math.Truncate(number)) - Assert.That( - BitConverter.DoubleToInt64Bits(fraction), - Is.EqualTo(BitConverter.DoubleToInt64Bits(number) & long.MinValue) - ); - else - Assert.That(integral + fraction, Is.EqualTo(number)); - } - - [Test] - public async Task RandomSeedsAreNumericAndRepeatable() - { - using var state = CreateState(); - await state.DoStringAsync( - """ - local function sequence(seed) - math.randomseed(seed) - local t={}; for i=1,8 do t[i]=math.random() end - return table.concat(t,',') - end - assert(sequence(1)==sequence(1)) - assert(sequence(1)~=sequence(2)) - assert(sequence('1')==sequence(1)) - assert(sequence(1.5)==sequence(2)) - assert(sequence(1+2^32)==sequence(1)) - """ - ); - } -} diff --git a/tests/Lua.Tests/FrexpReconstructionTests.cs b/tests/Lua.Tests/FrexpReconstructionTests.cs new file mode 100644 index 00000000..a60b035b --- /dev/null +++ b/tests/Lua.Tests/FrexpReconstructionTests.cs @@ -0,0 +1,30 @@ +using Lua.Standard; + +namespace Lua.Tests; + +public class FrexpReconstructionTests +{ + [Test] + public void FiniteValuesNormalizeAndReconstructBitExactly() + { + var random = new Random(0x52); + for (var i = 0; i < 4096; i++) + { + var bits = random.NextInt64(long.MinValue, long.MaxValue); + if ((i & 1) == 0) + bits &= unchecked((long)0x800fffffffffffff); // Include subnormals. + var input = BitConverter.Int64BitsToDouble(bits); + if (!double.IsFinite(input)) + continue; + var (mantissa, exponent) = MathEx.Frexp(input); + if (input == 0) + Assert.That(exponent, Is.Zero); + else + Assert.That(Math.Abs(mantissa), Is.GreaterThanOrEqualTo(0.5).And.LessThan(1)); + Assert.That( + BitConverter.DoubleToInt64Bits(Math.ScaleB(mantissa, exponent)), + Is.EqualTo(bits) + ); + } + } +} diff --git a/tests/Lua.Tests/LuaStackCapacityTests.cs b/tests/Lua.Tests/LuaStackCapacityTests.cs new file mode 100644 index 00000000..92315bf7 --- /dev/null +++ b/tests/Lua.Tests/LuaStackCapacityTests.cs @@ -0,0 +1,16 @@ +using Lua.Runtime; + +namespace Lua.Tests; + +public class LuaStackCapacityTests +{ + [Test] + public void EmptyStackCanGrowAndRejectsOverflowingCapacity() + { + var stack = new LuaStack(0); + stack.Push(42); + Assert.That(stack.Pop().Read(), Is.EqualTo(42)); + Assert.Throws(() => stack.EnsureCapacity(int.MaxValue)); + Assert.That(stack.Count, Is.Zero); + } +} diff --git a/tests/Lua.Tests/MathematicsLibraryReviewTests.cs b/tests/Lua.Tests/MathematicsLibraryTests.cs similarity index 55% rename from tests/Lua.Tests/MathematicsLibraryReviewTests.cs rename to tests/Lua.Tests/MathematicsLibraryTests.cs index 439dea0d..10dee4fd 100644 --- a/tests/Lua.Tests/MathematicsLibraryReviewTests.cs +++ b/tests/Lua.Tests/MathematicsLibraryTests.cs @@ -2,7 +2,7 @@ namespace Lua.Tests; -public class MathematicsLibraryReviewTests +public class MathematicsLibraryTests { static LuaState CreateState() { @@ -66,31 +66,61 @@ public async Task AngleConversionsAndFrexpPreserveBothZeroSigns() Assert.That(values[1].Read(), Is.Zero); } } -} -public class FrexpReconstructionTests -{ - [Test] - public void FiniteValuesNormalizeAndReconstructBitExactly() + [TestCase(-0.0)] + [TestCase(-1d)] + [TestCase(-1.5)] + [TestCase(1e20)] + [TestCase(-1e20)] + [TestCase(double.Epsilon)] + [TestCase(-double.Epsilon)] + [TestCase(double.PositiveInfinity)] + [TestCase(double.NegativeInfinity)] + [TestCase(double.NaN)] + public async Task ModfKeepsDoubleRangeAndSignedFractionalZero(double number) { - var random = new Random(0x52); - for (var i = 0; i < 4096; i++) + using var state = CreateState(); + var values = await state.CallAsync( + state.Environment["math"].Read()["modf"], + [number] + ); + var integral = values[0].Read(); + var fraction = values[1].Read(); + if (double.IsNaN(number)) { - var bits = random.NextInt64(long.MinValue, long.MaxValue); - if ((i & 1) == 0) - bits &= unchecked((long)0x800fffffffffffff); // Include subnormals. - var input = BitConverter.Int64BitsToDouble(bits); - if (!double.IsFinite(input)) - continue; - var (mantissa, exponent) = MathEx.Frexp(input); - if (input == 0) - Assert.That(exponent, Is.Zero); - else - Assert.That(Math.Abs(mantissa), Is.GreaterThanOrEqualTo(0.5).And.LessThan(1)); + Assert.That(double.IsNaN(integral) && double.IsNaN(fraction), Is.True); + return; + } + Assert.That( + BitConverter.DoubleToInt64Bits(integral), + Is.EqualTo(BitConverter.DoubleToInt64Bits(Math.Truncate(number))) + ); + if (double.IsInfinity(number) || number == Math.Truncate(number)) Assert.That( - BitConverter.DoubleToInt64Bits(Math.ScaleB(mantissa, exponent)), - Is.EqualTo(bits) + BitConverter.DoubleToInt64Bits(fraction), + Is.EqualTo(BitConverter.DoubleToInt64Bits(number) & long.MinValue) ); - } + else + Assert.That(integral + fraction, Is.EqualTo(number)); + } + + [Test] + public async Task RandomSeedsAreNumericAndRepeatable() + { + using var state = CreateState(); + await state.DoStringAsync( + """ + local function sequence(seed) + math.randomseed(seed) + local t={}; for i=1,8 do t[i]=math.random() end + return table.concat(t,',') + end + assert(sequence(1)==sequence(1)) + assert(sequence(1)~=sequence(2)) + assert(sequence('1')==sequence(1)) + assert(sequence(1.5)==sequence(2)) + assert(sequence(1+2^32)==sequence(1)) + """ + ); } } diff --git a/tests/Lua.Tests/RuntimeMetamethodFailureTests.cs b/tests/Lua.Tests/RuntimeMetamethodFailureTests.cs index fa5fc752..7a286f67 100644 --- a/tests/Lua.Tests/RuntimeMetamethodFailureTests.cs +++ b/tests/Lua.Tests/RuntimeMetamethodFailureTests.cs @@ -26,13 +26,13 @@ bool suspend { if (suspend) await Task.Yield(); - throw new LuaRuntimeException(context.State, "branch-review-fault"); + throw new LuaRuntimeException(context.State, "metamethod-fault"); } ); state.Environment["value"] = new LuaTable { Metatable = metatable }; var values = await state.DoStringAsync("return pcall(function() " + source + " end)"); Assert.That(values[0].Read(), Is.False); - Assert.That(values[1].Read(), Does.Contain("branch-review-fault")); + Assert.That(values[1].Read(), Does.Contain("metamethod-fault")); Assert.That(state.Stack.Count, Is.Zero); Assert.That(state.CallStackFrameCount, Is.Zero); Assert.That((await state.DoStringAsync("return 42"))[0].Read(), Is.EqualTo(42)); diff --git a/tests/Lua.Tests/ScannerReviewTests.cs b/tests/Lua.Tests/ScannerTokenTests.cs similarity index 95% rename from tests/Lua.Tests/ScannerReviewTests.cs rename to tests/Lua.Tests/ScannerTokenTests.cs index d3ed0f2e..1766c649 100644 --- a/tests/Lua.Tests/ScannerReviewTests.cs +++ b/tests/Lua.Tests/ScannerTokenTests.cs @@ -4,7 +4,7 @@ namespace Lua.Tests; [TestFixture(LuaStringMode.Utf16)] [TestFixture(LuaStringMode.Bytes)] -public class ScannerReviewTests(LuaStringMode mode) +public class ScannerTokenTests(LuaStringMode mode) { LuaState CreateState() => LuaState.Create( @@ -44,7 +44,7 @@ string expected [TestCase("'\\256'")] [TestCase("'\\x0'")] [TestCase("'\\xGG'")] - public void InvalidQuotedStringsAreStillRejected(string literal) + public void InvalidQuotedStringsAreRejected(string literal) { using var state = CreateState(); Assert.Throws(() => @@ -109,7 +109,7 @@ public void MalformedNumeralsMatchLua52TokenBoundaries(string expression, string [TestCase("0X.8P+2", 2)] [TestCase("000001.25", 1.25)] [TestCase("0x1p18446744073709551616", 1)] - public async Task ValidNumeralBoundariesAndExponentsStillWork( + public async Task ValidNumeralBoundariesAndExponentsAreAccepted( string expression, double expected ) diff --git a/tests/Lua.Tests/TableHelperReviewTests.cs b/tests/Lua.Tests/TableLibraryTests.cs similarity index 89% rename from tests/Lua.Tests/TableHelperReviewTests.cs rename to tests/Lua.Tests/TableLibraryTests.cs index b663c4f3..79254ba0 100644 --- a/tests/Lua.Tests/TableHelperReviewTests.cs +++ b/tests/Lua.Tests/TableLibraryTests.cs @@ -6,7 +6,7 @@ namespace Lua.Tests; [TestFixture(LuaStringMode.Utf16)] [TestFixture(LuaStringMode.Bytes)] -public class TableHelperReviewTests(LuaStringMode mode) +public class TableLibraryTests(LuaStringMode mode) { LuaState CreateState() { @@ -21,7 +21,7 @@ LuaState CreateState() [TestCase("table.remove(t,0.5)")] [TestCase("table.insert(t,0/0,99)")] [TestCase("table.remove(t,math.huge)")] - public async Task InvalidPositionsAreStillRejected(string operation) + public async Task InvalidPositionsAreRejected(string operation) { using var state = CreateState(); var result = await state.DoStringAsync( @@ -105,14 +105,4 @@ public async Task ExcessiveUnpackRangesAreRejectedWithoutStackGrowth(string rang Assert.That(state.Stack.Count, Is.Zero); Assert.That((await state.DoStringAsync("return 42"))[0].Read(), Is.EqualTo(42)); } - - [Test] - public void EmptyStackCanGrowAndRejectsOverflowingCapacity() - { - var stack = new LuaStack(0); - stack.Push(42); - Assert.That(stack.Pop().Read(), Is.EqualTo(42)); - Assert.Throws(() => stack.EnsureCapacity(int.MaxValue)); - Assert.That(stack.Count, Is.Zero); - } } diff --git a/tests/Lua.Tests/VirtualMachineReviewTests.cs b/tests/Lua.Tests/VirtualMachineExecutionTests.cs similarity index 99% rename from tests/Lua.Tests/VirtualMachineReviewTests.cs rename to tests/Lua.Tests/VirtualMachineExecutionTests.cs index 8b9adf1e..1fd8d475 100644 --- a/tests/Lua.Tests/VirtualMachineReviewTests.cs +++ b/tests/Lua.Tests/VirtualMachineExecutionTests.cs @@ -5,7 +5,7 @@ namespace Lua.Tests; [TestFixture(LuaStringMode.Utf16)] [TestFixture(LuaStringMode.Bytes)] -public class VirtualMachineReviewTests(LuaStringMode stringMode) +public class VirtualMachineExecutionTests(LuaStringMode stringMode) { LuaState CreateState() {