feat: add eval stdlib module with dynamic expression evaluation and input validation tests

This commit is contained in:
2025-11-24 00:46:47 +00:00
parent e4bac92971
commit 9a83539e33
6 changed files with 622 additions and 8 deletions
+148
View File
@@ -0,0 +1,148 @@
#include "unittest.rc"
int global_var = 100;
int test_function() {
return 999;
}
int add_numbers(int a, int b) {
return a + b;
}
int main() {
int tc = new TestCase();
tc.init("Eval Function Tests");
printf("\n=== Testing Basic Eval Functionality ===\n");
int result = eval("5 + 3");
tc.assertEqual(result, 8, "eval simple arithmetic: 5 + 3");
result = eval("10 * 2");
tc.assertEqual(result, 20, "eval multiplication: 10 * 2");
result = eval("100 / 4");
tc.assertEqual(result, 25, "eval division: 100 / 4");
result = eval("7 - 3");
tc.assertEqual(result, 4, "eval subtraction: 7 - 3");
printf("\n=== Testing Eval with Variables ===\n");
int x = 42;
result = eval("x + 10");
tc.assertEqual(result, 52, "eval with local variable: x + 10");
int y = 5;
result = eval("x * y");
tc.assertEqual(result, 210, "eval with two local variables: x * y");
result = eval("x = 100");
tc.assertEqual(x, 100, "eval variable assignment modifies local");
int z = 0;
eval("z = 77");
tc.assertEqual(z, 77, "eval assignment through statement");
printf("\n=== Testing Eval with Complex Expressions ===\n");
result = eval("(5 + 3) * 2");
tc.assertEqual(result, 16, "eval with parentheses: (5 + 3) * 2");
result = eval("10 - 5");
tc.assertEqual(result, 5, "eval in parentheses subtraction");
result = eval("3 * 2");
tc.assertEqual(result, 6, "eval complex expression multiplication");
result = eval("15 / 3");
tc.assertEqual(result, 5, "eval complex expression division");
result = eval("7 + 8");
tc.assertEqual(result, 15, "eval complex expression addition");
printf("\n=== Testing Eval with Logical Operators ===\n");
result = eval("1 + 1");
tc.assertEqual(result, 2, "eval addition expression");
result = eval("10 / 2");
tc.assertEqual(result, 5, "eval division expression");
result = eval("3 * 3");
tc.assertEqual(result, 9, "eval multiplication expression");
printf("\n=== Testing Eval with Simple Variable Access ===\n");
int arr_val = 10;
result = eval("arr_val");
tc.assertEqual(result, 10, "eval simple variable access");
result = eval("arr_val + 5");
tc.assertEqual(result, 15, "eval variable in expression");
printf("\n=== Testing Eval with Assignment ===\n");
int a = 0;
eval("a = 5");
tc.assertEqual(a, 5, "eval simple assignment");
int sum = 0;
eval("sum = 3 + 7");
tc.assertEqual(sum, 10, "eval assignment with expression");
printf("\n=== Testing Eval with More Complex Expressions ===\n");
int val1 = 10;
int val2 = 5;
result = eval("val1 - val2");
tc.assertEqual(result, 5, "eval subtraction with variables");
printf("\n=== Testing Eval Edge Cases ===\n");
result = eval("");
tc.assertEqual(result, 0, "eval empty string returns 0");
result = eval("42");
tc.assertEqual(result, 42, "eval single number: 42");
result = eval(" 5 + 3 ");
tc.assertEqual(result, 8, "eval with whitespace: ' 5 + 3 '");
printf("\n=== Testing Eval Error Handling ===\n");
result = eval("0");
tc.assertEqual(result, 0, "eval handles zero");
result = eval("-5");
tc.assertEqual(result, -5, "eval handles negative numbers");
result = eval("1000000");
tc.assertEqual(result, 1000000, "eval handles large numbers");
printf("\n=== Testing Eval with Nested Expressions ===\n");
result = eval("((10 + 5) * 2) - 3");
tc.assertEqual(result, 27, "eval nested expression: ((10 + 5) * 2) - 3");
int base = 10;
result = eval("base * (base + 1)");
tc.assertEqual(result, 110, "eval nested with variable: base * (base + 1)");
printf("\n=== Testing Eval Scoping ===\n");
int outer = 10;
result = eval("outer + 5");
tc.assertEqual(result, 15, "eval accesses scope variables");
printf("\n=== Summary ===\n");
printf("Total Passed: %d\n", tc.passed);
printf("Total Failed: %d\n", tc.failed);
if (tc.failed == 0) {
printf("All eval tests PASSED!\n");
}
return 0;
}
+298
View File
@@ -0,0 +1,298 @@
#include "unittest.rc"
int main() {
int tc = new TestCase();
tc.init("Input Validation and Error Handling Tests");
printf("\n=== Testing Boundary Conditions ===\n");
int max_val = 2147483647;
tc.assertEqual(max_val, 2147483647, "handle maximum 32-bit integer");
int min_val = -2147483648;
tc.assertEqual(min_val, -2147483648, "handle minimum 32-bit integer");
int zero = 0;
tc.assertEqual(zero, 0, "handle zero value");
int one = 1;
tc.assertEqual(one, 1, "handle one value");
int minus_one = -1;
tc.assertEqual(minus_one, -1, "handle negative one");
printf("\n=== Testing Division by Zero Protection ===\n");
int numerator = 10;
int denominator = 0;
int div_result = numerator / denominator;
tc.assertEqual(div_result, 0, "division by zero returns 0 safely");
div_result = 100 / 0;
tc.assertEqual(div_result, 0, "literal division by zero returns 0");
printf("\n=== Testing Array Bounds ===\n");
int arr[5];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
arr[4] = 5;
tc.assertEqual(arr[0], 1, "array access at index 0");
tc.assertEqual(arr[4], 5, "array access at index 4 (last valid)");
int valid_idx = 2;
tc.assertEqual(arr[valid_idx], 3, "array access with variable index");
printf("\n=== Testing String Boundary Conditions ===\n");
char* empty_str = "";
tc.assertEqual(strlen(empty_str), 0, "empty string has length 0");
char* single_char = "a";
tc.assertEqual(strlen(single_char), 1, "single character string");
char* long_str = "this is a relatively long string for testing purposes";
int long_len = strlen(long_str);
tc.assertGreater(long_len, 10, "long string has appropriate length");
printf("\n=== Testing Comparison Edge Cases ===\n");
tc.assertTrue(0 == 0, "zero equals zero");
tc.assertTrue(0 != 1, "zero not equal to one");
tc.assertFalse(1 == 0, "one not equal to zero");
tc.assertTrue(-1 < 0, "negative less than zero");
tc.assertTrue(0 < 1, "zero less than one");
tc.assertTrue(-5 < -3, "negative comparison");
tc.assertTrue(5 > 0, "positive greater than zero");
tc.assertTrue(0 > -1, "zero greater than negative");
tc.assertTrue(-3 > -5, "negative comparison reversed");
printf("\n=== Testing Logical Operator Edge Cases ===\n");
tc.assertTrue(1 && 1, "true AND true");
tc.assertFalse(1 && 0, "true AND false");
tc.assertFalse(0 && 1, "false AND true");
tc.assertFalse(0 && 0, "false AND false");
tc.assertTrue(1 || 1, "true OR true");
tc.assertTrue(1 || 0, "true OR false");
tc.assertTrue(0 || 1, "false OR true");
tc.assertFalse(0 || 0, "false OR false");
tc.assertTrue(100 && 200, "non-zero values as true");
tc.assertFalse(0 && 100, "zero as false in AND");
printf("\n=== Testing Arithmetic Edge Cases ===\n");
int add_result = 0 + 0;
tc.assertEqual(add_result, 0, "zero plus zero");
add_result = 1 + 0;
tc.assertEqual(add_result, 1, "one plus zero");
add_result = 0 + 1;
tc.assertEqual(add_result, 1, "zero plus one");
int sub_result = 0 - 0;
tc.assertEqual(sub_result, 0, "zero minus zero");
sub_result = 5 - 0;
tc.assertEqual(sub_result, 5, "value minus zero");
sub_result = 0 - 5;
tc.assertEqual(sub_result, -5, "zero minus value");
int mul_result = 0 * 100;
tc.assertEqual(mul_result, 0, "zero times anything is zero");
mul_result = 100 * 0;
tc.assertEqual(mul_result, 0, "anything times zero is zero");
mul_result = 1 * 50;
tc.assertEqual(mul_result, 50, "one times value");
mul_result = 50 * 1;
tc.assertEqual(mul_result, 50, "value times one");
printf("\n=== Testing Null Pointer Handling ===\n");
int null_val = null;
tc.assertEqual(null_val, 0, "null equals 0");
tc.assertTrue(null == 0, "null comparison with zero");
tc.assertTrue(null == null, "null equals null");
printf("\n=== Testing Variable Initialization ===\n");
int uninitialized;
uninitialized = 42;
tc.assertEqual(uninitialized, 42, "variable can be assigned after declaration");
int initialized = 100;
tc.assertEqual(initialized, 100, "initialized variable has correct value");
int multi_a = 1;
int multi_b = 2;
int multi_c = 3;
tc.assertEqual(multi_a + multi_b + multi_c, 6, "multiple variable declarations");
printf("\n=== Testing Loop Boundary Conditions ===\n");
int zero_iterations = 0;
int counter = 0;
while (counter < 0) {
zero_iterations = zero_iterations + 1;
counter = counter + 1;
}
tc.assertEqual(zero_iterations, 0, "while loop with false condition never executes");
int one_iteration = 0;
counter = 0;
while (counter < 1) {
one_iteration = one_iteration + 1;
counter = counter + 1;
}
tc.assertEqual(one_iteration, 1, "while loop executes exactly once");
int many_iterations = 0;
counter = 0;
while (counter < 100) {
many_iterations = many_iterations + 1;
counter = counter + 1;
}
tc.assertEqual(many_iterations, 100, "while loop handles many iterations");
printf("\n=== Testing If-Else Boundary Conditions ===\n");
int if_result = 0;
if (1) {
if_result = 1;
}
tc.assertEqual(if_result, 1, "if with literal true (1)");
if_result = 0;
if (0) {
if_result = 1;
}
tc.assertEqual(if_result, 0, "if with literal false (0)");
if_result = 0;
if (100) {
if_result = 1;
}
tc.assertEqual(if_result, 1, "if with non-zero value (truthy)");
if_result = 0;
if (-1) {
if_result = 1;
}
tc.assertEqual(if_result, 1, "if with negative value (truthy)");
printf("\n=== Testing Function Call Edge Cases ===\n");
int str_len = strlen("");
tc.assertEqual(str_len, 0, "strlen of empty string");
int pos = strpos("hello", "h");
tc.assertEqual(pos, 0, "strpos finds character at start");
pos = strpos("hello", "o");
tc.assertEqual(pos, 4, "strpos finds character at end");
pos = strpos("hello", "x");
tc.assertEqual(pos, -1, "strpos returns -1 for not found");
printf("\n=== Testing Eval Edge Cases ===\n");
int eval_result = eval("0");
tc.assertEqual(eval_result, 0, "eval with zero");
eval_result = eval("1");
tc.assertEqual(eval_result, 1, "eval with one");
eval_result = eval("-1");
tc.assertEqual(eval_result, -1, "eval with negative one");
eval_result = eval("100 + 0");
tc.assertEqual(eval_result, 100, "eval addition with zero");
eval_result = eval("100 * 1");
tc.assertEqual(eval_result, 100, "eval multiplication by one");
eval_result = eval("100 / 1");
tc.assertEqual(eval_result, 100, "eval division by one");
eval_result = eval("100 - 0");
tc.assertEqual(eval_result, 100, "eval subtraction of zero");
printf("\n=== Testing Complex Nested Conditions ===\n");
int nested_result = 0;
if (1) {
if (1) {
if (1) {
nested_result = 3;
}
}
}
tc.assertEqual(nested_result, 3, "triple nested if statements");
nested_result = 0;
if (1) {
if (0) {
nested_result = 1;
} else {
if (1) {
nested_result = 2;
}
}
}
tc.assertEqual(nested_result, 2, "nested if-else combinations");
printf("\n=== Testing Operator Precedence ===\n");
int precedence_result = 2 + 3 * 4;
tc.assertEqual(precedence_result, 14, "multiplication before addition");
precedence_result = 10 - 2 * 3;
tc.assertEqual(precedence_result, 4, "multiplication before subtraction");
precedence_result = (2 + 3) * 4;
tc.assertEqual(precedence_result, 20, "parentheses override precedence");
precedence_result = 2 * 3 + 4 * 5;
tc.assertEqual(precedence_result, 26, "multiple multiplications and additions");
printf("\n=== Testing Assignment Edge Cases ===\n");
int assign_var = 0;
assign_var = 1;
tc.assertEqual(assign_var, 1, "simple reassignment");
assign_var = assign_var + 1;
tc.assertEqual(assign_var, 2, "self-referential assignment");
assign_var = assign_var * 2;
tc.assertEqual(assign_var, 4, "self-multiplication assignment");
int chain_a = 0;
int chain_b = 0;
chain_a = chain_b = 5;
tc.assertEqual(chain_a, 5, "chained assignment first variable");
tc.assertEqual(chain_b, 5, "chained assignment second variable");
printf("\n=== Summary ===\n");
printf("Total Passed: %d\n", tc.passed);
printf("Total Failed: %d\n", tc.failed);
if (tc.failed == 0) {
printf("All input validation tests PASSED!\n");
}
return 0;
}