some random fixes

This commit is contained in:
2026-08-08 01:18:07 -05:00
parent 36fb359aa2
commit 128f9ab9d4
15 changed files with 1041 additions and 52 deletions
+184
View File
@@ -26,6 +26,19 @@ static errorret_t helper_chain(void) {
errorOk();
}
// Helper that throws with no format arguments (exercises the zero-arg
// ##__VA_ARGS__ branch of the errorThrow macro).
static errorret_t helper_throwNoArgs(void) {
errorThrow("Simple message with no arguments");
}
static const errorcode_t CUSTOM_ERROR_CODE = 7;
// Helper that throws with an explicit, non-default error code.
static errorret_t helper_throwWithCode(void) {
errorThrowWithCode(CUSTOM_ERROR_CODE, "Custom error %d", 99);
}
static void test_errorThrow(void **state) {
errorret_t ret = helper_throw();
@@ -84,6 +97,159 @@ static void test_errorChain(void **state) {
assert_int_equal(memoryGetAllocatedCount(), 0);
}
static void test_errorThrowNoFormatArguments(void **state) {
errorret_t ret = helper_throwNoArgs();
assert_int_not_equal(ret.code, ERROR_OK);
assert_string_equal(ret.state->message, "Simple message with no arguments");
errorCatch(ret);
assert_int_equal(memoryGetAllocatedCount(), 0);
}
static void test_errorThrowWithCode(void **state) {
errorret_t ret = helper_throwWithCode();
// The explicit code must round-trip, not just "not OK".
assert_int_equal(ret.code, CUSTOM_ERROR_CODE);
assert_non_null(strstr(ret.state->message, "99"));
errorCatch(ret);
assert_int_equal(memoryGetAllocatedCount(), 0);
}
static void test_errorChainOkRetvalPassesThroughUnchanged(void **state) {
// errorChainImpl's own early-return branch, called directly since the
// errorChain macro pre-filters on code != ERROR_OK before ever reaching it.
errorret_t ok = helper_ok();
errorret_t chained = errorChainImpl(ok, __FILE__, __func__, __LINE__);
assert_int_equal(chained.code, ERROR_OK);
assert_null(chained.state);
assert_int_equal(memoryGetAllocatedCount(), 0);
}
static void test_errorPrintOkRetvalPassesThroughUnchanged(void **state) {
errorret_t ok = helper_ok();
errorret_t printed = errorPrint(ok);
assert_int_equal(printed.code, ERROR_OK);
assert_null(printed.state);
assert_int_equal(memoryGetAllocatedCount(), 0);
}
static void test_errorPrintErrorRetvalPassesThroughUnchanged(void **state) {
errorret_t ret = helper_throw();
errorret_t printed = errorPrint(ret);
// errorPrint logs, but must not mutate or consume the error state.
assert_int_equal(printed.code, ret.code);
assert_ptr_equal(printed.state, ret.state);
assert_non_null(printed.state->message);
errorCatch(printed);
assert_int_equal(memoryGetAllocatedCount(), 0);
}
// --- Negative / misuse paths ---
//
// These bypass the errorThrow/errorChain/errorOk macros to call the *Impl
// functions directly with invalid arguments, since correct macro usage can
// never produce these states (they always supply a valid &ERROR_STATE,
// __FILE__, __func__, __LINE__).
static void test_errorThrowImplNullStateAsserts(void **state) {
expect_assert_failure(
errorThrowImpl(NULL, ERROR_NOT_OK, __FILE__, __func__, __LINE__, "msg")
);
}
static void test_errorThrowImplOkCodeAsserts(void **state) {
errorstate_t local = { 0 };
expect_assert_failure(
errorThrowImpl(&local, ERROR_OK, __FILE__, __func__, __LINE__, "msg")
);
}
static void test_errorThrowImplNullFileAsserts(void **state) {
errorstate_t local = { 0 };
expect_assert_failure(
errorThrowImpl(&local, ERROR_NOT_OK, NULL, __func__, __LINE__, "msg")
);
}
static void test_errorThrowImplNullFunctionAsserts(void **state) {
errorstate_t local = { 0 };
expect_assert_failure(
errorThrowImpl(&local, ERROR_NOT_OK, __FILE__, NULL, __LINE__, "msg")
);
}
static void test_errorThrowImplNegativeLineAsserts(void **state) {
errorstate_t local = { 0 };
expect_assert_failure(
errorThrowImpl(&local, ERROR_NOT_OK, __FILE__, __func__, -1, "msg")
);
}
static void test_errorThrowImplNullMessageAsserts(void **state) {
errorstate_t local = { 0 };
expect_assert_failure(
errorThrowImpl(&local, ERROR_NOT_OK, __FILE__, __func__, __LINE__, NULL)
);
}
static void test_errorOkAssertsIfPreviousErrorNotCaught(void **state) {
// Simulate a caller forgetting to errorCatch a previous throw: leave
// ERROR_STATE.code non-OK, then errorOk() must assert rather than silently
// returning an OK that papers over the uncaught error.
assert_int_equal(ERROR_STATE.code, ERROR_OK);
ERROR_STATE.code = ERROR_NOT_OK;
expect_assert_failure(helper_ok());
// Nothing was actually allocated for this fake corruption - just restore
// the global so later tests see a clean state.
ERROR_STATE.code = ERROR_OK;
}
static void test_errorChainImplNullStateAsserts(void **state) {
errorret_t bad = { .code = ERROR_NOT_OK, .state = NULL };
expect_assert_failure(
errorChainImpl(bad, __FILE__, __func__, __LINE__)
);
}
static void test_errorChainImplNullMessageAsserts(void **state) {
errorstate_t local = { .code = ERROR_NOT_OK, .message = NULL, .lines = NULL };
errorret_t bad = { .code = ERROR_NOT_OK, .state = &local };
expect_assert_failure(
errorChainImpl(bad, __FILE__, __func__, __LINE__)
);
}
static void test_errorCatchNullStateAsserts(void **state) {
errorret_t bad = { .code = ERROR_NOT_OK, .state = NULL };
expect_assert_failure(errorCatch(bad));
}
static void test_errorCatchNullMessageAsserts(void **state) {
errorstate_t local = { .code = ERROR_NOT_OK, .message = NULL, .lines = NULL };
errorret_t bad = { .code = ERROR_NOT_OK, .state = &local };
expect_assert_failure(errorCatch(bad));
}
static void test_errorPrintNullStateAsserts(void **state) {
errorret_t bad = { .code = ERROR_NOT_OK, .state = NULL };
expect_assert_failure(errorPrint(bad));
}
static void test_errorPrintNullMessageAsserts(void **state) {
errorstate_t local = { .code = ERROR_NOT_OK, .message = NULL, .lines = NULL };
errorret_t bad = { .code = ERROR_NOT_OK, .state = &local };
expect_assert_failure(errorPrint(bad));
}
static void test_errorCatch_ok(void **state) {
// Catching an ok ret should be a no-op
errorret_t ret = helper_ok();
@@ -178,6 +344,24 @@ int main(void) {
cmocka_unit_test(test_errorOk),
cmocka_unit_test(test_errorIsOk),
cmocka_unit_test(test_errorChain),
cmocka_unit_test(test_errorThrowNoFormatArguments),
cmocka_unit_test(test_errorThrowWithCode),
cmocka_unit_test(test_errorChainOkRetvalPassesThroughUnchanged),
cmocka_unit_test(test_errorPrintOkRetvalPassesThroughUnchanged),
cmocka_unit_test(test_errorPrintErrorRetvalPassesThroughUnchanged),
cmocka_unit_test(test_errorThrowImplNullStateAsserts),
cmocka_unit_test(test_errorThrowImplOkCodeAsserts),
cmocka_unit_test(test_errorThrowImplNullFileAsserts),
cmocka_unit_test(test_errorThrowImplNullFunctionAsserts),
cmocka_unit_test(test_errorThrowImplNegativeLineAsserts),
cmocka_unit_test(test_errorThrowImplNullMessageAsserts),
cmocka_unit_test(test_errorOkAssertsIfPreviousErrorNotCaught),
cmocka_unit_test(test_errorChainImplNullStateAsserts),
cmocka_unit_test(test_errorChainImplNullMessageAsserts),
cmocka_unit_test(test_errorCatchNullStateAsserts),
cmocka_unit_test(test_errorCatchNullMessageAsserts),
cmocka_unit_test(test_errorPrintNullStateAsserts),
cmocka_unit_test(test_errorPrintNullMessageAsserts),
cmocka_unit_test(test_errorCatch_ok),
cmocka_unit_test(test_errorCatch_error),
cmocka_unit_test(test_error_thread_isolation),