def adder(model, parameters): first = parameters[0].value second = parameters[1].value return [ DataValue(value=first), DataValue(value=second), DataValue(value=(first + second)), ]
def from_json(cls, json_data): data = deepcopy(json_data) data["optimal_point"] = [ DataValue(**data) for data in data["optimal_point"] ] data["optimal_kpis"] = [ DataValue(**data) for data in data["optimal_kpis"] ] return cls(**data)
def test_string(self): dv = DataValue(type="PRESSURE", name="p1", value=10) self.assertEqual(str(dv), "PRESSURE p1 = 10 (AVERAGE)") dv = DataValue(type="PRESSURE", name="p1", value=10, accuracy=0.1, quality="POOR") self.assertEqual(str(dv), "PRESSURE p1 = 10 +/- 0.1 (POOR)")
def setUp(self): self.registry = ProbeFactoryRegistry() self.plugin = self.registry.plugin self.data_values = [ DataValue(name="foo"), DataValue(name="bar"), DataValue(name="baz"), ] self.slot_map = (InputSlotInfo(name="baz"), InputSlotInfo(name="bar")) self.slots = (Slot(), Slot())
def test_data_source_run_error(self): data_values = [DataValue(name="foo")] self.layer.data_sources[0].input_slot_info = [ InputSlotInfo(name="foo") ] factory = self.registry.data_source_factories[0] factory.raises_on_data_source_run = True with testfixtures.LogCapture() as capture: with self.assertRaises(Exception): self.layer.execute_layer(data_values) capture.check( ( "force_bdss.core.execution_layer", "INFO", "Evaluating for Data Source test_data_source", ), ("force_bdss.core.execution_layer", "INFO", "Passed values:"), ( "force_bdss.core.execution_layer", "INFO", "0: foo = None (AVERAGE)", ), ( "force_bdss.core.execution_layer", "ERROR", "Evaluation could not be performed. " "Run method raised exception.", ), )
def setUp(self): self.plugin = {"id": "id", "name": "name"} self.factory = BaseCSVWriterFactory(plugin=self.plugin) self.notification_listener = self.factory.create_listener() self.model = self.factory.create_model() self.notification_listener.initialize(self.model) self.parameters = [ DataValue(name="p1", value=1.0), DataValue(name="p2", value=5.0), ] self.kpis = [ DataValue(name="kpi1", value=5.7), DataValue(name="kpi2", value=10), ]
def test_getstate_base_event(self): event = BaseDriverEvent() self.assertDictEqual( event.__getstate__(), { "id": "force_bdss.events.base_driver_event.BaseDriverEvent", "model_data": {}, }, ) event = DummyEvent(stateful_data=DataValue(value=1)) self.assertDictEqual( event.__getstate__(), { "id": "force_bdss.tests.dummy_classes" ".notification_listener.DummyEvent", "model_data": { "stateless_data": 1, "stateful_data": { "accuracy": None, "name": "", "quality": "AVERAGE", "type": "", "value": 1, }, }, }, )
def test_error_for_non_data_source(self): data_values = [DataValue(name="foo")] self.layer.data_sources[0].input_slot_info = [ InputSlotInfo(name="foo") ] self.layer.data_sources[0].output_slot_info = [ OutputSlotInfo(name="one") ] def probe_run(self, *args, **kwargs): return ["hello"] factory = self.registry.data_source_factories[0] factory.run_function = probe_run with testfixtures.LogCapture(): with self.assertRaisesRegex( RuntimeError, "The result list returned by DataSource " "test_data_source" " contains an entry that is not a DataValue." " An entry of type <.* 'str'> was instead found" " in position 0." r" Fix the DataSource.run\(\) method to" " return the appropriate entity.", ): self.layer.execute_layer(data_values)
def test_notify_events(self): workflow_file = ProbeWorkflowFile(path=fixtures.get("test_probe.json")) workflow_file.read() workflow = workflow_file.workflow with self.assertTraitChanges(workflow, "event", count=1): with self.assertTraitChanges(workflow.mco_model, "event", count=1): workflow.mco_model.notify_start_event() with self.assertTraitChanges(workflow, "event", count=1): with self.assertTraitChanges(workflow.mco_model, "event", count=1): workflow.mco_model.notify_finish_event() with self.assertTraitChanges(workflow, "event", count=1): with self.assertTraitChanges(workflow.mco_model, "event", count=1): workflow.mco_model.notify_progress_event([ DataValue(value=2), DataValue(value=3) ], [DataValue(value=4), DataValue(value=5)])
def test_progress_event_handling(self): self.operation._initialize_listeners() listener = self.operation.listeners[0] self.operation.workflow.mco_model.notify_progress_event( [DataValue(value=1), DataValue(value=2)], [DataValue(value=3), DataValue(value=4)], ) self.assertIsInstance(listener.deliver_call_args[0][0], MCOProgressEvent) event = listener.deliver_call_args[0][0] self.assertEqual(1, event.optimal_point[0].value, 1) self.assertEqual(2, event.optimal_point[1].value, 2) self.assertEqual(3, event.optimal_kpis[0].value, 3) self.assertEqual(4, event.optimal_kpis[1].value, 4)
def test_execute_layer_results(self): data_values = [ DataValue(name="foo"), DataValue(name="bar"), DataValue(name="baz"), DataValue(name="quux"), ] def run(self, *args, **kwargs): return [DataValue(value=1), DataValue(value=2), DataValue(value=3)] ds_factory = self.registry.data_source_factories[0] ds_factory.input_slots_size = 2 ds_factory.output_slots_size = 3 ds_factory.run_function = run evaluator_model = ds_factory.create_model() evaluator_model.input_slot_info = [ InputSlotInfo(name="foo"), InputSlotInfo(name="quux"), ] evaluator_model.output_slot_info = [ OutputSlotInfo(name="one"), OutputSlotInfo(name=""), OutputSlotInfo(name="three"), ] self.layer.data_sources = [evaluator_model] res = self.layer.execute_layer(data_values) self.assertEqual(len(res), 2) self.assertEqual(res[0].name, "one") self.assertEqual(res[0].value, 1) self.assertEqual(res[1].name, "three") self.assertEqual(res[1].value, 3) with mock.patch( "force_bdss.data_sources.base_data_source.BaseDataSource._run", return_value=run(None)) as mock_run: # mock_run.side_effect = [1, 2] self.layer.execute_layer(data_values) mock_run.assert_called_once()
def test_default_weights_weighted_progress_event(self): event = WeightedMCOProgressEvent( optimal_kpis=[DataValue(value=10)], optimal_point=[DataValue(value=12), DataValue(value=13)], ) self.assertEqual(len(event.optimal_kpis), len(event.weights)) self.assertListEqual( event.weights, [1.0 / len(event.optimal_kpis)] * len(event.optimal_kpis), ) self.assertEqual(event.serialize(), [12, 13, 10, 1.0]) event = WeightedMCOProgressEvent( optimal_kpis=[], optimal_point=[DataValue(value=12), DataValue(value=13)], ) self.assertEqual(len(event.optimal_kpis), len(event.weights)) self.assertListEqual(event.weights, []) self.assertEqual(event.serialize(), [12, 13])
def test_getstate_progress_event(self): event = MCOProgressEvent( optimal_kpis=[DataValue(value=10)], optimal_point=[DataValue(value=12), DataValue(value=13)], ) self.assertEqual( event.__getstate__(), { "id": "force_bdss.events.mco_events.MCOProgressEvent", "model_data": { "optimal_kpis": [{ "accuracy": None, "name": "", "quality": "AVERAGE", "type": "", "value": 10, }], "optimal_point": [ { "accuracy": None, "name": "", "quality": "AVERAGE", "type": "", "value": 12, }, { "accuracy": None, "name": "", "quality": "AVERAGE", "type": "", "value": 13, }, ], }, }, ) self.assertIsInstance(event, UIEventMixin)
def _internal_evaluate(self, parameter_values): """Evaluates the workflow using the given parameter values running on the internal process""" data_values = [ DataValue(type=parameter.type, name=parameter.name, value=value) for parameter, value in zip( self.mco_model.parameters, parameter_values ) ] kpi_results = self.execute(data_values) # Return just the values to the MCO, since the DataValue # class is not specific to the BaseMCO classes kpi_values = [kpi.value for kpi in kpi_results] return kpi_values
def test_error_for_output_slots(self): data_values = [DataValue(name="foo")] self.layer.data_sources[0].input_slot_info = [ InputSlotInfo(name="foo") ] def probe_run(self, *args, **kwargs): return ["too", "many", "data", "values"] factory = self.registry.data_source_factories[0] factory.run_function = probe_run with testfixtures.LogCapture(): with self.assertRaisesRegex( RuntimeError, r"The number of data values \(4 values\) returned" " by 'test_data_source' does not match the number" r" of output slots it specifies \(1 values\)." " This is likely a plugin error.", ): self.layer.execute_layer(data_values)
def test_error_for_incorrect_return_type(self): data_values = [DataValue(name="foo")] self.layer.data_sources[0].input_slot_info = [ InputSlotInfo(name="foo") ] def probe_run(self, *args, **kwargs): return "hello" factory = self.registry.data_source_factories[0] factory.run_function = probe_run with testfixtures.LogCapture(): with self.assertRaisesRegex( RuntimeError, "The run method of data source " "test_data_source must return a list. It " r"returned instead <.* 'str'>. Fix the run\(\)" " method to return the appropriate entity.", ): self.layer.execute_layer(data_values)
def test_serialize_progress_event(self): event = MCOProgressEvent( optimal_kpis=[DataValue(value=10)], optimal_point=[DataValue(value=12), DataValue(value=13)], ) self.assertListEqual(event.serialize(), [12, 13, 10]) event = WeightedMCOProgressEvent( optimal_kpis=[DataValue(value=10)], optimal_point=[DataValue(value=12), DataValue(value=13)], weights=[1.0], ) self.assertListEqual([12, 13, 10, 1.0], event.serialize())
def receive_from_mco(self, model): self.receive_called = True return [ DataValue(name="whatever", value=1.0) for _ in range(self.nb_output_data_values) ]
def run_func(model, parameters): return [DataValue() for _ in range(model.output_slots_size)]
def test_multilayer_execution(self): # The multilayer peforms the following execution # layer 0: in1 + in2 | in3 + in4 # res1 res2 # layer 1: res1 + res2 # res3 # layer 2: res3 * res1 # res4 # layer 3: res4 * res2 # out1 # Final result should be # out1 = ((in1 + in2 + in3 + in4) * (in1 + in2) * (in3 + in4) data_values = [ DataValue(value=10, name="in1"), DataValue(value=15, name="in2"), DataValue(value=3, name="in3"), DataValue(value=7, name="in4"), ] def adder(model, parameters): first = parameters[0].value second = parameters[1].value return [DataValue(value=(first + second))] adder_factory = ProbeDataSourceFactory( self.plugin, input_slots_size=2, output_slots_size=1, run_function=adder, ) def multiplier(model, parameters): first = parameters[0].value second = parameters[1].value return [DataValue(value=(first * second))] multiplier_factory = ProbeDataSourceFactory( self.plugin, input_slots_size=2, output_slots_size=1, run_function=multiplier, ) mco_factory = ProbeMCOFactory(self.plugin) mco_model = mco_factory.create_model() parameter_factory = mco_factory.parameter_factories[0] mco_model.parameters = [ parameter_factory.create_model({"name": "in1"}), parameter_factory.create_model({"name": "in2"}), parameter_factory.create_model({"name": "in3"}), parameter_factory.create_model({"name": "in4"}), ] mco_model.kpis = [KPISpecification(name="out1")] wf = Workflow( mco_model=mco_model, execution_layers=[ ExecutionLayer(), ExecutionLayer(), ExecutionLayer(), ExecutionLayer(), ], ) # Layer 0 model = adder_factory.create_model() model.input_slot_info = [ InputSlotInfo(name="in1"), InputSlotInfo(name="in2"), ] model.output_slot_info = [OutputSlotInfo(name="res1")] wf.execution_layers[0].data_sources.append(model) model = adder_factory.create_model() model.input_slot_info = [ InputSlotInfo(name="in3"), InputSlotInfo(name="in4"), ] model.output_slot_info = [OutputSlotInfo(name="res2")] wf.execution_layers[0].data_sources.append(model) # layer 1 model = adder_factory.create_model() model.input_slot_info = [ InputSlotInfo(name="res1"), InputSlotInfo(name="res2"), ] model.output_slot_info = [OutputSlotInfo(name="res3")] wf.execution_layers[1].data_sources.append(model) # layer 2 model = multiplier_factory.create_model() model.input_slot_info = [ InputSlotInfo(name="res3"), InputSlotInfo(name="res1"), ] model.output_slot_info = [OutputSlotInfo(name="res4")] wf.execution_layers[2].data_sources.append(model) # layer 3 model = multiplier_factory.create_model() model.input_slot_info = [ InputSlotInfo(name="res4"), InputSlotInfo(name="res2"), ] model.output_slot_info = [OutputSlotInfo(name="out1")] wf.execution_layers[3].data_sources.append(model) kpi_results = wf.execute(data_values) self.assertEqual(1, len(kpi_results)) self.assertEqual(8750, kpi_results[0].value)
def multiplier(model, parameters): first = parameters[0].value second = parameters[1].value return [DataValue(value=(first * second))]
def run(self, *args, **kwargs): return [DataValue(value=1), DataValue(value=2), DataValue(value=3)]
def test_kpi_specification_adherence(self): # Often the user may only wish to treat a subset of DataSource # output slots as KPIs. This test makes sure they get what they # ask for! # keep input DataValues constant data_values = [ DataValue(value=99, name="in1"), DataValue(value=1, name="in2"), ] # dummy addition DataSource(a, b) that also returns its inputs # [a, b, a+b] def adder(model, parameters): first = parameters[0].value second = parameters[1].value return [ DataValue(value=first), DataValue(value=second), DataValue(value=(first + second)), ] adder_factory = ProbeDataSourceFactory( self.plugin, input_slots_size=2, output_slots_size=3, run_function=adder, ) mco_factory = ProbeMCOFactory(self.plugin) parameter_factory = mco_factory.parameter_factories[0] mco_model = mco_factory.create_model() # DataSourceModel stats constant throughout model = adder_factory.create_model() model.input_slot_info = [ InputSlotInfo(name="in1"), InputSlotInfo(name="in2"), ] model.output_slot_info = [ OutputSlotInfo(name="out1"), OutputSlotInfo(name="out2"), OutputSlotInfo(name="out3"), ] # test Parameter and KPI spec that follows DataSource slots # exactly mco_model.parameters = [ parameter_factory.create_model({"name": "in1"}), parameter_factory.create_model({"name": "in2"}), ] mco_model.kpis = [ KPISpecification(name="out1"), KPISpecification(name="out2"), KPISpecification(name="out3"), ] # need to make a new workflow for each KPISpecification wf = Workflow(mco_model=mco_model, execution_layers=[ExecutionLayer()]) wf.execution_layers[0].data_sources.append(model) kpi_results = wf.execute(data_values) self.assertEqual(len(kpi_results), 3) self.assertEqual(kpi_results[0].value, 99) self.assertEqual(kpi_results[1].value, 1) self.assertEqual(kpi_results[2].value, 100) self.assertEqual(kpi_results[0].name, "out1") self.assertEqual(kpi_results[1].name, "out2") self.assertEqual(kpi_results[2].name, "out3") # now test all possible combinations of KPISpecification, including # those with KPIs repeated, and empty KPI specification import itertools out_options = [("out1", 99), ("out2", 1), ("out3", 100)] for num_outputs in range(len(out_options) + 2, 0, -1): for spec in itertools.permutations(out_options, r=num_outputs): mco_model.kpis = [ KPISpecification(name=opt[0]) for opt in spec ] wf = Workflow( mco_model=mco_model, execution_layers=[ExecutionLayer()] ) wf.execution_layers[0].data_sources.append(model) kpi_results = wf.execute(data_values) self.assertEqual(len(kpi_results), num_outputs) for i in range(num_outputs): self.assertEqual(kpi_results[i].name, spec[i][0]) self.assertEqual(kpi_results[i].value, spec[i][1])
def test_initialization(self): dv = DataValue() self.assertEqual(dv.type, "") self.assertEqual(dv.value, None) self.assertEqual(dv.accuracy, None) self.assertEqual(dv.quality, "AVERAGE")
def probe_run(self, *args, **kwargs): return [DataValue(), DataValue()]