diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2021-08-13 22:26:16 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2021-08-16 12:33:36 +0200 |
commit | 54e9530b503a0d5fc800c013df9263e621f5adab (patch) | |
tree | dc7fce540e772d896cbf08e07184c23a7ff3299b | |
parent | validation: Simplify pre-condition N/A support (diff) | |
download | rtems-central-54e9530b503a0d5fc800c013df9263e621f5adab.tar.bz2 |
validation: Move map index/entry to context
-rw-r--r-- | rtemsspec/tests/test_validation.py | 204 | ||||
-rw-r--r-- | rtemsspec/transitionmap.py | 25 | ||||
-rw-r--r-- | rtemsspec/validation.py | 67 |
3 files changed, 166 insertions, 130 deletions
diff --git a/rtemsspec/tests/test_validation.py b/rtemsspec/tests/test_validation.py index 1fef4bfe..287ee3a2 100644 --- a/rtemsspec/tests/test_validation.py +++ b/rtemsspec/tests/test_validation.py @@ -258,6 +258,15 @@ typedef enum { Directive_Post_Id_NA } Directive_Post_Id; +typedef struct { + uint16_t Skip : 1; + uint16_t Pre_Name_NA : 1; + uint16_t Pre_Node_NA : 1; + uint16_t Pre_Id_NA : 1; + uint16_t Post_Status : 3; + uint16_t Post_Id : 3; +} Directive_Entry; + /** * @brief Test context for spec:/directive test case. */ @@ -281,16 +290,27 @@ typedef struct { rtems_id id_remote_task; - /** - * @brief This member defines the pre-condition states for the next action. - */ - size_t pcs[ 3 ]; - - /** - * @brief This member indicates if the test action loop is currently - * executed. - */ - bool in_action_loop; + struct { + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 3 ]; + + /** + * @brief If this member is true, then the test action loop is executed. + */ + bool in_action_loop; + + /** + * @brief This member contains the next transition map index. + */ + size_t index; + + /** + * @brief This member contains the current transition map entry. + */ + Directive_Entry entry; + } Map; } Directive_Context; static Directive_Context @@ -599,7 +619,7 @@ static void Directive_Setup_Wrap( void *arg ) Directive_Context *ctx; ctx = arg; - ctx->in_action_loop = false; + ctx->Map.in_action_loop = false; Directive_Setup( ctx ); } @@ -618,7 +638,7 @@ static void Directive_Teardown_Wrap( void *arg ) Directive_Context *ctx; ctx = arg; - ctx->in_action_loop = false; + ctx->Map.in_action_loop = false; Directive_Teardown( ctx ); } @@ -627,15 +647,6 @@ static void Directive_Action( Directive_Context *ctx ) ctx->status = rtems_task_ident( ctx->name, ctx->node, ctx->id ); } -typedef struct { - uint16_t Skip : 1; - uint16_t Pre_Name_NA : 1; - uint16_t Pre_Node_NA : 1; - uint16_t Pre_Id_NA : 1; - uint16_t Post_Status : 3; - uint16_t Post_Id : 3; -} Directive_Entry; - static const Directive_Entry Directive_Entries[] = { { 0, 0, 0, 0, Directive_Post_Status_InvAddr, Directive_Post_Id_NullPtr }, @@ -661,8 +672,8 @@ static size_t Directive_Scope( void *arg, char *buf, size_t n ) ctx = arg; - if ( ctx->in_action_loop ) { - return T_get_scope( Directive_PreDesc, buf, n, ctx->pcs ); + if ( ctx->Map.in_action_loop ) { + return T_get_scope( Directive_PreDesc, buf, n, ctx->Map.pcs ); } return 0; @@ -676,8 +687,12 @@ static T_fixture Directive_Fixture = { .initial_context = &Directive_Instance }; -static inline Directive_Entry Directive_GetEntry( size_t index ) +static inline Directive_Entry Directive_PopEntry( Directive_Context *ctx ) { + size_t index; + + index = ctx->Map.index; + ctx->Map.index = index + 1; return Directive_Entries[ Directive_Map[ index ] ]; @@ -689,38 +704,34 @@ static inline Directive_Entry Directive_GetEntry( size_t index ) T_TEST_CASE_FIXTURE( Directive, &Directive_Fixture ) { Directive_Context *ctx; - size_t index; ctx = T_fixture_context(); - ctx->in_action_loop = true; - index = 0; + ctx->Map.in_action_loop = true; + ctx->Map.index = 0; for ( - ctx->pcs[ 0 ] = Directive_Pre_Name_Invalid; - ctx->pcs[ 0 ] < Directive_Pre_Name_NA; - ++ctx->pcs[ 0 ] + ctx->Map.pcs[ 0 ] = Directive_Pre_Name_Invalid; + ctx->Map.pcs[ 0 ] < Directive_Pre_Name_NA; + ++ctx->Map.pcs[ 0 ] ) { for ( - ctx->pcs[ 1 ] = Directive_Pre_Node_Local; - ctx->pcs[ 1 ] < Directive_Pre_Node_NA; - ++ctx->pcs[ 1 ] + ctx->Map.pcs[ 1 ] = Directive_Pre_Node_Local; + ctx->Map.pcs[ 1 ] < Directive_Pre_Node_NA; + ++ctx->Map.pcs[ 1 ] ) { for ( - ctx->pcs[ 2 ] = Directive_Pre_Id_NullPtr; - ctx->pcs[ 2 ] < Directive_Pre_Id_NA; - ++ctx->pcs[ 2 ] + ctx->Map.pcs[ 2 ] = Directive_Pre_Id_NullPtr; + ctx->Map.pcs[ 2 ] < Directive_Pre_Id_NA; + ++ctx->Map.pcs[ 2 ] ) { - Directive_Entry entry; - - entry = Directive_GetEntry( index ); - ++index; + ctx->Map.entry = Directive_PopEntry( ctx ); - Directive_Pre_Name_Prepare( ctx, ctx->pcs[ 0 ] ); - Directive_Pre_Node_Prepare( ctx, ctx->pcs[ 1 ] ); - Directive_Pre_Id_Prepare( ctx, ctx->pcs[ 2 ] ); + Directive_Pre_Name_Prepare( ctx, ctx->Map.pcs[ 0 ] ); + Directive_Pre_Node_Prepare( ctx, ctx->Map.pcs[ 1 ] ); + Directive_Pre_Id_Prepare( ctx, ctx->Map.pcs[ 2 ] ); Directive_Action( ctx ); - Directive_Post_Status_Check( ctx, entry.Post_Status ); - Directive_Post_Id_Check( ctx, entry.Post_Id ); + Directive_Post_Status_Check( ctx, ctx->Map.entry.Post_Status ); + Directive_Post_Id_Check( ctx, ctx->Map.entry.Post_Id ); } } } @@ -1824,6 +1835,15 @@ void Action2_Run( int *a, int b, int *c ); * @{ */ +typedef struct { + uint16_t Skip : 1; + uint16_t Pre_A_NA : 1; + uint16_t Pre_B_NA : 1; + uint16_t Pre_C_NA : 1; + uint16_t Post_A : 3; + uint16_t Post_B : 2; +} Action2_Entry; + /* Context support code */ /** @@ -1855,16 +1875,27 @@ typedef struct { */ int *c; - /** - * @brief This member defines the pre-condition states for the next action. - */ - size_t pcs[ 3 ]; - - /** - * @brief This member indicates if the test action loop is currently - * executed. - */ - bool in_action_loop; + struct { + /** + * @brief This member defines the pre-condition states for the next action. + */ + size_t pcs[ 3 ]; + + /** + * @brief If this member is true, then the test action loop is executed. + */ + bool in_action_loop; + + /** + * @brief This member contains the next transition map index. + */ + size_t index; + + /** + * @brief This member contains the current transition map entry. + */ + Action2_Entry entry; + } Map; } Action2_Context; static Action2_Context @@ -2094,7 +2125,7 @@ static void Action2_Setup_Wrap( void *arg ) Action2_Context *ctx; ctx = arg; - ctx->in_action_loop = false; + ctx->Map.in_action_loop = false; Action2_Setup( ctx ); } @@ -2113,7 +2144,7 @@ static void Action2_Teardown_Wrap( void *arg ) Action2_Context *ctx; ctx = arg; - ctx->in_action_loop = false; + ctx->Map.in_action_loop = false; Action2_Teardown( ctx ); } @@ -2132,15 +2163,6 @@ static void Action2_Cleanup( Action2_Context *ctx ) /* Cleanup */ } -typedef struct { - uint16_t Skip : 1; - uint16_t Pre_A_NA : 1; - uint16_t Pre_B_NA : 1; - uint16_t Pre_C_NA : 1; - uint16_t Post_A : 3; - uint16_t Post_B : 2; -} Action2_Entry; - static const Action2_Entry Action2_Entries[] = { { 0, 1, 0, 0, Action2_Post_A_A1, Action2_Post_B_NA }, @@ -2171,8 +2193,8 @@ static size_t Action2_Scope( void *arg, char *buf, size_t n ) ctx = arg; - if ( ctx->in_action_loop ) { - return T_get_scope( Action2_PreDesc, buf, n, ctx->pcs ); + if ( ctx->Map.in_action_loop ) { + return T_get_scope( Action2_PreDesc, buf, n, ctx->Map.pcs ); } return 0; @@ -2186,8 +2208,12 @@ static T_fixture Action2_Fixture = { .initial_context = &Action2_Instance }; -static inline Action2_Entry Action2_GetEntry( size_t index ) +static inline Action2_Entry Action2_PopEntry( Action2_Context *ctx ) { + size_t index; + + index = ctx->Map.index; + ctx->Map.index = index + 1; return Action2_Entries[ Action2_Map[ index ] ]; @@ -2198,7 +2224,6 @@ static T_fixture_node Action2_Node; void Action2_Run( int *a, int b, int *c ) { Action2_Context *ctx; - size_t index; ctx = &Action2_Instance; ctx->a = a; @@ -2206,43 +2231,40 @@ void Action2_Run( int *a, int b, int *c ) ctx->c = c; ctx = T_push_fixture( &Action2_Node, &Action2_Fixture ); - ctx->in_action_loop = true; - index = 0; + ctx->Map.in_action_loop = true; + ctx->Map.index = 0; for ( - ctx->pcs[ 0 ] = Action2_Pre_A_A0; - ctx->pcs[ 0 ] < Action2_Pre_A_NA; - ++ctx->pcs[ 0 ] + ctx->Map.pcs[ 0 ] = Action2_Pre_A_A0; + ctx->Map.pcs[ 0 ] < Action2_Pre_A_NA; + ++ctx->Map.pcs[ 0 ] ) { for ( - ctx->pcs[ 1 ] = Action2_Pre_B_B0; - ctx->pcs[ 1 ] < Action2_Pre_B_NA; - ++ctx->pcs[ 1 ] + ctx->Map.pcs[ 1 ] = Action2_Pre_B_B0; + ctx->Map.pcs[ 1 ] < Action2_Pre_B_NA; + ++ctx->Map.pcs[ 1 ] ) { for ( - ctx->pcs[ 2 ] = Action2_Pre_C_C0; - ctx->pcs[ 2 ] < Action2_Pre_C_NA; - ++ctx->pcs[ 2 ] + ctx->Map.pcs[ 2 ] = Action2_Pre_C_C0; + ctx->Map.pcs[ 2 ] < Action2_Pre_C_NA; + ++ctx->Map.pcs[ 2 ] ) { - Action2_Entry entry; - - entry = Action2_GetEntry( index ); - ++index; + ctx->Map.entry = Action2_PopEntry( ctx ); - if ( entry.Skip ) { + if ( ctx->Map.entry.Skip ) { continue; } Action2_Prepare( ctx ); Action2_Pre_A_Prepare( ctx, - entry.Pre_A_NA ? Action2_Pre_A_NA : ctx->pcs[ 0 ] + ctx->Map.entry.Pre_A_NA ? Action2_Pre_A_NA : ctx->Map.pcs[ 0 ] ); - Action2_Pre_B_Prepare( ctx, ctx->pcs[ 1 ] ); - Action2_Pre_C_Prepare( ctx, ctx->pcs[ 2 ] ); + Action2_Pre_B_Prepare( ctx, ctx->Map.pcs[ 1 ] ); + Action2_Pre_C_Prepare( ctx, ctx->Map.pcs[ 2 ] ); Action2_Action( ctx ); - Action2_Post_A_Check( ctx, entry.Post_A ); - Action2_Post_B_Check( ctx, entry.Post_B ); + Action2_Post_A_Check( ctx, ctx->Map.entry.Post_A ); + Action2_Post_B_Check( ctx, ctx->Map.entry.Post_B ); Action2_Cleanup( ctx ); } } diff --git a/rtemsspec/transitionmap.py b/rtemsspec/transitionmap.py index c7f2193a..703395cb 100644 --- a/rtemsspec/transitionmap.py +++ b/rtemsspec/transitionmap.py @@ -616,6 +616,20 @@ class TransitionMap: bits += math.ceil(math.log2(len(st_idx_to_st_name))) return 2**max(math.ceil(math.log2(bits)), 3) + def add_map_entry_type(self, content: CContent, ident: str) -> None: + """ Adds the transition map entry type definition to the content. """ + bits = self._get_entry_bits() + content.add("typedef struct {") + with content.indent(): + content.append(f"uint{bits}_t Skip : 1;") + for condition in self["pre-conditions"]: + content.append(f"uint{bits}_t Pre_{condition['name']}_NA : 1;") + for condition in self["post-conditions"]: + state_bits = math.ceil(math.log2(len(condition["states"]) + 1)) + content.append( + f"uint{bits}_t Post_{condition['name']} : {state_bits};") + content.add(f"}} {ident}_Entry;") + def add_map(self, content: CContent, ident: str) -> None: """ Adds the transition map definitions to the content. """ entries = [] @@ -636,17 +650,6 @@ class TransitionMap: enumerators.append(self._get_entry(ident, transitions[0])) enumerators.append("#endif") entries.append("\n".join(enumerators)) - bits = self._get_entry_bits() - content.add("typedef struct {") - with content.indent(): - content.append(f"uint{bits}_t Skip : 1;") - for condition in self["pre-conditions"]: - content.append(f"uint{bits}_t Pre_{condition['name']}_NA : 1;") - for condition in self["post-conditions"]: - state_bits = math.ceil(math.log2(len(condition["states"]) + 1)) - content.append( - f"uint{bits}_t Post_{condition['name']} : {state_bits};") - content.add(f"}} {ident}_Entry;") content.add([f"static const {ident}_Entry", f"{ident}_Entries[] = {{"]) entries[-1] = entries[-1].replace("},", "}") content.append(entries) diff --git a/rtemsspec/validation.py b/rtemsspec/validation.py index 8b76fe99..48c65077 100644 --- a/rtemsspec/validation.py +++ b/rtemsspec/validation.py @@ -528,23 +528,32 @@ class _ActionRequirementTestItem(_TestItem): def add_default_context_members(self, content: CContent) -> None: super().add_default_context_members(content) - content.add_description_block( - "This member defines the pre-condition states " - "for the next action.", None) - content.add(f"size_t pcs[ {self._pre_co_count} ];") - content.add_description_block( - "This member indicates if the test action loop " - "is currently executed.", None) - content.add("bool in_action_loop;") + content.add("struct {") + with content.indent(): + content.add_description_block( + "This member defines the pre-condition states " + "for the next action.", None) + content.add(f"size_t pcs[ {self._pre_co_count} ];") + content.add_description_block( + "If this member is true, then the test action " + "loop is executed.", None) + content.add("bool in_action_loop;") + content.add_description_block( + "This member contains the next transition map index.", None) + content.add("size_t index;") + content.add_description_block( + "This member contains the current transition map entry.", None) + content.add(f"{self.ident}_Entry entry;") + content.append("} Map;") def _add_fixture_scope(self, content: CContent) -> None: params = ["void *arg", "char *buf", "size_t n"] with content.function("static size_t", f"{self.ident}_Scope", params): content.add([f"{self.context} *ctx;", "", "ctx = arg;"]) - with content.condition("ctx->in_action_loop"): + with content.condition("ctx->Map.in_action_loop"): content.call_function( "return", "T_get_scope", - [f"{self.ident}_PreDesc", "buf", "n", "ctx->pcs"]) + [f"{self.ident}_PreDesc", "buf", "n", "ctx->Map.pcs"]) content.add("return 0;") def _add_call(self, content: CContent, key: str, name: str) -> None: @@ -554,34 +563,34 @@ class _ActionRequirementTestItem(_TestItem): def _add_loop_body(self, content: CContent, transition_map: TransitionMap) -> None: - content.add(f"{self.ident}_Entry entry;") - content.call_function("entry =", f"{self.ident}_GetEntry", ["index"]) - content.append("++index;") + entry = "ctx->Map.entry" + content.call_function(f"{entry} =", f"{self.ident}_PopEntry", ["ctx"]) if transition_map.pre_co_summary[0]: - with content.condition("entry.Skip"): + with content.condition(f"{entry}.Skip"): content.append("continue;") content.add_blank_line() self._add_call(content, "test-prepare", "Prepare") for index, pre_co in enumerate(self._item["pre-conditions"]): content.gap = False - state = f"ctx->pcs[ {index} ]" + state = f"ctx->Map.pcs[ {index} ]" if transition_map.pre_co_summary[index + 1]: enum_na = self._pre_co_idx_to_enum[index][-1] - state = f"entry.Pre_{pre_co['name']}_NA ? {enum_na} : {state}" + name = pre_co["name"] + state = f"{entry}.Pre_{name}_NA ? {enum_na} : {state}" prepare = f"{self._pre_co_idx_to_enum[index][0]}_Prepare" content.call_function(None, prepare, ["ctx", state]) self._add_call(content, "test-action", "Action") for index, enum in enumerate(self._post_co_idx_to_enum): content.gap = False content.call_function(None, f"{enum[0]}_Check", [ - "ctx", f"entry.{transition_map.get_post_entry_member(index)}" + "ctx", f"{entry}.{transition_map.get_post_entry_member(index)}" ]) self._add_call(content, "test-cleanup", "Cleanup") def _add_for_loops(self, content: CContent, transition_map: TransitionMap, index: int) -> None: if index < self._pre_co_count: - var = f"ctx->pcs[ {index} ]" + var = f"ctx->Map.pcs[ {index} ]" begin = self._pre_co_idx_to_enum[index][1] end = self._pre_co_idx_to_enum[index][-1] with content.for_loop(f"{var} = {begin}", f"{var} < {end}", @@ -593,11 +602,12 @@ class _ActionRequirementTestItem(_TestItem): def _add_test_case(self, content: CContent, transition_map: TransitionMap, header: Dict[str, Any]) -> None: ret = f"static inline {self.ident}_Entry" - name = f"{self.ident}_GetEntry" - params = ["size_t index"] + name = f"{self.ident}_PopEntry" + params = [f"{self.context} *ctx"] with content.function(ret, name, params, align=True): content.add([ - f"return {self.ident}_Entries[", + "size_t index;", "", "index = ctx->Map.index;", + "ctx->Map.index = index + 1;", f"return {self.ident}_Entries[", f" {self.ident}_Map[ index ]", "];" ]) fixture = f"{self.ident}_Fixture" @@ -608,11 +618,12 @@ class _ActionRequirementTestItem(_TestItem): ret = "void" name = f"{self.ident}_Run" params = self._get_run_params(header) - prologue.add([f"{self.context} *ctx;", "size_t index;"]) + prologue.add([f"{self.context} *ctx;"]) self.assign_run_params(prologue, header) prologue.call_function("ctx =", "T_push_fixture", [f"&{self.ident}_Node", f"&{fixture}"]) - prologue.append(["ctx->in_action_loop = true;", "index = 0;"]) + prologue.append( + ["ctx->Map.in_action_loop = true;", "ctx->Map.index = 0;"]) epilogue.add("T_pop_fixture();") align = True else: @@ -624,9 +635,8 @@ class _ActionRequirementTestItem(_TestItem): name = "T_TEST_CASE_FIXTURE" params = [f"{self.ident}", f"&{fixture}"] prologue.add([ - f"{self.context} *ctx;", "size_t index;", "", - "ctx = T_fixture_context();", "ctx->in_action_loop = true;", - "index = 0;" + f"{self.context} *ctx;", "", "ctx = T_fixture_context();", + "ctx->Map.in_action_loop = true;", "ctx->Map.index = 0;" ]) align = False with content.function(ret, name, params, align=align): @@ -678,6 +688,8 @@ class _ActionRequirementTestItem(_TestItem): else: _add_condition_enum(content, self._pre_co_idx_to_enum) _add_condition_enum(content, self._post_co_idx_to_enum) + transition_map = TransitionMap(self.item) + transition_map.add_map_entry_type(content, self.ident) instance = self.add_context(content) self._add_pre_condition_descriptions(content) content.add(self.substitute_code(self["test-support"])) @@ -685,7 +697,7 @@ class _ActionRequirementTestItem(_TestItem): self._pre_co_idx_to_enum, "Prepare") self._add_handler(content, self["post-conditions"], self._post_co_idx_to_enum, "Check") - optional_code = "ctx->in_action_loop = false;" + optional_code = "ctx->Map.in_action_loop = false;" setup = self.add_support_method(content, "test-setup", "Setup", @@ -701,7 +713,6 @@ class _ActionRequirementTestItem(_TestItem): self.add_function(content, "test-prepare", "Prepare") self.add_function(content, "test-action", "Action") self.add_function(content, "test-cleanup", "Cleanup") - transition_map = TransitionMap(self.item) transition_map.add_map(content, self.ident) self._add_fixture_scope(content) content.add([ |