Skip to content

Commit 8862138

Browse files
alexmalyshevmeta-codesync[bot]
authored andcommitted
More fixes to tests running with pytest
Summary: First set of fixes came from macOS, this set is from Linux. Reviewed By: czardoz Differential Revision: D93486760 fbshipit-source-id: d18b61255fb83f92b757ec05a0f8e28a41ffa33a
1 parent def5daf commit 8862138

11 files changed

Lines changed: 84 additions & 43 deletions

cinderx/PythonLib/cinderx/test_support.py

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ def wrapper(*args: ...) -> None:
206206
f"JIT compilation of {func.__qualname__} failed with {exc}"
207207
)
208208

209+
wrapper.inner_function = func
210+
209211
return wrapper
210212

211213
return func
@@ -235,6 +237,15 @@ def wrapper(*args: ..., **kwargs: ...) -> TRet:
235237
return wrapper
236238

237239

240+
def is_oss() -> bool:
241+
"""
242+
Check if this is running in an open source environment.
243+
244+
Currently implemented as looking for the absence of the Meta Python runtime.
245+
"""
246+
return "+meta" not in sys.version and "+cinder" not in sys.version
247+
248+
238249
def skip_module_if_oss() -> None:
239250
"""
240251
Skip a test module on OSS builds, i.e. ones that aren't built with Buck internally at Meta.
@@ -246,10 +257,8 @@ def skip_module_if_oss() -> None:
246257
(e.g. Meta Python's Lazy Imports).
247258
"""
248259

249-
if "+meta" in sys.version or "+cinder" in sys.version:
250-
return
251-
252-
raise unittest.SkipTest("Module not compatible with OSS imports")
260+
if is_oss():
261+
raise unittest.SkipTest("Module not compatible with OSS imports")
253262

254263

255264
def has_meta_lazy_imports() -> bool:
@@ -260,6 +269,16 @@ def has_meta_lazy_imports() -> bool:
260269
return hasattr(importlib, "set_lazy_imports")
261270

262271

272+
def undo_fail_decorators(func: Callable[..., object]) -> Callable[..., object]:
273+
"""
274+
Unravel "fail" decorators defined in this module off of a function.
275+
"""
276+
277+
while inner_func := getattr(func, "inner_function", None):
278+
func = inner_func
279+
return func
280+
281+
263282
def is_asan_build() -> bool:
264283
try:
265284
ctypes.pythonapi.__asan_init
@@ -337,13 +356,8 @@ def assertBytecodeContains(
337356
expected_opcode: str,
338357
expected_oparg: int | None = None,
339358
) -> None:
340-
try:
341-
# pyre-ignore[16] - for things wrapped by fail_if_deopt()
342-
inner_function = func.inner_function
343-
except AttributeError:
344-
pass
345-
else:
346-
func = inner_function
359+
# pyre-ignore[6]: func isn't properly typed as a callable yet.
360+
func = undo_fail_decorators(func)
347361

348362
bytecode_instructions = dis.get_instructions(func)
349363

cinderx/PythonLib/test_cinderx/test_coro_extensions.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
23
import sys
34
import types
45
import unittest
56

6-
from cinderx import test_support as cinder_support
7-
from cinderx.test_support import passIf, skip_if_jit
7+
from cinderx.test_support import hasCinderX, passIf, skip_if_jit, skip_module_if_oss
8+
9+
skip_module_if_oss()
810

911
# pyre-ignore[21]: can't find test.support
1012
from test.support import import_helper, maybe_get_event_loop_policy
1113

1214

13-
if cinder_support.hasCinderX():
15+
if hasCinderX():
1416
import cinder
1517

1618

cinderx/PythonLib/test_cinderx/test_frame_evaluator.py

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,13 @@
1111

1212

1313
CINDERX_INITIALIZED: bool = cinderx.is_initialized()
14-
ALREADY_INSTALLED: bool = cinderx.is_frame_evaluator_installed()
15-
JIT_ENABLED: bool = cinderx.jit.is_enabled()
1614
ARM: bool = "aarch64" in platform.machine() or "arm64" in platform.machine()
1715

1816

1917
@passUnless(CINDERX_INITIALIZED, "Need CinderX initialized to test frame evaluator")
20-
@passIf(ALREADY_INSTALLED, "Can only test frame evaluator with a clean slate")
2118
class FrameEvaluatorTest(unittest.TestCase):
2219
def test_install_then_remove(self) -> None:
23-
self.assertFalse(cinderx.is_frame_evaluator_installed())
20+
self.skip_if_already_installed()
2421

2522
cinderx.install_frame_evaluator()
2623
self.assertTrue(cinderx.is_frame_evaluator_installed())
@@ -29,7 +26,7 @@ def test_install_then_remove(self) -> None:
2926
self.assertFalse(cinderx.is_frame_evaluator_installed())
3027

3128
def test_idempotent(self) -> None:
32-
self.assertFalse(cinderx.is_frame_evaluator_installed())
29+
self.skip_if_already_installed()
3330

3431
cinderx.install_frame_evaluator()
3532
self.assertTrue(cinderx.is_frame_evaluator_installed())
@@ -43,39 +40,34 @@ def test_idempotent(self) -> None:
4340
cinderx.remove_frame_evaluator()
4441
self.assertFalse(cinderx.is_frame_evaluator_installed())
4542

46-
@passIf(JIT_ENABLED, "Need to check JIT with a clean slate")
4743
@passIf(ARM, "JIT doesn't work on ARM yet")
4844
def test_jit_auto(self) -> None:
49-
self.assertFalse(cinderx.is_frame_evaluator_installed())
50-
self.assertFalse(cinderx.jit.is_enabled())
45+
self.skip_if_already_installed()
5146

5247
cinderx.jit.auto()
5348
self.assertTrue(cinderx.is_frame_evaluator_installed())
5449

5550
cinderx.jit.disable()
5651
cinderx.remove_frame_evaluator()
5752

58-
@passIf(JIT_ENABLED, "Need to check JIT with a clean slate")
5953
@passIf(ARM, "JIT doesn't work on ARM yet")
6054
def test_jit_compile_after_n_calls(self) -> None:
61-
self.assertFalse(cinderx.is_frame_evaluator_installed())
62-
self.assertFalse(cinderx.jit.is_enabled())
55+
self.skip_if_already_installed()
6356

6457
cinderx.jit.compile_after_n_calls(40000)
6558
self.assertTrue(cinderx.is_frame_evaluator_installed())
6659

6760
cinderx.jit.disable()
6861
cinderx.remove_frame_evaluator()
6962

70-
@passIf(JIT_ENABLED, "Need to check JIT with a clean slate")
7163
@passIf(ARM, "JIT doesn't work on ARM yet")
7264
def test_jit_force_compile(self) -> None:
73-
self.assertFalse(cinderx.is_frame_evaluator_installed())
74-
self.assertFalse(cinderx.jit.is_enabled())
65+
self.skip_if_already_installed()
7566

7667
def foo(a: int, b: int) -> int:
7768
return a + b
7869

70+
cinderx.jit.enable()
7971
cinderx.jit.force_compile(foo)
8072
self.assertTrue(cinderx.jit.is_jit_compiled(foo))
8173
self.assertTrue(cinderx.is_frame_evaluator_installed())
@@ -84,15 +76,14 @@ def foo(a: int, b: int) -> int:
8476
cinderx.jit.disable()
8577
cinderx.remove_frame_evaluator()
8678

87-
@passIf(JIT_ENABLED, "Need to check JIT with a clean slate")
8879
@passIf(ARM, "JIT doesn't work on ARM yet")
8980
def test_jit_lazy_compile(self) -> None:
90-
self.assertFalse(cinderx.is_frame_evaluator_installed())
91-
self.assertFalse(cinderx.jit.is_enabled())
81+
self.skip_if_already_installed()
9282

9383
def foo(a: int, b: int) -> int:
9484
return a + b
9585

86+
cinderx.jit.enable()
9687
cinderx.jit.lazy_compile(foo)
9788
self.assertFalse(cinderx.jit.is_jit_compiled(foo))
9889
self.assertTrue(cinderx.is_frame_evaluator_installed())
@@ -105,6 +96,12 @@ def foo(a: int, b: int) -> int:
10596
cinderx.jit.disable()
10697
cinderx.remove_frame_evaluator()
10798

99+
def skip_if_already_installed(self) -> None:
100+
# JIT can be enabled via decorators from other test modules, so this has to
101+
# be run inside of the test function and not as a decorator itself.
102+
if cinderx.is_frame_evaluator_installed():
103+
self.skipTest("Have to test frame evaluator with a clean slate")
104+
108105

109106
if __name__ == "__main__":
110107
unittest.main()

cinderx/PythonLib/test_cinderx/test_jit_coroutines.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
# pyre-unsafe
44

5-
# pyre-ignore[21]: Pyre doesn't know about _testcapi
6-
import _testcapi
75
import asyncio
86
import dis
97
import sys
@@ -15,9 +13,15 @@
1513
compiles_after_one_call,
1614
passIf,
1715
passUnless,
16+
skip_module_if_oss,
1817
skip_unless_jit,
1918
)
2019

20+
skip_module_if_oss()
21+
22+
# pyre-ignore[21]: Pyre doesn't know about _testcapi
23+
import _testcapi
24+
2125
# Allow this file to run without CinderX.
2226
if cinderx.is_initialized():
2327
from .test_compiler.test_static.common import StaticTestBase

cinderx/PythonLib/test_cinderx/test_jit_preload.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@
88
import sys
99
import unittest
1010

11-
import cinderx
12-
13-
cinderx.init()
14-
1511
import cinderx.jit
1612
from cinderx.test_support import (
1713
ENCODING,

cinderx/PythonLib/test_cinderx/test_jit_support_instrumentation.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
from types import CodeType, FrameType
88

99
from cinderx.jit import force_compile, is_jit_compiled
10-
from cinderx.test_support import passUnless, skip_unless_jit
10+
from cinderx.test_support import passUnless, skip_module_if_oss, skip_unless_jit
11+
12+
skip_module_if_oss()
1113

1214

1315
# sys.monitoring is only available in Python 3.12+

cinderx/PythonLib/test_cinderx/test_jitlist.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,17 @@
1313
from pathlib import Path
1414

1515
import cinderx.jit
16-
from cinderx.test_support import ENCODING, passUnless, skip_unless_jit, subprocess_env
16+
from cinderx.test_support import (
17+
ENCODING,
18+
is_oss,
19+
passIf,
20+
passUnless,
21+
skip_unless_jit,
22+
subprocess_env,
23+
)
24+
25+
26+
OSS: bool = is_oss()
1727

1828

1929
@skip_unless_jit("Tests JIT list behavior")
@@ -128,6 +138,7 @@ def code_func_nojit() -> None:
128138
code_func_nojit()
129139
self.assertFalse(cinderx.jit.is_jit_compiled(code_func_nojit))
130140

141+
@passIf(OSS, "Qualname change events are Meta Python only")
131142
def test_change_func_qualname(self) -> None:
132143
# This should be a skipIf decorator, but that makes pyre unhappy for some
133144
# unknown reason.

cinderx/PythonLib/test_cinderx/test_parallel_gc.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66

77
import cinderx
88
import cinderx.jit
9+
from cinderx.test_support import passIf, passUnless, skip_module_if_oss
10+
11+
skip_module_if_oss()
912

1013
# pyre-ignore[21]: Pyre doesn't know about cpython/Lib/test.
1114
import test.test_gc
12-
from cinderx.test_support import passIf, passUnless
1315

1416

1517
def _restore_parallel_gc(settings: dict[str, int] | None) -> None:

cinderx/PythonLib/test_cinderx/test_perf_profiler_precompile.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
import sysconfig
77
import unittest
88

9-
from cinderx.test_support import passIf
9+
from cinderx.test_support import passIf, skip_module_if_oss
10+
11+
skip_module_if_oss()
1012

1113
# pyre-ignore[21]: can't find test.support
1214
from test.support.os_helper import temp_dir

cinderx/PythonLib/test_cinderx/test_python314_bytecodes.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
# Copyright (c) Meta Platforms, Inc. and affiliates.
22

3+
import dis
34
import opcode
45
import sys
56
import types
67
import unittest
78
from typing import Callable
89

910
import cinderx.test_support as cinder_support
10-
from cinderx.test_support import passUnless
11+
from cinderx.test_support import passUnless, undo_fail_decorators
1112

1213

1314
def one():
@@ -405,6 +406,14 @@ def x(a):
405406
assert a
406407

407408
x(True)
409+
410+
# pytest overwrites assert statements and destroys LOAD_COMMON_CONSTANT
411+
# bytecodes.
412+
inner_x = undo_fail_decorators(x)
413+
for inst in dis.get_instructions(inner_x):
414+
if inst.opname == "LOAD_GLOBAL" and "pytest" in inst.argval:
415+
return
416+
408417
self.assertBytecodeContains(x, "LOAD_COMMON_CONSTANT")
409418

410419
def test_LOAD_SPECIAL(self):

0 commit comments

Comments
 (0)