mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-24 13:43:28 +00:00
expo: Add tests for the configuration editor
Add some simple tests and a helpful script to make the configuration editor easier to set up. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
a0874dc4ac
commit
87c1a4130c
6 changed files with 280 additions and 0 deletions
|
@ -16,6 +16,12 @@
|
||||||
stdout-path = "/serial";
|
stdout-path = "/serial";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
cedit-theme {
|
||||||
|
font-size = <30>;
|
||||||
|
menu-inset = <3>;
|
||||||
|
menuitem-gap-y = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
alarm_wdt: alarm-wdt {
|
alarm_wdt: alarm-wdt {
|
||||||
compatible = "sandbox,alarm-wdt";
|
compatible = "sandbox,alarm-wdt";
|
||||||
timeout-sec = <5>;
|
timeout-sec = <5>;
|
||||||
|
|
|
@ -144,6 +144,12 @@
|
||||||
cedit: cedit {
|
cedit: cedit {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
cedit-theme {
|
||||||
|
font-size = <30>;
|
||||||
|
menu-inset = <3>;
|
||||||
|
menuitem-gap-y = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
fuzzing-engine {
|
fuzzing-engine {
|
||||||
compatible = "sandbox,fuzzing-engine";
|
compatible = "sandbox,fuzzing-engine";
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
#include <command.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
#include <expo.h>
|
#include <expo.h>
|
||||||
#include <menu.h>
|
#include <menu.h>
|
||||||
|
@ -668,3 +669,46 @@ static int expo_test_build(struct unit_test_state *uts)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
BOOTSTD_TEST(expo_test_build, UT_TESTF_DM);
|
BOOTSTD_TEST(expo_test_build, UT_TESTF_DM);
|
||||||
|
|
||||||
|
/* Check the cedit command */
|
||||||
|
static int expo_cedit(struct unit_test_state *uts)
|
||||||
|
{
|
||||||
|
extern struct expo *cur_exp;
|
||||||
|
struct scene_obj_menu *menu;
|
||||||
|
struct scene_obj_txt *txt;
|
||||||
|
struct expo *exp;
|
||||||
|
struct scene *scn;
|
||||||
|
|
||||||
|
if (!IS_ENABLED(CONFIG_CMD_CEDIT))
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
|
ut_assertok(run_command("cedit load hostfs - cedit.dtb", 0));
|
||||||
|
|
||||||
|
console_record_reset_enable();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ^N Move down to second menu
|
||||||
|
* ^M Open menu
|
||||||
|
* ^N Move down to second item
|
||||||
|
* ^M Select item
|
||||||
|
* \e Quit
|
||||||
|
*/
|
||||||
|
console_in_puts("\x0e\x0d\x0e\x0d\e");
|
||||||
|
ut_assertok(run_command("cedit run", 0));
|
||||||
|
|
||||||
|
exp = cur_exp;
|
||||||
|
scn = expo_lookup_scene_id(exp, exp->scene_id);
|
||||||
|
ut_assertnonnull(scn);
|
||||||
|
|
||||||
|
menu = scene_obj_find(scn, scn->highlight_id, SCENEOBJT_NONE);
|
||||||
|
ut_assertnonnull(menu);
|
||||||
|
|
||||||
|
txt = scene_obj_find(scn, menu->title_id, SCENEOBJT_NONE);
|
||||||
|
ut_assertnonnull(txt);
|
||||||
|
ut_asserteq_str("AC Power", expo_get_str(exp, txt->str_id));
|
||||||
|
|
||||||
|
ut_asserteq(ID_AC_ON, menu->cur_item_id);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
BOOTSTD_TEST(expo_cedit, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
|
||||||
|
|
84
test/boot/files/expo_layout.dts
Normal file
84
test/boot/files/expo_layout.dts
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Sample expo screen layout
|
||||||
|
*/
|
||||||
|
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
/*
|
||||||
|
enum {
|
||||||
|
ZERO,
|
||||||
|
ID_PROMPT,
|
||||||
|
|
||||||
|
ID_SCENE1,
|
||||||
|
ID_SCENE1_TITLE,
|
||||||
|
|
||||||
|
ID_CPU_SPEED,
|
||||||
|
ID_CPU_SPEED_TITLE,
|
||||||
|
ID_CPU_SPEED_1,
|
||||||
|
ID_CPU_SPEED_2,
|
||||||
|
ID_CPU_SPEED_3,
|
||||||
|
|
||||||
|
ID_POWER_LOSS,
|
||||||
|
ID_AC_OFF,
|
||||||
|
ID_AC_ON,
|
||||||
|
ID_AC_MEMORY,
|
||||||
|
|
||||||
|
ID_DYNAMIC_START,
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
/ {
|
||||||
|
dynamic-start = <ID_DYNAMIC_START>;
|
||||||
|
|
||||||
|
scenes {
|
||||||
|
main {
|
||||||
|
id = <ID_SCENE1>;
|
||||||
|
|
||||||
|
/* value refers to the matching id in /strings */
|
||||||
|
title-id = <ID_SCENE1_TITLE>;
|
||||||
|
|
||||||
|
/* simple string is used as it is */
|
||||||
|
prompt = "UP and DOWN to choose, ENTER to select";
|
||||||
|
|
||||||
|
/* defines a menu within the scene */
|
||||||
|
cpu-speed {
|
||||||
|
type = "menu";
|
||||||
|
id = <ID_CPU_SPEED>;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* has both string and ID. The string is ignored
|
||||||
|
* if the ID is present and points to a string
|
||||||
|
*/
|
||||||
|
title = "CPU speed";
|
||||||
|
title-id = <ID_CPU_SPEED_TITLE>;
|
||||||
|
|
||||||
|
/* menu items as simple strings */
|
||||||
|
item-label = "2 GHz", "2.5 GHz", "3 GHz";
|
||||||
|
|
||||||
|
/* IDs for the menu items */
|
||||||
|
item-id = <ID_CPU_SPEED_1 ID_CPU_SPEED_2
|
||||||
|
ID_CPU_SPEED_3>;
|
||||||
|
};
|
||||||
|
|
||||||
|
power-loss {
|
||||||
|
type = "menu";
|
||||||
|
id = <ID_POWER_LOSS>;
|
||||||
|
|
||||||
|
title = "AC Power";
|
||||||
|
item-label = "Always Off", "Always On",
|
||||||
|
"Memory";
|
||||||
|
|
||||||
|
item-id = <ID_AC_OFF ID_AC_ON ID_AC_MEMORY>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
strings {
|
||||||
|
title {
|
||||||
|
id = <ID_SCENE1_TITLE>;
|
||||||
|
value = "Test Configuration";
|
||||||
|
value-es = "configuración de prueba";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
|
@ -282,6 +282,15 @@ label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)
|
||||||
copy_prepared_image(cons, mmc_dev, fname)
|
copy_prepared_image(cons, mmc_dev, fname)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_cedit_file(cons):
|
||||||
|
infname = os.path.join(cons.config.source_dir,
|
||||||
|
'test/boot/files/expo_layout.dts')
|
||||||
|
expo_tool = os.path.join(cons.config.source_dir, 'tools/expo.py')
|
||||||
|
outfname = 'cedit.dtb'
|
||||||
|
u_boot_utils.run_and_log(
|
||||||
|
cons, f'{expo_tool} -e {infname} -l {infname} -o {outfname}')
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.buildconfigspec('ut_dm')
|
@pytest.mark.buildconfigspec('ut_dm')
|
||||||
def test_ut_dm_init(u_boot_console):
|
def test_ut_dm_init(u_boot_console):
|
||||||
"""Initialize data for ut dm tests."""
|
"""Initialize data for ut dm tests."""
|
||||||
|
@ -319,6 +328,7 @@ def test_ut_dm_init_bootstd(u_boot_console):
|
||||||
|
|
||||||
setup_bootflow_image(u_boot_console)
|
setup_bootflow_image(u_boot_console)
|
||||||
setup_bootmenu_image(u_boot_console)
|
setup_bootmenu_image(u_boot_console)
|
||||||
|
setup_cedit_file(u_boot_console)
|
||||||
|
|
||||||
# Restart so that the new mmc1.img is picked up
|
# Restart so that the new mmc1.img is picked up
|
||||||
u_boot_console.restart_uboot()
|
u_boot_console.restart_uboot()
|
||||||
|
|
130
tools/expo.py
Executable file
130
tools/expo.py
Executable file
|
@ -0,0 +1,130 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# SPDX-License-Identifier: GPL-2.0+
|
||||||
|
|
||||||
|
"""
|
||||||
|
Expo utility - used for testing of expo features
|
||||||
|
|
||||||
|
Copyright 2023 Google LLC
|
||||||
|
Written by Simon Glass <sjg@chromium.org>
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import collections
|
||||||
|
import io
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
#from u_boot_pylib import cros_subprocess
|
||||||
|
from u_boot_pylib import tools
|
||||||
|
|
||||||
|
# Parse:
|
||||||
|
# SCENE1 = 7,
|
||||||
|
# or SCENE2,
|
||||||
|
RE_ENUM = re.compile(r'(\S*)(\s*= (\d))?,')
|
||||||
|
|
||||||
|
# Parse #define <name> "string"
|
||||||
|
RE_DEF = re.compile(r'#define (\S*)\s*"(.*)"')
|
||||||
|
|
||||||
|
def calc_ids(fname):
|
||||||
|
"""Figure out the value of the enums in a C file
|
||||||
|
|
||||||
|
Args:
|
||||||
|
fname (str): Filename to parse
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
OrderedDict():
|
||||||
|
key (str): enum name
|
||||||
|
value (int or str):
|
||||||
|
Value of enum, if int
|
||||||
|
Value of #define, if string
|
||||||
|
"""
|
||||||
|
vals = collections.OrderedDict()
|
||||||
|
with open(fname, 'r', encoding='utf-8') as inf:
|
||||||
|
in_enum = False
|
||||||
|
cur_id = 0
|
||||||
|
for line in inf.readlines():
|
||||||
|
line = line.strip()
|
||||||
|
if line == 'enum {':
|
||||||
|
in_enum = True
|
||||||
|
continue
|
||||||
|
if in_enum and line == '};':
|
||||||
|
in_enum = False
|
||||||
|
|
||||||
|
if in_enum:
|
||||||
|
if not line or line.startswith('/*'):
|
||||||
|
continue
|
||||||
|
m_enum = RE_ENUM.match(line)
|
||||||
|
if m_enum.group(3):
|
||||||
|
cur_id = int(m_enum.group(3))
|
||||||
|
vals[m_enum.group(1)] = cur_id
|
||||||
|
cur_id += 1
|
||||||
|
else:
|
||||||
|
m_def = RE_DEF.match(line)
|
||||||
|
if m_def:
|
||||||
|
vals[m_def.group(1)] = tools.to_bytes(m_def.group(2))
|
||||||
|
|
||||||
|
return vals
|
||||||
|
|
||||||
|
|
||||||
|
def run_expo(args):
|
||||||
|
"""Run the expo program"""
|
||||||
|
ids = calc_ids(args.enum_fname)
|
||||||
|
|
||||||
|
indata = tools.read_file(args.layout)
|
||||||
|
|
||||||
|
outf = io.BytesIO()
|
||||||
|
|
||||||
|
for name, val in ids.items():
|
||||||
|
if isinstance(val, int):
|
||||||
|
outval = b'%d' % val
|
||||||
|
else:
|
||||||
|
outval = b'"%s"' % val
|
||||||
|
find_str = r'\b%s\b' % name
|
||||||
|
indata = re.sub(tools.to_bytes(find_str), outval, indata)
|
||||||
|
|
||||||
|
outf.write(indata)
|
||||||
|
data = outf.getvalue()
|
||||||
|
|
||||||
|
with open('/tmp/asc', 'wb') as outf:
|
||||||
|
outf.write(data)
|
||||||
|
proc = subprocess.run('dtc', input=data, capture_output=True, check=True)
|
||||||
|
edtb = proc.stdout
|
||||||
|
if proc.stderr:
|
||||||
|
print(proc.stderr)
|
||||||
|
return 1
|
||||||
|
tools.write_file(args.outfile, edtb)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args(argv):
|
||||||
|
"""Parse the command-line arguments
|
||||||
|
|
||||||
|
Args:
|
||||||
|
argv (list of str): List of string arguments
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple: (options, args) with the command-line options and arugments.
|
||||||
|
options provides access to the options (e.g. option.debug)
|
||||||
|
args is a list of string arguments
|
||||||
|
"""
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('-e', '--enum-fname', type=str,
|
||||||
|
help='C file containing enum declaration for expo items')
|
||||||
|
parser.add_argument('-l', '--layout', type=str,
|
||||||
|
help='Devicetree file source .dts for expo layout')
|
||||||
|
parser.add_argument('-o', '--outfile', type=str,
|
||||||
|
help='Filename to write expo layout dtb')
|
||||||
|
|
||||||
|
return parser.parse_args(argv)
|
||||||
|
|
||||||
|
def start_expo():
|
||||||
|
"""Start the expo program"""
|
||||||
|
args = parse_args(sys.argv[1:])
|
||||||
|
|
||||||
|
ret_code = run_expo(args)
|
||||||
|
sys.exit(ret_code)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
start_expo()
|
Loading…
Reference in a new issue