test_reactor.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. # -*- coding: utf-8 -*-
  2. """
  3. integration.reactor.reactor
  4. ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5. Test Salt's reactor system
  6. """
  7. from __future__ import absolute_import
  8. import signal
  9. import pytest
  10. import salt.utils.event
  11. import salt.utils.reactor
  12. from tests.support.case import ShellCase
  13. from tests.support.mixins import SaltMinionEventAssertsMixin
  14. from tests.support.unit import skipIf
  15. class TimeoutException(Exception):
  16. pass
  17. @pytest.mark.windows_whitelisted
  18. class ReactorTest(SaltMinionEventAssertsMixin, ShellCase):
  19. """
  20. Test Salt's reactor system
  21. """
  22. def setUp(self):
  23. self.timeout = 30
  24. def get_event(self, class_type="master"):
  25. return salt.utils.event.get_event(
  26. class_type,
  27. sock_dir=self.master_opts["sock_dir"],
  28. transport=self.master_opts["transport"],
  29. keep_loop=True,
  30. opts=self.master_opts,
  31. )
  32. def fire_event(self, tag, data):
  33. event = self.get_event()
  34. event.fire_event(tag, data)
  35. def alarm_handler(self, signal, frame):
  36. raise TimeoutException("Timeout of {0} seconds reached".format(self.timeout))
  37. def test_ping_reaction(self):
  38. """
  39. Fire an event on the master and ensure
  40. that it pings the minion
  41. """
  42. # Create event bus connection
  43. e = salt.utils.event.get_event(
  44. "minion", sock_dir=self.minion_opts["sock_dir"], opts=self.minion_opts
  45. )
  46. e.fire_event({"a": "b"}, "/test_event")
  47. self.assertMinionEventReceived({"a": "b"}, timeout=30)
  48. @skipIf(salt.utils.platform.is_windows(), "no sigalarm on windows")
  49. def test_reactor_reaction(self):
  50. """
  51. Fire an event on the master and ensure
  52. The reactor event responds
  53. """
  54. signal.signal(signal.SIGALRM, self.alarm_handler)
  55. signal.alarm(self.timeout)
  56. master_event = self.get_event()
  57. master_event.fire_event({"id": "minion"}, "salt/test/reactor")
  58. try:
  59. while True:
  60. event = master_event.get_event(full=True)
  61. if event is None:
  62. continue
  63. if event.get("tag") == "test_reaction":
  64. self.assertTrue(event["data"]["test_reaction"])
  65. break
  66. finally:
  67. signal.alarm(0)
  68. @skipIf(salt.utils.platform.is_windows(), "no sigalarm on windows")
  69. def test_reactor_is_leader(self):
  70. """
  71. when leader is set to false reactor should timeout/not do anything
  72. """
  73. # by default reactor should be leader
  74. ret = self.run_run_plus("reactor.is_leader")
  75. self.assertTrue(ret["return"])
  76. # make reactor not leader
  77. self.run_run_plus("reactor.set_leader", False)
  78. ret = self.run_run_plus("reactor.is_leader")
  79. self.assertFalse(ret["return"])
  80. signal.signal(signal.SIGALRM, self.alarm_handler)
  81. signal.alarm(self.timeout)
  82. try:
  83. master_event = self.get_event()
  84. self.fire_event({"id": "minion"}, "salt/test/reactor")
  85. while True:
  86. event = master_event.get_event(full=True)
  87. if event is None:
  88. continue
  89. if event.get("tag") == "test_reaction":
  90. # if we reach this point, the test is a failure
  91. self.assertTrue(False) # pylint: disable=redundant-unittest-assert
  92. break
  93. except TimeoutException as exc:
  94. self.assertTrue("Timeout" in str(exc))
  95. finally:
  96. signal.alarm(0)
  97. # make reactor leader again
  98. self.run_run_plus("reactor.set_leader", True)
  99. ret = self.run_run_plus("reactor.is_leader")
  100. self.assertTrue(ret["return"])
  101. # trigger a reaction
  102. signal.alarm(self.timeout)
  103. try:
  104. master_event = self.get_event()
  105. self.fire_event({"id": "minion"}, "salt/test/reactor")
  106. while True:
  107. event = master_event.get_event(full=True)
  108. if event is None:
  109. continue
  110. if event.get("tag") == "test_reaction":
  111. self.assertTrue(event["data"]["test_reaction"])
  112. break
  113. finally:
  114. signal.alarm(0)