-
Notifications
You must be signed in to change notification settings - Fork 39
tests: unit: add tests for bm_scheduler #756
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
lemrey
wants to merge
2
commits into
nrfconnect:main
Choose a base branch
from
lemrey:event-sched-test
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # | ||
| # Copyright (c) 2026 Nordic Semiconductor ASA | ||
| # | ||
| # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause | ||
| # | ||
|
|
||
| cmake_minimum_required(VERSION 3.20.0) | ||
|
|
||
| find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) | ||
|
|
||
| project(bm_scheduler) | ||
|
|
||
| # Generate and add test file | ||
| test_runner_generate(src/unity_test.c) | ||
| target_sources(app PRIVATE src/unity_test.c) | ||
|
|
||
| # The unit under test (bm_scheduler.c) is compiled when CONFIG_BM_SCHEDULER=y |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| CONFIG_UNITY=y | ||
|
|
||
| CONFIG_BM_SCHEDULER=y |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,225 @@ | ||
| /* | ||
| * Copyright (c) 2026 Nordic Semiconductor ASA | ||
| * | ||
| * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause | ||
| */ | ||
| #include <unity.h> | ||
| #include <errno.h> | ||
| #include <stdint.h> | ||
| #include <string.h> | ||
|
|
||
| #include <bm/bm_scheduler.h> | ||
|
|
||
| #define MAX_RECORDED_CALLS 16 | ||
|
|
||
| struct call_record { | ||
| bm_scheduler_fn_t handler; | ||
| size_t len; | ||
| uint8_t data[64]; | ||
| }; | ||
|
|
||
| static struct call_record call_log[MAX_RECORDED_CALLS]; | ||
| static size_t call_count; | ||
|
|
||
| static void record_call(bm_scheduler_fn_t handler, void *evt, size_t len) | ||
| { | ||
| if (call_count >= MAX_RECORDED_CALLS) { | ||
| return; | ||
| } | ||
|
|
||
| call_log[call_count].handler = handler; | ||
| call_log[call_count].len = len; | ||
| if (len > 0 && len <= sizeof(call_log[call_count].data)) { | ||
| memcpy(call_log[call_count].data, evt, len); | ||
| } | ||
| call_count++; | ||
| } | ||
|
|
||
| static void handler_a(void *evt, size_t len) | ||
| { | ||
| record_call(handler_a, evt, len); | ||
| } | ||
|
|
||
| static void handler_b(void *evt, size_t len) | ||
| { | ||
| record_call(handler_b, evt, len); | ||
| } | ||
|
|
||
| void test_bm_scheduler_defer_efault(void) | ||
| { | ||
| int err; | ||
| uint8_t data = 0; | ||
|
|
||
| err = bm_scheduler_defer(NULL, NULL, 0); | ||
| TEST_ASSERT_EQUAL(-EFAULT, err); | ||
|
|
||
| err = bm_scheduler_defer(NULL, &data, sizeof(data)); | ||
| TEST_ASSERT_EQUAL(-EFAULT, err); | ||
| } | ||
|
|
||
| void test_bm_scheduler_defer_einval(void) | ||
| { | ||
| int err; | ||
| uint8_t data = 0; | ||
|
|
||
| /* data != NULL but len == 0 */ | ||
| err = bm_scheduler_defer(handler_a, &data, 0); | ||
| TEST_ASSERT_EQUAL(-EINVAL, err); | ||
|
|
||
| /* data == NULL but len != 0 */ | ||
| err = bm_scheduler_defer(handler_a, NULL, sizeof(data)); | ||
| TEST_ASSERT_EQUAL(-EINVAL, err); | ||
| } | ||
|
|
||
| void test_bm_scheduler_defer_enomem(void) | ||
| { | ||
| int err; | ||
| uint8_t big_data[CONFIG_BM_SCHEDULER_BUF_SIZE + 1] = {0}; | ||
|
|
||
| /* Requesting more than the entire heap is guaranteed to fail. */ | ||
| err = bm_scheduler_defer(handler_a, big_data, sizeof(big_data)); | ||
| TEST_ASSERT_EQUAL(-ENOMEM, err); | ||
| } | ||
|
|
||
| void test_bm_scheduler_defer_no_data(void) | ||
| { | ||
| int err; | ||
|
|
||
| /* NULL data with 0 length is a valid combination. */ | ||
| err = bm_scheduler_defer(handler_a, NULL, 0); | ||
| TEST_ASSERT_EQUAL(0, err); | ||
|
|
||
| /* The deferred event must be invoked when processing runs. */ | ||
| (void)bm_scheduler_process(); | ||
|
|
||
| TEST_ASSERT_EQUAL(1, call_count); | ||
| TEST_ASSERT_EQUAL_PTR(handler_a, call_log[0].handler); | ||
| TEST_ASSERT_EQUAL(0, call_log[0].len); | ||
| } | ||
|
|
||
| void test_bm_scheduler_defer(void) | ||
| { | ||
| int err; | ||
| uint8_t payload[] = {0xDE, 0xAD, 0xBE, 0xEF}; | ||
|
|
||
| err = bm_scheduler_defer(handler_a, payload, sizeof(payload)); | ||
| TEST_ASSERT_EQUAL(0, err); | ||
|
|
||
| /* Defer must not invoke the handler synchronously. */ | ||
| TEST_ASSERT_EQUAL(0, call_count); | ||
|
|
||
| (void)bm_scheduler_process(); | ||
|
|
||
| TEST_ASSERT_EQUAL(1, call_count); | ||
| TEST_ASSERT_EQUAL_PTR(handler_a, call_log[0].handler); | ||
| TEST_ASSERT_EQUAL(sizeof(payload), call_log[0].len); | ||
| TEST_ASSERT_EQUAL_MEMORY(payload, call_log[0].data, sizeof(payload)); | ||
| } | ||
|
|
||
| void test_bm_scheduler_process(void) | ||
| { | ||
| int err; | ||
|
|
||
| /* Processing with no deferred events is a no-op that returns success. */ | ||
| err = bm_scheduler_process(); | ||
| TEST_ASSERT_EQUAL(0, err); | ||
| TEST_ASSERT_EQUAL(0, call_count); | ||
| } | ||
|
|
||
| void test_bm_scheduler_process_dispatches_in_order(void) | ||
| { | ||
| int err; | ||
| uint8_t payload_a[] = {1, 2, 3}; | ||
| uint8_t payload_b[] = {0xAA, 0xBB}; | ||
|
|
||
| /* Defer two events with distinct handlers and payloads, so we can | ||
| * verify both that each event is routed to its own handler and that | ||
| * events are dispatched in FIFO order. | ||
| */ | ||
| err = bm_scheduler_defer(handler_a, payload_a, sizeof(payload_a)); | ||
| TEST_ASSERT_EQUAL(0, err); | ||
|
|
||
| err = bm_scheduler_defer(handler_b, payload_b, sizeof(payload_b)); | ||
| TEST_ASSERT_EQUAL(0, err); | ||
|
|
||
| TEST_ASSERT_EQUAL(0, call_count); | ||
|
|
||
| err = bm_scheduler_process(); | ||
| TEST_ASSERT_EQUAL(0, err); | ||
|
|
||
| TEST_ASSERT_EQUAL(2, call_count); | ||
|
|
||
| TEST_ASSERT_EQUAL_PTR(handler_a, call_log[0].handler); | ||
| TEST_ASSERT_EQUAL(sizeof(payload_a), call_log[0].len); | ||
| TEST_ASSERT_EQUAL_MEMORY(payload_a, call_log[0].data, sizeof(payload_a)); | ||
|
|
||
| TEST_ASSERT_EQUAL_PTR(handler_b, call_log[1].handler); | ||
| TEST_ASSERT_EQUAL(sizeof(payload_b), call_log[1].len); | ||
| TEST_ASSERT_EQUAL_MEMORY(payload_b, call_log[1].data, sizeof(payload_b)); | ||
| } | ||
|
|
||
| void test_bm_scheduler_process_data_is_copied(void) | ||
| { | ||
| int err; | ||
| uint8_t payload[] = {0x55, 0x66, 0x77, 0x88}; | ||
| const uint8_t expected[] = {0x55, 0x66, 0x77, 0x88}; | ||
|
|
||
| err = bm_scheduler_defer(handler_a, payload, sizeof(payload)); | ||
| TEST_ASSERT_EQUAL(0, err); | ||
|
|
||
| /* Mutate the source buffer after deferring. The scheduler must have | ||
| * captured a snapshot of the data, so the handler should see the | ||
| * original bytes, not the mutated ones. | ||
| */ | ||
| memset(payload, 0, sizeof(payload)); | ||
|
|
||
| (void)bm_scheduler_process(); | ||
|
|
||
| TEST_ASSERT_EQUAL(1, call_count); | ||
| TEST_ASSERT_EQUAL(sizeof(payload), call_log[0].len); | ||
|
|
||
| TEST_ASSERT_EQUAL_MEMORY(expected, call_log[0].data, sizeof(expected)); | ||
| } | ||
|
|
||
| void test_bm_scheduler_process_releases_memory(void) | ||
| { | ||
| int err; | ||
| uint8_t payload[64] = {0}; | ||
|
|
||
| /* Fill the heap until allocation fails, then drain the queue. After | ||
| * processing, the heap must be free again so a new defer succeeds. | ||
| */ | ||
| do { | ||
| err = bm_scheduler_defer(handler_a, payload, sizeof(payload)); | ||
| } while (err == 0); | ||
| TEST_ASSERT_EQUAL(-ENOMEM, err); | ||
|
|
||
| err = bm_scheduler_process(); | ||
| TEST_ASSERT_EQUAL(0, err); | ||
|
|
||
| /* The heap must be reusable after processing. */ | ||
| err = bm_scheduler_defer(handler_a, payload, sizeof(payload)); | ||
| TEST_ASSERT_EQUAL(0, err); | ||
| } | ||
|
|
||
| void setUp(void) | ||
| { | ||
| /* Drain any deferred events that may have leaked from a previous | ||
| * test, so that each test starts from a clean state. | ||
| */ | ||
| (void)bm_scheduler_process(); | ||
|
|
||
| call_count = 0; | ||
| memset(call_log, 0, sizeof(call_log)); | ||
| } | ||
|
|
||
| void tearDown(void) | ||
| { | ||
| } | ||
|
|
||
| extern int unity_main(void); | ||
|
|
||
| int main(void) | ||
| { | ||
| return unity_main(); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| tests: | ||
| lib.bm_scheduler: | ||
| platform_allow: native_sim | ||
| tags: unittest |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.