]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
expo: Add tests for the configuration editor
authorSimon Glass <sjg@chromium.org>
Thu, 1 Jun 2023 16:23:03 +0000 (10:23 -0600)
committerTom Rini <trini@konsulko.com>
Fri, 14 Jul 2023 16:54:51 +0000 (12:54 -0400)
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>
arch/sandbox/dts/sandbox.dtsi
arch/sandbox/dts/test.dts
test/boot/expo.c
test/boot/files/expo_layout.dts [new file with mode: 0644]
test/py/tests/test_ut.py
tools/expo.py [new file with mode: 0755]

index 30a305c4d208bf4ed90a0dab44b0e75ee8e0838e..f0ee0b3481ac87bb03e2379080e2f8cfab03866c 100644 (file)
                stdout-path = "/serial";
        };
 
+       cedit-theme {
+               font-size = <30>;
+               menu-inset = <3>;
+               menuitem-gap-y = <1>;
+       };
+
        alarm_wdt: alarm-wdt {
                compatible = "sandbox,alarm-wdt";
                timeout-sec = <5>;
index 442222e4b995f6c7fc997035a233170d476a11e2..b5509eee8cfedca86659fd66dd5d2ac062ffa6e8 100644 (file)
        cedit: cedit {
        };
 
+       cedit-theme {
+               font-size = <30>;
+               menu-inset = <3>;
+               menuitem-gap-y = <1>;
+       };
+
        fuzzing-engine {
                compatible = "sandbox,fuzzing-engine";
        };
index e7148024fe303230c114fafa96eacf413e436d6d..3898f853a75165ca28eadca6766579dee8a1b02d 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <command.h>
 #include <dm.h>
 #include <expo.h>
 #include <menu.h>
@@ -668,3 +669,46 @@ static int expo_test_build(struct unit_test_state *uts)
        return 0;
 }
 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);
diff --git a/test/boot/files/expo_layout.dts b/test/boot/files/expo_layout.dts
new file mode 100644 (file)
index 0000000..55d5c91
--- /dev/null
@@ -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";
+               };
+       };
+};
index 0b45863b43859e69097a1fdc128568a6bded4ff5..aa1d477cd5653e0c5511668b2c35c83f32e1dc3e 100644 (file)
@@ -282,6 +282,15 @@ label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)
         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')
 def test_ut_dm_init(u_boot_console):
     """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_bootmenu_image(u_boot_console)
+    setup_cedit_file(u_boot_console)
 
     # Restart so that the new mmc1.img is picked up
     u_boot_console.restart_uboot()
diff --git a/tools/expo.py b/tools/expo.py
new file mode 100755 (executable)
index 0000000..c6eb87a
--- /dev/null
@@ -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()