diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2020-07-27 09:23:13 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2020-07-27 14:21:19 +0200 |
commit | 244b2771339059836c1dc22c3664f1b4fa772f51 (patch) | |
tree | 578297adbd0916fa52566fd3dd2b4c8c4fc83115 /rtemsspec | |
parent | config.yml: Fix UIDs (diff) | |
download | rtems-central-244b2771339059836c1dc22c3664f1b4fa772f51.tar.bz2 |
validation: Support N/A in the action transitions
Sometimes the pre-conditions are not independent and it is necessary to
mark pre-conditions as not applicable in a particular transition.
Diffstat (limited to 'rtemsspec')
-rw-r--r-- | rtemsspec/tests/spec-validation/action2.yml | 11 | ||||
-rw-r--r-- | rtemsspec/tests/test_validation.py | 204 | ||||
-rw-r--r-- | rtemsspec/validation.py | 97 |
3 files changed, 266 insertions, 46 deletions
diff --git a/rtemsspec/tests/spec-validation/action2.yml b/rtemsspec/tests/spec-validation/action2.yml index caafed70..a2a23345 100644 --- a/rtemsspec/tests/spec-validation/action2.yml +++ b/rtemsspec/tests/spec-validation/action2.yml @@ -138,7 +138,16 @@ transition-map: B: Y pre-conditions: A: all - B: all + B: + - X +- enabled-by: true + post-conditions: + A: Y + B: X + pre-conditions: + A: N/A + B: + - Y rationale: null references: [] text: | diff --git a/rtemsspec/tests/test_validation.py b/rtemsspec/tests/test_validation.py index 603d9437..c9c4a9d1 100644 --- a/rtemsspec/tests/test_validation.py +++ b/rtemsspec/tests/test_validation.py @@ -167,7 +167,8 @@ def test_validation(tmpdir): typedef enum { ClassicTaskIdentification_Pre_Name_Invalid, ClassicTaskIdentification_Pre_Name_Self, - ClassicTaskIdentification_Pre_Name_Valid + ClassicTaskIdentification_Pre_Name_Valid, + ClassicTaskIdentification_Pre_Name_NA } ClassicTaskIdentification_Pre_Name; typedef enum { @@ -176,12 +177,14 @@ typedef enum { ClassicTaskIdentification_Pre_Node_Invalid, ClassicTaskIdentification_Pre_Node_SearchAll, ClassicTaskIdentification_Pre_Node_SearchOther, - ClassicTaskIdentification_Pre_Node_SearchLocal + ClassicTaskIdentification_Pre_Node_SearchLocal, + ClassicTaskIdentification_Pre_Node_NA } ClassicTaskIdentification_Pre_Node; typedef enum { ClassicTaskIdentification_Pre_Id_NullPtr, - ClassicTaskIdentification_Pre_Id_Valid + ClassicTaskIdentification_Pre_Id_Valid, + ClassicTaskIdentification_Pre_Id_NA } ClassicTaskIdentification_Pre_Id; typedef enum { @@ -189,7 +192,8 @@ typedef enum { ClassicTaskIdentification_Post_Status_InvAddr, ClassicTaskIdentification_Post_Status_InvName, ClassicTaskIdentification_Post_Status_InvNode, - ClassicTaskIdentification_Post_Status_InvId + ClassicTaskIdentification_Post_Status_InvId, + ClassicTaskIdentification_Post_Status_NA } ClassicTaskIdentification_Post_Status; typedef enum { @@ -197,7 +201,8 @@ typedef enum { ClassicTaskIdentification_Post_Id_NullPtr, ClassicTaskIdentification_Post_Id_Self, ClassicTaskIdentification_Post_Id_LocalTask, - ClassicTaskIdentification_Post_Id_RemoteTask + ClassicTaskIdentification_Post_Id_RemoteTask, + ClassicTaskIdentification_Post_Id_NA } ClassicTaskIdentification_Post_Id; /** @@ -289,6 +294,9 @@ static void ClassicTaskIdentification_Pre_Name_Prepare( ctx->name = rtems_build_name( 'T', 'A', 'S', 'K' ); break; } + + case ClassicTaskIdentification_Pre_Name_NA: + break; } /* Epilogue */ @@ -329,6 +337,9 @@ static void ClassicTaskIdentification_Pre_Node_Prepare( ctx->node = RTEMS_SEARCH_LOCAL_NODE; break; } + + case ClassicTaskIdentification_Pre_Node_NA: + break; } } @@ -348,6 +359,9 @@ static void ClassicTaskIdentification_Pre_Id_Prepare( ctx->id = &ctx->id_value; break; } + + case ClassicTaskIdentification_Pre_Id_NA: + break; } } @@ -381,6 +395,9 @@ static void ClassicTaskIdentification_Post_Status_Check( T_rsc(ctx->status, RTEMS_INVALID_ID); break; } + + case ClassicTaskIdentification_Post_Status_NA: + break; } } @@ -418,6 +435,9 @@ static void ClassicTaskIdentification_Post_Id_Check( T_eq_u32(ctx->id_value, ctx->id_remote_task); break; } + + case ClassicTaskIdentification_Post_Id_NA: + break; } } @@ -614,6 +634,94 @@ static const uint8_t ClassicTaskIdentification_TransitionMap[][ 2 ] = { } }; +static const struct { + uint8_t Pre_Name_NA : 1; + uint8_t Pre_Node_NA : 1; + uint8_t Pre_Id_NA : 1; +} ClassicTaskIdentification_TransitionInfo[] = { + { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { +#if defined(RTEMS_MULTIPROCESSING) + 0, 0, 0 +#else + 0, 0, 0 +#endif + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { + 0, 0, 0 + }, { +#if defined(RTEMS_MULTIPROCESSING) + 0, 0, 0 +#else + 0, 0, 0 +#endif + }, { + 0, 0, 0 + }, { + 0, 0, 0 + } +}; + /** * @fn void T_case_body_ClassicTaskIdentification( void ) * @@ -635,19 +743,37 @@ T_TEST_CASE_FIXTURE( for ( ctx->pcs[ 0 ] = ClassicTaskIdentification_Pre_Name_Invalid; - ctx->pcs[ 0 ] != ClassicTaskIdentification_Pre_Name_Valid + 1; + ctx->pcs[ 0 ] < ClassicTaskIdentification_Pre_Name_NA; ++ctx->pcs[ 0 ] ) { + if ( ClassicTaskIdentification_TransitionInfo[ index ].Pre_Name_NA ) { + ctx->pcs[ 0 ] = ClassicTaskIdentification_Pre_Name_NA; + index += ( ClassicTaskIdentification_Pre_Name_NA - 1 ) + * ClassicTaskIdentification_Pre_Node_NA + * ClassicTaskIdentification_Pre_Id_NA; + } + for ( ctx->pcs[ 1 ] = ClassicTaskIdentification_Pre_Node_Local; - ctx->pcs[ 1 ] != ClassicTaskIdentification_Pre_Node_SearchLocal + 1; + ctx->pcs[ 1 ] < ClassicTaskIdentification_Pre_Node_NA; ++ctx->pcs[ 1 ] ) { + if ( ClassicTaskIdentification_TransitionInfo[ index ].Pre_Node_NA ) { + ctx->pcs[ 1 ] = ClassicTaskIdentification_Pre_Node_NA; + index += ( ClassicTaskIdentification_Pre_Node_NA - 1 ) + * ClassicTaskIdentification_Pre_Id_NA; + } + for ( ctx->pcs[ 2 ] = ClassicTaskIdentification_Pre_Id_NullPtr; - ctx->pcs[ 2 ] != ClassicTaskIdentification_Pre_Id_Valid + 1; + ctx->pcs[ 2 ] < ClassicTaskIdentification_Pre_Id_NA; ++ctx->pcs[ 2 ] ) { + if ( ClassicTaskIdentification_TransitionInfo[ index ].Pre_Id_NA ) { + ctx->pcs[ 2 ] = ClassicTaskIdentification_Pre_Id_NA; + index += ( ClassicTaskIdentification_Pre_Id_NA - 1 ); + } + ClassicTaskIdentification_Pre_Name_Prepare( ctx, ctx->pcs[ 0 ] ); ClassicTaskIdentification_Pre_Node_Prepare( ctx, ctx->pcs[ 1 ] ); ClassicTaskIdentification_Pre_Id_Prepare( ctx, ctx->pcs[ 2 ] ); @@ -916,22 +1042,26 @@ extern "C" { typedef enum { Action2_Pre_A_X, - Action2_Pre_A_Y + Action2_Pre_A_Y, + Action2_Pre_A_NA } Action2_Pre_A; typedef enum { Action2_Pre_B_X, - Action2_Pre_B_Y + Action2_Pre_B_Y, + Action2_Pre_B_NA } Action2_Pre_B; typedef enum { Action2_Post_A_X, - Action2_Post_A_Y + Action2_Post_A_Y, + Action2_Post_A_NA } Action2_Post_A; typedef enum { Action2_Post_B_X, - Action2_Post_B_Y + Action2_Post_B_Y, + Action2_Post_B_NA } Action2_Post_B; /* Header code for Action 2 with Action2_Run() */ @@ -1088,6 +1218,9 @@ static void Action2_Pre_A_Prepare( Action2_Context *ctx, Action2_Pre_A state ) /* Pre A Y */ break; } + + case Action2_Pre_A_NA: + break; } /* Pre A epilogue. */ @@ -1107,6 +1240,9 @@ static void Action2_Pre_B_Prepare( Action2_Context *ctx, Action2_Pre_B state ) /* Pre B Y */ break; } + + case Action2_Pre_B_NA: + break; } /* Pre B epilogue. */ @@ -1126,6 +1262,9 @@ static void Action2_Post_A_Check( Action2_Context *ctx, Action2_Post_A state ) /* Post A Y */ break; } + + case Action2_Post_A_NA: + break; } /* Post A epilogue. */ @@ -1145,6 +1284,9 @@ static void Action2_Post_B_Check( Action2_Context *ctx, Action2_Post_B state ) /* Post B Y */ break; } + + case Action2_Post_B_NA: + break; } /* Post B epilogue. */ @@ -1212,14 +1354,29 @@ static const uint8_t Action2_TransitionMap[][ 2 ] = { Action2_Post_A_X, Action2_Post_B_Y }, { - Action2_Post_A_X, - Action2_Post_B_Y + Action2_Post_A_Y, + Action2_Post_B_X }, { Action2_Post_A_X, Action2_Post_B_Y }, { - Action2_Post_A_X, - Action2_Post_B_Y + Action2_Post_A_Y, + Action2_Post_B_X + } +}; + +static const struct { + uint8_t Pre_A_NA : 1; + uint8_t Pre_B_NA : 1; +} Action2_TransitionInfo[] = { + { + 0, 0 + }, { + 1, 0 + }, { + 0, 0 + }, { + 1, 0 } }; @@ -1240,14 +1397,25 @@ void Action2_Run( int *a, int b, int *c ) for ( ctx->pcs[ 0 ] = Action2_Pre_A_X; - ctx->pcs[ 0 ] != Action2_Pre_A_Y + 1; + ctx->pcs[ 0 ] < Action2_Pre_A_NA; ++ctx->pcs[ 0 ] ) { + if ( Action2_TransitionInfo[ index ].Pre_A_NA ) { + ctx->pcs[ 0 ] = Action2_Pre_A_NA; + index += ( Action2_Pre_A_NA - 1 ) + * Action2_Pre_B_NA; + } + for ( ctx->pcs[ 1 ] = Action2_Pre_B_X; - ctx->pcs[ 1 ] != Action2_Pre_B_Y + 1; + ctx->pcs[ 1 ] < Action2_Pre_B_NA; ++ctx->pcs[ 1 ] ) { + if ( Action2_TransitionInfo[ index ].Pre_B_NA ) { + ctx->pcs[ 1 ] = Action2_Pre_B_NA; + index += ( Action2_Pre_B_NA - 1 ); + } + Action2_Pre_A_Prepare( ctx, ctx->pcs[ 0 ] ); Action2_Pre_B_Prepare( ctx, ctx->pcs[ 1 ] ); /* Action */ diff --git a/rtemsspec/validation.py b/rtemsspec/validation.py index fd758241..f914143c 100644 --- a/rtemsspec/validation.py +++ b/rtemsspec/validation.py @@ -25,6 +25,7 @@ # POSSIBILITY OF SUCH DAMAGE. import itertools +import math import os from typing import Any, Dict, List, NamedTuple, Optional, Tuple @@ -200,14 +201,17 @@ class _TestSuiteItem(_TestItem): content.add("/** @} */") -class _PostCondition(NamedTuple): - """ A set of post conditions with an enabled by expression. """ +class _Transition(NamedTuple): + """ + A transition to a set of post conditions with an enabled by expression. + """ enabled_by: str - conditions: Tuple[int, ...] + post_conditions: Tuple[int, ...] + info: str _DirectiveIndexToEnum = Tuple[Tuple[str, ...], ...] -_TransitionMap = List[List[_PostCondition]] +_TransitionMap = List[List[_Transition]] def _directive_state_to_index( @@ -224,7 +228,8 @@ def _directive_index_to_enum(prefix: str, tuple([f"{prefix}_{condition['name']}"] + [ f"{prefix}_{condition['name']}_{state['name']}" for state in condition["states"] - ]) for index, condition in enumerate(conditions)) + ] + [f"{prefix}_{condition['name']}_NA"]) + for index, condition in enumerate(conditions)) def _directive_add_enum(content: CContent, @@ -353,7 +358,8 @@ class _TestDirectiveItem(_TestItem): def _add_transitions(self, condition_index: int, map_index: int, transition: Dict[str, Any], transition_map: _TransitionMap, - post: Tuple[int, ...]) -> None: + pre_cond_not_applicables: List[str], + post_cond: Tuple[int, ...]) -> None: # pylint: disable=too-many-arguments if condition_index < self._pre_condition_count: condition = self._pre_index_to_condition[condition_index] @@ -361,22 +367,27 @@ class _TestDirectiveItem(_TestItem): map_index *= state_count states = transition["pre-conditions"][condition["name"]] if isinstance(states, str): - assert states == "all" + assert states in ["all", "N/A"] for index in range(state_count): - self._add_transitions(condition_index + 1, - map_index + index, transition, - transition_map, post) + self._add_transitions( + condition_index + 1, map_index + index, transition, + transition_map, + pre_cond_not_applicables + [str(int(states == "N/A"))], + post_cond) else: for state in states: self._add_transitions( condition_index + 1, map_index + self._pre_state_to_index[condition_index][state], - transition, transition_map, post) + transition, transition_map, + pre_cond_not_applicables + ["0"], post_cond) else: enabled_by = enabled_by_to_exp(transition["enabled-by"], ExpressionMapper()) assert enabled_by != "1" or not transition_map[map_index] - transition_map[map_index].append(_PostCondition(enabled_by, post)) + transition_map[map_index].append( + _Transition(enabled_by, post_cond, + " " + ", ".join(pre_cond_not_applicables))) def _get_transition_map(self) -> _TransitionMap: transition_count = 1 @@ -390,7 +401,7 @@ class _TestDirectiveItem(_TestItem): post = tuple(self._post_state_to_index[index][ transition["post-conditions"][self._post_index_to_name[index]]] for index in range(self._post_condition_count)) - self._add_transitions(0, 0, transition, transition_map, post) + self._add_transitions(0, 0, transition, transition_map, [], post) return transition_map def _post_condition_enumerators(self, conditions: Any) -> str: @@ -405,30 +416,49 @@ class _TestDirectiveItem(_TestItem): f"{self.ident}_TransitionMap[][ {self._post_condition_count} ]" " = {", " {" ]) - elements = [] + map_elements = [] + info_elements = [] for transistions in transition_map: assert transistions[0].enabled_by == "1" if len(transistions) == 1: - elements.append( + map_elements.append( self._post_condition_enumerators( - transistions[0].conditions)) + transistions[0].post_conditions)) + info_elements.append(transistions[0].info) else: ifelse = "#if " - enumerators = [] # type: List[str] + map_enumerators = [] # type: List[str] + info_enumerators = [] # type: List[str] for variant in transistions[1:]: - enumerators.append(ifelse + variant.enabled_by) - enumerators.append( - self._post_condition_enumerators(variant.conditions)) + map_enumerators.append(ifelse + variant.enabled_by) + info_enumerators.append(ifelse + variant.enabled_by) + map_enumerators.append( + self._post_condition_enumerators( + variant.post_conditions)) + info_enumerators.append(variant.info) ifelse = "#elif " - enumerators.append("#else") - enumerators.append( + map_enumerators.append("#else") + info_enumerators.append("#else") + map_enumerators.append( self._post_condition_enumerators( - transistions[0].conditions)) - enumerators.append("#endif") - elements.append("\n".join(enumerators)) - content.append(["\n }, {\n".join(elements), " }", "};"]) + transistions[0].post_conditions)) + info_enumerators.append(transistions[0].info) + map_enumerators.append("#endif") + info_enumerators.append("#endif") + map_elements.append("\n".join(map_enumerators)) + info_elements.append("\n".join(info_enumerators)) + content.append(["\n }, {\n".join(map_elements), " }", "};"]) + pre_bits = 2**max(math.ceil(math.log2(self._pre_condition_count)), 3) + content.add("static const struct {") + with content.indent(): + for condition in self["pre-conditions"]: + content.append( + f"uint{pre_bits}_t Pre_{condition['name']}_NA : 1;") + content.add([f"}} {self.ident}_TransitionInfo[] = {{", " {"]) + content.append(["\n }, {\n".join(info_elements), " }", "};"]) def _add_action(self, content: CContent) -> None: + content.add_blank_line() for index, enum in enumerate(self._pre_index_to_enum): content.append(f"{enum[0]}_Prepare( ctx, ctx->pcs[ {index} ] );") content.append(self.substitute_code(self["test-action"])) @@ -445,8 +475,18 @@ class _TestDirectiveItem(_TestItem): var = f"ctx->pcs[ {index} ]" begin = self._pre_index_to_enum[index][1] end = self._pre_index_to_enum[index][-1] - with content.for_loop(f"{var} = {begin}", f"{var} != {end} + 1", + with content.for_loop(f"{var} = {begin}", f"{var} < {end}", f"++{var}"): + name = self._item['pre-conditions'][index]["name"] + pre_na = f"{self.ident}_TransitionInfo[ index ].Pre_{name}_NA" + with content.condition(pre_na): + content.append(f"{var} = {end};") + content.append(f"index += ( {end} - 1 )") + for index_2 in range(index + 1, self._pre_condition_count): + with content.indent(): + content.append( + f"* {self._pre_index_to_enum[index_2][-1]}") + content.lines[-1] += ";" self._add_for_loops(content, index + 1) else: self._add_action(content) @@ -508,6 +548,9 @@ class _TestDirectiveItem(_TestItem): self.substitute_code(state["test-code"])) content.append("break;") content.add("}") + content.add(f"case {enum[-1]}:") + with content.indent(): + content.append("break;") content.add("}") content.add(self.substitute_code(condition["test-epilogue"])) |