baldertest 0.1.0__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.
Files changed (89) hide show
  1. _balder/__init__.py +12 -0
  2. _balder/_version.py +34 -0
  3. _balder/balder_plugin.py +73 -0
  4. _balder/balder_session.py +341 -0
  5. _balder/balder_settings.py +15 -0
  6. _balder/cnnrelations/__init__.py +7 -0
  7. _balder/cnnrelations/and_connection_relation.py +176 -0
  8. _balder/cnnrelations/base_connection_relation.py +270 -0
  9. _balder/cnnrelations/or_connection_relation.py +65 -0
  10. _balder/collector.py +874 -0
  11. _balder/connection.py +863 -0
  12. _balder/connection_metadata.py +255 -0
  13. _balder/console/__init__.py +0 -0
  14. _balder/console/balder.py +58 -0
  15. _balder/controllers/__init__.py +12 -0
  16. _balder/controllers/base_device_controller.py +72 -0
  17. _balder/controllers/controller.py +29 -0
  18. _balder/controllers/device_controller.py +446 -0
  19. _balder/controllers/feature_controller.py +715 -0
  20. _balder/controllers/normal_scenario_setup_controller.py +402 -0
  21. _balder/controllers/scenario_controller.py +524 -0
  22. _balder/controllers/setup_controller.py +134 -0
  23. _balder/controllers/vdevice_controller.py +95 -0
  24. _balder/decorator_connect.py +104 -0
  25. _balder/decorator_covered_by.py +74 -0
  26. _balder/decorator_fixture.py +29 -0
  27. _balder/decorator_for_vdevice.py +118 -0
  28. _balder/decorator_gateway.py +34 -0
  29. _balder/decorator_insert_into_tree.py +52 -0
  30. _balder/decorator_parametrize.py +31 -0
  31. _balder/decorator_parametrize_by_feature.py +36 -0
  32. _balder/device.py +18 -0
  33. _balder/exceptions.py +182 -0
  34. _balder/executor/__init__.py +0 -0
  35. _balder/executor/basic_executable_executor.py +133 -0
  36. _balder/executor/basic_executor.py +205 -0
  37. _balder/executor/executor_tree.py +217 -0
  38. _balder/executor/parametrized_testcase_executor.py +52 -0
  39. _balder/executor/scenario_executor.py +169 -0
  40. _balder/executor/setup_executor.py +163 -0
  41. _balder/executor/testcase_executor.py +203 -0
  42. _balder/executor/unresolved_parametrized_testcase_executor.py +184 -0
  43. _balder/executor/variation_executor.py +882 -0
  44. _balder/exit_code.py +19 -0
  45. _balder/feature.py +74 -0
  46. _balder/feature_replacement_mapping.py +107 -0
  47. _balder/feature_vdevice_mapping.py +88 -0
  48. _balder/fixture_definition_scope.py +19 -0
  49. _balder/fixture_execution_level.py +22 -0
  50. _balder/fixture_manager.py +483 -0
  51. _balder/fixture_metadata.py +26 -0
  52. _balder/node_gateway.py +103 -0
  53. _balder/objects/__init__.py +0 -0
  54. _balder/objects/connections/__init__.py +0 -0
  55. _balder/objects/connections/osi_1_physical.py +116 -0
  56. _balder/objects/connections/osi_2_datalink.py +35 -0
  57. _balder/objects/connections/osi_3_network.py +47 -0
  58. _balder/objects/connections/osi_4_transport.py +40 -0
  59. _balder/objects/connections/osi_5_session.py +13 -0
  60. _balder/objects/connections/osi_6_presentation.py +13 -0
  61. _balder/objects/connections/osi_7_application.py +83 -0
  62. _balder/objects/devices/__init__.py +0 -0
  63. _balder/objects/devices/this_device.py +12 -0
  64. _balder/parametrization.py +75 -0
  65. _balder/plugin_manager.py +138 -0
  66. _balder/previous_executor_mark.py +23 -0
  67. _balder/routing_path.py +335 -0
  68. _balder/scenario.py +20 -0
  69. _balder/setup.py +18 -0
  70. _balder/solver.py +246 -0
  71. _balder/testresult.py +163 -0
  72. _balder/unmapped_vdevice.py +13 -0
  73. _balder/utils/__init__.py +0 -0
  74. _balder/utils/functions.py +103 -0
  75. _balder/utils/inner_device_managing_metaclass.py +14 -0
  76. _balder/utils/mixin_can_be_covered_by_executor.py +24 -0
  77. _balder/utils/typings.py +4 -0
  78. _balder/vdevice.py +9 -0
  79. balder/__init__.py +56 -0
  80. balder/connections.py +43 -0
  81. balder/devices.py +9 -0
  82. balder/exceptions.py +44 -0
  83. balder/parametrization.py +8 -0
  84. baldertest-0.1.0.dist-info/METADATA +356 -0
  85. baldertest-0.1.0.dist-info/RECORD +89 -0
  86. baldertest-0.1.0.dist-info/WHEEL +5 -0
  87. baldertest-0.1.0.dist-info/entry_points.txt +2 -0
  88. baldertest-0.1.0.dist-info/licenses/LICENSE +21 -0
  89. baldertest-0.1.0.dist-info/top_level.txt +2 -0
_balder/exit_code.py ADDED
@@ -0,0 +1,19 @@
1
+ from enum import Enum
2
+
3
+
4
+ class ExitCode(Enum):
5
+ """
6
+ This enum describes the balder exit codes.
7
+ """
8
+ #: tests were collected and all tests and fixtures terminates with success
9
+ SUCCESS = 0
10
+ #: tests were collected but some tests failed
11
+ TESTS_FAILED = 1
12
+ #: test was interrupted by user
13
+ USER_INTERRUPT = 2
14
+ #: an internal unexpected error occurs
15
+ UNEXPECTED_ERROR = 3
16
+ #: Balder usage error
17
+ BALDER_USAGE_ERROR = 4
18
+ #: no tests were collected
19
+ NO_TESTS_COLLECTED = 5
_balder/feature.py ADDED
@@ -0,0 +1,74 @@
1
+ from __future__ import annotations
2
+ from typing import Type, Dict, Tuple, Union
3
+
4
+ from _balder.device import Device
5
+ from _balder.vdevice import VDevice
6
+ from _balder.utils.inner_device_managing_metaclass import InnerDeviceManagingMetaclass
7
+
8
+
9
+ class Feature(metaclass=InnerDeviceManagingMetaclass):
10
+ """
11
+ This is the basic feature class. It represents an abstract class that should not be used directly. It is the base
12
+ class for all feature elements.
13
+ """
14
+
15
+ def __init__(self, **kwargs):
16
+ """
17
+ :param kwargs: contains a dictionary that references all vDevices of the feature and a real
18
+ scenario :meth:`Device` as value
19
+ """
20
+ from _balder.controllers import FeatureController # pylint: disable=import-outside-toplevel
21
+
22
+ #: this property contains the active mapping for the devices
23
+ self.active_vdevices: Dict[VDevice, Union[Device, str]] = {}
24
+ all_vdevices = FeatureController.get_for(self.__class__).get_abs_inner_vdevice_classes()
25
+ not_processed_kwargs = {}
26
+ for cur_kwargs_key, cur_kwargs_val in kwargs.items():
27
+ if cur_kwargs_key in [cur_vdevice.__name__ for cur_vdevice in all_vdevices]:
28
+ cur_vdevice = [cur_vdevice for cur_vdevice in all_vdevices if cur_vdevice.__name__ == cur_kwargs_key][0]
29
+ if isinstance(cur_kwargs_val, str) or issubclass(cur_kwargs_val, Device):
30
+ if not isinstance(cur_kwargs_val, str) and issubclass(cur_kwargs_val, VDevice):
31
+ raise TypeError(f"the given value of vDevice mapping for vDevice `{cur_kwargs_key}` has to be "
32
+ f"of the type `Device` - it is a subclass of `VDevice` - this is not allowed "
33
+ f"here")
34
+ if self.active_vdevices:
35
+ raise AttributeError(
36
+ "the constructor expects exactly none or one vDevice mapping - found more than one here")
37
+
38
+ self.active_vdevices = {cur_vdevice: cur_kwargs_val}
39
+ else:
40
+ raise TypeError(f"the given value of vDevice mapping for vDevice `{cur_kwargs_key}` has to be of "
41
+ f"the type `Device` or has to be a string with the name of the device class")
42
+ else:
43
+ not_processed_kwargs[cur_kwargs_key] = cur_kwargs_val
44
+ if len(not_processed_kwargs) != 0:
45
+ raise TypeError(
46
+ f"can not resolve the given attributes `{str(not_processed_kwargs)}` in feature "
47
+ f"`{self.__class__.__name__}`")
48
+
49
+ # ---------------------------------- STATIC METHODS ----------------------------------------------------------------
50
+
51
+ # ---------------------------------- CLASS METHODS ----------------------------------------------------------------
52
+
53
+ # ---------------------------------- PROPERTIES --------------------------------------------------------------------
54
+
55
+ @property
56
+ def active_vdevice_device_mapping(self) -> Tuple[Union[None, Type[VDevice]], Union[None, Type[Device]]]:
57
+ """This property returns the mapped device that is active here"""
58
+ if len(self.active_vdevices) == 0:
59
+ return None, None
60
+ return list(self.active_vdevices.keys())[0], list(self.active_vdevices.values())[0]
61
+
62
+ @property
63
+ def active_vdevice(self) -> Union[None, Type[VDevice]]:
64
+ """This property returns the active VDevice that is active here"""
65
+ return self.active_vdevice_device_mapping[0]
66
+
67
+ @property
68
+ def active_mapped_device(self) -> Union[None, Type[VDevice]]:
69
+ """This property returns the active mapped Device"""
70
+ return self.active_vdevice_device_mapping[1]
71
+
72
+ # ---------------------------------- PROTECTED METHODS -------------------------------------------------------------
73
+
74
+ # ---------------------------------- METHODS -----------------------------------------------------------------------
@@ -0,0 +1,107 @@
1
+ from typing import Union, Type
2
+ import dataclasses
3
+ from .device import Device
4
+ from .feature import Feature
5
+ from .controllers import DeviceController
6
+
7
+
8
+ class FeatureReplacementMapping:
9
+ """
10
+ helper object that stores mappings between scenario and setup features - is used in :class:`VariationExecutor`
11
+ """
12
+
13
+ @dataclasses.dataclass
14
+ class FeatureMapping:
15
+ """
16
+ stores a single mapping
17
+ """
18
+ #: the feature attribute name in scenario device
19
+ attr_name: str
20
+ #: the scenario feature instance or None if the current variation does not use this setup feature in scenario
21
+ scenario_feature: Union[Feature, None]
22
+ #: the setup feature that is used for the scenario feature
23
+ setup_feature: Feature
24
+
25
+ def __init__(self):
26
+ self._mappings: list[FeatureReplacementMapping.FeatureMapping] = []
27
+
28
+ @property
29
+ def mappings(self) -> list[FeatureMapping]:
30
+ """
31
+ returns all existing mappings
32
+ """
33
+ return list(self._mappings)
34
+
35
+ @property
36
+ def attr_names(self) -> list[str]:
37
+ """
38
+ returns all used attribute names
39
+ """
40
+ return [mapping.attr_name for mapping in self._mappings]
41
+
42
+ @property
43
+ def all_scenario_features(self) -> list[Feature]:
44
+ """
45
+ returns all scenario features
46
+ """
47
+ return [mapping.scenario_feature for mapping in self._mappings]
48
+
49
+ @property
50
+ def all_setup_features(self) -> list[Feature]:
51
+ """
52
+ returns all setup features
53
+ """
54
+ return [mapping.setup_feature for mapping in self._mappings]
55
+
56
+ def add(self, attr_name: str, scenario_feature: Union[Feature, None], setup_feature: Feature):
57
+ """
58
+ adds a new mapping
59
+
60
+ :param attr_name: the feature attribute name in scenario device
61
+ :param scenario_feature: the scenario feature instance or None if the current variation does not use this setup
62
+ feature in scenario
63
+ :param setup_feature: the setup feature that is used for the scenario feature
64
+ """
65
+ if attr_name in self.attr_names:
66
+ raise KeyError(f'entry for property name `{attr_name}` already exist - can not define it multiple times')
67
+ self._mappings.append(FeatureReplacementMapping.FeatureMapping(attr_name, scenario_feature, setup_feature))
68
+
69
+ def get_features_for_attr_name(self, attr_name: str) -> tuple[Feature, Feature]:
70
+ """
71
+ returns the scenario and its mapped setup feature for a specific attribute name used in the scenario device
72
+ """
73
+ for mapping in self._mappings:
74
+ if mapping.attr_name == attr_name:
75
+ return mapping.scenario_feature, mapping.setup_feature
76
+ raise KeyError(f'entry for property name `{attr_name}` does not exist')
77
+
78
+ def get_replaced_scenario_feature_for(self, setup_feature: Feature) -> Union[Feature, None]:
79
+ """
80
+ returns the mapped scenario feature for a given setup feature
81
+ """
82
+ for mapping in self._mappings:
83
+ if mapping.setup_feature == setup_feature:
84
+ return mapping.scenario_feature
85
+ raise KeyError(f'cannot find setup feature for {setup_feature}')
86
+
87
+ def add_remaining_setup_features_as_autonomous(self, cur_setup_device: Type[Device]):
88
+ """
89
+ Adds all features that were not added as autonomous features.
90
+ """
91
+ cur_setup_features = DeviceController.get_for(cur_setup_device).get_all_instantiated_feature_objects()
92
+
93
+ # also add all setup features that are not assigned as autonomous features
94
+ for cur_setup_feature in cur_setup_features.values():
95
+ if cur_setup_feature not in self.all_setup_features:
96
+ # determine free name
97
+ idx = 0
98
+ autonomous_name = None
99
+ while (autonomous_name is None
100
+ or autonomous_name in self.attr_names):
101
+ autonomous_name = f"_autonomous_feat_{idx}"
102
+ idx += 1
103
+ self.add(
104
+ attr_name=autonomous_name,
105
+ scenario_feature=None,
106
+ setup_feature=cur_setup_feature
107
+ )
@@ -0,0 +1,88 @@
1
+ from __future__ import annotations
2
+ from typing import Type
3
+ import dataclasses
4
+
5
+ from .controllers.feature_controller import FeatureController
6
+ from .device import Device
7
+ from .feature import Feature
8
+ from .vdevice import VDevice
9
+
10
+
11
+ class FeatureVDeviceMapping:
12
+ """
13
+ helper object that stores mappings between :class:`VDevice` and :class:`Device`
14
+ """
15
+
16
+ @dataclasses.dataclass
17
+ class VDeviceDeviceMapping:
18
+ """describes the mapping of one VDevice to one Device"""
19
+ #: the vdevice class
20
+ vdevice: Type[VDevice]
21
+ #: the mapped device to this VDevice
22
+ device: Type[Device]
23
+
24
+ @dataclasses.dataclass
25
+ class VDevicesMapping:
26
+ """
27
+ stores a single mapping
28
+ """
29
+ #: the feature object, this mapping belongs to
30
+ feature: Feature
31
+ #: the available mapping for this feature (at the moment, we only support one)
32
+ mappings: list[FeatureVDeviceMapping.VDeviceDeviceMapping]
33
+
34
+ def __init__(self):
35
+ self._mappings: list[FeatureVDeviceMapping.VDevicesMapping] = []
36
+
37
+ @property
38
+ def mappings(self) -> list[VDevicesMapping]:
39
+ """
40
+ returns all existing mappings
41
+ """
42
+ return list(self._mappings)
43
+
44
+ @property
45
+ def features(self) -> list[Feature]:
46
+ """
47
+ returns all used attribute names
48
+ """
49
+ return [mapping.feature for mapping in self._mappings]
50
+
51
+ def items(self) -> list[tuple[Feature, list[VDeviceDeviceMapping]]]:
52
+ """
53
+ :return: a list of Feature/vdevice mapping tuples
54
+ """
55
+ return [(mapping.feature, mapping.mappings) for mapping in self._mappings]
56
+
57
+ def add(self, feature: Feature, mappings: dict[Type[VDevice], Type[Device]]):
58
+ """
59
+ adds a new mapping
60
+
61
+ :param feature: the :class:`Feature` class this mapping belongs to
62
+ :param mappings: a dictionary that describes the mapping between the :class:`VDevice` and :class:`Device`. The
63
+ :class:`VDevice` needs to be part of the :class:`Feature`
64
+ """
65
+ if feature in self.features:
66
+ raise KeyError(f'entry for feature `{feature}` already exist - can not define it multiple times')
67
+ feature_controller = FeatureController.get_for(feature.__class__)
68
+ vdevice_device_mappings = []
69
+ for cur_vdev, cur_dev in mappings.items():
70
+ if not (isinstance(cur_vdev, type) and issubclass(cur_vdev, VDevice)):
71
+ raise TypeError(f'the provided key objects in mappings needs to be a subclass of `{VDevice.__name__}`')
72
+ if not (isinstance(cur_dev, type) and issubclass(cur_dev, Device)):
73
+ raise TypeError(f'the provided value objects in mappings needs to be a subclass of `{Device.__name__}`')
74
+ if cur_vdev not in feature_controller.get_abs_inner_vdevice_classes():
75
+ raise ValueError(f'the provided VDevice `{cur_vdev}` is not part of the provided feature `{feature}`')
76
+ vdevice_device_mappings.append(self.VDeviceDeviceMapping(cur_vdev, cur_dev))
77
+ new_mapping = self.VDevicesMapping(feature=feature, mappings=vdevice_device_mappings)
78
+
79
+ self._mappings.append(new_mapping)
80
+
81
+ def get_mappings_for_feature(self, feature: Feature) -> list[VDeviceDeviceMapping]:
82
+ """
83
+ returns the list with all mappings for the provided feature
84
+ """
85
+ for cur_item in self._mappings:
86
+ if cur_item.feature == feature:
87
+ return cur_item.mappings
88
+ raise KeyError(f'entry for feature `{feature}` does not exist')
@@ -0,0 +1,19 @@
1
+ from __future__ import annotations
2
+ from typing import List
3
+ from enum import Enum
4
+
5
+
6
+ class FixtureDefinitionScope(Enum):
7
+ """
8
+ This enum describes the definition scope of a fixture. A definition scope is the position the fixture was defined.
9
+ If the fixture was defined within the balderglob.py file, it has the definition-scope `GLOB`. If it is defined
10
+ within a scenario or setup it has the equivalent SCENARIO or SETUP scope.
11
+ """
12
+ GLOB = 'glob'
13
+ SETUP = 'setup'
14
+ SCENARIO = 'scenario'
15
+
16
+ @classmethod
17
+ def get_order(cls) -> List[FixtureDefinitionScope]:
18
+ """returns the priority order of the fixture definition scope"""
19
+ return [cls.GLOB, cls.SETUP, cls.SCENARIO]
@@ -0,0 +1,22 @@
1
+ from __future__ import annotations
2
+ from typing import List
3
+ from enum import Enum
4
+
5
+
6
+ class FixtureExecutionLevel(Enum):
7
+ """
8
+ This enum describes the fixture-execution-level of a fixture. It describes when the fixture should be executed. This
9
+ level will be set in the fixture decorator.
10
+ """
11
+ SESSION = 'session'
12
+ SETUP = 'setup'
13
+ SCENARIO = 'scenario'
14
+ VARIATION = 'variation'
15
+ TESTCASE = 'testcase'
16
+
17
+ @classmethod
18
+ def get_order(cls) -> List[FixtureExecutionLevel]:
19
+ """
20
+ returns the execution order of fixtures
21
+ """
22
+ return [cls.SESSION, cls.SETUP, cls.SCENARIO, cls.VARIATION, cls.TESTCASE]