feat: add eval stdlib module with dynamic expression evaluation and input validation tests
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user