bazel_test_runner.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  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"
  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. return stdout
  57. def test_compile_lib(self) -> None:
  58. # TODO: Can remove this in favor of always running `test_run` if we can
  59. # make linking a binary sufficiently efficient.
  60. self._run_bazel(["build", "//:example_lib"])
  61. @unittest.skipUnless(
  62. "CARBON_BAZEL_TEST_FULL" in os.environ,
  63. "Skipping expensive test step for minimal testing",
  64. )
  65. def test_run(self) -> None:
  66. stdout = self._run_bazel(["run", "//:example"])
  67. self.assertEqual(stdout, ["Hello World!"])
  68. if __name__ == "__main__":
  69. unittest.main()