uboot/test/test-main.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2021 Google LLC
   4 * Written by Simon Glass <sjg@chromium.org>
   5 */
   6
   7#include <common.h>
   8#include <console.h>
   9#include <dm.h>
  10#include <dm/root.h>
  11#include <dm/test.h>
  12#include <dm/uclass-internal.h>
  13#include <test/test.h>
  14#include <test/ut.h>
  15
  16DECLARE_GLOBAL_DATA_PTR;
  17
  18/* This is valid when a test is running, NULL otherwise */
  19static struct unit_test_state *cur_test_state;
  20
  21struct unit_test_state *test_get_state(void)
  22{
  23        return cur_test_state;
  24}
  25
  26void test_set_state(struct unit_test_state *uts)
  27{
  28        cur_test_state = uts;
  29}
  30
  31/**
  32 * dm_test_pre_run() - Get ready to run a driver model test
  33 *
  34 * This clears out the driver model data structures. For sandbox it resets the
  35 * state structure
  36 *
  37 * @uts: Test state
  38 */
  39static int dm_test_pre_run(struct unit_test_state *uts)
  40{
  41        bool of_live = uts->of_live;
  42
  43        uts->root = NULL;
  44        uts->testdev = NULL;
  45        uts->force_fail_alloc = false;
  46        uts->skip_post_probe = false;
  47        gd->dm_root = NULL;
  48        if (CONFIG_IS_ENABLED(UT_DM) && !CONFIG_IS_ENABLED(OF_PLATDATA))
  49                memset(dm_testdrv_op_count, '\0', sizeof(dm_testdrv_op_count));
  50        arch_reset_for_test();
  51
  52        /* Determine whether to make the live tree available */
  53        gd_set_of_root(of_live ? uts->of_root : NULL);
  54        ut_assertok(dm_init(of_live));
  55        uts->root = dm_root();
  56
  57        return 0;
  58}
  59
  60static int dm_test_post_run(struct unit_test_state *uts)
  61{
  62        int id;
  63
  64        /*
  65         * With of-platdata-inst the uclasses are created at build time. If we
  66         * destroy them we cannot get them back since uclass_add() is not
  67         * supported. So skip this.
  68         */
  69        if (!CONFIG_IS_ENABLED(OF_PLATDATA_INST)) {
  70                for (id = 0; id < UCLASS_COUNT; id++) {
  71                        struct uclass *uc;
  72
  73                        /*
  74                         * If the uclass doesn't exist we don't want to create
  75                         * it. So check that here before we call
  76                         * uclass_find_device().
  77                         */
  78                        uc = uclass_find(id);
  79                        if (!uc)
  80                                continue;
  81                        ut_assertok(uclass_destroy(uc));
  82                }
  83        }
  84
  85        return 0;
  86}
  87
  88/* Ensure all the test devices are probed */
  89static int do_autoprobe(struct unit_test_state *uts)
  90{
  91        struct udevice *dev;
  92        int ret;
  93
  94        /* Scanning the uclass is enough to probe all the devices */
  95        for (ret = uclass_first_device(UCLASS_TEST, &dev);
  96             dev;
  97             ret = uclass_next_device(&dev))
  98                ;
  99
 100        return ret;
 101}
 102
 103/*
 104 * ut_test_run_on_flattree() - Check if we should run a test with flat DT
 105 *
 106 * This skips long/slow tests where there is not much value in running a flat
 107 * DT test in addition to a live DT test.
 108 *
 109 * @return true to run the given test on the flat device tree
 110 */
 111static bool ut_test_run_on_flattree(struct unit_test *test)
 112{
 113        const char *fname = strrchr(test->file, '/') + 1;
 114
 115        if (!(test->flags & UT_TESTF_DM))
 116                return false;
 117
 118        return !strstr(fname, "video") || strstr(test->name, "video_base");
 119}
 120
 121/**
 122 * test_matches() - Check if a test should be run
 123 *
 124 * This checks if the a test should be run. In the normal case of running all
 125 * tests, @select_name is NULL.
 126 *
 127 * @prefix: String prefix for the tests. Any tests that have this prefix will be
 128 *      printed without the prefix, so that it is easier to see the unique part
 129 *      of the test name. If NULL, any suite name (xxx_test) is considered to be
 130 *      a prefix.
 131 * @test_name: Name of current test
 132 * @select_name: Name of test to run (or NULL for all)
 133 * @return true to run this test, false to skip it
 134 */
 135static bool test_matches(const char *prefix, const char *test_name,
 136                         const char *select_name)
 137{
 138        size_t len;
 139
 140        if (!select_name)
 141                return true;
 142
 143        /* Allow glob expansion in the test name */
 144        len = select_name[strlen(select_name) - 1] == '*' ? strlen(select_name) : 0;
 145        if (len-- == 1)
 146                return true;
 147
 148        if (!strncmp(test_name, select_name, len))
 149                return true;
 150
 151        if (prefix) {
 152                /* All tests have this prefix */
 153                if (!strncmp(test_name, prefix, strlen(prefix)))
 154                        test_name += strlen(prefix);
 155        } else {
 156                const char *p = strstr(test_name, "_test_");
 157
 158                /* convert xxx_test_yyy to yyy, i.e. remove the suite name */
 159                if (p)
 160                        test_name = p + strlen("_test_");
 161        }
 162
 163        if (!strncmp(test_name, select_name, len))
 164                return true;
 165
 166        return false;
 167}
 168
 169/**
 170 * ut_list_has_dm_tests() - Check if a list of tests has driver model ones
 171 *
 172 * @tests: List of tests to run
 173 * @count: Number of tests to ru
 174 * @return true if any of the tests have the UT_TESTF_DM flag
 175 */
 176static bool ut_list_has_dm_tests(struct unit_test *tests, int count)
 177{
 178        struct unit_test *test;
 179
 180        for (test = tests; test < tests + count; test++) {
 181                if (test->flags & UT_TESTF_DM)
 182                        return true;
 183        }
 184
 185        return false;
 186}
 187
 188/**
 189 * dm_test_restore() Put things back to normal so sandbox works as expected
 190 *
 191 * @of_root: Value to set for of_root
 192 * @return 0 if OK, -ve on error
 193 */
 194static int dm_test_restore(struct device_node *of_root)
 195{
 196        int ret;
 197
 198        gd_set_of_root(of_root);
 199        gd->dm_root = NULL;
 200        ret = dm_init(CONFIG_IS_ENABLED(OF_LIVE));
 201        if (ret)
 202                return ret;
 203        dm_scan_plat(false);
 204        if (!CONFIG_IS_ENABLED(OF_PLATDATA))
 205                dm_scan_fdt(false);
 206
 207        return 0;
 208}
 209
 210/**
 211 * test_pre_run() - Handle any preparation needed to run a test
 212 *
 213 * @uts: Test state
 214 * @test: Test to prepare for
 215 * @return 0 if OK, -EAGAIN to skip this test since some required feature is not
 216 *      available, other -ve on error (meaning that testing cannot likely
 217 *      continue)
 218 */
 219static int test_pre_run(struct unit_test_state *uts, struct unit_test *test)
 220{
 221        if (test->flags & UT_TESTF_DM)
 222                ut_assertok(dm_test_pre_run(uts));
 223
 224        ut_set_skip_delays(uts, false);
 225
 226        uts->start = mallinfo();
 227
 228        if (test->flags & UT_TESTF_SCAN_PDATA)
 229                ut_assertok(dm_scan_plat(false));
 230
 231        if (test->flags & UT_TESTF_PROBE_TEST)
 232                ut_assertok(do_autoprobe(uts));
 233
 234        if (!CONFIG_IS_ENABLED(OF_PLATDATA) &&
 235            (test->flags & UT_TESTF_SCAN_FDT))
 236                ut_assertok(dm_extended_scan(false));
 237
 238        if (test->flags & UT_TESTF_CONSOLE_REC) {
 239                int ret = console_record_reset_enable();
 240
 241                if (ret) {
 242                        printf("Skipping: Console recording disabled\n");
 243                        return -EAGAIN;
 244                }
 245        }
 246        ut_silence_console(uts);
 247
 248        return 0;
 249}
 250
 251/**
 252 * test_post_run() - Handle cleaning up after a test
 253 *
 254 * @uts: Test state
 255 * @test: Test to clean up after
 256 * @return 0 if OK, -ve on error (meaning that testing cannot likely continue)
 257 */
 258static int test_post_run(struct unit_test_state *uts, struct unit_test *test)
 259{
 260        ut_unsilence_console(uts);
 261        if (test->flags & UT_TESTF_DM)
 262                ut_assertok(dm_test_post_run(uts));
 263
 264        return 0;
 265}
 266
 267/**
 268 * ut_run_test() - Run a single test
 269 *
 270 * This runs the test, handling any preparation and clean-up needed. It prints
 271 * the name of each test before running it.
 272 *
 273 * @uts: Test state to update. The caller should ensure that this is zeroed for
 274 *      the first call to this function. On exit, @uts->fail_count is
 275 *      incremented by the number of failures (0, one hopes)
 276 * @test_name: Test to run
 277 * @name: Name of test, possibly skipping a prefix that should not be displayed
 278 * @return 0 if all tests passed, -EAGAIN if the test should be skipped, -1 if
 279 *      any failed
 280 */
 281static int ut_run_test(struct unit_test_state *uts, struct unit_test *test,
 282                       const char *test_name)
 283{
 284        const char *fname = strrchr(test->file, '/') + 1;
 285        const char *note = "";
 286        int ret;
 287
 288        if ((test->flags & UT_TESTF_DM) && !uts->of_live)
 289                note = " (flat tree)";
 290        printf("Test: %s: %s%s\n", test_name, fname, note);
 291
 292        /* Allow access to test state from drivers */
 293        test_set_state(uts);
 294
 295        ret = test_pre_run(uts, test);
 296        if (ret == -EAGAIN)
 297                return -EAGAIN;
 298        if (ret)
 299                return ret;
 300
 301        test->func(uts);
 302
 303        ret = test_post_run(uts, test);
 304        if (ret)
 305                return ret;
 306
 307        test_set_state( NULL);
 308
 309        return 0;
 310}
 311
 312/**
 313 * ut_run_test_live_flat() - Run a test with both live and flat tree
 314 *
 315 * This calls ut_run_test() with livetree enabled, which is the standard setup
 316 * for runnig tests. Then, for driver model test, it calls it again with
 317 * livetree disabled. This allows checking of flattree being used when OF_LIVE
 318 * is enabled, as is the case in U-Boot proper before relocation, as well as in
 319 * SPL.
 320 *
 321 * @uts: Test state to update. The caller should ensure that this is zeroed for
 322 *      the first call to this function. On exit, @uts->fail_count is
 323 *      incremented by the number of failures (0, one hopes)
 324 * @test: Test to run
 325 * @name: Name of test, possibly skipping a prefix that should not be displayed
 326 * @return 0 if all tests passed, -EAGAIN if the test should be skipped, -1 if
 327 *      any failed
 328 */
 329static int ut_run_test_live_flat(struct unit_test_state *uts,
 330                                 struct unit_test *test, const char *name)
 331{
 332        int runs;
 333
 334        /* Run with the live tree if possible */
 335        runs = 0;
 336        if (CONFIG_IS_ENABLED(OF_LIVE)) {
 337                if (!(test->flags & UT_TESTF_FLAT_TREE)) {
 338                        uts->of_live = true;
 339                        ut_assertok(ut_run_test(uts, test, test->name));
 340                        runs++;
 341                }
 342        }
 343
 344        /*
 345         * Run with the flat tree if we couldn't run it with live tree,
 346         * or it is a core test.
 347         */
 348        if (!(test->flags & UT_TESTF_LIVE_TREE) &&
 349            (!runs || ut_test_run_on_flattree(test))) {
 350                uts->of_live = false;
 351                ut_assertok(ut_run_test(uts, test, test->name));
 352                runs++;
 353        }
 354
 355        return 0;
 356}
 357
 358/**
 359 * ut_run_tests() - Run a set of tests
 360 *
 361 * This runs the tests, handling any preparation and clean-up needed. It prints
 362 * the name of each test before running it.
 363 *
 364 * @uts: Test state to update. The caller should ensure that this is zeroed for
 365 *      the first call to this function. On exit, @uts->fail_count is
 366 *      incremented by the number of failures (0, one hopes)
 367 * @prefix: String prefix for the tests. Any tests that have this prefix will be
 368 *      printed without the prefix, so that it is easier to see the unique part
 369 *      of the test name. If NULL, no prefix processing is done
 370 * @tests: List of tests to run
 371 * @count: Number of tests to run
 372 * @select_name: Name of a single test to run (from the list provided). If NULL
 373 *      then all tests are run
 374 * @return 0 if all tests passed, -ENOENT if test @select_name was not found,
 375 *      -EBADF if any failed
 376 */
 377static int ut_run_tests(struct unit_test_state *uts, const char *prefix,
 378                        struct unit_test *tests, int count,
 379                        const char *select_name)
 380{
 381        struct unit_test *test;
 382        int found = 0;
 383
 384        for (test = tests; test < tests + count; test++) {
 385                const char *test_name = test->name;
 386                int ret;
 387
 388                if (!test_matches(prefix, test_name, select_name))
 389                        continue;
 390                ret = ut_run_test_live_flat(uts, test, select_name);
 391                found++;
 392                if (ret == -EAGAIN)
 393                        continue;
 394                if (ret)
 395                        return ret;
 396        }
 397        if (select_name && !found)
 398                return -ENOENT;
 399
 400        return uts->fail_count ? -EBADF : 0;
 401}
 402
 403int ut_run_list(const char *category, const char *prefix,
 404                struct unit_test *tests, int count, const char *select_name)
 405{
 406        struct unit_test_state uts = { .fail_count = 0 };
 407        bool has_dm_tests = false;
 408        int ret;
 409
 410        if (!CONFIG_IS_ENABLED(OF_PLATDATA) &&
 411            ut_list_has_dm_tests(tests, count)) {
 412                has_dm_tests = true;
 413                /*
 414                 * If we have no device tree, or it only has a root node, then
 415                 * these * tests clearly aren't going to work...
 416                 */
 417                if (!gd->fdt_blob || fdt_next_node(gd->fdt_blob, 0, NULL) < 0) {
 418                        puts("Please run with test device tree:\n"
 419                             "    ./u-boot -d arch/sandbox/dts/test.dtb\n");
 420                        return CMD_RET_FAILURE;
 421                }
 422        }
 423
 424        if (!select_name)
 425                printf("Running %d %s tests\n", count, category);
 426
 427        uts.of_root = gd_of_root();
 428        ret = ut_run_tests(&uts, prefix, tests, count, select_name);
 429
 430        if (ret == -ENOENT)
 431                printf("Test '%s' not found\n", select_name);
 432        else
 433                printf("Failures: %d\n", uts.fail_count);
 434
 435        /* Best efforts only...ignore errors */
 436        if (has_dm_tests)
 437                dm_test_restore(uts.of_root);
 438
 439        return ret;
 440}
 441