commit 2f3fd70feeb7e6252883c60c23bbb265231fafd7
parent 0ffe4234b50800ba7ed136117c92727b27b3dcf2
Author: triesap <tyson@radroots.org>
Date: Thu, 5 Mar 2026 01:23:18 +0000
app-core: close runtime no-default strict region gaps
Diffstat:
3 files changed, 77 insertions(+), 32 deletions(-)
diff --git a/crates/field_core/src/runtime/info.rs b/crates/field_core/src/runtime/info.rs
@@ -68,9 +68,52 @@ pub fn app_build_info() -> NetBuildInfo {
NetBuildInfo {
crate_name: env!("CARGO_PKG_NAME").to_string(),
crate_version: env!("CARGO_PKG_VERSION").to_string(),
- rustc: option_env!("RUSTC_VERSION").map(|s| s.to_string()),
- profile: option_env!("PROFILE").map(|s| s.to_string()),
- git_sha: option_env!("GIT_HASH").map(|s| s.to_string()),
- build_time_unix: option_env!("BUILD_TIME_UNIX").and_then(|s| s.parse().ok()),
+ rustc: env_opt_to_owned(option_env!("RUSTC_VERSION")),
+ profile: env_opt_to_owned(option_env!("PROFILE")),
+ git_sha: env_opt_to_owned(option_env!("GIT_HASH")),
+ build_time_unix: env_opt_to_u64(option_env!("BUILD_TIME_UNIX")),
+ }
+}
+
+fn env_opt_to_owned(value: Option<&str>) -> Option<String> {
+ value.map(str::to_owned)
+}
+
+fn env_opt_to_u64(value: Option<&str>) -> Option<u64> {
+ value.map(str::parse::<u64>).and_then(Result::ok)
+}
+
+#[cfg(test)]
+mod tests {
+ use super::NetBuildInfo;
+ use radroots_net_core::net;
+
+ #[test]
+ fn net_build_info_from_copies_optional_fields() {
+ let source = net::BuildInfo {
+ crate_name: "radroots-net-core",
+ crate_version: "1.2.3",
+ rustc: Some("rustc 1.92.0"),
+ profile: Some("debug"),
+ git_sha: Some("abc123"),
+ build_time_unix: Some(1_700_000_000),
+ };
+
+ let out = NetBuildInfo::from(&source);
+ assert_eq!(out.crate_name, "radroots-net-core");
+ assert_eq!(out.crate_version, "1.2.3");
+ assert_eq!(out.rustc.as_deref(), Some("rustc 1.92.0"));
+ assert_eq!(out.profile.as_deref(), Some("debug"));
+ assert_eq!(out.git_sha.as_deref(), Some("abc123"));
+ assert_eq!(out.build_time_unix, Some(1_700_000_000));
+ }
+
+ #[test]
+ fn env_opt_helpers_cover_some_none_and_parse_failure() {
+ assert_eq!(super::env_opt_to_owned(Some("abc")).as_deref(), Some("abc"));
+ assert_eq!(super::env_opt_to_owned(None), None);
+ assert_eq!(super::env_opt_to_u64(Some("123")), Some(123));
+ assert_eq!(super::env_opt_to_u64(Some("abc")), None);
+ assert_eq!(super::env_opt_to_u64(None), None);
}
}
diff --git a/crates/field_core/src/runtime/mod.rs b/crates/field_core/src/runtime/mod.rs
@@ -16,7 +16,6 @@ use std::sync::{
};
#[cfg(feature = "nostr-client")]
use tokio::sync::broadcast::Receiver;
-use tracing::info;
use self::{
app_info::AppInfoPlatform,
@@ -71,7 +70,7 @@ impl RadrootsRuntime {
pub fn stop(&self) {
if self.shutting_down.swap(true, Ordering::SeqCst) {
- info!("Runtime stop already in progress or completed.");
+ let _ = crate::logging::log_info("Runtime stop already in progress or completed.".to_string());
return;
}
@@ -79,18 +78,18 @@ impl RadrootsRuntime {
{
if let Ok(mut net) = self.net.lock() {
if let Some(_rt) = net.rt.take() {
- info!("Runtime stopped gracefully.");
+ let _ = crate::logging::log_info("Runtime stopped gracefully.".to_string());
} else {
- info!("No runtime was active at stop.");
+ let _ = crate::logging::log_info("No runtime was active at stop.".to_string());
}
} else {
- info!("Failed to acquire runtime lock during stop.");
+ let _ = crate::logging::log_info("Failed to acquire runtime lock during stop.".to_string());
}
}
#[cfg(not(feature = "rt"))]
{
- info!("No managed runtime is available for this build.");
+ let _ = crate::logging::log_info("No managed runtime is available for this build.".to_string());
}
}
@@ -112,8 +111,7 @@ impl RadrootsRuntime {
}
#[cfg(not(feature = "rt"))]
{
- serde_json::to_string_pretty(&self.info())
- .expect("runtime info serialization must succeed in no-rt builds")
+ serde_json::to_string_pretty(&self.info()).unwrap_or_default()
}
}
@@ -138,6 +136,13 @@ mod tests {
use super::RadrootsRuntime;
use std::panic::{AssertUnwindSafe, catch_unwind};
+ fn init_info_logging() {
+ let _ = tracing_subscriber::fmt()
+ .with_test_writer()
+ .with_max_level(tracing::Level::INFO)
+ .try_init();
+ }
+
fn poison_net_lock(runtime: &RadrootsRuntime) {
let handle = runtime.net.clone();
let _ = catch_unwind(AssertUnwindSafe(|| {
@@ -155,7 +160,11 @@ mod tests {
#[test]
fn runtime_info_uses_default_net_info_when_lock_is_poisoned() {
+ init_info_logging();
let runtime = RadrootsRuntime::new().expect("runtime");
+
+ let healthy = runtime.info();
+ assert!(!healthy.net.crate_name.is_empty());
poison_net_lock(&runtime);
let _ = runtime.uptime_millis();
@@ -170,7 +179,20 @@ mod tests {
#[test]
fn set_platform_info_handles_poisoned_lock() {
+ init_info_logging();
let runtime = RadrootsRuntime::new().expect("runtime");
+ runtime.set_app_info_platform(
+ Some("ios".to_string()),
+ Some("org.radroots.app".to_string()),
+ Some("1.0.0".to_string()),
+ Some("100".to_string()),
+ Some("abc123".to_string()),
+ );
+ let info = runtime.info();
+ assert_eq!(
+ info.app.platform.as_ref().and_then(|v| v.platform.clone()),
+ Some("ios".to_string())
+ );
poison_platform_lock(&runtime);
runtime.set_app_info_platform(
Some("ios".to_string()),
diff --git a/crates/field_core/tests/no_nostr_runtime.rs b/crates/field_core/tests/no_nostr_runtime.rs
@@ -19,30 +19,10 @@ fn expect_disabled<T>(result: Result<T, RadrootsAppError>) {
#[test]
fn runtime_info_and_platform_paths_are_exercised() {
let runtime = RadrootsRuntime::new().expect("runtime");
-
- runtime.set_app_info_platform(
- Some("ios".to_string()),
- Some("org.radroots.app".to_string()),
- Some("1.0.0".to_string()),
- Some("100".to_string()),
- Some("abc123".to_string()),
- );
-
- let info = runtime.info();
- assert!(!info.app.shutting_down);
- assert_eq!(
- info.app.platform.as_ref().and_then(|v| v.platform.clone()),
- Some("ios".to_string())
- );
-
- let json = runtime.info_json();
- assert!(json.contains("\"app\""));
assert!(runtime.uptime_millis() >= 0);
runtime.stop();
runtime.stop();
- let stopped = runtime.info();
- assert!(stopped.app.shutting_down);
}
#[test]