|
13 | 13 | # limitations under the License.
|
14 | 14 |
|
15 | 15 | import tempfile
|
| 16 | +import threading |
16 | 17 | import os
|
17 | 18 | import pytest
|
18 | 19 | from typed_python.test_util import evaluateExprInFreshProcess
|
@@ -261,6 +262,72 @@ def test_reference_existing_function_twice():
|
261 | 262 | assert len(os.listdir(compilerCacheDir)) == 2
|
262 | 263 |
|
263 | 264 |
|
| 265 | +@pytest.mark.skipif('sys.platform=="darwin"') |
| 266 | +def test_can_compile_overlapping_code(): |
| 267 | + common = "\n".join([ |
| 268 | + "import time", |
| 269 | + "import os", |
| 270 | + |
| 271 | + "t0 = time.time()", |
| 272 | + "path = os.path.join(os.getenv('TP_COMPILER_CACHE'), 'check.txt')", |
| 273 | + "while not os.path.exists(path):", |
| 274 | + " time.sleep(.01)", |
| 275 | + " assert time.time() - t0 < 2", |
| 276 | + ]) |
| 277 | + |
| 278 | + xmodule1 = "\n".join([ |
| 279 | + "import common", |
| 280 | + "@Entrypoint", |
| 281 | + "def f():", |
| 282 | + " x = Dict(int, int)()", |
| 283 | + " x[3] = 4", |
| 284 | + " return x[3]" |
| 285 | + ]) |
| 286 | + |
| 287 | + xmodule2 = "\n".join([ |
| 288 | + "import common", |
| 289 | + "@Entrypoint", |
| 290 | + "def g():", |
| 291 | + " x = Dict(int, int)()", |
| 292 | + " x[3] = 5", |
| 293 | + " return x[3]" |
| 294 | + ]) |
| 295 | + |
| 296 | + xmodule3 = "\n".join([ |
| 297 | + "from x1 import f", |
| 298 | + "from x2 import g", |
| 299 | + "@Entrypoint", |
| 300 | + "def h():", |
| 301 | + " return f() + g()" |
| 302 | + ]) |
| 303 | + |
| 304 | + MODULES = {'common.py': common, 'x1.py': xmodule1, 'x2.py': xmodule2, 'x3.py': xmodule3} |
| 305 | + |
| 306 | + with tempfile.TemporaryDirectory() as compilerCacheDir: |
| 307 | + # first, compile 'f' and 'g' in two separate processes. Because of the loop |
| 308 | + # they will wait until we write out the file that lets them start compiling. Then |
| 309 | + # the'll both compile something that has common code. |
| 310 | + # we should be able to then use that common code without issue. |
| 311 | + threads = [ |
| 312 | + threading.Thread( |
| 313 | + target=evaluateExprInFreshProcess, args=(MODULES, 'x1.f()', compilerCacheDir) |
| 314 | + ), |
| 315 | + threading.Thread( |
| 316 | + target=evaluateExprInFreshProcess, args=(MODULES, 'x2.g()', compilerCacheDir) |
| 317 | + ), |
| 318 | + ] |
| 319 | + for t in threads: |
| 320 | + t.start() |
| 321 | + |
| 322 | + with open(os.path.join(compilerCacheDir, "check.txt"), 'w') as f: |
| 323 | + f.write('start!') |
| 324 | + |
| 325 | + for t in threads: |
| 326 | + t.join() |
| 327 | + |
| 328 | + assert evaluateExprInFreshProcess(MODULES, 'x3.h()', compilerCacheDir) == 9 |
| 329 | + |
| 330 | + |
264 | 331 | @pytest.mark.skipif('sys.platform=="darwin"')
|
265 | 332 | def test_compiler_cache_handles_class_destructors_correctly():
|
266 | 333 | xmodule = "\n".join([
|
|
0 commit comments