-
Notifications
You must be signed in to change notification settings - Fork 0
/
test_case.py
145 lines (109 loc) · 4.61 KB
/
test_case.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import os
import pprint
import re
from os import PathLike
from pathlib import Path
from typing import Mapping, Sequence, Tuple, Union
import networkx as nx
import networkx.algorithms.isomorphism as iso
import matplotlib.pyplot as plt
import pygraphviz as pgv
from export_dot import modal_to_dot
from parse_dot import parse_dot
import logging
from parse_xml import parse_xml
log = logging.getLogger(__name__)
log.setLevel(level=logging.DEBUG)
modal_contracts = []
def read_directory(path_to_dag) -> Sequence[Mapping[str, PathLike]]:
path_to_dag = Path(path_to_dag)
path_to_dag.resolve()
dag = nx.drawing.nx_pydot.read_dot(path_to_dag)
roots = [n for n, d in dag.in_degree() if d == 0]
log.info(f'Found {len(roots)} root components')
base_dir = path_to_dag.parent
for file in os.scandir(base_dir):
if file.is_file() and re.match(r'.*-mc-.*\.xml', file.name):
mc_path = convert_component(Path(base_dir, file.name), mc=True)
mc_graph = nx.drawing.nx_pydot.read_dot(mc_path)
modal_contracts.append((mc_graph, mc_path))
tests = []
for root in roots:
test_case, _ = add_branch(dag, root, Path(path_to_dag.parent))
tests += test_case
return tests
def add_branch(graph: nx.DiGraph, root_node, base_path) -> Tuple[Sequence[Mapping], Path]:
rename = convert_component(Path(base_path, root_node))
test_cases = []
test = {}
out_degree = graph.out_degree(root_node)
in_degree = graph.in_degree(root_node)
if out_degree == 2:
log.info('Found decomposition')
test['type'] = 'decomp'
for child in graph.adj[root_node]:
if re.match(r'.*extended.*context.*', child):
log.warning(f'Found extended context. Trying to find base context ...')
context = Path(base_path, re.sub('extended-', '', child))
if not context.exists():
log.error('Can not find context!')
raise FileNotFoundError(f'Context component not found, expected \'{context}\'')
new_context = convert_component(context)
test['context'] = new_context
elif re.match(r'.*system.*', child):
child_path = convert_component(Path(base_path, child))
test['system'] = child_path
log.info('Finding corresponding modal-contract ...')
log.debug(f'mc subgraph search for {rename}')
current_subgraph = nx.drawing.nx_pydot.read_dot(rename)
def is_subgraph(mc_info) -> bool:
nonlocal current_subgraph
graph, path = mc_info
try:
GM = iso.GraphMatcher(graph, current_subgraph, edge_match=iso.categorical_edge_match(['label'], ['-']))
return GM.subgraph_is_monomorphic()
except KeyError:
log.debug('Lib-Error in subgraph matching!')
return False
candidates = list(filter(is_subgraph, modal_contracts))
if len(candidates) > 1:
log.info(f'Found multiple matching contracts: {candidates}')
elif len(candidates) == 0:
log.warning('Found no matching contract!')
else:
test['modal_contract'] = candidates[0][1]
modal_contracts.remove(candidates[0])
#best_fit = max(modal_contracts, key=lambda mc: nx.graph_edit_distance(current_subgraph, mc))
#modal_contracts.remove(best_fit)
#print(nx.graph_edit_distance(current_subgraph, best_fit))
test['orig_sys'] = rename
elif in_degree == 2:
log.info('Found composition')
test['type'] = 'comp'
id = 0
for child in graph.predecessors(root_node):
child_path = convert_component(Path(base_path, child))
test[f'input{id}'] = child_path
id += 1
test['merge'] = rename
else:
log.warning(f'Found passing node {root_node}')
if len(test) > 0:
test_cases.append(test)
for child in graph.adj[root_node]:
tests, _ = add_branch(graph, child, base_path)
test_cases += tests
return test_cases, rename
def convert_component(path: Union[str, PathLike], mc=False) -> Path:
root_file = Path(path)
if not root_file.exists():
raise FileNotFoundError(f'File does not exists: {root_file}')
elif root_file.suffix != '.xml':
raise ValueError(f'Expected xml file, got {root_file.suffix}')
rename_to = root_file.with_suffix('.dot')
if rename_to.exists():
pass
#return rename_to
graph_repr = parse_xml(root_file)
modal_to_dot(str(rename_to.absolute()), graph_repr, mc=mc)
return rename_to