summaryrefslogtreecommitdiff
path: root/tests/vb2_ui_action_tests.c
diff options
context:
space:
mode:
authorHsuan Ting Chen <roccochen@chromium.org>2020-05-12 11:08:11 +0800
committerCommit Bot <commit-bot@chromium.org>2020-05-14 08:37:16 +0000
commit21d119d81d7a76c63149acdb94c49ff882ce16f6 (patch)
treee5760e3e5ddf19b38511f330727449c510a3c101 /tests/vb2_ui_action_tests.c
parent92cb5fa717d99e9e2972b02541e0ad925dd35bae (diff)
downloadvboot-21d119d81d7a76c63149acdb94c49ff882ce16f6.tar.gz
vboot/ui: Split UI tests
Rearrange UI tests into three files: vb2_ui_utility_tests for utility functions and core UI functions, vb2_ui_action_tests for hooked actions, and vb2_ui_tests for UI entries. This CL does not add any extra tests. BRANCH=none BUG=b:156448738 TEST=make clean && make runtests TEST=make clean && DETACHABLE=1; make runtests Signed-off-by: Hsuan Ting Chen <roccochen@chromium.org> Change-Id: I36a0a43aa3295b06cf32446dcc107652d64d2b8f Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2198268 Reviewed-by: Joel Kitching <kitching@chromium.org>
Diffstat (limited to 'tests/vb2_ui_action_tests.c')
-rw-r--r--tests/vb2_ui_action_tests.c734
1 files changed, 734 insertions, 0 deletions
diff --git a/tests/vb2_ui_action_tests.c b/tests/vb2_ui_action_tests.c
new file mode 100644
index 00000000..dd87bc33
--- /dev/null
+++ b/tests/vb2_ui_action_tests.c
@@ -0,0 +1,734 @@
+/* Copyright 2020 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Tests for UI related actions.
+ */
+
+#include "2api.h"
+#include "2common.h"
+#include "2misc.h"
+#include "2nvstorage.h"
+#include "2ui.h"
+#include "2ui_private.h"
+#include "test_common.h"
+#include "vboot_kernel.h"
+
+/* Fixed value for ignoring some checks. */
+#define MOCK_IGNORE 0xffffu
+
+/* Mock screen index for testing screen utility functions. */
+#define MOCK_NO_SCREEN 0xef0
+#define MOCK_SCREEN_BASE 0xeff
+#define MOCK_SCREEN_MENU 0xfff
+#define MOCK_SCREEN_TARGET0 0xff0
+#define MOCK_SCREEN_TARGET1 0xff1
+#define MOCK_SCREEN_TARGET2 0xff2
+#define MOCK_SCREEN_TARGET3 0xff3
+#define MOCK_SCREEN_TARGET4 0xff4
+
+/* Mock data */
+struct display_call {
+ const struct vb2_screen_info *screen;
+ uint32_t locale_id;
+ uint32_t selected_item;
+ uint32_t disabled_item_mask;
+};
+
+static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
+ __attribute__((aligned(VB2_WORKBUF_ALIGN)));
+static struct vb2_context *ctx;
+static struct vb2_gbb_header gbb;
+
+static int mock_calls_until_shutdown;
+
+static struct vb2_ui_context mock_ui_context;
+static struct vb2_screen_state *mock_state;
+
+static struct display_call mock_displayed[64];
+static int mock_displayed_count;
+static int mock_displayed_i;
+
+static uint32_t mock_key[64];
+static int mock_key_trusted[64];
+static int mock_key_count;
+static int mock_key_total;
+
+static enum vb2_screen mock_get_screen_info_last;
+
+static vb2_error_t mock_vbtlk_retval;
+static uint32_t mock_vbtlk_expected_flag;
+
+/* Mock screens */
+const struct vb2_menu_item mock_empty_menu[] = {};
+struct vb2_screen_info mock_screen_blank = {
+ .id = VB2_SCREEN_BLANK,
+ .name = "mock_screen_blank",
+ .num_items = ARRAY_SIZE(mock_empty_menu),
+ .items = mock_empty_menu,
+};
+struct vb2_screen_info mock_screen_base = {
+ .id = MOCK_SCREEN_BASE,
+ .name = "mock_screen_base: menuless screen",
+ .num_items = ARRAY_SIZE(mock_empty_menu),
+ .items = mock_empty_menu,
+};
+struct vb2_menu_item mock_screen_menu_items[] = {
+ {
+ .text = "option 0",
+ .target = MOCK_SCREEN_TARGET0,
+ },
+ {
+ .text = "option 1",
+ .target = MOCK_SCREEN_TARGET1,
+ },
+ {
+ .text = "option 2",
+ .target = MOCK_SCREEN_TARGET2,
+ },
+ {
+ .text = "option 3",
+ .target = MOCK_SCREEN_TARGET3,
+ },
+ {
+ .text = "option 4 (no target)",
+ },
+};
+const struct vb2_screen_info mock_screen_menu = {
+ .id = MOCK_SCREEN_MENU,
+ .name = "mock_screen_menu: screen with 5 options",
+ .num_items = ARRAY_SIZE(mock_screen_menu_items),
+ .items = mock_screen_menu_items,
+};
+const struct vb2_screen_info mock_screen_target0 = {
+ .id = MOCK_SCREEN_TARGET0,
+ .name = "mock_screen_target0",
+ .num_items = ARRAY_SIZE(mock_empty_menu),
+ .items = mock_empty_menu,
+};
+const struct vb2_screen_info mock_screen_target1 = {
+ .id = MOCK_SCREEN_TARGET1,
+ .name = "mock_screen_target1",
+ .num_items = ARRAY_SIZE(mock_empty_menu),
+ .items = mock_empty_menu,
+};
+const struct vb2_screen_info mock_screen_target2 = {
+ .id = MOCK_SCREEN_TARGET2,
+ .name = "mock_screen_target2",
+ .num_items = ARRAY_SIZE(mock_empty_menu),
+ .items = mock_empty_menu,
+};
+const struct vb2_screen_info mock_screen_target3 = {
+ .id = MOCK_SCREEN_TARGET3,
+ .name = "mock_screen_target3",
+ .num_items = ARRAY_SIZE(mock_empty_menu),
+ .items = mock_empty_menu,
+};
+const struct vb2_screen_info mock_screen_target4 = {
+ .id = MOCK_SCREEN_TARGET4,
+ .name = "mock_screen_target4",
+ .num_items = ARRAY_SIZE(mock_empty_menu),
+ .items = mock_empty_menu,
+};
+
+/* Mock actions */
+static uint32_t global_action_called;
+static vb2_error_t global_action_countdown(struct vb2_ui_context *ui)
+{
+ if (++global_action_called >= 10)
+ return VB2_SUCCESS;
+ return VB2_REQUEST_UI_CONTINUE;
+}
+
+static vb2_error_t global_action_change_screen(struct vb2_ui_context *ui)
+{
+ change_screen(ui, MOCK_SCREEN_BASE);
+ return VB2_REQUEST_UI_CONTINUE;
+}
+
+static void screen_state_eq(const struct vb2_screen_state *state,
+ enum vb2_screen screen,
+ uint32_t selected_item,
+ uint32_t disabled_item_mask)
+{
+ if (screen != MOCK_IGNORE) {
+ if (state->screen == NULL)
+ TEST_TRUE(0, " state.screen does not exist");
+ else
+ TEST_EQ(state->screen->id, screen, " state.screen");
+ }
+ if (selected_item != MOCK_IGNORE)
+ TEST_EQ(state->selected_item,
+ selected_item, " state.selected_item");
+ if (disabled_item_mask != MOCK_IGNORE)
+ TEST_EQ(state->disabled_item_mask,
+ disabled_item_mask, " state.disabled_item_mask");
+}
+
+static void add_mock_key(uint32_t press, int trusted)
+{
+ if (mock_key_total >= ARRAY_SIZE(mock_key) ||
+ mock_key_total >= ARRAY_SIZE(mock_key_trusted)) {
+ TEST_TRUE(0, " mock_key ran out of entries!");
+ return;
+ }
+
+ mock_key[mock_key_total] = press;
+ mock_key_trusted[mock_key_total] = trusted;
+ mock_key_total++;
+}
+
+static void add_mock_keypress(uint32_t press)
+{
+ add_mock_key(press, 0);
+}
+
+
+static void set_mock_vbtlk(vb2_error_t retval, uint32_t get_info_flags)
+{
+ mock_vbtlk_retval = retval;
+ mock_vbtlk_expected_flag = get_info_flags;
+}
+
+static void displayed_eq(const char *text,
+ enum vb2_screen screen,
+ uint32_t locale_id,
+ uint32_t selected_item,
+ uint32_t disabled_item_mask)
+{
+ char text_buf[256];
+
+ if (mock_displayed_i >= mock_displayed_count) {
+ sprintf(text_buf, " missing screen %s", text);
+ TEST_TRUE(0, text_buf);
+ return;
+ }
+
+ if (screen != MOCK_IGNORE) {
+ sprintf(text_buf, " screen of %s", text);
+ TEST_EQ(mock_displayed[mock_displayed_i].screen->id, screen,
+ text_buf);
+ }
+ if (locale_id != MOCK_IGNORE) {
+ sprintf(text_buf, " locale_id of %s", text);
+ TEST_EQ(mock_displayed[mock_displayed_i].locale_id, locale_id,
+ text_buf);
+ }
+ if (selected_item != MOCK_IGNORE) {
+ sprintf(text_buf, " selected_item of %s", text);
+ TEST_EQ(mock_displayed[mock_displayed_i].selected_item,
+ selected_item, text_buf);
+ }
+ if (disabled_item_mask != MOCK_IGNORE) {
+ sprintf(text_buf, " disabled_item_mask of %s", text);
+ TEST_EQ(mock_displayed[mock_displayed_i].disabled_item_mask,
+ disabled_item_mask, text_buf);
+ }
+ mock_displayed_i++;
+}
+
+static void displayed_no_extra(void)
+{
+ if (mock_displayed_i == 0)
+ TEST_EQ(mock_displayed_count, 0, " no screen");
+ else
+ TEST_EQ(mock_displayed_count, mock_displayed_i,
+ " no extra screens");
+}
+
+/* Reset mock data (for use before each test) */
+static void reset_common_data(void)
+{
+ TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
+ "vb2api_init failed");
+
+ memset(&gbb, 0, sizeof(gbb));
+
+ vb2_nv_init(ctx);
+
+ /* For shutdown_required */
+ mock_calls_until_shutdown = 10;
+
+ /* For try_recovery_action */
+ invalid_disk_last = -1;
+
+ /* Mock ui_context based on mock screens */
+ mock_ui_context = (struct vb2_ui_context){
+ .ctx = ctx,
+ .root_screen = &mock_screen_blank,
+ .state = (struct vb2_screen_state){
+ .screen = &mock_screen_blank,
+ .selected_item = 0,
+ .disabled_item_mask = 0,
+ },
+ .locale_id = 0,
+ .key = 0,
+
+ };
+ mock_state = &mock_ui_context.state;
+
+ /* For vb2ex_display_ui */
+ memset(mock_displayed, 0, sizeof(mock_displayed));
+ mock_displayed_count = 0;
+ mock_displayed_i = 0;
+
+ /* For VbExKeyboardRead */
+ memset(mock_key, 0, sizeof(mock_key));
+ memset(mock_key_trusted, 0, sizeof(mock_key_trusted));
+ mock_key_count = 0;
+ mock_key_total = 0;
+
+ /* For global actions */
+ global_action_called = 0;
+
+ /* For vb2_get_screen_info */
+ mock_get_screen_info_last = -1;
+
+ /* For VbTryLoadKernel */
+ mock_vbtlk_retval = VB2_ERROR_MOCK;
+ mock_vbtlk_expected_flag = MOCK_IGNORE;
+}
+
+/* Mock functions */
+struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c)
+{
+ return &gbb;
+}
+
+uint32_t VbExIsShutdownRequested(void)
+{
+ if (mock_calls_until_shutdown < 0) /* Never request shutdown */
+ return 0;
+ if (mock_calls_until_shutdown == 0)
+ return 1;
+ mock_calls_until_shutdown--;
+
+ return 0;
+}
+
+const struct vb2_screen_info *vb2_get_screen_info(enum vb2_screen screen)
+{
+ mock_get_screen_info_last = screen;
+
+ switch ((int)screen) {
+ case VB2_SCREEN_BLANK:
+ return &mock_screen_blank;
+ case MOCK_SCREEN_BASE:
+ return &mock_screen_base;
+ case MOCK_SCREEN_MENU:
+ return &mock_screen_menu;
+ case MOCK_SCREEN_TARGET0:
+ return &mock_screen_target0;
+ case MOCK_SCREEN_TARGET1:
+ return &mock_screen_target1;
+ case MOCK_SCREEN_TARGET2:
+ return &mock_screen_target2;
+ case MOCK_SCREEN_TARGET3:
+ return &mock_screen_target3;
+ case MOCK_SCREEN_TARGET4:
+ return &mock_screen_target4;
+ case MOCK_NO_SCREEN:
+ return NULL;
+ default:
+ return &mock_screen_blank;
+ }
+}
+
+vb2_error_t vb2ex_display_ui(enum vb2_screen screen,
+ uint32_t locale_id,
+ uint32_t selected_item,
+ uint32_t disabled_item_mask)
+{
+ VB2_DEBUG("displayed %d: screen = %#x, locale_id = %u, "
+ "selected_item = %u, disabled_item_mask = %#x\n",
+ mock_displayed_count, screen, locale_id, selected_item,
+ disabled_item_mask);
+
+ if (mock_displayed_count >= ARRAY_SIZE(mock_displayed)) {
+ TEST_TRUE(0, " mock vb2ex_display_ui ran out of entries!");
+ return VB2_ERROR_MOCK;
+ }
+
+ mock_displayed[mock_displayed_count] = (struct display_call){
+ .screen = vb2_get_screen_info(screen),
+ .locale_id = locale_id,
+ .selected_item = selected_item,
+ .disabled_item_mask = disabled_item_mask,
+ };
+ mock_displayed_count++;
+
+ return VB2_SUCCESS;
+}
+
+uint32_t VbExKeyboardRead(void)
+{
+ return VbExKeyboardReadWithFlags(NULL);
+}
+
+uint32_t VbExKeyboardReadWithFlags(uint32_t *key_flags)
+{
+ if (mock_key_count < mock_key_total) {
+ if (key_flags != NULL) {
+ if (mock_key_trusted[mock_key_count])
+ *key_flags = VB_KEY_FLAG_TRUSTED_KEYBOARD;
+ else
+ *key_flags = 0;
+ }
+ return mock_key[mock_key_count++];
+ }
+
+ return 0;
+}
+
+vb2_error_t VbTryLoadKernel(struct vb2_context *c, uint32_t get_info_flags)
+{
+ TEST_EQ(mock_vbtlk_expected_flag, get_info_flags,
+ " unexpected get_info_flags");
+
+ return mock_vbtlk_retval;
+}
+
+/* Tests */
+static void menu_action_tests(void)
+{
+ int i, target_id;
+ char test_name[256];
+
+ VB2_DEBUG("Testing menu actions...\n");
+
+ /* Valid menu_up_action */
+ reset_common_data();
+ mock_state->screen = &mock_screen_menu;
+ mock_state->selected_item = 2;
+ mock_ui_context.key = VB_KEY_UP;
+ TEST_EQ(menu_up_action(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
+ "valid menu_up_action");
+ screen_state_eq(mock_state, MOCK_SCREEN_MENU, 1, MOCK_IGNORE);
+
+ /* Valid menu_up_action with mask */
+ reset_common_data();
+ mock_state->screen = &mock_screen_menu;
+ mock_state->selected_item = 2;
+ mock_state->disabled_item_mask = 0x0a; /* 0b01010 */
+ mock_ui_context.key = VB_KEY_UP;
+ TEST_EQ(menu_up_action(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
+ "valid menu_up_action with mask");
+ screen_state_eq(mock_state, MOCK_SCREEN_MENU, 0, MOCK_IGNORE);
+
+ /* Invalid menu_up_action (blocked) */
+ reset_common_data();
+ mock_state->screen = &mock_screen_menu;
+ mock_state->selected_item = 0;
+ mock_ui_context.key = VB_KEY_UP;
+ TEST_EQ(menu_up_action(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
+ "invalid menu_up_action (blocked)");
+ screen_state_eq(mock_state, MOCK_SCREEN_MENU, 0, MOCK_IGNORE);
+
+ /* Invalid menu_up_action (blocked by mask) */
+ reset_common_data();
+ mock_state->screen = &mock_screen_menu;
+ mock_state->selected_item = 2;
+ mock_state->disabled_item_mask = 0x0b; /* 0b01011 */
+ mock_ui_context.key = VB_KEY_UP;
+ TEST_EQ(menu_up_action(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
+ "invalid menu_up_action (blocked by mask)");
+ screen_state_eq(mock_state, MOCK_SCREEN_MENU, 2, MOCK_IGNORE);
+
+ /* Ignore volume-up when not DETACHABLE */
+ if (!DETACHABLE) {
+ reset_common_data();
+ mock_state->screen = &mock_screen_menu;
+ mock_state->selected_item = 2;
+ mock_ui_context.key = VB_BUTTON_VOL_UP_SHORT_PRESS;
+ TEST_EQ(menu_up_action(&mock_ui_context),
+ VB2_REQUEST_UI_CONTINUE,
+ "ignore volume-up when not DETACHABLE");
+ screen_state_eq(mock_state, MOCK_SCREEN_MENU, 2, MOCK_IGNORE);
+ }
+
+ /* Valid menu_down_action */
+ reset_common_data();
+ mock_state->screen = &mock_screen_menu;
+ mock_state->selected_item = 2;
+ mock_ui_context.key = VB_KEY_DOWN;
+ TEST_EQ(menu_down_action(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
+ "valid menu_down_action");
+ screen_state_eq(mock_state, MOCK_SCREEN_MENU, 3, MOCK_IGNORE);
+
+ /* Valid menu_down_action with mask */
+ reset_common_data();
+ mock_state->screen = &mock_screen_menu;
+ mock_state->selected_item = 2;
+ mock_state->disabled_item_mask = 0x0a; /* 0b01010 */
+ mock_ui_context.key = VB_KEY_DOWN;
+ TEST_EQ(menu_down_action(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
+ "valid menu_down_action with mask");
+ screen_state_eq(mock_state, MOCK_SCREEN_MENU, 4, MOCK_IGNORE);
+
+ /* Invalid menu_down_action (blocked) */
+ reset_common_data();
+ mock_state->screen = &mock_screen_menu;
+ mock_state->selected_item = 4;
+ mock_ui_context.key = VB_KEY_DOWN;
+ TEST_EQ(menu_down_action(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
+ "invalid menu_down_action (blocked)");
+ screen_state_eq(mock_state, MOCK_SCREEN_MENU, 4, MOCK_IGNORE);
+
+ /* Invalid menu_down_action (blocked by mask) */
+ reset_common_data();
+ mock_state->screen = &mock_screen_menu;
+ mock_state->selected_item = 2;
+ mock_state->disabled_item_mask = 0x1a; /* 0b11010 */
+ mock_ui_context.key = VB_KEY_DOWN;
+ TEST_EQ(menu_down_action(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
+ "invalid menu_down_action (blocked by mask)");
+ screen_state_eq(mock_state, MOCK_SCREEN_MENU, 2, MOCK_IGNORE);
+
+ /* Ignore volume-down when not DETACHABLE */
+ if (!DETACHABLE) {
+ reset_common_data();
+ mock_state->screen = &mock_screen_menu;
+ mock_state->selected_item = 2;
+ mock_ui_context.key = VB_BUTTON_VOL_DOWN_SHORT_PRESS;
+ TEST_EQ(menu_down_action(&mock_ui_context),
+ VB2_REQUEST_UI_CONTINUE,
+ "ignore volume-down when not DETACHABLE");
+ screen_state_eq(mock_state, MOCK_SCREEN_MENU, 2, MOCK_IGNORE);
+ }
+
+ /* menu_select_action with no item screen */
+ reset_common_data();
+ mock_state->screen = &mock_screen_base;
+ mock_ui_context.key = VB_KEY_ENTER;
+ TEST_EQ(menu_select_action(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
+ "menu_select_action with no item screen");
+ screen_state_eq(mock_state, MOCK_SCREEN_BASE, 0, MOCK_IGNORE);
+
+ /* Try to select target 0..3 */
+ for (i = 0; i <= 3; i++) {
+ sprintf(test_name, "select target %d", i);
+ target_id = MOCK_SCREEN_TARGET0 + i;
+ reset_common_data();
+ mock_state->screen = &mock_screen_menu;
+ mock_state->selected_item = i;
+ mock_ui_context.key = VB_KEY_ENTER;
+ TEST_EQ(menu_select_action(&mock_ui_context),
+ VB2_REQUEST_UI_CONTINUE, test_name);
+ screen_state_eq(mock_state, target_id, 0, MOCK_IGNORE);
+ }
+
+ /* Try to select no target item */
+ reset_common_data();
+ mock_state->screen = &mock_screen_menu;
+ mock_state->selected_item = 4;
+ mock_ui_context.key = VB_KEY_ENTER;
+ TEST_EQ(menu_select_action(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
+ "select no target");
+ screen_state_eq(mock_state, MOCK_SCREEN_MENU, 4, MOCK_IGNORE);
+
+ /* Ignore power button short press when not DETACHABLE */
+ if (!DETACHABLE) {
+ reset_common_data();
+ mock_state->screen = &mock_screen_menu;
+ mock_state->selected_item = 1;
+ mock_ui_context.key = VB_BUTTON_POWER_SHORT_PRESS;
+ TEST_EQ(menu_select_action(&mock_ui_context),
+ VB2_REQUEST_UI_CONTINUE,
+ "ignore power button short press when not DETACHABLE");
+ screen_state_eq(mock_state, MOCK_SCREEN_MENU, 1, MOCK_IGNORE);
+ }
+
+ /* vb2_ui_back_action */
+ reset_common_data();
+ mock_ui_context.key = VB_KEY_ESC;
+ TEST_EQ(vb2_ui_back_action(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
+ "vb2_ui_back_action");
+ screen_state_eq(mock_state, VB2_SCREEN_BLANK, 0, MOCK_IGNORE);
+
+ VB2_DEBUG("...done.\n");
+}
+
+static void ui_loop_tests(void)
+{
+ VB2_DEBUG("Testing ui_loop...\n");
+
+ /* Die if no root screen */
+ reset_common_data();
+ TEST_ABORT(ui_loop(ctx, MOCK_NO_SCREEN, NULL),
+ "die if no root screen");
+ displayed_no_extra();
+
+ /* Shutdown if requested */
+ reset_common_data();
+ TEST_EQ(ui_loop(ctx, MOCK_SCREEN_BASE, NULL),
+ VB2_REQUEST_SHUTDOWN, "shutdown if requested");
+ TEST_EQ(mock_calls_until_shutdown, 0, " used up shutdown request");
+ displayed_eq("mock_screen_base", MOCK_SCREEN_BASE, MOCK_IGNORE,
+ MOCK_IGNORE, MOCK_IGNORE);
+ displayed_no_extra();
+
+ /* Global action */
+ reset_common_data();
+ mock_calls_until_shutdown = -1;
+ TEST_EQ(ui_loop(ctx, VB2_SCREEN_BLANK, global_action_countdown),
+ VB2_SUCCESS, "global action");
+ TEST_EQ(global_action_called, 10, " global action called");
+
+ /* Global action can change screen */
+ reset_common_data();
+ TEST_EQ(ui_loop(ctx, VB2_SCREEN_BLANK, global_action_change_screen),
+ VB2_REQUEST_SHUTDOWN, "global action can change screen");
+ displayed_eq("pass", MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE,
+ MOCK_IGNORE);
+ displayed_eq("change to mock_screen_base", MOCK_IGNORE, MOCK_IGNORE,
+ MOCK_IGNORE, MOCK_IGNORE);
+
+ /* KEY_UP, KEY_DOWN, and KEY_ENTER navigation */
+ reset_common_data();
+ add_mock_keypress(VB_KEY_UP); /* (blocked) */
+ add_mock_keypress(VB_KEY_DOWN);
+ add_mock_keypress(VB_KEY_DOWN);
+ add_mock_keypress(VB_KEY_DOWN);
+ add_mock_keypress(VB_KEY_DOWN);
+ add_mock_keypress(VB_KEY_DOWN); /* (blocked) */
+ add_mock_keypress(VB_KEY_UP);
+ add_mock_keypress(VB_KEY_ENTER);
+ TEST_EQ(ui_loop(ctx, MOCK_SCREEN_MENU, NULL),
+ VB2_REQUEST_SHUTDOWN, "KEY_UP, KEY_DOWN, and KEY_ENTER");
+ displayed_eq("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, 0,
+ MOCK_IGNORE);
+ displayed_eq("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, 1,
+ MOCK_IGNORE);
+ displayed_eq("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, 2,
+ MOCK_IGNORE);
+ displayed_eq("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, 3,
+ MOCK_IGNORE);
+ displayed_eq("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, 4,
+ MOCK_IGNORE);
+ displayed_eq("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, 3,
+ MOCK_IGNORE);
+ displayed_eq("mock_screen_target_3", MOCK_SCREEN_TARGET3, MOCK_IGNORE,
+ MOCK_IGNORE, MOCK_IGNORE);
+ displayed_no_extra();
+
+ /* For DETACHABLE */
+ if (DETACHABLE) {
+ reset_common_data();
+ add_mock_keypress(VB_BUTTON_VOL_UP_SHORT_PRESS);
+ add_mock_keypress(VB_BUTTON_VOL_DOWN_SHORT_PRESS);
+ add_mock_keypress(VB_BUTTON_VOL_DOWN_SHORT_PRESS);
+ add_mock_keypress(VB_BUTTON_VOL_DOWN_SHORT_PRESS);
+ add_mock_keypress(VB_BUTTON_VOL_DOWN_SHORT_PRESS);
+ add_mock_keypress(VB_BUTTON_VOL_DOWN_SHORT_PRESS);
+ add_mock_keypress(VB_BUTTON_VOL_UP_SHORT_PRESS);
+ add_mock_keypress(VB_BUTTON_POWER_SHORT_PRESS);
+ TEST_EQ(ui_loop(ctx, MOCK_SCREEN_MENU, NULL),
+ VB2_REQUEST_SHUTDOWN, "DETACHABLE");
+ displayed_eq("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE,
+ 0, MOCK_IGNORE);
+ displayed_eq("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE,
+ 1, MOCK_IGNORE);
+ displayed_eq("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE,
+ 2, MOCK_IGNORE);
+ displayed_eq("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE,
+ 3, MOCK_IGNORE);
+ displayed_eq("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE,
+ 4, MOCK_IGNORE);
+ displayed_eq("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE,
+ 3, MOCK_IGNORE);
+ displayed_eq("mock_screen_target_3", MOCK_SCREEN_TARGET3,
+ MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE);
+ displayed_no_extra();
+ }
+
+ VB2_DEBUG("...done.\n");
+}
+
+static void try_recovery_action_tests(void)
+{
+ VB2_DEBUG("Testing try recovery action...\n");
+
+ /* Success on the first try */
+ reset_common_data();
+ set_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE);
+ TEST_EQ(try_recovery_action(&mock_ui_context), VB2_SUCCESS,
+ "success on the first try");
+ TEST_EQ(mock_get_screen_info_last, -1, " no change_screen");
+
+ /* No disk found on the first try */
+ reset_common_data();
+ set_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE);
+ TEST_EQ(try_recovery_action(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
+ "no disk found on the first try");
+ TEST_EQ(mock_get_screen_info_last, VB2_SCREEN_RECOVERY_SELECT,
+ " recovery select screen");
+
+ /* Invalid disk on the first try */
+ reset_common_data();
+ set_mock_vbtlk(VB2_ERROR_MOCK, VB_DISK_FLAG_REMOVABLE);
+ TEST_EQ(try_recovery_action(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
+ "invalid on the first try");
+ TEST_EQ(mock_get_screen_info_last, VB2_SCREEN_RECOVERY_INVALID,
+ " recovery invalid screen");
+
+ /* Success, last == 0 */
+ reset_common_data();
+ set_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE);
+ invalid_disk_last = 0;
+ TEST_EQ(try_recovery_action(&mock_ui_context), VB2_SUCCESS,
+ "success, last == 0");
+ TEST_EQ(mock_get_screen_info_last, -1, " no change_screen");
+
+ /* No disk found, last == 0 */
+ reset_common_data();
+ set_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE);
+ invalid_disk_last = 0;
+ TEST_EQ(try_recovery_action(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
+ "no disk found, last == 0");
+ TEST_EQ(mock_get_screen_info_last, -1, " no change_screen");
+
+ /* Invalid disk, last == 0 */
+ reset_common_data();
+ set_mock_vbtlk(VB2_ERROR_MOCK, VB_DISK_FLAG_REMOVABLE);
+ invalid_disk_last = 0;
+ TEST_EQ(try_recovery_action(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
+ "invalid, last == 0");
+ TEST_EQ(mock_get_screen_info_last, VB2_SCREEN_RECOVERY_INVALID,
+ " recovery invalid screen");
+
+ /* Success, last == 1 */
+ reset_common_data();
+ set_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE);
+ invalid_disk_last = 1;
+ TEST_EQ(try_recovery_action(&mock_ui_context), VB2_SUCCESS,
+ "success, last == 1");
+ TEST_EQ(mock_get_screen_info_last, -1, " no change_screen");
+
+ /* No disk found, last == 1 */
+ reset_common_data();
+ set_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE);
+ invalid_disk_last = 1;
+ TEST_EQ(try_recovery_action(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
+ "no disk found, last == 1");
+ TEST_EQ(mock_get_screen_info_last, VB2_SCREEN_RECOVERY_SELECT,
+ " recovery select screen");
+
+ /* Invalid disk, last == 1 */
+ reset_common_data();
+ set_mock_vbtlk(VB2_ERROR_MOCK, VB_DISK_FLAG_REMOVABLE);
+ invalid_disk_last = 1;
+ TEST_EQ(try_recovery_action(&mock_ui_context), VB2_REQUEST_UI_CONTINUE,
+ "invalid, last == 1");
+ TEST_EQ(mock_get_screen_info_last, -1, " no change_screen");
+
+ VB2_DEBUG("...done.\n");
+}
+
+int main(void)
+{
+ menu_action_tests();
+ ui_loop_tests();
+ try_recovery_action_tests();
+
+ return gTestSuccess ? 0 : 255;
+}