|
45 | 45 | )
|
46 | 46 | """
|
47 | 47 |
|
| 48 | +WORKDIR = 'build' |
| 49 | + |
48 | 50 |
|
49 | 51 | def run_setup(script_name: str, script_args: List[str]) -> bool:
|
50 | 52 | """Run a setup script in a somewhat controlled environment.
|
@@ -102,143 +104,144 @@ class TestRun(MypycDataSuite):
|
102 | 104 | separate = False
|
103 | 105 |
|
104 | 106 | def run_case(self, testcase: DataDrivenTestCase) -> None:
|
105 |
| - bench = testcase.config.getoption('--bench', False) and 'Benchmark' in testcase.name |
106 |
| - |
107 | 107 | # setup.py wants to be run from the root directory of the package, which we accommodate
|
108 | 108 | # by chdiring into tmp/
|
109 | 109 | with use_custom_builtins(os.path.join(self.data_prefix, ICODE_GEN_BUILTINS), testcase), (
|
110 | 110 | chdir_manager('tmp')):
|
111 |
| - text = '\n'.join(testcase.input) |
112 |
| - |
113 |
| - options = Options() |
114 |
| - options.use_builtins_fixtures = True |
115 |
| - options.show_traceback = True |
116 |
| - options.strict_optional = True |
117 |
| - # N.B: We try to (and ought to!) run with the current |
118 |
| - # version of python, since we are going to link and run |
119 |
| - # against the current version of python. |
120 |
| - # But a lot of the tests use type annotations so we can't say it is 3.5. |
121 |
| - options.python_version = max(sys.version_info[:2], (3, 6)) |
122 |
| - options.export_types = True |
123 |
| - options.preserve_asts = True |
124 |
| - |
125 |
| - # Avoid checking modules/packages named 'unchecked', to provide a way |
126 |
| - # to test interacting with code we don't have types for. |
127 |
| - options.per_module_options['unchecked.*'] = {'follow_imports': 'error'} |
128 |
| - |
129 |
| - workdir = 'build' |
130 |
| - os.mkdir(workdir) |
131 |
| - |
132 |
| - source_path = 'native.py' |
133 |
| - with open(source_path, 'w', encoding='utf-8') as f: |
134 |
| - f.write(text) |
135 |
| - with open('interpreted.py', 'w', encoding='utf-8') as f: |
136 |
| - f.write(text) |
137 |
| - |
138 |
| - shutil.copyfile(TESTUTIL_PATH, 'testutil.py') |
139 |
| - |
140 |
| - source = build.BuildSource(source_path, 'native', text) |
141 |
| - sources = [source] |
142 |
| - module_names = ['native'] |
143 |
| - module_paths = [os.path.abspath('native.py')] |
144 |
| - |
145 |
| - # Hard code another module name to compile in the same compilation unit. |
146 |
| - to_delete = [] |
147 |
| - for fn, text in testcase.files: |
148 |
| - fn = os.path.relpath(fn, test_temp_dir) |
149 |
| - |
150 |
| - if os.path.basename(fn).startswith('other'): |
151 |
| - name = os.path.basename(fn).split('.')[0] |
152 |
| - module_names.append(name) |
153 |
| - sources.append(build.BuildSource(fn, name, text)) |
154 |
| - to_delete.append(fn) |
155 |
| - module_paths.append(os.path.abspath(fn)) |
156 |
| - |
157 |
| - shutil.copyfile(fn, |
158 |
| - os.path.join(os.path.dirname(fn), name + '_interpreted.py')) |
159 |
| - |
160 |
| - for source in sources: |
161 |
| - options.per_module_options.setdefault(source.module, {})['mypyc'] = True |
162 |
| - |
163 |
| - groups = construct_groups(sources, self.separate, len(module_names) > 1) |
164 |
| - |
165 |
| - try: |
166 |
| - result = emitmodule.parse_and_typecheck( |
167 |
| - sources=sources, |
168 |
| - options=options, |
169 |
| - alt_lib_path='.') |
170 |
| - errors = Errors() |
171 |
| - compiler_options = CompilerOptions(multi_file=self.multi_file) |
172 |
| - ir, cfiles = emitmodule.compile_modules_to_c( |
173 |
| - result, |
174 |
| - compiler_options=compiler_options, |
175 |
| - errors=errors, |
176 |
| - groups=groups, |
177 |
| - ) |
178 |
| - if errors.num_errors: |
179 |
| - errors.flush_errors() |
180 |
| - assert False, "Compile error" |
181 |
| - except CompileError as e: |
182 |
| - for line in e.messages: |
183 |
| - print(line) |
184 |
| - assert False, 'Compile error' |
185 |
| - |
186 |
| - # Check that serialization works on this IR |
187 |
| - check_serialization_roundtrip(ir) |
188 |
| - |
189 |
| - setup_file = os.path.abspath(os.path.join(workdir, 'setup.py')) |
190 |
| - # We pass the C file information to the build script via setup.py unfortunately |
191 |
| - with open(setup_file, 'w', encoding='utf-8') as f: |
192 |
| - f.write(setup_format.format(module_paths, self.separate, cfiles)) |
193 |
| - |
194 |
| - if not run_setup(setup_file, ['build_ext', '--inplace']): |
195 |
| - if testcase.config.getoption('--mypyc-showc'): |
196 |
| - show_c(cfiles) |
197 |
| - assert False, "Compilation failed" |
198 |
| - |
199 |
| - # Assert that an output file got created |
200 |
| - suffix = 'pyd' if sys.platform == 'win32' else 'so' |
201 |
| - assert glob.glob('native.*.{}'.format(suffix)) |
202 |
| - |
203 |
| - for p in to_delete: |
204 |
| - os.remove(p) |
205 |
| - |
206 |
| - driver_path = 'driver.py' |
207 |
| - env = os.environ.copy() |
208 |
| - env['MYPYC_RUN_BENCH'] = '1' if bench else '0' |
209 |
| - |
210 |
| - # XXX: This is an ugly hack. |
211 |
| - if 'MYPYC_RUN_GDB' in os.environ: |
212 |
| - if platform.system() == 'Darwin': |
213 |
| - subprocess.check_call(['lldb', '--', sys.executable, driver_path], env=env) |
214 |
| - assert False, ("Test can't pass in lldb mode. (And remember to pass -s to " |
215 |
| - "pytest)") |
216 |
| - elif platform.system() == 'Linux': |
217 |
| - subprocess.check_call(['gdb', '--args', sys.executable, driver_path], env=env) |
218 |
| - assert False, ("Test can't pass in gdb mode. (And remember to pass -s to " |
219 |
| - "pytest)") |
220 |
| - else: |
221 |
| - assert False, 'Unsupported OS' |
222 |
| - |
223 |
| - proc = subprocess.Popen([sys.executable, driver_path], stdout=subprocess.PIPE, |
224 |
| - stderr=subprocess.STDOUT, env=env) |
225 |
| - output = proc.communicate()[0].decode('utf8') |
226 |
| - outlines = output.splitlines() |
| 111 | + os.mkdir(WORKDIR) |
| 112 | + self.run_case_inner(testcase) |
| 113 | + |
| 114 | + def run_case_inner(self, testcase: DataDrivenTestCase) -> None: |
| 115 | + bench = testcase.config.getoption('--bench', False) and 'Benchmark' in testcase.name |
| 116 | + |
| 117 | + text = '\n'.join(testcase.input) |
| 118 | + |
| 119 | + options = Options() |
| 120 | + options.use_builtins_fixtures = True |
| 121 | + options.show_traceback = True |
| 122 | + options.strict_optional = True |
| 123 | + # N.B: We try to (and ought to!) run with the current |
| 124 | + # version of python, since we are going to link and run |
| 125 | + # against the current version of python. |
| 126 | + # But a lot of the tests use type annotations so we can't say it is 3.5. |
| 127 | + options.python_version = max(sys.version_info[:2], (3, 6)) |
| 128 | + options.export_types = True |
| 129 | + options.preserve_asts = True |
| 130 | + |
| 131 | + # Avoid checking modules/packages named 'unchecked', to provide a way |
| 132 | + # to test interacting with code we don't have types for. |
| 133 | + options.per_module_options['unchecked.*'] = {'follow_imports': 'error'} |
| 134 | + |
| 135 | + source_path = 'native.py' |
| 136 | + with open(source_path, 'w', encoding='utf-8') as f: |
| 137 | + f.write(text) |
| 138 | + with open('interpreted.py', 'w', encoding='utf-8') as f: |
| 139 | + f.write(text) |
| 140 | + |
| 141 | + shutil.copyfile(TESTUTIL_PATH, 'testutil.py') |
| 142 | + |
| 143 | + source = build.BuildSource(source_path, 'native', text) |
| 144 | + sources = [source] |
| 145 | + module_names = ['native'] |
| 146 | + module_paths = [os.path.abspath('native.py')] |
| 147 | + |
| 148 | + # Hard code another module name to compile in the same compilation unit. |
| 149 | + to_delete = [] |
| 150 | + for fn, text in testcase.files: |
| 151 | + fn = os.path.relpath(fn, test_temp_dir) |
| 152 | + |
| 153 | + if os.path.basename(fn).startswith('other'): |
| 154 | + name = os.path.basename(fn).split('.')[0] |
| 155 | + module_names.append(name) |
| 156 | + sources.append(build.BuildSource(fn, name, text)) |
| 157 | + to_delete.append(fn) |
| 158 | + module_paths.append(os.path.abspath(fn)) |
| 159 | + |
| 160 | + shutil.copyfile(fn, |
| 161 | + os.path.join(os.path.dirname(fn), name + '_interpreted.py')) |
| 162 | + |
| 163 | + for source in sources: |
| 164 | + options.per_module_options.setdefault(source.module, {})['mypyc'] = True |
| 165 | + |
| 166 | + groups = construct_groups(sources, self.separate, len(module_names) > 1) |
227 | 167 |
|
| 168 | + try: |
| 169 | + result = emitmodule.parse_and_typecheck( |
| 170 | + sources=sources, |
| 171 | + options=options, |
| 172 | + alt_lib_path='.') |
| 173 | + errors = Errors() |
| 174 | + compiler_options = CompilerOptions(multi_file=self.multi_file) |
| 175 | + ir, cfiles = emitmodule.compile_modules_to_c( |
| 176 | + result, |
| 177 | + compiler_options=compiler_options, |
| 178 | + errors=errors, |
| 179 | + groups=groups, |
| 180 | + ) |
| 181 | + if errors.num_errors: |
| 182 | + errors.flush_errors() |
| 183 | + assert False, "Compile error" |
| 184 | + except CompileError as e: |
| 185 | + for line in e.messages: |
| 186 | + print(line) |
| 187 | + assert False, 'Compile error' |
| 188 | + |
| 189 | + # Check that serialization works on this IR |
| 190 | + check_serialization_roundtrip(ir) |
| 191 | + |
| 192 | + setup_file = os.path.abspath(os.path.join(WORKDIR, 'setup.py')) |
| 193 | + # We pass the C file information to the build script via setup.py unfortunately |
| 194 | + with open(setup_file, 'w', encoding='utf-8') as f: |
| 195 | + f.write(setup_format.format(module_paths, self.separate, cfiles)) |
| 196 | + |
| 197 | + if not run_setup(setup_file, ['build_ext', '--inplace']): |
228 | 198 | if testcase.config.getoption('--mypyc-showc'):
|
229 | 199 | show_c(cfiles)
|
230 |
| - if proc.returncode != 0: |
231 |
| - print() |
232 |
| - print('*** Exit status: %d' % proc.returncode) |
233 |
| - |
234 |
| - # Verify output. |
235 |
| - if bench: |
236 |
| - print('Test output:') |
237 |
| - print(output) |
| 200 | + assert False, "Compilation failed" |
| 201 | + |
| 202 | + # Assert that an output file got created |
| 203 | + suffix = 'pyd' if sys.platform == 'win32' else 'so' |
| 204 | + assert glob.glob('native.*.{}'.format(suffix)) |
| 205 | + |
| 206 | + for p in to_delete: |
| 207 | + os.remove(p) |
| 208 | + |
| 209 | + driver_path = 'driver.py' |
| 210 | + env = os.environ.copy() |
| 211 | + env['MYPYC_RUN_BENCH'] = '1' if bench else '0' |
| 212 | + |
| 213 | + # XXX: This is an ugly hack. |
| 214 | + if 'MYPYC_RUN_GDB' in os.environ: |
| 215 | + if platform.system() == 'Darwin': |
| 216 | + subprocess.check_call(['lldb', '--', sys.executable, driver_path], env=env) |
| 217 | + assert False, ("Test can't pass in lldb mode. (And remember to pass -s to " |
| 218 | + "pytest)") |
| 219 | + elif platform.system() == 'Linux': |
| 220 | + subprocess.check_call(['gdb', '--args', sys.executable, driver_path], env=env) |
| 221 | + assert False, ("Test can't pass in gdb mode. (And remember to pass -s to " |
| 222 | + "pytest)") |
238 | 223 | else:
|
239 |
| - assert_test_output(testcase, outlines, 'Invalid output') |
240 |
| - |
241 |
| - assert proc.returncode == 0 |
| 224 | + assert False, 'Unsupported OS' |
| 225 | + |
| 226 | + proc = subprocess.Popen([sys.executable, driver_path], stdout=subprocess.PIPE, |
| 227 | + stderr=subprocess.STDOUT, env=env) |
| 228 | + output = proc.communicate()[0].decode('utf8') |
| 229 | + outlines = output.splitlines() |
| 230 | + |
| 231 | + if testcase.config.getoption('--mypyc-showc'): |
| 232 | + show_c(cfiles) |
| 233 | + if proc.returncode != 0: |
| 234 | + print() |
| 235 | + print('*** Exit status: %d' % proc.returncode) |
| 236 | + |
| 237 | + # Verify output. |
| 238 | + if bench: |
| 239 | + print('Test output:') |
| 240 | + print(output) |
| 241 | + else: |
| 242 | + assert_test_output(testcase, outlines, 'Invalid output') |
| 243 | + |
| 244 | + assert proc.returncode == 0 |
242 | 245 |
|
243 | 246 |
|
244 | 247 | # Run the main multi-module tests in multi-file compliation mode
|
|
0 commit comments