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:

Reply via email to