summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2023-01-12 15:56:43 +0100
committerMatthias Beyer <mail@beyermatthias.de>2023-01-18 09:07:18 +0100
commita474433d12e72a353bb6fcc347dd18d1b4c6ebb2 (patch)
tree1e8f983c1d75cba7a9659bccad8b96c3b1da8dbb
parent8732e5e0f14fa65ad9e330ee3c6d69e37157b8ec (diff)
Reimplement check_invalid_utf8_is_rejected as BehaviourTest
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
-rw-r--r--mqtt-tester/src/behaviour/invalid_utf8_is_rejected.rs47
-rw-r--r--mqtt-tester/src/behaviour/mod.rs1
-rw-r--r--mqtt-tester/src/client_report.rs83
3 files changed, 71 insertions, 60 deletions
diff --git a/mqtt-tester/src/behaviour/invalid_utf8_is_rejected.rs b/mqtt-tester/src/behaviour/invalid_utf8_is_rejected.rs
new file mode 100644
index 0000000..eea0fa5
--- /dev/null
+++ b/mqtt-tester/src/behaviour/invalid_utf8_is_rejected.rs
@@ -0,0 +1,47 @@
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+
+use mqtt_format::v3::{connect_return::MConnectReturnCode, packet::MConnack};
+
+use crate::{
+ behaviour_test::BehaviourTest,
+ command::{Input, Output},
+ executable::ClientExecutableCommand,
+};
+
+pub struct InvalidUtf8IsRejected;
+
+#[async_trait::async_trait]
+impl BehaviourTest for InvalidUtf8IsRejected {
+ fn commands(&self) -> Vec<Box<dyn ClientExecutableCommand>> {
+ vec![]
+ }
+
+ async fn execute(&self, mut input: Input, _output: Output) -> Result<(), miette::Error> {
+ input
+ .send_packet(MConnack {
+ session_present: false,
+ connect_return_code: MConnectReturnCode::Accepted,
+ })
+ .await?;
+
+ input
+ .send(&[
+ 0b0011_0000, // PUBLISH packet, DUP = 0, QoS = 0, Retain = 0
+ 0b0000_0111, // Length
+ // Now the variable header
+ 0b0000_0000,
+ 0b0000_0010,
+ 0x61,
+ 0xC1, // An invalid UTF-8 byte
+ 0b0000_0000, // Packet identifier
+ 0b0000_0001,
+ 0x1, // Payload
+ ])
+ .await?;
+ Ok(())
+ }
+}
diff --git a/mqtt-tester/src/behaviour/mod.rs b/mqtt-tester/src/behaviour/mod.rs
index 48f9c92..690d42c 100644
--- a/mqtt-tester/src/behaviour/mod.rs
+++ b/mqtt-tester/src/behaviour/mod.rs
@@ -4,4 +4,5 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
+pub mod invalid_utf8_is_rejected;
pub mod wait_for_connect;
diff --git a/mqtt-tester/src/client_report.rs b/mqtt-tester/src/client_report.rs
index 34dfcc2..f6962c2 100644
--- a/mqtt-tester/src/client_report.rs
+++ b/mqtt-tester/src/client_report.rs
@@ -6,7 +6,6 @@
use std::path::PathBuf;
use std::sync::Arc;
-use std::time::Duration;
use futures::FutureExt;
use miette::IntoDiagnostic;
@@ -20,6 +19,7 @@ use mqtt_format::v3::qos::MQualityOfService;
use mqtt_format::v3::strings::MString;
use mqtt_format::v3::subscription_request::MSubscriptionRequests;
+use crate::behaviour::invalid_utf8_is_rejected::InvalidUtf8IsRejected;
use crate::behaviour::wait_for_connect::WaitForConnect;
use crate::behaviour_test::BehaviourTest;
use crate::executable::ClientExecutable;
@@ -36,7 +36,6 @@ pub async fn create_client_report(
let executable = ClientExecutable::new(client_exe_path);
let reports = vec![
- check_invalid_utf8_is_rejected(&executable).boxed_local(),
check_receiving_server_packet(&executable).boxed_local(),
check_invalid_first_packet_is_rejected(&executable).boxed_local(),
check_utf8_with_nullchar_is_rejected(&executable).boxed_local(),
@@ -51,7 +50,8 @@ pub async fn create_client_report(
check_connect_flag_username_zero_means_password_zero(&executable).boxed_local(),
];
- let flows = vec![Box::new(WaitForConnect)];
+ let flows: Vec<Box<dyn BehaviourTest>> =
+ vec![Box::new(WaitForConnect), Box::new(InvalidUtf8IsRejected)];
let invariants: Vec<Arc<dyn PacketInvariant>> = vec![Arc::new(NoUsernameMeansNoPassword)];
@@ -107,74 +107,37 @@ macro_rules! mk_report {
};
}
+#[macro_export]
macro_rules! wait_for_output {
($output:ident,
timeout_ms: $timeout_ms:literal,
out_success => $success:block,
out_failure => $failure:block
) => {{
- let (result, output) =
- match tokio::time::timeout(Duration::from_millis($timeout_ms), $output).await {
- Ok(Ok(out)) => (
- if out.status.success() {
- $success
- } else {
- $failure
- },
- Some(out.stderr),
- ),
- Ok(Err(_)) | Err(_) => (ReportResult::Failure, None),
- };
+ #[allow(unused_imports)]
+ use futures::Future;
+
+ let (result, output) = match tokio::time::timeout(
+ std::time::Duration::from_millis($timeout_ms),
+ $output,
+ )
+ .await
+ {
+ Ok(Ok(out)) => (
+ if out.status.success() {
+ $success
+ } else {
+ $failure
+ },
+ Some(out.stderr),
+ ),
+ Ok(Err(_)) | Err(_) => (ReportResult::Failure, None),
+ };
(result, output)
}};
}
-async fn check_invalid_utf8_is_rejected(executable: &ClientExecutable) -> miette::Result<Report> {
- let (client, mut input, _output) = executable
- .call(&[])
- .map(crate::command::Command::new)?
- .spawn()?;
-
- input
- .send_packet(MConnack {
- session_present: false,
- connect_return_code: MConnectReturnCode::Accepted,
- })
- .await?;
-
- input
- .send(&[
- 0b0011_0000, // PUBLISH packet, DUP = 0, QoS = 0, Retain = 0
- 0b0000_0111, // Length
- // Now the variable header
- 0b0000_0000,
- 0b0000_0010,
- 0x61,
- 0xC1, // An invalid UTF-8 byte
- 0b0000_0000, // Packet identifier
- 0b0000_0001,
- 0x1, // Payload
- ])
- .await?;
-
- let output = client.wait_with_output();
- let (result, output) = wait_for_output! {
- output,
- timeout_ms: 100,
- out_success => { ReportResult::Failure },
- out_failure => { ReportResult::Success }
- };
-
- Ok(mk_report! {
- name: "Check if invalid UTF-8 is rejected",
- desc: "Invalid UTF-8 is not allowed per the MQTT spec. Any receiver should immediately close the connection upon receiving such a packet.",
- normative: "[MQTT-1.5.3-1, MQTT-1.5.3-2]",
- result,
- output
- })
-}
-
async fn check_receiving_server_packet(executable: &ClientExecutable) -> miette::Result<Report> {
let (client, mut input, _output) = executable
.call(&[])