From 141e0908842e26bd9a9562032201f33e542cf986 Mon Sep 17 00:00:00 2001 From: Facebook GitHub Bot Date: Thu, 24 Jul 2025 08:47:30 -0700 Subject: [PATCH] Re-sync with internal repository The internal and external repositories are out of sync. This Pull Request attempts to brings them back in sync by patching the GitHub repository. Please carefully review this patch. You must disable ShipIt for your project in order to merge this pull request. DO NOT IMPORT this pull request. Instead, merge it directly on GitHub using the MERGE BUTTON. Re-enable ShipIt after merging. --- buck_integration/scruttest.py | 50 -------- buck_integration/unittestify.py | 212 -------------------------------- 2 files changed, 262 deletions(-) delete mode 100644 buck_integration/scruttest.py delete mode 100644 buck_integration/unittestify.py diff --git a/buck_integration/scruttest.py b/buck_integration/scruttest.py deleted file mode 100644 index a8d286f..0000000 --- a/buck_integration/scruttest.py +++ /dev/null @@ -1,50 +0,0 @@ -# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. - -# pyre-strict - -# ---------------------------------- -# This library exports shared functionality for Buck macros: -# - `scrut_test` -# - `buck_scrut_test` -# - `coghweel_scrut_test` (planned) -# ---------------------------------- - - -import os -import re -from pathlib import Path - - -class ScrutAssertionError(AssertionError): - output: str - cmd: object - - def __init__( - self, *args: object, output: str, cmd: object, **kwargs: object - ) -> None: - self.cmd = cmd - self.output = output - super().__init__(*args, **kwargs) - - def __str__(self) -> str: - return "validation failed" - - def render(self) -> str: - cmd = " ".join(self.cmd) if isinstance(self.cmd, list) else self.cmd - return f"{cmd}:\n\n{self.output}" - - -def _path_component_to_method_name(path: str) -> str: - name = re.sub("[^a-z0-9_]", "_", path.lower()) - name = re.sub("__+", "_", name) - return name.strip("_") - - -def generate_test_method_name(path: Path) -> str: - method_name = _path_component_to_method_name(path.name) - if len(parents := path.parent.name.split(os.sep)) > 0: - parent = _path_component_to_method_name(parents.pop()) - method_name = f"{parent}_{method_name}" - if not method_name.startswith("test_"): - method_name = f"test_{method_name}" - return method_name diff --git a/buck_integration/unittestify.py b/buck_integration/unittestify.py deleted file mode 100644 index 6b0a8ac..0000000 --- a/buck_integration/unittestify.py +++ /dev/null @@ -1,212 +0,0 @@ -# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. - -# ---------------------------------- -# !THIS FILE IS EXECUTED, THIS IS NOT A LIBRARY! -# ---------------------------------- -# This is largly stolen from our Cram code in //third-party/cram/unittestify.py -# ---------------------------------- -# Translate Scrut tests to standard Python unittest tests. -# ---------------------------------- - -from __future__ import annotations - -import os -import subprocess -import sys -import unittest -from pathlib import Path -from typing import Callable - -from . import scruttest - - -class ScrutTests(unittest.TestCase): - @classmethod - def auto_generate_tests(cls) -> None: - """Add test files as methods""" - - env = os.environ.copy() - - try: - scrut_args = env.pop("SCRUT_ARGS").split() - except KeyError as err: - raise Exception("Required SCRUT_ARGS env var not set") from err - - try: - scrut_location = env.pop("SCRUT_LOCATION") - except KeyError as err: - raise Exception("Required SCRUT_LOCATION env var not set") from err - - try: - scrut_tests_dir = env.pop("SCRUT_TESTS_DIR") - except KeyError as err: - raise Exception("Required SCRUT_TESTS_DIR env var not set") from err - - try: - scrut_user_provided_env = env.pop("SCRUT_USER_PROVIDED_ENV") - except KeyError as err: - raise Exception("Required SCRUT_USER_PROVIDED_ENV env var not set") from err - - # Expanded string macros (e.g. `$(location)`, `$(exe_target)`, etc.) - # are absolute paths locally, but relative on RE. Try to make user - # provided envs absolute so the tests can use them from any directory. - # - # NOTE: `buck run` scrut, because it's local, gets absolute paths. - # So path resolution only matters here in unittestify. - # - # See https://fburl.com/workplace/tisvmbto - if scrut_user_provided_env: - # Unfortunate side-effect of needing to take a list of selects - # to join into a string. - assert ( - scrut_user_provided_env[-1] == "," - ), f"missing expected trailing comma in `{scrut_user_provided_env}`" - scrut_user_provided_env = scrut_user_provided_env[:-1] - - cwd = os.getcwd() - for k in scrut_user_provided_env.split(","): - try: - value = env[k] - except KeyError as err: - raise Exception( - f"User provided env `{k}` is not in the environment", - ) from err - - # On Windows, buck will give you a command string rather than - # an executable path when using `exe` or `exe_target`. - # The string is the interpreter followed by the script path. - # Note: Using `location` or pointing to a `command_alias` - # with envs (or args) will give you an executable path. - if ( - os.name == "nt" - and (parts := value.partition(" ")) - and (interpreter := parts[0]) - and (script := parts[2]) - and os.path.isabs(interpreter) - and interpreter.lower().endswith((".exe", ".bat", ".cmd")) - and not os.path.isabs(script) - and os.path.lexists(script) - ): - env[k] = interpreter + " " + os.path.join(cwd, script) - continue - - # Do not resolve paths to avoid changing arg0's name. - # Do not normalize paths to avoid incorrectly handling symlinks. - if not os.path.isabs(value) and os.path.lexists(value): - env[k] = os.path.join(cwd, value) - - scrut_append_tests_dir = ( - env.pop("SCRUT_APPEND_TESTS_DIR") - if "SCRUT_APPEND_TESTS_DIR" in env - else None - ) - - scrut_prepend_tests_dir = ( - env.pop("SCRUT_PREPEND_TESTS_DIR") - if "SCRUT_PREPEND_TESTS_DIR" in env - else None - ) - - # TODO(T138035235) coverage is currently using wrong libs - if "LD_PRELOAD" in env: - env.pop("LD_PRELOAD") - - # Since prepend/append files are in another filegroup, keep track of common path - base_path = Path(scrut_tests_dir).parent.parent - - # Add bootstrap/teardown for each test - if scrut_append_tests_dir is not None: - scrut_args.extend( - [ - "--append-test-file-paths={}".format( - testpath.relative_to(base_path) - ) - for testpath in Path(scrut_append_tests_dir).iterdir() - ], - ) - if scrut_prepend_tests_dir is not None: - scrut_args.extend( - [ - "--prepend-test-file-paths={}".format( - testpath.relative_to(base_path) - ) - for testpath in Path(scrut_prepend_tests_dir).iterdir() - ], - ) - - # Run test subcommand from scrut - args = [os.path.join(os.getcwd(), scrut_location), "test"] + scrut_args - - method_names = {} - for fmt, suffixes in { - "cram": [".t", ".cram"], - "markdown": [".md", ".markdown", ".scrut"], - }.items(): - for suffix in suffixes: - for testpath in Path(scrut_tests_dir).glob(f"**/*{suffix}"): - method_name = scruttest.generate_test_method_name(testpath) - if method_name in method_names: - raise Exception( - "Colliding test names: {} and {} both result in {}".format( - testpath, - method_names[method_name], - method_name, - ) - ) - method_names[method_name] = testpath - - fmt_args = [] - if fmt == "cram": - fmt_args.append("--cram-compat") - fmt_args.append("--combine-output") - fmt_args.append("--keep-output-crlf") - - setattr( - cls, - method_name, - _make_scrut_test_method( - args=args - + fmt_args - + [str(testpath.relative_to(base_path))], - env=env, - cwd=Path.joinpath(Path(os.getcwd()), base_path), - ), - ) - - -def _make_scrut_test_method( - *, args: list[str], env: dict[str, str], cwd: Path -) -> Callable[[], None]: - # pyre-fixme[2]: Parameter must be annotated. - def runsingletest(self) -> None: - try: - subprocess.run( - args, - capture_output=True, - cwd=cwd, - check=True, - env=env, - text=True, - encoding="utf-8", - ) - except OSError as err: - cmd = " ".join(args) - raise self.fail( - f"`scrut {cmd}` failed due to {err.__class__.__name__}:\n{err}" - ) - except subprocess.CalledProcessError as err: - sys.tracebacklimit = 0 - fail = scruttest.ScrutAssertionError( - f"Scrut test failed {err}", - cmd=err.cmd, - output=err.output, - ) - print("\n" + fail.render()) - if err.stderr: - print("\n" + err.stderr, file=sys.stderr) - raise fail from None - - return runsingletest - - -ScrutTests.auto_generate_tests()