microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.19.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

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

175lines · modecode

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