diff options
Diffstat (limited to 'source/test.c')
| -rw-r--r-- | source/test.c | 107 |
1 files changed, 103 insertions, 4 deletions
diff --git a/source/test.c b/source/test.c index 2013e04..c59deaf 100644 --- a/source/test.c +++ b/source/test.c @@ -4,9 +4,11 @@ #include <wiiuse/wpad.h> #include <stdlib.h> #include <stdarg.h> +#include <inttypes.h> #define TEST_INTERNAL #include "test.h" +#include "term.h" typedef u32 et_test_status; @@ -188,14 +190,34 @@ static const struct et_state state_begin_testing_struct = { const struct et_state *et_state_begin_testing = &state_begin_testing_struct; +struct summ_test_plan_private { + struct et_test_plan *plan; + size_t selected_test; +}; + +#define SUMM_MENU_ROWS 3 + +static void summ_test_print_menu(struct summ_test_plan_private *priv) { + const struct et_test *test = priv->plan->tests[priv->selected_test].test; + + fputs(TERM_CUR_UP(SUMM_MENU_ROWS), stdout); + puts(TERM_CLEARLINE "Press A to test again. Press HOME/START to exit."); + puts(TERM_CLEARLINE "Press +/X to show output for [DL/DR]:"); + printf(TERM_CLEARLINE "%s\n", test->name); +} + static int summ_test_plan_init(const struct et_state *state, void *state_data, et_state_init_data init_data) { - struct et_test_plan *ptest_plan = (*(struct et_test_plan **)state_data = init_data.p); + struct summ_test_plan_private *priv = state_data; + struct et_test_plan *ptest_plan = init_data.p; size_t passed = 0; size_t failed = 0; size_t errored = 0; size_t skipped = 0; size_t unknown = 0; + priv->plan = ptest_plan; + priv->selected_test = 0; + for (size_t i = 0; i < ptest_plan->num_tests; ++i) { switch (TEST_STATUS_GET_TYPE(ptest_plan->tests[i].status)) { case TEST_SPASS: ++passed; break; @@ -208,12 +230,15 @@ static int summ_test_plan_init(const struct et_state *state, void *state_data, e printf("\nTesting complete.\nPASS: %zu, FAIL: %zu, ERROR: %zu, SKIP: %zu, UNK: %zu\n\n", passed, failed, errored, skipped, unknown); - puts("Press A to test again. Press HOME/START to exit."); + for (int i = 0; i < SUMM_MENU_ROWS; ++i) putchar('\n'); + summ_test_print_menu(priv); return 0; } static int summ_test_plan_tick(const struct et_state *state, void *state_data, struct et_next_state *next_state) { + struct summ_test_plan_private *priv = state_data; + u32 wpad_buttons = WPAD_ButtonsDown(0); u32 pad_buttons = PAD_ButtonsDown(0); @@ -228,11 +253,45 @@ static int summ_test_plan_tick(const struct et_state *state, void *state_data, s exit(0); } + if (wpad_buttons & WPAD_BUTTON_LEFT || pad_buttons & PAD_BUTTON_LEFT) { + if (priv->selected_test > 0) { + --priv->selected_test; + } else { + priv->selected_test = priv->plan->num_tests - 1; + } + + summ_test_print_menu(priv); + } + + if (wpad_buttons & WPAD_BUTTON_RIGHT || pad_buttons & PAD_BUTTON_RIGHT) { + if (priv->selected_test < priv->plan->num_tests - 1) { + ++priv->selected_test; + } else { + priv->selected_test = 0; + } + + summ_test_print_menu(priv); + } + + if (wpad_buttons & WPAD_BUTTON_1 || pad_buttons & PAD_BUTTON_X) { + struct et_test_plan_entry *entry = priv->plan->tests + priv->selected_test; + printf("\nExtended status for %s:\n", entry->test->name); + if (entry->ext_status) { + puts(entry->ext_status); + } else { + puts("(no status)"); + } + + for (int i = 0; i < SUMM_MENU_ROWS + 1; ++i) putchar('\n'); + summ_test_print_menu(priv); + } + return 0; } static void summ_test_plan_cleanup(const struct et_state *state, void *state_data) { - struct et_test_plan *ptest_plan = *(void **)state_data; + struct summ_test_plan_private *priv = state_data; + struct et_test_plan *ptest_plan = priv->plan; for (size_t i = 0; i < ptest_plan->num_tests; ++i) { et_test_plan_entry_cleanup(ptest_plan->tests + i); @@ -243,7 +302,7 @@ static void summ_test_plan_cleanup(const struct et_state *state, void *state_dat } static const struct et_state summ_test_plan_struct = { - .private_size = sizeof(struct et_test_plan *), + .private_size = sizeof(struct summ_test_plan_private), .init_f = summ_test_plan_init, .tick_f = summ_test_plan_tick, .cleanup_f = summ_test_plan_cleanup @@ -352,3 +411,43 @@ const char *et_test_get_status_mnemonic(et_test_status status) { return "UNKS"; } } + +et_test_status test_exi_readwrite(struct et_test_plan *plan, void *data, size_t data_sz, et_test_error base) { + struct et_test_plan_entry *cur = test_current(plan); + int chan = plan->exi_channel; + et_test_status status = TEST_PASS; + s32 exi_res; + + if ((exi_res = EXI_Lock(chan, EXI_DEVICE_0, NULL)) <= 0) { + status = TEST_ERROR(base); + test_plan_entry_set_error(cur, "failed to lock EXI channel: %" PRId32, exi_res); + goto fail_lock; + } + + if ((exi_res = EXI_Select(chan, EXI_DEVICE_0, EXI_SPEED32MHZ)) <= 0) { + status = TEST_ERROR(base + 1); + test_plan_entry_set_error(cur, "failed to select EXI channel: %" PRId32, exi_res); + goto fail_select; + } + + if ((exi_res = EXI_Imm(chan, data, data_sz, EXI_READWRITE, NULL)) <= 0) { + status = TEST_ERROR(base + 2); + test_plan_entry_set_error(cur, "failed to send EXI data: %" PRId32, exi_res); + goto fail_data; + } + + if ((exi_res = EXI_Sync(chan)) <= 0) { + status = TEST_ERROR(base + 3); + test_plan_entry_set_error(cur, "failed to complete transfer: %" PRId32, exi_res); + goto fail_data; + } + +fail_data: + EXI_Deselect(chan); + +fail_select: + EXI_Unlock(chan); + +fail_lock: + return status; +} |
