microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
f8fa2d604d87c013ff3dbce15ad74191da4e6760

Branches

Tags

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

Clone

HTTPS

Download ZIP

source/pip/tests/test_project.py

272lines · modecode

1# Copyright (c) Microsoft Corporation.
2# Licensed under the MIT License.
3
4import pytest
5import os
6
7
8@pytest.fixture
9def qsharp():
10 import qsharp
11 import qsharp._fs
12 import qsharp._http
13
14 qsharp._fs.read_file = read_file_memfs
15 qsharp._fs.list_directory = list_directory_memfs
16 qsharp._fs.exists = exists_memfs
17 qsharp._fs.join = join_memfs
18 qsharp._fs.resolve = resolve_memfs
19 qsharp._http.fetch_github = fetch_github_test
20
21 return qsharp
22
23
24def test_project(qsharp) -> None:
25 qsharp.init(project_root="/good")
26 result = qsharp.eval("Test.ReturnsFour()")
27 assert result == 4
28
29
30def test_project_compile_error(qsharp) -> None:
31 with pytest.raises(Exception) as excinfo:
32 qsharp.init(project_root="/compile_error")
33 assert str(excinfo.value).startswith("Qsc.TypeCk.TyMismatch")
34
35
36def test_project_bad_qsharp_json(qsharp) -> None:
37 with pytest.raises(Exception) as excinfo:
38 qsharp.init(project_root="/bad_qsharp_json")
39 assert str(excinfo.value).find("Failed to parse manifest") != -1
40
41
42def test_project_unreadable_qsharp_json(qsharp) -> None:
43 with pytest.raises(Exception) as excinfo:
44 qsharp.init(project_root="/unreadable_qsharp_json")
45 assert str(excinfo.value).startswith(
46 "Error reading /unreadable_qsharp_json/qsharp.json."
47 )
48
49
50def test_project_unreadable_source(qsharp) -> None:
51 with pytest.raises(Exception) as excinfo:
52 qsharp.init(project_root="/unreadable_source")
53 # If this seems like a silly substring to assert on, it's
54 # because the error reporting code is inserting a line break
55 # between "could not" and "read test.qs"
56 assert str(excinfo.value).find("OSError: could not") != -1
57
58
59def test_project_dependencies(qsharp) -> None:
60 qsharp.init(project_root="/with_deps")
61 result = qsharp.eval("Test.CallsDependency()")
62 assert result == 4
63
64
65def test_project_circular_dependency_error(qsharp) -> None:
66 with pytest.raises(Exception) as excinfo:
67 qsharp.init(project_root="/circular")
68 assert str(excinfo.value).find("Circular dependency detected between") != -1
69
70
71def test_github_dependency(qsharp) -> None:
72 qsharp.init(project_root="/with_github_dep")
73 result = qsharp.eval("Test.CallsDependency()")
74 assert result == 12
75
76
77def test_circuit(qsharp) -> None:
78 qsharp.init(project_root="/circuit")
79 result = qsharp.eval("Test.TestCircuit()")
80 assert result == qsharp.Result.Zero
81
82
83def test_src_package_udt(qsharp) -> None:
84 qsharp.init(project_root="/src_package_udt")
85 arg = qsharp.code.Test.Data(42)
86 result = qsharp.run(qsharp.code.Test.Op, 1, arg)
87 assert result == [42]
88
89
90with open(
91 os.path.join(os.path.dirname(__file__), "circuit.qsc"), "r", encoding="utf-8"
92) as f:
93 circuit_qsc_contents = f.read()
94
95memfs = {
96 "": {
97 "good": {
98 "src": {
99 "test.qs": "namespace Test { operation ReturnsFour() : Int { 4 } export ReturnsFour; }",
100 },
101 "qsharp.json": "{}",
102 },
103 "src_package_udt": {
104 "src": {
105 "test.qs": "namespace Test { struct Data { value : Int } operation Op(data : Data) : Int { data.value } }"
106 },
107 "qsharp.json": "{}",
108 },
109 "bad_qsharp_json": {"qsharp.json": "BAD_JSON_CONTENTS"},
110 "unreadable_qsharp_json": {
111 "qsharp.json": OSError("could not read qsharp.json")
112 },
113 "unreadable_source": {
114 "src": {
115 "test.qs": OSError("could not read test.qs"),
116 },
117 "qsharp.json": "{}",
118 },
119 "compile_error": {
120 "src": {
121 "test.qs": "namespace Test { operation ReturnsFour() : Int { 4.0 } }",
122 },
123 "qsharp.json": "{}",
124 },
125 "with_deps": {
126 "src": {
127 "test.qs": "namespace Test { operation CallsDependency() : Int { return Foo.Test.ReturnsFour(); } }",
128 },
129 "qsharp.json": """
130 {
131 "dependencies": {
132 "Foo": {
133 "path": "../good"
134 }
135 }
136 }""",
137 },
138 "circular": {
139 "src": {
140 "test.qs": "namespace Test {}",
141 },
142 "qsharp.json": """
143 {
144 "dependencies": {
145 "Foo": {
146 "path": "../circular"
147 }
148 }
149 }""",
150 },
151 "with_github_dep": {
152 "src": {
153 "test.qs": "namespace Test { operation CallsDependency() : Int { return Foo.Test.ReturnsTwelve(); } }",
154 },
155 "qsharp.json": """
156 {
157 "dependencies": {
158 "Foo": {
159 "github" : {
160 "owner" : "test-owner",
161 "repo" : "test-repo",
162 "ref" : "12345"
163 }
164 }
165 }
166 }""",
167 },
168 "circuit": {
169 "src": {
170 "test.qs": "namespace Test {"
171 " import circuit.circuit;"
172 " operation TestCircuit() : Result {"
173 " use qs = Qubit[2];"
174 " let result = circuit(qs);"
175 " ResetAll(qs);"
176 " result"
177 " }"
178 "}",
179 "circuit.qsc": circuit_qsc_contents,
180 },
181 "qsharp.json": "{}",
182 },
183 }
184}
185
186
187def fetch_github_test(owner: str, repo: str, ref: str, path: str):
188 if (
189 owner == "test-owner"
190 and repo == "test-repo"
191 and ref == "12345"
192 and path == "/qsharp.json"
193 ):
194 return """{ "files" : ["src/test.qs"] }"""
195 if (
196 owner == "test-owner"
197 and repo == "test-repo"
198 and ref == "12345"
199 and path == "/src/test.qs"
200 ):
201 return "namespace Test { operation ReturnsTwelve() : Int { 12 } export ReturnsTwelve;}"
202 raise Exception(f"Unexpected fetch_github call: {owner}, {repo}, {ref}, {path}")
203
204
205def read_file_memfs(path):
206 global memfs
207 item = memfs
208 for part in path.split("/"):
209 if part in item:
210 if isinstance(item[part], OSError):
211 raise item[part]
212 else:
213 item = item[part]
214 else:
215 raise Exception("File not found: " + path)
216
217 return (path, item)
218
219
220def list_directory_memfs(dir_path):
221 global memfs
222 item = memfs
223 for part in dir_path.split("/"):
224 if part in item:
225 item = item[part]
226 else:
227 raise Exception("Directory not found: " + dir_path)
228
229 contents = list(
230 map(
231 lambda x: {
232 "path": join_memfs(dir_path, x[0]),
233 "entry_name": x[0],
234 "type": "folder" if isinstance(x[1], dict) else "file",
235 },
236 item.items(),
237 )
238 )
239
240 return contents
241
242
243def exists_memfs(path):
244 global memfs
245 parts = path.split("/")
246 item = memfs
247 for part in parts:
248 if part in item:
249 item = item[part]
250 else:
251 return False
252
253 return True
254
255
256# The below functions force the use of `/` separators in the unit tests
257# so that they function on Windows consistently with other platforms.
258def join_memfs(path, *paths):
259 return "/".join([path, *paths])
260
261
262def resolve_memfs(base, path):
263 parts = f"{base}/{path}".split("/")
264 new_parts = []
265 for part in parts:
266 if part == ".":
267 continue
268 if part == "..":
269 new_parts.pop()
270 continue
271 new_parts.append(part)
272 return "/".join(new_parts)