From f6562a38aa4a4008c043a69062dbc883b0abc0a8 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Fri, 8 May 2026 14:17:38 +0100 Subject: [PATCH] tests: add test for symbol length `__pinned_init` or `__init` functions are natural inline boundaries. Things within them calling into helper functions should be inlined, and wrapping functions that forwarding call to them should be, too. But these functions themselves can contain complex initialization, so it's best to leave it to the compilers to decide if they're inlineable. As a result, these symbols do show up in the symbol table when they're not inlined. Linux kernel has 512 byte symbol length limit, so we need to keep them small. Add a test to ensure that any growth of them are being considered and not accidental. Signed-off-by: Gary Guo --- tests/symbol_length.rs | 61 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 tests/symbol_length.rs diff --git a/tests/symbol_length.rs b/tests/symbol_length.rs new file mode 100644 index 00000000..c449c778 --- /dev/null +++ b/tests/symbol_length.rs @@ -0,0 +1,61 @@ +#![cfg(all(unix, not(miri)))] + +use std::io::{Error, Result, Write}; + +use pin_init::*; + +#[pin_data] +pub struct Test {} + +pub fn init() -> impl PinInit { + pin_init!(Test {} ? Error) +} + +fn init_fn_ptr>(_: &I) -> *mut () { + I::__pinned_init as *mut () +} + +fn read_symbols() -> Result> { + let path = std::env::current_exe()?; + let output = std::process::Command::new("nm") + .arg(path) + .arg("--just-symbols") + .output()?; + if !output.status.success() { + Err(Error::other("exit code is not 0"))? + } + let symbols = String::from_utf8_lossy(&output.stdout); + Ok(symbols + .lines() + .filter(|x| !x.is_empty()) + .map(|x| x.to_owned()) + .collect()) +} + +#[test] +fn type_name() { + let init = init(); + let init_fn = init_fn_ptr(&init); + std::hint::black_box(init_fn); + + let mut symbols = match read_symbols() { + Ok(v) => v, + Err(err) => { + // This might be some setup issue (e.g. no nm installed). + // Instead of failing the test, print the error and continue. + // Do not use `eprintln!()` as it would be captured. + writeln!(std::io::stderr(), "cannot read symbols {:?}", err).unwrap(); + return; + } + }; + + // Filter out non-related symbols. + symbols.retain(|x| x.contains("pin_init") && !x.contains("map")); + + // Find the longest symbol + symbols.sort_by_key(|x| x.len().wrapping_neg()); + let symbol = &symbols[0]; + println!("{}: {}", symbol.len(), symbol); + + assert!(symbol.len() < 180); +}