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/packages/tests.rs

300lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3use crate::{compile, LanguageFeatures, TargetCapabilityFlags};
4use expect_test::expect;
5use qsc_frontend::compile::{CompileUnit, SourceMap};
6use qsc_passes::PackageType;
7use qsc_project::{PackageInfo, Project, ProjectType};
8use rustc_hash::FxHashMap;
9use std::sync::Arc;
10
11fn mock_program() -> Project {
12 // Mock data for the ProgramConfig
13 let package_graph_sources = qsc_project::PackageGraphSources {
14 root: qsc_project::PackageInfo {
15 sources: vec![(
16 Arc::from("test"),
17 Arc::from("@EntryPoint() operation Main() : Unit {}"),
18 )],
19 language_features: LanguageFeatures::default(),
20 dependencies: FxHashMap::from_iter(vec![(
21 Arc::from("SomeLibraryAlias"),
22 Arc::from("SomeLibraryKey"),
23 )]),
24 package_type: Some(qsc_project::PackageType::Exe),
25 },
26 packages: FxHashMap::from_iter(vec![(
27 Arc::from("SomeLibraryKey"),
28 PackageInfo {
29 sources: vec![(
30 Arc::from("librarymain"),
31 Arc::from("operation LibraryMain() : Unit {} export LibraryMain;"),
32 )],
33 language_features: LanguageFeatures::default(),
34 dependencies: FxHashMap::default(),
35 package_type: Some(qsc_project::PackageType::Lib),
36 },
37 )]),
38 };
39 Project {
40 lints: vec![],
41 errors: vec![],
42 path: "project/qsharp.json".into(),
43 name: "project".into(),
44 project_type: qsc_project::ProjectType::QSharp(package_graph_sources),
45 }
46}
47
48#[test]
49fn test_prepare_package_store() {
50 let program = mock_program();
51 let ProjectType::QSharp(package_graph_sources) = program.project_type else {
52 panic!("project should be a Q# project");
53 };
54 let buildable_program =
55 super::prepare_package_store(TargetCapabilityFlags::default(), package_graph_sources);
56
57 expect![[r"
58 []
59 "]]
60 .assert_debug_eq(&buildable_program.dependency_errors);
61
62 // compile the user code
63 let compiled = compile::compile(
64 &buildable_program.store,
65 &buildable_program.user_code_dependencies[..],
66 SourceMap::new(buildable_program.user_code.sources, None),
67 PackageType::Exe,
68 TargetCapabilityFlags::default(),
69 LanguageFeatures::default(),
70 );
71
72 let CompileUnit {
73 package,
74 ast,
75 errors,
76 ..
77 } = compiled.0;
78
79 expect![[r#"
80 Package:
81 entry expression: Expr 8 [0-0] [Type Unit]: Call:
82 Expr 7 [24-28] [Type Unit]: Var: Item 1
83 Expr 6 [28-30] [Type Unit]: Unit
84 Item 0 [0-40] (Public):
85 Namespace (Ident 5 [0-40] "test"): Item 1
86 Item 1 [0-40] (Internal):
87 Parent: 0
88 EntryPoint
89 Callable 0 [14-40] (operation):
90 name: Ident 1 [24-28] "Main"
91 input: Pat 2 [28-30] [Type Unit]: Unit
92 output: Unit
93 functors: empty set
94 body: SpecDecl 3 [14-40]: Impl:
95 Block 4 [38-40]: <empty>
96 adj: <none>
97 ctl: <none>
98 ctl-adj: <none>"#]]
99 .assert_eq(&package.to_string());
100 expect![[r#"
101 Package 0:
102 Namespace 1 [0-40] (Ident 2 [0-40] "test"):
103 Item 3 [0-40]:
104 Attr 4 [0-13] (Ident 5 [1-11] "EntryPoint"):
105 Expr 6 [11-13]: Unit
106 Callable 7 [14-40] (Operation):
107 name: Ident 8 [24-28] "Main"
108 input: Pat 9 [28-30]: Unit
109 output: Type 10 [33-37]: Path: Path 11 [33-37] (Ident 12 [33-37] "Unit")
110 body: Block: Block 13 [38-40]: <empty>"#]]
111 .assert_eq(&ast.package.to_string());
112 expect![[r"
113 []
114 "]]
115 .assert_debug_eq(&errors);
116}
117
118// if there are inconsequential errors in the dependency compilation process, we don't want to
119// abort compilation. This way, we can still show the user some diagnostics.
120
121#[test]
122fn missing_dependency_doesnt_force_failure() {
123 let program = mock_program();
124 let ProjectType::QSharp(mut package_graph_sources) = program.project_type else {
125 panic!("project should be a Q# project");
126 };
127 package_graph_sources
128 .root
129 .dependencies
130 .insert("NonExistent".into(), "nonexistent-dep-key".into());
131
132 let buildable_program =
133 super::prepare_package_store(TargetCapabilityFlags::default(), package_graph_sources);
134
135 expect![[r"
136 []
137 "]]
138 .assert_debug_eq(&buildable_program.dependency_errors);
139
140 // compile the user code
141 let compiled = compile::compile(
142 &buildable_program.store,
143 &buildable_program.user_code_dependencies[..],
144 SourceMap::new(buildable_program.user_code.sources, None),
145 PackageType::Exe,
146 TargetCapabilityFlags::default(),
147 LanguageFeatures::default(),
148 );
149
150 let CompileUnit {
151 package,
152 ast,
153 errors,
154 ..
155 } = compiled.0;
156
157 expect![[r#"
158 Package:
159 entry expression: Expr 8 [0-0] [Type Unit]: Call:
160 Expr 7 [24-28] [Type Unit]: Var: Item 1
161 Expr 6 [28-30] [Type Unit]: Unit
162 Item 0 [0-40] (Public):
163 Namespace (Ident 5 [0-40] "test"): Item 1
164 Item 1 [0-40] (Internal):
165 Parent: 0
166 EntryPoint
167 Callable 0 [14-40] (operation):
168 name: Ident 1 [24-28] "Main"
169 input: Pat 2 [28-30] [Type Unit]: Unit
170 output: Unit
171 functors: empty set
172 body: SpecDecl 3 [14-40]: Impl:
173 Block 4 [38-40]: <empty>
174 adj: <none>
175 ctl: <none>
176 ctl-adj: <none>"#]]
177 .assert_eq(&package.to_string());
178 expect![[r#"
179 Package 0:
180 Namespace 1 [0-40] (Ident 2 [0-40] "test"):
181 Item 3 [0-40]:
182 Attr 4 [0-13] (Ident 5 [1-11] "EntryPoint"):
183 Expr 6 [11-13]: Unit
184 Callable 7 [14-40] (Operation):
185 name: Ident 8 [24-28] "Main"
186 input: Pat 9 [28-30]: Unit
187 output: Type 10 [33-37]: Path: Path 11 [33-37] (Ident 12 [33-37] "Unit")
188 body: Block: Block 13 [38-40]: <empty>"#]]
189 .assert_eq(&ast.package.to_string());
190 expect![[r"
191 []
192 "]]
193 .assert_debug_eq(&errors);
194}
195
196#[allow(clippy::too_many_lines)]
197#[test]
198fn dependency_error() {
199 let program = mock_program();
200 // Inject a syntax error into one of the dependencies
201 let ProjectType::QSharp(mut package_graph_sources) = program.project_type else {
202 panic!("project should be a Q# project");
203 };
204 package_graph_sources
205 .packages
206 .values_mut()
207 .next()
208 .expect("expected at least one dependency in the mock program")
209 .sources[0]
210 .1 = "broken_syntax".into();
211
212 let buildable_program =
213 super::prepare_package_store(TargetCapabilityFlags::default(), package_graph_sources);
214
215 expect![[r#"
216 [
217 WithSource {
218 sources: [
219 Source {
220 name: "librarymain",
221 contents: "broken_syntax",
222 offset: 0,
223 },
224 ],
225 error: Frontend(
226 Error(
227 Parse(
228 Error(
229 Token(
230 Eof,
231 Ident,
232 Span {
233 lo: 0,
234 hi: 13,
235 },
236 ),
237 ),
238 ),
239 ),
240 ),
241 },
242 ]
243 "#]]
244 .assert_debug_eq(&buildable_program.dependency_errors);
245
246 // compile the user code
247 let compiled = compile::compile(
248 &buildable_program.store,
249 &buildable_program.user_code_dependencies[..],
250 SourceMap::new(buildable_program.user_code.sources, None),
251 PackageType::Exe,
252 TargetCapabilityFlags::default(),
253 LanguageFeatures::default(),
254 );
255
256 let CompileUnit {
257 package,
258 ast,
259 errors,
260 ..
261 } = compiled.0;
262
263 expect![[r#"
264 Package:
265 entry expression: Expr 8 [0-0] [Type Unit]: Call:
266 Expr 7 [24-28] [Type Unit]: Var: Item 1
267 Expr 6 [28-30] [Type Unit]: Unit
268 Item 0 [0-40] (Public):
269 Namespace (Ident 5 [0-40] "test"): Item 1
270 Item 1 [0-40] (Internal):
271 Parent: 0
272 EntryPoint
273 Callable 0 [14-40] (operation):
274 name: Ident 1 [24-28] "Main"
275 input: Pat 2 [28-30] [Type Unit]: Unit
276 output: Unit
277 functors: empty set
278 body: SpecDecl 3 [14-40]: Impl:
279 Block 4 [38-40]: <empty>
280 adj: <none>
281 ctl: <none>
282 ctl-adj: <none>"#]]
283 .assert_eq(&package.to_string());
284 expect![[r#"
285 Package 0:
286 Namespace 1 [0-40] (Ident 2 [0-40] "test"):
287 Item 3 [0-40]:
288 Attr 4 [0-13] (Ident 5 [1-11] "EntryPoint"):
289 Expr 6 [11-13]: Unit
290 Callable 7 [14-40] (Operation):
291 name: Ident 8 [24-28] "Main"
292 input: Pat 9 [28-30]: Unit
293 output: Type 10 [33-37]: Path: Path 11 [33-37] (Ident 12 [33-37] "Unit")
294 body: Block: Block 13 [38-40]: <empty>"#]]
295 .assert_eq(&ast.package.to_string());
296 expect![[r"
297 []
298 "]]
299 .assert_debug_eq(&errors);
300}
301