diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8a9f59a..dc74e31 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -60,6 +60,6 @@ jobs: name: "Run Host Tests" with: command: make - args: test-messages + args: test diff --git a/Cargo.toml b/Cargo.toml index b766599..0999014 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,10 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +name = "messages" +path = "src/lib.rs" + [dependencies] derive_more = "0.99.17" serde = {version = "1.0.150", default-features = false, features = ["derive"]} @@ -17,14 +21,16 @@ mavlink = { git = "https://github.com/uorocketry/rust-mavlink.git", features = [ bitflags = { version = "2.3.1", features = ["serde"] } proptest = { version = "1.2.0", optional = true } proptest-derive = { version = "0.3.0", optional = true } +proptest-arbitrary-interop = { version = "0.1.0", optional = true } messages-proc-macros-lib = { path = "messages-proc-macros-lib" } -chrono = {version = "0.4.0", features = ["serde"], default-features = false} +chrono = { git = "https://github.com/uorocketry/chrono", features = ["serde", "arbitrary"], default-features = false} [dev-dependencies] proptest = "1.2.0" proptest-derive = "0.3.0" postcard = { version = "1.0.4", features = ["alloc"] } +proptest-arbitrary-interop = "0.1.0" [features] default = ["mavlink/embedded-hal-02", "mavlink/uorocketry"] -std = ["chrono/std", "mavlink/std", "mavlink/tcp", "mavlink/udp", "mavlink/direct-serial", "mavlink/serde", "dep:proptest", "dep:proptest-derive"] +std = ["chrono/std", "mavlink/std", "mavlink/tcp", "mavlink/udp", "mavlink/direct-serial", "mavlink/serde", "dep:proptest-arbitrary-interop", "dep:proptest", "dep:proptest-derive"] \ No newline at end of file diff --git a/Makefile.toml b/Makefile.toml index ae30f26..bef49ec 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -1,14 +1,9 @@ -[env] -CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true - -[config] -default_to_workspace = false # ----------------------- # Host Testing # ----------------------- -[tasks.test-messages] +[tasks.test] command = "cargo" -args = ["test", "-p", "messages", "--target", "${CARGO_MAKE_RUST_TARGET_TRIPLE}", "--features", "std", "--no-default-features"] +args = ["test", "--target", "${CARGO_MAKE_RUST_TARGET_TRIPLE}", "--features", "std", "--no-default-features"] env = {RUST_MIN_STACK = "8388608"} diff --git a/messages-proc-macros-lib/src/lib.rs b/messages-proc-macros-lib/src/lib.rs index 0189974..8031b3f 100644 --- a/messages-proc-macros-lib/src/lib.rs +++ b/messages-proc-macros-lib/src/lib.rs @@ -6,9 +6,7 @@ use quote::quote; pub fn common_derives(args: TokenStream, input: TokenStream) -> TokenStream { let mut output = TokenStream::from(quote! { #[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] - #[cfg_attr(feature = "ts", derive(ts_rs::TS))] - #[cfg_attr(feature = "ts", ts(export))] - #[cfg_attr(std, derive(proptest_derive::Arbitrary))] + #[cfg_attr(all(feature = "std", test), derive(proptest_derive::Arbitrary))] }); // Allow to omit the defmt::Format derive. Useful if this should be manually implemented. diff --git a/proptest-regressions/lib.txt b/proptest-regressions/lib.txt new file mode 100644 index 0000000..5b1f508 --- /dev/null +++ b/proptest-regressions/lib.txt @@ -0,0 +1,9 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc 61b4824c090c01db4b55ba9e9fcc0fb7bbb6843574b2b802fbc377e8f839c62d # shrinks to msg = Message { timestamp: FormattedNaiveDateTime(-0001-01-01T00:00:00.000000001), node: PressureBoard, data: Sensor(Sensor { data: EkfNavAcc(EkfNavAcc { status: EkfStatus { status: 268435456 }, velocity_std_dev: Some([0.0, 0.0, 0.0]), position_std_dev: Some([-0.0, 0.0, 0.0]) }) }) } +cc 1b5e64b2da76dcb68777a6b6564de7a77d5f4b6ab26e1f36432e2df7d11f828b # shrinks to msg = Message { timestamp: FormattedNaiveDateTime(0000-01-01T00:00:00.000000001), node: PressureBoard, data: Sensor(Sensor { component_id: 0, data: Imu2(Imu2 { temperature: Some(0.0), delta_velocity: Some([0.0, 0.0, 0.0]), delta_angle: Some([0.0, 0.0, 0.0]) }) }) } +cc dba5d5b40143101de3363dadb069654a4e5b62704479ee3824b993edba0b0efd # shrinks to msg = Message { timestamp: FormattedNaiveDateTime(0000-01-01T00:00:00), node: PressureBoard, data: Sensor(Sensor { component_id: 0, data: SbgData(EkfQuat(EkfQuat { time_stamp: 268435456, quaternion: Some([0.0, 0.0, 0.0, 0.0]), euler_std_dev: Some([0.0, 0.0, 0.0]), status: EkfStatus { status: 268435456 } })) }) } diff --git a/src/lib.rs b/src/lib.rs index 05f0744..31cd75c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,4 @@ #![cfg_attr(all(not(feature = "std"), not(test)), no_std)] -#![no_main] //! # Messages //! @@ -10,10 +9,11 @@ use crate::command::Command; use crate::node::Node; use crate::sensor::Sensor; use crate::state::State; +use chrono::NaiveDateTime; use derive_more::From; /// This is to help control versions. pub use mavlink; -use chrono::NaiveDateTime; + use messages_proc_macros_lib::common_derives; pub mod command; @@ -23,15 +23,28 @@ pub mod sensor; pub mod sensor_status; pub mod state; -pub const MAX_SIZE: usize = 64; +pub const MAX_SIZE_CAN: usize = 64; +pub const MAX_SIZE_RADIO: usize = 255; +use defmt::Format; pub use logging::{ErrorContext, Event, Log, LogLevel}; +#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] +#[cfg_attr(all(feature = "std", test), derive(proptest_derive::Arbitrary))] +pub struct FormattedNaiveDateTime(pub NaiveDateTime); + +impl Format for FormattedNaiveDateTime { + fn format(&self, fmt: defmt::Formatter) { + defmt::write!(fmt, ""); + } +} + /// Topmost message. Encloses all the other possible messages, and is the only thing that should /// be sent over the wire. -#[common_derives(NoFormat)] +#[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] +#[cfg_attr(all(feature = "std", test), derive(proptest_derive::Arbitrary))] pub struct Message { - pub timestamp: NaiveDateTime, + pub timestamp: FormattedNaiveDateTime, /// The original sender of this message. pub node: Node, @@ -51,7 +64,7 @@ pub enum Data { } impl Message { - pub fn new(timestamp: NaiveDateTime, node: Node, data: impl Into) -> Self { + pub fn new(timestamp: FormattedNaiveDateTime, node: Node, data: impl Into) -> Self { Message { timestamp, node, @@ -60,9 +73,9 @@ impl Message { } } -#[cfg(test)] +#[cfg(all(test, feature = "std"))] mod test { - use crate::{Message, MAX_SIZE}; + use crate::{Message, MAX_SIZE_CAN, MAX_SIZE_RADIO}; use proptest::prelude::*; proptest! { @@ -70,8 +83,24 @@ mod test { fn message_size(msg: Message) { let bytes = postcard::to_allocvec(&msg).unwrap(); - dbg!(msg); - assert!(dbg!(bytes.len()) <= MAX_SIZE); + dbg!(msg.clone()); + + match msg.data { + crate::Data::Sensor(sensor) => { + match sensor.data { + crate::sensor::SensorData::SbgData(_) => { + assert!(bytes.len() <= MAX_SIZE_RADIO); + } + _ => { + assert!(bytes.len() <= MAX_SIZE_CAN); + } + } + } + _ => { + assert!(bytes.len() <= MAX_SIZE_CAN); + } + + } } } } diff --git a/src/node.rs b/src/node.rs index a58236b..92c363d 100644 --- a/src/node.rs +++ b/src/node.rs @@ -5,7 +5,7 @@ use messages_proc_macros_lib::common_derives; pub enum Node { PressureBoard, TemperatureBoard, - StrainBoard, + StrainBoard, } impl From for u16 { diff --git a/src/sensor.rs b/src/sensor.rs index 9d93f43..e931dea 100644 --- a/src/sensor.rs +++ b/src/sensor.rs @@ -7,13 +7,35 @@ use messages_proc_macros_lib::common_derives; #[common_derives] pub struct Sensor { /// Used to differentiate between multiple components on the same sender. Unused right now. - // pub component_id: u8, + pub component_id: u8, pub data: SensorData, } #[common_derives] #[derive(From)] pub enum SensorData { + // UtcTime(UtcTime), + // Air(Air), + // EkfQuat(EkfQuat), + // EkfNav1(EkfNav1), + // EkfNav2(EkfNav2), + // EkfNavAcc(EkfNavAcc), + // Imu1(Imu1), + // Imu2(Imu2), + NavPosLlh(NavPosLlh), + // GpsVel(GpsVel), + // GpsVelAcc(GpsVelAcc), + // GpsPos1(GpsPos1), + // GpsPos2(GpsPos2), + // GpsPosAcc(GpsPosAcc), + ResetReason(ResetReason), + RecoverySensing(RecoverySensing), + SbgData(SbgData), +} + +#[common_derives] +#[derive(From)] +pub enum SbgData { UtcTime(UtcTime), Air(Air), EkfQuat(EkfQuat), @@ -22,14 +44,11 @@ pub enum SensorData { EkfNavAcc(EkfNavAcc), Imu1(Imu1), Imu2(Imu2), - NavPosLlh(NavPosLlh), GpsVel(GpsVel), GpsVelAcc(GpsVelAcc), GpsPos1(GpsPos1), GpsPos2(GpsPos2), GpsPosAcc(GpsPosAcc), - ResetReason(ResetReason), - RecoverySensing(RecoverySensing), } #[common_derives] @@ -245,7 +264,7 @@ pub struct RecoverySensing { impl Sensor { pub fn new(data: impl Into) -> Self { Sensor { - // component_id: 0, + component_id: 0, data: data.into(), } }