bazel_test_runner.py 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. #!/usr/bin/env python3
  2. """Checks various LLVM tool symlinks behave as expected."""
  3. __copyright__ = """
  4. Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  5. Exceptions. See /LICENSE for license information.
  6. SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  7. """
  8. import os
  9. import sys
  10. import time
  11. import unittest
  12. from bazel_tools.tools.python.runfiles import runfiles
  13. from bazel_integration_test.py import test_base
  14. class BazelExampleTest(test_base.TestBase):
  15. def setUp(self) -> None:
  16. test_base.TestBase.setUp(self)
  17. self.runfiles = runfiles.Create()
  18. self.install_module = self.runfiles.Rlocation(
  19. "carbon/toolchain/install/prefix/lib/carbon"
  20. )
  21. self.startup_flags = [
  22. "--ignore_all_rc_files",
  23. "--batch",
  24. ]
  25. self.flags = [
  26. f"--override_module=carbon_toolchain={self.install_module}"
  27. ]
  28. def _run_bazel(self, command: list[str]) -> str:
  29. """Runs bazel with retry logic for transient errors."""
  30. for attempt in range(5):
  31. exit_code, stdout, stderr = self.RunBazel(
  32. self.startup_flags + command + self.flags
  33. )
  34. # Several error codes are reliably permanent, break immediately.
  35. # `1` -- The build failed.
  36. # `2` -- Command line or environment problem.
  37. # `3` -- Tests failed or timed out, we don't retry at this layer
  38. # on execution timeout.
  39. # `4` -- Test command but no tests found.
  40. # `8` -- Explicitly interrupted build.
  41. #
  42. # Note that `36` is documented as "likely permanent", but we retry
  43. # it as most of our transient failures actually produce that error
  44. # code.
  45. perm_error = (1, 2, 3, 4, 8)
  46. if exit_code in perm_error:
  47. break
  48. for line in stderr:
  49. print(line, file=sys.stderr)
  50. if exit_code == 0:
  51. return stdout
  52. # Retry transient errors with a brief delay.
  53. print(f"Attempt {attempt + 1} failed with exit code {exit_code}")
  54. time.sleep(attempt)
  55. self.AssertExitCode(exit_code, 0, stderr)
  56. def test_compile_lib(self) -> None:
  57. # TODO: Can remove this in favor of always running `test_run` if we can
  58. # make linking a binary sufficiently efficient.
  59. self._run_bazel(["build", "//:example_lib"])
  60. @unittest.skipUnless(
  61. "CARBON_BAZEL_TEST_FULL" in os.environ,
  62. "Skipping expensive test step for minimal testing",
  63. )
  64. def test_run(self) -> None:
  65. stdout = self._run_bazel(["run", "//:example"])
  66. self.assertEqual(stdout, ["Hello World!"])
  67. if __name__ == "__main__":
  68. unittest.main()