Allow script arrays to hold any value type, add script engine tests, archive old rpg code

Remove the per-array type category so arrays can mix types like structs.
Add 13 passing and 125 expected-failure duskscript test fixtures with a
table-driven runner. Also includes the in-progress entity/physics and
archive moves from the working tree.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
YourWishesandClaude Sonnet 5.5 committed 2026-10-14 23:25:26 -05:00
1 parent 5c259e46e2
commit f6b884bf7f
710 files changed
+6172 -27594

No files matched your search

+233
View File
@@ -55,6 +55,98 @@ static void test_scriptNumbersAreAllFloats(void **state) {
consoleDispose();
}
// Runs a packed fixture and describes where it stopped, for a failure message
static scriptresult_t duskscript_test_run(const char_t *path, scripterror_t *error) {
scriptresult_t result;
consoleInit();
assert_int_equal(errorIsOk(scriptInit()), true);
result = scriptRuntimeRunFile(SCRIPT.runtime, path, true, error);
return result;
}
static void duskscript_test_finish(void) {
assert_int_equal(errorIsOk(scriptDispose()), true);
consoleDispose();
}
// A pass fixture is a script of assert() calls, it has to run to the end
static void test_scriptPasses(void **state) {
const char_t *path = (const char_t *)*state;
scripterror_t error;
scriptresult_t result;
uint8_t i;
memoryZero(&error, sizeof(error));
result = duskscript_test_run(path, &error);
duskscript_test_finish();
if(result != SCRIPT_OK) {
print_error("%s stopped with code %d: %s\n", path, (int)result, error.message);
for(i = 0; i < error.frameCount; i++) {
print_error(" at %s %s:%d:%d\n", error.frames[i].name, error.frames[i].file, (int)error.frames[i].line, (int)error.frames[i].column);
}
}
assert_int_equal(result, SCRIPT_OK);
}
// A fail fixture does one thing the engine has to refuse, as a runtime error
// with a message, and not a crash, a hang, or going on as if nothing happened
static void test_scriptFailsWithRuntimeError(void **state) {
const char_t *path = (const char_t *)*state;
scripterror_t error;
scriptresult_t result;
memoryZero(&error, sizeof(error));
result = duskscript_test_run(path, &error);
duskscript_test_finish();
if(result != SCRIPT_ERROR_RUNTIME) print_error("%s was expected to fail but gave code %d\n", path, (int)result);
assert_int_equal(result, SCRIPT_ERROR_RUNTIME);
assert_true(error.message[0] != '\0');
}
// The engine is still usable after a script failed: a run after an error
static void test_scriptRunsAfterAnError(void **state) {
scripterror_t error;
memoryZero(&error, sizeof(error));
consoleInit();
assert_int_equal(errorIsOk(scriptInit()), true);
assert_int_equal(scriptRuntimeRunFile(SCRIPT.runtime, "fail_assert_false.dsb", true, &error), SCRIPT_ERROR_RUNTIME);
assert_int_equal(scriptRuntimeRunFile(SCRIPT.runtime, "fail_div_zero.dsb", true, &error), SCRIPT_ERROR_RUNTIME);
assert_int_equal(scriptRuntimeRunFile(SCRIPT.runtime, "pass_arrays.dsb", true, &error), SCRIPT_OK);
assert_int_equal(scriptRuntimeRunFile(SCRIPT.runtime, "pass_structs.dsb", true, &error), SCRIPT_OK);
duskscript_test_finish();
}
// The same script can run again and again, nothing of it is left behind
static void test_scriptRunsRepeatedly(void **state) {
scripterror_t error;
int32_t i;
memoryZero(&error, sizeof(error));
consoleInit();
assert_int_equal(errorIsOk(scriptInit()), true);
for(i = 0; i < 20; i++) {
assert_int_equal(scriptRuntimeRunFile(SCRIPT.runtime, "pass_mixed.dsb", true, &error), SCRIPT_OK);
assert_int_equal(scriptRuntimeRunFile(SCRIPT.runtime, "pass_strings.dsb", true, &error), SCRIPT_OK);
}
duskscript_test_finish();
}
// A file that does not exist is an error, not a crash
static void test_scriptMissingFile(void **state) {
scripterror_t error;
memoryZero(&error, sizeof(error));
consoleInit();
assert_int_equal(errorIsOk(scriptInit()), true);
assert_int_not_equal(scriptRuntimeRunFile(SCRIPT.runtime, "no_such_script.dsb", true, &error), SCRIPT_OK);
duskscript_test_finish();
}
#define SCRIPT_PASS(name) { "pass_" #name, test_scriptPasses, NULL, NULL, (void *)("pass_" #name ".dsb") }
#define SCRIPT_FAIL(name) { "fail_" #name, test_scriptFailsWithRuntimeError, NULL, NULL, (void *)("fail_" #name ".dsb") }
// Fixtures load through the asset system now, so ASSET needs a real zip
// behind it - open the packed test.dsk directly rather than the full
// assetInit()/assetInitPlatform(), which expects a real launched engine.
@@ -76,6 +168,147 @@ int main(void) {
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_scriptRunsAndPrintsToConsole),
cmocka_unit_test(test_scriptNumbersAreAllFloats),
cmocka_unit_test(test_scriptRunsAfterAnError),
cmocka_unit_test(test_scriptRunsRepeatedly),
cmocka_unit_test(test_scriptMissingFile),
SCRIPT_PASS(arrays),
SCRIPT_PASS(async),
SCRIPT_PASS(constants),
SCRIPT_PASS(control),
SCRIPT_PASS(conversion),
SCRIPT_PASS(functions),
SCRIPT_PASS(logic),
SCRIPT_PASS(math),
SCRIPT_PASS(mixed),
SCRIPT_PASS(numbers),
SCRIPT_PASS(strings),
SCRIPT_PASS(structs),
SCRIPT_PASS(types),
SCRIPT_FAIL(abs_string),
SCRIPT_FAIL(add_array),
SCRIPT_FAIL(add_bool),
SCRIPT_FAIL(add_null),
SCRIPT_FAIL(array_too_long),
SCRIPT_FAIL(array_too_long_merge),
SCRIPT_FAIL(assert_empty_string),
SCRIPT_FAIL(assert_false),
SCRIPT_FAIL(assert_no_arguments),
SCRIPT_FAIL(assert_null),
SCRIPT_FAIL(assert_zero),
SCRIPT_FAIL(async_error),
SCRIPT_FAIL(async_error_nested),
SCRIPT_FAIL(bitwise_string),
SCRIPT_FAIL(call_missing_member),
SCRIPT_FAIL(call_null),
SCRIPT_FAIL(call_number),
SCRIPT_FAIL(callback_raises),
SCRIPT_FAIL(chr_fraction),
SCRIPT_FAIL(chr_too_big),
SCRIPT_FAIL(chr_zero),
SCRIPT_FAIL(compare_mixed),
SCRIPT_FAIL(compare_null),
SCRIPT_FAIL(compare_strings),
SCRIPT_FAIL(const_array_alias_assign),
SCRIPT_FAIL(const_array_pop),
SCRIPT_FAIL(const_array_push),
SCRIPT_FAIL(const_array_sort),
SCRIPT_FAIL(const_struct_alias_assign),
SCRIPT_FAIL(const_struct_alias_new_key),
SCRIPT_FAIL(contains_number),
SCRIPT_FAIL(deepclone_cycle),
SCRIPT_FAIL(deepclone_struct_cycle),
SCRIPT_FAIL(div_zero),
SCRIPT_FAIL(error_after_output),
SCRIPT_FAIL(error_in_loop),
SCRIPT_FAIL(error_inside_function),
SCRIPT_FAIL(error_inside_nested_calls),
SCRIPT_FAIL(fill_negative),
SCRIPT_FAIL(fill_too_many),
SCRIPT_FAIL(filter_non_function),
SCRIPT_FAIL(flatten_non_array_items),
SCRIPT_FAIL(foreach_null),
SCRIPT_FAIL(foreach_number),
SCRIPT_FAIL(foreach_struct),
SCRIPT_FAIL(include_missing),
SCRIPT_FAIL(index_assign_negative),
SCRIPT_FAIL(index_assign_oob),
SCRIPT_FAIL(index_fraction),
SCRIPT_FAIL(index_negative),
SCRIPT_FAIL(index_number),
SCRIPT_FAIL(index_read_oob),
SCRIPT_FAIL(index_string_key),
SCRIPT_FAIL(indexof_non_array),
SCRIPT_FAIL(indexof_string_long_needle),
SCRIPT_FAIL(insert_negative),
SCRIPT_FAIL(insert_out_of_range),
SCRIPT_FAIL(insertarr_out_of_range),
SCRIPT_FAIL(invert_string),
SCRIPT_FAIL(join_non_array),
SCRIPT_FAIL(join_non_string_separator),
SCRIPT_FAIL(len_null),
SCRIPT_FAIL(len_number),
SCRIPT_FAIL(map_non_array),
SCRIPT_FAIL(map_non_function),
SCRIPT_FAIL(member_of_null),
SCRIPT_FAIL(member_of_number),
SCRIPT_FAIL(min_string),
SCRIPT_FAIL(missing_parameter),
SCRIPT_FAIL(missing_second_parameter),
SCRIPT_FAIL(mod_zero),
SCRIPT_FAIL(mul_string),
SCRIPT_FAIL(mutual_recursion_too_deep),
SCRIPT_FAIL(negate_string),
SCRIPT_FAIL(pop_string),
SCRIPT_FAIL(pow_fraction),
SCRIPT_FAIL(push_string),
SCRIPT_FAIL(rand_backwards),
SCRIPT_FAIL(rand_empty_range),
SCRIPT_FAIL(rand_fraction),
SCRIPT_FAIL(randf_empty_range),
SCRIPT_FAIL(recursion_too_deep),
SCRIPT_FAIL(reduce_non_function),
SCRIPT_FAIL(reverse_string),
SCRIPT_FAIL(sort_bad_comparer_result),
SCRIPT_FAIL(sort_mixed),
SCRIPT_FAIL(sort_non_array),
SCRIPT_FAIL(sort_structs),
SCRIPT_FAIL(splice_negative_count),
SCRIPT_FAIL(splice_out_of_range),
SCRIPT_FAIL(split_non_string),
SCRIPT_FAIL(sqrt_negative),
SCRIPT_FAIL(string_assign),
SCRIPT_FAIL(string_index_oob),
SCRIPT_FAIL(string_too_long),
SCRIPT_FAIL(struct_number_key),
SCRIPT_FAIL(struct_number_key_assign),
SCRIPT_FAIL(struct_too_many_keys),
SCRIPT_FAIL(sub_string),
SCRIPT_FAIL(subarr_backwards),
SCRIPT_FAIL(subarr_negative),
SCRIPT_FAIL(subarr_past_end),
SCRIPT_FAIL(subarr_string_past_end),
SCRIPT_FAIL(tobase_bad_base),
SCRIPT_FAIL(tobase_big_base),
SCRIPT_FAIL(tobase_fraction),
SCRIPT_FAIL(tobase_string),
SCRIPT_FAIL(tobool_invalid),
SCRIPT_FAIL(tobool_null),
SCRIPT_FAIL(tonum_bad_digit),
SCRIPT_FAIL(tonum_bool),
SCRIPT_FAIL(tonum_empty),
SCRIPT_FAIL(tonum_invalid),
SCRIPT_FAIL(tonum_too_big),
SCRIPT_FAIL(tonum_trailing),
SCRIPT_FAIL(too_few_arguments),
SCRIPT_FAIL(too_many_arguments),
SCRIPT_FAIL(tostr_decimals_on_string),
SCRIPT_FAIL(tostr_negative_decimals),
SCRIPT_FAIL(tostr_too_many_decimals),
SCRIPT_FAIL(trim_null),
SCRIPT_FAIL(undefined_function_call),
SCRIPT_FAIL(undefined_variable_read),
SCRIPT_FAIL(undefined_variable_write),
SCRIPT_FAIL(upcase_number),
};
return cmocka_run_group_tests(tests, duskscript_test_setup, duskscript_test_teardown);
}