summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-10-15 08:50:18 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-10-15 08:50:18 +0800
commit269cf920996f9a5a0cb6909fd442ce28f0805cc0 (patch)
tree096a5b887d9df10c31a08767b51185cb09b3dbc6
parent8821367defad946089e5161f29d6ad32e8a631bd (diff)
downloadRUCDSA-269cf920996f9a5a0cb6909fd442ce28f0805cc0.tar.gz
RUCDSA-269cf920996f9a5a0cb6909fd442ce28f0805cc0.tar.xz
update tests
Signed-off-by: Richard Qin <richard.qin.x@gmail.com>
-rw-r--r--lab03/tests/Makefile2
-rw-r--r--lab03/tests/test.c110
-rw-r--r--lab03/vec.h4
3 files changed, 110 insertions, 6 deletions
diff --git a/lab03/tests/Makefile b/lab03/tests/Makefile
index 78c49f6..90c4453 100644
--- a/lab03/tests/Makefile
+++ b/lab03/tests/Makefile
@@ -8,7 +8,7 @@ TARGET := test_runner
all: $(TARGET)
-$(TARGET): test.c ../container_of.h ../list.h ../vec.h ../polynomial.h
+$(TARGET): test.c ../container_of.h ../list.h ../vec.h ../polynomial.h ../expression.h
$(CC) $(CFLAGS) -I.. test.c $(LDLIBS) -o $@
run: $(TARGET)
diff --git a/lab03/tests/test.c b/lab03/tests/test.c
index 1fc3cab..c10b130 100644
--- a/lab03/tests/test.c
+++ b/lab03/tests/test.c
@@ -2,6 +2,7 @@
/* Copyright (C) 2026 Richard Qin */
#include "container_of.h"
+#include "expression.h"
#include "list.h"
#include "polynomial.h"
#include "vec.h"
@@ -354,6 +355,98 @@ static bool test_poly_list_arithmetic_and_alias(void)
return true;
}
+static bool test_expression_nested_precedence_and_variables(void)
+{
+ struct expression_context context;
+ struct expression_error error;
+ double result;
+ expression_init(&context);
+ CHECK(expression_collect_variables(&context,
+ "-(A + 2.5) * (B - (-C + 4)) / 2", &error));
+ CHECK(context.variables.size == 3);
+ CHECK(expression_set_variable(&context, "A", 3.0));
+ CHECK(expression_set_variable(&context, "B", 10.0));
+ CHECK(expression_set_variable(&context, "C", 2.0));
+ CHECK(expression_eval(&context,
+ "-(A + 2.5) * (B - (-C + 4)) / 2", &result, &error));
+ CHECK(fabs(result + 22.0) < 1e-12);
+ expression_destroy(&context);
+ return true;
+}
+
+static bool test_expression_variable_dedup_and_update(void)
+{
+ struct expression_context context;
+ struct expression_error error;
+ double result;
+ expression_init(&context);
+ CHECK(expression_collect_variables(&context,
+ "A1 + A1 * B2 - (B2 / 2) + C", &error));
+ CHECK(context.variables.size == 3);
+ CHECK(expression_set_variable(&context, "A1", 4.0));
+ CHECK(expression_set_variable(&context, "B2", 6.0));
+ CHECK(expression_set_variable(&context, "C", 1.0));
+ CHECK(expression_eval(&context,
+ "A1 + A1 * B2 - (B2 / 2) + C", &result, &error));
+ CHECK(fabs(result - 26.0) < 1e-12);
+ CHECK(expression_set_variable(&context, "B2", 10.0));
+ CHECK(expression_eval(&context,
+ "A1 + A1 * B2 - (B2 / 2) + C", &result, &error));
+ CHECK(result == 40.0);
+ expression_destroy(&context);
+ return true;
+}
+
+static bool test_expression_unary_and_decimal_values(void)
+{
+ struct expression_context context;
+ struct expression_error error;
+ double result;
+ expression_init(&context);
+ CHECK(expression_collect_variables(&context,
+ "--5 + -(+2.5) * (3 - -1) + .5", &error));
+ CHECK(expression_eval(&context,
+ "--5 + -(+2.5) * (3 - -1) + .5", &result, &error));
+ CHECK(fabs(result + 4.5) < 1e-12);
+ expression_destroy(&context);
+ return true;
+}
+
+static bool test_expression_deep_parentheses_and_associativity(void)
+{
+ struct expression_context context;
+ struct expression_error error;
+ double result;
+ expression_init(&context);
+ CHECK(expression_collect_variables(&context,
+ "1 - 2 - 3 + 4 * (5 + (6 - (7 - 8)))", &error));
+ CHECK(expression_eval(&context,
+ "1 - 2 - 3 + 4 * (5 + (6 - (7 - 8)))", &result, &error));
+ CHECK(fabs(result - 44.0) < 1e-12);
+ expression_destroy(&context);
+ return true;
+}
+
+static bool test_expression_error_paths(void)
+{
+ struct expression_context context;
+ struct expression_error error;
+ double result;
+ expression_init(&context);
+ CHECK(expression_collect_variables(&context, "X + 1", &error));
+ CHECK(!expression_eval(&context, "X + 1", &result, &error));
+ CHECK(error.code == EXPRESSION_UNSET_VARIABLE);
+ CHECK(expression_set_variable(&context, "X", 2.0));
+ CHECK(!expression_eval(&context, "X / (3 - 3)", &result, &error));
+ CHECK(error.code == EXPRESSION_DIVISION_BY_ZERO);
+ CHECK(!expression_eval(&context, "X + (2 * 3", &result, &error));
+ CHECK(error.code == EXPRESSION_PAREN_ERROR);
+ CHECK(!expression_collect_variables(&context, "X @ 2", &error));
+ CHECK(error.code == EXPRESSION_SYNTAX_ERROR);
+ expression_destroy(&context);
+ return true;
+}
+
struct test_case {
const char *name;
bool (*function)(void);
@@ -375,11 +468,21 @@ int main(void)
test_poly_list_normalization_and_conversion },
{ "poly_list arithmetic and alias",
test_poly_list_arithmetic_and_alias },
+ { "expression nested precedence and variables",
+ test_expression_nested_precedence_and_variables },
+ { "expression variable dedup and update",
+ test_expression_variable_dedup_and_update },
+ { "expression unary and decimal values",
+ test_expression_unary_and_decimal_values },
+ { "expression deep parentheses and associativity",
+ test_expression_deep_parentheses_and_associativity },
+ { "expression error paths", test_expression_error_paths },
};
size_t failures = 0;
for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) {
- printf("[%zu/10] %s\n", i + 1, tests[i].name);
+ printf("[%zu/%zu] %s\n", i + 1,
+ sizeof(tests) / sizeof(tests[0]), tests[i].name);
if (tests[i].function()) {
puts(" passed");
} else {
@@ -387,7 +490,8 @@ int main(void)
puts(" failed");
}
}
- printf("\n%zu/10 tests passed\n",
- sizeof(tests) / sizeof(tests[0]) - failures);
+ printf("\n%zu/%zu tests passed\n",
+ sizeof(tests) / sizeof(tests[0]) - failures,
+ sizeof(tests) / sizeof(tests[0]));
return failures == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
diff --git a/lab03/vec.h b/lab03/vec.h
index b751b80..d62df76 100644
--- a/lab03/vec.h
+++ b/lab03/vec.h
@@ -24,12 +24,12 @@
* `data` points to storage for at most `capacity` elements. The first
* `size` positions contain valid elements.
*/
-struct vec {
+typedef struct vec {
void *data;
size_t size;
size_t capacity;
size_t elem_size;
-};
+} vec;
/**
* @brief Compares two elements.