1#![cfg_attr(all(coverage_nightly, test), feature(coverage_attribute))]
39
40mod cpu;
41
42pub use cpu::Cpu;
43
44#[derive(Debug, thiserror::Error)]
46pub enum PprofError {
47 #[error(transparent)]
48 Io(#[from] std::io::Error),
49 #[error(transparent)]
50 Pprof(#[from] pprof::Error),
51}
52
53#[cfg(test)]
54#[cfg_attr(all(coverage_nightly, test), coverage(off))]
55mod tests {
56 use std::io::Read;
57 use std::time::SystemTime;
58
59 use flate2::read::GzDecoder;
60 use pprof::protos::Message;
61
62 use crate::Cpu;
63
64 #[test]
65 fn empty_profile() {
66 let before_nanos = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_nanos() as i64;
67
68 let cpu = Cpu::new::<String>(1000, &[]);
69 let profile = cpu.capture(std::time::Duration::from_secs(1)).unwrap();
70
71 let mut reader = GzDecoder::new(profile.as_slice());
73 let mut buf = Vec::new();
74 reader.read_to_end(&mut buf).unwrap();
75 let profile = pprof::protos::Profile::decode(buf.as_slice()).unwrap();
76
77 assert!(profile.duration_nanos > 1_000_000_000);
78 assert!(profile.time_nanos > before_nanos);
79 let now_nanos = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_nanos() as i64;
80 assert!(profile.time_nanos < now_nanos);
81
82 assert_eq!(profile.string_table[profile.drop_frames as usize], "");
83 assert_eq!(profile.string_table[profile.keep_frames as usize], "");
84
85 let Some(period_type) = profile.period_type else {
86 panic!("missing period type");
87 };
88 assert_eq!(profile.string_table[period_type.ty as usize], "cpu");
89 assert_eq!(profile.string_table[period_type.unit as usize], "nanoseconds");
90
91 assert_eq!(profile.period, 1_000_000);
92 }
93}