-
Notifications
You must be signed in to change notification settings - Fork 6.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tests: cpp: tests for std::thread and std::this_thread
This commit adds tests for std::thread and std::this_thread. Fixes #25569 Signed-off-by: Christopher Friedt <[email protected]>
- Loading branch information
Showing
6 changed files
with
299 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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,8 @@ | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
cmake_minimum_required(VERSION 3.13.1) | ||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) | ||
project(thread) | ||
|
||
FILE(GLOB_RECURSE app_sources src/*.cpp) | ||
target_sources(app PRIVATE ${app_sources}) |
This file contains 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,6 @@ | ||
CONFIG_NEWLIB_LIBC=y | ||
CONFIG_CPLUSPLUS=y | ||
CONFIG_LIB_CPLUSPLUS=y | ||
CONFIG_STD_CPP17=y | ||
CONFIG_ZTEST=y | ||
CONFIG_EXCEPTIONS=y |
This file contains 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,38 @@ | ||
/* | ||
* Copyright (c) 2020 Friedt Professional Engineering Services, Inc | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <ztest.h> | ||
|
||
BUILD_ASSERT(__cplusplus == 201703); | ||
|
||
extern void test_this_thread_get_id(void); | ||
extern void test_this_thread_yield(void); | ||
extern void test_this_thread_sleep_until(void); | ||
extern void test_this_thread_sleep_for(void); | ||
|
||
extern void test_thread_get_id(void); | ||
extern void test_thread_native_handle(void); | ||
extern void test_thread_hardware_concurrency(void); | ||
extern void test_thread_join(void); | ||
extern void test_thread_detach(void); | ||
extern void test_thread_swap(void); | ||
|
||
void test_main(void) | ||
{ | ||
TC_PRINT("version %u\n", (uint32_t)__cplusplus); | ||
ztest_test_suite(std_thread_tests, ztest_unit_test(test_this_thread_get_id), | ||
ztest_unit_test(test_this_thread_yield), | ||
ztest_unit_test(test_this_thread_sleep_until), | ||
ztest_unit_test(test_this_thread_sleep_for), | ||
|
||
ztest_unit_test(test_thread_get_id), | ||
ztest_unit_test(test_thread_native_handle), | ||
ztest_unit_test(test_thread_hardware_concurrency), | ||
ztest_unit_test(test_thread_join), ztest_unit_test(test_thread_detach), | ||
ztest_unit_test(test_thread_swap)); | ||
|
||
ztest_run_test_suite(std_thread_tests); | ||
} |
This file contains 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,40 @@ | ||
/* | ||
* Copyright (c) 2020 Friedt Professional Engineering Services, Inc | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <chrono> | ||
#include <system_error> | ||
#include <thread> | ||
#include <ztest.h> | ||
|
||
BUILD_ASSERT(__cplusplus == 201703); | ||
|
||
using namespace std; | ||
using namespace std::chrono_literals; | ||
|
||
auto now() | ||
{ | ||
return chrono::steady_clock::now(); | ||
} | ||
|
||
void test_this_thread_get_id(void) | ||
{ | ||
thread::id id = this_thread::get_id(); | ||
} | ||
|
||
void test_this_thread_yield(void) | ||
{ | ||
this_thread::yield(); | ||
} | ||
|
||
void test_this_thread_sleep_until(void) | ||
{ | ||
this_thread::sleep_until(now() + 10ms); | ||
} | ||
|
||
void test_this_thread_sleep_for(void) | ||
{ | ||
this_thread::sleep_for(10ms); | ||
} |
This file contains 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,200 @@ | ||
/* | ||
* Copyright (c) 2020 Friedt Professional Engineering Services, Inc | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <system_error> | ||
#include <thread> | ||
#include <ztest.h> | ||
|
||
BUILD_ASSERT(__cplusplus == 201703); | ||
|
||
using namespace std; | ||
|
||
void test_thread_joinable(void) | ||
{ | ||
if (!IS_ENABLED(CONFIG_ARCH_POSIX)) { | ||
// cannot autoallocate thread stacks yet in Zephyr | ||
ztest_test_skip(); | ||
} | ||
|
||
// implicitly tests the move assignment operator (operator=) | ||
thread th = thread([]() {}); | ||
zassert_true(th.joinable(), "non-default constructed thread should be joinable"); | ||
|
||
if (IS_ENABLED(__cpp_exceptions)) { | ||
try { | ||
th.join(); | ||
} catch (const system_error &e) { | ||
zassert_true(false, "joinable thread should join"); | ||
} | ||
} else { | ||
th.join(); | ||
} | ||
|
||
zassert_false(th.joinable(), "previously joined thread should not be joinable"); | ||
|
||
th = thread([]() {}); | ||
th.detach(); | ||
zassert_false(th.joinable(), "detached thread should not be joinable"); | ||
} | ||
|
||
void test_thread_get_id(void) | ||
{ | ||
thread::id tid = this_thread::get_id(); | ||
} | ||
|
||
void test_thread_native_handle(void) | ||
{ | ||
if (!IS_ENABLED(CONFIG_ARCH_POSIX)) { | ||
// cannot autoallocate thread stacks yet in Zephyr | ||
ztest_test_skip(); | ||
} | ||
|
||
thread th([]() {}); | ||
th.native_handle(); | ||
th.join(); | ||
} | ||
|
||
void test_thread_hardware_concurrency(void) | ||
{ | ||
if (IS_ENABLED(CONFIG_ARCH_POSIX)) { | ||
zassert_true(thread::hardware_concurrency() >= 1, "actual: %u, expected: >= 1", | ||
thread::hardware_concurrency()); | ||
} else { | ||
zassert_equal(thread::hardware_concurrency(), CONFIG_MP_NUM_CPUS, | ||
"actual: %u, expected: %u", thread::hardware_concurrency(), | ||
CONFIG_MP_NUM_CPUS); | ||
} | ||
} | ||
|
||
void test_thread_join(void) | ||
{ | ||
thread th; | ||
bool caught = false; | ||
|
||
if (IS_ENABLED(__cpp_exceptions)) { | ||
try { | ||
th.join(); | ||
} catch (const system_error &e) { | ||
caught = true; | ||
zassert_equal(e.code(), errc::no_such_process, | ||
"expected errc::no_such_process"); | ||
} | ||
zassert_true(caught, "join of default-constructed thread should throw"); | ||
} | ||
|
||
if (!IS_ENABLED(CONFIG_ARCH_POSIX)) { | ||
// cannot autoallocate thread stacks yet in Zephyr | ||
ztest_test_skip(); | ||
} | ||
|
||
th = thread([]() {}); | ||
if (IS_ENABLED(__cpp_exceptions)) { | ||
caught = false; | ||
try { | ||
th.join(); | ||
} catch (const system_error &e) { | ||
caught = true; | ||
} | ||
zassert_false(caught, "join() should not throw"); | ||
} else { | ||
th.join(); | ||
} | ||
|
||
if (IS_ENABLED(__cpp_exceptions)) { | ||
caught = false; | ||
try { | ||
th.join(); | ||
} catch (const system_error &e) { | ||
caught = true; | ||
zassert_equal(e.code(), errc::invalid_argument, | ||
"expected errc::invalid_argument"); | ||
} | ||
zassert_true(caught, "join should throw with already-joined thread"); | ||
} | ||
} | ||
|
||
void test_thread_detach(void) | ||
{ | ||
thread th; | ||
bool caught = false; | ||
|
||
if (IS_ENABLED(__cpp_exceptions)) { | ||
// this is the behaviour in linux for detach() with an invalid thread object | ||
caught = false; | ||
try { | ||
th.detach(); | ||
} catch (const system_error &e) { | ||
caught = true; | ||
zassert_equal(e.code(), errc::invalid_argument, | ||
"expected errc::invalid_argument"); | ||
} | ||
zassert_true(caught, "detach should throw with default-constructed thread"); | ||
} | ||
|
||
if (!IS_ENABLED(CONFIG_ARCH_POSIX)) { | ||
// cannot autoallocate thread stacks yet in Zephyr | ||
ztest_test_skip(); | ||
} | ||
|
||
th = thread([]() {}); | ||
if (IS_ENABLED(__cpp_exceptions)) { | ||
caught = false; | ||
try { | ||
th.detach(); | ||
} catch (const system_error &e) { | ||
caught = true; | ||
} | ||
zassert_false(caught, "detach on a valid thread should not throw"); | ||
} else { | ||
th.detach(); | ||
} | ||
|
||
if (IS_ENABLED(__cpp_exceptions)) { | ||
caught = false; | ||
try { | ||
th.detach(); | ||
} catch (const system_error &e) { | ||
caught = true; | ||
} | ||
zassert_true(caught, "detach on an already-detached thread should throw"); | ||
} | ||
} | ||
|
||
void test_thread_swap(void) | ||
{ | ||
thread th1; | ||
thread th2; | ||
|
||
if (IS_ENABLED(__cpp_exceptions)) { | ||
bool caught = false; | ||
try { | ||
th1.swap(th2); | ||
} catch (...) { | ||
caught = true; | ||
} | ||
zassert_false(caught, "thread::swap() is noexcept"); | ||
} | ||
|
||
if (!IS_ENABLED(CONFIG_ARCH_POSIX)) { | ||
// cannot autoallocate thread stacks yet in Zephyr | ||
ztest_test_skip(); | ||
} | ||
|
||
th1 = thread([]() {}); | ||
th2 = thread([]() {}); | ||
|
||
thread::id th1_id = th1.get_id(); | ||
thread::id th2_id = th2.get_id(); | ||
|
||
th1.swap(th2); | ||
|
||
zassert_equal(th2.get_id(), th1_id, "expected ids to be swapped"); | ||
|
||
zassert_equal(th1.get_id(), th2_id, "expected ids to be swapped"); | ||
|
||
th1.join(); | ||
th2.join(); | ||
} |
This file contains 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,7 @@ | ||
tests: | ||
cpp.thread: | ||
tags: cpp | ||
cpp.thread.exceptions: | ||
tags: cpp | ||
extra_configs: | ||
- CONFIG_EXCEPTIONS=y |