Skip to content

Commit 9958011

Browse files
committed
test: initial version of a rr test
TODO: a lot of things; is it ok to test like this a closed source part: ct-rr-worker? also, depends on many build artifacts that are not stable/ready for others (lldbinit.py in workdir: src/db-backend; ct-rr-worker build) also, a problem with socket in the end, non-critical also depends on local `rr-trace` in src/db-backend: it can be recorded from rust `rr_gdb.rs` from `codetracer-rr-backend`: TODO automate this for test? currently ignored by default: run with `cargo test -- --ignored rr`
1 parent 3f9644d commit 9958011

File tree

1 file changed

+189
-0
lines changed

1 file changed

+189
-0
lines changed

src/db-backend/tests/rr_test.rs

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
use std::io::BufReader;
2+
use std::path::PathBuf;
3+
use std::process::{Command, Stdio};
4+
5+
use serde_json::json;
6+
7+
use db_backend::dap::{self, DapClient, DapMessage, LaunchRequestArguments};
8+
// use db_backend::dap_types::StackTraceArguments;
9+
use db_backend::task;
10+
11+
#[test]
12+
#[ignore] // ignored by default, as they depend on closed source ct-rr-worker/also not finished setup
13+
fn test_rr() {
14+
let bin = env!("CARGO_BIN_EXE_db-backend");
15+
let pid = std::process::id() as usize;
16+
let trace_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("rr-trace");
17+
18+
let mut child = Command::new(bin)
19+
.arg("dap-server")
20+
.arg("--stdio")
21+
.stdin(Stdio::piped())
22+
.stdout(Stdio::piped())
23+
.spawn()
24+
.unwrap();
25+
26+
let mut writer = child.stdin.take().unwrap();
27+
let mut reader = BufReader::new(child.stdout.take().unwrap());
28+
29+
let mut client = DapClient::default();
30+
let init = client.request("initialize", json!({}));
31+
dap::write_message(&mut writer, &init).unwrap();
32+
let launch_args = LaunchRequestArguments {
33+
program: Some("rr_gdb".to_string()),
34+
trace_folder: Some(trace_dir),
35+
trace_file: None,
36+
raw_diff_index: None,
37+
pid: Some(pid as u64),
38+
cwd: None,
39+
no_debug: None,
40+
restart: None,
41+
name: None,
42+
request: None,
43+
typ: None,
44+
session_id: None,
45+
ct_rr_worker_exe: Some(PathBuf::from("/home/alexander92/codetracer-rr-backend/src/build-debug/bin/ct-rr-worker")),
46+
};
47+
let launch = client.launch(launch_args).unwrap();
48+
dap::write_message(&mut writer, &launch).unwrap();
49+
50+
let msg1 = dap::from_reader(&mut reader).unwrap();
51+
match msg1 {
52+
DapMessage::Response(r) => {
53+
assert_eq!(r.command, "initialize");
54+
// assert!(r.body["supportsLoadedSourcesRequest"].as_bool().unwrap());
55+
assert!(r.body["supportsStepBack"].as_bool().unwrap());
56+
assert!(r.body["supportsConfigurationDoneRequest"].as_bool().unwrap());
57+
assert!(r.body["supportsDisassembleRequest"].as_bool().unwrap());
58+
assert!(r.body["supportsLogPoints"].as_bool().unwrap());
59+
assert!(r.body["supportsRestartRequest"].as_bool().unwrap());
60+
}
61+
_ => panic!(),
62+
}
63+
let msg2 = dap::from_reader(&mut reader).unwrap();
64+
match msg2 {
65+
DapMessage::Event(e) => assert_eq!(e.event, "initialized"),
66+
_ => panic!(),
67+
}
68+
let conf_done = client.request("configurationDone", json!({}));
69+
dap::write_message(&mut writer, &conf_done).unwrap();
70+
let msg3 = dap::from_reader(&mut reader).unwrap();
71+
match msg3 {
72+
DapMessage::Response(r) => assert_eq!(r.command, "launch"),
73+
_ => panic!(),
74+
}
75+
let msg4 = dap::from_reader(&mut reader).unwrap();
76+
match msg4 {
77+
DapMessage::Response(r) => assert_eq!(r.command, "configurationDone"),
78+
_ => panic!(),
79+
}
80+
81+
let msg5 = dap::from_reader(&mut reader).unwrap();
82+
match msg5 {
83+
DapMessage::Event(e) => {
84+
assert_eq!(e.event, "stopped");
85+
assert_eq!(e.body["reason"], "entry");
86+
}
87+
_ => panic!("expected a stopped event, but got {:?}", msg5),
88+
}
89+
90+
let msg_complete_move = dap::from_reader(&mut reader).unwrap();
91+
match msg_complete_move {
92+
DapMessage::Event(e) => {
93+
assert_eq!(e.event, "ct/complete-move");
94+
let move_state = serde_json::from_value::<task::MoveState>(e.body).expect("valid move state");
95+
let path = PathBuf::from(move_state.clone().location.path);
96+
let filename = path.file_name().expect("filename");
97+
assert_eq!(filename.display().to_string(), "rr_gdb.rs");
98+
assert_eq!(move_state.location.line, 205);
99+
assert_eq!(move_state.location.function_name.starts_with("rr_gdb::main"), true);
100+
101+
}
102+
_ => panic!("expected a complete move events, but got {:?}", msg_complete_move),
103+
}
104+
105+
// next to next line in `main`
106+
let next_request = client.request("next", json!({}));
107+
dap::write_message(&mut writer, &next_request).unwrap();
108+
109+
// `stepIn` to `run`
110+
let step_in_request = client.request("stepIn", json!({}));
111+
dap::write_message(&mut writer, &step_in_request).unwrap();
112+
113+
// `next` to next line in `run`: to check a local
114+
dap::write_message(&mut writer, &next_request).unwrap();
115+
116+
for _ in 0 .. 7 {
117+
let _ = dap::from_reader(&mut reader).unwrap();
118+
}
119+
120+
let msg_complete_move_before_local_check = dap::from_reader(&mut reader).unwrap();
121+
match msg_complete_move_before_local_check {
122+
DapMessage::Event(e) => {
123+
assert_eq!(e.event, "ct/complete-move");
124+
let move_state = serde_json::from_value::<task::MoveState>(e.body).expect("valid move state");
125+
let path = PathBuf::from(move_state.clone().location.path);
126+
let filename = path.file_name().expect("filename");
127+
assert_eq!(filename.display().to_string(), "rr_gdb.rs");
128+
assert_eq!(move_state.location.line, 72);
129+
assert_eq!(move_state.location.function_name.starts_with("rr_gdb::run"), true);
130+
}
131+
_ => panic!("expected a complete move events, but got {:?}", msg_complete_move_before_local_check),
132+
133+
}
134+
135+
let load_locals_request = client.request("ct/load-locals", serde_json::to_value(&task::CtLoadLocalsArguments {
136+
count_budget: 3_000,
137+
min_count_limit: 50,
138+
rr_ticks: 0,
139+
}).unwrap());
140+
let _next_response = dap::from_reader(&mut reader).unwrap();
141+
142+
dap::write_message(&mut writer, &load_locals_request).unwrap();
143+
let load_locals_response = dap::from_reader(&mut reader).unwrap();
144+
if let DapMessage::Response(response) = load_locals_response {
145+
assert_eq!(response.command, "ct/load-locals");
146+
println!("{:?}", response.body);
147+
let variables = serde_json::from_value::<task::CtLoadLocalsResponseBody>(response.body)
148+
.expect("valid local response")
149+
.locals;
150+
assert_eq!(variables[0].expression, "i");
151+
assert_eq!(variables[0].value.typ.lang_type, "i64"); //?
152+
assert_eq!(variables[0].value.i, "0");
153+
}
154+
155+
// let threads_request = client.request("threads", json!({}));
156+
// dap::write_message(&mut writer, &threads_request).unwrap();
157+
// let msg_threads = dap::from_reader(&mut reader).unwrap();
158+
// match msg_threads {
159+
// DapMessage::Response(r) => {
160+
// assert_eq!(r.command, "threads");
161+
// assert_eq!(r.body["threads"][0]["id"], 1);
162+
// }
163+
// _ => panic!(
164+
// "expected a Response DapMessage after a threads request, but got {:?}",
165+
// msg_threads
166+
// ),
167+
// }
168+
169+
// let stack_trace_request = client.request(
170+
// "stackTrace",
171+
// serde_json::to_value(StackTraceArguments {
172+
// thread_id: 1,
173+
// format: None,
174+
// levels: None,
175+
// start_frame: None,
176+
// })
177+
// .unwrap(),
178+
// );
179+
// dap::write_message(&mut writer, &stack_trace_request).unwrap();
180+
// let msg_stack_trace = dap::from_reader(&mut reader).unwrap();
181+
// match msg_stack_trace {
182+
// DapMessage::Response(r) => assert_eq!(r.command, "stackTrace"), // TODO: test stackFrames / totalFrames ?
183+
// _ => panic!(),
184+
// }
185+
186+
drop(writer);
187+
drop(reader);
188+
let _ = child.wait().unwrap();
189+
}

0 commit comments

Comments
 (0)