Seregon/StratoSDK

StratoSDK is a framework with a declarative approach similar to Flutter/React, written and designed entirely for Rust.

Rust/27.3 KB/No license
crates/strato-ui-renderer/src/platform/mac/clipboard_tests.rs
StratoSDK / crates / strato-ui-renderer / src / platform / mac / clipboard_tests.rs
1//! Memory-behavior repro for APP-4154 batch 1.C (strato_ui-platform-nsstring).
2//!
3//! Exercises the `NSString::alloc(nil).init_str(...)` → `make_nsstring(...)` conversions
4//! applied to `pasteboard_type_for_image_mime_type` and related clipboard
5//! helpers. The helper is shared by every retained-NSString site in this file
6//! (6 in `read_image_data_from_pasteboard`, 2 in `Clipboard::write`, and this
7//! one in `pasteboard_type_for_image_mime_type`), so it is representative for
8//! the whole file.
9//!
10//! On master the raw `NSString::alloc(nil).init_str(...)` returns a string with
11//! a +1 retain count that no pool drain can clean up, so even inside an outer
12//! `NSAutoreleasePool` the string survives past `pool.drain()` and memory grows
13//! linearly with iteration count.
14//!
15//! On the PR branch `make_nsstring` autoreleases, so every string returned here
16//! is released when the surrounding pool drains and peak RSS stays flat across
17//! outer iterations.
18//!
19//! Run as:
20//! cargo test --release -p strato_ui \
21//! pasteboard_type_for_image_mime_type_memory_behavior -- --nocapture --ignored
22//! and measure peak RSS with `/usr/bin/time -l`.
23use cocoa::base::nil;
24use cocoa::foundation::NSAutoreleasePool;
25 
26use super::pasteboard_type_for_image_mime_type;
27 
28/// Number of outer pool cycles. Each cycle creates an `NSAutoreleasePool`,
29/// runs the inner loop, then drains. On master the retained NSStrings survive
30/// the drain, so memory usage grows proportionally to OUTER * INNER.
31const OUTER: usize = 60;
32 
33/// Number of inner iterations per pool cycle. Must be large enough to produce
34/// a measurable RSS delta but small enough to fit easily in memory on the
35/// branch side (where strings are reclaimed per cycle).
36const INNER: usize = 20_000;
37 
38const MIME_TYPES: &[&str] = &[
39 "image/png",
40 "image/jpeg",
41 "image/gif",
42 "image/webp",
43 "image/svg+xml",
44];
45 
46#[test]
47#[ignore = "memory repro; run with --ignored --nocapture in release mode"]
48fn pasteboard_type_for_image_mime_type_memory_behavior() {
49 unsafe {
50 for _ in 0..OUTER {
51 let pool = NSAutoreleasePool::new(nil);
52 for _ in 0..INNER {
53 for mime in MIME_TYPES {
54 let ns = pasteboard_type_for_image_mime_type(mime);
55 assert!(ns.is_some(), "mime {mime} should be mapped");
56 }
57 }
58 pool.drain();
59 }
60 }
61}
62