|
11 | 11 | import grpc.aio |
12 | 12 | import pytest |
13 | 13 | from frequenz.api.common import components_pb2, metrics_pb2 |
14 | | -from frequenz.api.microgrid import grid_pb2, inverter_pb2, microgrid_pb2 |
| 14 | +from frequenz.api.microgrid import grid_pb2, inverter_pb2, microgrid_pb2, sensor_pb2 |
15 | 15 | from frequenz.client.base import retry |
16 | 16 | from google.protobuf.empty_pb2 import Empty |
17 | 17 |
|
|
31 | 31 | MeterData, |
32 | 32 | MicrogridApiClient, |
33 | 33 | MicrogridId, |
| 34 | + SensorId, |
34 | 35 | ) |
| 36 | +from frequenz.client.microgrid.sensor import Sensor |
35 | 37 |
|
36 | 38 |
|
37 | 39 | class _TestClient(MicrogridApiClient): |
@@ -461,6 +463,101 @@ async def test_metadata_grpc_error( |
461 | 463 | assert "fake grpc details for metadata" in caplog.records[0].exc_text |
462 | 464 |
|
463 | 465 |
|
| 466 | +async def test_list_sensors(client: _TestClient) -> None: |
| 467 | + """Test the list_sensors() method.""" |
| 468 | + server_response = microgrid_pb2.ComponentList() |
| 469 | + client.mock_stub.ListComponents.return_value = server_response |
| 470 | + assert set(await client.list_sensors()) == set() |
| 471 | + |
| 472 | + # Add a sensor |
| 473 | + sensor_component = microgrid_pb2.Component( |
| 474 | + id=201, |
| 475 | + category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_SENSOR, |
| 476 | + sensor=sensor_pb2.Metadata( |
| 477 | + type=components_pb2.SensorType.SENSOR_TYPE_ACCELEROMETER, |
| 478 | + ), |
| 479 | + ) |
| 480 | + server_response.components.append(sensor_component) |
| 481 | + assert set(await client.list_sensors()) == { |
| 482 | + Sensor(id=SensorId(201)), |
| 483 | + } |
| 484 | + |
| 485 | + # Add another sensor |
| 486 | + sensor_component_2 = microgrid_pb2.Component( |
| 487 | + id=202, |
| 488 | + category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_SENSOR, |
| 489 | + sensor=sensor_pb2.Metadata( |
| 490 | + type=components_pb2.SensorType.SENSOR_TYPE_HYGROMETER |
| 491 | + ), |
| 492 | + ) |
| 493 | + server_response.components.append(sensor_component_2) |
| 494 | + assert set(await client.list_sensors()) == { |
| 495 | + Sensor(id=SensorId(201)), |
| 496 | + Sensor(id=SensorId(202)), |
| 497 | + } |
| 498 | + |
| 499 | + # Add a non-sensor component to the mock response from ListSensors |
| 500 | + # The client.list_sensors() method should filter this out if it's robust, |
| 501 | + # or the ListSensors RPC itself should only return sensor components. |
| 502 | + meter_component = microgrid_pb2.Component( |
| 503 | + id=203, category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_METER |
| 504 | + ) |
| 505 | + server_response.components.append(meter_component) |
| 506 | + # Assert that only SENSOR category components are returned by client.list_sensors() |
| 507 | + assert set(await client.list_sensors()) == { |
| 508 | + Sensor(id=SensorId(201)), |
| 509 | + Sensor(id=SensorId(202)), |
| 510 | + Sensor(id=SensorId(203)), |
| 511 | + } |
| 512 | + # Clean up: remove the meter component from the mock response |
| 513 | + server_response.components.pop() |
| 514 | + |
| 515 | + _replace_components( |
| 516 | + server_response, |
| 517 | + [ |
| 518 | + microgrid_pb2.Component( |
| 519 | + id=204, |
| 520 | + category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_SENSOR, |
| 521 | + sensor=sensor_pb2.Metadata( |
| 522 | + type=components_pb2.SensorType.SENSOR_TYPE_ANEMOMETER |
| 523 | + ), |
| 524 | + ), |
| 525 | + microgrid_pb2.Component( |
| 526 | + id=205, |
| 527 | + category=components_pb2.ComponentCategory.COMPONENT_CATEGORY_SENSOR, |
| 528 | + sensor=sensor_pb2.Metadata( |
| 529 | + type=components_pb2.SensorType.SENSOR_TYPE_PYRANOMETER |
| 530 | + ), |
| 531 | + ), |
| 532 | + ], |
| 533 | + ) |
| 534 | + assert set(await client.list_sensors()) == { |
| 535 | + Sensor(id=SensorId(204)), |
| 536 | + Sensor(id=SensorId(205)), |
| 537 | + } |
| 538 | + |
| 539 | + |
| 540 | +async def test_list_sensors_grpc_error(client: _TestClient) -> None: |
| 541 | + """Test the list_sensors() method when the gRPC call fails.""" |
| 542 | + client.mock_stub.GetMicrogridMetadata.return_value = ( |
| 543 | + microgrid_pb2.MicrogridMetadata(microgrid_id=101) |
| 544 | + ) |
| 545 | + client.mock_stub.ListComponents.side_effect = grpc.aio.AioRpcError( |
| 546 | + mock.MagicMock(name="mock_status"), |
| 547 | + mock.MagicMock(name="mock_initial_metadata"), |
| 548 | + mock.MagicMock(name="mock_trailing_metadata"), |
| 549 | + "fake grpc details", |
| 550 | + "fake grpc debug_error_string", |
| 551 | + ) |
| 552 | + with pytest.raises( |
| 553 | + ApiClientError, |
| 554 | + match=r"Failed calling 'ListComponents' on 'grpc://mock_host:1234': .* " |
| 555 | + r"<status=<MagicMock name='mock_status\.name' id='.*'>>: fake grpc details " |
| 556 | + r"\(fake grpc debug_error_string\)", |
| 557 | + ): |
| 558 | + await client.list_sensors() |
| 559 | + |
| 560 | + |
464 | 561 | @pytest.fixture |
465 | 562 | def meter83() -> microgrid_pb2.Component: |
466 | 563 | """Return a test meter component.""" |
|
0 commit comments