microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
alex/pythontelem

Branches

Tags

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

Clone

HTTPS

Download ZIP

compiler/qsc_frontend/src/compile/tests/multiple_packages.rs

511lines · modecode

1use std::sync::Arc;
2
3use super::{compile, PackageStore, SourceMap};
4use crate::compile::TargetCapabilityFlags;
5
6use crate::compile::core;
7use expect_test::expect;
8use expect_test::Expect;
9use indoc::indoc;
10use qsc_data_structures::language_features::LanguageFeatures;
11use qsc_hir::hir::PackageId;
12
13/// Runs a test where each successive package relies solely on the package before it
14/// useful for testing chains of reexports
15fn multiple_package_check(packages: Vec<(&str, &str)>) {
16 multiple_package_check_inner(packages, None);
17}
18
19fn multiple_package_check_expect_err(packages: Vec<(&str, &str)>, expect: &Expect) {
20 multiple_package_check_inner(packages, Some(expect));
21}
22
23fn multiple_package_check_inner(packages: Vec<(&str, &str)>, expect: Option<&Expect>) {
24 let mut store = PackageStore::new(core());
25 let mut prev_id_and_name: Option<(PackageId, &str)> = None;
26 let num_packages = packages.len();
27 for (ix, (package_name, package_source)) in packages.into_iter().enumerate() {
28 let is_last = ix == num_packages - 1;
29 let deps = if let Some((prev_id, prev_name)) = prev_id_and_name {
30 vec![(prev_id, Some(Arc::from(prev_name)))]
31 } else {
32 vec![]
33 };
34
35 let sources = SourceMap::new(
36 [(
37 Arc::from(format!("{package_name}.qs")),
38 Arc::from(package_source),
39 )],
40 None,
41 );
42
43 let unit = compile(
44 &store,
45 &deps[..],
46 sources,
47 TargetCapabilityFlags::all(),
48 LanguageFeatures::default(),
49 );
50
51 match (is_last, &expect) {
52 (true, Some(expect)) => {
53 expect.assert_eq(&format!("{:#?}", unit.errors));
54 }
55 _ => {
56 assert!(unit.errors.is_empty(), "{:#?}", unit.errors);
57 }
58 }
59
60 prev_id_and_name = Some((store.insert(unit), package_name));
61 }
62}
63
64#[test]
65fn namespace_named_main_doesnt_create_main_namespace() {
66 multiple_package_check_expect_err(
67 vec![
68 (
69 "Main",
70 "operation Foo(x: Int, y: Bool) : Int {
71 x
72 }
73 export Foo;",
74 ),
75 (
76 "C",
77 r#"
78 // this fails because `Main` is considered the "root"
79 import Main.Main.Foo;
80 @EntryPoint()
81 operation Main() : Unit {
82 Foo(10, true);
83 }"#,
84 ),
85 ],
86 &expect!([r#"
87 [
88 Error(
89 Resolve(
90 NotFound(
91 "Main.Main.Foo",
92 Span {
93 lo: 86,
94 hi: 99,
95 },
96 ),
97 ),
98 ),
99 Error(
100 Resolve(
101 NotFound(
102 "Foo",
103 Span {
104 lo: 205,
105 hi: 208,
106 },
107 ),
108 ),
109 ),
110 Error(
111 Type(
112 Error(
113 AmbiguousTy(
114 Span {
115 lo: 205,
116 hi: 218,
117 },
118 ),
119 ),
120 ),
121 ),
122 ]"#]),
123 );
124}
125
126#[test]
127fn namespaces_named_main_treated_as_root() {
128 multiple_package_check(vec![
129 (
130 "Main",
131 "operation Foo(x: Int, y: Bool) : Int {
132 x
133 }
134 export Foo;",
135 ),
136 (
137 "C",
138 "
139 // note that this is not Main.Main
140 // and that the namespace `Main` is omitted here
141 import Main.Foo;
142 @EntryPoint()
143 operation Main() : Unit {
144 Foo(10, true);
145 }",
146 ),
147 ]);
148}
149
150#[test]
151fn multiple_packages_reference_exports() {
152 multiple_package_check(vec![
153 (
154 "PackageA",
155 indoc! {"
156 operation Foo(x: Int, y: Bool) : Int {
157 x
158 }
159 export Foo;
160 "},
161 ),
162 (
163 "PackageB",
164 indoc! {"
165 import PackageA.PackageA.Foo;
166 export Foo;
167 "},
168 ),
169 (
170 "PackageC",
171 indoc! {"
172 import PackageB.PackageB.Foo;
173 @EntryPoint()
174 operation Main() : Unit {
175 Foo(10, true);
176 }
177 "},
178 ),
179 ]);
180}
181
182#[test]
183#[allow(clippy::too_many_lines)]
184fn multiple_packages_disallow_unexported_imports() {
185 multiple_package_check_expect_err(
186 vec![
187 (
188 "PackageA",
189 indoc! {"
190 function FunctionA() : Int {
191 1
192 }
193 "},
194 ),
195 (
196 "PackageB",
197 indoc! {"
198 import PackageA.PackageA.FunctionA;
199 @EntryPoint()
200 function Main() : Unit {
201 FunctionA();
202 }
203 "},
204 ),
205 ],
206 &expect![[r#"
207 [
208 Error(
209 Resolve(
210 NotFound(
211 "PackageA.PackageA.FunctionA",
212 Span {
213 lo: 7,
214 hi: 34,
215 },
216 ),
217 ),
218 ),
219 Error(
220 Resolve(
221 NotFound(
222 "FunctionA",
223 Span {
224 lo: 78,
225 hi: 87,
226 },
227 ),
228 ),
229 ),
230 Error(
231 Type(
232 Error(
233 AmbiguousTy(
234 Span {
235 lo: 78,
236 hi: 89,
237 },
238 ),
239 ),
240 ),
241 ),
242 ]"#]],
243 );
244}
245
246#[test]
247fn reexport() {
248 multiple_package_check(vec![
249 (
250 "PackageA",
251 indoc! {"
252 export Std.Core.Length as Foo;
253 "},
254 ),
255 (
256 "PackageB",
257 indoc! {"
258
259 import PackageA.PackageA.Foo;
260 @EntryPoint()
261 function Main() : Unit {
262 use qs = Qubit[2];
263 let len = Foo(qs);
264 }
265 "},
266 ),
267 ]);
268}
269
270#[test]
271fn reexport_export_has_alias() {
272 multiple_package_check(vec![
273 (
274 "PackageA",
275 indoc! {"
276 operation Foo(x: Int, y: Bool) : Int {
277 x
278 }
279 export Foo as Bar;
280 "},
281 ),
282 (
283 "PackageB",
284 indoc! {"
285 import PackageA.PackageA.Bar;
286 "},
287 ),
288 ]);
289}
290
291#[test]
292fn reexport_import_has_alias() {
293 multiple_package_check(vec![
294 (
295 "PackageA",
296 "operation Foo(x: Int, y: Bool) : Int {
297 x
298 }
299 export Foo;
300 ",
301 ),
302 (
303 "PackageB",
304 "
305 import PackageA.PackageA.Foo as Bar;
306
307 export Bar;
308 ",
309 ),
310 ]);
311}
312
313#[test]
314fn reexport_reexport_has_alias() {
315 multiple_package_check(vec![
316 (
317 "PackageA",
318 "
319 operation Foo(x: Int, y: Bool) : Int {
320 x
321 }
322 export Foo;
323 ",
324 ),
325 (
326 "PackageB",
327 "
328 import PackageA.PackageA.Foo;
329 export Foo as Bar;
330 ",
331 ),
332 (
333 "PackageC",
334 "
335 import PackageB.PackageB.Bar;
336 @EntryPoint()
337 operation Main() : Unit {
338 Bar(10, true);
339 }
340 ",
341 ),
342 ]);
343}
344
345#[test]
346fn reexport_callable_combined_aliases() {
347 multiple_package_check(vec![
348 (
349 "PackageA",
350 "
351 operation Foo(x: Int, y: Bool) : Int {
352 x
353 }
354 export Foo;
355 ",
356 ),
357 (
358 "PackageB",
359 "
360 import PackageA.PackageA.Foo;
361 import PackageA.PackageA.Foo as Foo2;
362 export Foo, Foo as Bar, Foo2, Foo2 as Bar2;
363 ",
364 ),
365 (
366 "PackageC",
367 "
368 import PackageB.PackageB.Foo, PackageB.PackageB.Bar, PackageB.PackageB.Foo2, PackageB.PackageB.Bar2;
369 @EntryPoint()
370 operation Main() : Unit {
371 Foo(10, true);
372 Foo2(10, true);
373 Bar(10, true);
374 Bar2(10, true);
375 }
376 ",
377 ),
378 ]);
379}
380
381#[test]
382fn direct_reexport() {
383 multiple_package_check(vec![
384 (
385 "A",
386 "operation Foo(x: Int, y: Bool) : Int {
387 x
388 }
389 export Foo as Bar;",
390 ),
391 ("B", "export A.A.Bar as Baz;"),
392 (
393 "C",
394 "import B.B.Baz as Quux;
395 @EntryPoint()
396 operation Main() : Unit {
397 Quux(10, true);
398 }",
399 ),
400 ]);
401}
402
403#[test]
404fn reexports_still_type_check() {
405 multiple_package_check_expect_err(
406 vec![
407 (
408 "A",
409 "operation Foo(x: Int, y: Bool) : Int {
410 x
411 }
412 export Foo as Bar;",
413 ),
414 (
415 "B",
416 "
417 export A.A.Bar as Baz;",
418 ),
419 (
420 "C",
421 "import B.B.Baz as Quux;
422 @EntryPoint()
423 operation Main() : Unit {
424 Quux(10, 10);
425 }",
426 ),
427 ],
428 &expect![[r#"
429 [
430 Error(
431 Type(
432 Error(
433 TyMismatch(
434 "Bool",
435 "Int",
436 Span {
437 lo: 128,
438 hi: 140,
439 },
440 ),
441 ),
442 ),
443 ),
444 ]"#]],
445 );
446}
447
448#[test]
449fn namespaces_named_lowercase_main_not_treated_as_root() {
450 multiple_package_check(vec![
451 (
452 "main",
453 "operation Foo(x: Int, y: Bool) : Int {
454 x
455 }
456 export Foo;",
457 ),
458 (
459 "C",
460 "
461 import main.main.Foo;
462 @EntryPoint()
463 operation Main() : Unit {
464 Foo(10, true);
465 }",
466 ),
467 ]);
468}
469
470#[test]
471fn aliased_export_via_aliased_import() {
472 multiple_package_check(vec![
473 (
474 "MyGithubLibrary",
475 r#"
476 namespace TestPackage {
477
478 import Subpackage.Subpackage.Hello as SubHello;
479
480 export HelloFromGithub;
481 export SubHello;
482
483 /// This is a Doc String!
484 function HelloFromGithub() : Unit {
485 SubHello();
486 }
487 }
488
489 namespace Subpackage.Subpackage {
490 function Hello() : Unit {}
491 export Hello;
492 }
493
494 "#,
495 ),
496 (
497 "UserCode",
498 r#"
499 import MyGithubLibrary.TestPackage.SubHello;
500 import MyGithubLibrary.TestPackage.HelloFromGithub;
501 import MyGithubLibrary.Subpackage.Subpackage as P;
502
503 function Main() : Unit {
504 HelloFromGithub();
505 SubHello();
506 P.Hello();
507 }
508 "#,
509 ),
510 ]);
511}
512