[rtems-central commit] validation: Add ability to skip action transitions

Sebastian Huber sebh at rtems.org
Mon Jul 27 13:46:55 UTC 2020


Module:    rtems-central
Branch:    master
Commit:    55e17d23c133681cf4a6a24e5190216f5378f1e8
Changeset: http://git.rtems.org/rtems-central/commit/?id=55e17d23c133681cf4a6a24e5190216f5378f1e8

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Mon Jul 27 14:54:13 2020 +0200

validation: Add ability to skip action transitions

---

 rtemsspec/tests/spec-validation/action2.yml      |  24 +++++
 rtemsspec/tests/spec-validation/directive.yml    |   1 +
 rtemsspec/tests/test_validation.py               | 115 ++++++++++++++---------
 rtemsspec/validation.py                          |  24 ++++-
 spec/req/rtems/ident-local.yml                   |   1 +
 spec/req/rtems/ident.yml                         |   1 +
 spec/req/rtems/tasks/ident.yml                   |   1 +
 spec/spec/requirement-action-skip-reasons.yml    |  27 ++++++
 spec/spec/requirement-action-transition-post.yml |  10 ++
 spec/spec/requirement-action.yml                 |   4 +
 10 files changed, 160 insertions(+), 48 deletions(-)

diff --git a/rtemsspec/tests/spec-validation/action2.yml b/rtemsspec/tests/spec-validation/action2.yml
index a2a2334..a2b852e 100644
--- a/rtemsspec/tests/spec-validation/action2.yml
+++ b/rtemsspec/tests/spec-validation/action2.yml
@@ -66,11 +66,19 @@ pre-conditions:
       /* Pre B Y */
     text: |
       Pre B Y.
+  - name: Z
+    test-code: |
+      /* Pre B Z */
+    text: |
+      Pre B Z.
   test-epilogue: |
     /* Pre B epilogue. */
   test-prologue: |
     /* Pre B prologue. */
 requirement-type: functional
+skip-reasons:
+  SkipReason: |
+    Skip it due to some reason.
 test-action: |
   /* Action */
 test-brief: |
@@ -148,6 +156,22 @@ transition-map:
     A: N/A
     B:
     - Y
+- enabled-by: true
+  post-conditions:
+    A: X
+    B: X
+  pre-conditions:
+    A:
+    - X
+    B:
+    - Z
+- enabled-by: true
+  post-conditions: SkipReason
+  pre-conditions:
+    A:
+    - Y
+    B:
+    - Z
 rationale: null
 references: []
 text: |
diff --git a/rtemsspec/tests/spec-validation/directive.yml b/rtemsspec/tests/spec-validation/directive.yml
index e8842fe..2c8c20f 100644
--- a/rtemsspec/tests/spec-validation/directive.yml
+++ b/rtemsspec/tests/spec-validation/directive.yml
@@ -152,6 +152,7 @@ pre-conditions:
   test-epilogue: null
   test-prologue: null
 requirement-type: functional
+skip-reasons: {}
 test-action: |
   ctx->status = rtems_task_ident( ctx->name, ctx->node, ctx->id );
 test-brief: Test rtems_task_ident() brief description.
diff --git a/rtemsspec/tests/test_validation.py b/rtemsspec/tests/test_validation.py
index c9c4a9d..459f7cc 100644
--- a/rtemsspec/tests/test_validation.py
+++ b/rtemsspec/tests/test_validation.py
@@ -635,90 +635,91 @@ static const uint8_t ClassicTaskIdentification_TransitionMap[][ 2 ] = {
 };
 
 static const struct {
+  uint8_t Skip : 1;
   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, 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, 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
+    0, 0, 0, 0
 #else
-    0, 0, 0
+    0, 0, 0, 0
 #endif
   }, {
-    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
+    0, 0, 0, 0
 #else
-    0, 0, 0
+    0, 0, 0, 0
 #endif
   }, {
-    0, 0, 0
+    0, 0, 0, 0
   }, {
-    0, 0, 0
+    0, 0, 0, 0
   }
 };
 
@@ -774,6 +775,11 @@ T_TEST_CASE_FIXTURE(
           index += ( ClassicTaskIdentification_Pre_Id_NA - 1 );
         }
 
+        if ( ClassicTaskIdentification_TransitionInfo[ index ].Skip ) {
+          ++index;
+          continue;
+        }
+
         ClassicTaskIdentification_Pre_Name_Prepare( ctx, ctx->pcs[ 0 ] );
         ClassicTaskIdentification_Pre_Node_Prepare( ctx, ctx->pcs[ 1 ] );
         ClassicTaskIdentification_Pre_Id_Prepare( ctx, ctx->pcs[ 2 ] );
@@ -1049,6 +1055,7 @@ typedef enum {
 typedef enum {
   Action2_Pre_B_X,
   Action2_Pre_B_Y,
+  Action2_Pre_B_Z,
   Action2_Pre_B_NA
 } Action2_Pre_B;
 
@@ -1193,7 +1200,8 @@ static const char * const Action2_PreDesc_A[] = {
 
 static const char * const Action2_PreDesc_B[] = {
   "X",
-  "Y"
+  "Y",
+  "Z"
 };
 
 static const char * const * const Action2_PreDesc[] = {
@@ -1241,6 +1249,11 @@ static void Action2_Pre_B_Prepare( Action2_Context *ctx, Action2_Pre_B state )
       break;
     }
 
+    case Action2_Pre_B_Z: {
+      /* Pre B Z */
+      break;
+    }
+
     case Action2_Pre_B_NA:
       break;
   }
@@ -1358,25 +1371,36 @@ static const uint8_t Action2_TransitionMap[][ 2 ] = {
     Action2_Post_B_X
   }, {
     Action2_Post_A_X,
+    Action2_Post_B_X
+  }, {
+    Action2_Post_A_X,
     Action2_Post_B_Y
   }, {
     Action2_Post_A_Y,
     Action2_Post_B_X
+  }, {
+    Action2_Post_A_Y,
+    Action2_Post_B_Y
   }
 };
 
 static const struct {
+  uint8_t Skip : 1;
   uint8_t Pre_A_NA : 1;
   uint8_t Pre_B_NA : 1;
 } Action2_TransitionInfo[] = {
   {
-    0, 0
+    0, 0, 0
   }, {
-    1, 0
+    0, 1, 0
   }, {
-    0, 0
+    0, 0, 0
+  }, {
+    0, 0, 0
+  }, {
+    0, 1, 0
   }, {
-    1, 0
+    1, 0, 0
   }
 };
 
@@ -1416,6 +1440,11 @@ void Action2_Run( int *a, int b, int *c )
         index += ( Action2_Pre_B_NA - 1 );
       }
 
+      if ( Action2_TransitionInfo[ index ].Skip ) {
+        ++index;
+        continue;
+      }
+
       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 f914143..8dddec9 100644
--- a/rtemsspec/validation.py
+++ b/rtemsspec/validation.py
@@ -398,10 +398,20 @@ class _TestDirectiveItem(_TestItem):
         transition_map = [list() for _ in range(transition_count)
                           ]  # type: _TransitionMap
         for transition in self["transition-map"]:
-            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)
+            if isinstance(transition["post-conditions"], dict):
+                info = ["0"]
+                post_cond = tuple(
+                    self._post_state_to_index[index][
+                        transition["post-conditions"][
+                            self._post_index_to_name[index]]]
+                    for index in range(self._post_condition_count))
+            else:
+                info = ["1"]
+                post_cond = tuple(
+                    len(self._post_state_to_index[index]) - 1
+                    for index in range(self._post_condition_count))
+            self._add_transitions(0, 0, transition, transition_map, info,
+                                  post_cond)
         return transition_map
 
     def _post_condition_enumerators(self, conditions: Any) -> str:
@@ -448,9 +458,11 @@ class _TestDirectiveItem(_TestItem):
                 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)
+        pre_bits = 2**max(math.ceil(math.log2(self._pre_condition_count + 1)),
+                          3)
         content.add("static const struct {")
         with content.indent():
+            content.append(f"uint{pre_bits}_t Skip : 1;")
             for condition in self["pre-conditions"]:
                 content.append(
                     f"uint{pre_bits}_t Pre_{condition['name']}_NA : 1;")
@@ -458,6 +470,8 @@ class _TestDirectiveItem(_TestItem):
         content.append(["\n  }, {\n".join(info_elements), "  }", "};"])
 
     def _add_action(self, content: CContent) -> None:
+        with content.condition(f"{self.ident}_TransitionInfo[ index ].Skip"):
+            content.append(["++index;", "continue;"])
         content.add_blank_line()
         for index, enum in enumerate(self._pre_index_to_enum):
             content.append(f"{enum[0]}_Prepare( ctx, ctx->pcs[ {index} ] );")
diff --git a/spec/req/rtems/ident-local.yml b/spec/req/rtems/ident-local.yml
index 38bf9cd..9bb542f 100644
--- a/spec/req/rtems/ident-local.yml
+++ b/spec/req/rtems/ident-local.yml
@@ -83,6 +83,7 @@ pre-conditions:
   test-epilogue: null
   test-prologue: null
 requirement-type: functional
+skip-reasons: {}
 test-action: |
   ctx->status = ( *ctx->action )( ctx->name, ctx->id );
 test-brief: null
diff --git a/spec/req/rtems/ident.yml b/spec/req/rtems/ident.yml
index b56603b..1a9bbfb 100644
--- a/spec/req/rtems/ident.yml
+++ b/spec/req/rtems/ident.yml
@@ -136,6 +136,7 @@ pre-conditions:
   test-epilogue: null
   test-prologue: null
 requirement-type: functional
+skip-reasons: {}
 test-action: |
   ctx->status = ( *ctx->action )( ctx->name, ctx->node, ctx->id );
 test-brief: null
diff --git a/spec/req/rtems/tasks/ident.yml b/spec/req/rtems/tasks/ident.yml
index 0a8171d..3d2d687 100644
--- a/spec/req/rtems/tasks/ident.yml
+++ b/spec/req/rtems/tasks/ident.yml
@@ -43,6 +43,7 @@ pre-conditions:
   test-epilogue: null
   test-prologue: null
 requirement-type: functional
+skip-reasons: {}
 test-action: |
   if ( ctx->id != NULL ) {
     ctx->status = rtems_task_ident( RTEMS_SELF, 0xdeadbeef, ctx->id );
diff --git a/spec/spec/requirement-action-skip-reasons.yml b/spec/spec/requirement-action-skip-reasons.yml
new file mode 100644
index 0000000..75be7ed
--- /dev/null
+++ b/spec/spec/requirement-action-skip-reasons.yml
@@ -0,0 +1,27 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: spec-member
+  uid: root
+spec-description: null
+spec-example: null
+spec-info:
+  dict:
+    attributes: {}
+    description: |
+      This set of attributes specifies skip reasons used to justify why
+      transitions in the transition map are skipped.
+    generic-attributes:
+      description: |
+        The key defines the name of a skip reason.  The name can be used in
+        :ref:`SpecTypeActionRequirementTransitionPostConditions` to skip the
+        corresponding transitions.  The value shall give a reason why the
+        transitions are skipped.
+      key-spec-type: requirement-action-name
+      value-spec-type: str
+    mandatory-attributes: all
+spec-name: Action Requirement Skip Reasons
+spec-type: requirement-action-skip-reasons
+type: spec
diff --git a/spec/spec/requirement-action-transition-post.yml b/spec/spec/requirement-action-transition-post.yml
index 7fca2f1..935484e 100644
--- a/spec/spec/requirement-action-transition-post.yml
+++ b/spec/spec/requirement-action-transition-post.yml
@@ -22,6 +22,16 @@ spec-info:
       key-spec-type: requirement-action-name
       value-spec-type: requirement-action-name
     mandatory-attributes: all
+  str:
+    assert:
+      and:
+      - re: ^[A-Z][a-zA-Z0-9]+$
+      - not:
+          eq: NA
+    description: |
+      It shall be the name of a skip reason.  If a skip reason is given instead
+      of a listing of post-condition states, then this transition is skipped
+      and no test code runs for this transition.
 spec-name: Action Requirement Transition Post-Conditions
 spec-type: requirement-action-transition-post
 type: spec
diff --git a/spec/spec/requirement-action.yml b/spec/spec/requirement-action.yml
index 8eb7b7b..6afa787 100644
--- a/spec/spec/requirement-action.yml
+++ b/spec/spec/requirement-action.yml
@@ -81,6 +81,7 @@ spec-example: |
     test-epilogue: null
     test-prologue: null
   requirement-type: functional
+  skip-reasons: {}
   test-action: |
     /* Call the function of the action */
   test-brief: null
@@ -137,6 +138,9 @@ spec-info:
       pre-conditions:
         description: null
         spec-type: requirement-action-condition-list
+      skip-reasons:
+        description: null
+        spec-type: requirement-action-skip-reasons
       test-action:
         description: |
           It shall be the test action code.



More information about the vc mailing list