diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/boot/Makefile | 2 | ||||
-rw-r--r-- | test/boot/bootflow.c | 130 | ||||
-rw-r--r-- | test/boot/expo.c | 539 | ||||
-rw-r--r-- | test/cmd/font.c | 6 | ||||
-rw-r--r-- | test/py/tests/bootstd/armbian.bmp.xz | bin | 0 -> 1384 bytes | |||
-rw-r--r-- | test/py/tests/bootstd/mmc4.img.xz | bin | 0 -> 7072 bytes | |||
-rw-r--r-- | test/py/tests/test_android/test_avb.py | 2 | ||||
-rw-r--r-- | test/py/tests/test_ut.py | 218 |
8 files changed, 875 insertions, 22 deletions
diff --git a/test/boot/Makefile b/test/boot/Makefile index d724629d3b..22ed61c8fa 100644 --- a/test/boot/Makefile +++ b/test/boot/Makefile @@ -5,6 +5,8 @@ obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o obj-$(CONFIG_FIT) += image.o +obj-$(CONFIG_EXPO) += expo.o + ifdef CONFIG_OF_LIVE obj-$(CONFIG_BOOTMETH_VBE_SIMPLE) += vbe_simple.o endif diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index e1e0708210..5b76cd3ab1 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -11,14 +11,23 @@ #include <bootflow.h> #include <bootmeth.h> #include <bootstd.h> +#include <cli.h> #include <dm.h> +#include <expo.h> #ifdef CONFIG_SANDBOX #include <asm/test.h> #endif +#include <dm/device-internal.h> #include <dm/lists.h> #include <test/suites.h> #include <test/ut.h> #include "bootstd_common.h" +#include "../../boot/bootflow_internal.h" +#include "../../boot/scene_internal.h" + +DECLARE_GLOBAL_DATA_PTR; + +extern U_BOOT_DRIVER(bootmeth_script); static int inject_response(struct unit_test_state *uts) { @@ -188,6 +197,8 @@ static int bootflow_cmd_info(struct unit_test_state *uts) ut_assert_nextline("Filename: /extlinux/extlinux.conf"); ut_assert_nextlinen("Buffer: "); ut_assert_nextline("Size: 253 (595 bytes)"); + ut_assert_nextline("OS: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)"); + ut_assert_nextline("Logo: (none)"); ut_assert_nextline("Error: 0"); ut_assert_console_end(); @@ -460,3 +471,122 @@ static int bootflow_cmd_boot(struct unit_test_state *uts) return 0; } BOOTSTD_TEST(bootflow_cmd_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/** + * prep_mmc4_bootdev() - Set up the mmc4 bootdev so we can access a fake Armbian + * + * @uts: Unit test state + * Returns 0 on success, -ve on failure + */ +static int prep_mmc4_bootdev(struct unit_test_state *uts) +{ + static const char *order[] = {"mmc2", "mmc1", "mmc4", NULL}; + struct udevice *dev, *bootstd; + struct bootstd_priv *std; + const char **old_order; + ofnode node; + + /* Enable the mmc4 node since we need a second bootflow */ + node = ofnode_path("/mmc4"); + ut_assertok(lists_bind_fdt(gd->dm_root, node, &dev, NULL, false)); + + /* Enable the script bootmeth too */ + ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); + ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_script), + "bootmeth_script", 0, ofnode_null(), &dev)); + + /* Change the order to include mmc4 */ + std = dev_get_priv(bootstd); + old_order = std->bootdev_order; + std->bootdev_order = order; + + console_record_reset_enable(); + ut_assertok(run_command("bootflow scan", 0)); + ut_assert_console_end(); + + /* Restore the order used by the device tree */ + std->bootdev_order = old_order; + + return 0; +} + +/* Check 'bootflow menu' to select a bootflow */ +static int bootflow_cmd_menu(struct unit_test_state *uts) +{ + char prev[3]; + + ut_assertok(prep_mmc4_bootdev(uts)); + + /* Add keypresses to move to and select the second one in the list */ + prev[0] = CTL_CH('n'); + prev[1] = '\r'; + prev[2] = '\0'; + ut_asserteq(2, console_in_puts(prev)); + + ut_assertok(run_command("bootflow menu", 0)); + ut_assert_nextline("Selected: Armbian"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_cmd_menu, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/** + * check_font() - Check that the font size for an item matches expectations + * + * @uts: Unit test state + * @scn: Scene containing the text object + * @id: ID of the text object + * Returns 0 on success, -ve on failure + */ +static int check_font(struct unit_test_state *uts, struct scene *scn, uint id, + int font_size) +{ + struct scene_obj_txt *txt; + + txt = scene_obj_find(scn, id, SCENEOBJT_TEXT); + ut_assertnonnull(txt); + + ut_asserteq(font_size, txt->font_size); + + return 0; +} + +/* Check themes work with a bootflow menu */ +static int bootflow_menu_theme(struct unit_test_state *uts) +{ + const int font_size = 30; + struct scene *scn; + struct expo *exp; + ofnode node; + int i; + + ut_assertok(prep_mmc4_bootdev(uts)); + + ut_assertok(bootflow_menu_new(&exp)); + node = ofnode_path("/bootstd/theme"); + ut_assert(ofnode_valid(node)); + ut_assertok(bootflow_menu_apply_theme(exp, node)); + + scn = expo_lookup_scene_id(exp, MAIN); + ut_assertnonnull(scn); + + /* + * Check that the txt objects have the correct font size from the + * device tree node: bootstd/theme + * + * Check both menu items, since there are two bootflows + */ + ut_assertok(check_font(uts, scn, OBJ_PROMPT, font_size)); + ut_assertok(check_font(uts, scn, OBJ_POINTER, font_size)); + for (i = 0; i < 2; i++) { + ut_assertok(check_font(uts, scn, ITEM_DESC + i, font_size)); + ut_assertok(check_font(uts, scn, ITEM_KEY + i, font_size)); + ut_assertok(check_font(uts, scn, ITEM_LABEL + i, font_size)); + } + + expo_destroy(exp); + + return 0; +} +BOOTSTD_TEST(bootflow_menu_theme, UT_TESTF_DM | UT_TESTF_SCAN_FDT); diff --git a/test/boot/expo.c b/test/boot/expo.c new file mode 100644 index 0000000000..7104dff05e --- /dev/null +++ b/test/boot/expo.c @@ -0,0 +1,539 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2022 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <dm.h> +#include <expo.h> +#include <menu.h> +#include <video.h> +#include <linux/input.h> +#include <test/suites.h> +#include <test/ut.h> +#include "bootstd_common.h" +#include "../../boot/scene_internal.h" + +enum { + /* scenes */ + SCENE1 = 7, + SCENE2, + + /* objects */ + OBJ_LOGO, + OBJ_TEXT, + OBJ_TEXT2, + OBJ_MENU, + OBJ_MENU_TITLE, + + /* strings */ + STR_TEXT, + STR_TEXT2, + STR_MENU_TITLE, + STR_POINTER_TEXT, + + STR_ITEM1_LABEL, + STR_ITEM1_DESC, + STR_ITEM1_KEY, + STR_ITEM1_PREVIEW, + + STR_ITEM2_LABEL, + STR_ITEM2_DESC, + STR_ITEM2_KEY, + STR_ITEM2_PREVIEW, + + /* menu items */ + ITEM1, + ITEM1_LABEL, + ITEM1_DESC, + ITEM1_KEY, + ITEM1_PREVIEW, + + ITEM2, + ITEM2_LABEL, + ITEM2_DESC, + ITEM2_KEY, + ITEM2_PREVIEW, + + /* pointer to current item */ + POINTER_TEXT, +}; + +#define BAD_POINTER ((void *)1) + +/* names for various things */ +#define EXPO_NAME "my menus" +#define SCENE_NAME1 "main" +#define SCENE_NAME2 "second" +#define SCENE_TITLE "Main Menu" +#define LOGO_NAME "logo" + +/* Check base expo support */ +static int expo_base(struct unit_test_state *uts) +{ + struct udevice *dev; + struct expo *exp; + ulong start_mem; + char name[100]; + int i; + + ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev)); + + start_mem = ut_check_free(); + + exp = NULL; + strcpy(name, EXPO_NAME); + ut_assertok(expo_new(name, NULL, &exp)); + *name = '\0'; + ut_assertnonnull(exp); + ut_asserteq(0, exp->scene_id); + ut_asserteq(0, exp->next_id); + + /* Make sure the name was allocated */ + ut_assertnonnull(exp->name); + ut_asserteq_str(EXPO_NAME, exp->name); + + ut_assertok(expo_set_display(exp, dev)); + expo_destroy(exp); + ut_assertok(ut_check_delta(start_mem)); + + /* test handling out-of-memory conditions */ + for (i = 0; i < 2; i++) { + struct expo *exp2; + + malloc_enable_testing(i); + exp2 = BAD_POINTER; + ut_asserteq(-ENOMEM, expo_new(EXPO_NAME, NULL, &exp2)); + ut_asserteq_ptr(BAD_POINTER, exp2); + malloc_disable_testing(); + } + + return 0; +} +BOOTSTD_TEST(expo_base, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check creating a scene */ +static int expo_scene(struct unit_test_state *uts) +{ + struct scene *scn; + struct expo *exp; + ulong start_mem; + char name[100]; + int id; + + start_mem = ut_check_free(); + + ut_assertok(expo_new(EXPO_NAME, NULL, &exp)); + + scn = NULL; + ut_asserteq(0, exp->next_id); + strcpy(name, SCENE_NAME1); + id = scene_new(exp, name, SCENE1, &scn); + *name = '\0'; + ut_assertnonnull(scn); + ut_asserteq(SCENE1, id); + ut_asserteq(SCENE1 + 1, exp->next_id); + ut_asserteq_ptr(exp, scn->expo); + + /* Make sure the name was allocated */ + ut_assertnonnull(scn->name); + ut_asserteq_str(SCENE_NAME1, scn->name); + + /* Set the title */ + strcpy(name, SCENE_TITLE); + ut_assertok(scene_title_set(scn, name)); + *name = '\0'; + ut_assertnonnull(scn->title); + ut_asserteq_str(SCENE_TITLE, scn->title); + + /* Use an allocated ID */ + scn = NULL; + id = scene_new(exp, SCENE_NAME2, 0, &scn); + ut_assertnonnull(scn); + ut_asserteq(SCENE2, id); + ut_asserteq(SCENE2 + 1, exp->next_id); + ut_asserteq_ptr(exp, scn->expo); + + ut_asserteq_str(SCENE_NAME2, scn->name); + + expo_destroy(exp); + + ut_assertok(ut_check_delta(start_mem)); + + return 0; +} +BOOTSTD_TEST(expo_scene, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check creating a scene with objects */ +static int expo_object(struct unit_test_state *uts) +{ + struct scene_obj_img *img; + struct scene_obj_txt *txt; + struct scene *scn; + struct expo *exp; + ulong start_mem; + char name[100]; + char *data; + int id; + + start_mem = ut_check_free(); + + ut_assertok(expo_new(EXPO_NAME, NULL, &exp)); + id = scene_new(exp, SCENE_NAME1, SCENE1, &scn); + ut_assert(id > 0); + + ut_asserteq(0, scene_obj_count(scn)); + + data = NULL; + strcpy(name, LOGO_NAME); + id = scene_img(scn, name, OBJ_LOGO, data, &img); + ut_assert(id > 0); + *name = '\0'; + ut_assertnonnull(img); + ut_asserteq(OBJ_LOGO, id); + ut_asserteq(OBJ_LOGO + 1, exp->next_id); + ut_asserteq_ptr(scn, img->obj.scene); + ut_asserteq(SCENEOBJT_IMAGE, img->obj.type); + + ut_asserteq_ptr(data, img->data); + + /* Make sure the name was allocated */ + ut_assertnonnull(scn->name); + ut_asserteq_str(SCENE_NAME1, scn->name); + + ut_asserteq(1, scene_obj_count(scn)); + + id = scene_txt_str(scn, "text", OBJ_TEXT, STR_TEXT, "my string", &txt); + ut_assert(id > 0); + ut_assertnonnull(txt); + ut_asserteq(OBJ_TEXT, id); + ut_asserteq(SCENEOBJT_TEXT, txt->obj.type); + ut_asserteq(2, scene_obj_count(scn)); + + /* Check passing NULL as the final parameter */ + id = scene_txt_str(scn, "text2", OBJ_TEXT2, STR_TEXT2, "another string", + NULL); + ut_assert(id > 0); + ut_asserteq(3, scene_obj_count(scn)); + + expo_destroy(exp); + + ut_assertok(ut_check_delta(start_mem)); + + return 0; +} +BOOTSTD_TEST(expo_object, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check setting object attributes */ +static int expo_object_attr(struct unit_test_state *uts) +{ + struct scene_obj_menu *menu; + struct scene_obj_img *img; + struct scene_obj_txt *txt; + struct scene *scn; + struct expo *exp; + ulong start_mem; + char name[100]; + char *data; + int id; + + start_mem = ut_check_free(); + + ut_assertok(expo_new(EXPO_NAME, NULL, &exp)); + id = scene_new(exp, SCENE_NAME1, SCENE1, &scn); + ut_assert(id > 0); + + data = NULL; + id = scene_img(scn, LOGO_NAME, OBJ_LOGO, data, &img); + ut_assert(id > 0); + + ut_assertok(scene_obj_set_pos(scn, OBJ_LOGO, 123, 456)); + ut_asserteq(123, img->obj.x); + ut_asserteq(456, img->obj.y); + + ut_asserteq(-ENOENT, scene_obj_set_pos(scn, OBJ_TEXT2, 0, 0)); + + id = scene_txt_str(scn, "text", OBJ_TEXT, STR_TEXT, "my string", &txt); + ut_assert(id > 0); + + strcpy(name, "font2"); + ut_assertok(scene_txt_set_font(scn, OBJ_TEXT, name, 42)); + ut_asserteq_ptr(name, txt->font_name); + ut_asserteq(42, txt->font_size); + + ut_asserteq(-ENOENT, scene_txt_set_font(scn, OBJ_TEXT2, name, 42)); + + id = scene_menu(scn, "main", OBJ_MENU, &menu); + ut_assert(id > 0); + + ut_assertok(scene_menu_set_title(scn, OBJ_MENU, OBJ_TEXT)); + + ut_asserteq(-ENOENT, scene_menu_set_title(scn, OBJ_TEXT2, OBJ_TEXT)); + ut_asserteq(-EINVAL, scene_menu_set_title(scn, OBJ_MENU, OBJ_TEXT2)); + + expo_destroy(exp); + + ut_assertok(ut_check_delta(start_mem)); + + return 0; +} +BOOTSTD_TEST(expo_object_attr, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check creating a scene with a menu */ +static int expo_object_menu(struct unit_test_state *uts) +{ + struct scene_obj_menu *menu; + struct scene_menitem *item; + int id, label_id, desc_id, key_id, pointer_id, preview_id; + struct scene_obj_txt *ptr, *name1, *desc1, *key1, *tit, *prev1; + struct scene *scn; + struct expo *exp; + ulong start_mem; + + start_mem = ut_check_free(); + + ut_assertok(expo_new(EXPO_NAME, NULL, &exp)); + id = scene_new(exp, SCENE_NAME1, SCENE1, &scn); + ut_assert(id > 0); + + id = scene_menu(scn, "main", OBJ_MENU, &menu); + ut_assert(id > 0); + ut_assertnonnull(menu); + ut_asserteq(OBJ_MENU, id); + ut_asserteq(SCENEOBJT_MENU, menu->obj.type); + ut_asserteq(0, menu->title_id); + ut_asserteq(0, menu->pointer_id); + + ut_assertok(scene_obj_set_pos(scn, OBJ_MENU, 50, 400)); + ut_asserteq(50, menu->obj.x); + ut_asserteq(400, menu->obj.y); + + id = scene_txt_str(scn, "title", OBJ_MENU_TITLE, STR_MENU_TITLE, + "Main Menu", &tit); + ut_assert(id > 0); + ut_assertok(scene_menu_set_title(scn, OBJ_MENU, OBJ_MENU_TITLE)); + ut_asserteq(OBJ_MENU_TITLE, menu->title_id); + + pointer_id = scene_txt_str(scn, "cur_item", POINTER_TEXT, + STR_POINTER_TEXT, ">", &ptr); + ut_assert(pointer_id > 0); + + ut_assertok(scene_menu_set_pointer(scn, OBJ_MENU, POINTER_TEXT)); + ut_asserteq(POINTER_TEXT, menu->pointer_id); + + label_id = scene_txt_str(scn, "label1", ITEM1_LABEL, STR_ITEM1_LABEL, + "Play", &name1); + ut_assert(label_id > 0); + + desc_id = scene_txt_str(scn, "desc1", ITEM1_DESC, STR_ITEM1_DESC, + "Lord Melchett", &desc1); + ut_assert(desc_id > 0); + + key_id = scene_txt_str(scn, "item1-key", ITEM1_KEY, STR_ITEM1_KEY, "1", + &key1); + ut_assert(key_id > 0); + + preview_id = scene_txt_str(scn, "item1-preview", ITEM1_PREVIEW, + STR_ITEM1_PREVIEW, "(preview1)", &prev1); + ut_assert(preview_id > 0); + + id = scene_menuitem(scn, OBJ_MENU, "linux", ITEM1, ITEM1_KEY, + ITEM1_LABEL, ITEM1_DESC, ITEM1_PREVIEW, 0, &item); + ut_asserteq(ITEM1, id); + ut_asserteq(id, item->id); + ut_asserteq(key_id, item->key_id); + ut_asserteq(label_id, item->label_id); + ut_asserteq(desc_id, item->desc_id); + ut_asserteq(preview_id, item->preview_id); + + /* adding an item should cause the first item to become current */ + ut_asserteq(id, menu->cur_item_id); + + /* the title should be at the top */ + ut_asserteq(menu->obj.x, tit->obj.x); + ut_asserteq(menu->obj.y, tit->obj.y); + + /* the first item should be next */ + ut_asserteq(menu->obj.x, name1->obj.x); + ut_asserteq(menu->obj.y + 32, name1->obj.y); + + ut_asserteq(menu->obj.x + 230, key1->obj.x); + ut_asserteq(menu->obj.y + 32, key1->obj.y); + + ut_asserteq(menu->obj.x + 200, ptr->obj.x); + ut_asserteq(menu->obj.y + 32, ptr->obj.y); + + ut_asserteq(menu->obj.x + 280, desc1->obj.x); + ut_asserteq(menu->obj.y + 32, desc1->obj.y); + + ut_asserteq(-4, prev1->obj.x); + ut_asserteq(menu->obj.y + 32, prev1->obj.y); + ut_asserteq(false, prev1->obj.hide); + + expo_destroy(exp); + + ut_assertok(ut_check_delta(start_mem)); + + return 0; +} +BOOTSTD_TEST(expo_object_menu, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check rendering a scene */ +static int expo_render_image(struct unit_test_state *uts) +{ + struct scene_obj_menu *menu; + struct scene *scn, *scn2; + struct expo_action act; + struct scene_obj *obj; + struct udevice *dev; + struct expo *exp; + int id; + + console_record_reset_enable(); + ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev)); + + ut_assertok(expo_new(EXPO_NAME, NULL, &exp)); + id = scene_new(exp, SCENE_NAME1, SCENE1, &scn); + ut_assert(id > 0); + ut_assertok(expo_set_display(exp, dev)); + + id = scene_img(scn, "logo", OBJ_LOGO, video_get_u_boot_logo(), NULL); + ut_assert(id > 0); + ut_assertok(scene_obj_set_pos(scn, OBJ_LOGO, 50, 20)); + + id = scene_txt_str(scn, "text", OBJ_TEXT, STR_TEXT, "my string", NULL); + ut_assert(id > 0); + ut_assertok(scene_txt_set_font(scn, OBJ_TEXT, "cantoraone_regular", + 40)); + ut_assertok(scene_obj_set_pos(scn, OBJ_TEXT, 400, 100)); + + id = scene_txt_str(scn, "text", OBJ_TEXT2, STR_TEXT2, "another string", + NULL); + ut_assert(id > 0); + ut_assertok(scene_txt_set_font(scn, OBJ_TEXT2, "nimbus_sans_l_regular", + 60)); + ut_assertok(scene_obj_set_pos(scn, OBJ_TEXT2, 200, 600)); + + id = scene_menu(scn, "main", OBJ_MENU, &menu); + ut_assert(id > 0); + + id = scene_txt_str(scn, "title", OBJ_MENU_TITLE, STR_MENU_TITLE, + "Main Menu", NULL); + ut_assert(id > 0); + ut_assertok(scene_menu_set_title(scn, OBJ_MENU, OBJ_MENU_TITLE)); + + id = scene_txt_str(scn, "cur_item", POINTER_TEXT, STR_POINTER_TEXT, ">", + NULL); + ut_assert(id > 0); + ut_assertok(scene_menu_set_pointer(scn, OBJ_MENU, POINTER_TEXT)); + + id = scene_txt_str(scn, "label1", ITEM1_LABEL, STR_ITEM1_LABEL, "Play", + NULL); + ut_assert(id > 0); + id = scene_txt_str(scn, "item1 txt", ITEM1_DESC, STR_ITEM1_DESC, + "Lord Melchett", NULL); + ut_assert(id > 0); + id = scene_txt_str(scn, "item1-key", ITEM1_KEY, STR_ITEM1_KEY, "1", + NULL); + ut_assert(id > 0); + id = scene_img(scn, "item1-preview", ITEM1_PREVIEW, + video_get_u_boot_logo(), NULL); + id = scene_menuitem(scn, OBJ_MENU, "item1", ITEM1, ITEM1_KEY, + ITEM1_LABEL, ITEM1_DESC, ITEM1_PREVIEW, 0, NULL); + ut_assert(id > 0); + + id = scene_txt_str(scn, "label2", ITEM2_LABEL, STR_ITEM2_LABEL, "Now", + NULL); + ut_assert(id > 0); + id = scene_txt_str(scn, "item2 txt", ITEM2_DESC, STR_ITEM2_DESC, + "Lord Percy", NULL); + ut_assert(id > 0); + id = scene_txt_str(scn, "item2-key", ITEM2_KEY, STR_ITEM2_KEY, "2", + NULL); + ut_assert(id > 0); + id = scene_img(scn, "item2-preview", ITEM2_PREVIEW, + video_get_u_boot_logo(), NULL); + ut_assert(id > 0); + + id = scene_menuitem(scn, OBJ_MENU, "item2", ITEM2, ITEM2_KEY, + ITEM2_LABEL, ITEM2_DESC, ITEM2_PREVIEW, 0, NULL); + ut_assert(id > 0); + + ut_assertok(scene_obj_set_pos(scn, OBJ_MENU, 50, 400)); + + scn2 = expo_lookup_scene_id(exp, SCENE1); + ut_asserteq_ptr(scn, scn2); + scn2 = expo_lookup_scene_id(exp, SCENE2); + ut_assertnull(scn2); + + /* render without a scene */ + ut_asserteq(-ECHILD, expo_render(exp)); + + /* render it */ + expo_set_scene_id(exp, SCENE1); + ut_assertok(expo_render(exp)); + + /* move down */ + ut_assertok(expo_send_key(exp, BKEY_DOWN)); + + ut_assertok(expo_action_get(exp, &act)); + + ut_asserteq(EXPOACT_POINT, act.type); + ut_asserteq(ITEM2, act.select.id); + ut_assertok(expo_render(exp)); + + /* make sure only the preview for the second item is shown */ + obj = scene_obj_find(scn, ITEM1_PREVIEW, SCENEOBJT_NONE); + ut_asserteq(true, obj->hide); + + obj = scene_obj_find(scn, ITEM2_PREVIEW, SCENEOBJT_NONE); + ut_asserteq(false, obj->hide); + + /* select it */ + ut_assertok(expo_send_key(exp, BKEY_SELECT)); + + ut_assertok(expo_action_get(exp, &act)); + ut_asserteq(EXPOACT_SELECT, act.type); + ut_asserteq(ITEM2, act.select.id); + + /* make sure the action doesn't come again */ + ut_asserteq(-EAGAIN, expo_action_get(exp, &act)); + + /* make sure there was no console output */ + ut_assert_console_end(); + + /* now try in text mode */ + exp_set_text_mode(exp, true); + ut_assertok(expo_render(exp)); + + ut_assert_nextline("U-Boot : Boot Menu"); + ut_assert_nextline("%s", ""); + ut_assert_nextline("Main Menu"); + ut_assert_nextline("%s", ""); + ut_assert_nextline(" 1 Play Lord Melchett"); + ut_assert_nextline(" > 2 Now Lord Percy"); + + /* Move back up to the first item */ + ut_assertok(expo_send_key(exp, BKEY_UP)); + + ut_assertok(expo_action_get(exp, &act)); + + ut_asserteq(EXPOACT_POINT, act.type); + ut_asserteq(ITEM1, act.select.id); + + ut_assertok(expo_render(exp)); + ut_assert_nextline("U-Boot : Boot Menu"); + ut_assert_nextline("%s", ""); + ut_assert_nextline("Main Menu"); + ut_assert_nextline("%s", ""); + ut_assert_nextline(" > 1 Play Lord Melchett"); + ut_assert_nextline(" 2 Now Lord Percy"); + + ut_assert_console_end(); + + expo_destroy(exp); + + return 0; +} +BOOTSTD_TEST(expo_render_image, UT_TESTF_DM | UT_TESTF_SCAN_FDT); diff --git a/test/cmd/font.c b/test/cmd/font.c index 7a4156ade6..adb353965a 100644 --- a/test/cmd/font.c +++ b/test/cmd/font.c @@ -33,7 +33,7 @@ static int font_test_base(struct unit_test_state *uts) ut_assertok(ut_check_console_end(uts)); ut_asserteq_str("nimbus_sans_l_regular", - vidconsole_get_font(dev, &size)); + vidconsole_get_font_size(dev, &size)); ut_asserteq(18, size); max_metrics = 1; @@ -53,14 +53,14 @@ static int font_test_base(struct unit_test_state *uts) ut_assertok(ut_check_console_end(uts)); ut_asserteq_str("cantoraone_regular", - vidconsole_get_font(dev, &size)); + vidconsole_get_font_size(dev, &size)); ut_asserteq(40, size); ut_assertok(run_command("font size 30", 0)); ut_assertok(ut_check_console_end(uts)); ut_asserteq_str("cantoraone_regular", - vidconsole_get_font(dev, &size)); + vidconsole_get_font_size(dev, &size)); ut_asserteq(30, size); return 0; diff --git a/test/py/tests/bootstd/armbian.bmp.xz b/test/py/tests/bootstd/armbian.bmp.xz Binary files differnew file mode 100644 index 0000000000..ad137ea6e6 --- /dev/null +++ b/test/py/tests/bootstd/armbian.bmp.xz diff --git a/test/py/tests/bootstd/mmc4.img.xz b/test/py/tests/bootstd/mmc4.img.xz Binary files differnew file mode 100644 index 0000000000..f4db011969 --- /dev/null +++ b/test/py/tests/bootstd/mmc4.img.xz diff --git a/test/py/tests/test_android/test_avb.py b/test/py/tests/test_android/test_avb.py index a3f883136b..bc5c5b5582 100644 --- a/test/py/tests/test_android/test_avb.py +++ b/test/py/tests/test_android/test_avb.py @@ -39,6 +39,7 @@ def test_avb_verify(u_boot_console): @pytest.mark.buildconfigspec('cmd_avb') @pytest.mark.buildconfigspec('cmd_mmc') +@pytest.mark.notbuildconfigspec('sandbox') def test_avb_mmc_uuid(u_boot_console): """Check if 'avb get_uuid' works, compare results with 'part list mmc 1' output @@ -97,6 +98,7 @@ def test_avb_is_unlocked(u_boot_console): @pytest.mark.buildconfigspec('cmd_avb') @pytest.mark.buildconfigspec('cmd_mmc') +@pytest.mark.notbuildconfigspec('sandbox') def test_avb_mmc_read(u_boot_console): """Test mmc read operation """ diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py index bab8b97672..6958fabfa3 100644 --- a/test/py/tests/test_ut.py +++ b/test/py/tests/test_ut.py @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 # Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. +import getpass import gzip import os import os.path @@ -13,34 +14,217 @@ def mkdir_cond(dirname): """Create a directory if it doesn't already exist Args: - dirname: Name of directory to create + dirname (str): Name of directory to create """ if not os.path.exists(dirname): os.mkdir(dirname) -def setup_bootflow_image(u_boot_console): - """Create a 20MB disk image with a single FAT partition""" - cons = u_boot_console - fname = os.path.join(cons.config.source_dir, 'mmc1.img') +def setup_image(cons, mmc_dev, part_type): + """Create a 20MB disk image with a single partition + + Args: + cons (ConsoleBase): Console to use + mmc_dev (int): MMC device number to use, e.g. 1 + part_type (int): Partition type, e.g. 0xc for FAT32 + + Returns: + tuple: + str: Filename of MMC image + str: Directory name of 'mnt' directory + """ + fname = os.path.join(cons.config.source_dir, f'mmc{mmc_dev}.img') mnt = os.path.join(cons.config.persistent_data_dir, 'mnt') mkdir_cond(mnt) u_boot_utils.run_and_log(cons, 'qemu-img create %s 20M' % fname) u_boot_utils.run_and_log(cons, 'sudo sfdisk %s' % fname, - stdin=b'type=c') + stdin=f'type={part_type:x}'.encode('utf-8')) + return fname, mnt + +def mount_image(cons, fname, mnt, fstype): + """Create a filesystem and mount it on partition 1 + + Args: + cons (ConsoleBase): Console to use + fname (str): Filename of MMC image + mnt (str): Directory name of 'mnt' directory + fstype (str): Filesystem type ('vfat' or 'ext4') + + Returns: + str: Name of loop device used + """ + out = u_boot_utils.run_and_log(cons, 'sudo losetup --show -f -P %s' % fname) + loop = out.strip() + part = f'{loop}p1' + u_boot_utils.run_and_log(cons, f'sudo mkfs.{fstype} {part}') + opts = '' + if fstype == 'vfat': + opts += ' -o uid={os.getuid()},gid={os.getgid()}' + u_boot_utils.run_and_log(cons, f'sudo mount -o loop {part} {mnt}{opts}') + u_boot_utils.run_and_log(cons, f'sudo chown {getpass.getuser()} {mnt}') + return loop + +def copy_prepared_image(cons, mmc_dev, fname): + """Use a prepared image since we cannot create one + + Args: + cons (ConsoleBase): Console touse + mmc_dev (int): MMC device number + fname (str): Filename of MMC image + """ + infname = os.path.join(cons.config.source_dir, + f'test/py/tests/bootstd/mmc{mmc_dev}.img.xz') + u_boot_utils.run_and_log( + cons, + ['sh', '-c', 'xz -dc %s >%s' % (infname, fname)]) + +def setup_bootmenu_image(cons): + """Create a 20MB disk image with a single ext4 partition + + This is modelled on Armbian 22.08 Jammy + """ + mmc_dev = 4 + fname, mnt = setup_image(cons, mmc_dev, 0x83) loop = None mounted = False complete = False try: - out = u_boot_utils.run_and_log(cons, - 'sudo losetup --show -f -P %s' % fname) - loop = out.strip() - fatpart = '%sp1' % loop - u_boot_utils.run_and_log(cons, 'sudo mkfs.vfat %s' % fatpart) + loop = mount_image(cons, fname, mnt, 'ext4') + mounted = True + + vmlinux = 'Image' + initrd = 'uInitrd' + dtbdir = 'dtb' + script = '''# DO NOT EDIT THIS FILE +# +# Please edit /boot/armbianEnv.txt to set supported parameters +# + +setenv load_addr "0x9000000" +setenv overlay_error "false" +# default values +setenv rootdev "/dev/mmcblk%dp1" +setenv verbosity "1" +setenv console "both" +setenv bootlogo "false" +setenv rootfstype "ext4" +setenv docker_optimizations "on" +setenv earlycon "off" + +echo "Boot script loaded from ${devtype} ${devnum}" + +if test -e ${devtype} ${devnum} ${prefix}armbianEnv.txt; then + load ${devtype} ${devnum} ${load_addr} ${prefix}armbianEnv.txt + env import -t ${load_addr} ${filesize} +fi + +if test "${logo}" = "disabled"; then setenv logo "logo.nologo"; fi + +if test "${console}" = "display" || test "${console}" = "both"; then setenv consoleargs "console=tty1"; fi +if test "${console}" = "serial" || test "${console}" = "both"; then setenv consoleargs "console=ttyS2,1500000 ${consoleargs}"; fi +if test "${earlycon}" = "on"; then setenv consoleargs "earlycon ${consoleargs}"; fi +if test "${bootlogo}" = "true"; then setenv consoleargs "bootsplash.bootfile=bootsplash.armbian ${consoleargs}"; fi + +# get PARTUUID of first partition on SD/eMMC the boot script was loaded from +if test "${devtype}" = "mmc"; then part uuid mmc ${devnum}:1 partuuid; fi + +setenv bootargs "root=${rootdev} rootwait rootfstype=${rootfstype} ${consoleargs} consoleblank=0 loglevel=${verbosity} ubootpart=${partuuid} usb-storage.quirks=${usbstoragequirks} ${extraargs} ${extraboardargs}" + +if test "${docker_optimizations}" = "on"; then setenv bootargs "${bootargs} cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory swapaccount=1"; fi + +load ${devtype} ${devnum} ${ramdisk_addr_r} ${prefix}uInitrd +load ${devtype} ${devnum} ${kernel_addr_r} ${prefix}Image + +load ${devtype} ${devnum} ${fdt_addr_r} ${prefix}dtb/${fdtfile} +fdt addr ${fdt_addr_r} +fdt resize 65536 +for overlay_file in ${overlays}; do + if load ${devtype} ${devnum} ${load_addr} ${prefix}dtb/rockchip/overlay/${overlay_prefix}-${overlay_file}.dtbo; then + echo "Applying kernel provided DT overlay ${overlay_prefix}-${overlay_file}.dtbo" + fdt apply ${load_addr} || setenv overlay_error "true" + fi +done +for overlay_file in ${user_overlays}; do + if load ${devtype} ${devnum} ${load_addr} ${prefix}overlay-user/${overlay_file}.dtbo; then + echo "Applying user provided DT overlay ${overlay_file}.dtbo" + fdt apply ${load_addr} || setenv overlay_error "true" + fi +done +if test "${overlay_error}" = "true"; then + echo "Error applying DT overlays, restoring original DT" + load ${devtype} ${devnum} ${fdt_addr_r} ${prefix}dtb/${fdtfile} +else + if load ${devtype} ${devnum} ${load_addr} ${prefix}dtb/rockchip/overlay/${overlay_prefix}-fixup.scr; then + echo "Applying kernel provided DT fixup script (${overlay_prefix}-fixup.scr)" + source ${load_addr} + fi + if test -e ${devtype} ${devnum} ${prefix}fixup.scr; then + load ${devtype} ${devnum} ${load_addr} ${prefix}fixup.scr + echo "Applying user provided fixup script (fixup.scr)" + source ${load_addr} + fi +fi +booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r} + +# Recompile with: +# mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr +''' % (mmc_dev) + bootdir = os.path.join(mnt, 'boot') + mkdir_cond(bootdir) + cmd_fname = os.path.join(bootdir, 'boot.cmd') + scr_fname = os.path.join(bootdir, 'boot.scr') + with open(cmd_fname, 'w') as outf: + print(script, file=outf) + + infname = os.path.join(cons.config.source_dir, + 'test/py/tests/bootstd/armbian.bmp.xz') + bmp_file = os.path.join(bootdir, 'boot.bmp') + u_boot_utils.run_and_log( + cons, + ['sh', '-c', f'xz -dc {infname} >{bmp_file}']) + + u_boot_utils.run_and_log( + cons, f'mkimage -C none -A arm -T script -d {cmd_fname} {scr_fname}') + + kernel = 'vmlinuz-5.15.63-rockchip64' + target = os.path.join(bootdir, kernel) + with open(target, 'wb') as outf: + print('kernel', outf) + + symlink = os.path.join(bootdir, 'Image') + if os.path.exists(symlink): + os.remove(symlink) + u_boot_utils.run_and_log( + cons, f'echo here {kernel} {symlink}') + os.symlink(kernel, symlink) + u_boot_utils.run_and_log( - cons, 'sudo mount -o loop %s %s -o uid=%d,gid=%d' % - (fatpart, mnt, os.getuid(), os.getgid())) + cons, f'mkimage -C none -A arm -T script -d {cmd_fname} {scr_fname}') + complete = True + + except ValueError as exc: + print('Falled to create image, failing back to prepared copy: %s', + str(exc)) + finally: + if mounted: + u_boot_utils.run_and_log(cons, 'sudo umount %s' % mnt) + if loop: + u_boot_utils.run_and_log(cons, 'sudo losetup -d %s' % loop) + + if not complete: + copy_prepared_image(cons, mmc_dev, fname) + +def setup_bootflow_image(cons): + """Create a 20MB disk image with a single FAT partition""" + mmc_dev = 1 + fname, mnt = setup_image(cons, mmc_dev, 0xc) + + loop = None + mounted = False + complete = False + try: + loop = mount_image(cons, fname, mnt, 'vfat') mounted = True vmlinux = 'vmlinuz-5.3.7-301.fc31.armv7hl' @@ -90,12 +274,7 @@ label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) u_boot_utils.run_and_log(cons, 'sudo losetup -d %s' % loop) if not complete: - # Use a prepared image since we cannot create one - infname = os.path.join(cons.config.source_dir, - 'test/py/tests/bootstd/mmc1.img.xz') - u_boot_utils.run_and_log( - cons, - ['sh', '-c', 'xz -dc %s >%s' % (infname, fname)]) + copy_prepared_image(cons, mmc_dev, fname) @pytest.mark.buildconfigspec('ut_dm') @@ -134,6 +313,7 @@ def test_ut_dm_init_bootstd(u_boot_console): """Initialise data for bootflow tests""" setup_bootflow_image(u_boot_console) + setup_bootmenu_image(u_boot_console) # Restart so that the new mmc1.img is picked up u_boot_console.restart_uboot() |