use crate::core::{ObjectId, PlatformFamily};
use crate::platform::{Platform, StubPlatform, WidgetTriggerEvent, WidgetTriggerKind};
#[cfg(feature = "harmony")]
#[test]
fn runtime_selects_harmony_backend_when_feature_enabled() {
let platform = crate::platform::get_platform();
assert_eq!(platform.backend_name(), "harmony-state-backend");
assert_eq!(platform.family(), PlatformFamily::Desktop);
}
#[test]
fn the_selected_backend_is_real_and_not_the_unknown_stub() {
let name = crate::platform::backend_name();
assert!(!name.is_empty(), "a backend must name itself");
let has_device_profile = cfg!(device_profile);
if has_device_profile {
assert_ne!(
name, "unknown-runtime-stub",
"a device build resolved no backend at all: one of the \
`create_native_platform` arms is missing its condition"
);
}
}
#[cfg(feature = "harmony")]
#[test]
fn runtime_does_not_fall_back_to_unknown_stub_with_harmony() {
let name = crate::platform::backend_name();
assert_ne!(name, "unknown-runtime-stub");
}
#[test]
fn consistency_menu_trigger_roundtrip() {
let platform = StubPlatform::new("test-desktop", PlatformFamily::Desktop);
let window = platform.create_window("w", 0, 0, 100, 100);
assert!(platform.inject_menu_trigger(window));
assert_eq!(platform.poll_menu_triggered(), Some(window));
}
#[test]
fn consistency_typed_widget_trigger_roundtrip() {
let platform = StubPlatform::new("test-desktop", PlatformFamily::Desktop);
let window = platform.create_window("w", 0, 0, 100, 100);
platform.register_widget(window, "btn", 0, 0, 80, 30);
assert!(platform.inject_widget_trigger_event(window, WidgetTriggerKind::Clicked));
assert_eq!(
platform.poll_widget_trigger_event(),
Some(WidgetTriggerEvent { widget_id: window, kind: WidgetTriggerKind::Clicked })
);
}
#[test]
fn consistency_compat_poll_widget_triggered_is_single_delivery_shim() {
let platform = StubPlatform::new("test-desktop", PlatformFamily::Desktop);
let window = platform.create_window("w", 0, 0, 100, 100);
assert!(platform.inject_widget_trigger_event(window, WidgetTriggerKind::Clicked));
assert_eq!(platform.poll_widget_triggered(), Some(window));
assert_eq!(platform.poll_widget_triggered(), None);
assert_eq!(platform.poll_widget_trigger_event(), None);
}
#[test]
fn consistency_list_box_data_path_roundtrip() {
let platform = StubPlatform::new("test-desktop", PlatformFamily::Desktop);
let list_box = platform.create_window("list", 0, 0, 120, 80);
assert!(platform.set_widget_selected_index(list_box, Some(1)));
assert_eq!(platform.widget_selected_index(list_box), Some(1));
assert!(platform.set_widget_selected_index(list_box, None));
assert_eq!(platform.widget_selected_index(list_box), None);
}
#[test]
fn consistency_combo_box_data_and_event_path_roundtrip() {
let platform = StubPlatform::new("test-desktop", PlatformFamily::Desktop);
let combo = platform.create_window("combo", 0, 0, 120, 24);
assert!(platform.set_widget_selected_index(combo, Some(1)));
assert_eq!(platform.widget_selected_index(combo), Some(1));
assert!(platform.inject_widget_trigger_event(combo, WidgetTriggerKind::SelectionChanged));
assert_eq!(
platform.poll_widget_trigger_event(),
Some(WidgetTriggerEvent { widget_id: combo, kind: WidgetTriggerKind::SelectionChanged })
);
}
#[test]
fn consistency_capability_contract_by_profile() {
let desktop = StubPlatform::new("test-desktop", PlatformFamily::Desktop);
let embedded = StubPlatform::new("test-embedded", PlatformFamily::Embedded);
assert!(desktop.native_capability_contract().is_some());
assert!(desktop.embedded_capability_contract().is_none());
assert!(embedded.native_capability_contract().is_none());
assert!(embedded.embedded_capability_contract().is_some());
}
#[test]
fn embedded_profile_self_drawn_controls_are_registered_with_the_host() {
let platform = StubPlatform::new("test-embedded", PlatformFamily::Embedded);
platform.register_widget(0x1001, "b", 0, 0, 80, 24);
platform.register_widget(0x1002, "c", 0, 0, 80, 24);
assert_eq!(platform.get_widget_text(0x1001), "b");
assert!(platform.is_widget_visible(0x1002));
assert!(platform.is_widget_enabled(0x1002));
assert_eq!(platform.widget_count(), 2);
assert!(platform.destroy_widget(0x1001));
assert_eq!(platform.widget_count(), 1);
}
#[test]
fn host_controls_are_explicitly_unsupported_on_every_profile() {
for family in [PlatformFamily::Desktop, PlatformFamily::Embedded] {
let platform = StubPlatform::new("test", family);
let window = platform.create_window("w", 0, 0, 200, 120);
assert_eq!(platform.create_menu_bar(window, 0, 0, 200, 24), 0);
assert_eq!(platform.create_menu(window, "File", 0, 0, 80, 24), 0);
assert_eq!(platform.menu_add_item(window, "Open", None), 0);
assert_eq!(platform.create_tool_bar(window, 0, 24, 200, 24), 0);
assert_eq!(platform.create_status_bar(window, "ready", 0, 96, 200, 24), 0);
assert_eq!(platform.create_button(window, "b", 0, 0, 80, 24), 0);
assert!(!platform.attach_menu_bar_to_window(window, window));
assert!(!platform.inject_menu_trigger(ObjectId::MAX));
}
}
#[test]
fn embedded_profile_selection_state_roundtrip() {
let platform = StubPlatform::new("test-embedded", PlatformFamily::Embedded);
let combo = platform.create_window("combo", 0, 0, 120, 24);
assert_ne!(combo, 0);
assert!(platform.set_widget_selected_index(combo, Some(1)));
assert_eq!(platform.widget_selected_index(combo), Some(1));
assert!(platform.inject_widget_trigger_event(combo, WidgetTriggerKind::SelectionChanged));
assert_eq!(
platform.poll_widget_trigger_event(),
Some(WidgetTriggerEvent { widget_id: combo, kind: WidgetTriggerKind::SelectionChanged })
);
let list = platform.create_window("list", 0, 30, 120, 80);
assert_ne!(list, 0);
assert!(platform.set_widget_selected_index(list, Some(0)));
assert_eq!(platform.widget_selected_index(list), Some(0));
assert!(platform.inject_widget_trigger_event(list, WidgetTriggerKind::SelectionChanged));
assert_eq!(
platform.poll_widget_trigger_event(),
Some(WidgetTriggerEvent { widget_id: list, kind: WidgetTriggerKind::SelectionChanged })
);
}
#[test]
fn stub_reports_unknown_platform_facts_honestly() {
let platform = StubPlatform::new("test-desktop", PlatformFamily::Desktop);
assert_eq!(platform.total_memory_mb(), None);
assert_eq!(platform.process_memory_utilization(), None);
assert_eq!(platform.process_cpu_utilization(), None);
}
#[test]
fn battery_unknown_defaults_to_mains_power() {
let platform = StubPlatform::new("test-desktop", PlatformFamily::Desktop);
assert!(!platform.is_on_battery());
}
#[test]
fn stub_without_spooler_refuses_print_job() {
let platform = StubPlatform::new("test-desktop", PlatformFamily::Desktop);
assert!(!platform.has_print_support());
let result = platform.spawn_print_job(std::path::Path::new("/tmp/does-not-matter.txt"));
assert!(result.is_err(), "a backend with no spooler must report the gap, not fake success");
}
#[test]
fn routing_resolves_every_kind_through_the_single_policy() {
use crate::control_backend::route_preference_for_widget_kind;
for kind in [
crate::widget::WidgetKind::ListBox,
crate::widget::WidgetKind::ScrollArea,
crate::widget::WidgetKind::SpinBox,
crate::widget::WidgetKind::Button,
] {
assert_eq!(
route_preference_for_widget_kind(kind),
crate::control_backend::ControlRoutePreference::CustomRequired,
"{kind:?} must route through the single painting backend"
);
}
}
#[cfg(any(target_os = "macos", target_os = "linux"))]
#[test]
fn unix_print_probe_detects_cups_client_despite_nonzero_version_exit() {
let lp_exists = std::process::Command::new("lp").arg("--help").output().is_ok();
let lpr_exists = std::process::Command::new("lpr").arg("--help").output().is_ok();
if lp_exists || lpr_exists {
assert!(
crate::platform::types::unix_print_clients_available(),
"a spooler client exists on PATH but was reported missing"
);
}
}
#[test]
fn stub_reports_no_web_engine_capability() {
let platform = StubPlatform::new("test-desktop", PlatformFamily::Desktop);
assert!(
!platform.supports_web_engine(),
"a backend that implements nothing must not claim a rendering engine"
);
}
#[test]
fn shortcut_style_follows_the_backend_not_a_middle_layer_cfg() {
use crate::shortcut::PlatformShortcutStyle;
let platform = StubPlatform::new("test-desktop", PlatformFamily::Desktop);
let expected = if cfg!(any(target_os = "macos", target_os = "ios")) {
PlatformShortcutStyle::Mac
} else {
PlatformShortcutStyle::Desktop
};
assert_eq!(platform.shortcut_style(), expected);
}
#[test]
fn format_shortcut_uses_the_backend_style() {
use crate::shortcut::{format_shortcut_for_platform, Key, Shortcut};
let platform = StubPlatform::new("test-desktop", PlatformFamily::Desktop);
let shortcut = Shortcut::primary(Key::Z);
assert_eq!(
platform.format_shortcut(&shortcut),
format_shortcut_for_platform(&shortcut, platform.shortcut_style()),
);
}
#[test]
fn every_backend_is_reported_at_the_mode_it_actually_has() {
use crate::platform::{runtime_gui_mode_for, RuntimeGuiMode};
struct Named(&'static str);
impl Platform for Named {
fn as_any(&self) -> &dyn core::any::Any {
self
}
fn backend_name(&self) -> &'static str {
self.0
}
fn family(&self) -> PlatformFamily {
PlatformFamily::Desktop
}
fn init(&self) {}
fn run(&self) {}
fn quit(&self) {}
fn create_window(&self, _t: &str, _x: i32, _y: i32, _w: u32, _h: u32) -> ObjectId {
0
}
}
for name in ["cocoa", "WindowsPlatform"] {
assert_eq!(
runtime_gui_mode_for(&Named(name)),
RuntimeGuiMode::NativeInteractive,
"{name} opens native windows, so it must be reported interactive regardless of what \
its capabilities() say about DPI — those are separate questions"
);
}
let expected_gtk = if cfg!(all(target_os = "linux", feature = "gtk-native")) {
RuntimeGuiMode::NativeInteractive
} else {
RuntimeGuiMode::PreviewOrStub
};
assert_eq!(runtime_gui_mode_for(&Named("gtk")), expected_gtk);
let expected_wayland = if cfg!(all(target_os = "linux", feature = "wayland-native")) {
RuntimeGuiMode::NativeInteractive
} else {
RuntimeGuiMode::PreviewOrStub
};
assert_eq!(runtime_gui_mode_for(&Named("wayland")), expected_wayland);
for name in [
"macos-objc2-preview",
"macos-fallback-stub",
"unknown-runtime-stub",
"harmony-state-backend",
"android-state-backend",
"android-mobile",
"ios-state-backend",
"wasm-state-backend",
"portable",
"recording-test-backend",
"harmony-desktop",
] {
assert_eq!(
runtime_gui_mode_for(&Named(name)),
RuntimeGuiMode::PreviewOrStub,
"{name} creates no native window, so claiming it will open one is the silent \
failure this function exists to prevent"
);
}
let stub = StubPlatform::new("portable", PlatformFamily::Embedded);
assert_eq!(runtime_gui_mode_for(&stub), RuntimeGuiMode::PreviewOrStub);
}
#[test]
fn a_declared_typed_trigger_capability_is_backed_by_the_queue_that_delivers_it() {
use crate::platform::PlatformCapabilities;
fn assert_delivers(name: &str, platform: &dyn Platform) {
let caps: PlatformCapabilities = platform.capabilities();
if !caps.typed_widget_trigger {
return;
}
let window = platform.create_window("trigger-probe", 0, 0, 100, 100);
assert!(
platform.inject_widget_trigger_event(window, WidgetTriggerKind::Clicked),
"{name}: declares `typed_widget_trigger: true` but `inject_widget_trigger_event` \
refused a window it just created, so the flag promises a queue this backend does \
not delegate to"
);
assert_eq!(
platform.poll_widget_trigger_event(),
Some(WidgetTriggerEvent { widget_id: window, kind: WidgetTriggerKind::Clicked }),
"{name}: the injected event must come back out of the typed view"
);
assert_eq!(
platform.poll_widget_triggered(),
None,
"{name}: and both views must be one queue, so the typed poll already consumed it"
);
}
assert_delivers("stub", &StubPlatform::new("trigger-stub", PlatformFamily::Desktop));
#[cfg(target_os = "linux")]
assert_delivers("linux", &crate::platform::linux::LinuxPlatform::new());
#[cfg(all(target_os = "linux", feature = "wayland-native"))]
assert_delivers("wayland", &crate::platform::wayland::WaylandPlatform::new());
#[cfg(all(target_os = "macos", feature = "cocoa-legacy"))]
assert_delivers("cocoa", &crate::platform::macos::MacOSPlatform::default());
#[cfg(all(target_os = "macos", any(feature = "macos", feature = "cocoa-legacy")))]
assert_delivers("macos-objc2", &crate::platform::macos_objc2::MacOSObjc2Platform::default());
#[cfg(target_os = "windows")]
assert_delivers("windows", &crate::platform::windows::WindowsPlatform::new());
#[cfg(feature = "wasm")]
assert_delivers("wasm", &crate::platform::wasm::WasmPlatform::default());
#[cfg(feature = "harmony")]
assert_delivers("harmony", &crate::platform::harmony::HarmonyPlatform::new());
}
#[test]
fn capability_flags_agree_with_the_methods_they_promise() {
use crate::platform::PlatformCapabilities;
fn assert_agrees(name: &str, platform: &dyn Platform) {
let caps: PlatformCapabilities = platform.capabilities();
if caps.ime {
assert!(
platform.ime_bridge().is_some(),
"{name}: claims `ime: true` but `ime_bridge()` answers None, so the flag \
promises an input-method client that does not exist"
);
}
if caps.accessibility {
assert!(
platform.accessibility_bridge().is_some(),
"{name}: claims `accessibility: true` but `accessibility_bridge()` answers None"
);
}
if caps.dpi_scaling {
let scale = platform.dpi_scale_factor();
assert!(
scale.is_finite() && scale > 0.0,
"{name}: claims `dpi_scaling: true` but reports a scale of {scale}, which no \
layout can use"
);
}
}
assert_agrees("stub", &StubPlatform::new("flags-stub", PlatformFamily::Desktop));
#[cfg(target_os = "linux")]
assert_agrees("linux", &crate::platform::linux::LinuxPlatform::new());
#[cfg(all(target_os = "linux", feature = "wayland-native"))]
assert_agrees("wayland", &crate::platform::wayland::WaylandPlatform::new());
#[cfg(all(target_os = "macos", feature = "cocoa-legacy"))]
assert_agrees("cocoa", &crate::platform::macos::MacOSPlatform::default());
#[cfg(all(target_os = "macos", any(feature = "macos", feature = "cocoa-legacy")))]
assert_agrees("macos-objc2", &crate::platform::macos_objc2::MacOSObjc2Platform::default());
#[cfg(target_os = "windows")]
assert_agrees("windows", &crate::platform::windows::WindowsPlatform::new());
#[cfg(feature = "wasm")]
assert_agrees("wasm", &crate::platform::wasm::WasmPlatform::default());
#[cfg(feature = "harmony")]
assert_agrees("harmony", &crate::platform::harmony::HarmonyPlatform::new());
#[cfg(target_os = "android")]
assert_agrees("android", &crate::platform::android::AndroidPlatform::new());
#[cfg(target_os = "ios")]
assert_agrees("ios", &crate::platform::ios::IosMobilePlatform::new());
}