// Five Test Suite — adapted from Harbour hbtest framework // Harbour: /mnt/d/harbour-core/utils/hbtest/ // // Pattern: FUNCTION TestXxx() containing individual assertions // Uses: ASSERT(expr, expected, description) // // This tests ALL implemented Five features for regression. FUNCTION Main() LOCAL nPass := 0, nFail := 0, nTotal := 0 ? "=============================================" ? " Five Test Suite" ? " Adapted from Harbour hbtest (5000+ tests)" ? "=============================================" ? "" // --- String Functions --- ? "--- String Functions ---" nTotal += Test("Upper('hello')", Upper("hello"), "HELLO") nTotal += Test("Lower('WORLD')", Lower("WORLD"), "world") nTotal += Test("Len('test')", Len("test"), 4) nTotal += Test("Len('')", Len(""), 0) nTotal += Test("AllTrim(' hi ')", AllTrim(" hi "), "hi") nTotal += Test("Space(5)", Space(5), " ") nTotal += Test("Replicate('*',3)", Replicate("*", 3), "***") nTotal += Test("PadR('ab', 5)", PadR("ab", 5), "ab ") nTotal += Test("PadL('ab', 5)", PadL("ab", 5), " ab") nTotal += Test("'Hello' + ' World'", "Hello" + " World", "Hello World") ? "" // --- Numeric Operations --- ? "--- Numeric Operations ---" nTotal += Test("2 + 3", 2 + 3, 5) nTotal += Test("10 - 7", 10 - 7, 3) nTotal += Test("6 * 7", 6 * 7, 42) nTotal += Test("10 / 3 (double)", 10 / 3 > 3.33, .T.) nTotal += Test("10 % 3", 10 % 3, 1) nTotal += Test("2 ** 10", 2 ** 10, 1024) nTotal += Test("Abs(-42)", Abs(-42), 42) nTotal += Test("Abs(42)", Abs(42), 42) nTotal += Test("Int(3.7)", Int(3.7), 3) nTotal += Test("Int(-3.7)", Int(-3.7), -3) ? "" // --- Comparison --- ? "--- Comparison Operations ---" nTotal += Test("1 = 1", 1 = 1, .T.) nTotal += Test("1 = 2", 1 = 2, .F.) nTotal += Test("'abc' = 'abc'", "abc" = "abc", .T.) nTotal += Test("'abc' < 'def'", "abc" < "def", .T.) nTotal += Test("10 > 5", 10 > 5, .T.) nTotal += Test("10 <= 10", 10 <= 10, .T.) nTotal += Test("10 >= 11", 10 >= 11, .F.) nTotal += Test("1 != 2", 1 != 2, .T.) ? "" // --- Logical --- ? "--- Logical Operations ---" nTotal += Test(".T. .AND. .T.", .T. .AND. .T., .T.) nTotal += Test(".T. .AND. .F.", .T. .AND. .F., .F.) nTotal += Test(".F. .OR. .T.", .F. .OR. .T., .T.) nTotal += Test(".F. .OR. .F.", .F. .OR. .F., .F.) nTotal += Test(".NOT. .T.", .NOT. .T., .F.) nTotal += Test(".NOT. .F.", .NOT. .F., .T.) ? "" // --- Type Checking --- ? "--- Type Functions ---" nTotal += Test("ValType(42)", ValType(42), "N") nTotal += Test("ValType('str')", ValType("str"), "C") nTotal += Test("ValType(.T.)", ValType(.T.), "L") nTotal += Test("ValType(NIL)", ValType(NIL), "U") nTotal += Test("ValType({})", ValType({}), "A") nTotal += Test("Empty('')", Empty(""), .T.) nTotal += Test("Empty(0)", Empty(0), .T.) nTotal += Test("Empty(.F.)", Empty(.F.), .T.) nTotal += Test("Empty('x')", Empty("x"), .F.) nTotal += Test("Empty(1)", Empty(1), .F.) nTotal += Test("Empty(.T.)", Empty(.T.), .F.) ? "" // --- Array Operations --- ? "--- Array Operations ---" nTotal += TestArray() ? "" // --- Control Flow --- ? "--- Control Flow ---" nTotal += TestFlow() ? "" // --- Functions --- ? "--- Function Calls ---" nTotal += TestFunctions() ? "" // --- Summary --- ? "=============================================" ? " Results:" ? " Total: ", nTotal ? "=============================================" ? "" RETURN NIL // Test helper: returns 1, prints PASS/FAIL FUNCTION Test(cDesc, xResult, xExpected) IF ValType(xResult) = ValType(xExpected) IF xResult = xExpected // PASS - silent (Harbour style: only show failures) RETURN 1 ENDIF ENDIF ? " FAIL:", cDesc ? " Got: ", xResult ? " Expected:", xExpected RETURN 1 // Array tests FUNCTION TestArray() LOCAL a, n := 0 a := {1, 2, 3} n += Test("Len({1,2,3})", Len(a), 3) AAdd(a, 4) n += Test("AAdd: Len after", Len(a), 4) n += Test("AScan({1,2,3,4}, 3)", AScan(a, 3), 3) n += Test("AScan not found", AScan(a, 99), 0) n += Test("ATail({1,2,3,4})", ATail(a), 4) // ASort a := {30, 10, 20} ASort(a) n += Test("ASort [1]", a[1], 10) n += Test("ASort [2]", a[2], 20) n += Test("ASort [3]", a[3], 30) RETURN n // Control flow tests FUNCTION TestFlow() LOCAL n := 0, i, nSum // IF/ELSE IF .T. n += Test("IF .T.", .T., .T.) ELSE n += Test("IF .T. (should not reach)", .F., .T.) ENDIF IF .F. n += Test("IF .F. (should not reach)", .F., .T.) ELSE n += Test("IF .F. ELSE", .T., .T.) ENDIF // FOR loop nSum := 0 FOR i := 1 TO 10 nSum += i NEXT n += Test("FOR 1..10 sum", nSum, 55) // DO WHILE nSum := 0 i := 1 DO WHILE i <= 5 nSum += i i++ ENDDO n += Test("DO WHILE 1..5 sum", nSum, 15) RETURN n // Function call tests FUNCTION TestFunctions() LOCAL n := 0 n += Test("Double(21)", Double(21), 42) n += Test("Add(10,20)", Add(10, 20), 30) n += Test("Nested: Double(Add(3,4))", Double(Add(3, 4)), 14) n += Test("Factorial(5)", Factorial(5), 120) RETURN n FUNCTION Double(x) RETURN x * 2 FUNCTION Add(a, b) RETURN a + b FUNCTION Factorial(n) IF n <= 1 RETURN 1 ENDIF RETURN n * Factorial(n - 1)