/tests/testutil.py

https://github.com/facebookincubator/FCR · Python · 67 lines · 38 code · 17 blank · 12 comment · 7 complexity · d362df87a755994121596b4b92d89fdf MD5 · raw file

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # Copyright (c) Facebook, Inc. and its affiliates.
  4. #
  5. # This source code is licensed under the MIT license found in the
  6. # LICENSE file in the root directory of this source tree.
  7. import asyncio
  8. import functools
  9. import typing
  10. import unittest
  11. if typing.TYPE_CHECKING:
  12. from fbnet.command_runner.counters import Counters
  13. # `asyncio.events.AbstractEventLoop` to have type `float` but is never initialized.
  14. # pyre-fixme[13]: Attribute `slow_callback_duration` inherited from abstract class
  15. class FcrTestEventLoop(asyncio.SelectorEventLoop):
  16. def __init__(self, *args, **kwargs) -> None:
  17. super().__init__(*args, **kwargs)
  18. self._counter_mgr = None
  19. def inc_counter(self, name: str) -> None:
  20. if self._counter_mgr:
  21. self._counter_mgr.incCounter(name)
  22. def set_counter_mgr(self, counter_mgr: "Counters") -> None:
  23. self._counter_mgr = counter_mgr
  24. def async_test(func) -> typing.Callable:
  25. @functools.wraps(func)
  26. def _wrapper(self, *args, **kwargs) -> None:
  27. self._loop.run_until_complete(func(self, *args, **kwargs))
  28. return _wrapper
  29. class AsyncTestCase(unittest.TestCase):
  30. def setUp(self) -> None:
  31. self._loop = FcrTestEventLoop()
  32. asyncio.set_event_loop(None)
  33. def tearDown(self) -> None:
  34. pending = [t for t in asyncio.Task.all_tasks(self._loop) if not t.done()]
  35. if pending:
  36. # give opportunity to pending tasks to complete
  37. res = self._run_loop(asyncio.wait(pending, timeout=1, loop=self._loop))
  38. done, pending = res[0]
  39. for p in pending:
  40. print("Task is still pending", p)
  41. self._loop.close()
  42. def wait_for_tasks(self, timeout: int = 10) -> None:
  43. pending = asyncio.Task.all_tasks(self._loop)
  44. self._loop.run_until_complete(asyncio.gather(*pending, loop=self._loop))
  45. def _run_loop(self, *args) -> typing.List[typing.Any]:
  46. """
  47. Run a set of coroutines in a loop
  48. """
  49. finished, _ = self._loop.run_until_complete(asyncio.wait(args, loop=self._loop))
  50. return [task.result() for task in finished]