baldertest 0.1.0b6__py3-none-any.whl → 0.1.0b7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- _balder/_version.py +1 -1
- _balder/balder_session.py +13 -9
- _balder/console/balder.py +1 -0
- _balder/controllers/base_device_controller.py +2 -3
- _balder/controllers/feature_controller.py +11 -12
- _balder/exceptions.py +1 -1
- _balder/executor/basic_executor.py +33 -19
- _balder/executor/executor_tree.py +46 -34
- _balder/executor/scenario_executor.py +20 -14
- _balder/executor/setup_executor.py +13 -14
- _balder/executor/testcase_executor.py +3 -6
- _balder/executor/variation_executor.py +177 -131
- _balder/previous_executor_mark.py +3 -0
- _balder/routing_path.py +1 -1
- _balder/solver.py +13 -15
- balder/exceptions.py +2 -2
- baldertest-0.1.0b7.dist-info/METADATA +388 -0
- {baldertest-0.1.0b6.dist-info → baldertest-0.1.0b7.dist-info}/RECORD +22 -22
- {baldertest-0.1.0b6.dist-info → baldertest-0.1.0b7.dist-info}/WHEEL +1 -1
- baldertest-0.1.0b6.dist-info/METADATA +0 -92
- {baldertest-0.1.0b6.dist-info → baldertest-0.1.0b7.dist-info}/LICENSE +0 -0
- {baldertest-0.1.0b6.dist-info → baldertest-0.1.0b7.dist-info}/entry_points.txt +0 -0
- {baldertest-0.1.0b6.dist-info → baldertest-0.1.0b7.dist-info}/top_level.txt +0 -0
|
@@ -12,7 +12,7 @@ from _balder.previous_executor_mark import PreviousExecutorMark
|
|
|
12
12
|
from _balder.routing_path import RoutingPath
|
|
13
13
|
from _balder.unmapped_vdevice import UnmappedVDevice
|
|
14
14
|
from _balder.controllers import DeviceController, VDeviceController, FeatureController, NormalScenarioSetupController
|
|
15
|
-
from _balder.exceptions import
|
|
15
|
+
from _balder.exceptions import NotApplicableVariationException, UnclearAssignableFeatureConnectionError
|
|
16
16
|
|
|
17
17
|
if TYPE_CHECKING:
|
|
18
18
|
from _balder.setup import Setup
|
|
@@ -62,6 +62,12 @@ class VariationExecutor(BasicExecutor):
|
|
|
62
62
|
self._original_active_vdevice_mappings: \
|
|
63
63
|
Dict[Type[Device], Dict[Feature, Dict[Type[VDevice], Type[Device]]]] = {}
|
|
64
64
|
|
|
65
|
+
# is True if the applicability check was done
|
|
66
|
+
self._applicability_check_done = False
|
|
67
|
+
#: this property holds the exception of type :class:`NotApplicableVariationException` if the variation can not
|
|
68
|
+
#: be applied, otherwise this property is None
|
|
69
|
+
self._not_applicable_variation_exc = None
|
|
70
|
+
|
|
65
71
|
# contains the result object for the BODY part of this branch
|
|
66
72
|
self.body_result = BranchBodyResult(self)
|
|
67
73
|
|
|
@@ -90,7 +96,7 @@ class VariationExecutor(BasicExecutor):
|
|
|
90
96
|
@property
|
|
91
97
|
def cur_setup_class(self) -> Setup:
|
|
92
98
|
"""property returns the current :class:`Setup` for this variation"""
|
|
93
|
-
return self._parent_executor.
|
|
99
|
+
return self._parent_executor.parent_executor.base_setup_class
|
|
94
100
|
|
|
95
101
|
@property
|
|
96
102
|
def base_device_mapping(self) -> Dict[Type[Device], Type[Device]]:
|
|
@@ -102,11 +108,6 @@ class VariationExecutor(BasicExecutor):
|
|
|
102
108
|
|
|
103
109
|
@property
|
|
104
110
|
def all_child_executors(self) -> List[TestcaseExecutor]:
|
|
105
|
-
return self.testcase_executors
|
|
106
|
-
|
|
107
|
-
@property
|
|
108
|
-
def testcase_executors(self) -> List[TestcaseExecutor]:
|
|
109
|
-
"""returns all sub testcase executors that belongs to this variation-executor"""
|
|
110
111
|
return self._testcase_executors
|
|
111
112
|
|
|
112
113
|
@property
|
|
@@ -131,24 +132,35 @@ class VariationExecutor(BasicExecutor):
|
|
|
131
132
|
`determine_feature_replacement_and_vdevice_mappings()`"""
|
|
132
133
|
return self._abs_setup_feature_vdevice_mappings
|
|
133
134
|
|
|
135
|
+
@property
|
|
136
|
+
def not_applicable_variation_exc(self) -> Union[NotApplicableVariationException, None]:
|
|
137
|
+
return self._not_applicable_variation_exc
|
|
138
|
+
|
|
134
139
|
# ---------------------------------- PROTECTED METHODS -------------------------------------------------------------
|
|
135
140
|
|
|
136
|
-
def _prepare_execution(self):
|
|
141
|
+
def _prepare_execution(self, show_discarded):
|
|
137
142
|
print(" VARIATION ", end='')
|
|
138
143
|
device_map_str = [f"{scenario_device.__qualname__}:{setup_device.__qualname__}"
|
|
139
144
|
for scenario_device, setup_device in self._base_device_mapping.items()]
|
|
140
145
|
print(' | '.join(device_map_str))
|
|
141
|
-
self.
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
146
|
+
if show_discarded and not self.can_be_applied():
|
|
147
|
+
print(f" DISCARDED BECAUSE `{self.not_applicable_variation_exc.args[0]}`")
|
|
148
|
+
else:
|
|
149
|
+
self.determine_abs_variation_connections()
|
|
150
|
+
self.update_scenario_device_feature_instances()
|
|
151
|
+
self.update_active_vdevice_device_mappings_in_all_features()
|
|
152
|
+
self.update_inner_referenced_feature_instances()
|
|
153
|
+
self.exchange_unmapped_vdevice_references()
|
|
154
|
+
self.update_vdevice_referenced_feature_instances()
|
|
155
|
+
self.set_conn_dependent_methods()
|
|
156
|
+
|
|
157
|
+
def _body_execution(self, show_discarded):
|
|
158
|
+
if show_discarded and not self.can_be_applied():
|
|
159
|
+
# do nothing if this variation can not be applied (is discarded)
|
|
160
|
+
return
|
|
161
|
+
|
|
162
|
+
for cur_testcase_executor in self.get_testcase_executors():
|
|
163
|
+
if cur_testcase_executor.has_runnable_tests():
|
|
152
164
|
|
|
153
165
|
cur_testcase_executor.execute()
|
|
154
166
|
elif cur_testcase_executor.prev_mark == PreviousExecutorMark.SKIP:
|
|
@@ -158,13 +170,134 @@ class VariationExecutor(BasicExecutor):
|
|
|
158
170
|
else:
|
|
159
171
|
cur_testcase_executor.set_result_for_whole_branch(ResultState.NOT_RUN)
|
|
160
172
|
|
|
161
|
-
def _cleanup_execution(self):
|
|
173
|
+
def _cleanup_execution(self, show_discarded):
|
|
174
|
+
if show_discarded and not self.can_be_applied():
|
|
175
|
+
# do nothing if this variation can not be applied (is discarded)
|
|
176
|
+
return
|
|
177
|
+
|
|
162
178
|
self.restore_original_vdevice_references()
|
|
163
179
|
self.revert_active_vdevice_device_mappings_in_all_features()
|
|
164
180
|
self.revert_scenario_device_feature_instances()
|
|
165
181
|
|
|
182
|
+
def _verify_applicability_trough_feature_implementation_matching(self):
|
|
183
|
+
"""
|
|
184
|
+
This method validates, that the features in this variation are valid. For this the setup devices must
|
|
185
|
+
implement all the required features of the scenario device. In other words, a feature child class must be
|
|
186
|
+
implemented in the setup device for each feature in the scenario device.
|
|
187
|
+
"""
|
|
188
|
+
for scenario_device, setup_device in self._base_device_mapping.items():
|
|
189
|
+
scenario_device_orig_features = \
|
|
190
|
+
DeviceController.get_for(scenario_device).get_original_instanced_feature_objects()
|
|
191
|
+
for cur_scenario_feature_attr_name, cur_scenario_feature in scenario_device_orig_features.items():
|
|
192
|
+
found_setup_feature_for_scenario_feature = False
|
|
193
|
+
setup_device_instantiated_features = \
|
|
194
|
+
DeviceController.get_for(setup_device).get_all_instantiated_feature_objects()
|
|
195
|
+
for _, cur_setup_feature in setup_device_instantiated_features.items():
|
|
196
|
+
if isinstance(cur_setup_feature, cur_scenario_feature.__class__):
|
|
197
|
+
found_setup_feature_for_scenario_feature = True
|
|
198
|
+
if not found_setup_feature_for_scenario_feature:
|
|
199
|
+
raise NotApplicableVariationException(
|
|
200
|
+
f'no matching setup-level feature found for scenario-level feature '
|
|
201
|
+
f'`{cur_scenario_feature_attr_name} = {cur_scenario_feature.__class__.__name__}()` of device '
|
|
202
|
+
f'`{scenario_device.__qualname__}`')
|
|
203
|
+
|
|
204
|
+
def _verify_applicability_trough_vdevice_feature_impl_matching(self) -> None:
|
|
205
|
+
"""
|
|
206
|
+
This method checks for all vDevices that are in the setups/scenario features of this VariationExecutor, if their
|
|
207
|
+
vDevices-Mappings (so the mapped setup-devices) implements all features that are defined in the vDevices
|
|
208
|
+
"""
|
|
209
|
+
|
|
210
|
+
for cur_scenario_device, cur_replacement_dict in self.feature_replacement.items():
|
|
211
|
+
cur_setup_device = self.get_setup_device_for(scenario_device=cur_scenario_device)
|
|
212
|
+
all_inner_setup_features = \
|
|
213
|
+
DeviceController.get_for(cur_setup_device).get_all_instantiated_feature_objects()
|
|
214
|
+
|
|
215
|
+
# describes the mapping from the new setup feature (key) to the instantiated scenario feature (value)
|
|
216
|
+
# note that this dictionary only contains the required one
|
|
217
|
+
setup_to_scenario_feature_mapping: Dict[Type[Feature], Feature] = {
|
|
218
|
+
cur_replacement_tuple[1]: cur_replacement_tuple[0]
|
|
219
|
+
for cur_attr_name, cur_replacement_tuple in cur_replacement_dict.items()
|
|
220
|
+
if cur_replacement_tuple[0] is not None}
|
|
221
|
+
|
|
222
|
+
# now secure that all features are available in the corresponding setup device, that are defined in the
|
|
223
|
+
# mapped vDevice
|
|
224
|
+
for _, cur_setup_feature_obj in all_inner_setup_features.items():
|
|
225
|
+
# only check if there is a requirement of this feature (the feature is required by the Scenario)
|
|
226
|
+
if cur_setup_feature_obj.__class__ not in setup_to_scenario_feature_mapping.keys():
|
|
227
|
+
# ignore this, because no requirement for this feature
|
|
228
|
+
continue
|
|
229
|
+
related_scenario_feature_obj = setup_to_scenario_feature_mapping[cur_setup_feature_obj.__class__]
|
|
230
|
+
# get vDevice and device mapping
|
|
231
|
+
partner_scenario_vdevice, partner_scenario_device = \
|
|
232
|
+
related_scenario_feature_obj.active_vdevice_device_mapping
|
|
233
|
+
|
|
234
|
+
if partner_scenario_device is None:
|
|
235
|
+
# ignore because no mapping exist here
|
|
236
|
+
continue
|
|
237
|
+
|
|
238
|
+
partner_setup_device = self.get_setup_device_for(scenario_device=partner_scenario_vdevice)
|
|
239
|
+
# get the related vDevice on setup view that is currently active
|
|
240
|
+
mapped_setup_vdevices = [
|
|
241
|
+
cur_vdevice for cur_vdevice
|
|
242
|
+
in FeatureController.get_for(
|
|
243
|
+
cur_setup_feature_obj.__class__).get_abs_inner_vdevice_classes()
|
|
244
|
+
if issubclass(cur_vdevice, partner_scenario_vdevice)]
|
|
245
|
+
if len(mapped_setup_vdevices) != 1:
|
|
246
|
+
# find no mapping for the vDevice -> not possible
|
|
247
|
+
# todo optimize this exception message
|
|
248
|
+
raise NotApplicableVariationException(
|
|
249
|
+
f'can not find a valid setup-level vDevice in setup feature '
|
|
250
|
+
f'`{cur_setup_feature_obj.__class__}`')
|
|
251
|
+
# now check that the setup partner device has all features implemented that are required
|
|
252
|
+
# features from the VDevice
|
|
253
|
+
partner_setup_device_features = \
|
|
254
|
+
DeviceController.get_for(partner_setup_device).get_all_instantiated_feature_objects()
|
|
255
|
+
mapped_setup_vdevices_instantiated_features = \
|
|
256
|
+
VDeviceController.get_for(mapped_setup_vdevices[0]).get_all_instantiated_feature_objects()
|
|
257
|
+
for _, cur_vdevice_feature in mapped_setup_vdevices_instantiated_features.items():
|
|
258
|
+
# check that there exists a child feature in the setup device for every used feature in the
|
|
259
|
+
# vDevice class
|
|
260
|
+
if len([cur_device_feature for _, cur_device_feature in partner_setup_device_features.items()
|
|
261
|
+
if isinstance(cur_device_feature, cur_vdevice_feature.__class__)]) == 0:
|
|
262
|
+
raise NotApplicableVariationException(
|
|
263
|
+
f'can not find a child feature in mapped setup device `{partner_setup_device.__qualname__}`'
|
|
264
|
+
f' for required feature `{cur_vdevice_feature.__class__}` of vDevice '
|
|
265
|
+
f'`{mapped_setup_vdevices[0].__qualname__}`')
|
|
266
|
+
|
|
267
|
+
def _verify_applicability_trough_all_valid_routings(self) -> None:
|
|
268
|
+
"""
|
|
269
|
+
This method ensures that valid routings exist for every defined connection.
|
|
270
|
+
|
|
271
|
+
The check is passed, if the method finds one or more valid routings for EVERY scenario-level
|
|
272
|
+
:class:`Connection`.
|
|
273
|
+
"""
|
|
274
|
+
if not self._routings:
|
|
275
|
+
self.determine_absolute_scenario_device_connections()
|
|
276
|
+
self.create_all_valid_routings()
|
|
277
|
+
for scenario_cnn, cur_routings in self._routings.items():
|
|
278
|
+
if len(cur_routings) == 0:
|
|
279
|
+
raise NotApplicableVariationException(
|
|
280
|
+
f'can not find a valid routing on setup level for the connection `{scenario_cnn.get_tree_str()}` '
|
|
281
|
+
f'between scenario devices `{scenario_cnn.from_device}` and `{scenario_cnn.to_device}`')
|
|
282
|
+
|
|
166
283
|
# ---------------------------------- METHODS -----------------------------------------------------------------------
|
|
167
284
|
|
|
285
|
+
def testsummary(self):
|
|
286
|
+
if self.can_be_applied():
|
|
287
|
+
return super().testsummary()
|
|
288
|
+
return {
|
|
289
|
+
ResultState.NOT_RUN: 0,
|
|
290
|
+
ResultState.FAILURE: 0,
|
|
291
|
+
ResultState.ERROR: 0,
|
|
292
|
+
ResultState.SUCCESS: 0,
|
|
293
|
+
ResultState.SKIP: 0,
|
|
294
|
+
ResultState.COVERED_BY: 0
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
def get_testcase_executors(self) -> List[TestcaseExecutor]:
|
|
298
|
+
"""returns all sub testcase executors that belongs to this variation-executor"""
|
|
299
|
+
return self._testcase_executors
|
|
300
|
+
|
|
168
301
|
def add_testcase_executor(self, testcase_executor: TestcaseExecutor):
|
|
169
302
|
"""
|
|
170
303
|
This method adds a new TestcaseExecutor to the child element list of this object branch
|
|
@@ -226,7 +359,8 @@ class VariationExecutor(BasicExecutor):
|
|
|
226
359
|
# now check if there is a mapping on setup level too
|
|
227
360
|
for cur_replacing_feature in replacing_features:
|
|
228
361
|
mapped_setup_vdevice, mapped_setup_device = cur_replacing_feature.active_vdevice_device_mapping
|
|
229
|
-
if mapped_setup_vdevice is not None and
|
|
362
|
+
if mapped_setup_vdevice is not None and \
|
|
363
|
+
not issubclass(mapped_setup_vdevice, used_scenario_vdevice):
|
|
230
364
|
# drop this feature matching, because we have different vdevice mapped
|
|
231
365
|
cleanup_replacing_features.remove(cur_replacing_feature)
|
|
232
366
|
elif mapped_setup_device is not None and \
|
|
@@ -235,7 +369,7 @@ class VariationExecutor(BasicExecutor):
|
|
|
235
369
|
cleanup_replacing_features.remove(cur_replacing_feature)
|
|
236
370
|
|
|
237
371
|
if len(cleanup_replacing_features) != 1:
|
|
238
|
-
raise
|
|
372
|
+
raise NotApplicableVariationException(
|
|
239
373
|
f'this variation can not be applicable because there was no setup feature implementation of '
|
|
240
374
|
f'`{cur_abstract_scenario_feature_obj.__class__.__name__}` (used by scenario device '
|
|
241
375
|
f'`{cur_scenario_device.__name__}`) in setup device `{cur_setup_device.__name__}`')
|
|
@@ -254,7 +388,7 @@ class VariationExecutor(BasicExecutor):
|
|
|
254
388
|
f"`{cur_abstract_scenario_feature_obj.__class__.__name__}` (used in scenario device "
|
|
255
389
|
f"`{cur_scenario_device.__name__}` and in setup device `{cur_setup_device.__name__}`) - "
|
|
256
390
|
f"VARIATION CAN NOT BE APPLIED")
|
|
257
|
-
raise
|
|
391
|
+
raise NotApplicableVariationException(
|
|
258
392
|
f'this variation can not be applicable because there was no vDevice mapping given on '
|
|
259
393
|
f'scenario or on setup level for the feature '
|
|
260
394
|
f'`{cur_abstract_scenario_feature_obj.__class__.__name__}` (used by scenario device '
|
|
@@ -349,26 +483,6 @@ class VariationExecutor(BasicExecutor):
|
|
|
349
483
|
# can not find some
|
|
350
484
|
return None
|
|
351
485
|
|
|
352
|
-
def has_feature_implementation_matching(self):
|
|
353
|
-
"""
|
|
354
|
-
This method returns True if the features in this variation are valid. For this the setup devices must
|
|
355
|
-
implement all the required features of the scenario device. In other words, a feature child class must be
|
|
356
|
-
implemented in the setup device for each feature in the scenario device.
|
|
357
|
-
"""
|
|
358
|
-
for scenario_device, setup_device in self._base_device_mapping.items():
|
|
359
|
-
scenario_device_orig_features = \
|
|
360
|
-
DeviceController.get_for(scenario_device).get_original_instanced_feature_objects()
|
|
361
|
-
for _, cur_scenario_feature in scenario_device_orig_features.items():
|
|
362
|
-
found_setup_feature_for_scenario_feature = False
|
|
363
|
-
setup_device_instantiated_features = \
|
|
364
|
-
DeviceController.get_for(setup_device).get_all_instantiated_feature_objects()
|
|
365
|
-
for _, cur_setup_feature in setup_device_instantiated_features.items():
|
|
366
|
-
if isinstance(cur_setup_feature, cur_scenario_feature.__class__):
|
|
367
|
-
found_setup_feature_for_scenario_feature = True
|
|
368
|
-
if not found_setup_feature_for_scenario_feature:
|
|
369
|
-
return False
|
|
370
|
-
return True
|
|
371
|
-
|
|
372
486
|
def cleanup_empty_executor_branches(self):
|
|
373
487
|
"""
|
|
374
488
|
This method searches the whole tree and removes branches where an executor item has no own children. It can
|
|
@@ -377,82 +491,6 @@ class VariationExecutor(BasicExecutor):
|
|
|
377
491
|
This method implementation of the :class:`VariationExecutor` does nothing.
|
|
378
492
|
"""
|
|
379
493
|
|
|
380
|
-
def has_vdevice_feature_implementation_matching(self) -> bool:
|
|
381
|
-
"""
|
|
382
|
-
This method checks for all vDevices that are in the setups/scenario features of this VariationExecutor, if their
|
|
383
|
-
vDevices-Mappings (so the mapped setup-devices) implements all features that are defined in the vDevices
|
|
384
|
-
|
|
385
|
-
This method returns false, if there is missing some :class:`Feature` classes.
|
|
386
|
-
"""
|
|
387
|
-
|
|
388
|
-
for cur_scenario_device, cur_replacement_dict in self.feature_replacement.items():
|
|
389
|
-
cur_setup_device = self.get_setup_device_for(scenario_device=cur_scenario_device)
|
|
390
|
-
all_inner_setup_features = \
|
|
391
|
-
DeviceController.get_for(cur_setup_device).get_all_instantiated_feature_objects()
|
|
392
|
-
|
|
393
|
-
# describes the mapping from the new setup feature (key) to the instantiated scenario feature (value)
|
|
394
|
-
# note that this dictionary only contains the required one
|
|
395
|
-
new_to_old_feature_mapping: Dict[Type[Feature], Feature] = {
|
|
396
|
-
cur_replacement_tuple[1]: cur_replacement_tuple[0]
|
|
397
|
-
for cur_attr_name, cur_replacement_tuple in cur_replacement_dict.items()
|
|
398
|
-
if cur_replacement_tuple[0] is not None}
|
|
399
|
-
|
|
400
|
-
# now secure that all features are available in the corresponding setup device, that are defined in the
|
|
401
|
-
# mapped vDevice
|
|
402
|
-
for _, cur_setup_feature_obj in all_inner_setup_features.items():
|
|
403
|
-
# only check if there is a requirement of this feature (the feature is required by the Scenario)
|
|
404
|
-
if cur_setup_feature_obj.__class__ not in new_to_old_feature_mapping.keys():
|
|
405
|
-
# ignore this, because no requirement for this feature
|
|
406
|
-
continue
|
|
407
|
-
related_scenario_feature_obj = new_to_old_feature_mapping[cur_setup_feature_obj.__class__]
|
|
408
|
-
# get vDevice and device mapping
|
|
409
|
-
partner_scenario_vdevice, partner_scenario_device = \
|
|
410
|
-
related_scenario_feature_obj.active_vdevice_device_mapping
|
|
411
|
-
|
|
412
|
-
if partner_scenario_device is None:
|
|
413
|
-
# ignore because no mapping exist here
|
|
414
|
-
continue
|
|
415
|
-
|
|
416
|
-
partner_setup_device = self.get_setup_device_for(scenario_device=partner_scenario_vdevice)
|
|
417
|
-
# get the related vDevice on setup view that is currently active
|
|
418
|
-
mapped_setup_vdevices = [
|
|
419
|
-
cur_vdevice for cur_vdevice
|
|
420
|
-
in FeatureController.get_for(
|
|
421
|
-
cur_setup_feature_obj.__class__).get_abs_inner_vdevice_classes()
|
|
422
|
-
if issubclass(cur_vdevice, partner_scenario_vdevice)]
|
|
423
|
-
if len(mapped_setup_vdevices) != 1:
|
|
424
|
-
# find no mapping for the vDevice -> not possible
|
|
425
|
-
return False
|
|
426
|
-
# now check that the setup partner device has all features implemented that are required
|
|
427
|
-
# features from the VDevice
|
|
428
|
-
partner_setup_device_features = \
|
|
429
|
-
DeviceController.get_for(partner_setup_device).get_all_instantiated_feature_objects()
|
|
430
|
-
mapped_setup_vdevices_instantiated_features = \
|
|
431
|
-
VDeviceController.get_for(mapped_setup_vdevices[0]).get_all_instantiated_feature_objects()
|
|
432
|
-
for _, cur_vdevice_feature in mapped_setup_vdevices_instantiated_features.items():
|
|
433
|
-
# check that there exists a child feature in the setup device for every used feature in the
|
|
434
|
-
# vDevice class
|
|
435
|
-
if len([cur_device_feature for _, cur_device_feature in partner_setup_device_features.items()
|
|
436
|
-
if isinstance(cur_device_feature, cur_vdevice_feature.__class__)]) == 0:
|
|
437
|
-
return False
|
|
438
|
-
return True
|
|
439
|
-
|
|
440
|
-
def has_all_valid_routings(self) -> bool:
|
|
441
|
-
"""
|
|
442
|
-
This method returns true if there exist valid routings for every defined connection. Otherwise, it returns
|
|
443
|
-
false.
|
|
444
|
-
|
|
445
|
-
:return: returns true if the method finds one or more valid routings for EVERY :class:`Connection`. Otherwise,
|
|
446
|
-
it returns false
|
|
447
|
-
"""
|
|
448
|
-
if not self._routings:
|
|
449
|
-
self.determine_absolute_scenario_device_connections()
|
|
450
|
-
self.create_all_valid_routings()
|
|
451
|
-
for _, cur_routings in self._routings.items():
|
|
452
|
-
if len(cur_routings) == 0:
|
|
453
|
-
return False
|
|
454
|
-
return True
|
|
455
|
-
|
|
456
494
|
def update_scenario_device_feature_instances(self):
|
|
457
495
|
"""
|
|
458
496
|
This method ensures that the (mostly abstract) feature instances of a scenario are exchanged with the
|
|
@@ -632,27 +670,35 @@ class VariationExecutor(BasicExecutor):
|
|
|
632
670
|
# object
|
|
633
671
|
setattr(cur_vdevice, cur_vdevice_attr_name, replacing_candidate)
|
|
634
672
|
|
|
635
|
-
def
|
|
673
|
+
def verify_applicability(self) -> None:
|
|
636
674
|
"""
|
|
637
|
-
This method
|
|
675
|
+
This method verifies if this variation is executable. First the method checks if all defined
|
|
638
676
|
:class:`Feature` instances are available and fully implemented in the mapped setup :class:`Device`.
|
|
639
677
|
Furthermore, it checks if their exists a valid routing which also matches the defined class `@for_vdevice`
|
|
640
678
|
definition of the used :class:`Feature` classes.
|
|
641
679
|
"""
|
|
680
|
+
self._applicability_check_done = True
|
|
642
681
|
try:
|
|
643
682
|
self.determine_feature_replacement_and_vdevice_mappings()
|
|
644
683
|
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
except NotApplicableVariationError:
|
|
684
|
+
self._verify_applicability_trough_feature_implementation_matching()
|
|
685
|
+
|
|
686
|
+
self._verify_applicability_trough_vdevice_feature_impl_matching()
|
|
687
|
+
|
|
688
|
+
self._verify_applicability_trough_all_valid_routings()
|
|
689
|
+
except NotApplicableVariationException as not_applicable_variation_exc:
|
|
652
690
|
# this variation can not be used, because the features can not be resolved correctly!
|
|
653
|
-
|
|
691
|
+
self._not_applicable_variation_exc = not_applicable_variation_exc
|
|
692
|
+
self.prev_mark = PreviousExecutorMark.DISCARDED
|
|
693
|
+
|
|
694
|
+
def can_be_applied(self) -> bool:
|
|
695
|
+
"""
|
|
696
|
+
:return: returns True if the previous verify_applicability check was successfully
|
|
697
|
+
"""
|
|
698
|
+
if self._applicability_check_done is not True:
|
|
699
|
+
raise RuntimeError('this method can not be used before no check was executed')
|
|
654
700
|
|
|
655
|
-
return
|
|
701
|
+
return self._not_applicable_variation_exc is None
|
|
656
702
|
|
|
657
703
|
def determine_absolute_scenario_device_connections(self):
|
|
658
704
|
"""
|
|
@@ -698,7 +744,7 @@ class VariationExecutor(BasicExecutor):
|
|
|
698
744
|
cur_mapped_setup_device = list(mapping_dict.values())[0]
|
|
699
745
|
|
|
700
746
|
if cur_mapped_setup_device not in self.base_device_mapping.values():
|
|
701
|
-
raise
|
|
747
|
+
raise NotApplicableVariationException(
|
|
702
748
|
f'the mapped setup device `{cur_mapped_setup_device.__qualname__}` which is mapped to the '
|
|
703
749
|
f'VDevice `{cur_setup_feature_vdevice.__qualname__}` is no part of this variation')
|
|
704
750
|
|
_balder/routing_path.py
CHANGED
|
@@ -301,7 +301,7 @@ class RoutingPath:
|
|
|
301
301
|
raise RoutingBrokenChainError(
|
|
302
302
|
f"can not append gateway, because the device of the gateway (`{elem.device}`) doesn't "
|
|
303
303
|
f"match with the latest end-device (`{self.end_device}`) of this route")
|
|
304
|
-
|
|
304
|
+
if self.end_node_name not in [elem.from_node_name, elem.to_node_name]:
|
|
305
305
|
raise RoutingBrokenChainError(
|
|
306
306
|
f"can not append gateway, because neither the from-node "
|
|
307
307
|
f"(`{elem.from_node_name}`) nor the to-node (`{elem.to_node_name}`) of the gateway match with "
|
_balder/solver.py
CHANGED
|
@@ -198,21 +198,19 @@ class Solver:
|
|
|
198
198
|
if variation_executor is None:
|
|
199
199
|
# variation is not available -> create new VariationExecutor
|
|
200
200
|
variation_executor = VariationExecutor(device_mapping=cur_device_mapping, parent=scenario_executor)
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
if cur_testcase_executor.should_be_ignored():
|
|
215
|
-
variation_executor.prev_mark = PreviousExecutorMark.IGNORE
|
|
201
|
+
variation_executor.verify_applicability()
|
|
202
|
+
|
|
203
|
+
scenario_executor.add_variation_executor(variation_executor)
|
|
204
|
+
for cur_testcase in ScenarioController.get_for(cur_scenario).get_all_test_methods():
|
|
205
|
+
cur_testcase_executor = TestcaseExecutor(cur_testcase, parent=variation_executor)
|
|
206
|
+
variation_executor.add_testcase_executor(cur_testcase_executor)
|
|
207
|
+
|
|
208
|
+
# determine prev_mark IGNORE/SKIP for the testcase
|
|
209
|
+
if cur_testcase_executor.should_be_skipped():
|
|
210
|
+
cur_testcase_executor.prev_mark = PreviousExecutorMark.SKIP
|
|
211
|
+
# always overwrite if it should be ignored
|
|
212
|
+
if cur_testcase_executor.should_be_ignored():
|
|
213
|
+
cur_testcase_executor.prev_mark = PreviousExecutorMark.IGNORE
|
|
216
214
|
|
|
217
215
|
# now filter all elements that have no child elements
|
|
218
216
|
# -> these are items that have no valid matching, because no variation can be applied for it (there are no
|
balder/exceptions.py
CHANGED
|
@@ -5,7 +5,7 @@ from _balder.exceptions import FixtureScopeError, FixtureReferenceError, Unclear
|
|
|
5
5
|
AccessToUnmappedVDeviceException, FeatureOverwritingError, UnknownVDeviceException, RoutingBrokenChainError, \
|
|
6
6
|
IllegalConnectionTypeError, ConnectionMetadataConflictError, DeviceScopeError, ConnectionIntersectionError, \
|
|
7
7
|
UnclearAssignableFeatureConnectionError, InheritanceError, MultiInheritanceError, InnerFeatureResolvingError, \
|
|
8
|
-
VDeviceResolvingError, IllegalVDeviceMappingError,
|
|
8
|
+
VDeviceResolvingError, IllegalVDeviceMappingError, NotApplicableVariationException, UnclearMethodVariationError, \
|
|
9
9
|
UnexpectedPluginMethodReturnValue
|
|
10
10
|
|
|
11
11
|
__all__ = [
|
|
@@ -37,7 +37,7 @@ __all__ = [
|
|
|
37
37
|
"InnerFeatureResolvingError",
|
|
38
38
|
"VDeviceResolvingError",
|
|
39
39
|
"IllegalVDeviceMappingError",
|
|
40
|
-
"
|
|
40
|
+
"NotApplicableVariationException",
|
|
41
41
|
"UnclearMethodVariationError",
|
|
42
42
|
"UnexpectedPluginMethodReturnValue",
|
|
43
43
|
]
|