4
mirror of https://gitlab.com/zephray/glider.git synced 2026-08-06 03:30:32 +00:00
Files
glider/fw/User/tests/test_config_menu.c
2026-07-04 07:20:36 -04:00

378 lines
12 KiB
C

#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include "config.h"
#include "ui_menu.h"
#define ASSERT_TRUE(expr) do { \
if (!(expr)) { \
printf("ASSERT_TRUE failed at %s:%d: %s\n", __FILE__, __LINE__, #expr); \
return 1; \
} \
} while (0)
#define ASSERT_EQ(expected, actual) do { \
long long exp__ = (long long)(expected); \
long long act__ = (long long)(actual); \
if (exp__ != act__) { \
printf("ASSERT_EQ failed at %s:%d: expected %lld got %lld\n", \
__FILE__, __LINE__, exp__, act__); \
return 1; \
} \
} while (0)
static int test_config_defaults_match_button_design(void) {
config_init();
ASSERT_EQ(CONFIG_SCHEMA_VERSION, config.schema_version);
ASSERT_EQ(ACT_NEXT_MODE, config.button_actions[0]);
ASSERT_EQ(ACT_PREV_MODE, config.button_actions[1]);
ASSERT_EQ(ACT_OPEN_SETTINGS, config.button_actions[2]);
ASSERT_EQ(ACT_POFF, config.button_actions[3]);
ASSERT_EQ(ACT_CLEAR, config.button_actions[4]);
ASSERT_EQ(ACT_TOGGLE_AC, config.button_actions[5]);
ASSERT_EQ(AC_OFF, config.autoclear_mode);
ASSERT_EQ(AC_5MIN, config.autoclear_interval);
ASSERT_EQ(AC_THRES_MED, config.autoclear_threshold);
ASSERT_EQ(0, config.osd_scale_2x);
return 0;
}
static int test_legacy_config_validation_repairs_appended_fields(void) {
config_init();
config.schema_version = 0;
for (int i = 0; i < CONFIG_BUTTON_BINDING_COUNT; i++)
config.button_actions[i] = -99;
config.update_mode = -1;
config.lightness = 99;
config.contrast = -99;
config.reserved_tone = 99;
config.autoclear_mode = 99;
config.autoclear_interval = 99;
config.autoclear_threshold = 99;
config.osd_scale_2x = 99;
config_validate_loaded(offsetof(config_t, schema_version));
ASSERT_EQ(CONFIG_SCHEMA_VERSION, config.schema_version);
ASSERT_EQ(ACT_NEXT_MODE, config.button_actions[0]);
ASSERT_EQ(ACT_PREV_MODE, config.button_actions[1]);
ASSERT_EQ(ACT_OPEN_SETTINGS, config.button_actions[2]);
ASSERT_EQ(UM_FAST_MONO_BAYER, config.update_mode);
ASSERT_EQ(0, config.lightness);
ASSERT_EQ(0, config.contrast);
ASSERT_EQ(0, config.reserved_tone);
ASSERT_EQ(AC_OFF, config.autoclear_mode);
ASSERT_EQ(AC_5MIN, config.autoclear_interval);
ASSERT_EQ(AC_THRES_MED, config.autoclear_threshold);
ASSERT_EQ(0, config.osd_scale_2x);
return 0;
}
static int test_legacy_config_validation_defaults_osd_scale_from_ppi(void) {
config_init();
config.hact = 1600;
config.vact = 1200;
config.size_x_mm = 135;
config.size_y_mm = 101;
config.osd_scale_2x = 0;
config_validate_loaded(offsetof(config_t, osd_scale_2x));
ASSERT_EQ(1, config.osd_scale_2x);
config_init();
config.hact = 1600;
config.vact = 1200;
config.size_x_mm = 270;
config.size_y_mm = 203;
config.osd_scale_2x = 1;
config_validate_loaded(offsetof(config_t, osd_scale_2x));
ASSERT_EQ(0, config.osd_scale_2x);
return 0;
}
static int test_config_validation_repairs_invalid_values(void) {
config_init();
config.button_actions[0] = -1;
config.button_actions[1] = ACT_COUNT;
config.update_mode = 999;
config.input_sel = 99;
config.lightness = 4;
config.contrast = -4;
config.reserved_tone = 4;
config.autoclear_mode = 99;
config.autoclear_interval = -1;
config.autoclear_threshold = 99;
config.osd_scale_2x = 99;
config_validate_loaded(sizeof(config));
ASSERT_EQ(ACT_NEXT_MODE, config.button_actions[0]);
ASSERT_EQ(ACT_PREV_MODE, config.button_actions[1]);
ASSERT_EQ(UM_FAST_MONO_BAYER, config.update_mode);
ASSERT_EQ(INPUT_SEL_AUTO, config.input_sel);
ASSERT_EQ(3, config.lightness);
ASSERT_EQ(-1, config.contrast);
ASSERT_EQ(0, config.reserved_tone);
ASSERT_EQ(AC_OFF, config.autoclear_mode);
ASSERT_EQ(AC_5MIN, config.autoclear_interval);
ASSERT_EQ(AC_THRES_MED, config.autoclear_threshold);
ASSERT_EQ(1, config.osd_scale_2x);
config.osd_scale_2x = -1;
config_validate_loaded(sizeof(config));
ASSERT_EQ(0, config.osd_scale_2x);
config.contrast = 99;
config_validate_loaded(sizeof(config));
ASSERT_EQ(6, config.contrast);
return 0;
}
static int test_menu_navigation_commits_and_cancels_modal_values(void) {
ui_menu_t menu;
config_init();
ui_menu_init(&menu, &config);
ASSERT_EQ(UI_MENU_DEPTH_CATEGORIES, ui_menu_depth(&menu));
ASSERT_TRUE(ui_menu_selected_label(&menu) != NULL);
ASSERT_EQ('D', ui_menu_selected_label(&menu)[0]);
ui_menu_handle(&menu, UI_MENU_EVENT_ENTER);
ASSERT_EQ(UI_MENU_DEPTH_ITEMS, ui_menu_depth(&menu));
ASSERT_EQ('U', ui_menu_selected_label(&menu)[0]);
ui_menu_handle(&menu, UI_MENU_EVENT_ENTER);
ASSERT_EQ(UI_MENU_DEPTH_MODAL, ui_menu_depth(&menu));
ASSERT_EQ(UM_FAST_MONO_BAYER, config.update_mode);
ui_menu_handle(&menu, UI_MENU_EVENT_NEXT);
ASSERT_TRUE(ui_menu_modal_value_label(&menu) != NULL);
ASSERT_EQ('W', ui_menu_modal_value_label(&menu)[0]);
ui_menu_handle(&menu, UI_MENU_EVENT_BACK);
ASSERT_EQ(UI_MENU_DEPTH_ITEMS, ui_menu_depth(&menu));
ASSERT_EQ(UM_FAST_MONO_BAYER, config.update_mode);
ui_menu_handle(&menu, UI_MENU_EVENT_ENTER);
ui_menu_handle(&menu, UI_MENU_EVENT_NEXT);
ui_menu_handle(&menu, UI_MENU_EVENT_ENTER);
ASSERT_EQ(UI_MENU_DEPTH_ITEMS, ui_menu_depth(&menu));
ASSERT_EQ(UM_FAST_MONO_BLUE_NOISE, config.update_mode);
return 0;
}
static int test_menu_snapshot_exposes_visible_rows_and_values(void) {
ui_menu_t menu;
config_init();
ui_menu_init(&menu, &config);
ASSERT_EQ(3, ui_menu_row_count(&menu));
ASSERT_EQ('D', ui_menu_row_label(&menu, 0)[0]);
ASSERT_EQ('B', ui_menu_row_label(&menu, 1)[0]);
ASSERT_EQ(1, ui_menu_row_selected(&menu, 0));
ui_menu_handle(&menu, UI_MENU_EVENT_ENTER);
ASSERT_EQ(6, ui_menu_row_count(&menu));
ASSERT_EQ('U', ui_menu_row_label(&menu, 0)[0]);
ASSERT_EQ('B', ui_menu_row_value(&menu, 0)[0]);
ASSERT_EQ(1, ui_menu_row_selected(&menu, 0));
ASSERT_EQ('L', ui_menu_row_label(&menu, 1)[0]);
ASSERT_EQ('C', ui_menu_row_label(&menu, 2)[0]);
ASSERT_EQ('A', ui_menu_row_label(&menu, 3)[0]);
ui_menu_handle(&menu, UI_MENU_EVENT_ENTER);
ASSERT_EQ(4, ui_menu_row_count(&menu));
ASSERT_EQ('B', ui_menu_row_label(&menu, 0)[0]);
ASSERT_EQ('W', ui_menu_row_label(&menu, 1)[0]);
ASSERT_EQ(1, ui_menu_row_selected(&menu, 0));
return 0;
}
static int test_menu_scalar_modal_commits_lightness(void) {
ui_menu_t menu;
config_init();
ui_menu_init(&menu, &config);
ui_menu_handle(&menu, UI_MENU_EVENT_ENTER);
ui_menu_handle(&menu, UI_MENU_EVENT_NEXT);
ASSERT_EQ('L', ui_menu_selected_label(&menu)[0]);
ui_menu_handle(&menu, UI_MENU_EVENT_ENTER);
ASSERT_EQ(UI_MENU_DEPTH_MODAL, ui_menu_depth(&menu));
ui_menu_handle(&menu, UI_MENU_EVENT_NEXT);
ASSERT_TRUE(ui_menu_modal_value_label(&menu) != NULL);
ASSERT_EQ('1', ui_menu_modal_value_label(&menu)[0]);
ui_menu_handle(&menu, UI_MENU_EVENT_ENTER);
ASSERT_EQ(UI_MENU_DEPTH_ITEMS, ui_menu_depth(&menu));
ASSERT_EQ(1, config.lightness);
return 0;
}
static int test_menu_scalar_modal_exposes_preview_value_without_commit(void) {
ui_menu_t menu;
config_init();
ui_menu_init(&menu, &config);
ui_menu_handle(&menu, UI_MENU_EVENT_ENTER);
ui_menu_handle(&menu, UI_MENU_EVENT_NEXT);
ui_menu_handle(&menu, UI_MENU_EVENT_ENTER);
ASSERT_EQ(1, ui_menu_modal_is_tone(&menu));
ASSERT_EQ(1, ui_menu_modal_tone_target(&menu));
ASSERT_EQ(0, ui_menu_modal_preview_value(&menu));
ui_menu_handle(&menu, UI_MENU_EVENT_NEXT);
ASSERT_EQ(1, ui_menu_modal_preview_value(&menu));
ASSERT_EQ(0, config.lightness);
ui_menu_handle(&menu, UI_MENU_EVENT_BACK);
ASSERT_EQ(UI_MENU_DEPTH_ITEMS, ui_menu_depth(&menu));
ASSERT_EQ(0, config.lightness);
return 0;
}
static int test_menu_contrast_uses_lcd_monitor_range(void) {
ui_menu_t menu;
config_init();
ui_menu_init(&menu, &config);
ui_menu_handle(&menu, UI_MENU_EVENT_ENTER);
ui_menu_handle(&menu, UI_MENU_EVENT_NEXT);
ui_menu_handle(&menu, UI_MENU_EVENT_NEXT);
ASSERT_EQ('C', ui_menu_selected_label(&menu)[0]);
ui_menu_handle(&menu, UI_MENU_EVENT_ENTER);
ASSERT_EQ(UI_MENU_DEPTH_MODAL, ui_menu_depth(&menu));
ASSERT_EQ(1, ui_menu_modal_is_tone(&menu));
ASSERT_EQ(2, ui_menu_modal_tone_target(&menu));
ASSERT_EQ(8, ui_menu_modal_count(&menu));
ASSERT_EQ(1, ui_menu_modal_index(&menu));
ASSERT_EQ(0, ui_menu_modal_preview_value(&menu));
ui_menu_handle(&menu, UI_MENU_EVENT_PREV);
ASSERT_EQ(-1, ui_menu_modal_preview_value(&menu));
ui_menu_handle(&menu, UI_MENU_EVENT_PREV);
ASSERT_EQ(6, ui_menu_modal_preview_value(&menu));
return 0;
}
static int test_menu_exposes_category_and_scalar_modal_metadata(void) {
ui_menu_t menu;
config_init();
ui_menu_init(&menu, &config);
ASSERT_EQ('D', ui_menu_category_label(&menu)[0]);
ASSERT_EQ(0, ui_menu_modal_is_scalar(&menu));
ui_menu_handle(&menu, UI_MENU_EVENT_ENTER);
ASSERT_EQ('D', ui_menu_category_label(&menu)[0]);
ui_menu_handle(&menu, UI_MENU_EVENT_NEXT);
ui_menu_handle(&menu, UI_MENU_EVENT_ENTER);
ASSERT_EQ(UI_MENU_DEPTH_MODAL, ui_menu_depth(&menu));
ASSERT_EQ(1, ui_menu_modal_is_scalar(&menu));
ASSERT_EQ(7, ui_menu_modal_count(&menu));
ASSERT_EQ(3, ui_menu_modal_index(&menu));
ASSERT_EQ('0', ui_menu_modal_value_label(&menu)[0]);
return 0;
}
static int test_menu_viewport_moves_lazily(void) {
ASSERT_EQ(0, ui_menu_viewport_first(0, 0, 7, 4));
ASSERT_EQ(0, ui_menu_viewport_first(0, 3, 7, 4));
ASSERT_EQ(1, ui_menu_viewport_first(0, 4, 7, 4));
ASSERT_EQ(4, ui_menu_viewport_first(4, 7, 8, 4));
ASSERT_EQ(4, ui_menu_viewport_first(4, 6, 8, 4));
ASSERT_EQ(3, ui_menu_viewport_first(4, 3, 8, 4));
ASSERT_EQ(0, ui_menu_viewport_first(4, 0, 3, 4));
return 0;
}
static int test_menu_autoclear_threshold_uses_frequency_labels(void) {
ui_menu_t menu;
config_init();
ui_menu_init(&menu, &config);
ui_menu_handle(&menu, UI_MENU_EVENT_ENTER);
for (int i = 0; i < 5; i++)
ui_menu_handle(&menu, UI_MENU_EVENT_NEXT);
ASSERT_EQ('C', ui_menu_selected_label(&menu)[0]);
ui_menu_handle(&menu, UI_MENU_EVENT_ENTER);
ASSERT_EQ(UI_MENU_DEPTH_MODAL, ui_menu_depth(&menu));
ASSERT_EQ('S', ui_menu_row_label(&menu, 0)[0]);
ASSERT_EQ('O', ui_menu_row_label(&menu, 1)[0]);
ASSERT_EQ('O', ui_menu_row_label(&menu, 2)[0]);
ASSERT_EQ('f', ui_menu_row_label(&menu, 2)[1]);
return 0;
}
static int test_system_menu_exposes_osd_scale_setting(void) {
ui_menu_t menu;
config_init();
ui_menu_init(&menu, &config);
ui_menu_handle(&menu, UI_MENU_EVENT_NEXT);
ui_menu_handle(&menu, UI_MENU_EVENT_NEXT);
ASSERT_EQ('S', ui_menu_selected_label(&menu)[0]);
ui_menu_handle(&menu, UI_MENU_EVENT_ENTER);
ASSERT_EQ(UI_MENU_DEPTH_ITEMS, ui_menu_depth(&menu));
ASSERT_EQ('I', ui_menu_row_label(&menu, 0)[0]);
ASSERT_EQ('O', ui_menu_row_label(&menu, 1)[0]);
ASSERT_EQ('1', ui_menu_row_value(&menu, 1)[0]);
ui_menu_handle(&menu, UI_MENU_EVENT_NEXT);
ui_menu_handle(&menu, UI_MENU_EVENT_ENTER);
ASSERT_EQ(UI_MENU_DEPTH_MODAL, ui_menu_depth(&menu));
ASSERT_EQ(2, ui_menu_row_count(&menu));
ASSERT_EQ('1', ui_menu_row_label(&menu, 0)[0]);
ASSERT_EQ('2', ui_menu_row_label(&menu, 1)[0]);
ui_menu_handle(&menu, UI_MENU_EVENT_NEXT);
ui_menu_handle(&menu, UI_MENU_EVENT_ENTER);
ASSERT_EQ(1, config.osd_scale_2x);
return 0;
}
int main(void) {
int rc = 0;
rc |= test_config_defaults_match_button_design();
rc |= test_legacy_config_validation_repairs_appended_fields();
rc |= test_legacy_config_validation_defaults_osd_scale_from_ppi();
rc |= test_config_validation_repairs_invalid_values();
rc |= test_menu_navigation_commits_and_cancels_modal_values();
rc |= test_menu_snapshot_exposes_visible_rows_and_values();
rc |= test_menu_scalar_modal_commits_lightness();
rc |= test_menu_scalar_modal_exposes_preview_value_without_commit();
rc |= test_menu_contrast_uses_lcd_monitor_range();
rc |= test_menu_exposes_category_and_scalar_modal_metadata();
rc |= test_menu_viewport_moves_lazily();
rc |= test_menu_autoclear_threshold_uses_frequency_labels();
rc |= test_system_menu_exposes_osd_scale_setting();
return rc;
}