Files
carbon-lang/examples/bazel_test_runner.py
Jon Ross-Perkins 17897bb05d Add transient error retries to bazel integration tests (#6796)
e.g. for failures like
https://github.com/carbon-language/carbon-lang/actions/runs/22418738440/job/64911093548

We work around this similarly in run_bazel.py already; this is mirroring
over some of the logic (sharing would require work on Python's set up).

Assisted-by: Google Antigravity with Gemini 3 Flash

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2026-02-26 17:36:51 +00:00

83 lines
2.8 KiB
Python
Executable File

#!/usr/bin/env python3
"""Checks various LLVM tool symlinks behave as expected."""
__copyright__ = """
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
Exceptions. See /LICENSE for license information.
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
"""
import os
import sys
import time
import unittest
from bazel_tools.tools.python.runfiles import runfiles
from bazel_integration_test.py import test_base
class BazelExampleTest(test_base.TestBase):
def setUp(self) -> None:
test_base.TestBase.setUp(self)
self.runfiles = runfiles.Create()
self.install_module = self.runfiles.Rlocation(
"carbon/toolchain/install/prefix/lib/carbon"
)
self.startup_flags = [
"--ignore_all_rc_files",
"--batch",
]
self.flags = [
f"--override_module=carbon_toolchain={self.install_module}"
]
def _run_bazel(self, command: list[str]) -> str:
"""Runs bazel with retry logic for transient errors."""
for attempt in range(5):
exit_code, stdout, stderr = self.RunBazel(
self.startup_flags + command + self.flags
)
# Several error codes are reliably permanent, break immediately.
# `1` -- The build failed.
# `2` -- Command line or environment problem.
# `3` -- Tests failed or timed out, we don't retry at this layer
# on execution timeout.
# `4` -- Test command but no tests found.
# `8` -- Explicitly interrupted build.
#
# Note that `36` is documented as "likely permanent", but we retry
# it as most of our transient failures actually produce that error
# code.
perm_error = (1, 2, 3, 4, 8)
if exit_code in perm_error:
break
for line in stderr:
print(line, file=sys.stderr)
if exit_code == 0:
return stdout
# Retry transient errors with a brief delay.
print(f"Attempt {attempt + 1} failed with exit code {exit_code}")
time.sleep(attempt)
self.AssertExitCode(exit_code, 0, stderr)
def test_compile_lib(self) -> None:
# TODO: Can remove this in favor of always running `test_run` if we can
# make linking a binary sufficiently efficient.
self._run_bazel(["build", "//:example_lib"])
@unittest.skipUnless(
"CARBON_BAZEL_TEST_FULL" in os.environ,
"Skipping expensive test step for minimal testing",
)
def test_run(self) -> None:
stdout = self._run_bazel(["run", "//:example"])
self.assertEqual(stdout, ["Hello World!"])
if __name__ == "__main__":
unittest.main()