diff --git a/docs/code-examples/roundtrips.py b/docs/code-examples/roundtrips.py index 79a663619ae6..10b32ecfd4ef 100755 --- a/docs/code-examples/roundtrips.py +++ b/docs/code-examples/roundtrips.py @@ -7,12 +7,14 @@ import argparse import multiprocessing import os -import subprocess import sys import time from os import listdir from os.path import isfile, join +sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/../../scripts/") +from roundtrip_utils import cmake_build, cmake_configure, cpp_build_dir, roundtrip_env, run, run_comparison # noqa + # fmt: off # These entries won't run at all. @@ -57,16 +59,6 @@ # fmt: on -def run( - args: list[str], *, env: dict[str, str] | None = None, timeout: int | None = None, cwd: str | None = None -) -> None: - print(f"> {subprocess.list2cmdline(args)}") - result = subprocess.run(args, env=env, cwd=cwd, timeout=timeout, check=False, capture_output=True, text=True) - assert ( - result.returncode == 0 - ), f"{subprocess.list2cmdline(args)} failed with exit-code {result.returncode}. Output:\n{result.stdout}\n{result.stderr}" - - def main() -> None: parser = argparse.ArgumentParser(description="Run end-to-end cross-language roundtrip tests for all API examples") parser.add_argument("--no-py", action="store_true", help="Skip Python tests") @@ -115,16 +107,7 @@ def main() -> None: print("----------------------------------------------------------") print("Build rerun_c & rerun_cpp…") start_time = time.time() - os.makedirs("build", exist_ok=True) - build_type = "Debug" - if args.release: - build_type = "Release" - configure_args = ["cmake", f"-DCMAKE_BUILD_TYPE={build_type}", "-DCMAKE_COMPILE_WARNING_AS_ERROR=ON", ".."] - run( - configure_args, - env=build_env, - cwd="build", - ) + cmake_configure(args.release, build_env) cmake_build("rerun_sdk", args.release) elapsed = time.time() - start_time print(f"rerun-sdk for C++ built in {elapsed:.1f} seconds") @@ -218,26 +201,6 @@ def run_example(example: str, language: str, args: argparse.Namespace) -> None: assert False, f"Unknown language: {language}" -def roundtrip_env(*, save_path: str | None = None) -> dict[str, str]: - env = os.environ.copy() - - # NOTE: Make sure to disable batching, otherwise the Arrow concatenation logic within - # the batcher will happily insert uninitialized padding bytes as needed! - env["RERUN_FLUSH_NUM_ROWS"] = "0" - - # Turn on strict mode to catch errors early - env["RERUN_STRICT"] = "1" - - # Treat any warning as panics - env["RERUN_PANIC_ON_WARN"] = "1" - - if save_path: - # NOTE: Force the recording stream to write to disk! - env["_RERUN_TEST_FORCE_SAVE"] = save_path - - return env - - def run_roundtrip_python(example: str) -> str: main_path = f"docs/code-examples/{example}.py" output_path = f"docs/code-examples/{example}_py.rrd" @@ -284,41 +247,13 @@ def run_roundtrip_cpp(example: str, release: bool) -> str: cmake_build(target_name, release) - cmd = [f"./build/docs/code-examples/{example}"] + (extra_args.get(example) or []) + cmd = [f"{cpp_build_dir}/docs/code-examples/{example}"] + (extra_args.get(example) or []) env = roundtrip_env(save_path=output_path) run(cmd, env=env, timeout=12000) return output_path -def cmake_build(target: str, release: bool) -> None: - config = "Debug" - if release: - config = "Release" - - build_process_args = [ - "cmake", - "--build", - ".", - "--config", - config, - "--target", - target, - "--parallel", - str(multiprocessing.cpu_count()), - ] - run(build_process_args, cwd="build") - - -def run_comparison(rrd0_path: str, rrd1_path: str, full_dump: bool) -> None: - cmd = ["rerun", "compare"] - if full_dump: - cmd += ["--full-dump"] - cmd += [rrd0_path, rrd1_path] - - run(cmd, env=roundtrip_env(), timeout=30) - - def check_non_empty_rrd(path: str) -> None: from pathlib import Path diff --git a/pixi.toml b/pixi.toml index 2a17c2904a15..48254d7956a8 100644 --- a/pixi.toml +++ b/pixi.toml @@ -48,31 +48,31 @@ py-test = { cmd = "python -m pytest -vv rerun_py/tests/unit", depends_on = [ ] } # All the cpp-* tasks can be configured with environment variables, e.g.: RERUN_WERROR=ON CXX=clang++ -cpp-prepare-release = "cmake -G 'Ninja' -B build -S . -DCMAKE_BUILD_TYPE=Release" -cpp-prepare = "cmake -G 'Ninja' -B build -S . -DCMAKE_BUILD_TYPE=Debug" -cpp-build-all = { cmd = "cmake --build build --config Debug --target all", depends_on = [ +cpp-prepare-release = "cmake -G 'Ninja' -B build/release -S . -DCMAKE_BUILD_TYPE=Release" +cpp-prepare = "cmake -G 'Ninja' -B build/debug -S . -DCMAKE_BUILD_TYPE=Debug" +cpp-build-all = { cmd = "cmake --build build/debug --config Debug --target all", depends_on = [ "cpp-prepare", ] } cpp-clean = "rm -rf build CMakeCache.txt CMakeFiles" -cpp-build-tests = { cmd = "cmake --build build --config Debug --target rerun_sdk_tests", depends_on = [ +cpp-build-tests = { cmd = "cmake --build build/debug --config Debug --target rerun_sdk_tests", depends_on = [ "cpp-prepare", ] } -cpp-build-roundtrips = { cmd = "cmake --build build --config Debug --target roundtrips", depends_on = [ +cpp-build-roundtrips = { cmd = "cmake --build build/debug --config Debug --target roundtrips", depends_on = [ "cpp-prepare", ] } -cpp-build-examples = { cmd = "cmake --build build --config Debug --target examples", depends_on = [ +cpp-build-examples = { cmd = "cmake --build build/debug --config Debug --target examples", depends_on = [ "cpp-prepare", ] } -cpp-build-doc-examples = { cmd = "cmake --build build --config Debug --target doc_examples", depends_on = [ +cpp-build-doc-examples = { cmd = "cmake --build build/debug --config Debug --target doc_examples", depends_on = [ "cpp-prepare", ] } -cpp-build-log-benchmark = { cmd = "cmake --build build --config Release --target log_benchmark", depends_on = [ +cpp-build-log-benchmark = { cmd = "cmake --build build/release --config Release --target log_benchmark", depends_on = [ "cpp-prepare-release", ] } -cpp-test = { cmd = "export RERUN_STRICT=1 && ./build/rerun_cpp/tests/rerun_sdk_tests", depends_on = [ +cpp-test = { cmd = "export RERUN_STRICT=1 && ./build/debug/rerun_cpp/tests/rerun_sdk_tests", depends_on = [ "cpp-build-tests", ] } -cpp-log-benchmark = { cmd = "export RERUN_STRICT=1 && ./build/tests/cpp/log_benchmark/log_benchmark", depends_on = [ +cpp-log-benchmark = { cmd = "export RERUN_STRICT=1 && ./build/release/tests/cpp/log_benchmark/log_benchmark", depends_on = [ "cpp-build-log-benchmark", ] } cpp-build-and-test-all = { depends_on = ["cpp-build-all", "cpp-test"] } diff --git a/scripts/roundtrip_utils.py b/scripts/roundtrip_utils.py new file mode 100644 index 000000000000..a45819985706 --- /dev/null +++ b/scripts/roundtrip_utils.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 + +"""Shared functionality for roundtrip tests.""" + +from __future__ import annotations + +import multiprocessing +import os +import subprocess + +cpp_build_dir = "./build/roundtrips" +repo_root = None + + +def get_repo_root() -> str: + global repo_root + if repo_root is not None: + return repo_root + else: + get_rev_parse = subprocess.run(["git", "rev-parse", "--show-toplevel"], capture_output=True) + assert get_rev_parse.returncode == 0 + repo_root = get_rev_parse.stdout.decode("utf-8").strip() + print("Repository root:", repo_root) + return repo_root + + +def run( + args: list[str], *, env: dict[str, str] | None = None, timeout: int | None = None, cwd: str | None = None +) -> None: + # Run from the repo root if not specify otherwise. + if cwd is None: + cwd = get_repo_root() + + print(f"> {subprocess.list2cmdline(args)}") + result = subprocess.run(args, env=env, cwd=cwd, timeout=timeout, check=False, capture_output=True, text=True) + assert ( + result.returncode == 0 + ), f"{subprocess.list2cmdline(args)} failed with exit-code {result.returncode}. Output:\n{result.stdout}\n{result.stderr}" + + +def roundtrip_env(*, save_path: str | None = None) -> dict[str, str]: + env = os.environ.copy() + + # NOTE: Make sure to disable batching, otherwise the Arrow concatenation logic within + # the batcher will happily insert uninitialized padding bytes as needed! + env["RERUN_FLUSH_NUM_ROWS"] = "0" + + # Turn on strict mode to catch errors early + env["RERUN_STRICT"] = "1" + + # Treat any warning as panics + env["RERUN_PANIC_ON_WARN"] = "1" + + if save_path: + # NOTE: Force the recording stream to write to disk! + env["_RERUN_TEST_FORCE_SAVE"] = save_path + + return env + + +def cmake_configure(release: bool, env: dict[str, str]) -> None: + os.makedirs(cpp_build_dir, exist_ok=True) + build_type = "Debug" + if release: + build_type = "Release" + # TODO(andreas): We should pixi for the prepare so we can ensure we have build tooling ready + configure_args = [ + "cmake", + "-B", + cpp_build_dir, + f"-DCMAKE_BUILD_TYPE={build_type}", + "-DCMAKE_COMPILE_WARNING_AS_ERROR=ON", + ".", + ] + run( + configure_args, + env=env, + ) + + +def cmake_build(target: str, release: bool) -> None: + config = "Debug" + if release: + config = "Release" + + build_process_args = [ + "cmake", + "--build", + cpp_build_dir, + "--config", + config, + "--target", + target, + "--parallel", + str(multiprocessing.cpu_count()), + ] + run(build_process_args) + + +def run_comparison(rrd0_path: str, rrd1_path: str, full_dump: bool) -> None: + cmd = ["rerun", "compare"] + if full_dump: + cmd += ["--full-dump"] + cmd += [rrd0_path, rrd1_path] + + run(cmd, env=roundtrip_env(), timeout=30) diff --git a/tests/cpp/log_benchmark/main.cpp b/tests/cpp/log_benchmark/main.cpp index 2852f03abbd1..08a1e17fa5f1 100644 --- a/tests/cpp/log_benchmark/main.cpp +++ b/tests/cpp/log_benchmark/main.cpp @@ -25,7 +25,7 @@ // For better whole-executable timing capture you can also first build the executable and then run: // ``` // pixi run cpp-build-log-benchmark -// ./build/tests/cpp/log_benchmark/log_benchmark +// ./build/release/tests/cpp/log_benchmark/log_benchmark // ``` // diff --git a/tests/roundtrips.py b/tests/roundtrips.py index d53d39bb8f74..41b913bb3019 100755 --- a/tests/roundtrips.py +++ b/tests/roundtrips.py @@ -12,12 +12,14 @@ import argparse import multiprocessing import os -import subprocess import sys import time from os import listdir from os.path import isfile, join +sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/../scripts/") +from roundtrip_utils import cmake_build, cmake_configure, cpp_build_dir, roundtrip_env, run, run_comparison # noqa + ARCHETYPES_PATH = "crates/re_types/definitions/rerun/archetypes" opt_out = { @@ -29,16 +31,6 @@ } -def run( - args: list[str], *, env: dict[str, str] | None = None, timeout: int | None = None, cwd: str | None = None -) -> None: - print(f"> {subprocess.list2cmdline(args)}") - result = subprocess.run(args, env=env, cwd=cwd, timeout=timeout, check=False, capture_output=True, text=True) - assert ( - result.returncode == 0 - ), f"{subprocess.list2cmdline(args)} failed with exit-code {result.returncode}. Output:\n{result.stdout}\n{result.stderr}" - - def main() -> None: parser = argparse.ArgumentParser(description="Run our end-to-end cross-language roundtrip tests for all SDK") parser.add_argument("--no-py-build", action="store_true", help="Skip building rerun-sdk for Python") @@ -80,16 +72,7 @@ def main() -> None: print("----------------------------------------------------------") print("Build rerun_c & rerun_cpp…") start_time = time.time() - os.makedirs("build", exist_ok=True) - build_type = "Debug" - if args.release: - build_type = "Release" - configure_args = ["cmake", f"-DCMAKE_BUILD_TYPE={build_type}", "-DCMAKE_COMPILE_WARNING_AS_ERROR=ON", ".."] - run( - configure_args, - env=build_env, - cwd="build", - ) + cmake_configure(args.release, build_env) cmake_build("rerun_sdk", args.release) elapsed = time.time() - start_time print(f"rerun-sdk for C++ built in {elapsed:.1f} seconds") @@ -155,22 +138,6 @@ def main() -> None: print("All tests passed!") -def roundtrip_env() -> dict[str, str]: - env = os.environ.copy() - - # NOTE: Make sure to disable batching, otherwise the Arrow concatenation logic within - # the batcher will happily insert uninitialized padding bytes as needed! - env["RERUN_FLUSH_NUM_ROWS"] = "0" - - # Turn on strict mode to catch errors early - env["RERUN_STRICT"] = "1" - - # Treat any warning as panics - env["RERUN_PANIC_ON_WARN"] = "1" - - return env - - def build(arch: str, language: str, args: argparse.Namespace) -> None: if language == "cpp": run_roundtrip_cpp(arch, args.release) @@ -226,39 +193,11 @@ def run_roundtrip_cpp(arch: str, release: bool) -> str: cmake_build(target_name, release) - cmd = [f"./build/tests/cpp/roundtrips/{target_name}", output_path] + cmd = [f"{cpp_build_dir}/tests/cpp/roundtrips/{target_name}", output_path] run(cmd, env=roundtrip_env(), timeout=12000) return output_path -def cmake_build(target: str, release: bool) -> None: - config = "Debug" - if release: - config = "Release" - - build_process_args = [ - "cmake", - "--build", - ".", - "--config", - config, - "--target", - target, - "--parallel", - str(multiprocessing.cpu_count()), - ] - run(build_process_args, cwd="build") - - -def run_comparison(rrd0_path: str, rrd1_path: str, full_dump: bool) -> None: - cmd = ["rerun", "compare"] - if full_dump: - cmd += ["--full-dump"] - cmd += [rrd0_path, rrd1_path] - - run(cmd, env=roundtrip_env(), timeout=30) - - if __name__ == "__main__": main()