def AddActionListToGraph(parent: ActionNode, current: ActionNode, action_list: List[Action], end: ActionNode, partial_tests: Set[CoverageTest]) -> None: nonlocal root_node assert isinstance(parent, ActionNode) assert isinstance(end, ActionNode) assert len(action_list) > 0 only_state_check_actions = True current.AssertValidity() end.AssertValidity() for action in action_list: assert isinstance(action, Action) if action.is_state_check: parent.AddStateCheckAction(action, ActionCoverage.PARTIAL) parent.partial_coverage_tests.update(partial_tests) continue only_state_check_actions = False if action.name in parent.children: current = parent.children[action.name] else: current = ActionNode(action) current.coverage = ActionCoverage.PARTIAL parent.AddChild(current) current.partial_coverage_tests.update(partial_tests) parent = current if current == end: return if only_state_check_actions: # If only state_check actions were added, then no need to add a new # edge. return logging.info("Merging children of\n{" + parent.GetGraphPathStr() + "}\n{" + end.GetGraphPathStr() + "}") if current.action.name is end.action.name: MergeNodes(current, end) else: MergeChildren(current, end) root_node.AssertChildrenValidity()
def CreateFullCoverageActionGraph(root_node: ActionNode, tests: List[CoverageTest]) -> ActionNode: assert isinstance(root_node, ActionNode) assert isinstance(tests, list) for test in tests: assert isinstance(test, CoverageTest) parent = root_node for action in test.actions: assert isinstance(action, Action) assert parent is not None if action.is_state_check: parent.AddStateCheckAction(action, ActionCoverage.FULL) else: node = None if action.name in parent.children: node = parent.children[action.name] else: node = ActionNode(action) parent.AddChild(node) node.coverage = ActionCoverage.FULL node.full_coverage_tests.add(test) parent = node
def MergeNodes(node_a: ActionNode, node_b: ActionNode) -> ActionNode: assert not node_a.dead assert not node_b.dead if node_a == node_b: return node_a assert node_a.action.name == node_b.action.name logging.info("Merging nodes with paths:\n{" + node_a.GetGraphPathStr() + "},\n{" + node_b.GetGraphPathStr() + "}") new_node = ActionNode(node_a.action) new_node.coverage = (ActionCoverage.FULL if node_a.coverage == ActionCoverage.FULL or node_b.coverage == ActionCoverage.FULL else ActionCoverage.PARTIAL) new_node.state_check_actions = node_a.state_check_actions new_node.state_check_actions.update(node_b.state_check_actions) new_node.state_check_actions_coverage = MergeStateCheckCoverage( node_a.state_check_actions_coverage, node_b.state_check_actions_coverage) new_node.full_coverage_tests = node_a.full_coverage_tests new_node.full_coverage_tests.update(node_b.full_coverage_tests) new_node.partial_coverage_tests = node_a.partial_coverage_tests new_node.partial_coverage_tests.update(node_b.partial_coverage_tests) children_a = node_a.children.copy() children_b = node_b.children.copy() parents_a = node_a.parents.copy() parents_b = node_b.parents.copy() # Fully remove the merging nodes from the graph for child in list(children_a.values()) + list(children_b.values()): if new_node.action.name in child.parents: del child.parents[new_node.action.name] for parent in list(parents_a.values()) + list(parents_b.values()): if new_node.action.name in parent.children: del parent.children[new_node.action.name] # Merge children. # Start by adding the non-intersecting children to the dictionary. children = ({ k: children_a.get(k, children_b.get(k)).ResolveToAliveNode() for k in (children_a.keys() ^ children_b.keys()) }) # For all children that are the same, they must be merged. children.update({ k: MergeNodes(children_a[k].ResolveToAliveNode(), children_b[k].ResolveToAliveNode()) for k in (children_a.keys() & children_b.keys()) }) # Merge parents. # Start by adding the non-intersecting parents to the dictionary. parents = ({ k: parents_a.get(k, parents_b.get(k)).ResolveToAliveNode() for k in (parents_a.keys() ^ parents_b.keys()) }) # For all parents that are the same, they must be merged. parents.update({ k: MergeNodes(parents_a[k].ResolveToAliveNode(), parents_b[k].ResolveToAliveNode()) for k in (parents_a.keys() & parents_b.keys()) }) # Re-add the node back into the graph. for child in children.values(): child = child.ResolveToAliveNode() new_node.AddChild(child) for parent in parents.values(): parent = parent.ResolveToAliveNode() parent.AddChild(new_node) node_a.dead = new_node node_b.dead = new_node new_node.AssertValidity() return new_node