Skip to content

Commit a6c7b0f

Browse files
authored
Feat/1012 intel crash fix (tinyhumansai#1320)
1 parent 09f8f12 commit a6c7b0f

1 file changed

Lines changed: 229 additions & 15 deletions

File tree

app/src-tauri/src/lib.rs

Lines changed: 229 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1881,6 +1881,12 @@ fn macos_os_version() -> Option<String> {
18811881
mod tests {
18821882
use super::*;
18831883

1884+
// Tests that read/write process-global env vars must serialize through this
1885+
// mutex. Rust's test runner executes tests in parallel by default; without
1886+
// coordination, concurrent set_var / remove_var calls race and produce
1887+
// spurious failures.
1888+
static ENV_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
1889+
18841890
/// Test that is_daemon_mode correctly detects daemon flag variations
18851891
#[test]
18861892
fn is_daemon_mode_detects_daemon_flag() {
@@ -1892,20 +1898,17 @@ mod tests {
18921898
/// Test core_rpc_url returns expected format
18931899
#[test]
18941900
fn core_rpc_url_returns_expected_format() {
1895-
// Save original env
1901+
let _g = ENV_LOCK.lock().unwrap();
18961902
let original = std::env::var("OPENHUMAN_CORE_RPC_URL").ok();
18971903

1898-
// Test with env var set
18991904
std::env::set_var("OPENHUMAN_CORE_RPC_URL", "http://localhost:9999/rpc");
19001905
let url = core_rpc_url();
19011906
assert_eq!(url, "http://localhost:9999/rpc");
19021907

1903-
// Test fallback when env not set
19041908
std::env::remove_var("OPENHUMAN_CORE_RPC_URL");
19051909
let url = core_rpc_url();
19061910
assert_eq!(url, "http://127.0.0.1:7788/rpc");
19071911

1908-
// Restore original
19091912
match original {
19101913
Some(v) => std::env::set_var("OPENHUMAN_CORE_RPC_URL", v),
19111914
None => std::env::remove_var("OPENHUMAN_CORE_RPC_URL"),
@@ -1915,25 +1918,21 @@ mod tests {
19151918
/// Test overlay_parent_rpc_url handles empty env var
19161919
#[test]
19171920
fn overlay_parent_rpc_url_handles_empty() {
1918-
// Save original env
1921+
let _g = ENV_LOCK.lock().unwrap();
19191922
let original = std::env::var("OPENHUMAN_CORE_RPC_URL").ok();
19201923

1921-
// Test with empty string (should return None)
19221924
std::env::set_var("OPENHUMAN_CORE_RPC_URL", "");
1923-
let result = overlay_parent_rpc_url();
1924-
assert!(result.is_none());
1925+
assert!(overlay_parent_rpc_url().is_none());
19251926

1926-
// Test with whitespace only (should return None)
19271927
std::env::set_var("OPENHUMAN_CORE_RPC_URL", " ");
1928-
let result = overlay_parent_rpc_url();
1929-
assert!(result.is_none());
1928+
assert!(overlay_parent_rpc_url().is_none());
19301929

1931-
// Test with valid URL
19321930
std::env::set_var("OPENHUMAN_CORE_RPC_URL", "http://127.0.0.1:7788/rpc");
1933-
let result = overlay_parent_rpc_url();
1934-
assert_eq!(result, Some("http://127.0.0.1:7788/rpc".to_string()));
1931+
assert_eq!(
1932+
overlay_parent_rpc_url(),
1933+
Some("http://127.0.0.1:7788/rpc".to_string())
1934+
);
19351935

1936-
// Restore original
19371936
match original {
19381937
Some(v) => std::env::set_var("OPENHUMAN_CORE_RPC_URL", v),
19391938
None => std::env::remove_var("OPENHUMAN_CORE_RPC_URL"),
@@ -1983,4 +1982,219 @@ mod tests {
19831982
//
19841983
// This test passes if the code compiles with these log messages.
19851984
}
1985+
1986+
// -------------------------------------------------------------------------
1987+
// macos_os_version (issue #1012)
1988+
// -------------------------------------------------------------------------
1989+
1990+
/// On macOS, sw_vers is always present and must return a version string.
1991+
#[cfg(target_os = "macos")]
1992+
#[test]
1993+
fn macos_os_version_returns_some() {
1994+
assert!(
1995+
macos_os_version().is_some(),
1996+
"sw_vers -productVersion must succeed on macOS"
1997+
);
1998+
}
1999+
2000+
/// The returned version must be a non-empty trimmed string.
2001+
#[cfg(target_os = "macos")]
2002+
#[test]
2003+
fn macos_os_version_is_nonempty() {
2004+
let ver = macos_os_version().expect("sw_vers must return a version on macOS");
2005+
assert!(!ver.is_empty());
2006+
// No leading/trailing whitespace (the impl trims).
2007+
assert_eq!(ver, ver.trim());
2008+
}
2009+
2010+
/// The version string must look like dot-separated integers ("14.5", "13.2.1").
2011+
#[cfg(target_os = "macos")]
2012+
#[test]
2013+
fn macos_os_version_is_dotted_integer_format() {
2014+
let ver = macos_os_version().expect("sw_vers must return a version on macOS");
2015+
let all_numeric_parts = ver
2016+
.split('.')
2017+
.all(|part| !part.is_empty() && part.chars().all(|c| c.is_ascii_digit()));
2018+
assert!(
2019+
all_numeric_parts,
2020+
"os version {ver:?} must be dot-separated integers (e.g. '14.5')"
2021+
);
2022+
}
2023+
2024+
/// The version must have at least one component (e.g. a bare major "15" is valid).
2025+
#[cfg(target_os = "macos")]
2026+
#[test]
2027+
fn macos_os_version_has_at_least_one_component() {
2028+
let ver = macos_os_version().expect("sw_vers must return a version on macOS");
2029+
assert!(
2030+
!ver.split('.').next().unwrap_or("").is_empty(),
2031+
"version must have at least one numeric component"
2032+
);
2033+
}
2034+
2035+
// -------------------------------------------------------------------------
2036+
// Platform constants (issue #1012 Sentry tagging)
2037+
// -------------------------------------------------------------------------
2038+
2039+
/// cpu_arch tag is derived from std::env::consts::ARCH which must be non-empty.
2040+
#[test]
2041+
fn platform_arch_constant_is_nonempty() {
2042+
assert!(
2043+
!std::env::consts::ARCH.is_empty(),
2044+
"ARCH constant used for Sentry cpu_arch tag must be non-empty"
2045+
);
2046+
}
2047+
2048+
/// os_name tag is derived from std::env::consts::OS which must be non-empty.
2049+
#[test]
2050+
fn platform_os_constant_is_nonempty() {
2051+
assert!(
2052+
!std::env::consts::OS.is_empty(),
2053+
"OS constant used for Sentry os_name tag must be non-empty"
2054+
);
2055+
}
2056+
2057+
/// On a macOS build the OS constant must equal "macos".
2058+
#[cfg(target_os = "macos")]
2059+
#[test]
2060+
fn platform_os_is_macos_on_macos_build() {
2061+
assert_eq!(std::env::consts::OS, "macos");
2062+
}
2063+
2064+
/// On an Intel macOS build the ARCH constant must equal "x86_64".
2065+
/// This is the architecture that triggers --disable-gpu-compositing.
2066+
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
2067+
#[test]
2068+
fn platform_arch_is_x86_64_on_intel_build() {
2069+
assert_eq!(std::env::consts::ARCH, "x86_64");
2070+
}
2071+
2072+
/// On Apple Silicon the ARCH constant must equal "aarch64"; the GPU flag
2073+
/// must NOT be compiled in (verified by this test existing in the binary).
2074+
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
2075+
#[test]
2076+
fn platform_arch_is_aarch64_on_apple_silicon_build() {
2077+
assert_eq!(std::env::consts::ARCH, "aarch64");
2078+
}
2079+
2080+
// -------------------------------------------------------------------------
2081+
// build_sentry_release_tag
2082+
// -------------------------------------------------------------------------
2083+
2084+
#[test]
2085+
fn sentry_release_tag_starts_with_openhuman() {
2086+
let tag = build_sentry_release_tag();
2087+
assert!(
2088+
tag.starts_with("openhuman@"),
2089+
"release tag must start with 'openhuman@', got: {tag:?}"
2090+
);
2091+
}
2092+
2093+
#[test]
2094+
fn sentry_release_tag_contains_cargo_pkg_version() {
2095+
let tag = build_sentry_release_tag();
2096+
let version = env!("CARGO_PKG_VERSION");
2097+
assert!(
2098+
tag.contains(version),
2099+
"release tag {tag:?} must embed CARGO_PKG_VERSION {version:?}"
2100+
);
2101+
}
2102+
2103+
#[test]
2104+
fn sentry_release_tag_version_part_is_nonempty() {
2105+
let tag = build_sentry_release_tag();
2106+
let after_prefix = tag.strip_prefix("openhuman@").unwrap_or("");
2107+
assert!(!after_prefix.is_empty(), "version part must not be empty");
2108+
}
2109+
2110+
/// When a SHA is baked in the tag takes the form `openhuman@<ver>+<sha12>`.
2111+
/// When it is not, the tag is simply `openhuman@<ver>` with no `+`.
2112+
/// Either way the full tag must be non-empty.
2113+
#[test]
2114+
fn sentry_release_tag_is_nonempty() {
2115+
assert!(!build_sentry_release_tag().is_empty());
2116+
}
2117+
2118+
// -------------------------------------------------------------------------
2119+
// resolve_sentry_environment
2120+
// -------------------------------------------------------------------------
2121+
2122+
#[test]
2123+
fn sentry_environment_reads_openhuman_app_env() {
2124+
let _g = ENV_LOCK.lock().unwrap();
2125+
let key = "OPENHUMAN_APP_ENV";
2126+
let original = std::env::var(key).ok();
2127+
std::env::set_var(key, "staging");
2128+
let env = resolve_sentry_environment();
2129+
match original {
2130+
Some(v) => std::env::set_var(key, v),
2131+
None => std::env::remove_var(key),
2132+
}
2133+
assert_eq!(env, "staging");
2134+
}
2135+
2136+
#[test]
2137+
fn sentry_environment_trims_whitespace_from_openhuman_app_env() {
2138+
let _g = ENV_LOCK.lock().unwrap();
2139+
let key = "OPENHUMAN_APP_ENV";
2140+
let original = std::env::var(key).ok();
2141+
std::env::set_var(key, " dev ");
2142+
let env = resolve_sentry_environment();
2143+
match original {
2144+
Some(v) => std::env::set_var(key, v),
2145+
None => std::env::remove_var(key),
2146+
}
2147+
assert_eq!(env, "dev");
2148+
}
2149+
2150+
#[test]
2151+
fn sentry_environment_skips_empty_openhuman_app_env() {
2152+
let _g = ENV_LOCK.lock().unwrap();
2153+
let key = "OPENHUMAN_APP_ENV";
2154+
let original = std::env::var(key).ok();
2155+
std::env::set_var(key, "");
2156+
let env = resolve_sentry_environment();
2157+
match original {
2158+
Some(v) => std::env::set_var(key, v),
2159+
None => std::env::remove_var(key),
2160+
}
2161+
// Falls through to VITE_ compile-time value or "production"; must be non-empty.
2162+
assert!(!env.is_empty());
2163+
}
2164+
2165+
#[test]
2166+
fn sentry_environment_skips_whitespace_only_openhuman_app_env() {
2167+
let _g = ENV_LOCK.lock().unwrap();
2168+
let key = "OPENHUMAN_APP_ENV";
2169+
let original = std::env::var(key).ok();
2170+
std::env::set_var(key, " ");
2171+
let env = resolve_sentry_environment();
2172+
match original {
2173+
Some(v) => std::env::set_var(key, v),
2174+
None => std::env::remove_var(key),
2175+
}
2176+
assert!(!env.is_empty());
2177+
}
2178+
2179+
/// When neither runtime env var nor compile-time VITE_ is set, the fallback
2180+
/// must be "production". Guard with a compile-time check so this test only
2181+
/// asserts the hard default when no compile-time override is present.
2182+
#[test]
2183+
fn sentry_environment_defaults_to_production_when_unset() {
2184+
let _g = ENV_LOCK.lock().unwrap();
2185+
if option_env!("VITE_OPENHUMAN_APP_ENV").is_some() {
2186+
// A compile-time override is baked in; skip — the fallback path is
2187+
// exercised by sentry_environment_skips_empty_openhuman_app_env.
2188+
return;
2189+
}
2190+
let key = "OPENHUMAN_APP_ENV";
2191+
let original = std::env::var(key).ok();
2192+
std::env::remove_var(key);
2193+
let env = resolve_sentry_environment();
2194+
match original {
2195+
Some(v) => std::env::set_var(key, v),
2196+
None => std::env::remove_var(key),
2197+
}
2198+
assert_eq!(env, "production");
2199+
}
19862200
}

0 commit comments

Comments
 (0)