Skip to content

Commit 2df2f7c

Browse files
committed
test(unit/cli): Rework pre-processor binding manager tests
1 parent 9eaaf81 commit 2df2f7c

7 files changed

Lines changed: 105 additions & 347 deletions

tests/unit/cli/conftest.py

Lines changed: 1 addition & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -80,23 +80,6 @@ def several_inputs_outputs_stream_socket_without_some_arguments_config(several_i
8080
return several_inputs_outputs_stream_config
8181

8282

83-
@pytest.fixture
84-
def several_k8s_pre_processors_config():
85-
"""
86-
Configuration with several k8s processors
87-
"""
88-
return load_configuration_from_json_file(file_name='several_k8s_pre_processors_configuration.json')
89-
90-
91-
@pytest.fixture
92-
def several_k8s_pre_processors_without_some_arguments_config():
93-
"""
94-
Configuration with several k8s processors
95-
"""
96-
return load_configuration_from_json_file(
97-
file_name='several_k8s_pre_processors_without_some_arguments_configuration.json')
98-
99-
10083
@pytest.fixture
10184
def csv_io_postmortem_config(invalid_csv_io_stream_config):
10285
"""
@@ -419,124 +402,12 @@ def empty_pre_processor_config(pre_processor_complete_configuration):
419402
return pre_processor_complete_configuration
420403

421404

422-
@pytest.fixture(params=['k8s_pre_processor_wrong_binding_configuration.json'])
423-
def pre_processor_wrong_binding_configuration(request):
424-
"""
425-
Return a dictionary containing wrong bindings with a pre-processor
426-
"""
427-
return load_configuration_from_json_file(file_name=request.param)
428-
429-
430405
@pytest.fixture(params=['k8s_pre_processor_with_non_existing_puller_configuration.json'])
431406
def pre_processor_with_unexisting_puller_configuration(request):
432407
"""
433408
Return a dictionary containing a pre-processor with a puller that doesn't exist
434409
"""
435-
return load_configuration_from_json_file(
436-
file_name=request.param)
437-
438-
439-
@pytest.fixture(params=['k8s_pre_processor_with_reused_puller_in_bindings_configuration.json'])
440-
def pre_processor_with_reused_puller_in_bindings_configuration(request):
441-
"""
442-
Return a dictionary containing a pre-processor with a puller that doesn't exist
443-
"""
444-
return load_configuration_from_json_file(
445-
file_name=request.param)
446-
447-
448-
@pytest.fixture
449-
def pre_processor_pullers_and_processors_dictionaries(pre_processor_complete_configuration):
450-
"""
451-
Return a dictionary which contains puller actors, a dictionary of processors as well as the pushers
452-
"""
453-
return get_pre_processor_pullers_and_processors_dictionaries_from_configuration(
454-
configuration=pre_processor_complete_configuration)
455-
456-
457-
def get_pre_processor_pullers_and_processors_dictionaries_from_configuration(configuration: dict) -> (dict, dict, dict):
458-
"""
459-
Return a tuple of dictionaries (pullers, processors) created from the given configuration.
460-
:param dict configuration : Dictionary containing the configuration
461-
"""
462-
report_filter = BroadcastReportFilter()
463-
puller_generator = PullerGenerator(report_filter=report_filter)
464-
pullers = puller_generator.generate(main_config=configuration)
465-
466-
pusher_generator = PusherGenerator()
467-
pushers = pusher_generator.generate(main_config=configuration)
468-
469-
route_table = RouteTable()
470-
471-
dispatcher = DispatcherActor('dispatcher', None, pushers, route_table)
472-
473-
report_filter.register(lambda msg: True, dispatcher.get_proxy())
474-
475-
processor_generator = PreProcessorGenerator()
476-
processors = processor_generator.generate(main_config=configuration)
477-
478-
return pullers, processors, pushers
479-
480-
481-
@pytest.fixture
482-
def pre_processor_binding_manager(pre_processor_complete_configuration, pre_processor_pullers_and_processors_dictionaries):
483-
"""
484-
Return a ProcessorBindingManager with a Processor
485-
"""
486-
pullers = pre_processor_pullers_and_processors_dictionaries[0]
487-
processors = pre_processor_pullers_and_processors_dictionaries[1]
488-
489-
return PreProcessorBindingManager(
490-
config=pre_processor_complete_configuration,
491-
pullers=pullers,
492-
processors=processors
493-
)
494-
495-
496-
@pytest.fixture
497-
def pre_processor_binding_manager_with_wrong_binding_types(pre_processor_wrong_binding_configuration):
498-
"""
499-
Return a PreProcessorBindingManager with wrong target for the pre-processor (a pusher instead of a puller)
500-
"""
501-
_, processors, pushers = get_pre_processor_pullers_and_processors_dictionaries_from_configuration(
502-
configuration=pre_processor_wrong_binding_configuration)
503-
504-
return PreProcessorBindingManager(
505-
config=pre_processor_wrong_binding_configuration,
506-
pullers=pushers,
507-
processors=processors
508-
)
509-
510-
511-
@pytest.fixture
512-
def pre_processor_binding_manager_with_unexisting_puller(pre_processor_with_unexisting_puller_configuration):
513-
"""
514-
Return a PreProcessorBindingManager with an unexisting target for the pre-processor (a puller that doesn't exist)
515-
"""
516-
pullers, processors, _ = get_pre_processor_pullers_and_processors_dictionaries_from_configuration(
517-
configuration=pre_processor_with_unexisting_puller_configuration)
518-
519-
return PreProcessorBindingManager(
520-
config=pre_processor_with_unexisting_puller_configuration,
521-
pullers=pullers,
522-
processors=processors
523-
)
524-
525-
526-
@pytest.fixture
527-
def pre_processor_binding_manager_with_reused_puller_in_bindings(
528-
pre_processor_with_reused_puller_in_bindings_configuration):
529-
"""
530-
Return a PreProcessorBindingManager with a puller used by two different pre-processors
531-
"""
532-
pullers, processors, _ = get_pre_processor_pullers_and_processors_dictionaries_from_configuration(
533-
configuration=pre_processor_with_reused_puller_in_bindings_configuration)
534-
535-
return PreProcessorBindingManager(
536-
config=pre_processor_with_reused_puller_in_bindings_configuration,
537-
pullers=pullers,
538-
processors=processors
539-
)
410+
return load_configuration_from_json_file(request.param)
540411

541412

542413
def get_config_with_longest_argument_names(config: dict, arguments: dict):

tests/unit/cli/test_binding_manager.py

Lines changed: 104 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -27,143 +27,161 @@
2727
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2828
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2929

30-
import copy
30+
from unittest.mock import Mock
3131

3232
import pytest
3333

34+
from powerapi.actor import ActorProxy
3435
from powerapi.cli.binding_manager import PreProcessorBindingManager
35-
from powerapi.exception import UnsupportedActorTypeException, UnexistingActorException, TargetActorAlreadyUsed
36+
from powerapi.cli.generator import PreProcessorGenerator, PullerGenerator
37+
from powerapi.dispatcher import DispatcherActor
38+
from powerapi.exception import UnexistingActorException, UnsupportedActorTypeException, TargetActorAlreadyUsed
39+
from powerapi.filter import BroadcastReportFilter
40+
from powerapi.processor.processor_actor import PreProcessorActor, ProcessorActor
41+
from powerapi.puller import PullerActor
3642

3743

38-
def test_create_pre_processor_binding_manager_with_actors(pre_processor_complete_configuration, pre_processor_pullers_and_processors_dictionaries):
44+
class NoopPreprocessor(PreProcessorActor):
3945
"""
40-
Test that a PreProcessorBindingManager is correctly created when an actor and a processor dictionary are provided
46+
Pre-processor actor that does nothing, for testing purposes.
4147
"""
42-
expected_actors_dictionary = copy.copy(pre_processor_pullers_and_processors_dictionaries[0])
43-
expected_processors_dictionary = copy.copy(pre_processor_pullers_and_processors_dictionaries[1])
4448

45-
binding_manager = PreProcessorBindingManager(
46-
config=pre_processor_complete_configuration,
47-
pullers=pre_processor_pullers_and_processors_dictionaries[0],
48-
processors=pre_processor_pullers_and_processors_dictionaries[1]
49-
)
5049

51-
assert binding_manager.actors == expected_actors_dictionary
52-
assert binding_manager.processors == expected_processors_dictionary
50+
@pytest.fixture
51+
def preprocessor_config():
52+
"""
53+
Fixture that provides a configuration with a socket puller and a no-op pre-processor.
54+
"""
55+
return {
56+
'verbose': True,
57+
'stream': True,
58+
'input': {
59+
'pytest-socket-puller': {
60+
'type': 'socket',
61+
'model': 'HWPCReport',
62+
'host': 'localhost',
63+
'port': 8889
64+
}
65+
},
66+
'pre-processor': {
67+
'pytest-noop-preprocessor': {
68+
'type': 'noop',
69+
'puller': 'pytest-socket-puller'
70+
}
71+
}
72+
}
5373

5474

55-
def test_create_processor_binding_manager_without_actors():
75+
@pytest.fixture
76+
def puller_generator() -> PullerGenerator:
5677
"""
57-
Test that a ProcessorBindingManager is correctly created without a dictionary
78+
Fixture that provides a generator for the puller actors.
5879
"""
59-
binding_manager = PreProcessorBindingManager(config={}, pullers=None, processors=None)
80+
report_filter = BroadcastReportFilter()
81+
report_filter.register(lambda _: True, Mock(actor_name='pytest-dispatcher', actor_type=DispatcherActor, spec=ActorProxy))
6082

61-
assert len(binding_manager.actors) == 0
62-
assert len(binding_manager.processors) == 0
83+
generator = PullerGenerator(report_filter)
84+
return generator
6385

6486

65-
def test_process_bindings_for_pre_processor(pre_processor_complete_configuration, pre_processor_pullers_and_processors_dictionaries):
87+
@pytest.fixture
88+
def preprocessor_generator() -> PreProcessorGenerator:
6689
"""
67-
Test that the bindings between a puller and a processor are correctly created
90+
Fixture to return a preprocessor generator with the noop preprocessor available.
6891
"""
69-
pullers = pre_processor_pullers_and_processors_dictionaries[0]
70-
processors = pre_processor_pullers_and_processors_dictionaries[1]
71-
binding_manager = PreProcessorBindingManager(pre_processor_complete_configuration, pullers, processors)
72-
73-
dispatchers = list(pullers['one_puller'].report_filter.dispatchers())
74-
assert len(dispatchers) == 1
75-
assert dispatchers[0].actor_name == 'dispatcher'
92+
generator = PreProcessorGenerator()
7693

77-
binding_manager.process_bindings()
78-
79-
dispatchers = list(pullers['one_puller'].report_filter.dispatchers())
80-
assert len(dispatchers) == 1
81-
assert dispatchers[0].actor_name == 'my_processor'
94+
def _noop_processor_factory(_) -> ProcessorActor:
95+
return NoopPreprocessor('pytest-noop-preprocessor')
8296

83-
assert len(processors['my_processor'].target_actors) == 1
84-
assert processors['my_processor'].target_actors[0].actor_name == 'dispatcher'
97+
generator.add_processor_factory('noop', _noop_processor_factory)
98+
return generator
8599

86100

87-
def test_process_bindings_for_pre_processor_raise_exception_with_wrong_binding_types(pre_processor_binding_manager_with_wrong_binding_types):
101+
def test_preprocessor_binding_manager_replace_puller_target(puller_generator, preprocessor_generator, preprocessor_config):
88102
"""
89-
Test that an exception is raised with a wrong type for the from actor in a binding
103+
The binding manager should replace the target of the puller actor from a dispatcher actor to the pre-processor actor.
90104
"""
105+
pullers = puller_generator.generate(preprocessor_config)
106+
processors = preprocessor_generator.generate(preprocessor_config)
107+
binding_manager = PreProcessorBindingManager(preprocessor_config, pullers, processors)
91108

92-
with pytest.raises(UnsupportedActorTypeException):
93-
pre_processor_binding_manager_with_wrong_binding_types.process_bindings()
109+
puller = pullers['pytest-socket-puller']
110+
assert isinstance(puller, PullerActor)
94111

112+
puller_target_proxy, = puller.report_filter.dispatchers()
113+
assert issubclass(puller_target_proxy.actor_type, DispatcherActor)
114+
assert puller_target_proxy.actor_name == 'pytest-dispatcher'
95115

96-
def test_process_bindings_for_pre_processor_raise_exception_with_no_existing_puller(
97-
pre_processor_binding_manager_with_unexisting_puller):
98-
"""
99-
Test that an exception is raised with a puller that doesn't exist
100-
"""
116+
binding_manager.process_bindings()
101117

102-
with pytest.raises(UnexistingActorException):
103-
pre_processor_binding_manager_with_unexisting_puller.process_bindings()
118+
puller_target_proxy, = puller.report_filter.dispatchers()
119+
assert issubclass(puller_target_proxy.actor_type, PreProcessorActor)
120+
assert puller_target_proxy.actor_name == 'pytest-noop-preprocessor'
104121

105122

106-
def test_process_bindings_for_pre_processor_raise_exception_with_reused_puller_in_bindings(
107-
pre_processor_binding_manager_with_reused_puller_in_bindings):
123+
def test_preprocessor_binding_manager_with_empty_preprocessor_config(puller_generator, preprocessor_config):
108124
"""
109-
Test that an exception is raised when the same puller is used by several processors
125+
The binding manager should not replace the target of the puller actor when there is no pre-processor configuration.
110126
"""
127+
preprocessor_config['pre-processor'] = {}
111128

112-
with pytest.raises(TargetActorAlreadyUsed):
113-
pre_processor_binding_manager_with_reused_puller_in_bindings.process_bindings()
129+
pullers = puller_generator.generate(preprocessor_config)
130+
processors = {}
131+
binding_manager = PreProcessorBindingManager(preprocessor_config, pullers, processors)
114132

133+
puller = pullers['pytest-socket-puller']
134+
assert isinstance(puller, PullerActor)
115135

116-
def test_check_processors_targets_are_unique_raise_exception_with_reused_puller_in_bindings(
117-
pre_processor_binding_manager_with_reused_puller_in_bindings):
118-
"""
119-
Test that an exception is raised when the same puller is used by several processors
120-
"""
121-
with pytest.raises(TargetActorAlreadyUsed):
122-
pre_processor_binding_manager_with_reused_puller_in_bindings.check_processors_targets_are_unique()
136+
puller_target_proxy, = puller.report_filter.dispatchers()
137+
assert issubclass(puller_target_proxy.actor_type, DispatcherActor)
138+
assert puller_target_proxy.actor_name == 'pytest-dispatcher'
123139

140+
binding_manager.process_bindings()
124141

125-
def test_check_processors_targets_are_unique_pass_without_reused_puller_in_bindings(
126-
pre_processor_binding_manager):
127-
"""
128-
Test that a correct without repeated target passes the validation
129-
"""
130-
try:
131-
pre_processor_binding_manager.check_processors_targets_are_unique()
132-
except TargetActorAlreadyUsed:
133-
pytest.fail("Processors targets are not unique")
142+
puller_target_proxy, = puller.report_filter.dispatchers()
143+
assert issubclass(puller_target_proxy.actor_type, DispatcherActor)
144+
assert puller_target_proxy.actor_name == 'pytest-dispatcher'
134145

135146

136-
def check_all_processors_targets(preprocessor_binding_manager: PreProcessorBindingManager):
147+
def test_preprocessor_binding_manager_with_invalid_puller_name(puller_generator, preprocessor_generator, preprocessor_config):
137148
"""
138-
Helper function that checks the processors targets of the given binding manager.
149+
The binding manager should raise an exception when the puller name of the pre-processor is invalid.
139150
"""
140-
for processor_name, processor in preprocessor_binding_manager.processors.items():
141-
preprocessor_binding_manager.check_processor_targets(processor_name, processor)
151+
preprocessor_config['pre-processor']['pytest-noop-preprocessor']['puller'] = 'invalid-puller-target'
142152

153+
pullers = puller_generator.generate(preprocessor_config)
154+
processors = preprocessor_generator.generate(preprocessor_config)
155+
binding_manager = PreProcessorBindingManager(preprocessor_config, pullers, processors)
143156

144-
def test_check_processor_targets_raise_exception_with_no_existing_puller(pre_processor_binding_manager_with_unexisting_puller):
145-
"""
146-
Test that an exception is raised with a puller that doesn't exist
147-
"""
148157
with pytest.raises(UnexistingActorException):
149-
check_all_processors_targets(pre_processor_binding_manager_with_unexisting_puller)
158+
binding_manager.process_bindings()
150159

151160

152-
def test_check_processor_targets_raise_exception_with_raise_exception_with_wrong_binding_types(pre_processor_binding_manager_with_wrong_binding_types):
161+
def test_preprocessor_binding_manager_with_invalid_puller_type(puller_generator, preprocessor_generator, preprocessor_config):
153162
"""
154-
Test that an exception is raised with a puller that doesn't exist
163+
The binding manager should raise an exception when the puller type of the pre-processor is invalid.
155164
"""
165+
pullers = puller_generator.generate(preprocessor_config)
166+
pullers['pytest-socket-puller'] = Mock(name='pytest-socket-puller')
167+
168+
processors = preprocessor_generator.generate(preprocessor_config)
169+
binding_manager = PreProcessorBindingManager(preprocessor_config, pullers, processors)
170+
156171
with pytest.raises(UnsupportedActorTypeException):
157-
check_all_processors_targets(pre_processor_binding_manager_with_wrong_binding_types)
172+
binding_manager.process_bindings()
158173

159174

160-
def test_check_processor_targets_pass_with_correct_targets(pre_processor_binding_manager):
175+
def test_preprocessor_binding_manager_with_duplicate_target(puller_generator, preprocessor_generator, preprocessor_config):
161176
"""
162-
Test that validation of a configuration with existing targets of the correct type
177+
The binding manager should raise an exception when multiple pre-processor have the same target.
163178
"""
164-
try:
165-
check_all_processors_targets(pre_processor_binding_manager)
166-
except UnsupportedActorTypeException as e:
167-
pytest.fail(f'Unsupported actor type: {e}')
168-
except UnexistingActorException as e:
169-
pytest.fail(f'Actor does not exist: {e}')
179+
pre_processors = preprocessor_config['pre-processor']
180+
pre_processors['pytest-noop-preprocessor-duplicate'] = pre_processors['pytest-noop-preprocessor']
181+
182+
pullers = puller_generator.generate(preprocessor_config)
183+
processors = preprocessor_generator.generate(preprocessor_config)
184+
binding_manager = PreProcessorBindingManager(preprocessor_config, pullers, processors)
185+
186+
with pytest.raises(TargetActorAlreadyUsed):
187+
binding_manager.process_bindings()

0 commit comments

Comments
 (0)