From 9e7ee2687d8f0189564b9e72a2d598444a8433d2 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 13 Apr 2021 10:07:12 +0200 Subject: validation: Add get_post_conditions() --- rtemsspec/tests/spec-validation/action2.yml | 10 ++++++ rtemsspec/tests/test_validation.py | 19 +++++++++-- rtemsspec/validation.py | 49 +++++++++++++++++++++++++++++ specview.py | 45 ++------------------------ 4 files changed, 79 insertions(+), 44 deletions(-) diff --git a/rtemsspec/tests/spec-validation/action2.yml b/rtemsspec/tests/spec-validation/action2.yml index 822a4701..8c269a12 100644 --- a/rtemsspec/tests/spec-validation/action2.yml +++ b/rtemsspec/tests/spec-validation/action2.yml @@ -272,4 +272,14 @@ transition-map: - B0 C: - C0 +- enabled-by: BOOM + post-conditions: + A: N/A + B: B0 + pre-conditions: + A: N/A + B: + - B0 + C: + - C0 type: requirement diff --git a/rtemsspec/tests/test_validation.py b/rtemsspec/tests/test_validation.py index 938762c3..a35ff371 100644 --- a/rtemsspec/tests/test_validation.py +++ b/rtemsspec/tests/test_validation.py @@ -49,8 +49,13 @@ def test_validation(tmpdir): assert len(list(transition_map.get_variants([]))) == 36 assert len(list(transition_map.get_variants(["RTEMS_MULTIPROCESSING" ]))) == 36 + assert len(list(transition_map.get_post_conditions([]))) == 4 + assert len( + list(transition_map.get_post_conditions(["RTEMS_MULTIPROCESSING" + ]))) == 5 transition_map = TransitionMap(item_cache["/action2"]) assert transition_map.skip_idx_to_name(1) == "SkipReason" + assert len(list(transition_map.get_post_conditions(["BOOM"]))) == 6 generate(validation_config, item_cache) @@ -2109,14 +2114,24 @@ static const Action2_Entry Action2_Entries[] = { { 0, 1, 0, 0, Action2_Post_A_A1, Action2_Post_B_NA }, { 0, 0, 0, 0, Action2_Post_A_A2, Action2_Post_B_B0 }, - { 0, 0, 0, 0, Action2_Post_A_A1, Action2_Post_B_B0 }, { 1, 0, 0, 0, Action2_Post_A_NA, Action2_Post_B_NA }, + { 0, 0, 0, 0, Action2_Post_A_A1, Action2_Post_B_B0 }, +#if defined(BOOM) + { 0, 1, 0, 0, Action2_Post_A_NA, Action2_Post_B_B0 }, +#else + { 0, 0, 0, 0, Action2_Post_A_A1, Action2_Post_B_B0 }, +#endif +#if defined(BOOM) + { 0, 1, 0, 0, Action2_Post_A_NA, Action2_Post_B_B0 }, +#else + { 0, 0, 0, 0, Action2_Post_A_A2, Action2_Post_B_B0 }, +#endif { 0, 0, 0, 0, Action2_Post_A_A3, Action2_Post_B_B0 } }; static const uint8_t Action2_Map[] = { - 2, 2, 2, 0, 0, 0, 1, 1, 1, 1, 1, 4, 0, 0, 0, 3, 3, 3 + 4, 3, 3, 0, 0, 0, 1, 1, 1, 5, 1, 6, 0, 0, 0, 2, 2, 2 }; static size_t Action2_Scope( void *arg, char *buf, size_t n ) diff --git a/rtemsspec/validation.py b/rtemsspec/validation.py index 944764f6..baff5305 100644 --- a/rtemsspec/validation.py +++ b/rtemsspec/validation.py @@ -615,6 +615,10 @@ _POST_COND_OP = { "specified-by": _post_cond_specified_by, } +PostCond = Tuple[int, ...] + +PreCondsOfPostCond = List[Tuple[List[int], ...]] + class TransitionMap: """ Representation of an action requirement transition map. """ @@ -677,6 +681,51 @@ class TransitionMap: variant = transitions[0] yield map_idx, variant + def get_post_conditions( + self, enabled: List[str] + ) -> Iterator[Tuple[PostCond, PreCondsOfPostCond]]: + """ + Yields tuples of post-condition variants and the corresponding + pre-condition variants which are enabled by the enabled list. + + The first entry of the post-condition variant is the skip index. The + remaining entries are post-condition indices. The pre-condition + variants are a list of tuples. Each tuple entry corresponds to a + pre-condition and provides a list of corresponding pre-condition state + indices. + """ + entries = {} # type: Dict[PostCond, PreCondsOfPostCond] + for map_idx, variant in self.get_variants(enabled): + key = (variant.skip, ) + variant.post_cond + entry = entries.setdefault(key, []) + entry.append( + tuple([state] for state in self.map_idx_to_pre_co_states( + map_idx, variant.pre_cond_na))) + for post_cond, pre_conds in sorted(entries.items(), + key=lambda x: (x[0][0], len(x[1]))): + while True: + last = pre_conds[0] + combined_pre_conds = [last] + combined_count = 0 + for row in pre_conds[1:]: + if row == last: + continue + diff = [ + index for index, states in enumerate(last) + if states != row[index] + ] + if len(diff) == 1: + index = diff[0] + combined_count += 1 + last[index].extend(row[index]) + else: + combined_pre_conds.append(row) + last = row + pre_conds = combined_pre_conds + if combined_count == 0: + break + yield post_cond, pre_conds + def _post_process(self) -> None: for map_idx, transitions in enumerate(self): if not transitions or not isinstance( diff --git a/specview.py b/specview.py index 40c988d1..5ef0f731 100755 --- a/specview.py +++ b/specview.py @@ -28,7 +28,7 @@ import argparse import itertools import sys -from typing import Dict, Iterator, List, Set, Tuple +from typing import List, Set, Tuple from rtemsspec.items import Item, ItemCache, Link from rtemsspec.sphinxcontent import SphinxContent @@ -124,48 +124,9 @@ def _to_name(transition_map, co_idx: int, st_idx: int) -> str: f"{transition_map.post_co_idx_st_idx_to_st_name(co_idx, st_idx)}") -_PostCond = Tuple[int, ...] -_Entries = List[Tuple[List[int], ...]] - - -def _get_entries(transition_map: TransitionMap, - enabled: List[str]) -> Iterator[Tuple[_PostCond, _Entries]]: - entries = {} # type: Dict[_PostCond, _Entries] - for map_idx, variant in transition_map.get_variants(enabled): - key = (variant.skip, ) + variant.post_cond - entry = entries.setdefault(key, []) - entry.append( - tuple([state] for state in transition_map.map_idx_to_pre_co_states( - map_idx, variant.pre_cond_na))) - for post_cond, entry in sorted(entries.items(), - key=lambda x: (x[0][0], len(x[1]))): - while True: - last = entry[0] - combined_entry = [last] - combined_count = 0 - for row in entry[1:]: - if row == last: - continue - diff = [ - index for index, states in enumerate(last) - if states != row[index] - ] - if len(diff) == 1: - index = diff[0] - combined_count += 1 - last[index].extend(row[index]) - else: - combined_entry.append(row) - last = row - entry = combined_entry - if combined_count == 0: - break - yield post_cond, entry - - def _action_list(enabled: List[str], item: Item) -> None: transition_map = TransitionMap(item) - for post_cond, entry in _get_entries(transition_map, enabled): + for post_cond, pre_conds in transition_map.get_post_conditions(enabled): print("") if post_cond[0]: print(transition_map.skip_idx_to_name(post_cond[0])) @@ -173,7 +134,7 @@ def _action_list(enabled: List[str], item: Item) -> None: print(", ".join( _to_name(transition_map, co_idx, st_idx) for co_idx, st_idx in enumerate(post_cond[1:]))) - for row in entry: + for row in pre_conds: entries = [] for co_idx, co_states in enumerate(row): co_name = transition_map.pre_co_idx_to_co_name(co_idx) -- cgit v1.2.3