test_context_submission_status.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. # Copyright 2023 Avaiga Private Limited
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  4. # the License. You may obtain a copy of the License at
  5. #
  6. # http://www.apache.org/licenses/LICENSE-2.0
  7. #
  8. # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  9. # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
  10. # specific language governing permissions and limitations under the License.
  11. from unittest.mock import Mock, patch
  12. import pytest
  13. from taipy.core import Status
  14. from taipy.gui_core._context import _GuiCoreContext, _SubmissionStatus
  15. class MockJob:
  16. def __init__(self, id: str, status):
  17. self.status = status
  18. self.id = id
  19. def is_failed(self):
  20. return self.status == Status.FAILED
  21. def is_canceled(self):
  22. return self.status == Status.CANCELED
  23. def is_blocked(self):
  24. return self.status == Status.BLOCKED
  25. def is_pending(self):
  26. return self.status == Status.PENDING
  27. def is_running(self):
  28. return self.status == Status.RUNNING
  29. def is_completed(self):
  30. return self.status == Status.COMPLETED
  31. def is_skipped(self):
  32. return self.status == Status.SKIPPED
  33. def is_abandoned(self):
  34. return self.status == Status.ABANDONED
  35. def is_submitted(self):
  36. return self.status == Status.SUBMITTED
  37. def mock_core_get(entity_id):
  38. jobs = {
  39. "job0_submitted": MockJob("job0_submitted", Status.SUBMITTED),
  40. "job1_failed": MockJob("job1_failed", Status.FAILED),
  41. "job2_canceled": MockJob("job2_canceled", Status.CANCELED),
  42. "job3_blocked": MockJob("job3_blocked", Status.BLOCKED),
  43. "job4_pending": MockJob("job4_pending", Status.PENDING),
  44. "job5_running": MockJob("job5_running", Status.RUNNING),
  45. "job6_completed": MockJob("job6_completed", Status.COMPLETED),
  46. "job7_skipped": MockJob("job7_skipped", Status.SKIPPED),
  47. "job8_abandoned": MockJob("job8_abandoned", Status.ABANDONED),
  48. }
  49. return jobs[entity_id]
  50. class TestGuiCoreContext_SubmissionStatus:
  51. @pytest.mark.parametrize(
  52. "job_ids, expected_status",
  53. [
  54. (["job1_failed"], _SubmissionStatus.FAILED),
  55. (["job2_canceled"], _SubmissionStatus.CANCELED),
  56. (["job3_blocked"], _SubmissionStatus.BLOCKED),
  57. (["job4_pending"], _SubmissionStatus.WAITING),
  58. (["job5_running"], _SubmissionStatus.RUNNING),
  59. (["job6_completed"], _SubmissionStatus.COMPLETED),
  60. (["job7_skipped"], _SubmissionStatus.COMPLETED),
  61. (["job8_abandoned"], _SubmissionStatus.UNDEFINED),
  62. ],
  63. )
  64. def test_single_job(self, job_ids, expected_status):
  65. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  66. gui_core_context = _GuiCoreContext(Mock())
  67. status = gui_core_context._get_submittable_status(job_ids)
  68. assert status == expected_status
  69. @pytest.mark.parametrize(
  70. "job_ids, expected_status",
  71. [
  72. (["job1_failed", "job1_failed"], _SubmissionStatus.FAILED),
  73. (["job1_failed", "job2_canceled"], _SubmissionStatus.FAILED),
  74. (["job1_failed", "job3_blocked"], _SubmissionStatus.FAILED),
  75. (["job1_failed", "job4_pending"], _SubmissionStatus.FAILED),
  76. (["job1_failed", "job5_running"], _SubmissionStatus.FAILED),
  77. (["job1_failed", "job6_completed"], _SubmissionStatus.FAILED),
  78. (["job1_failed", "job7_skipped"], _SubmissionStatus.FAILED),
  79. (["job1_failed", "job8_abandoned"], _SubmissionStatus.FAILED),
  80. (["job2_canceled", "job1_failed"], _SubmissionStatus.FAILED),
  81. (["job3_blocked", "job1_failed"], _SubmissionStatus.FAILED),
  82. (["job4_pending", "job1_failed"], _SubmissionStatus.FAILED),
  83. (["job5_running", "job1_failed"], _SubmissionStatus.FAILED),
  84. (["job6_completed", "job1_failed"], _SubmissionStatus.FAILED),
  85. (["job7_skipped", "job1_failed"], _SubmissionStatus.FAILED),
  86. (["job8_abandoned", "job1_failed"], _SubmissionStatus.FAILED),
  87. ],
  88. )
  89. def test_one_failed_job(self, job_ids, expected_status):
  90. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  91. gui_core_context = _GuiCoreContext(Mock())
  92. status = gui_core_context._get_submittable_status(job_ids)
  93. assert status == expected_status
  94. @pytest.mark.parametrize(
  95. "job_ids, expected_status",
  96. [
  97. (["job2_canceled", "job2_canceled"], _SubmissionStatus.CANCELED),
  98. (["job2_canceled", "job3_blocked"], _SubmissionStatus.CANCELED),
  99. (["job2_canceled", "job4_pending"], _SubmissionStatus.CANCELED),
  100. (["job2_canceled", "job5_running"], _SubmissionStatus.CANCELED),
  101. (["job2_canceled", "job6_completed"], _SubmissionStatus.CANCELED),
  102. (["job2_canceled", "job7_skipped"], _SubmissionStatus.CANCELED),
  103. (["job2_canceled", "job8_abandoned"], _SubmissionStatus.CANCELED),
  104. (["job3_blocked", "job2_canceled"], _SubmissionStatus.CANCELED),
  105. (["job4_pending", "job2_canceled"], _SubmissionStatus.CANCELED),
  106. (["job5_running", "job2_canceled"], _SubmissionStatus.CANCELED),
  107. (["job6_completed", "job2_canceled"], _SubmissionStatus.CANCELED),
  108. (["job7_skipped", "job2_canceled"], _SubmissionStatus.CANCELED),
  109. (["job8_abandoned", "job2_canceled"], _SubmissionStatus.CANCELED),
  110. ],
  111. )
  112. def test_no_failed_one_cancel(self, job_ids, expected_status):
  113. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  114. gui_core_context = _GuiCoreContext(Mock())
  115. status = gui_core_context._get_submittable_status(job_ids)
  116. assert status == expected_status
  117. @pytest.mark.parametrize(
  118. "job_ids, expected_status",
  119. [
  120. (["job4_pending", "job3_blocked"], _SubmissionStatus.WAITING),
  121. (["job4_pending", "job4_pending"], _SubmissionStatus.WAITING),
  122. (["job4_pending", "job6_completed"], _SubmissionStatus.WAITING),
  123. (["job4_pending", "job7_skipped"], _SubmissionStatus.WAITING),
  124. (["job3_blocked", "job4_pending"], _SubmissionStatus.WAITING),
  125. (["job6_completed", "job4_pending"], _SubmissionStatus.WAITING),
  126. (["job7_skipped", "job4_pending"], _SubmissionStatus.WAITING),
  127. ],
  128. )
  129. def test_no_failed_or_cancel_one_pending(self, job_ids, expected_status):
  130. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  131. gui_core_context = _GuiCoreContext(Mock())
  132. status = gui_core_context._get_submittable_status(job_ids)
  133. assert status == expected_status
  134. @pytest.mark.parametrize(
  135. "job_ids, expected_status",
  136. [
  137. (["job5_running", "job3_blocked"], _SubmissionStatus.RUNNING),
  138. (["job5_running", "job4_pending"], _SubmissionStatus.RUNNING),
  139. (["job5_running", "job5_running"], _SubmissionStatus.RUNNING),
  140. (["job5_running", "job6_completed"], _SubmissionStatus.RUNNING),
  141. (["job5_running", "job7_skipped"], _SubmissionStatus.RUNNING),
  142. (["job3_blocked", "job5_running"], _SubmissionStatus.RUNNING),
  143. (["job4_pending", "job5_running"], _SubmissionStatus.RUNNING),
  144. (["job6_completed", "job5_running"], _SubmissionStatus.RUNNING),
  145. (["job7_skipped", "job5_running"], _SubmissionStatus.RUNNING),
  146. ],
  147. )
  148. def test_no_failed_cancel_nor_pending_one_running(self, job_ids, expected_status):
  149. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  150. gui_core_context = _GuiCoreContext(Mock())
  151. status = gui_core_context._get_submittable_status(job_ids)
  152. assert status == expected_status
  153. @pytest.mark.parametrize(
  154. "job_ids, expected_status",
  155. [
  156. (["job3_blocked", "job3_blocked"], _SubmissionStatus.BLOCKED),
  157. (["job3_blocked", "job6_completed"], _SubmissionStatus.BLOCKED),
  158. (["job3_blocked", "job7_skipped"], _SubmissionStatus.BLOCKED),
  159. (["job6_completed", "job3_blocked"], _SubmissionStatus.BLOCKED),
  160. (["job7_skipped", "job3_blocked"], _SubmissionStatus.BLOCKED),
  161. ],
  162. )
  163. def test_no_failed_cancel_pending_nor_running_one_blocked(self, job_ids, expected_status):
  164. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  165. gui_core_context = _GuiCoreContext(Mock())
  166. status = gui_core_context._get_submittable_status(job_ids)
  167. assert status == expected_status
  168. @pytest.mark.parametrize(
  169. "job_ids, expected_status",
  170. [
  171. (["job6_completed", "job6_completed"], _SubmissionStatus.COMPLETED),
  172. (["job6_completed", "job7_skipped"], _SubmissionStatus.COMPLETED),
  173. (["job7_skipped", "job6_completed"], _SubmissionStatus.COMPLETED),
  174. (["job7_skipped", "job7_skipped"], _SubmissionStatus.COMPLETED),
  175. ],
  176. )
  177. def test_only_completed_or_skipped(self, job_ids, expected_status):
  178. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  179. gui_core_context = _GuiCoreContext(Mock())
  180. status = gui_core_context._get_submittable_status(job_ids)
  181. assert status == expected_status
  182. @pytest.mark.parametrize(
  183. "job_ids, expected_status",
  184. [
  185. (["job3_blocked", "job8_abandoned"], _SubmissionStatus.UNDEFINED),
  186. (["job4_pending", "job8_abandoned"], _SubmissionStatus.UNDEFINED),
  187. (["job5_running", "job8_abandoned"], _SubmissionStatus.UNDEFINED),
  188. (["job6_completed", "job8_abandoned"], _SubmissionStatus.UNDEFINED),
  189. (["job7_skipped", "job8_abandoned"], _SubmissionStatus.UNDEFINED),
  190. (["job8_abandoned", "job8_abandoned"], _SubmissionStatus.UNDEFINED),
  191. (["job8_abandoned", "job3_blocked"], _SubmissionStatus.UNDEFINED),
  192. (["job8_abandoned", "job4_pending"], _SubmissionStatus.UNDEFINED),
  193. (["job8_abandoned", "job5_running"], _SubmissionStatus.UNDEFINED),
  194. (["job8_abandoned", "job6_completed"], _SubmissionStatus.UNDEFINED),
  195. (["job8_abandoned", "job7_skipped"], _SubmissionStatus.UNDEFINED),
  196. ],
  197. )
  198. def test_WRONG_CASE_abandoned_without_cancel_or_failed(self, job_ids, expected_status):
  199. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  200. gui_core_context = _GuiCoreContext(Mock())
  201. status = gui_core_context._get_submittable_status(job_ids)
  202. assert status == expected_status
  203. def test_no_job(self):
  204. with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get):
  205. gui_core_context = _GuiCoreContext(Mock())
  206. status = gui_core_context._get_submittable_status([])
  207. assert status == _SubmissionStatus.UNDEFINED