Skip to content

Commit 892e893

Browse files
committed
UNIT TEEEESTS
1 parent 945e10e commit 892e893

File tree

8 files changed

+200
-67
lines changed

8 files changed

+200
-67
lines changed

readme.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@
88
- config: ✔️
99
- event: ✔️
1010
- image: ✔️
11-
- insn:
12-
- packet:
11+
- insn: ✔️
12+
- packet: ✔️
1313
- asid: ✔️️
14-
- encoder: ❌
15-
- error: ❌
16-
- flags: ❌
17-
- query: ❌
14+
- encoder: ✔️
15+
- query: ✔️
1816
- version: ✔️
1917

2018
# Integration Tests

src/encoder.rs

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
use super::error::{
2+
PtError, ensure_ptok,
3+
extract_pterr, deref_ptresult,
4+
deref_ptresult_mut
5+
};
16
use super::config::Config;
2-
use super::error::{PtError, ensure_ptok, extract_pterr, deref_ptresult};
37

48
use std::marker::PhantomData;
59

@@ -14,26 +18,43 @@ use libipt_sys::{
1418
pt_enc_sync_set
1519
};
1620

21+
#[cfg(test)]
1722
mod tests {
23+
use super::*;
24+
use crate::packet::mnt::Mnt;
25+
1826
#[test]
19-
fn can_allocate_encoder() {
27+
fn test_pktdec_alloc() {
28+
Encoder::new(&mut Config::<()>::new(&mut [0; 0])).unwrap();
29+
}
30+
31+
#[test ]
32+
fn test_pktdec_props() {
33+
// this just checks memory safety for property access
34+
// usage can be found in the integration tests
35+
let mut p = Encoder::new(&mut Config::<()>::new(&mut [0; 0]))
36+
.unwrap();
2037

38+
assert!(p.config().is_ok());
39+
assert_eq!(p.offset().unwrap(), 0);
40+
assert!(p.set_offset(6).is_err());
41+
assert!(p.next(Mnt::new(5)).is_err());
2142
}
2243
}
2344

24-
pub struct Encoder<T>(pt_encoder, PhantomData<T>);
25-
impl<T> Encoder<T> {
45+
pub struct Encoder<'a, T>(&'a mut pt_encoder, PhantomData<T>);
46+
impl<'a, T> Encoder<'a, T> {
2647
/// Allocate an Intel PT packet encoder.
2748
///
2849
/// The encoder will work on the buffer defined in @config, it shall contain raw trace data and remain valid for the lifetime of the encoder.
2950
/// The encoder starts at the beginning of the trace buffer.
3051
pub fn new(cfg: &mut Config<T>) -> Result<Self, PtError> {
31-
deref_ptresult(unsafe { pt_alloc_encoder(cfg.0.to_mut()) })
32-
.map(|x| Encoder::<T>(*x, PhantomData))
52+
deref_ptresult_mut(unsafe { pt_alloc_encoder(cfg.0.to_mut()) })
53+
.map(|x| Encoder::<T>(x, PhantomData))
3354
}
3455

3556
pub fn config(&self) -> Result<Config<T>, PtError> {
36-
deref_ptresult(unsafe{pt_enc_get_config(&self.0)})
57+
deref_ptresult(unsafe{pt_enc_get_config(self.0)})
3758
.map(Config::from)
3859
}
3960

@@ -44,7 +65,7 @@ impl<T> Encoder<T> {
4465
/// Returns Invalid if @offset is NULL.
4566
pub fn offset(&self) -> Result<u64, PtError> {
4667
let mut off = 0;
47-
ensure_ptok(unsafe{pt_enc_get_offset(&self.0, &mut off)})
68+
ensure_ptok(unsafe{pt_enc_get_offset(self.0, &mut off)})
4869
.map(|_| off)
4970
}
5071

@@ -59,7 +80,7 @@ impl<T> Encoder<T> {
5980
/// Returns Eos if the encoder reached the end of the Intel PT buffer.
6081
/// Returns Invalid if @packet is NULL.
6182
pub fn next(&mut self, pck: impl Into<pt_packet>) -> Result<u32, PtError> {
62-
extract_pterr(unsafe{pt_enc_next(&mut self.0, &pck.into())})
83+
extract_pterr(unsafe{ pt_enc_next(self.0, &pck.into()) })
6384
}
6485

6586
/// Hard set synchronization point of an Intel PT packet encoder.
@@ -69,10 +90,10 @@ impl<T> Encoder<T> {
6990
/// Returns Eos if the given offset is behind the end of the trace buffer.
7091
/// Returns Invalid if the encoder is NULL.
7192
pub fn set_offset(&mut self, offset: u64) -> Result<(), PtError> {
72-
ensure_ptok(unsafe{pt_enc_sync_set(&mut self.0, offset)})
93+
ensure_ptok(unsafe{pt_enc_sync_set(self.0, offset)})
7394
}
7495
}
7596

76-
impl<T> Drop for Encoder<T> {
77-
fn drop(&mut self) { unsafe { pt_free_encoder(&mut self.0) } }
97+
impl<'a, T> Drop for Encoder<'a, T> {
98+
fn drop(&mut self) { unsafe { pt_free_encoder(self.0) } }
7899
}

src/event/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ mod test {
8383
assert_eq!(evt.lost_cyc(), 3);
8484

8585
match evt.payload() {
86-
Payload::Stop => assert!(true),
86+
Payload::Stop => (),
8787
_ => unreachable!()
8888
}
8989
}

src/image/image.rs

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -92,19 +92,7 @@ mod test {
9292

9393
#[test]
9494
fn test_img_copy() {
95-
let file: PathBuf = [
96-
env!("CARGO_MANIFEST_DIR"), "testfiles", "garbage.txt"
97-
].iter().collect();
98-
99-
let mut i = Image::new(None).unwrap();
100-
let asid = Asid::new(Some(3), Some(4));
101-
i.add_file(file.to_str().unwrap(), 3, 10, Some(asid), 0x666)
102-
.unwrap();
103-
104-
assert_eq!(
105-
img_with_file().copy(&i).unwrap(),
106-
1
107-
)
95+
assert_eq!(img_with_file().copy(&img_with_file()).unwrap(), 0)
10896
}
10997

11098
#[test]

src/insn/decoder.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::error::{
22
PtError, deref_ptresult,
3-
deref_ptresult_mut,
3+
deref_ptresult_mut, PtErrorCode,
44
ensure_ptok, extract_pterr
55
};
66
use crate::Config;
@@ -41,19 +41,20 @@ mod test {
4141
use super::*;
4242

4343
#[test]
44-
fn test_blkdec_alloc() {
44+
fn test_insndec_alloc() {
4545
InsnDecoder::new(&Config::<()>::new(&mut [0; 0])).unwrap();
4646
}
4747

4848
#[test ]
49-
fn test_blkdec_props() {
49+
fn test_insndec_props() {
5050
// this just checks memory safety for property access
5151
// usage can be found in the integration tests
5252
let mut b = InsnDecoder::new(&Config::<()>::new(&mut [0; 0])).unwrap();
5353
let a = b.asid().unwrap();
5454
assert!(a.cr3().is_none());
5555
assert!(a.vmcs().is_none());
5656

57+
assert!(b.event().is_err());
5758
assert!(b.core_bus_ratio().is_err());
5859
assert!(b.event().is_err());
5960
assert!(b.config().is_ok());
@@ -67,6 +68,9 @@ mod test {
6768
}
6869
}
6970

71+
/// The decoder will work on the buffer defined in the Config,
72+
/// it shall contain raw trace data and remain valid for the lifetime of the decoder.
73+
/// The decoder needs to be synchronized before it can be used.
7074
pub struct InsnDecoder<'a, T>(&'a mut pt_insn_decoder, PhantomData<T>);
7175
impl<'a, T> InsnDecoder<'a, T> {
7276
/// Allocate an Intel PT instruction flow decoder.
@@ -240,6 +244,18 @@ impl<'a, T> InsnDecoder<'a, T> {
240244
}
241245
}
242246

247+
impl<'a, T> Iterator for InsnDecoder<'a, T> {
248+
type Item = Result<(Insn, Status), PtError>;
249+
250+
fn next(&mut self) -> Option<Result<(Insn, Status), PtError>> {
251+
match self.next() {
252+
// eos to stop iterating
253+
Err(x) if x.code() == PtErrorCode::Eos => None,
254+
x => Some(x)
255+
}
256+
}
257+
}
258+
243259
impl<'a, T> Drop for InsnDecoder<'a, T> {
244260
fn drop(&mut self) { unsafe { pt_insn_free_decoder(self.0) } }
245261
}

src/packet/decoder.rs

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
use crate::error::{
2+
PtError, PtErrorCode,
3+
deref_ptresult, deref_ptresult_mut,
4+
ensure_ptok
5+
};
16
use super::Packet;
2-
use crate::error::{PtError, deref_ptresult, ensure_ptok};
37
use crate::Config;
48

59
use std::mem;
@@ -19,20 +23,43 @@ use libipt_sys::{
1923
pt_pkt_sync_set
2024
};
2125

22-
pub struct PacketDecoder<T>(pt_packet_decoder, PhantomData<T>);
23-
impl<T> PacketDecoder<T> {
26+
#[cfg(test)]
27+
mod test {
28+
use super::*;
29+
30+
#[test]
31+
fn test_pktdec_alloc() {
32+
PacketDecoder::new(&Config::<()>::new(&mut [0; 0])).unwrap();
33+
}
34+
35+
#[test ]
36+
fn test_pktdec_props() {
37+
// this just checks memory safety for property access
38+
// usage can be found in the integration tests
39+
let mut p = PacketDecoder::new(&Config::<()>::new(&mut [0; 0])).unwrap();
40+
assert!(p.config().is_ok());
41+
assert!(p.offset().is_err());
42+
assert!(p.sync_offset().is_err());
43+
assert!(p.next().is_err());
44+
assert!(p.sync_backward().is_err());
45+
assert!(p.sync_forward().is_err());
46+
}
47+
}
48+
49+
pub struct PacketDecoder<'a, T>(&'a mut pt_packet_decoder, PhantomData<T>);
50+
impl<'a, T> PacketDecoder<'a, T> {
2451
/// Allocate an Intel PT packet decoder.
2552
///
2653
/// The decoder will work on the buffer defined in @config,
2754
/// it shall contain raw trace data and remain valid for the lifetime of the decoder.
2855
/// The decoder needs to be synchronized before it can be used.
2956
pub fn new(cfg: &Config<T>) -> Result<Self, PtError> {
30-
deref_ptresult(unsafe { pt_pkt_alloc_decoder(cfg.0.as_ref()) })
31-
.map(|d| PacketDecoder::<T>(*d, PhantomData))
57+
deref_ptresult_mut(unsafe { pt_pkt_alloc_decoder(cfg.0.as_ref()) })
58+
.map(|d| PacketDecoder::<T>(d, PhantomData))
3259
}
3360

3461
pub fn config(&self) -> Result<Config<T>, PtError> {
35-
deref_ptresult(unsafe { pt_pkt_get_config(&self.0) })
62+
deref_ptresult(unsafe { pt_pkt_get_config(self.0) })
3663
.map(Config::from)
3764
}
3865

@@ -41,7 +68,7 @@ impl<T> PacketDecoder<T> {
4168
/// Returns Nosync if decoder is out of sync.
4269
pub fn offset(&self) -> Result<u64, PtError> {
4370
let mut off: u64 = 0;
44-
ensure_ptok(unsafe { pt_pkt_get_offset(&self.0, &mut off) })
71+
ensure_ptok(unsafe { pt_pkt_get_offset(self.0, &mut off) })
4572
.map(|_| off)
4673
}
4774

@@ -51,7 +78,7 @@ impl<T> PacketDecoder<T> {
5178
/// Returns Nosync if decoder is out of sync.
5279
pub fn sync_offset(&self) -> Result<u64, PtError> {
5380
let mut off: u64 = 0;
54-
ensure_ptok(unsafe { pt_pkt_get_sync_offset(&self.0, &mut off) })
81+
ensure_ptok(unsafe { pt_pkt_get_sync_offset(self.0, &mut off) })
5582
.map(|_| off)
5683
}
5784

@@ -66,14 +93,14 @@ impl<T> PacketDecoder<T> {
6693
pub fn next(&mut self) -> Result<Packet<T>, PtError> {
6794
let mut pkt: pt_packet = unsafe { mem::zeroed() };
6895
ensure_ptok(unsafe {
69-
pt_pkt_next(&mut self.0,
96+
pt_pkt_next(self.0,
7097
&mut pkt,
7198
mem::size_of::<pt_packet>())
7299
}).map(|_| pkt.into())
73100
}
74101

75102
pub fn sync_backward(&mut self) -> Result<(), PtError> {
76-
ensure_ptok(unsafe { pt_pkt_sync_backward(&mut self.0) })
103+
ensure_ptok(unsafe { pt_pkt_sync_backward(self.0) })
77104
}
78105

79106
/// Synchronize an Intel PT packet decoder.
@@ -84,18 +111,30 @@ impl<T> PacketDecoder<T> {
84111
/// and at the end of the trace buffer in case of backward synchronization.
85112
/// Returns Eos if no further synchronization point is found.
86113
pub fn sync_forward(&mut self) -> Result<(), PtError> {
87-
ensure_ptok(unsafe { pt_pkt_sync_forward(&mut self.0) })
114+
ensure_ptok(unsafe { pt_pkt_sync_forward(self.0) })
88115
}
89116

90117
/// Hard set synchronization point of an Intel PT decoder.
91118
///
92119
/// Synchronize decoder to @offset within the trace buffer.
93120
/// Returns Eos if the given offset is behind the end of the trace buffer.
94121
pub fn sync_set(&mut self, offset: u64) -> Result<(), PtError> {
95-
ensure_ptok(unsafe { pt_pkt_sync_set(&mut self.0, offset) })
122+
ensure_ptok(unsafe { pt_pkt_sync_set(self.0, offset) })
123+
}
124+
}
125+
126+
impl<'a, T> Iterator for PacketDecoder<'a, T> {
127+
type Item = Result<Packet<T>, PtError>;
128+
129+
fn next(&mut self) -> Option<Result<Packet<T>, PtError>> {
130+
match self.next() {
131+
// eos to stop iterating
132+
Err(x) if x.code() == PtErrorCode::Eos => None,
133+
x => Some(x)
134+
}
96135
}
97136
}
98137

99-
impl<T> Drop for PacketDecoder<T> {
100-
fn drop(&mut self) { unsafe { pt_pkt_free_decoder(&mut self.0) }}
138+
impl<'a, T> Drop for PacketDecoder<'a, T> {
139+
fn drop(&mut self) { unsafe { pt_pkt_free_decoder(self.0) }}
101140
}

src/packet/mod.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,28 @@ pub mod unknown;
6060
pub mod decoder;
6161
pub use decoder::PacketDecoder;
6262

63+
#[cfg(test)]
64+
mod test {
65+
use super::*;
66+
use libipt_sys::pt_packet_mnt;
67+
use libipt_sys::pt_packet__bindgen_ty_1;
68+
69+
#[test]
70+
fn test_pkt_from() {
71+
let p1 = pt_packet_mnt { payload: 666 };
72+
let p2 = pt_packet {
73+
type_: PT_PACKET_TYPE_PPT_MNT,
74+
size: std::mem::size_of::<pt_packet_mnt>() as u8,
75+
payload: pt_packet__bindgen_ty_1 { mnt: p1 }
76+
};
77+
let p3: Packet::<()> = p2.into();
78+
match p3 {
79+
Packet::Mnt(m) => assert_eq!(m.payload(), p1.payload),
80+
_ => unreachable!()
81+
};
82+
}
83+
}
84+
6385
pub enum Packet<T> {
6486
Invalid(invalid::Invalid),
6587
Psbend(psbend::Psbend),

0 commit comments

Comments
 (0)