microsoft/qdk

Public

mirrored fromhttps://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
copilot/fix-2145

Branches

Tags

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

Clone

HTTPS

Download ZIP

compiler/qsc/src/interpret/debug/tests.rs

174lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use indoc::indoc;
5use miette::Result;
6use qsc_data_structures::{language_features::LanguageFeatures, target::TargetCapabilityFlags};
7use qsc_eval::{output::CursorReceiver, val::Value};
8use qsc_frontend::compile::SourceMap;
9use qsc_passes::PackageType;
10use std::io::Cursor;
11
12use crate::interpret::{Error, InterpretResult, Interpreter};
13
14fn line(interpreter: &mut Interpreter, line: impl AsRef<str>) -> (InterpretResult, String) {
15 let mut cursor = Cursor::new(Vec::<u8>::new());
16 let mut receiver = CursorReceiver::new(&mut cursor);
17 (
18 interpreter.eval_fragments(&mut receiver, line.as_ref()),
19 receiver.dump(),
20 )
21}
22
23fn eval(interpreter: &mut Interpreter) -> (Result<Value, Vec<Error>>, String) {
24 let mut cursor = Cursor::new(Vec::<u8>::new());
25 let mut receiver = CursorReceiver::new(&mut cursor);
26 (interpreter.eval_entry(&mut receiver), receiver.dump())
27}
28
29#[test]
30fn stack_traces_can_cross_eval_session_and_file_boundaries() {
31 let source1 = indoc! { r#"
32 namespace Test {
33 operation B(input : Int) : Unit is Adj {
34 body ... {
35 C(input)
36 }
37 adjoint invert;
38 }
39
40 operation C(input : Int) : Unit is Adj {
41 body ... {
42 1 / input;
43 }
44 adjoint self;
45 }
46 }
47 "#};
48 let source2 = indoc! { r#"
49 namespace Test2 {
50 open Test;
51 operation A(input : Int) : Unit is Adj {
52 body ... {
53 B(input)
54 }
55 adjoint invert;
56 }
57 }
58 "#};
59
60 let source_map = SourceMap::new(
61 [
62 ("1.qs".into(), source1.into()),
63 ("2.qs".into(), source2.into()),
64 ],
65 None,
66 );
67
68 let (std_id, store) = crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
69 let mut interpreter = Interpreter::new(
70 source_map,
71 PackageType::Lib,
72 TargetCapabilityFlags::all(),
73 LanguageFeatures::default(),
74 store,
75 &[(std_id, None)],
76 )
77 .expect("Failed to compile base environment.");
78
79 let (result, _) = line(
80 &mut interpreter,
81 "operation Z(input : Int) : Unit { Adjoint Test2.A(input); }",
82 );
83 result.expect("code should compile");
84
85 let (result, _output) = line(&mut interpreter, "Z(0)");
86
87 match result {
88 Ok(_) => panic!("Expected error"),
89 Err(e) => {
90 let stack_trace = e[0]
91 .stack_trace()
92 .expect("code should have a valid stack trace");
93 let expectation = indoc! {r#"
94 Error: division by zero
95 Call stack:
96 at Adjoint Test.C in 1.qs
97 at Adjoint Test.B in 1.qs
98 at Adjoint Test2.A in 2.qs
99 at Z in line_0
100 "#};
101 assert_eq!(expectation, stack_trace);
102 }
103 }
104}
105
106#[test]
107fn stack_traces_can_cross_file_and_entry_boundaries() {
108 let source1 = indoc! { r#"
109 namespace Test {
110 operation B(input : Int) : Unit is Adj {
111 body ... {
112 C(input)
113 }
114 adjoint invert;
115 }
116
117 operation C(input : Int) : Unit is Adj {
118 body ... {
119 1 / input;
120 }
121 adjoint self;
122 }
123 }
124 "#};
125 let source2 = indoc! { r#"
126 namespace Test2 {
127 open Test;
128 operation A(input : Int) : Unit is Adj {
129 body ... {
130 B(input)
131 }
132 adjoint invert;
133 }
134 }
135 "#};
136
137 let source_map = SourceMap::new(
138 [
139 ("1.qs".into(), source1.into()),
140 ("2.qs".into(), source2.into()),
141 ],
142 Some("Adjoint Test2.A(0)".into()),
143 );
144
145 let (std_id, store) = crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
146 let mut interpreter = Interpreter::new(
147 source_map,
148 PackageType::Exe,
149 TargetCapabilityFlags::all(),
150 LanguageFeatures::default(),
151 store,
152 &[(std_id, None)],
153 )
154 .expect("Failed to compile base environment.");
155
156 let (result, _) = eval(&mut interpreter);
157
158 match result {
159 Ok(_) => panic!("Expected error"),
160 Err(e) => {
161 let stack_trace = e[0]
162 .stack_trace()
163 .expect("code should have a valid stack trace");
164 let expectation = indoc! {r#"
165 Error: division by zero
166 Call stack:
167 at Adjoint Test.C in 1.qs
168 at Adjoint Test.B in 1.qs
169 at Adjoint Test2.A in 2.qs
170 "#};
171 assert_eq!(expectation, stack_trace);
172 }
173 }
174}
175