234 lines
10 KiB
C
234 lines
10 KiB
C
|
|
#include "test_utils.h"
|
||
|
|
#include "../loader/loader.h"
|
||
|
|
|
||
|
|
static RavaNativeValue_t test_add(RavaNativeValue_t *args, size_t arg_count, void *user_data) {
|
||
|
|
(void)user_data;
|
||
|
|
if (arg_count != 2) return rava_native_int(0);
|
||
|
|
int32_t a = args[0].data.int_val;
|
||
|
|
int32_t b = args[1].data.int_val;
|
||
|
|
return rava_native_int(a + b);
|
||
|
|
}
|
||
|
|
|
||
|
|
static RavaNativeValue_t test_multiply(RavaNativeValue_t *args, size_t arg_count, void *user_data) {
|
||
|
|
(void)user_data;
|
||
|
|
if (arg_count != 2) return rava_native_int(0);
|
||
|
|
int32_t a = args[0].data.int_val;
|
||
|
|
int32_t b = args[1].data.int_val;
|
||
|
|
return rava_native_int(a * b);
|
||
|
|
}
|
||
|
|
|
||
|
|
static RavaNativeValue_t test_greet(RavaNativeValue_t *args, size_t arg_count, void *user_data) {
|
||
|
|
(void)user_data;
|
||
|
|
if (arg_count != 1) return rava_native_string("");
|
||
|
|
const char *name = args[0].data.string_val;
|
||
|
|
char buffer[256];
|
||
|
|
snprintf(buffer, sizeof(buffer), "Hello, %s!", name ? name : "World");
|
||
|
|
return rava_native_string(buffer);
|
||
|
|
}
|
||
|
|
|
||
|
|
UnittestTestResult_t* test_registry_create_destroy(void) {
|
||
|
|
UNITTEST_BEGIN_TEST("TestLoader", "test_registry_create_destroy");
|
||
|
|
|
||
|
|
RavaNativeRegistry_t *registry = rava_native_registry_create();
|
||
|
|
UNITTEST_ASSERT_NOT_NULL(_unittest_result, registry, "registry should be created");
|
||
|
|
UNITTEST_ASSERT_EQUAL_INT(_unittest_result, 0, (int)registry->library_count, "library count should be 0");
|
||
|
|
UNITTEST_ASSERT_EQUAL_INT(_unittest_result, 0, (int)registry->cache_count, "cache count should be 0");
|
||
|
|
|
||
|
|
rava_native_registry_destroy(registry);
|
||
|
|
UNITTEST_ASSERT_PASS(_unittest_result, "registry destroyed without crash");
|
||
|
|
|
||
|
|
UNITTEST_END_TEST();
|
||
|
|
}
|
||
|
|
|
||
|
|
UnittestTestResult_t* test_register_method(void) {
|
||
|
|
UNITTEST_BEGIN_TEST("TestLoader", "test_register_method");
|
||
|
|
|
||
|
|
RavaNativeRegistry_t *registry = rava_native_registry_create();
|
||
|
|
|
||
|
|
RavaNativeType_e params[] = {RAVA_NATIVE_INT, RAVA_NATIVE_INT};
|
||
|
|
bool result = rava_native_register_method(registry, "Math", "add",
|
||
|
|
RAVA_NATIVE_INT, params, 2,
|
||
|
|
test_add, NULL);
|
||
|
|
UNITTEST_ASSERT_TRUE(_unittest_result, result, "method registration should succeed");
|
||
|
|
UNITTEST_ASSERT_EQUAL_INT(_unittest_result, 1, (int)registry->cache_count, "cache count should be 1");
|
||
|
|
|
||
|
|
rava_native_registry_destroy(registry);
|
||
|
|
|
||
|
|
UNITTEST_END_TEST();
|
||
|
|
}
|
||
|
|
|
||
|
|
UnittestTestResult_t* test_find_method(void) {
|
||
|
|
UNITTEST_BEGIN_TEST("TestLoader", "test_find_method");
|
||
|
|
|
||
|
|
RavaNativeRegistry_t *registry = rava_native_registry_create();
|
||
|
|
|
||
|
|
RavaNativeType_e params[] = {RAVA_NATIVE_INT, RAVA_NATIVE_INT};
|
||
|
|
rava_native_register_method(registry, "Math", "add",
|
||
|
|
RAVA_NATIVE_INT, params, 2,
|
||
|
|
test_add, NULL);
|
||
|
|
|
||
|
|
RavaNativeMethod_t *method = rava_native_find_method(registry, "Math", "add");
|
||
|
|
UNITTEST_ASSERT_NOT_NULL(_unittest_result, method, "method should be found");
|
||
|
|
UNITTEST_ASSERT_EQUAL_STR(_unittest_result, "Math", method->class_name, "class name should match");
|
||
|
|
UNITTEST_ASSERT_EQUAL_STR(_unittest_result, "add", method->method_name, "method name should match");
|
||
|
|
UNITTEST_ASSERT_EQUAL_INT(_unittest_result, RAVA_NATIVE_INT, (int)method->return_type, "return type should be INT");
|
||
|
|
UNITTEST_ASSERT_EQUAL_INT(_unittest_result, 2, (int)method->param_count, "param count should be 2");
|
||
|
|
|
||
|
|
RavaNativeMethod_t *not_found = rava_native_find_method(registry, "Math", "subtract");
|
||
|
|
UNITTEST_ASSERT_NULL(_unittest_result, not_found, "non-existent method should return NULL");
|
||
|
|
|
||
|
|
rava_native_registry_destroy(registry);
|
||
|
|
|
||
|
|
UNITTEST_END_TEST();
|
||
|
|
}
|
||
|
|
|
||
|
|
UnittestTestResult_t* test_invoke_method(void) {
|
||
|
|
UNITTEST_BEGIN_TEST("TestLoader", "test_invoke_method");
|
||
|
|
|
||
|
|
RavaNativeRegistry_t *registry = rava_native_registry_create();
|
||
|
|
|
||
|
|
RavaNativeType_e params[] = {RAVA_NATIVE_INT, RAVA_NATIVE_INT};
|
||
|
|
rava_native_register_method(registry, "Math", "add",
|
||
|
|
RAVA_NATIVE_INT, params, 2,
|
||
|
|
test_add, NULL);
|
||
|
|
|
||
|
|
RavaNativeMethod_t *method = rava_native_find_method(registry, "Math", "add");
|
||
|
|
|
||
|
|
RavaNativeValue_t args[2];
|
||
|
|
args[0] = rava_native_int(10);
|
||
|
|
args[1] = rava_native_int(20);
|
||
|
|
|
||
|
|
RavaNativeValue_t result = rava_native_invoke(method, args, 2);
|
||
|
|
UNITTEST_ASSERT_EQUAL_INT(_unittest_result, RAVA_NATIVE_INT, (int)result.type, "result should be INT");
|
||
|
|
UNITTEST_ASSERT_EQUAL_INT(_unittest_result, 30, result.data.int_val, "10 + 20 = 30");
|
||
|
|
|
||
|
|
rava_native_registry_destroy(registry);
|
||
|
|
|
||
|
|
UNITTEST_END_TEST();
|
||
|
|
}
|
||
|
|
|
||
|
|
UnittestTestResult_t* test_multiple_methods(void) {
|
||
|
|
UNITTEST_BEGIN_TEST("TestLoader", "test_multiple_methods");
|
||
|
|
|
||
|
|
RavaNativeRegistry_t *registry = rava_native_registry_create();
|
||
|
|
|
||
|
|
RavaNativeType_e int_params[] = {RAVA_NATIVE_INT, RAVA_NATIVE_INT};
|
||
|
|
rava_native_register_method(registry, "Math", "add",
|
||
|
|
RAVA_NATIVE_INT, int_params, 2,
|
||
|
|
test_add, NULL);
|
||
|
|
rava_native_register_method(registry, "Math", "multiply",
|
||
|
|
RAVA_NATIVE_INT, int_params, 2,
|
||
|
|
test_multiply, NULL);
|
||
|
|
|
||
|
|
RavaNativeType_e string_params[] = {RAVA_NATIVE_STRING};
|
||
|
|
rava_native_register_method(registry, "Greeter", "greet",
|
||
|
|
RAVA_NATIVE_STRING, string_params, 1,
|
||
|
|
test_greet, NULL);
|
||
|
|
|
||
|
|
UNITTEST_ASSERT_EQUAL_INT(_unittest_result, 3, (int)registry->cache_count, "should have 3 methods");
|
||
|
|
|
||
|
|
RavaNativeMethod_t *add = rava_native_find_method(registry, "Math", "add");
|
||
|
|
RavaNativeMethod_t *mul = rava_native_find_method(registry, "Math", "multiply");
|
||
|
|
RavaNativeMethod_t *greet = rava_native_find_method(registry, "Greeter", "greet");
|
||
|
|
|
||
|
|
UNITTEST_ASSERT_NOT_NULL(_unittest_result, add, "add should exist");
|
||
|
|
UNITTEST_ASSERT_NOT_NULL(_unittest_result, mul, "multiply should exist");
|
||
|
|
UNITTEST_ASSERT_NOT_NULL(_unittest_result, greet, "greet should exist");
|
||
|
|
|
||
|
|
RavaNativeValue_t args[2];
|
||
|
|
args[0] = rava_native_int(5);
|
||
|
|
args[1] = rava_native_int(7);
|
||
|
|
|
||
|
|
RavaNativeValue_t add_result = rava_native_invoke(add, args, 2);
|
||
|
|
UNITTEST_ASSERT_EQUAL_INT(_unittest_result, 12, add_result.data.int_val, "5 + 7 = 12");
|
||
|
|
|
||
|
|
RavaNativeValue_t mul_result = rava_native_invoke(mul, args, 2);
|
||
|
|
UNITTEST_ASSERT_EQUAL_INT(_unittest_result, 35, mul_result.data.int_val, "5 * 7 = 35");
|
||
|
|
|
||
|
|
rava_native_registry_destroy(registry);
|
||
|
|
|
||
|
|
UNITTEST_END_TEST();
|
||
|
|
}
|
||
|
|
|
||
|
|
UnittestTestResult_t* test_value_conversion(void) {
|
||
|
|
UNITTEST_BEGIN_TEST("TestLoader", "test_value_conversion");
|
||
|
|
|
||
|
|
RavaValue_t int_val = rava_value_int(42);
|
||
|
|
RavaNativeValue_t native_int = rava_value_to_native(int_val);
|
||
|
|
UNITTEST_ASSERT_EQUAL_INT(_unittest_result, RAVA_NATIVE_INT, (int)native_int.type, "type should be INT");
|
||
|
|
UNITTEST_ASSERT_EQUAL_INT(_unittest_result, 42, native_int.data.int_val, "value should be 42");
|
||
|
|
|
||
|
|
RavaValue_t back_to_rava = rava_native_to_value(native_int);
|
||
|
|
UNITTEST_ASSERT_EQUAL_INT(_unittest_result, RAVA_VAL_INT, (int)back_to_rava.type, "type should be RAVA_VAL_INT");
|
||
|
|
UNITTEST_ASSERT_EQUAL_INT(_unittest_result, 42, back_to_rava.data.int_val, "value should be 42");
|
||
|
|
|
||
|
|
RavaValue_t long_val = rava_value_long(123456789012LL);
|
||
|
|
RavaNativeValue_t native_long = rava_value_to_native(long_val);
|
||
|
|
UNITTEST_ASSERT_EQUAL_INT(_unittest_result, RAVA_NATIVE_LONG, (int)native_long.type, "type should be LONG");
|
||
|
|
UNITTEST_ASSERT_EQUAL_LONG(_unittest_result, 123456789012LL, native_long.data.long_val, "long value should match");
|
||
|
|
|
||
|
|
RavaValue_t bool_val = rava_value_boolean(true);
|
||
|
|
RavaNativeValue_t native_bool = rava_value_to_native(bool_val);
|
||
|
|
UNITTEST_ASSERT_EQUAL_INT(_unittest_result, RAVA_NATIVE_BOOLEAN, (int)native_bool.type, "type should be BOOLEAN");
|
||
|
|
UNITTEST_ASSERT_TRUE(_unittest_result, native_bool.data.bool_val, "bool should be true");
|
||
|
|
|
||
|
|
UNITTEST_END_TEST();
|
||
|
|
}
|
||
|
|
|
||
|
|
UnittestTestResult_t* test_string_method(void) {
|
||
|
|
UNITTEST_BEGIN_TEST("TestLoader", "test_string_method");
|
||
|
|
|
||
|
|
RavaNativeRegistry_t *registry = rava_native_registry_create();
|
||
|
|
|
||
|
|
RavaNativeType_e string_params[] = {RAVA_NATIVE_STRING};
|
||
|
|
rava_native_register_method(registry, "Greeter", "greet",
|
||
|
|
RAVA_NATIVE_STRING, string_params, 1,
|
||
|
|
test_greet, NULL);
|
||
|
|
|
||
|
|
RavaNativeMethod_t *greet = rava_native_find_method(registry, "Greeter", "greet");
|
||
|
|
UNITTEST_ASSERT_NOT_NULL(_unittest_result, greet, "greet should exist");
|
||
|
|
|
||
|
|
RavaNativeValue_t args[1];
|
||
|
|
args[0] = rava_native_string("Rava");
|
||
|
|
|
||
|
|
RavaNativeValue_t result = rava_native_invoke(greet, args, 1);
|
||
|
|
UNITTEST_ASSERT_EQUAL_INT(_unittest_result, RAVA_NATIVE_STRING, (int)result.type, "result should be STRING");
|
||
|
|
UNITTEST_ASSERT_EQUAL_STR(_unittest_result, "Hello, Rava!", result.data.string_val, "greeting should match");
|
||
|
|
|
||
|
|
free(args[0].data.string_val);
|
||
|
|
free(result.data.string_val);
|
||
|
|
rava_native_registry_destroy(registry);
|
||
|
|
|
||
|
|
UNITTEST_END_TEST();
|
||
|
|
}
|
||
|
|
|
||
|
|
int main(int argc, char **argv) {
|
||
|
|
UnittestConfig_t *config = unittest_config_create();
|
||
|
|
config->verbosity = 2;
|
||
|
|
|
||
|
|
if (argc > 1 && strcmp(argv[1], "--json") == 0) {
|
||
|
|
config->output_format = UNITTEST_FORMAT_JSON;
|
||
|
|
config->use_colors = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
UnittestTestSuite_t *suite = unittest_test_suite_create("Dynamic Library Loader Tests");
|
||
|
|
|
||
|
|
UnittestTestCase_t *tc = unittest_test_case_create("TestLoader");
|
||
|
|
unittest_test_case_add_result(tc, test_registry_create_destroy());
|
||
|
|
unittest_test_case_add_result(tc, test_register_method());
|
||
|
|
unittest_test_case_add_result(tc, test_find_method());
|
||
|
|
unittest_test_case_add_result(tc, test_invoke_method());
|
||
|
|
unittest_test_case_add_result(tc, test_multiple_methods());
|
||
|
|
unittest_test_case_add_result(tc, test_value_conversion());
|
||
|
|
unittest_test_case_add_result(tc, test_string_method());
|
||
|
|
unittest_test_suite_add_test_case(suite, tc);
|
||
|
|
|
||
|
|
unittest_generate_report(suite, config);
|
||
|
|
|
||
|
|
int failures = suite->total_failed + suite->total_errors;
|
||
|
|
unittest_test_suite_destroy(suite);
|
||
|
|
unittest_config_destroy(config);
|
||
|
|
|
||
|
|
return failures > 0 ? 1 : 0;
|
||
|
|
}
|