This is an automated email from the ASF dual-hosted git repository. janc pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 72541440cafe63f19454a996dbdf43ffb274624a Author: Wiktor Kwiatkowski <[email protected]> AuthorDate: Wed Jan 28 10:46:33 2026 +0100 test/mtest: Add initial test framework implementation The framework provides macros for defining test cases and test suites with automatic counting of passed and failed tests. Features: - MTEST_CASE macro for defining individual test cases - MTEST_SUITE macro for grouping test cases into suites - MTEST_INIT_ASSERT, MTEST_CLEANUP_ASSERT, and MTEST_CASE_ASSERT macros for test assertions with formatted output per test phase - MTEST_INIT and MTEST_CLEANUP for initializing/deinitializing necessary resources - MTEST_RUN_INIT and MTEST_RUN_CLEANUP for executing initialization and cleanup Init and cleanup are optional for the user to define. Any configuration to be done must be run explicitly by the user via the defined macros MTEST_RUN_INIT and MTEST_RUN_CLEANUP at the beginning and end of the suite, test cases should be placed between those two macros. --- test/mtest/mtest/include/mtest/mtest.h | 124 +++++++++++++++++++++++++++++++++ test/mtest/mtest/pkg.yml | 26 +++++++ test/mtest/mtest/src/mtest.c | 92 ++++++++++++++++++++++++ test/mtest/mtest/src/mtest_priv.h | 45 ++++++++++++ test/mtest/mtest/syscfg.yml | 20 ++++++ 5 files changed, 307 insertions(+) diff --git a/test/mtest/mtest/include/mtest/mtest.h b/test/mtest/mtest/include/mtest/mtest.h new file mode 100644 index 000000000..04a476f15 --- /dev/null +++ b/test/mtest/mtest/include/mtest/mtest.h @@ -0,0 +1,124 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef MTEST_H +#define MTEST_H +#include "console/console.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void mtest_case_init(const char *name); +void mtest_case_fail(void); +void mtest_case_complete(void); + +void mtest_suite_init(const char *name); +void mtest_suite_complete(void); +void mtest_suite_abort(void); +uint8_t mtest_suite_is_aborted(void); + +#define MTEST_ASSERT_FAIL_HANDLER_init() \ + do { \ + mtest_suite_abort(); \ + return; \ + } while (0) + +#define MTEST_ASSERT_FAIL_HANDLER_cleanup() \ + do { \ + mtest_suite_abort(); \ + return; \ + } while (0) + +#define MTEST_ASSERT_FAIL_HANDLER_case() \ + do { \ + mtest_case_fail(); \ + return; \ + } while (0) + +#define MTEST_ASSERT_IMPL(phase, cond, msg, ...) \ + do { \ + if (!(cond)) { \ + printf("MTEST [FAIL] \"" #cond "\" " msg "\n", ##__VA_ARGS__); \ + MTEST_ASSERT_FAIL_HANDLER_##phase(); \ + } \ + } while (0) + +#define MTEST_INIT_ASSERT(cond, msg, ...) \ + MTEST_ASSERT_IMPL(init, cond, msg, ##__VA_ARGS__) + +#define MTEST_CLEANUP_ASSERT(cond, msg, ...) \ + MTEST_ASSERT_IMPL(cleanup, cond, msg, ##__VA_ARGS__) + +#define MTEST_CASE_ASSERT(cond, msg, ...) \ + MTEST_ASSERT_IMPL(case, cond, msg, ##__VA_ARGS__) + +#define MTEST_INIT(suite_name) void MTEST_INIT_##suite_name(void) + +#define MTEST_CLEANUP(suite_name) void MTEST_CLEANUP_##suite_name(void) + +#define MTEST_RUN_INIT(suite_name) \ + do { \ + printf("MTEST start=init\n"); \ + MTEST_INIT_##suite_name(); \ + printf("MTEST end=init\n\n"); \ + if (mtest_suite_is_aborted()) { \ + return; \ + } \ + } while (0) + +#define MTEST_RUN_CLEANUP(suite_name) \ + do { \ + printf("\nMTEST start=cleanup\n"); \ + MTEST_CLEANUP_##suite_name(); \ + printf("MTEST end=cleanup\n\n"); \ + } while (0) + +#define MTEST_CASE_DECL(case_name) void case_name(void) + +#define MTEST_CASE_DEF(case_name, body) \ + void case_name(void) \ + { \ + mtest_case_init(#case_name); \ + body(); \ + mtest_case_complete(); \ + } + +#define MTEST_CASE(case_name) \ + void MTEST_CASE_##case_name(void); \ + MTEST_CASE_DEF(case_name, MTEST_CASE_##case_name) \ + void MTEST_CASE_##case_name(void) + +#define MTEST_SUITE_DECL(suite_name) void suite_name(void) + +#define MTEST_SUITE(suite_name) \ + void MTEST_SUITE_##suite_name(void); \ + void suite_name(void) \ + { \ + mtest_suite_init(#suite_name); \ + MTEST_SUITE_##suite_name(); \ + mtest_suite_complete(); \ + } \ + void MTEST_SUITE_##suite_name(void) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test/mtest/mtest/pkg.yml b/test/mtest/mtest/pkg.yml new file mode 100644 index 000000000..99c33dc4f --- /dev/null +++ b/test/mtest/mtest/pkg.yml @@ -0,0 +1,26 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: test/mtest/mtest +pkg.description: Test framework providing macros for test definition, assertions, and reporting. +pkg.author: "Apache Mynewt <[email protected]>" +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: +pkg.deps: + - "@apache-mynewt-core/sys/console" diff --git a/test/mtest/mtest/src/mtest.c b/test/mtest/mtest/src/mtest.c new file mode 100644 index 000000000..3b6d3d82c --- /dev/null +++ b/test/mtest/mtest/src/mtest.c @@ -0,0 +1,92 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "mtest_priv.h" +#include "mtest/mtest.h" + +static struct case_context case_ctx; +static struct suite_context suite_ctx; + +void +mtest_case_init(const char *name) +{ + case_ctx.failed = 0; + case_ctx.name = name; + printf("MTEST start=%s\n", case_ctx.name); +} + +void +mtest_case_fail(void) +{ + case_ctx.failed = 1; +} + +void +mtest_case_complete(void) +{ + printf("MTEST end=%s, status=%s\n", case_ctx.name, + case_ctx.failed == 0 ? "pass" : "fail"); + + suite_ctx.tests_run++; + + if (case_ctx.failed) { + suite_ctx.tests_failed++; + } else { + suite_ctx.tests_passed++; + } +} + +void +mtest_suite_init(const char *name) +{ + printf("MTEST test=%s \n", MYNEWT_VAL(APP_NAME)); + printf("MTEST bsp=%s \n", MYNEWT_VAL(BSP_NAME)); + printf("MTEST core=%s\n\n", MYNEWT_VAL(REPO_HASH_APACHE_MYNEWT_CORE)); + suite_ctx.name = name; + suite_ctx.tests_failed = 0; + suite_ctx.tests_passed = 0; + suite_ctx.tests_run = 0; + suite_ctx.aborted = 0; +} + +void +mtest_suite_complete(void) +{ + if (suite_ctx.aborted) { + printf("MTEST suite=%s, status=fail\n", suite_ctx.name); + } else { + const char *result = suite_ctx.tests_failed ? "fail" : "pass"; + printf("MTEST suite=%s, status=%s, pass=%d/%d, fail=%d/%d\n", + suite_ctx.name, result, suite_ctx.tests_passed, + suite_ctx.tests_run, suite_ctx.tests_failed, suite_ctx.tests_run); + } + printf("MTEST finished test=%s\n", MYNEWT_VAL(APP_NAME)); +} + +void +mtest_suite_abort(void) +{ + suite_ctx.aborted = 1; +} + +uint8_t +mtest_suite_is_aborted(void) +{ + return suite_ctx.aborted; +} diff --git a/test/mtest/mtest/src/mtest_priv.h b/test/mtest/mtest/src/mtest_priv.h new file mode 100644 index 000000000..6a2509b0a --- /dev/null +++ b/test/mtest/mtest/src/mtest_priv.h @@ -0,0 +1,45 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef MTEST_PRIV_H +#define MTEST_PRIV_H +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct case_context { + const char *name; + uint8_t failed; +}; + +struct suite_context { + const char *name; + int tests_run; + int tests_failed; + int tests_passed; + uint8_t aborted; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test/mtest/mtest/syscfg.yml b/test/mtest/mtest/syscfg.yml new file mode 100644 index 000000000..9d3c811a8 --- /dev/null +++ b/test/mtest/mtest/syscfg.yml @@ -0,0 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs:
