microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
e874bfb8e1dbfc3eec7aebe87f45fc0cb4c547b6

Branches

Tags

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

Clone

HTTPS

Download ZIP

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

172lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4#![allow(clippy::needless_raw_string_hashes)]
5
6use indoc::indoc;
7use miette::Result;
8use qsc_data_structures::language_features::LanguageFeatures;
9use qsc_eval::{output::CursorReceiver, val::Value};
10use qsc_frontend::compile::{SourceMap, TargetCapabilityFlags};
11use qsc_passes::PackageType;
12use std::io::Cursor;
13
14use crate::interpret::{Error, InterpretResult, Interpreter};
15
16fn line(interpreter: &mut Interpreter, line: impl AsRef<str>) -> (InterpretResult, String) {
17 let mut cursor = Cursor::new(Vec::<u8>::new());
18 let mut receiver = CursorReceiver::new(&mut cursor);
19 (
20 interpreter.eval_fragments(&mut receiver, line.as_ref()),
21 receiver.dump(),
22 )
23}
24
25fn eval(interpreter: &mut Interpreter) -> (Result<Value, Vec<Error>>, String) {
26 let mut cursor = Cursor::new(Vec::<u8>::new());
27 let mut receiver = CursorReceiver::new(&mut cursor);
28 (interpreter.eval_entry(&mut receiver), receiver.dump())
29}
30
31#[test]
32fn stack_traces_can_cross_eval_session_and_file_boundaries() {
33 let source1 = indoc! { r#"
34 namespace Test {
35 operation B(input : Int) : Unit is Adj {
36 body ... {
37 C(input)
38 }
39 adjoint invert;
40 }
41
42 operation C(input : Int) : Unit is Adj {
43 body ... {
44 1 / input;
45 }
46 adjoint self;
47 }
48 }
49 "#};
50 let source2 = indoc! { r#"
51 namespace Test2 {
52 open Test;
53 operation A(input : Int) : Unit is Adj {
54 body ... {
55 B(input)
56 }
57 adjoint invert;
58 }
59 }
60 "#};
61
62 let source_map = SourceMap::new(
63 [
64 ("1.qs".into(), source1.into()),
65 ("2.qs".into(), source2.into()),
66 ],
67 None,
68 );
69 let mut interpreter = Interpreter::new(
70 true,
71 source_map,
72 PackageType::Lib,
73 TargetCapabilityFlags::all(),
74 LanguageFeatures::default(),
75 )
76 .expect("Failed to compile base environment.");
77
78 let (result, _) = line(
79 &mut interpreter,
80 "operation Z(input : Int) : Unit { Adjoint Test2.A(input); }",
81 );
82 result.expect("code should compile");
83
84 let (result, _output) = line(&mut interpreter, "Z(0)");
85
86 match result {
87 Ok(_) => panic!("Expected error"),
88 Err(e) => {
89 let stack_trace = e[0]
90 .stack_trace()
91 .as_ref()
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 let mut interpreter = Interpreter::new(
145 true,
146 source_map,
147 PackageType::Exe,
148 TargetCapabilityFlags::all(),
149 LanguageFeatures::default(),
150 )
151 .expect("Failed to compile base environment.");
152
153 let (result, _) = eval(&mut interpreter);
154
155 match result {
156 Ok(_) => panic!("Expected error"),
157 Err(e) => {
158 let stack_trace = e[0]
159 .stack_trace()
160 .as_ref()
161 .expect("code should have a valid stack trace");
162 let expectation = indoc! {r#"
163 Error: division by zero
164 Call stack:
165 at Adjoint Test.C in 1.qs
166 at Adjoint Test.B in 1.qs
167 at Adjoint Test2.A in 2.qs
168 "#};
169 assert_eq!(expectation, stack_trace);
170 }
171 }
172}
173