🐐 Tests
This commit is contained in:
263
tests/09_test_fraction.py
Normal file
263
tests/09_test_fraction.py
Normal file
@@ -0,0 +1,263 @@
|
||||
from tests._helpers import (
|
||||
unittest, parameterized, Fraction, time,
|
||||
run_test, run_compiler_error_test,
|
||||
ArrayIndex, ArraySlice, Bool, BinOp, BuiltIn, DataArray, DataDict, DataRangeArray,
|
||||
Defini, Continva, Designa, DesignaDestructure, DesignaIndex, DumStatement,
|
||||
Erumpe, ExpressionStatement, Fvnctio, ID, InterpolatedString, Invoca,
|
||||
ModuleCall, Nullus, Numeral, PerStatement, Program, Redi, SiStatement,
|
||||
String, TemptaStatement, UnaryMinus, UnaryNot, Fractio, frac_to_fraction,
|
||||
fraction_to_frac, num_to_int, int_to_num, make_string,
|
||||
ValInt, ValStr, ValBool, ValList, ValDict, ValNul, ValFunc, ValFrac,
|
||||
CentvrionError, _RUNTIME_C, _cent_rng,
|
||||
Lexer, Parser, compile_program,
|
||||
os, subprocess, tempfile, StringIO, patch,
|
||||
)
|
||||
|
||||
|
||||
# --- FRACTIO module ---
|
||||
|
||||
fractio_tests = [
|
||||
# Basic fraction literals
|
||||
("CVM FRACTIO\nIIIS",
|
||||
Program([ModuleCall("FRACTIO")], [ExpressionStatement(Fractio("IIIS"))]),
|
||||
ValFrac(Fraction(7, 2))),
|
||||
("CVM FRACTIO\nS",
|
||||
Program([ModuleCall("FRACTIO")], [ExpressionStatement(Fractio("S"))]),
|
||||
ValFrac(Fraction(1, 2))),
|
||||
("CVM FRACTIO\nS:.",
|
||||
Program([ModuleCall("FRACTIO")], [ExpressionStatement(Fractio("S:."))]),
|
||||
ValFrac(Fraction(3, 4))),
|
||||
("CVM FRACTIO\n.",
|
||||
Program([ModuleCall("FRACTIO")], [ExpressionStatement(Fractio("."))]),
|
||||
ValFrac(Fraction(1, 12))),
|
||||
("CVM FRACTIO\n:.",
|
||||
Program([ModuleCall("FRACTIO")], [ExpressionStatement(Fractio(":."))]),
|
||||
ValFrac(Fraction(1, 4))),
|
||||
# Integer part with fraction
|
||||
("CVM FRACTIO\nVIIS:|::",
|
||||
Program([ModuleCall("FRACTIO")], [ExpressionStatement(Fractio("VIIS:|::"))]),
|
||||
ValFrac(Fraction(7) + Fraction(100, 144))),
|
||||
# Arithmetic
|
||||
("CVM FRACTIO\nIIIS + S",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Fractio("IIIS"), Fractio("S"), "SYMBOL_PLUS"))
|
||||
]),
|
||||
ValFrac(Fraction(4))
|
||||
),
|
||||
("CVM FRACTIO\nIIIS - S",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Fractio("IIIS"), Fractio("S"), "SYMBOL_MINUS"))
|
||||
]),
|
||||
ValFrac(Fraction(3))
|
||||
),
|
||||
("CVM FRACTIO\nS * IV",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Fractio("S"), Numeral("IV"), "SYMBOL_TIMES"))
|
||||
]),
|
||||
ValFrac(Fraction(2))
|
||||
),
|
||||
# Division returns fraction
|
||||
("CVM FRACTIO\nI / IV",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Numeral("I"), Numeral("IV"), "SYMBOL_DIVIDE"))
|
||||
]),
|
||||
ValFrac(Fraction(1, 4))
|
||||
),
|
||||
("CVM FRACTIO\nI / III",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Numeral("I"), Numeral("III"), "SYMBOL_DIVIDE"))
|
||||
]),
|
||||
ValFrac(Fraction(1, 3))
|
||||
),
|
||||
# Integer division still works without fractions in operands... but with FRACTIO returns ValFrac
|
||||
("CVM FRACTIO\nX / II",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Numeral("X"), Numeral("II"), "SYMBOL_DIVIDE"))
|
||||
]),
|
||||
ValFrac(Fraction(5))
|
||||
),
|
||||
# Modulo on fractions: 7/2 RELIQVVM 3/2 = 1/2 (7/2 / 3/2 = 7/3, floor=2, 7/2 - 3 = 1/2)
|
||||
("CVM FRACTIO\nIIIS RELIQVVM IS",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Fractio("IIIS"), Fractio("IS"), "KEYWORD_RELIQVVM"))
|
||||
]),
|
||||
ValFrac(Fraction(1, 2))
|
||||
),
|
||||
# Modulo with mixed operand types: 5/2 RELIQVVM 1 = 1/2
|
||||
("CVM FRACTIO\nIIS RELIQVVM I",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Fractio("IIS"), Numeral("I"), "KEYWORD_RELIQVVM"))
|
||||
]),
|
||||
ValFrac(Fraction(1, 2))
|
||||
),
|
||||
# Int operands under FRACTIO still return a fraction: 10 RELIQVVM 3 = 1 (as Fraction)
|
||||
("CVM FRACTIO\nX RELIQVVM III",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Numeral("X"), Numeral("III"), "KEYWORD_RELIQVVM"))
|
||||
]),
|
||||
ValFrac(Fraction(1))
|
||||
),
|
||||
# Exact multiple under FRACTIO: 3 RELIQVVM 3/2 = 0
|
||||
("CVM FRACTIO\nIII RELIQVVM IS",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Numeral("III"), Fractio("IS"), "KEYWORD_RELIQVVM"))
|
||||
]),
|
||||
ValFrac(Fraction(0))
|
||||
),
|
||||
# String concatenation with fraction
|
||||
("CVM FRACTIO\nDIC(IIIS & \"!\")",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BuiltIn("DIC", [BinOp(Fractio("IIIS"), String("!"), "SYMBOL_AMPERSAND")]))
|
||||
]),
|
||||
ValStr("IIIS!"), "IIIS!\n"
|
||||
),
|
||||
# Negative fractions
|
||||
("CVM FRACTIO\nCVM SVBNVLLA\n-IIS",
|
||||
Program([ModuleCall("FRACTIO"),ModuleCall("SVBNVLLA")],[
|
||||
ExpressionStatement(UnaryMinus(Fractio("IIS")))
|
||||
]),
|
||||
ValFrac(Fraction(-5,2))
|
||||
)
|
||||
]
|
||||
|
||||
class TestFractio(unittest.TestCase):
|
||||
@parameterized.expand(fractio_tests)
|
||||
def test_fractio(self, source, nodes, value, output=""):
|
||||
run_test(self, source, nodes, value, output)
|
||||
|
||||
|
||||
fractio_comparison_tests = [
|
||||
# fraction vs fraction
|
||||
("CVM FRACTIO\nIIIS PLVS III",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Fractio("IIIS"), Numeral("III"), "KEYWORD_PLVS"))
|
||||
]),
|
||||
ValBool(True)
|
||||
),
|
||||
("CVM FRACTIO\nIII MINVS IIIS",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Numeral("III"), Fractio("IIIS"), "KEYWORD_MINVS"))
|
||||
]),
|
||||
ValBool(True)
|
||||
),
|
||||
("CVM FRACTIO\nIIIS MINVS IV",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Fractio("IIIS"), Numeral("IV"), "KEYWORD_MINVS"))
|
||||
]),
|
||||
ValBool(True)
|
||||
),
|
||||
("CVM FRACTIO\nIV PLVS IIIS",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Numeral("IV"), Fractio("IIIS"), "KEYWORD_PLVS"))
|
||||
]),
|
||||
ValBool(True)
|
||||
),
|
||||
("CVM FRACTIO\nIIIS PLVS IIIS",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Fractio("IIIS"), Fractio("IIIS"), "KEYWORD_PLVS"))
|
||||
]),
|
||||
ValBool(False)
|
||||
),
|
||||
("CVM FRACTIO\nIIIS MINVS IIIS",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Fractio("IIIS"), Fractio("IIIS"), "KEYWORD_MINVS"))
|
||||
]),
|
||||
ValBool(False)
|
||||
),
|
||||
# HAVD_PLVS / HAVD_MINVS on fractions — equality boundary distinguishes from MINVS / PLVS
|
||||
("CVM FRACTIO\nIIIS HAVD_PLVS III",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Fractio("IIIS"), Numeral("III"), "KEYWORD_HAVD_PLVS"))
|
||||
]),
|
||||
ValBool(False) # 3.5 <= 3 is false
|
||||
),
|
||||
("CVM FRACTIO\nIIIS HAVD_MINVS IIIS",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Fractio("IIIS"), Fractio("IIIS"), "KEYWORD_HAVD_MINVS"))
|
||||
]),
|
||||
ValBool(True) # 3.5 >= 3.5 is true (equality boundary)
|
||||
),
|
||||
("CVM FRACTIO\nIIIS HAVD_PLVS IIIS",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Fractio("IIIS"), Fractio("IIIS"), "KEYWORD_HAVD_PLVS"))
|
||||
]),
|
||||
ValBool(True) # 3.5 <= 3.5 is true (equality boundary)
|
||||
),
|
||||
# equality: fraction == fraction
|
||||
("CVM FRACTIO\nIIIS EST IIIS",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Fractio("IIIS"), Fractio("IIIS"), "KEYWORD_EST"))
|
||||
]),
|
||||
ValBool(True)
|
||||
),
|
||||
("CVM FRACTIO\nIIIS EST IV",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(Fractio("IIIS"), Numeral("IV"), "KEYWORD_EST"))
|
||||
]),
|
||||
ValBool(False)
|
||||
),
|
||||
# equality: fraction == whole number (ValFrac(4) vs ValInt(4))
|
||||
("CVM FRACTIO\nIIIS + S EST IV",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(
|
||||
BinOp(Fractio("IIIS"), Fractio("S"), "SYMBOL_PLUS"),
|
||||
Numeral("IV"), "KEYWORD_EST"))
|
||||
]),
|
||||
ValBool(True)
|
||||
),
|
||||
("CVM FRACTIO\nS + S EST I",
|
||||
Program([ModuleCall("FRACTIO")], [
|
||||
ExpressionStatement(BinOp(
|
||||
BinOp(Fractio("S"), Fractio("S"), "SYMBOL_PLUS"),
|
||||
Numeral("I"), "KEYWORD_EST"))
|
||||
]),
|
||||
ValBool(True)
|
||||
),
|
||||
]
|
||||
|
||||
class TestFractioComparisons(unittest.TestCase):
|
||||
@parameterized.expand(fractio_comparison_tests)
|
||||
def test_fractio_comparison(self, source, nodes, value):
|
||||
run_test(self, source, nodes, value)
|
||||
|
||||
|
||||
class TestFractioHelpers(unittest.TestCase):
|
||||
def test_frac_to_fraction_ordering(self):
|
||||
with self.assertRaises(CentvrionError):
|
||||
frac_to_fraction(".S") # . before S violates highest-to-lowest
|
||||
|
||||
def test_frac_to_fraction_level_overflow(self):
|
||||
with self.assertRaises(CentvrionError):
|
||||
frac_to_fraction("SSSSSS") # SS means S twice = 12/12 = 1, violating < 12/12 constraint
|
||||
|
||||
def test_frac_to_fraction_iiis(self):
|
||||
self.assertEqual(frac_to_fraction("IIIS"), Fraction(7, 2))
|
||||
|
||||
def test_frac_to_fraction_s_colon_dot(self):
|
||||
self.assertEqual(frac_to_fraction("S:."), Fraction(3, 4))
|
||||
|
||||
def test_frac_to_fraction_dot(self):
|
||||
self.assertEqual(frac_to_fraction("."), Fraction(1, 12))
|
||||
|
||||
def test_frac_to_fraction_multilevel(self):
|
||||
self.assertEqual(frac_to_fraction("VIIS:|::"), Fraction(7) + Fraction(100, 144))
|
||||
|
||||
def test_fraction_to_frac_iiis(self):
|
||||
self.assertEqual(fraction_to_frac(Fraction(7, 2)), "IIIS")
|
||||
|
||||
def test_fraction_to_frac_s_colon_dot(self):
|
||||
self.assertEqual(fraction_to_frac(Fraction(3, 4)), "S:.")
|
||||
|
||||
def test_fraction_to_frac_dot(self):
|
||||
self.assertEqual(fraction_to_frac(Fraction(1, 12)), ".")
|
||||
|
||||
def test_fraction_to_frac_multilevel(self):
|
||||
self.assertEqual(
|
||||
fraction_to_frac(Fraction(7) + Fraction(100, 144)),
|
||||
"VIIS:|::"
|
||||
)
|
||||
|
||||
def test_roundtrip(self):
|
||||
# Only canonical forms roundtrip — fraction_to_frac always uses max colons before dots
|
||||
for s in ["IIIS", "S:.", ".", "::", "VIIS:|::", "S"]:
|
||||
self.assertEqual(fraction_to_frac(frac_to_fraction(s)), s)
|
||||
Reference in New Issue
Block a user