diff --git a/src/core/mxc_config_contract/src/dev/experimental.rs b/src/core/mxc_config_contract/src/dev/experimental.rs index 2f8d3dfb07..bcd6c34949 100644 --- a/src/core/mxc_config_contract/src/dev/experimental.rs +++ b/src/core/mxc_config_contract/src/dev/experimental.rs @@ -37,14 +37,13 @@ pub struct OneShotWindowsSandbox { pub daemon_pipe_name: OptionalField, } -#[rustfmt::skip] string_enum! { -/// Transport protocol for a WSLC port mapping. -#[derive(Debug)] -pub enum TransportProtocol { - /// TCP transport. - Tcp => ["tcp"], -} + /// Transport protocol for a WSLC port mapping. + #[derive(Debug)] + pub enum TransportProtocol { + /// TCP transport. + Tcp => ["tcp"], + } } /// A host-to-container WSLC port mapping. diff --git a/src/core/mxc_config_contract/src/dev/mod.rs b/src/core/mxc_config_contract/src/dev/mod.rs index dddb4e263a..a8a5db67b8 100644 --- a/src/core/mxc_config_contract/src/dev/mod.rs +++ b/src/core/mxc_config_contract/src/dev/mod.rs @@ -90,17 +90,59 @@ macro_rules! string_enum { deserializer.deserialize_str(StringEnumVisitor) } } + + // Generate a test for each string enum variant and its aliases. + // The test ensures that the enum deserializes from the canonical and + // alias string values (if any), and that it rejects externally tagged + // and non-string values. Emitted here as part of the macro to avoid + // repeating the same test logic for each enum in a separate location + // where the enum's private WIRE_VALUES constant is not accessible. + #[cfg(test)] + #[allow(non_snake_case)] + #[test] + fn $name() { + $( + for wire_value in [ + $canonical, + $($alias,)* + ] { + let json = serde_json::to_string(wire_value).unwrap(); + let parsed: $name = serde_json::from_str(&json).unwrap(); + + assert!( + matches!(parsed, $name::$variant), + "{wire_value:?} did not map to {}::{}", + stringify!($name), + stringify!($variant), + ); + + let externally_tagged = format!("{{{json}:null}}"); + assert!( + serde_json::from_str::<$name>(&externally_tagged).is_err(), + "{} accepted externally tagged value {externally_tagged}", + stringify!($name), + ); + } + )+ + + for json in ["null", "true", "0", "[]", "{}"] { + assert!( + serde_json::from_str::<$name>(json).is_err(), + "{} accepted non-string value {json}", + stringify!($name), + ); + } + } }; } -#[rustfmt::skip] string_enum! { -/// The exact version marker accepted by this contract. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Version { - /// The development `0.8.0-alpha` contract. - V0_8_0Alpha => ["0.8.0-alpha"], -} + /// The exact version marker accepted by this contract. + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + pub enum Version { + /// The development `0.8.0-alpha` contract. + V0_8_0Alpha => ["0.8.0-alpha"], + } } mod experimental; diff --git a/src/core/mxc_config_contract/src/dev/network.rs b/src/core/mxc_config_contract/src/dev/network.rs index b4a78d399b..3e033db55d 100644 --- a/src/core/mxc_config_contract/src/dev/network.rs +++ b/src/core/mxc_config_contract/src/dev/network.rs @@ -5,30 +5,28 @@ use std::num::NonZeroU16; use super::primitives::{OptionalField, True}; -#[rustfmt::skip] string_enum! { -/// The default outbound network policy. -#[derive(Debug)] -pub enum DefaultNetworkPolicy { - /// Allow outbound network access by default. - Allow => ["allow"], - /// Block outbound network access by default. - Block => ["block"], -} + /// The default outbound network policy. + #[derive(Debug)] + pub enum DefaultNetworkPolicy { + /// Allow outbound network access by default. + Allow => ["allow"], + /// Block outbound network access by default. + Block => ["block"], + } } -#[rustfmt::skip] string_enum! { -/// The mechanism used to enforce network policy. -#[derive(Debug)] -pub enum NetworkEnforcementMode { - /// Enforce policy through containment capabilities. - Capabilities => ["capabilities"], - /// Enforce policy through host firewall rules. - Firewall => ["firewall"], - /// Enforce policy through both capabilities and firewall rules. - Both => ["both"], -} + /// The mechanism used to enforce network policy. + #[derive(Debug)] + pub enum NetworkEnforcementMode { + /// Enforce policy through containment capabilities. + Capabilities => ["capabilities"], + /// Enforce policy through host firewall rules. + Firewall => ["firewall"], + /// Enforce policy through both capabilities and firewall rules. + Both => ["both"], + } } /// One of the proxy configurations accepted by the `0.8.0-alpha` contract. diff --git a/src/core/mxc_config_contract/src/dev/one_shot.rs b/src/core/mxc_config_contract/src/dev/one_shot.rs index 3b09d7550d..bc13ce509d 100644 --- a/src/core/mxc_config_contract/src/dev/one_shot.rs +++ b/src/core/mxc_config_contract/src/dev/one_shot.rs @@ -9,37 +9,36 @@ use super::stable::{ }; use crate::dev::Version; -#[rustfmt::skip] string_enum! { -/// Containment selections available in `0.8.0-alpha`. -#[derive(Debug)] -pub enum Containment { - // Stable-candidate values. - /// Select the host's native process-containment backend. - Process => ["process"], - /// Select the Windows ProcessContainer backend. - ProcessContainer => ["processcontainer", "appcontainer"], - /// Select the Linux LXC backend. - Lxc => ["lxc"], - /// Select the Linux Bubblewrap backend. - Bubblewrap => ["bubblewrap"], - /// Select the macOS Seatbelt backend. - Seatbelt => ["seatbelt", "macos_sandbox"], + /// Containment selections available in `0.8.0-alpha`. + #[derive(Debug)] + pub enum Containment { + // Stable-candidate values. + /// Select the host's native process-containment backend. + Process => ["process"], + /// Select the Windows ProcessContainer backend. + ProcessContainer => ["processcontainer", "appcontainer"], + /// Select the Linux LXC backend. + Lxc => ["lxc"], + /// Select the Linux Bubblewrap backend. + Bubblewrap => ["bubblewrap"], + /// Select the macOS Seatbelt backend. + Seatbelt => ["seatbelt", "macos_sandbox"], - // Development-only values. - /// Select the host's VM-class containment backend. - Vm => ["vm"], - /// Select the Windows Sandbox backend. - WindowsSandbox => ["windows_sandbox"], - /// Select the NanVix micro-VM backend. - Microvm => ["microvm"], - /// Select the Hyperlight micro-VM backend. - Hyperlight => ["hyperlight"], - /// Select the WSL container backend. - Wslc => ["wslc"], - /// Select the Windows IsolationSession backend. - IsolationSession => ["isolation_session"], -} + // Development-only values. + /// Select the host's VM-class containment backend. + Vm => ["vm"], + /// Select the Windows Sandbox backend. + WindowsSandbox => ["windows_sandbox"], + /// Select the NanVix micro-VM backend. + Microvm => ["microvm"], + /// Select the Hyperlight micro-VM backend. + Hyperlight => ["hyperlight"], + /// Select the WSL container backend. + Wslc => ["wslc"], + /// Select the Windows IsolationSession backend. + IsolationSession => ["isolation_session"], + } } /// A complete one-shot `0.8.0-alpha` configuration request. diff --git a/src/core/mxc_config_contract/src/dev/stable.rs b/src/core/mxc_config_contract/src/dev/stable.rs index 3ab5b8bc8b..2ac4809e3d 100644 --- a/src/core/mxc_config_contract/src/dev/stable.rs +++ b/src/core/mxc_config_contract/src/dev/stable.rs @@ -56,20 +56,19 @@ pub struct Fallback { pub allow_dacl_mutation: OptionalField, } -#[rustfmt::skip] string_enum! { -/// Clipboard access granted to the contained process. -#[derive(Debug)] -pub enum UiClipboard { - /// Deny clipboard reads and writes. - None => ["none"], - /// Allow clipboard reads. - Read => ["read"], - /// Allow clipboard writes. - Write => ["write"], - /// Allow clipboard reads and writes. - All => ["all"], -} + /// Clipboard access granted to the contained process. + #[derive(Debug)] + pub enum UiClipboard { + /// Deny clipboard reads and writes. + None => ["none"], + /// Allow clipboard reads. + Read => ["read"], + /// Allow clipboard writes. + Write => ["write"], + /// Allow clipboard reads and writes. + All => ["all"], + } } /// Cross-platform user-interface policy. @@ -87,20 +86,19 @@ pub struct Ui { pub injection: OptionalField, } -#[rustfmt::skip] string_enum! { -/// Isolation level for ProcessContainer desktop resources. -#[derive(Debug)] -pub enum ProcessContainerUiIsolation { - /// Isolate the complete container user-interface environment. - Container => ["container"], - /// Isolate desktop resources. - Desktop => ["desktop"], - /// Isolate user-interface handles. - Handles => ["handles"], - /// Isolate user-interface atoms. - Atoms => ["atoms"], -} + /// Isolation level for ProcessContainer desktop resources. + #[derive(Debug)] + pub enum ProcessContainerUiIsolation { + /// Isolate the complete container user-interface environment. + Container => ["container"], + /// Isolate desktop resources. + Desktop => ["desktop"], + /// Isolate user-interface handles. + Handles => ["handles"], + /// Isolate user-interface atoms. + Atoms => ["atoms"], + } } /// ProcessContainer-specific user-interface policy. @@ -121,16 +119,15 @@ pub struct ProcessContainerUi { pub ime: OptionalField, } -#[rustfmt::skip] string_enum! { -/// Mode for capture denials -#[derive(Debug)] -pub enum CaptureDenialsMode { - /// Access stays **denied** and the denial is recorded. Deny-by-default containment is preserved; this is the safe default. - Block => ["block"], - /// Access is **allowed** and recorded (audit mode). This relaxes deny-by-default for the run, so it is a security-sensitive choice and the runner emits a security warning. - Allow => ["allow"], -} + /// Mode for capture denials + #[derive(Debug)] + pub enum CaptureDenialsMode { + /// Access stays **denied** and the denial is recorded. Deny-by-default containment is preserved; this is the safe default. + Block => ["block"], + /// Access is **allowed** and recorded (audit mode). This relaxes deny-by-default for the run, so it is a security-sensitive choice and the runner emits a security warning. + Allow => ["allow"], + } } /// Windows denial-capture settings. @@ -181,16 +178,15 @@ pub struct Lxc { pub release: String, } -#[rustfmt::skip] string_enum! { -/// Launch method for macOS Seatbelt config. -#[derive(Debug)] -pub enum LaunchMethod { - /// Launch the contained process directly through `exec`. - Exec => ["exec"], - /// Launch the contained application through macOS LaunchServices. - Open => ["open"], -} + /// Launch method for macOS Seatbelt config. + #[derive(Debug)] + pub enum LaunchMethod { + /// Launch the contained process directly through `exec`. + Exec => ["exec"], + /// Launch the contained application through macOS LaunchServices. + Open => ["open"], + } } /// macOS Seatbelt backend settings. diff --git a/src/core/mxc_config_contract/src/published/v0_6_0_alpha/mod.rs b/src/core/mxc_config_contract/src/published/v0_6_0_alpha/mod.rs index 04abd080f9..fa533451f0 100644 --- a/src/core/mxc_config_contract/src/published/v0_6_0_alpha/mod.rs +++ b/src/core/mxc_config_contract/src/published/v0_6_0_alpha/mod.rs @@ -10,9 +10,7 @@ // Serde's default fieldless-enum deserializer also accepts externally // tagged object forms such as {"process": null}. Published contracts accept // only string values. This macro generates a string-only deserializer while -// supporting explicit compatibility aliases. Note that this macro should be -// preceded by `#[rustfmt::skip]` because it uses a syntax pattern that is not -// supported by rustfmt. +// supporting explicit compatibility aliases. macro_rules! string_enum { ( $(#[$enum_meta:meta])* @@ -92,6 +90,49 @@ macro_rules! string_enum { deserializer.deserialize_str(StringEnumVisitor) } } + + // Generate a test for each string enum variant and its aliases. + // The test ensures that the enum deserializes from the canonical and + // alias string values (if any), and that it rejects externally tagged + // and non-string values. Emitted here as part of the macro to avoid + // repeating the same test logic for each enum in a separate location + // where the enum's private WIRE_VALUES constant is not accessible. + #[cfg(test)] + #[allow(non_snake_case)] + #[test] + fn $name() { + $( + for wire_value in [ + $canonical, + $($alias,)* + ] { + let json = serde_json::to_string(wire_value).unwrap(); + let parsed: $name = serde_json::from_str(&json).unwrap(); + + assert!( + matches!(parsed, $name::$variant), + "{wire_value:?} did not map to {}::{}", + stringify!($name), + stringify!($variant), + ); + + let externally_tagged = format!("{{{json}:null}}"); + assert!( + serde_json::from_str::<$name>(&externally_tagged).is_err(), + "{} accepted externally tagged value {externally_tagged}", + stringify!($name), + ); + } + )+ + + for json in ["null", "true", "0", "[]", "{}"] { + assert!( + serde_json::from_str::<$name>(json).is_err(), + "{} accepted non-string value {json}", + stringify!($name), + ); + } + } }; } diff --git a/src/core/mxc_config_contract/src/published/v0_6_0_alpha/network.rs b/src/core/mxc_config_contract/src/published/v0_6_0_alpha/network.rs index 91d79106f3..235a191619 100644 --- a/src/core/mxc_config_contract/src/published/v0_6_0_alpha/network.rs +++ b/src/core/mxc_config_contract/src/published/v0_6_0_alpha/network.rs @@ -5,30 +5,28 @@ use std::num::NonZeroU16; use super::primitives::{OptionalField, True}; -#[rustfmt::skip] string_enum! { -/// The default outbound network policy. -#[derive(Debug)] -pub enum DefaultNetworkPolicy { - /// Allow outbound network access by default. - Allow => ["allow"], - /// Block outbound network access by default. - Block => ["block"], -} + /// The default outbound network policy. + #[derive(Debug)] + pub enum DefaultNetworkPolicy { + /// Allow outbound network access by default. + Allow => ["allow"], + /// Block outbound network access by default. + Block => ["block"], + } } -#[rustfmt::skip] string_enum! { -/// The mechanism used to enforce network policy. -#[derive(Debug)] -pub enum NetworkEnforcementMode { - /// Enforce policy through containment capabilities. - Capabilities => ["capabilities"], - /// Enforce policy through host firewall rules. - Firewall => ["firewall"], - /// Enforce policy through both capabilities and firewall rules. - Both => ["both"], -} + /// The mechanism used to enforce network policy. + #[derive(Debug)] + pub enum NetworkEnforcementMode { + /// Enforce policy through containment capabilities. + Capabilities => ["capabilities"], + /// Enforce policy through host firewall rules. + Firewall => ["firewall"], + /// Enforce policy through both capabilities and firewall rules. + Both => ["both"], + } } /// One of the proxy configurations accepted by the `0.6.0-alpha` contract. diff --git a/src/core/mxc_config_contract/src/published/v0_6_0_alpha/request.rs b/src/core/mxc_config_contract/src/published/v0_6_0_alpha/request.rs index 475e53530f..3f398dcf75 100644 --- a/src/core/mxc_config_contract/src/published/v0_6_0_alpha/request.rs +++ b/src/core/mxc_config_contract/src/published/v0_6_0_alpha/request.rs @@ -4,30 +4,28 @@ use super::network::Network; use super::primitives::{NonEmptyString, OptionalField}; -#[rustfmt::skip] string_enum! { -/// The exact version marker accepted by this contract. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Version { - /// The published `0.6.0-alpha` contract. - V0_6_0Alpha => ["0.6.0-alpha"], -} + /// The exact version marker accepted by this contract. + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + pub enum Version { + /// The published `0.6.0-alpha` contract. + V0_6_0Alpha => ["0.6.0-alpha"], + } } -#[rustfmt::skip] string_enum! { -/// Stable containment selections available in `0.6.0-alpha`. -#[derive(Debug)] -pub enum Containment { - /// Select the host's native process-containment backend. - Process => ["process"], - /// Select the Windows ProcessContainer backend. - ProcessContainer => ["processcontainer", "appcontainer"], - /// Select the Linux LXC backend. - Lxc => ["lxc"], - /// Select the Linux Bubblewrap backend. - Bubblewrap => ["bubblewrap"], -} + /// Stable containment selections available in `0.6.0-alpha`. + #[derive(Debug)] + pub enum Containment { + /// Select the host's native process-containment backend. + Process => ["process"], + /// Select the Windows ProcessContainer backend. + ProcessContainer => ["processcontainer", "appcontainer"], + /// Select the Linux LXC backend. + Lxc => ["lxc"], + /// Select the Linux Bubblewrap backend. + Bubblewrap => ["bubblewrap"], + } } /// Container lifecycle settings. @@ -83,20 +81,19 @@ pub struct Fallback { pub allow_dacl_mutation: OptionalField, } -#[rustfmt::skip] string_enum! { -/// Clipboard access granted to the contained process. -#[derive(Debug)] -pub enum UiClipboard { - /// Deny clipboard reads and writes. - None => ["none"], - /// Allow clipboard reads. - Read => ["read"], - /// Allow clipboard writes. - Write => ["write"], - /// Allow clipboard reads and writes. - All => ["all"], -} + /// Clipboard access granted to the contained process. + #[derive(Debug)] + pub enum UiClipboard { + /// Deny clipboard reads and writes. + None => ["none"], + /// Allow clipboard reads. + Read => ["read"], + /// Allow clipboard writes. + Write => ["write"], + /// Allow clipboard reads and writes. + All => ["all"], + } } /// Cross-platform user-interface policy. @@ -114,20 +111,19 @@ pub struct Ui { pub injection: OptionalField, } -#[rustfmt::skip] string_enum! { -/// Isolation level for ProcessContainer desktop resources. -#[derive(Debug)] -pub enum ProcessContainerUiIsolation { - /// Isolate the complete container user-interface environment. - Container => ["container"], - /// Isolate desktop resources. - Desktop => ["desktop"], - /// Isolate user-interface handles. - Handles => ["handles"], - /// Isolate user-interface atoms. - Atoms => ["atoms"], -} + /// Isolation level for ProcessContainer desktop resources. + #[derive(Debug)] + pub enum ProcessContainerUiIsolation { + /// Isolate the complete container user-interface environment. + Container => ["container"], + /// Isolate desktop resources. + Desktop => ["desktop"], + /// Isolate user-interface handles. + Handles => ["handles"], + /// Isolate user-interface atoms. + Atoms => ["atoms"], + } } /// ProcessContainer-specific user-interface policy. diff --git a/src/core/mxc_config_contract/src/published/v0_7_0_alpha/mod.rs b/src/core/mxc_config_contract/src/published/v0_7_0_alpha/mod.rs index 9bc9384365..96c862d40f 100644 --- a/src/core/mxc_config_contract/src/published/v0_7_0_alpha/mod.rs +++ b/src/core/mxc_config_contract/src/published/v0_7_0_alpha/mod.rs @@ -10,9 +10,7 @@ // Serde's default fieldless-enum deserializer also accepts externally // tagged object forms such as {"process": null}. Published contracts accept // only string values. This macro generates a string-only deserializer while -// supporting explicit compatibility aliases. Note that this macro should be -// preceded by `#[rustfmt::skip]` because it uses a syntax pattern that is not -// supported by rustfmt. +// supporting explicit compatibility aliases. macro_rules! string_enum { ( $(#[$enum_meta:meta])* @@ -92,6 +90,49 @@ macro_rules! string_enum { deserializer.deserialize_str(StringEnumVisitor) } } + + // Generate a test for each string enum variant and its aliases. + // The test ensures that the enum deserializes from the canonical and + // alias string values (if any), and that it rejects externally tagged + // and non-string values. Emitted here as part of the macro to avoid + // repeating the same test logic for each enum in a separate location + // where the enum's private WIRE_VALUES constant is not accessible. + #[cfg(test)] + #[allow(non_snake_case)] + #[test] + fn $name() { + $( + for wire_value in [ + $canonical, + $($alias,)* + ] { + let json = serde_json::to_string(wire_value).unwrap(); + let parsed: $name = serde_json::from_str(&json).unwrap(); + + assert!( + matches!(parsed, $name::$variant), + "{wire_value:?} did not map to {}::{}", + stringify!($name), + stringify!($variant), + ); + + let externally_tagged = format!("{{{json}:null}}"); + assert!( + serde_json::from_str::<$name>(&externally_tagged).is_err(), + "{} accepted externally tagged value {externally_tagged}", + stringify!($name), + ); + } + )+ + + for json in ["null", "true", "0", "[]", "{}"] { + assert!( + serde_json::from_str::<$name>(json).is_err(), + "{} accepted non-string value {json}", + stringify!($name), + ); + } + } }; } diff --git a/src/core/mxc_config_contract/src/published/v0_7_0_alpha/network.rs b/src/core/mxc_config_contract/src/published/v0_7_0_alpha/network.rs index e83440960d..1783bf7e4c 100644 --- a/src/core/mxc_config_contract/src/published/v0_7_0_alpha/network.rs +++ b/src/core/mxc_config_contract/src/published/v0_7_0_alpha/network.rs @@ -5,30 +5,28 @@ use std::num::NonZeroU16; use super::primitives::{OptionalField, True}; -#[rustfmt::skip] string_enum! { -/// The default outbound network policy. -#[derive(Debug)] -pub enum DefaultNetworkPolicy { - /// Allow outbound network access by default. - Allow => ["allow"], - /// Block outbound network access by default. - Block => ["block"], -} + /// The default outbound network policy. + #[derive(Debug)] + pub enum DefaultNetworkPolicy { + /// Allow outbound network access by default. + Allow => ["allow"], + /// Block outbound network access by default. + Block => ["block"], + } } -#[rustfmt::skip] string_enum! { -/// The mechanism used to enforce network policy. -#[derive(Debug)] -pub enum NetworkEnforcementMode { - /// Enforce policy through containment capabilities. - Capabilities => ["capabilities"], - /// Enforce policy through host firewall rules. - Firewall => ["firewall"], - /// Enforce policy through both capabilities and firewall rules. - Both => ["both"], -} + /// The mechanism used to enforce network policy. + #[derive(Debug)] + pub enum NetworkEnforcementMode { + /// Enforce policy through containment capabilities. + Capabilities => ["capabilities"], + /// Enforce policy through host firewall rules. + Firewall => ["firewall"], + /// Enforce policy through both capabilities and firewall rules. + Both => ["both"], + } } /// One of the proxy configurations accepted by the `0.7.0-alpha` contract. diff --git a/src/core/mxc_config_contract/src/published/v0_7_0_alpha/request.rs b/src/core/mxc_config_contract/src/published/v0_7_0_alpha/request.rs index 408c548f44..afbf8a83bd 100644 --- a/src/core/mxc_config_contract/src/published/v0_7_0_alpha/request.rs +++ b/src/core/mxc_config_contract/src/published/v0_7_0_alpha/request.rs @@ -4,32 +4,30 @@ use super::network::Network; use super::primitives::{NonEmptyString, OptionalField}; -#[rustfmt::skip] string_enum! { -/// The exact version marker accepted by this contract. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Version { - /// The published `0.7.0-alpha` contract. - V0_7_0Alpha => ["0.7.0-alpha"], -} + /// The exact version marker accepted by this contract. + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + pub enum Version { + /// The published `0.7.0-alpha` contract. + V0_7_0Alpha => ["0.7.0-alpha"], + } } -#[rustfmt::skip] string_enum! { -/// Stable containment selections available in `0.7.0-alpha`. -#[derive(Debug)] -pub enum Containment { - /// Select the host's native process-containment backend. - Process => ["process"], - /// Select the Windows ProcessContainer backend. - ProcessContainer => ["processcontainer", "appcontainer"], - /// Select the Linux LXC backend. - Lxc => ["lxc"], - /// Select the Linux Bubblewrap backend. - Bubblewrap => ["bubblewrap"], - /// Select the macOS Seatbelt backend. - Seatbelt => ["seatbelt", "macos_sandbox"], -} + /// Stable containment selections available in `0.7.0-alpha`. + #[derive(Debug)] + pub enum Containment { + /// Select the host's native process-containment backend. + Process => ["process"], + /// Select the Windows ProcessContainer backend. + ProcessContainer => ["processcontainer", "appcontainer"], + /// Select the Linux LXC backend. + Lxc => ["lxc"], + /// Select the Linux Bubblewrap backend. + Bubblewrap => ["bubblewrap"], + /// Select the macOS Seatbelt backend. + Seatbelt => ["seatbelt", "macos_sandbox"], + } } /// Container lifecycle settings. @@ -85,20 +83,19 @@ pub struct Fallback { pub allow_dacl_mutation: OptionalField, } -#[rustfmt::skip] string_enum! { -/// Clipboard access granted to the contained process. -#[derive(Debug)] -pub enum UiClipboard { - /// Deny clipboard reads and writes. - None => ["none"], - /// Allow clipboard reads. - Read => ["read"], - /// Allow clipboard writes. - Write => ["write"], - /// Allow clipboard reads and writes. - All => ["all"], -} + /// Clipboard access granted to the contained process. + #[derive(Debug)] + pub enum UiClipboard { + /// Deny clipboard reads and writes. + None => ["none"], + /// Allow clipboard reads. + Read => ["read"], + /// Allow clipboard writes. + Write => ["write"], + /// Allow clipboard reads and writes. + All => ["all"], + } } /// Cross-platform user-interface policy. @@ -116,20 +113,19 @@ pub struct Ui { pub injection: OptionalField, } -#[rustfmt::skip] string_enum! { -/// Isolation level for ProcessContainer desktop resources. -#[derive(Debug)] -pub enum ProcessContainerUiIsolation { - /// Isolate the complete container user-interface environment. - Container => ["container"], - /// Isolate desktop resources. - Desktop => ["desktop"], - /// Isolate user-interface handles. - Handles => ["handles"], - /// Isolate user-interface atoms. - Atoms => ["atoms"], -} + /// Isolation level for ProcessContainer desktop resources. + #[derive(Debug)] + pub enum ProcessContainerUiIsolation { + /// Isolate the complete container user-interface environment. + Container => ["container"], + /// Isolate desktop resources. + Desktop => ["desktop"], + /// Isolate user-interface handles. + Handles => ["handles"], + /// Isolate user-interface atoms. + Atoms => ["atoms"], + } } /// ProcessContainer-specific user-interface policy. @@ -175,16 +171,15 @@ pub struct Lxc { pub release: String, } -#[rustfmt::skip] string_enum! { -/// Launch method for macOS Seatbelt config. -#[derive(Debug)] -pub enum LaunchMethod { - /// Launch the contained process directly through `exec`. - Exec => ["exec"], - /// Launch the contained application through macOS LaunchServices. - Open => ["open"], -} + /// Launch method for macOS Seatbelt config. + #[derive(Debug)] + pub enum LaunchMethod { + /// Launch the contained process directly through `exec`. + Exec => ["exec"], + /// Launch the contained application through macOS LaunchServices. + Open => ["open"], + } } /// macOS Seatbelt configuration settings. diff --git a/src/core/mxc_config_contract/tests/v0_6_0_alpha/enums.rs b/src/core/mxc_config_contract/tests/v0_6_0_alpha/enums.rs index d276f03cd7..265f6760ff 100644 --- a/src/core/mxc_config_contract/tests/v0_6_0_alpha/enums.rs +++ b/src/core/mxc_config_contract/tests/v0_6_0_alpha/enums.rs @@ -154,47 +154,6 @@ fn rejects_invalid_process_container_ui_isolation_value() { ); } -#[test] -fn rejects_object_encoding_for_fieldless_enums() { - let cases = [ - r#"{ - "version": {"0.6.0-alpha": null}, - "process": {"commandLine": "echo"} - }"#, - r#"{ - "version": "0.6.0-alpha", - "containment": {"process": null}, - "process": {"commandLine": "echo"} - }"#, - r#"{ - "version": "0.6.0-alpha", - "network": {"defaultPolicy": {"allow": null}}, - "process": {"commandLine": "echo"} - }"#, - r#"{ - "version": "0.6.0-alpha", - "network": {"enforcementMode": {"both": null}}, - "process": {"commandLine": "echo"} - }"#, - r#"{ - "version": "0.6.0-alpha", - "ui": {"clipboard": {"all": null}}, - "process": {"commandLine": "echo"} - }"#, - r#"{ - "version": "0.6.0-alpha", - "processContainer": { - "ui": {"isolation": {"desktop": null}} - }, - "process": {"commandLine": "echo"} - }"#, - ]; - - for case in cases { - assert_invalid(case); - } -} - use mxc_config_contract::published::v0_6_0_alpha::{Containment, Request}; #[test] diff --git a/src/core/mxc_config_contract/tests/v0_6_0_alpha/root.rs b/src/core/mxc_config_contract/tests/v0_6_0_alpha/root.rs index 399d417fe5..1b17571699 100644 --- a/src/core/mxc_config_contract/tests/v0_6_0_alpha/root.rs +++ b/src/core/mxc_config_contract/tests/v0_6_0_alpha/root.rs @@ -195,26 +195,6 @@ fn rejects_non_exact_version() { ); } -#[test] -fn rejects_non_string_version() { - assert_invalid( - r#"{ - "version": 0.6, - "process": {"commandLine": "echo"} - }"#, - ); -} - -#[test] -fn rejects_null_version() { - assert_invalid( - r#"{ - "version": null, - "process": {"commandLine": "echo"} - }"#, - ); -} - // Required field tests #[test] fn rejects_missing_process() { diff --git a/src/core/mxc_config_contract/tests/v0_7_0_alpha/enums.rs b/src/core/mxc_config_contract/tests/v0_7_0_alpha/enums.rs index ad0ba46cc2..0b608a87c1 100644 --- a/src/core/mxc_config_contract/tests/v0_7_0_alpha/enums.rs +++ b/src/core/mxc_config_contract/tests/v0_7_0_alpha/enums.rs @@ -161,54 +161,6 @@ fn rejects_invalid_process_container_ui_isolation_value() { ); } -#[test] -fn rejects_object_encoding_for_fieldless_enums() { - let cases = [ - r#"{ - "version": {"0.7.0-alpha": null}, - "process": {"commandLine": "echo"} - }"#, - r#"{ - "version": "0.7.0-alpha", - "containment": {"process": null}, - "process": {"commandLine": "echo"} - }"#, - r#"{ - "version": "0.7.0-alpha", - "network": {"defaultPolicy": {"allow": null}}, - "process": {"commandLine": "echo"} - }"#, - r#"{ - "version": "0.7.0-alpha", - "network": {"enforcementMode": {"both": null}}, - "process": {"commandLine": "echo"} - }"#, - r#"{ - "version": "0.7.0-alpha", - "ui": {"clipboard": {"all": null}}, - "process": {"commandLine": "echo"} - }"#, - r#"{ - "version": "0.7.0-alpha", - "processContainer": { - "ui": {"isolation": {"desktop": null}} - }, - "process": {"commandLine": "echo"} - }"#, - r#"{ - "version": "0.7.0-alpha", - "seatbelt": { - "launchMethod": {"exec": null} - }, - "process": {"commandLine": "echo"} - }"#, - ]; - - for case in cases { - assert_invalid(case); - } -} - use mxc_config_contract::published::v0_7_0_alpha::{Containment, Request}; #[test] diff --git a/src/core/mxc_config_contract/tests/v0_7_0_alpha/root.rs b/src/core/mxc_config_contract/tests/v0_7_0_alpha/root.rs index 7f6f9a8473..899f338092 100644 --- a/src/core/mxc_config_contract/tests/v0_7_0_alpha/root.rs +++ b/src/core/mxc_config_contract/tests/v0_7_0_alpha/root.rs @@ -195,26 +195,6 @@ fn rejects_non_exact_version() { ); } -#[test] -fn rejects_non_string_version() { - assert_invalid( - r#"{ - "version": 0.6, - "process": {"commandLine": "echo"} - }"#, - ); -} - -#[test] -fn rejects_null_version() { - assert_invalid( - r#"{ - "version": null, - "process": {"commandLine": "echo"} - }"#, - ); -} - // Required field tests #[test] fn rejects_missing_process() { diff --git a/src/core/mxc_config_contract/tests/v0_7_0_alpha/seatbelt.rs b/src/core/mxc_config_contract/tests/v0_7_0_alpha/seatbelt.rs index 8c76689192..2c87fb2e4a 100644 --- a/src/core/mxc_config_contract/tests/v0_7_0_alpha/seatbelt.rs +++ b/src/core/mxc_config_contract/tests/v0_7_0_alpha/seatbelt.rs @@ -53,23 +53,6 @@ fn rejects_invalid_seatbelt_launch_method() { assert_invalid(json); } -#[test] -fn rejects_non_string_seatbelt_launch_method() { - for launch_method in ["true", "false", "0", "1", "[]", "{}"] { - let json = format!( - r#"{{ - "version": "0.7.0-alpha", - "seatbelt": {{ - "launchMethod": {launch_method} - }}, - "process": {{"commandLine": "echo"}} - }}"# - ); - - assert_invalid(&json); - } -} - #[test] fn accepts_empty_profile_override() { let json = r#"{ diff --git a/src/core/mxc_config_contract/tests/v0_8_0_alpha/enums.rs b/src/core/mxc_config_contract/tests/v0_8_0_alpha/enums.rs index 8258a99464..28cede116c 100644 --- a/src/core/mxc_config_contract/tests/v0_8_0_alpha/enums.rs +++ b/src/core/mxc_config_contract/tests/v0_8_0_alpha/enums.rs @@ -202,81 +202,6 @@ fn rejects_invalid_capture_denials_mode_value() { ); } -#[test] -fn rejects_non_string_capture_denials_mode_value() { - for capture_denials_mode in ["123", "true", "[]", "{}"] { - let json = format!( - r#"{{ - "version": "0.8.0-alpha", - "processContainer": {{ - "captureDenials": {{ - "mode": {capture_denials_mode}, - "outputPath": "c:\\temp\\denials.log" - }} - }}, - "process": {{"commandLine": "echo"}} - }}"# - ); - - assert_invalid(&json); - } -} - -#[test] -fn rejects_object_encoding_for_fieldless_enums() { - let cases = [ - r#"{ - "version": {"0.8.0-alpha": null}, - "process": {"commandLine": "echo"} - }"#, - r#"{ - "version": "0.8.0-alpha", - "containment": {"process": null}, - "process": {"commandLine": "echo"} - }"#, - r#"{ - "version": "0.8.0-alpha", - "network": {"defaultPolicy": {"allow": null}}, - "process": {"commandLine": "echo"} - }"#, - r#"{ - "version": "0.8.0-alpha", - "network": {"enforcementMode": {"both": null}}, - "process": {"commandLine": "echo"} - }"#, - r#"{ - "version": "0.8.0-alpha", - "ui": {"clipboard": {"all": null}}, - "process": {"commandLine": "echo"} - }"#, - r#"{ - "version": "0.8.0-alpha", - "processContainer": { - "ui": {"isolation": {"desktop": null}} - }, - "process": {"commandLine": "echo"} - }"#, - r#"{ - "version": "0.8.0-alpha", - "processContainer": { - "captureDenials": {"mode": {"block": null}} - }, - "process": {"commandLine": "echo"} - }"#, - r#"{ - "version": "0.8.0-alpha", - "seatbelt": { - "launchMethod": {"exec": null} - }, - "process": {"commandLine": "echo"} - }"#, - ]; - - for case in cases { - assert_invalid(case); - } -} - use mxc_config_contract::dev::{OneShotContainment, OneShotRequest}; #[test] diff --git a/src/core/mxc_config_contract/tests/v0_8_0_alpha/one_shot.rs b/src/core/mxc_config_contract/tests/v0_8_0_alpha/one_shot.rs index 6692b3b2dd..61cecaa4c4 100644 --- a/src/core/mxc_config_contract/tests/v0_8_0_alpha/one_shot.rs +++ b/src/core/mxc_config_contract/tests/v0_8_0_alpha/one_shot.rs @@ -236,26 +236,6 @@ fn rejects_non_exact_version() { ); } -#[test] -fn rejects_non_string_version() { - assert_invalid( - r#"{ - "version": 0.6, - "process": {"commandLine": "echo"} - }"#, - ); -} - -#[test] -fn rejects_null_version() { - assert_invalid( - r#"{ - "version": null, - "process": {"commandLine": "echo"} - }"#, - ); -} - // Required field tests #[test] fn rejects_missing_process() { diff --git a/src/core/mxc_config_contract/tests/v0_8_0_alpha/seatbelt.rs b/src/core/mxc_config_contract/tests/v0_8_0_alpha/seatbelt.rs index 198adeb7d0..cb1b4417e6 100644 --- a/src/core/mxc_config_contract/tests/v0_8_0_alpha/seatbelt.rs +++ b/src/core/mxc_config_contract/tests/v0_8_0_alpha/seatbelt.rs @@ -50,23 +50,6 @@ fn rejects_invalid_seatbelt_launch_method() { assert_invalid(json); } -#[test] -fn rejects_non_string_seatbelt_launch_method() { - for launch_method in ["true", "false", "0", "1", "[]", "{}"] { - let json = format!( - r#"{{ - "version": "0.8.0-alpha", - "seatbelt": {{ - "launchMethod": {launch_method} - }}, - "process": {{"commandLine": "echo"}} - }}"# - ); - - assert_invalid(&json); - } -} - #[test] fn accepts_empty_profile_override() { let json = r#"{