feat(mavlink): adopt the kaptan-native dialect
This commit is contained in:
1 parent
1c90870634
commit
5f91465e66
87 files changed
+7733
-6850
No files matched your search
@@ -32,11 +32,11 @@ struct MavlinkConfig {
|
||||
struct TelemetryConfig {
|
||||
#[config(
|
||||
id = 103,
|
||||
key = "telemetry.raw_imu_hz",
|
||||
key = "telemetry.imu_hz",
|
||||
unit = "Hz",
|
||||
range(min = 1, max = 100)
|
||||
)]
|
||||
raw_imu_hz: u8,
|
||||
imu_hz: u8,
|
||||
#[config(
|
||||
id = 104,
|
||||
key = "telemetry.heartbeat_hz",
|
||||
@@ -91,7 +91,7 @@ struct OneRecord<C>(Option<C>);
|
||||
impl<C: Clone> ConfigStore<C> for OneRecord<C> {
|
||||
type Error = ();
|
||||
|
||||
fn load(&mut self) -> Result<Option<C>, Self::Error> {
|
||||
fn load(&mut self, _: &C) -> Result<Option<C>, Self::Error> {
|
||||
Ok(self.0.take())
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ fn factory() -> TestUserConfig {
|
||||
log_level_filter: LevelFilter::Info,
|
||||
},
|
||||
telemetry: TelemetryConfig {
|
||||
raw_imu_hz: 20,
|
||||
imu_hz: 20,
|
||||
heartbeat_hz: 2,
|
||||
},
|
||||
driver: DriverConfig { driver_gain: 7 },
|
||||
@@ -123,6 +123,7 @@ struct MalformedProjection {
|
||||
|
||||
impl Config for MalformedProjection {
|
||||
const FIELD_COUNT: usize = TestUserConfig::FIELD_COUNT;
|
||||
const SNAPSHOT_VALUE_BYTES: usize = TestUserConfig::SNAPSHOT_VALUE_BYTES;
|
||||
const SCHEMA_ID: [u8; 16] = TestUserConfig::SCHEMA_ID;
|
||||
|
||||
fn descriptor(index: usize) -> Option<&'static kaptan_config::FieldDescriptor> {
|
||||
@@ -159,7 +160,7 @@ fn mavlink_logging_policy_is_projected_and_validated_independently() {
|
||||
);
|
||||
let mut candidate = UserConfigModel::<TestUserConfig, F722ImmutableConfig>::new(factory());
|
||||
candidate
|
||||
.set_field(FieldId::new(105), ConfigValue::U32(0))
|
||||
.set_field(FieldId::new(105), ConfigValue::U8(0))
|
||||
.unwrap();
|
||||
|
||||
let active = candidate.validate(&IMMUTABLE).unwrap();
|
||||
@@ -168,17 +169,13 @@ fn mavlink_logging_policy_is_projected_and_validated_independently() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn runtime_projection_rejects_missing_wrong_kind_and_wide_semantic_values() {
|
||||
fn runtime_projection_rejects_missing_and_wrong_kind_values() {
|
||||
for (system_id, rule) in [
|
||||
(None, kaptan_config::ValidationRule::Inconsistent),
|
||||
(
|
||||
Some(ConfigValue::Bool(true)),
|
||||
kaptan_config::ValidationRule::Inconsistent,
|
||||
),
|
||||
(
|
||||
Some(ConfigValue::U32(256)),
|
||||
kaptan_config::ValidationRule::AboveMaximum,
|
||||
),
|
||||
] {
|
||||
let malformed = MalformedProjection {
|
||||
inner: factory(),
|
||||
@@ -195,7 +192,7 @@ fn runtime_construction_reads_the_persisted_board_owned_user_root() {
|
||||
let factory = UserConfigModel::<TestUserConfig, F722ImmutableConfig>::new(factory());
|
||||
let mut persisted = factory.clone();
|
||||
persisted
|
||||
.set_field(FieldId::new(1000), ConfigValue::U32(42))
|
||||
.set_field(FieldId::new(1000), ConfigValue::U8(42))
|
||||
.expect("driver field must accept a valid persisted value");
|
||||
|
||||
let manager = ConfigManager::recover_compatible_or_factory(
|
||||
@@ -207,7 +204,7 @@ fn runtime_construction_reads_the_persisted_board_owned_user_root() {
|
||||
|
||||
assert_eq!(
|
||||
manager.active().field_value(FieldId::new(1000)),
|
||||
Some(ConfigValue::U32(42)),
|
||||
Some(ConfigValue::U8(42)),
|
||||
"runtime construction must receive the validated persisted field"
|
||||
);
|
||||
}
|
||||
@@ -215,19 +212,19 @@ fn runtime_construction_reads_the_persisted_board_owned_user_root() {
|
||||
#[test]
|
||||
fn committing_a_user_edit_does_not_mutate_the_boot_active_view() {
|
||||
let factory = UserConfigModel::<TestUserConfig, F722ImmutableConfig>::new(factory());
|
||||
let mut manager = ConfigManager::new(factory, IMMUTABLE, OneRecord(None)).unwrap();
|
||||
manager.begin().unwrap();
|
||||
manager
|
||||
.set(FieldId::new(1000), ConfigValue::U32(42))
|
||||
let mut manager = ConfigManager::recover(factory, IMMUTABLE, OneRecord(None)).unwrap();
|
||||
let mut replacement = manager.committed().clone();
|
||||
replacement
|
||||
.set_field(FieldId::new(1000), ConfigValue::U8(42))
|
||||
.unwrap();
|
||||
manager.commit().unwrap();
|
||||
manager.replace(replacement).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
manager.active().field_value(FieldId::new(1000)),
|
||||
Some(ConfigValue::U32(7))
|
||||
Some(ConfigValue::U8(7))
|
||||
);
|
||||
assert_eq!(
|
||||
manager.committed_value(FieldId::new(1000)),
|
||||
Some(ConfigValue::U32(42))
|
||||
manager.committed().field_value(FieldId::new(1000)),
|
||||
Some(ConfigValue::U8(42))
|
||||
);
|
||||
}
|
||||
@@ -141,13 +141,17 @@ fn ordinary_f722_image_has_direct_configuration_after_output_inhibition() {
|
||||
"ordinary board images must not hide configuration behind a development feature"
|
||||
);
|
||||
for required in [
|
||||
"configuration: F722ConfigManager",
|
||||
"config_protocol: ConfigProtocol",
|
||||
"receiver: IntegrityMavlinkReceiver<2>",
|
||||
"config_lease_ticks: u16",
|
||||
"wire::decode_command",
|
||||
"self.config_protocol.dispatch_from_composition",
|
||||
"visit_response(response, &mut sender)",
|
||||
"config_file: F722ConfigFile",
|
||||
"file_service: FileService",
|
||||
"receiver: IntegrityMavlinkReceiver<1>",
|
||||
"file_lease_ticks: u16",
|
||||
"TRANSFER_REPLAY_LEASE_SECONDS",
|
||||
"let Some(message) = frame.decode()",
|
||||
"wire::decode_request",
|
||||
".dispatch(&mut self.config_file",
|
||||
"send_file_response",
|
||||
"let class = kaptan_mavlink::transmitter::FrameClass::Critical",
|
||||
"control.status != FileStatus::RequestConflict",
|
||||
] {
|
||||
assert!(
|
||||
board.contains(required),
|
||||
@@ -163,23 +167,15 @@ fn ordinary_f722_image_has_direct_configuration_after_output_inhibition() {
|
||||
"the MPU runtime may drive only PB2 atomically, not retain GPIOB ownership"
|
||||
);
|
||||
assert!(!board.contains("development-config"));
|
||||
assert!(
|
||||
!board.contains("ArmRequest"),
|
||||
"telemetry must not decode arm commands"
|
||||
);
|
||||
assert!(
|
||||
!board.contains("MAV_CMD_COMPONENT_ARM_DISARM") && !board.contains("decode_arm_request"),
|
||||
"telemetry must not accept an arm command"
|
||||
);
|
||||
assert!(
|
||||
!firmware.contains("shared = [mavlink, motors]"),
|
||||
"the MAVLink worker must not share a motor resource"
|
||||
);
|
||||
assert!(
|
||||
firmware.contains("const MAVLINK_EVENT_RECEIVED")
|
||||
&& firmware.contains("mavlink.receive_config_interrupt(event)")
|
||||
&& firmware.contains("mavlink.receive_mavlink_interrupt(event)")
|
||||
&& !firmware.contains("development-config"),
|
||||
"ordinary images must always dispatch received configuration frames"
|
||||
"ordinary images must always dispatch received MAVLink frames"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -279,7 +275,7 @@ fn configuration_schema_is_generated_without_board_forwarding_code() {
|
||||
for semantic_id in [
|
||||
"MAVLINK_SYSTEM_ID",
|
||||
"MAVLINK_COMPONENT_ID",
|
||||
"RAW_IMU_HZ",
|
||||
"IMU_HZ",
|
||||
"HEARTBEAT_HZ",
|
||||
"MAVLINK_LOG_LEVEL_FILTER",
|
||||
"RANGE_HZ",
|
||||
@@ -330,8 +326,8 @@ fn f722_link_budget_reserves_only_deterministic_telemetry() {
|
||||
"ERROR_RECORDS_PER_SECOND",
|
||||
"LOG_RECORDS_PER_SECOND",
|
||||
"WORST_CASE_OBSERVABILITY_BYTES_PER_SECOND",
|
||||
"KAPTAN_ERROR_FRAME_MAXIMUM_BYTES",
|
||||
"KAPTAN_LOG_FRAME_MAXIMUM_BYTES",
|
||||
"ERROR_FRAME_MAXIMUM_BYTES",
|
||||
"LOG_FRAME_MAXIMUM_BYTES",
|
||||
"budget_ticks",
|
||||
"error_budget",
|
||||
"log_budget",
|
||||
@@ -385,6 +381,7 @@ fn mavlink_transport_faults_do_not_recurse_or_retain_dead_accounting() {
|
||||
#[test]
|
||||
fn f722_producers_keep_logs_and_reportable_errors_separate() {
|
||||
let board = platform_source("src/f722/board.rs");
|
||||
let config = platform_source("src/f722/config.rs");
|
||||
let logger = platform_source("../../libs/kaptan-log/src/facade.rs");
|
||||
let errors = platform_source("../../libs/kaptan-err-reportable/src/ingress.rs");
|
||||
|
||||
@@ -400,6 +397,14 @@ fn f722_producers_keep_logs_and_reportable_errors_separate() {
|
||||
);
|
||||
}
|
||||
assert!(board.contains("#[kaptan_err_reportable::propagate]"));
|
||||
assert!(
|
||||
config.contains("enum PersistConfigurationError {")
|
||||
&& config.contains("#[kaptan_error(id = 2210)]")
|
||||
&& config.contains("#[kaptan_error(id = 2209)]")
|
||||
&& config.contains("impl From<JournalError<F722FlashError>>")
|
||||
&& config.contains("fn persist_candidate(")
|
||||
&& config.contains("#[kaptan_err_reportable::propagate]")
|
||||
);
|
||||
assert!(!board.contains("report_error"));
|
||||
assert!(!board.contains("report_static_error"));
|
||||
assert!(logger.contains("GLOBAL_INGRESS_CAPACITY"));
|
||||
|
||||
Reference in new issue
Block a user