// SPDX-License-Identifier: GPL-2.0+ /* * Tests for bootstage API * * Copyright 2025 Canonical Ltd */ #include #include #include #include #include /* Test bootstage_mark_name() */ static int test_bootstage_mark(struct unit_test_state *uts) { const struct bootstage_record *rec; ulong time; int count; /* Get the current count so we know where our record will be */ count = bootstage_get_rec_count(); /* Mark a stage and verify we get a valid timestamp */ time = bootstage_mark_name(BOOTSTAGE_ID_USER + 50, "test_stage_mark"); ut_assert(time > 0); /* Verify the count increased by 1 */ ut_asserteq(count + 1, bootstage_get_rec_count()); /* Check that the record was added correctly */ rec = bootstage_get_rec(count); ut_assertnonnull(rec); ut_asserteq(BOOTSTAGE_ID_USER + 50, rec->id); ut_asserteq_str("test_stage_mark", rec->name); ut_asserteq(time, rec->time_us); ut_asserteq(0, rec->flags); ut_asserteq(time, bootstage_get_time(BOOTSTAGE_ID_USER + 50)); /* Restore the original count */ bootstage_set_rec_count(count); return 0; } COMMON_TEST(test_bootstage_mark, 0); /* Test bootstage_error_name() */ static int test_bootstage_error(struct unit_test_state *uts) { const struct bootstage_record *rec; ulong time; int count; count = bootstage_get_rec_count(); /* Mark an error stage and verify we get a valid timestamp */ time = bootstage_error_name(BOOTSTAGE_ID_USER + 51, "test_error"); ut_assert(time > 0); /* Check the error record */ rec = bootstage_get_rec(count); ut_assertnonnull(rec); ut_asserteq(BOOTSTAGE_ID_USER + 51, rec->id); ut_asserteq_str("test_error", rec->name); ut_asserteq(time, rec->time_us); ut_asserteq(BOOTSTAGEF_ERROR, rec->flags); /* Restore the original count */ bootstage_set_rec_count(count); return 0; } COMMON_TEST(test_bootstage_error, 0); /* Test bootstage_start() and bootstage_accum() */ static int test_bootstage_accum(struct unit_test_state *uts) { enum bootstage_id id = BOOTSTAGE_ID_USER + 53; uint start_time, elapsed1, elapsed2; const struct bootstage_record *rec; int index, count; count = bootstage_get_rec_count(); /* Start an accumulator */ start_time = bootstage_start(id, "test_accum"); ut_assert(start_time > 0); /* Check the accumulator record was created */ index = count; rec = bootstage_get_rec(index); ut_assertnonnull(rec); ut_asserteq(id, rec->id); ut_asserteq_str("test_accum", rec->name); ut_asserteq(start_time, rec->start_us); /* Accumulate the time */ udelay(1); elapsed1 = bootstage_accum(id); ut_assert(elapsed1 >= 0); /* Check the accumulated time was recorded */ ut_asserteq(elapsed1, rec->time_us); /* Start and accumulate again */ bootstage_start(id, "test_accum"); udelay(1); elapsed2 = bootstage_accum(id); ut_assert(elapsed2 >= 0); /* Check the total time accumulated */ rec = bootstage_get_rec(index); ut_asserteq(rec->time_us, elapsed1 + elapsed2); ut_asserteq(rec->time_us, bootstage_get_time(id)); /* Restore the original count */ bootstage_set_rec_count(count); return 0; } COMMON_TEST(test_bootstage_accum, 0); /* Test bootstage_mark_code() */ static int test_bootstage_mark_code(struct unit_test_state *uts) { const struct bootstage_record *rec; ulong time; int count; count = bootstage_get_rec_count(); /* Mark with file, function, and line number */ time = bootstage_mark_code("file.c", __func__, 123); ut_assert(time > 0); /* Check the record */ rec = bootstage_get_rec(count); ut_assertnonnull(rec); ut_asserteq(time, rec->time_us); ut_asserteq_str("file.c,123: test_bootstage_mark_code", rec->name); /* Restore the original count */ bootstage_set_rec_count(count); return 0; } COMMON_TEST(test_bootstage_mark_code, 0); /* Test bootstage_get_rec_count() */ static int test_bootstage_get_rec_count(struct unit_test_state *uts) { const struct bootstage_record *rec; int orig, count; /* Get initial count */ orig = bootstage_get_rec_count(); ut_assert(orig > 0); /* Add a new record */ bootstage_mark_name(BOOTSTAGE_ID_USER + 52, "test_count"); /* Verify count increased */ count = bootstage_get_rec_count(); ut_asserteq(orig + 1, count); /* Verify the record was added at the correct index */ rec = bootstage_get_rec(orig); ut_assertnonnull(rec); ut_asserteq(BOOTSTAGE_ID_USER + 52, rec->id); ut_asserteq_str("test_count", rec->name); /* Restore the original count */ bootstage_set_rec_count(orig); return 0; } COMMON_TEST(test_bootstage_get_rec_count, 0); /* Test bootstage_get_rec() */ static int test_bootstage_get_rec(struct unit_test_state *uts) { const struct bootstage_record *rec; int count; /* Get total count */ count = bootstage_get_rec_count(); ut_assert(count > 0); /* Get first record (should be "reset") */ rec = bootstage_get_rec(0); ut_assertnonnull(rec); ut_asserteq_str("reset", rec->name); /* Test out of bounds access */ ut_assertnull(bootstage_get_rec(count)); ut_assertnull(bootstage_get_rec(count + 100)); ut_assertnull(bootstage_get_rec(-1)); return 0; } COMMON_TEST(test_bootstage_get_rec, 0);