1#![allow(clippy::from_over_into)]
6mod abstract_trace_writer;
12mod base64;
13mod capnptrace;
14
15#[cfg(target_arch = "wasm32")]
16#[path = "./cbor_zstd_reader_wasm.rs"]
17mod cbor_zstd_reader;
18#[cfg(target_arch = "wasm32")]
19#[path = "./cbor_zstd_writer_wasm.rs"]
20mod cbor_zstd_writer;
21
22#[cfg(not(target_arch = "wasm32"))]
23mod cbor_zstd_reader;
24#[cfg(not(target_arch = "wasm32"))]
25mod cbor_zstd_writer;
26
27mod non_streaming_trace_writer;
28mod trace_readers;
29mod trace_writer;
30mod tracer;
31mod types;
32
33pub use crate::non_streaming_trace_writer::NonStreamingTraceWriter;
34pub use crate::trace_readers::TraceReader;
35pub use crate::trace_writer::TraceWriter;
36pub use crate::tracer::{NONE_TYPE_ID, NONE_VALUE, TraceEventsFileFormat, create_trace_reader, create_trace_writer};
37pub use crate::types::*;
38
39pub mod trace_capnp {
40 include!(concat!(env!("OUT_DIR"), "/src/trace_capnp.rs"));
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46 use std::path::Path;
47 #[test]
50 fn test_simple_trace() {
51 let mut tracer = NonStreamingTraceWriter::new("path.small", &vec![]);
52 let path = Path::new("/test/path.small");
53 tracer.start(path, Line(1));
54 tracer.register_step(path, Line(1));
55 tracer.register_step(path, Line(2));
56 tracer.register_asm(&["asm0".to_string(), "asm1".to_string()]);
57 tracer.register_special_event(EventLogKind::Write, "test");
58 tracer.register_special_event(EventLogKind::Write, "test2");
59 tracer.register_special_event(EventLogKind::Error, "testError");
60
61 let function_path_id = tracer.ensure_path_id(&path);
62 let function_line = Line(3);
63 let function_id = tracer.ensure_function_id("function", &path, function_line);
65 assert!(function_id == FunctionId(1));
66
67 let before_temp_step = tracer.events.len();
68 tracer.register_step(path, function_line);
69 tracer.drop_last_step();
70 assert_eq!(before_temp_step + 2, tracer.events.len());
72 assert!(matches!(tracer.events.last().unwrap(), TraceLowLevelEvent::DropLastStep));
73
74 let args = vec![tracer.arg("a", NONE_VALUE), tracer.arg("b", NONE_VALUE)];
75 tracer.register_call(function_id, args);
76 assert!(tracer.events.len() > 3);
79 let should_be_step = &tracer.events[tracer.events.len() - 2];
82 let should_be_call = &tracer.events[tracer.events.len() - 1];
83 if let TraceLowLevelEvent::Step(StepRecord { path_id, line }) = should_be_step {
84 assert_eq!(*path_id, function_path_id);
85 assert_eq!(*line, function_line);
86 } else {
87 assert!(false, "expected a auto-registered step event before the last call one");
88 }
89 assert!(matches!(should_be_call, TraceLowLevelEvent::Call(CallRecord { .. })));
90
91 let int_value_1 = ValueRecord::Int {
92 i: 1,
93 type_id: tracer.ensure_type_id(TypeKind::Int, "Int"),
94 };
95 let int_value_2 = ValueRecord::Int {
96 i: 2,
97 type_id: tracer.ensure_type_id(TypeKind::Int, "Int"),
98 };
99 let int_value_3 = ValueRecord::Int {
100 i: 3,
101 type_id: tracer.ensure_type_id(TypeKind::Int, "Int"),
102 };
103
104 tracer.register_variable_with_full_value("test_variable", int_value_1.clone());
105
106 let not_supported_value = ValueRecord::Error {
107 msg: "not supported".to_string(),
108 type_id: NONE_TYPE_ID,
109 };
110 tracer.register_variable_with_full_value("test_variable2", not_supported_value);
111
112 tracer.register_cell_value(Place(0), int_value_1.clone());
113 let type_id = tracer.ensure_type_id(TypeKind::Seq, "Vector<Int>");
114 tracer.register_compound_value(
115 Place(1),
116 ValueRecord::Sequence {
117 elements: vec![ValueRecord::Cell { place: Place(0) }], is_slice: false,
119 type_id,
120 },
121 );
122 tracer.register_variable("test_variable3", Place(1));
123 tracer.assign_cell(Place(1), int_value_2.clone());
124 tracer.register_cell_value(Place(2), int_value_2.clone());
125 tracer.assign_compound_item(Place(0), 0, Place(2));
126
127 tracer.register_return(NONE_VALUE);
128 tracer.drop_variable("test_variable3");
129
130 tracer.bind_variable("variable1", Place(1));
132 tracer.bind_variable("variable2", Place(2));
133 tracer.bind_variable("variable3", Place(3));
134
135 tracer.register_variable_with_full_value("variable1", int_value_1.clone());
136 tracer.register_variable_with_full_value("variable2", int_value_2.clone());
137 tracer.register_variable_with_full_value("variable3", int_value_3.clone());
138
139 let rvalue_1 = tracer.simple_rvalue("variable2");
144 tracer.assign("variable1", rvalue_1, PassBy::Value);
145 let rvalue_2 = tracer.compound_rvalue(&["variable2".to_string(), "variable3".to_string()]);
146 tracer.assign("variable1", rvalue_2, PassBy::Value);
147
148 let reference_type = TypeRecord {
150 kind: TypeKind::Pointer,
151 lang_type: "MyReference<Int>".to_string(),
152 specific_info: TypeSpecificInfo::Pointer {
153 dereference_type_id: tracer.ensure_type_id(TypeKind::Int, "Int"),
154 },
155 };
156 let reference_type_id = tracer.ensure_raw_type_id(reference_type);
157 let _reference_value = ValueRecord::Reference {
158 dereferenced: Box::new(int_value_1.clone()),
159 address: 0,
160 mutable: false,
161 type_id: reference_type_id,
162 };
163
164 tracer.drop_variables(&["variable1".to_string(), "variable2".to_string(), "variable3".to_string()]);
165
166 assert_eq!(tracer.events.len(), 47);
167 }
175
176 #[test]
177 fn test_equality_of_value_records() {
178 let a = ValueRecord::Int { i: 0, type_id: TypeId(0) }; let b = ValueRecord::Int { i: 0, type_id: TypeId(0) };
180 let different = ValueRecord::Int { i: 1, type_id: TypeId(0) };
181
182 assert_eq!(a, b);
183 assert_ne!(a, different);
184 }
185}