summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2020-08-14 08:13:22 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2020-08-19 11:29:34 +0200
commit3e9b695d3b638fa0072dbed9ddd2d8d3482161e4 (patch)
tree527b4898239ac527e5c308b8e7d8dda59fa00f40
parentspec: Unify test attribute keys (diff)
downloadrtems-central-3e9b695d3b638fa0072dbed9ddd2d8d3482161e4.tar.bz2
validation: Add test header for test cases
-rw-r--r--rtemsspec/tests/spec-validation/tc5.yml73
-rw-r--r--rtemsspec/tests/spec-validation/tc6.yml22
-rw-r--r--rtemsspec/tests/test_validation.py205
-rw-r--r--rtemsspec/validation.py159
4 files changed, 400 insertions, 59 deletions
diff --git a/rtemsspec/tests/spec-validation/tc5.yml b/rtemsspec/tests/spec-validation/tc5.yml
new file mode 100644
index 00000000..efd6fa54
--- /dev/null
+++ b/rtemsspec/tests/spec-validation/tc5.yml
@@ -0,0 +1,73 @@
+SPDX-License-Identifier: CC-BY-SA-5.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links: []
+test-actions:
+- action: |
+ /* Test case action 0 code */
+ checks:
+ - check: |
+ /* Test case action 0 check 0 code */
+ description: |
+ Test case action 0 check 0 description.
+ links: []
+ - check: |
+ /* Test case action 0 check 1 code; step ${step} */
+ description: |
+ Test case action 0 check 1 description.
+ links: []
+ description: |
+ Test case action 0 description.
+ links: []
+- action: |
+ /* Test case action 1 code */
+ checks:
+ - check: |
+ /* Test case action 1 check 0 code; step ${step} */
+ description: |
+ Test case action 1 check 0 description.
+ links: []
+ - check: |
+ /* Test case action 1 check 1 code */
+ description: |
+ Test case action 1 check 1 description.
+ links: []
+ description: |
+ Test case action 1 description.
+ links: []
+test-brief: Test case 5 brief description.
+test-description: Test case 5 description.
+test-epilogue: |
+ /* Test case 5 epilogue code */
+test-fixture: null
+test-header:
+ code: |
+ /* Header code for ${.:/test-run}() */
+ includes:
+ - d.h
+ local-includes:
+ - e.h
+ run-params:
+ - description: |
+ Parameter A description.
+ dir: in
+ name: a
+ specifier: int *${.:name}
+ - description: |
+ Parameter B description.
+ dir: null
+ name: b
+ specifier: int ${.:name}
+ - description: |
+ Parameter C description.
+ dir: out
+ name: c
+ specifier: int *${.:name}
+ target: tc5.h
+test-includes: []
+test-local-includes: []
+test-prologue: null
+test-support: null
+test-target: tc34.c
+type: test-case
diff --git a/rtemsspec/tests/spec-validation/tc6.yml b/rtemsspec/tests/spec-validation/tc6.yml
new file mode 100644
index 00000000..02c100b8
--- /dev/null
+++ b/rtemsspec/tests/spec-validation/tc6.yml
@@ -0,0 +1,22 @@
+SPDX-License-Identifier: CC-BY-SA-6.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links: []
+test-actions: []
+test-brief: null
+test-description: null
+test-epilogue: null
+test-fixture: null
+test-header:
+ code: null
+ includes: []
+ local-includes: []
+ run-params: []
+ target: tc6.h
+test-includes: []
+test-local-includes: []
+test-prologue: null
+test-support: null
+test-target: tc34.c
+type: test-case
diff --git a/rtemsspec/tests/test_validation.py b/rtemsspec/tests/test_validation.py
index ca7668a3..708a0ea2 100644
--- a/rtemsspec/tests/test_validation.py
+++ b/rtemsspec/tests/test_validation.py
@@ -104,7 +104,6 @@ def test_validation(tmpdir):
/** @} */
"""
assert content == src.read()
-
with open(os.path.join(base_directory, "tc12.c"), "r") as src:
content = """/* SPDX-License-Identifier: BSD-2-Clause */
@@ -894,7 +893,6 @@ T_TEST_CASE_FIXTURE( Tc2, &test_case_2_fixture )
/** @} */
"""
assert content == src.read()
-
with open(os.path.join(base_directory, "tc34.c"), "r") as src:
content = """/* SPDX-License-Identifier: BSD-2-Clause */
@@ -903,6 +901,8 @@ T_TEST_CASE_FIXTURE( Tc2, &test_case_2_fixture )
*
* @ingroup RTEMSTestCaseTc3
* @ingroup RTEMSTestCaseTc4
+ * @ingroup RTEMSTestCaseTc5
+ * @ingroup RTEMSTestCaseTc6
*/
/*
@@ -996,6 +996,207 @@ T_TEST_CASE( Tc4 )
}
/** @} */
+
+/**
+ * @defgroup RTEMSTestCaseTc5 spec:/tc5
+ *
+ * @ingroup RTEMSTestSuiteTs
+ *
+ * @brief Test Case
+ *
+ * @{
+ */
+
+static void Tc5_Wrap( int *a, int b, int *c )
+{
+ T_plan(2);
+
+ /* Test case action 0 code */
+ /* Test case action 0 check 0 code */
+ /* Test case action 0 check 1 code; step 0 */
+
+ /* Test case action 1 code */
+ /* Test case action 1 check 0 code; step 1 */
+ /* Test case action 1 check 1 code */
+
+ /* Test case 5 epilogue code */
+}
+
+static T_fixture_node Tc5_Node;
+
+void Tc5_Run( int *a, int b, int *c )
+{
+ T_push_fixture( &Tc5_Node, &T_empty_fixture );
+ Tc5_Wrap( a, b, c );
+ T_pop_fixture();
+}
+
+/** @} */
+
+/**
+ * @defgroup RTEMSTestCaseTc6 spec:/tc6
+ *
+ * @ingroup RTEMSTestSuiteTs
+ *
+ * @brief Test Case
+ *
+ * @{
+ */
+
+void Tc6_Run( void )
+{
+}
+
+/** @} */
+"""
+ assert content == src.read()
+ with open(os.path.join(base_directory, "tc5.h"), "r") as src:
+ content = """/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSTestCaseTc5
+ */
+
+/*
+ * Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TC5_H
+#define _TC5_H
+
+#include <d.h>
+
+#include "e.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup RTEMSTestCaseTc5
+ *
+ * @{
+ */
+
+/* Header code for Tc5_Run() */
+
+/**
+ * @brief Test case 5 brief description.
+ *
+ * Test case 5 description.
+ *
+ * This test case performs the following actions:
+ *
+ * - Test case action 0 description.
+ *
+ * - Test case action 0 check 0 description.
+ *
+ * - Test case action 0 check 1 description.
+ *
+ * - Test case action 1 description.
+ *
+ * - Test case action 1 check 0 description.
+ *
+ * - Test case action 1 check 1 description.
+ *
+ * @param[in] a Parameter A description.
+ *
+ * @param b Parameter B description.
+ *
+ * @param[out] c Parameter C description.
+ */
+void Tc5_Run( int *a, int b, int *c );
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TC5_H */
+"""
+ assert content == src.read()
+ with open(os.path.join(base_directory, "tc6.h"), "r") as src:
+ content = """/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSTestCaseTc6
+ */
+
+/*
+ * Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TC6_H
+#define _TC6_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup RTEMSTestCaseTc6
+ *
+ * @{
+ */
+
+/**
+ */
+void Tc6_Run( void );
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TC6_H */
"""
assert content == src.read()
with open(os.path.join(base_directory, "action2.h"), "r") as src:
diff --git a/rtemsspec/validation.py b/rtemsspec/validation.py
index 3e557020..3a344745 100644
--- a/rtemsspec/validation.py
+++ b/rtemsspec/validation.py
@@ -36,11 +36,16 @@ from rtemsspec.items import Item, ItemCache, ItemGetValueContext, ItemMapper
ItemMap = Dict[str, Item]
+def _get_test_run(ctx: ItemGetValueContext) -> Any:
+ return f"{to_camel_case(ctx.item.uid[1:]).replace(' ', '')}_Run"
+
+
class _CodeMapper(ItemMapper):
- def get_value(self, ctx: ItemGetValueContext) -> Any:
- if ctx.type_path_key == "requirement/functional/action:/test-run":
- return f"{to_camel_case(ctx.item.uid[1:]).replace(' ', '')}_Run"
- raise KeyError
+ def __init__(self, item: Item):
+ super().__init__(item)
+ self.add_get_value("requirement/functional/action:/test-run",
+ _get_test_run)
+ self.add_get_value("test-case:/test-run", _get_test_run)
class _TextMapper(ItemMapper):
@@ -147,7 +152,8 @@ class _TestItem:
_add_ingroup(content, test_case_to_suites[self.uid])
content.add(["@brief Test Case", "", "@{"])
- def _add_test_case_action_description(self, content: CContent) -> None:
+ def add_test_case_action_description(self, content: CContent) -> None:
+ """ Adds the test case action description. """
actions = self["test-actions"]
if actions:
content.add("This test case performs the following actions:")
@@ -167,31 +173,100 @@ class _TestItem:
content.append(self.substitute_text(check["check"]))
return content
- def generate(self, content: CContent, _base_directory: str,
+ def _get_run_params(self, header: Optional[Dict[str, Any]]) -> List[str]:
+ if not header:
+ return []
+ return [
+ self.substitute_text(param["specifier"],
+ f"test-header/run-params[{index}]")
+ for index, param in enumerate(header["run-params"])
+ ]
+
+ def add_header_body(self, content: CContent, header: Dict[str,
+ Any]) -> None:
+ """ Adds the test header body. """
+ content.add(self.substitute_code(header["code"]))
+ with content.doxygen_block():
+ content.add_brief_description(self.substitute_text(self.brief))
+ content.wrap(self.substitute_text(self.description))
+ self.add_test_case_action_description(content)
+ content.add_param_description(header["run-params"])
+ content.gap = False
+ content.declare_function("void", f"{self.ident}_Run",
+ self._get_run_params(header))
+
+ def generate_header(self, base_directory: str, header: Dict[str,
+ Any]) -> None:
+ """ Generates the test header. """
+ content = CContent()
+ content.register_license_and_copyrights_of_item(self._item)
+ content.prepend_spdx_license_identifier()
+ with content.file_block():
+ content.add_ingroup([self.group_identifier])
+ content.add_copyrights_and_licenses()
+ with content.header_guard(os.path.basename(header["target"])):
+ content.add_includes(list(map(CInclude, header["includes"])))
+ content.add_includes(list(map(CInclude, header["local-includes"])),
+ local=True)
+ with content.extern_c():
+ with content.add_to_group(self.group_identifier):
+ self.add_header_body(content, header)
+ content.write(os.path.join(base_directory, header["target"]))
+
+ def generate(self, content: CContent, base_directory: str,
test_case_to_suites: Dict[str, List["_TestItem"]]) -> None:
""" Generates the content. """
self.add_test_case_description(content, test_case_to_suites)
- content.add(self.substitute_code(self["test-support"]))
- with content.function_block(f"void T_case_body_{self.ident}( void )"):
- content.add_brief_description(self.brief)
- content.wrap(self.description)
- self._add_test_case_action_description(content)
- content.gap = False
- params = [f"{self.ident}"]
+ self._text_mapper.reset_step()
+ actions = self._generate_test_case_actions()
fixture = self["test-fixture"]
- if fixture:
- params.append(f"&{fixture}")
- name = "T_TEST_CASE_FIXTURE"
+ header = self["test-header"]
+ if header:
+ self.generate_header(base_directory, header)
+ if self._text_mapper.steps > 0 and not fixture:
+ fixture = "T_empty_fixture"
+ content.add(self.substitute_code(self["test-support"]))
+ if header:
+ params = self._get_run_params(header)
+ if fixture:
+ ret = "static void"
+ name = f"{self.ident}_Wrap"
+ else:
+ ret = "void"
+ name = f"{self.ident}_Run"
+ align = True
else:
- name = "T_TEST_CASE"
- with content.function("", name, params):
+ ret = ""
+ params = [f"{self.ident}"]
+ if fixture:
+ params.append(f"&{fixture}")
+ name = "T_TEST_CASE_FIXTURE"
+ else:
+ name = "T_TEST_CASE"
+ align = False
+ with content.function_block(
+ f"void T_case_body_{self.ident}( void )"):
+ content.add_brief_description(self.brief)
+ content.wrap(self.description)
+ self.add_test_case_action_description(content)
+ content.gap = False
+ with content.function(ret, name, params, align=align):
content.add(self.substitute_code(self["test-prologue"]))
- self._text_mapper.reset_step()
- action_content = self._generate_test_case_actions()
if self._text_mapper.steps > 0:
content.add(f"T_plan({self._text_mapper.steps});")
- content.add(action_content)
+ content.add(actions)
content.add(self.substitute_code(self["test-epilogue"]))
+ if header and fixture:
+ run = f"{self.ident}_Run"
+ content.add(f"static T_fixture_node {self.ident}_Node;")
+ with content.function("void", run, params, align=align):
+ content.call_function(None, "T_push_fixture",
+ [f"&{self.ident}_Node", f"&{fixture}"])
+ content.gap = False
+ content.call_function(
+ None, name,
+ [param["name"] for param in header["run-params"]])
+ content.append("T_pop_fixture();")
content.add("/** @} */")
@@ -579,51 +654,21 @@ class _TestDirectiveItem(_TestItem):
content.add("}")
content.add(self.substitute_code(condition["test-epilogue"]))
- def _get_run_params(self, header: Optional[Dict[str, Any]]) -> List[str]:
- if not header:
- return []
- return [
- self.substitute_text(param["specifier"],
- f"test-header/run-params[{index}]")
- for index, param in enumerate(header["run-params"])
- ]
+ def add_test_case_action_description(self, _content: CContent) -> None:
+ pass
- def _generate_header_body(self, content: CContent,
- header: Dict[str, Any]) -> None:
+ def add_header_body(self, content: CContent, header: Dict[str,
+ Any]) -> None:
_directive_add_enum(content, self._pre_index_to_enum)
_directive_add_enum(content, self._post_index_to_enum)
- content.add(self.substitute_code(header["code"]))
- with content.doxygen_block():
- content.add_brief_description(self.brief)
- content.wrap(self.description)
- content.add_param_description(header["run-params"])
- content.gap = False
- content.declare_function("void", f"{self.ident}_Run",
- self._get_run_params(header))
-
- def _generate_header(self, base_directory: str, header: Dict[str,
- Any]) -> None:
- content = CContent()
- content.register_license_and_copyrights_of_item(self._item)
- content.prepend_spdx_license_identifier()
- with content.file_block():
- content.add_ingroup([self.group_identifier])
- content.add_copyrights_and_licenses()
- with content.header_guard(os.path.basename(header["target"])):
- content.add_includes(list(map(CInclude, header["includes"])))
- content.add_includes(list(map(CInclude, header["local-includes"])),
- local=True)
- with content.extern_c():
- with content.add_to_group(self.group_identifier):
- self._generate_header_body(content, header)
- content.write(os.path.join(base_directory, header["target"]))
+ super().add_header_body(content, header)
def generate(self, content: CContent, base_directory: str,
test_case_to_suites: Dict[str, List[_TestItem]]) -> None:
self.add_test_case_description(content, test_case_to_suites)
header = self["test-header"]
if header:
- self._generate_header(base_directory, header)
+ self.generate_header(base_directory, header)
else:
_directive_add_enum(content, self._pre_index_to_enum)
_directive_add_enum(content, self._post_index_to_enum)