Skip to content

Commit f19e4f0

Browse files
committed
Implement dsn~usubscription-fetch-subscribers-invalid-topic (eclipse-uprotocol#22)
* update to use latest up-spec version * Implement dsn~usubscription-fetch-subscribers-invalid-topic
1 parent 803fadb commit f19e4f0

File tree

3 files changed

+96
-12
lines changed

3 files changed

+96
-12
lines changed

up-subscription/src/common/helpers.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,31 @@ pub(crate) fn duration_until_timestamp(future_timestamp_millis: u128) -> Option<
8989
None // Timestamp is in the past
9090
}
9191
}
92+
93+
// Validate that a topic URI
94+
// * is a valid uProtocol URI and
95+
// * does not contain a _wildcard_ authority and
96+
// * does not contain a _wildcard_ uEntity instance (`ue_id`) and
97+
// * does not contain a _wildcard_ resource ID
98+
pub(crate) fn validate_uri(topic: &UUri) -> Result<(), ServiceInvocationError> {
99+
topic
100+
.check_validity()
101+
.map_err(|e| ServiceInvocationError::InvalidArgument(format!("Invalid topic URI {e}")))?;
102+
if topic.has_wildcard_authority() {
103+
return Err(ServiceInvocationError::InvalidArgument(
104+
"Topic URI with wildcard authority".to_string(),
105+
));
106+
};
107+
if topic.has_wildcard_entity_instance() {
108+
return Err(ServiceInvocationError::InvalidArgument(
109+
"Topic URI with wildcard entity instance".to_string(),
110+
));
111+
};
112+
if topic.has_wildcard_resource_id() {
113+
return Err(ServiceInvocationError::InvalidArgument(
114+
"Topic URI with wildcard resource id".to_string(),
115+
));
116+
};
117+
118+
Ok(())
119+
}

up-subscription/src/handlers/fetch_subscribers.rs

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ impl RequestHandler for FetchSubscribersRequestHandler {
6464
));
6565
};
6666

67+
// topic input validation
68+
// [impl->dsn~usubscription-fetch-subscribers-invalid-topic~1]
69+
helpers::validate_uri(&topic)?;
70+
6771
// Interact with subscription manager backend
6872
let (respond_to, receive_from) = oneshot::channel::<SubscribersResponse>();
6973
let se = SubscriptionEvent::FetchSubscribers {
@@ -111,8 +115,11 @@ impl RequestHandler for FetchSubscribersRequestHandler {
111115
#[cfg(test)]
112116
mod tests {
113117
use super::*;
118+
use test_case::test_case;
114119
use tokio::sync::mpsc::{self};
115120

121+
use up_rust::UUri;
122+
116123
use crate::{helpers, tests::test_lib};
117124

118125
// [utest->dsn~usubscription-fetch-subscribers-protobuf~1]
@@ -123,7 +130,6 @@ mod tests {
123130
// create request and other required object(s)
124131
let fetch_subscribers_request = FetchSubscribersRequest {
125132
topic: Some(test_lib::helpers::local_topic1_uri()).into(),
126-
offset: Some(42),
127133
..Default::default()
128134
};
129135
let request_payload =
@@ -156,13 +162,9 @@ mod tests {
156162
let subscription_event = subscription_receiver.recv().await.unwrap();
157163
match subscription_event {
158164
SubscriptionEvent::FetchSubscribers {
159-
topic,
160-
offset,
161-
respond_to,
165+
topic, respond_to, ..
162166
} => {
163167
assert_eq!(topic, test_lib::helpers::local_topic1_uri());
164-
assert_eq!(offset, Some(42));
165-
166168
let _ = respond_to.send(SubscribersResponse::default());
167169
}
168170
_ => panic!("Wrong event type"),
@@ -288,4 +290,58 @@ mod tests {
288290
_ => panic!("Wrong error type"),
289291
}
290292
}
293+
294+
// [utest->dsn~usubscription-fetch-subscribers-invalid-topic~1]
295+
#[test_case(UUri::default(); "Bad topic UUri")]
296+
#[test_case(UUri {
297+
authority_name: String::from("*"),
298+
ue_id: test_lib::helpers::TOPIC_LOCAL1_ID,
299+
ue_version_major: test_lib::helpers::TOPIC_LOCAL1_VERSION as u32,
300+
resource_id: test_lib::helpers::TOPIC_LOCAL1_RESOURCE as u32,
301+
..Default::default()
302+
}; "Wildcard authority in topic UUri")]
303+
#[test_case(UUri {
304+
authority_name: test_lib::helpers::LOCAL_AUTHORITY.into(),
305+
ue_id: 0xFFFF_0000,
306+
ue_version_major: test_lib::helpers::TOPIC_LOCAL1_VERSION as u32,
307+
resource_id: test_lib::helpers::TOPIC_LOCAL1_RESOURCE as u32,
308+
..Default::default()
309+
}; "Wildcard entity id in topic UUri")]
310+
#[test_case(UUri {
311+
authority_name: test_lib::helpers::LOCAL_AUTHORITY.into(),
312+
ue_id: test_lib::helpers::TOPIC_LOCAL1_ID,
313+
ue_version_major: test_lib::helpers::TOPIC_LOCAL1_VERSION as u32,
314+
resource_id: 0x0000_FFFF,
315+
..Default::default()
316+
}; "Wildcard resource id in topic UUri")]
317+
#[tokio::test]
318+
async fn test_invalid_topic_uri(topic: UUri) {
319+
helpers::init_once();
320+
321+
// create request and other required object(s)
322+
let subscribe_request = test_lib::helpers::subscription_request(topic, None);
323+
let request_payload = UPayload::try_from_protobuf(subscribe_request.clone()).unwrap();
324+
let message_attributes = UAttributes {
325+
source: Some(test_lib::helpers::subscriber_uri1()).into(),
326+
..Default::default()
327+
};
328+
let (subscription_sender, _) = mpsc::channel::<SubscriptionEvent>(1);
329+
330+
// create handler and perform tested operation
331+
let request_handler = FetchSubscribersRequestHandler::new(subscription_sender);
332+
333+
let result = request_handler
334+
.handle_request(
335+
up_rust::core::usubscription::RESOURCE_ID_FETCH_SUBSCRIBERS,
336+
&message_attributes,
337+
Some(request_payload),
338+
)
339+
.await;
340+
341+
assert!(result.is_err());
342+
match result.unwrap_err() {
343+
ServiceInvocationError::InvalidArgument(_) => {}
344+
_ => panic!("Wrong error type"),
345+
}
346+
}
291347
}

up-subscription/src/tests/test_lib.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,9 @@ pub(crate) mod helpers {
160160
pub(crate) const LOCAL_AUTHORITY: &str = "LOCAL";
161161
pub(crate) const REMOTE_AUTHORITY: &str = "REMOTE";
162162

163-
const SUBSCRIBER1_ID: u32 = 0x0000_1000;
164-
const SUBSCRIBER1_VERSION: u8 = 0x01;
165-
const SUBSCRIBER1_RESOURCE: u16 = 0x1000;
163+
pub(crate) const SUBSCRIBER1_ID: u32 = 0x0000_1000;
164+
pub(crate) const SUBSCRIBER1_VERSION: u8 = 0x01;
165+
pub(crate) const SUBSCRIBER1_RESOURCE: u16 = 0x1000;
166166

167167
const SUBSCRIBER2_ID: u32 = 0x0000_2000;
168168
const SUBSCRIBER2_VERSION: u8 = 0x01;
@@ -179,9 +179,9 @@ pub(crate) mod helpers {
179179
#[allow(dead_code)] // final decision on removing this to happen after functional spec alignment is complete
180180
const NOTIFICATION_TOPIC_RESOURCE: u16 = 0x8001;
181181

182-
const TOPIC_LOCAL1_ID: u32 = 0x0010_0000;
183-
const TOPIC_LOCAL1_VERSION: u8 = 0x01;
184-
const TOPIC_LOCAL1_RESOURCE: u16 = 0x8AC7;
182+
pub(crate) const TOPIC_LOCAL1_ID: u32 = 0x0010_0000;
183+
pub(crate) const TOPIC_LOCAL1_VERSION: u8 = 0x01;
184+
pub(crate) const TOPIC_LOCAL1_RESOURCE: u16 = 0x8AC7;
185185

186186
const TOPIC_LOCAL2_ID: u32 = 0x0020_0000;
187187
const TOPIC_LOCAL2_VERSION: u8 = 0x01;

0 commit comments

Comments
 (0)