microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
billt/mac-intel-cryptography

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

source/compiler/qsc/src/interpret/debugger_tests.rs

286lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use crate::interpret::Debugger;
5use crate::line_column::Encoding;
6use qsc_data_structures::language_features::LanguageFeatures;
7use qsc_eval::{StepAction, StepResult, output::CursorReceiver};
8use qsc_fir::fir::StmtId;
9use std::io::Cursor;
10
11fn get_breakpoint_ids(debugger: &Debugger, path: &str) -> Vec<StmtId> {
12 let mut bps = debugger.get_breakpoints(path);
13 bps.sort_by_key(|f| f.id);
14 bps.iter().map(|f| f.id.into()).collect::<Vec<_>>()
15}
16
17fn expect_return(mut debugger: Debugger, expected: &str) {
18 let r = step_next(&mut debugger, &[]);
19 match r.0 {
20 Ok(StepResult::Return(value)) => assert_eq!(value.to_string(), expected),
21 Ok(v) => panic!("Expected Return, got {v:?}"),
22 Err(e) => panic!("Expected Return, got {e:?}"),
23 }
24}
25
26fn expect_bp(debugger: &mut Debugger, ids: &[StmtId], expected_id: StmtId) {
27 let r = step_next(debugger, ids);
28 match r.0 {
29 Ok(StepResult::BreakpointHit(actual_id)) => assert!(actual_id == expected_id),
30 Ok(v) => panic!("Expected BP, got {v:?}"),
31 Err(e) => panic!("Expected BP, got {e:?}"),
32 }
33}
34
35fn step_in(
36 debugger: &mut Debugger,
37 breakpoints: &[StmtId],
38) -> (Result<StepResult, Vec<crate::interpret::Error>>, String) {
39 step(debugger, breakpoints, qsc_eval::StepAction::In)
40}
41
42fn step_next(
43 debugger: &mut Debugger,
44 breakpoints: &[StmtId],
45) -> (Result<StepResult, Vec<crate::interpret::Error>>, String) {
46 step(debugger, breakpoints, qsc_eval::StepAction::Next)
47}
48
49fn step_out(
50 debugger: &mut Debugger,
51 breakpoints: &[StmtId],
52) -> (Result<StepResult, Vec<crate::interpret::Error>>, String) {
53 step(debugger, breakpoints, qsc_eval::StepAction::Out)
54}
55
56fn step(
57 debugger: &mut Debugger,
58 breakpoints: &[StmtId],
59 step: StepAction,
60) -> (Result<StepResult, Vec<crate::interpret::Error>>, String) {
61 let mut cursor = Cursor::new(Vec::<u8>::new());
62 let mut receiver = CursorReceiver::new(&mut cursor);
63 (
64 debugger.eval_step(&mut receiver, breakpoints, step),
65 receiver.dump(),
66 )
67}
68
69fn expect_next(debugger: &mut Debugger) {
70 let result = step_next(debugger, &[]);
71 match result.0 {
72 Ok(StepResult::Next) => (),
73 Ok(v) => panic!("Expected Next, got {v:?}"),
74 Err(e) => panic!("Expected Next, got {e:?}"),
75 }
76}
77
78fn expect_in(debugger: &mut Debugger) {
79 let result = step_in(debugger, &[]);
80 match result.0 {
81 Ok(StepResult::StepIn) => (),
82 Ok(v) => panic!("Expected StepIn, got {v:?}"),
83 Err(e) => panic!("Expected StepIn, got {e:?}"),
84 }
85}
86
87fn expect_out(debugger: &mut Debugger) {
88 let result = step_out(debugger, &[]);
89 match result.0 {
90 Ok(StepResult::StepOut) => (),
91 Ok(v) => panic!("Expected StepOut, got {v:?}"),
92 Err(e) => panic!("Expected StepOut, got {e:?}"),
93 }
94}
95
96#[cfg(test)]
97mod given_debugger {
98 use super::*;
99
100 static STEPPING_SOURCE: &str = r#"
101 namespace Test {
102 @EntryPoint()
103 operation A() : Int {
104 let d = B();
105 let e = d / 1;
106 e
107 }
108 operation B() : Int {
109 let g = 10;
110 let h = 20;
111 let l = C(g, h);
112 42
113 }
114 operation C(m: Int, n: Int) : Int {
115 let o = 42 - (m + n);
116 let p = (m + n) + o;
117 p
118 }
119 }"#;
120
121 static DUPLICATE_RANGE_SOURCE: &str = r#"
122 namespace Sample {
123 @EntryPoint()
124 operation Main() : Result[] {
125 use q1 = Qubit();
126 Y(q1);
127 let m1 = M(q1);
128 return [m1];
129 }
130 }"#;
131
132 #[cfg(test)]
133 mod step {
134 use qsc_data_structures::{source::SourceMap, target::TargetCapabilityFlags};
135 use rustc_hash::FxHashSet;
136
137 use super::*;
138
139 #[test]
140 fn in_one_level_operation_works() -> Result<(), Vec<crate::interpret::Error>> {
141 use qsc_data_structures::language_features::LanguageFeatures;
142 let sources = SourceMap::new([("test".into(), STEPPING_SOURCE.into())], None);
143 let (std_id, store) =
144 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
145 let mut debugger = Debugger::new(
146 sources,
147 TargetCapabilityFlags::all(),
148 Encoding::Utf8,
149 LanguageFeatures::default(),
150 store,
151 &[(std_id, None)],
152 )?;
153 let ids = get_breakpoint_ids(&debugger, "test");
154 let expected_id = ids[0];
155 expect_bp(&mut debugger, &ids, expected_id);
156 expect_in(&mut debugger);
157 expect_next(&mut debugger);
158 expect_next(&mut debugger);
159 expect_next(&mut debugger);
160 expect_next(&mut debugger);
161 expect_next(&mut debugger);
162 expect_next(&mut debugger);
163 expect_next(&mut debugger);
164 let expected = "42";
165 expect_return(debugger, expected);
166 Ok(())
167 }
168
169 #[test]
170 fn next_crosses_operation_works() -> Result<(), Vec<crate::interpret::Error>> {
171 let sources = SourceMap::new([("test".into(), STEPPING_SOURCE.into())], None);
172 let (std_id, store) =
173 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
174 let mut debugger = Debugger::new(
175 sources,
176 TargetCapabilityFlags::all(),
177 Encoding::Utf8,
178 LanguageFeatures::default(),
179 store,
180 &[(std_id, None)],
181 )?;
182 let ids = get_breakpoint_ids(&debugger, "test");
183 let expected_id = ids[0];
184 expect_bp(&mut debugger, &ids, expected_id);
185 expect_next(&mut debugger);
186 expect_next(&mut debugger);
187 expect_next(&mut debugger);
188 let expected = "42";
189 expect_return(debugger, expected);
190 Ok(())
191 }
192
193 #[test]
194 fn in_multiple_operations_works() -> Result<(), Vec<crate::interpret::Error>> {
195 let sources = SourceMap::new([("test".into(), STEPPING_SOURCE.into())], None);
196 let (std_id, store) =
197 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
198 let mut debugger = Debugger::new(
199 sources,
200 TargetCapabilityFlags::all(),
201 Encoding::Utf8,
202 LanguageFeatures::default(),
203 store,
204 &[(std_id, None)],
205 )?;
206 let ids = get_breakpoint_ids(&debugger, "test");
207 let expected_id = ids[0];
208 expect_bp(&mut debugger, &ids, expected_id);
209 expect_in(&mut debugger);
210 expect_next(&mut debugger);
211 expect_next(&mut debugger);
212 expect_in(&mut debugger);
213 expect_next(&mut debugger);
214 expect_next(&mut debugger);
215 expect_next(&mut debugger);
216 expect_next(&mut debugger);
217 expect_next(&mut debugger);
218 expect_next(&mut debugger);
219 expect_next(&mut debugger);
220 expect_next(&mut debugger);
221 let expected = "42";
222 expect_return(debugger, expected);
223 Ok(())
224 }
225
226 #[test]
227 fn out_multiple_operations_works() -> Result<(), Vec<crate::interpret::Error>> {
228 let sources = SourceMap::new([("test".into(), STEPPING_SOURCE.into())], None);
229 let (std_id, store) =
230 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
231 let mut debugger = Debugger::new(
232 sources,
233 TargetCapabilityFlags::all(),
234 Encoding::Utf8,
235 LanguageFeatures::default(),
236 store,
237 &[(std_id, None)],
238 )?;
239 let ids = get_breakpoint_ids(&debugger, "test");
240 let expected_id = ids[0];
241 expect_bp(&mut debugger, &ids, expected_id);
242 expect_in(&mut debugger);
243 expect_next(&mut debugger);
244 expect_next(&mut debugger);
245 expect_in(&mut debugger);
246 expect_out(&mut debugger);
247 expect_out(&mut debugger);
248 expect_next(&mut debugger);
249 expect_next(&mut debugger);
250 let expected = "42";
251 expect_return(debugger, expected);
252 Ok(())
253 }
254
255 #[test]
256 fn duplicate_source_ranges_collapse_to_one_hittable_breakpoint()
257 -> Result<(), Vec<crate::interpret::Error>> {
258 let sources = SourceMap::new([("test.qs".into(), DUPLICATE_RANGE_SOURCE.into())], None);
259 let (std_id, store) =
260 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
261 let mut debugger = Debugger::new(
262 sources,
263 TargetCapabilityFlags::all(),
264 Encoding::Utf8,
265 LanguageFeatures::default(),
266 store,
267 &[(std_id, None)],
268 )?;
269
270 let breakpoints = debugger.get_breakpoints("test.qs");
271 assert_eq!(breakpoints.len(), 4);
272
273 let unique_ranges: FxHashSet<_> = breakpoints.iter().map(|bp| bp.range).collect();
274 assert_eq!(unique_ranges.len(), breakpoints.len());
275
276 let return_breakpoint_id = breakpoints
277 .last()
278 .expect("expected a return breakpoint")
279 .id
280 .into();
281
282 expect_bp(&mut debugger, &[return_breakpoint_id], return_breakpoint_id);
283 Ok(())
284 }
285 }
286}
287