fix(client-rust): correct outer MxValue data_type and add end-to-end write_array_elements test
This commit is contained in:
@@ -17,6 +17,7 @@ use tonic::{Request, Response, Status};
|
||||
use zb_mom_ww_mxgateway_client::generated::mxaccess_gateway::v1::mx_access_gateway_server::{
|
||||
MxAccessGateway, MxAccessGatewayServer,
|
||||
};
|
||||
use zb_mom_ww_mxgateway_client::generated::mxaccess_gateway::v1::mx_command;
|
||||
use zb_mom_ww_mxgateway_client::generated::mxaccess_gateway::v1::mx_command_reply;
|
||||
use zb_mom_ww_mxgateway_client::generated::mxaccess_gateway::v1::mx_value::Kind;
|
||||
use zb_mom_ww_mxgateway_client::generated::mxaccess_gateway::v1::{
|
||||
@@ -27,8 +28,8 @@ use zb_mom_ww_mxgateway_client::generated::mxaccess_gateway::v1::{
|
||||
MxEventFamily, MxSparseArray, MxSparseElement, MxStatusCategory, MxStatusProxy, MxStatusSource,
|
||||
MxValue, OnAlarmTransitionEvent, OpenSessionReply, OpenSessionRequest, ProtocolStatus,
|
||||
ProtocolStatusCode, QueryActiveAlarmsRequest, RegisterReply, SessionState, StreamAlarmsRequest,
|
||||
StreamEventsRequest, SubscribeResult, Write2BulkEntry, WriteBulkEntry, WriteSecured2BulkEntry,
|
||||
WriteSecuredBulkEntry,
|
||||
StreamEventsRequest, SubscribeResult, Write2BulkEntry, WriteBulkEntry, WriteCommand,
|
||||
WriteSecured2BulkEntry, WriteSecuredBulkEntry,
|
||||
};
|
||||
use zb_mom_ww_mxgateway_client::{
|
||||
next_correlation_id, ApiKey, ClientOptions, CommandError, Error, GatewayClient, MxStatus,
|
||||
@@ -659,6 +660,9 @@ struct FakeState {
|
||||
authorization: Mutex<Option<String>>,
|
||||
last_command_kind: Mutex<Option<i32>>,
|
||||
last_correlation_id: Mutex<Option<String>>,
|
||||
/// Captures the last `WriteCommand` payload received, populated when the
|
||||
/// `WriteOk` override is active. Used by `write_array_elements` e2e test.
|
||||
last_write_command: Mutex<Option<WriteCommand>>,
|
||||
stream_dropped: Arc<AtomicBool>,
|
||||
/// Optional per-test override that pins the fake's `Invoke` handler to
|
||||
/// a specific reply shape (or `Err(Status)`). The default of `None`
|
||||
@@ -683,6 +687,10 @@ enum InvokeOverride {
|
||||
/// Fail the unary call with `Status::unavailable(...)` so the client's
|
||||
/// `Code::Unavailable` -> `Error::Unavailable` mapping is exercised.
|
||||
Unavailable(String),
|
||||
/// Accept a `Write` command (return `protocol_status = Ok`, no payload)
|
||||
/// and capture the decoded `WriteCommand` in
|
||||
/// `FakeState::last_write_command` for inspection.
|
||||
WriteOk,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -764,6 +772,23 @@ impl MxAccessGateway for FakeGateway {
|
||||
..MxCommandReply::default()
|
||||
})),
|
||||
InvokeOverride::Unavailable(message) => Err(Status::unavailable(message)),
|
||||
InvokeOverride::WriteOk => {
|
||||
// Extract and capture the WriteCommand payload so the test
|
||||
// can assert on server_handle, item_handle, user_id, and value.
|
||||
if let Some(mx_command::Payload::Write(write_cmd)) =
|
||||
request.command.and_then(|c| c.payload)
|
||||
{
|
||||
*self.state.last_write_command.lock().await = Some(write_cmd);
|
||||
}
|
||||
Ok(Response::new(MxCommandReply {
|
||||
session_id: request.session_id,
|
||||
correlation_id: "fake-correlation".to_owned(),
|
||||
kind,
|
||||
protocol_status: Some(ok_status("write ok")),
|
||||
payload: None,
|
||||
..MxCommandReply::default()
|
||||
}))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1092,6 +1117,77 @@ fn case_by_id<'a>(cases: &'a [Value], id: &str) -> &'a Value {
|
||||
.unwrap_or_else(|| panic!("missing fixture case {id}"))
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// write_array_elements — end-to-end fake-server test
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#[tokio::test]
|
||||
async fn write_array_elements_routes_sparse_array_write_through_fake_gateway() {
|
||||
// Arrange: stand up the fake gateway with WriteOk so the Write command
|
||||
// succeeds and the sent WriteCommand is captured for inspection.
|
||||
let state = Arc::new(FakeState::default());
|
||||
*state.invoke_override.lock().await = Some(InvokeOverride::WriteOk);
|
||||
let endpoint = spawn_fake_gateway(state.clone()).await;
|
||||
let client = GatewayClient::connect(ClientOptions::new(endpoint))
|
||||
.await
|
||||
.unwrap();
|
||||
let session = client.session("session-fixture");
|
||||
|
||||
// Act: call the public write_array_elements helper.
|
||||
session
|
||||
.write_array_elements(
|
||||
12,
|
||||
34,
|
||||
MxDataType::Integer,
|
||||
10,
|
||||
[(2u32, ClientMxValue::int32(42))],
|
||||
7,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Assert: the fake captured a Write command with the expected handles and
|
||||
// a SparseArrayValue whose total_length and element index/value are correct.
|
||||
let captured = state
|
||||
.last_write_command
|
||||
.lock()
|
||||
.await
|
||||
.take()
|
||||
.expect("fake should have captured a WriteCommand");
|
||||
|
||||
assert_eq!(captured.server_handle, 12, "server_handle must round-trip");
|
||||
assert_eq!(captured.item_handle, 34, "item_handle must round-trip");
|
||||
assert_eq!(captured.user_id, 7, "user_id must round-trip");
|
||||
|
||||
let value = captured.value.expect("WriteCommand must carry a value");
|
||||
assert_eq!(
|
||||
value.data_type, 0,
|
||||
"outer MxValue.data_type must be Unspecified (0), not the element type"
|
||||
);
|
||||
|
||||
let Kind::SparseArrayValue(ref sparse) = value.kind.as_ref().unwrap() else {
|
||||
panic!(
|
||||
"expected SparseArrayValue kind on the outer MxValue, got {:?}",
|
||||
value.kind
|
||||
);
|
||||
};
|
||||
assert_eq!(
|
||||
sparse.element_data_type,
|
||||
MxDataType::Integer as i32,
|
||||
"element_data_type must carry the element type"
|
||||
);
|
||||
assert_eq!(sparse.total_length, 10, "total_length must round-trip");
|
||||
assert_eq!(sparse.elements.len(), 1, "one element supplied");
|
||||
|
||||
let elem = &sparse.elements[0];
|
||||
assert_eq!(elem.index, 2, "element index must round-trip");
|
||||
assert_eq!(
|
||||
elem.value.as_ref().unwrap().kind,
|
||||
Some(Kind::Int32Value(42)),
|
||||
"element value must round-trip"
|
||||
);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// write_array_elements — proto shape unit tests
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user