#![cfg_attr(
all(feature = "docs", unix),
doc = "\n\nSee the [changelog][changelog] for a full release history."
)]
#![cfg_attr(feature = "docs", doc = "## Feature flags")]
#![cfg_attr(feature = "docs", doc = document_features::document_features!())]
#![cfg_attr(all(coverage_nightly, test), feature(coverage_attribute))]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![cfg(unix)]
#![deny(missing_docs)]
#![deny(unsafe_code)]
#![deny(unreachable_pub)]
mod cpu;
pub use cpu::Cpu;
#[derive(Debug, thiserror::Error)]
pub enum PprofError {
#[error(transparent)]
Io(#[from] std::io::Error),
#[error(transparent)]
Pprof(#[from] pprof::Error),
}
#[cfg(feature = "docs")]
#[scuffle_changelog::changelog]
pub mod changelog {}
#[cfg(test)]
#[cfg_attr(all(coverage_nightly, test), coverage(off))]
mod tests {
use std::io::Read;
use std::time::SystemTime;
use flate2::read::GzDecoder;
use pprof::protos::Message;
use crate::Cpu;
#[test]
fn empty_profile() {
let before_nanos = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_nanos() as i64;
let cpu = Cpu::new::<String>(1000, &[]);
let profile = cpu.capture(std::time::Duration::from_secs(1)).unwrap();
let mut reader = GzDecoder::new(profile.as_slice());
let mut buf = Vec::new();
reader.read_to_end(&mut buf).unwrap();
let profile = pprof::protos::Profile::decode(buf.as_slice()).unwrap();
assert!(profile.duration_nanos > 1_000_000_000);
assert!(profile.time_nanos > before_nanos);
let now_nanos = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_nanos() as i64;
assert!(profile.time_nanos < now_nanos);
assert_eq!(profile.string_table[profile.drop_frames as usize], "");
assert_eq!(profile.string_table[profile.keep_frames as usize], "");
let Some(period_type) = profile.period_type else {
panic!("missing period type");
};
assert_eq!(profile.string_table[period_type.ty as usize], "cpu");
assert_eq!(profile.string_table[period_type.unit as usize], "nanoseconds");
assert_eq!(profile.period, 1_000_000);
}
}