Skip to content

Commit 18aa009

Browse files
Expose MockMicrogridApiClient and MockComponent (#28)
2 parents 39419cc + dba5111 commit 18aa009

6 files changed

Lines changed: 50 additions & 10 deletions

File tree

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,15 @@ tonic = "0.14"
2323
tonic-prost = "0.14"
2424
tracing = { version = "0.1" }
2525
tracing-subscriber = { version = "0.3" }
26+
tokio-stream = { version = "0.1.17", features = ["sync"], optional = true }
2627

2728
[dev-dependencies]
2829
tracing-subscriber = { version = "0.3", features = ["std", "env-filter"] }
2930
tokio = { version = "1.48", features = ["test-util"] }
3031
tokio-stream = { version = "0.1.17", features = ["sync"] }
3132

32-
3333
[build-dependencies]
3434
tonic-prost-build = { version = "0.14", features = ["cleanup-markdown"] }
35+
36+
[features]
37+
test-utils = ["dep:tokio-stream"]

RELEASE_NOTES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
- The microgrid client now tolerates the API server being absent or returning incomplete data at startup. `MicrogridClientHandle::try_new` establishes the gRPC connection lazily, so it succeeds regardless of whether the server is reachable; transient stream errors are then handled by the existing per-stream retry loop. `LogicalMeterHandle::try_new` (and therefore `Microgrid::try_new`) wraps the entire component-graph setup — listing components, listing connections, and building the graph — in a single retry loop that sleeps 3 seconds between attempts, so applications block waiting for the server and a valid graph instead of exiting with an error.
1414

1515
- `Bounds::combine_parallel`, `Bounds::intersect`, and `Bounds::merge_if_overlapping` are now public, allowing external callers to combine bounds without going through higher-level types.
16+
- Put test utils under a feature gate.
17+
- Added `MockMicrogridApiClient::augment_electrical_component_bounds`: It captures requests so that these can be used in test cases. Obtain the list of captured requests using `MockMicrogridApiClient::augment_bounds_calls_handle` (also new).
18+
- Added `MockComponent.add_component_bounds`: It allows to add metric bounds to a mock component.
1619

1720
## Bug Fixes
1821

src/client.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ pub use proto::common::microgrid::electrical_components::{
1818
ElectricalComponent, ElectricalComponentCategory,
1919
};
2020

21-
#[cfg(test)]
22-
pub(crate) mod test_utils;
21+
#[cfg(any(test, feature = "test-utils"))]
22+
#[expect(clippy::unwrap_used, clippy::panic, clippy::expect_used)]
23+
pub mod test_utils;

src/client/proto.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ mod pb {
1717
// Only export what we need
1818
pub use pb::frequenz::api::common::v1alpha8 as common;
1919
pub use pb::frequenz::api::microgrid::v1alpha18 as microgrid;
20-
#[cfg(test)]
20+
#[cfg(any(test, feature = "test-utils"))]
2121
pub use pb::google;
2222

2323
mod electrical_component;

src/client/test_utils.rs

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,25 @@
66
mod tokio_synced_clock;
77
pub use tokio_synced_clock::TokioSyncedClock;
88

9+
use std::sync::Mutex;
910
use std::{sync::Arc, time::SystemTime};
10-
1111
use tokio_stream::wrappers::ReceiverStream;
1212
use tonic::Response;
1313

14+
use super::MicrogridApiClient;
1415
use crate::wall_clock_timer::Clock as _;
1516
use crate::{
1617
client::proto::{
1718
common::{
1819
metrics::{
19-
Metric, MetricSample, MetricValueVariant, SimpleMetricValue, metric_value_variant,
20+
Bounds, Metric, MetricSample, MetricValueVariant, SimpleMetricValue,
21+
metric_value_variant,
2022
},
2123
microgrid::electrical_components::{
2224
ElectricalComponent, ElectricalComponentCategory,
2325
ElectricalComponentCategorySpecificInfo, ElectricalComponentConnection,
2426
ElectricalComponentStateCode, ElectricalComponentStateSnapshot,
25-
ElectricalComponentTelemetry, Inverter, InverterType,
27+
ElectricalComponentTelemetry, Inverter, InverterType, MetricConfigBounds,
2628
electrical_component_category_specific_info::Kind,
2729
},
2830
},
@@ -38,8 +40,6 @@ use crate::{
3840
quantity::{Current, Power, ReactivePower, Voltage},
3941
};
4042

41-
use super::MicrogridApiClient;
42-
4343
/// A mock implementation of the `MicrogridApiClient` trait for testing purposes.
4444
///
4545
/// This mock client allows setting predefined responses for each method,
@@ -52,6 +52,7 @@ pub struct MockMicrogridApiClient {
5252
/// share a clone with [`LogicalMeterActor`], and pass another in via
5353
/// [`MockMicrogridApiClient::new_with_clock`].
5454
clock: TokioSyncedClock,
55+
pub augment_bounds_calls: Arc<Mutex<Vec<AugmentElectricalComponentBoundsRequest>>>,
5556
}
5657

5758
/// One row per emitted telemetry frame: `(power, reactive_power, voltage,
@@ -182,6 +183,21 @@ impl MockComponent {
182183
self
183184
}
184185

186+
pub fn add_component_bounds(
187+
mut self,
188+
metric: i32,
189+
lower: Option<f32>,
190+
upper: Option<f32>,
191+
) -> Self {
192+
self.component
193+
.metric_config_bounds
194+
.push(MetricConfigBounds {
195+
metric,
196+
config_bounds: Some(Bounds { lower, upper }),
197+
});
198+
self
199+
}
200+
185201
pub fn with_power(mut self, power: Vec<f32>) -> Self {
186202
let mut metrics = self.metrics;
187203
for (i, p) in power.iter().enumerate() {
@@ -288,6 +304,7 @@ impl MockMicrogridApiClient {
288304
components: vec![],
289305
connections: vec![],
290306
clock,
307+
augment_bounds_calls: Arc::new(Mutex::new(Vec::new())),
291308
};
292309

293310
fn traverse(node: &MockComponent, client: &mut MockMicrogridApiClient) {
@@ -305,6 +322,13 @@ impl MockMicrogridApiClient {
305322

306323
this_client
307324
}
325+
326+
/// Return a handle to captured augment bounds requests.
327+
pub fn augment_bounds_calls_handle(
328+
&self,
329+
) -> Arc<Mutex<Vec<AugmentElectricalComponentBoundsRequest>>> {
330+
self.augment_bounds_calls.clone()
331+
}
308332
}
309333

310334
#[async_trait::async_trait]
@@ -500,7 +524,13 @@ impl MicrogridApiClient for MockMicrogridApiClient {
500524
_request: impl tonic::IntoRequest<AugmentElectricalComponentBoundsRequest> + Send,
501525
) -> std::result::Result<tonic::Response<AugmentElectricalComponentBoundsResponse>, tonic::Status>
502526
{
503-
unimplemented!()
527+
// Capture calls for tests
528+
let req = _request.into_request().into_inner();
529+
self.augment_bounds_calls.lock().unwrap().push(req);
530+
531+
Ok(Response::new(AugmentElectricalComponentBoundsResponse {
532+
valid_until_time: None,
533+
}))
504534
}
505535
}
506536

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,6 @@ pub(crate) mod wall_clock_timer;
3838

3939
mod microgrid;
4040
pub use microgrid::{BatteryPool, Microgrid};
41+
42+
#[cfg(any(test, feature = "test-utils"))]
43+
pub use client::test_utils;

0 commit comments

Comments
 (0)