test_submission.py 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901
  1. # Copyright 2021-2024 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 datetime import datetime
  12. import pytest
  13. from taipy.core import TaskId
  14. from taipy.core.job._job_manager_factory import _JobManagerFactory
  15. from taipy.core.job.job import Job
  16. from taipy.core.job.status import Status
  17. from taipy.core.submission._submission_manager_factory import _SubmissionManagerFactory
  18. from taipy.core.submission.submission import Submission
  19. from taipy.core.submission.submission_status import SubmissionStatus
  20. from taipy.core.task._task_manager_factory import _TaskManagerFactory
  21. from taipy.core.task.task import Task
  22. def test_submission_equals(submission):
  23. submission_manager = _SubmissionManagerFactory()._build_manager()
  24. submission_id = submission.id
  25. submission_manager._set(submission)
  26. # To test if instance is same type
  27. task = Task("task", {}, print, [], [], submission_id)
  28. submission_2 = submission_manager._get(submission_id)
  29. assert submission == submission_2
  30. assert submission != submission_id
  31. assert submission != task
  32. def test_create_submission(scenario, job, current_datetime):
  33. submission_1 = Submission(scenario.id, scenario._ID_PREFIX, scenario.config_id)
  34. assert submission_1.id is not None
  35. assert submission_1.entity_id == scenario.id
  36. assert submission_1.entity_type == scenario._ID_PREFIX
  37. assert submission_1.entity_config_id == scenario.config_id
  38. assert submission_1.jobs == []
  39. assert isinstance(submission_1.creation_date, datetime)
  40. assert submission_1._submission_status == SubmissionStatus.SUBMITTED
  41. assert submission_1._version is not None
  42. submission_2 = Submission(
  43. scenario.id,
  44. scenario._ID_PREFIX,
  45. scenario.config_id,
  46. "submission_id",
  47. [job],
  48. {"debug": True, "log": "log_file", "retry_note": 5},
  49. current_datetime,
  50. SubmissionStatus.COMPLETED,
  51. "version_id",
  52. )
  53. assert submission_2.id == "submission_id"
  54. assert submission_2.entity_id == scenario.id
  55. assert submission_2.entity_type == scenario._ID_PREFIX
  56. assert submission_2.entity_config_id == scenario.config_id
  57. assert submission_2._jobs == [job]
  58. assert submission_2._properties == {"debug": True, "log": "log_file", "retry_note": 5}
  59. assert submission_2.creation_date == current_datetime
  60. assert submission_2._submission_status == SubmissionStatus.COMPLETED
  61. assert submission_2._version == "version_id"
  62. class MockJob:
  63. def __init__(self, id: str, status):
  64. self.status = status
  65. self.id = id
  66. def is_failed(self):
  67. return self.status == Status.FAILED
  68. def is_canceled(self):
  69. return self.status == Status.CANCELED
  70. def is_blocked(self):
  71. return self.status == Status.BLOCKED
  72. def is_pending(self):
  73. return self.status == Status.PENDING
  74. def is_running(self):
  75. return self.status == Status.RUNNING
  76. def is_completed(self):
  77. return self.status == Status.COMPLETED
  78. def is_skipped(self):
  79. return self.status == Status.SKIPPED
  80. def is_abandoned(self):
  81. return self.status == Status.ABANDONED
  82. def is_submitted(self):
  83. return self.status == Status.SUBMITTED
  84. def __test_update_submission_status(job_ids, expected_submission_status):
  85. jobs = {
  86. "job0_submitted": MockJob("job0_submitted", Status.SUBMITTED),
  87. "job1_failed": MockJob("job1_failed", Status.FAILED),
  88. "job2_canceled": MockJob("job2_canceled", Status.CANCELED),
  89. "job3_blocked": MockJob("job3_blocked", Status.BLOCKED),
  90. "job4_pending": MockJob("job4_pending", Status.PENDING),
  91. "job5_running": MockJob("job5_running", Status.RUNNING),
  92. "job6_completed": MockJob("job6_completed", Status.COMPLETED),
  93. "job7_skipped": MockJob("job7_skipped", Status.SKIPPED),
  94. "job8_abandoned": MockJob("job8_abandoned", Status.ABANDONED),
  95. }
  96. submission = Submission("submission_id", "ENTITY_TYPE", "entity_config_id")
  97. submission.jobs = [jobs[job_id] for job_id in job_ids]
  98. for job_id in job_ids:
  99. job = jobs[job_id]
  100. submission._update_submission_status(job)
  101. assert submission.submission_status == expected_submission_status
  102. @pytest.mark.parametrize(
  103. "job_ids, expected_submission_status",
  104. [
  105. (["job1_failed"], SubmissionStatus.FAILED),
  106. (["job2_canceled"], SubmissionStatus.CANCELED),
  107. (["job3_blocked"], SubmissionStatus.BLOCKED),
  108. (["job4_pending"], SubmissionStatus.PENDING),
  109. (["job5_running"], SubmissionStatus.RUNNING),
  110. (["job6_completed"], SubmissionStatus.COMPLETED),
  111. (["job7_skipped"], SubmissionStatus.COMPLETED),
  112. (["job8_abandoned"], SubmissionStatus.UNDEFINED),
  113. ],
  114. )
  115. def test_update_single_submission_status(job_ids, expected_submission_status):
  116. __test_update_submission_status(job_ids, expected_submission_status)
  117. @pytest.mark.parametrize(
  118. "job_ids, expected_submission_status",
  119. [
  120. (["job1_failed", "job1_failed"], SubmissionStatus.FAILED),
  121. (["job1_failed", "job2_canceled"], SubmissionStatus.FAILED),
  122. (["job1_failed", "job3_blocked"], SubmissionStatus.FAILED),
  123. (["job1_failed", "job4_pending"], SubmissionStatus.FAILED),
  124. (["job1_failed", "job5_running"], SubmissionStatus.FAILED),
  125. (["job1_failed", "job6_completed"], SubmissionStatus.FAILED),
  126. (["job1_failed", "job7_skipped"], SubmissionStatus.FAILED),
  127. (["job1_failed", "job8_abandoned"], SubmissionStatus.FAILED),
  128. (["job2_canceled", "job1_failed"], SubmissionStatus.FAILED),
  129. (["job3_blocked", "job1_failed"], SubmissionStatus.FAILED),
  130. (["job4_pending", "job1_failed"], SubmissionStatus.FAILED),
  131. (["job5_running", "job1_failed"], SubmissionStatus.FAILED),
  132. (["job6_completed", "job1_failed"], SubmissionStatus.FAILED),
  133. (["job7_skipped", "job1_failed"], SubmissionStatus.FAILED),
  134. (["job8_abandoned", "job1_failed"], SubmissionStatus.FAILED),
  135. ],
  136. )
  137. def test_update_submission_status_with_one_failed_job_in_jobs(job_ids, expected_submission_status):
  138. __test_update_submission_status(job_ids, expected_submission_status)
  139. @pytest.mark.parametrize(
  140. "job_ids, expected_submission_status",
  141. [
  142. (["job2_canceled", "job2_canceled"], SubmissionStatus.CANCELED),
  143. (["job2_canceled", "job3_blocked"], SubmissionStatus.CANCELED),
  144. (["job2_canceled", "job4_pending"], SubmissionStatus.CANCELED),
  145. (["job2_canceled", "job5_running"], SubmissionStatus.CANCELED),
  146. (["job2_canceled", "job6_completed"], SubmissionStatus.CANCELED),
  147. (["job2_canceled", "job7_skipped"], SubmissionStatus.CANCELED),
  148. (["job2_canceled", "job8_abandoned"], SubmissionStatus.CANCELED),
  149. (["job3_blocked", "job2_canceled"], SubmissionStatus.CANCELED),
  150. (["job4_pending", "job2_canceled"], SubmissionStatus.CANCELED),
  151. (["job5_running", "job2_canceled"], SubmissionStatus.CANCELED),
  152. (["job6_completed", "job2_canceled"], SubmissionStatus.CANCELED),
  153. (["job7_skipped", "job2_canceled"], SubmissionStatus.CANCELED),
  154. (["job8_abandoned", "job2_canceled"], SubmissionStatus.CANCELED),
  155. ],
  156. )
  157. def test_update_submission_status_with_one_canceled_job_in_jobs(job_ids, expected_submission_status):
  158. __test_update_submission_status(job_ids, expected_submission_status)
  159. @pytest.mark.parametrize(
  160. "job_ids, expected_submission_status",
  161. [
  162. (["job4_pending", "job3_blocked"], SubmissionStatus.PENDING),
  163. (["job4_pending", "job4_pending"], SubmissionStatus.PENDING),
  164. (["job4_pending", "job6_completed"], SubmissionStatus.PENDING),
  165. (["job4_pending", "job7_skipped"], SubmissionStatus.PENDING),
  166. (["job3_blocked", "job4_pending"], SubmissionStatus.PENDING),
  167. (["job6_completed", "job4_pending"], SubmissionStatus.PENDING),
  168. (["job7_skipped", "job4_pending"], SubmissionStatus.PENDING),
  169. ],
  170. )
  171. def test_update_submission_status_with_no_failed_or_cancel_one_pending_in_jobs(job_ids, expected_submission_status):
  172. __test_update_submission_status(job_ids, expected_submission_status)
  173. @pytest.mark.parametrize(
  174. "job_ids, expected_submission_status",
  175. [
  176. (["job5_running", "job3_blocked"], SubmissionStatus.RUNNING),
  177. (["job5_running", "job4_pending"], SubmissionStatus.RUNNING),
  178. (["job5_running", "job5_running"], SubmissionStatus.RUNNING),
  179. (["job5_running", "job6_completed"], SubmissionStatus.RUNNING),
  180. (["job5_running", "job7_skipped"], SubmissionStatus.RUNNING),
  181. (["job3_blocked", "job5_running"], SubmissionStatus.RUNNING),
  182. (["job4_pending", "job5_running"], SubmissionStatus.RUNNING),
  183. (["job6_completed", "job5_running"], SubmissionStatus.RUNNING),
  184. (["job7_skipped", "job5_running"], SubmissionStatus.RUNNING),
  185. ],
  186. )
  187. def test_update_submission_status_with_no_failed_cancel_nor_pending_one_running_in_jobs(
  188. job_ids, expected_submission_status
  189. ):
  190. __test_update_submission_status(job_ids, expected_submission_status)
  191. @pytest.mark.parametrize(
  192. "job_ids, expected_submission_status",
  193. [
  194. (["job3_blocked", "job3_blocked"], SubmissionStatus.BLOCKED),
  195. (["job3_blocked", "job6_completed"], SubmissionStatus.BLOCKED),
  196. (["job3_blocked", "job7_skipped"], SubmissionStatus.BLOCKED),
  197. (["job6_completed", "job3_blocked"], SubmissionStatus.BLOCKED),
  198. (["job7_skipped", "job3_blocked"], SubmissionStatus.BLOCKED),
  199. ],
  200. )
  201. def test_update_submission_status_with_no_failed_cancel_pending_nor_running_one_blocked_in_jobs(
  202. job_ids, expected_submission_status
  203. ):
  204. __test_update_submission_status(job_ids, expected_submission_status)
  205. @pytest.mark.parametrize(
  206. "job_ids, expected_submission_status",
  207. [
  208. (["job6_completed", "job6_completed"], SubmissionStatus.COMPLETED),
  209. (["job6_completed", "job7_skipped"], SubmissionStatus.COMPLETED),
  210. (["job7_skipped", "job6_completed"], SubmissionStatus.COMPLETED),
  211. (["job7_skipped", "job7_skipped"], SubmissionStatus.COMPLETED),
  212. ],
  213. )
  214. def test_update_submission_status_with_only_completed_or_skipped_in_jobs(job_ids, expected_submission_status):
  215. __test_update_submission_status(job_ids, expected_submission_status)
  216. @pytest.mark.parametrize(
  217. "job_ids, expected_submission_status",
  218. [
  219. (["job3_blocked", "job8_abandoned"], SubmissionStatus.UNDEFINED),
  220. (["job4_pending", "job8_abandoned"], SubmissionStatus.UNDEFINED),
  221. (["job5_running", "job8_abandoned"], SubmissionStatus.UNDEFINED),
  222. (["job6_completed", "job8_abandoned"], SubmissionStatus.UNDEFINED),
  223. (["job7_skipped", "job8_abandoned"], SubmissionStatus.UNDEFINED),
  224. (["job8_abandoned", "job8_abandoned"], SubmissionStatus.UNDEFINED),
  225. (["job8_abandoned", "job3_blocked"], SubmissionStatus.UNDEFINED),
  226. (["job8_abandoned", "job4_pending"], SubmissionStatus.UNDEFINED),
  227. (["job8_abandoned", "job5_running"], SubmissionStatus.UNDEFINED),
  228. (["job8_abandoned", "job6_completed"], SubmissionStatus.UNDEFINED),
  229. (["job8_abandoned", "job7_skipped"], SubmissionStatus.UNDEFINED),
  230. ],
  231. )
  232. def test_update_submission_status_with_wrong_case_abandoned_without_cancel_or_failed_in_jobs(
  233. job_ids, expected_submission_status
  234. ):
  235. __test_update_submission_status(job_ids, expected_submission_status)
  236. def test_auto_set_and_reload():
  237. task = Task(config_id="name_1", properties={}, function=print, id=TaskId("task_1"))
  238. submission_1 = Submission(task.id, task._ID_PREFIX, task.config_id, properties={})
  239. job_1 = Job("job_1", task, submission_1.id, submission_1.entity_id)
  240. job_2 = Job("job_2", task, submission_1.id, submission_1.entity_id)
  241. _TaskManagerFactory._build_manager()._set(task)
  242. _SubmissionManagerFactory._build_manager()._set(submission_1)
  243. _JobManagerFactory._build_manager()._set(job_1)
  244. _JobManagerFactory._build_manager()._set(job_2)
  245. submission_2 = _SubmissionManagerFactory._build_manager()._get(submission_1)
  246. assert submission_1.id == submission_2.id
  247. assert submission_1.entity_id == submission_2.entity_id
  248. assert submission_1.creation_date == submission_2.creation_date
  249. assert submission_1.submission_status == submission_2.submission_status
  250. # auto set & reload on jobs attribute
  251. assert submission_1.jobs == []
  252. assert submission_2.jobs == []
  253. submission_1.jobs = [job_1]
  254. assert submission_1.jobs == [job_1]
  255. assert submission_2.jobs == [job_1]
  256. submission_2.jobs = [job_2]
  257. assert submission_1.jobs == [job_2]
  258. assert submission_2.jobs == [job_2]
  259. submission_1.jobs = [job_1, job_2]
  260. assert submission_1.jobs == [job_1, job_2]
  261. assert submission_2.jobs == [job_1, job_2]
  262. submission_2.jobs = [job_2, job_1]
  263. assert submission_1.jobs == [job_2, job_1]
  264. assert submission_2.jobs == [job_2, job_1]
  265. # auto set & reload on is_canceled attribute
  266. assert not submission_1.is_canceled
  267. assert not submission_2.is_canceled
  268. submission_1.is_canceled = True
  269. assert submission_1.is_canceled
  270. assert submission_2.is_canceled
  271. submission_2.is_canceled = False
  272. assert not submission_1.is_canceled
  273. assert not submission_2.is_canceled
  274. # auto set & reload on is_completed attribute
  275. assert not submission_1.is_completed
  276. assert not submission_2.is_completed
  277. submission_1.is_completed = True
  278. assert submission_1.is_completed
  279. assert submission_2.is_completed
  280. submission_2.is_completed = False
  281. assert not submission_1.is_completed
  282. assert not submission_2.is_completed
  283. # auto set & reload on is_abandoned attribute
  284. assert not submission_1.is_abandoned
  285. assert not submission_2.is_abandoned
  286. submission_1.is_abandoned = True
  287. assert submission_1.is_abandoned
  288. assert submission_2.is_abandoned
  289. submission_2.is_abandoned = False
  290. assert not submission_1.is_abandoned
  291. assert not submission_2.is_abandoned
  292. # auto set & reload on submission_status attribute
  293. assert submission_1.submission_status == SubmissionStatus.SUBMITTED
  294. assert submission_2.submission_status == SubmissionStatus.SUBMITTED
  295. submission_1.submission_status = SubmissionStatus.BLOCKED
  296. assert submission_1.submission_status == SubmissionStatus.BLOCKED
  297. assert submission_2.submission_status == SubmissionStatus.BLOCKED
  298. submission_2.submission_status = SubmissionStatus.COMPLETED
  299. assert submission_1.submission_status == SubmissionStatus.COMPLETED
  300. assert submission_2.submission_status == SubmissionStatus.COMPLETED
  301. with submission_1 as submission:
  302. assert submission.jobs == [job_2, job_1]
  303. assert submission.submission_status == SubmissionStatus.COMPLETED
  304. submission.jobs = [job_1]
  305. submission.submission_status = SubmissionStatus.PENDING
  306. assert submission.jobs == [job_2, job_1]
  307. assert submission.submission_status == SubmissionStatus.COMPLETED
  308. assert submission_1.jobs == [job_1]
  309. assert submission_1.submission_status == SubmissionStatus.PENDING
  310. assert submission_2.jobs == [job_1]
  311. assert submission_2.submission_status == SubmissionStatus.PENDING
  312. def test_auto_set_and_reload_properties():
  313. task = Task(config_id="name_1", properties={}, function=print, id=TaskId("task_1"))
  314. submission_1 = Submission(task.id, task._ID_PREFIX, task.config_id, properties={})
  315. _TaskManagerFactory._build_manager()._set(task)
  316. _SubmissionManagerFactory._build_manager()._set(submission_1)
  317. submission_2 = _SubmissionManagerFactory._build_manager()._get(submission_1)
  318. # auto set & reload on properties attribute
  319. assert submission_1.properties == {}
  320. assert submission_2.properties == {}
  321. submission_1._properties["qux"] = 4
  322. assert submission_1.properties["qux"] == 4
  323. assert submission_2.properties["qux"] == 4
  324. assert submission_1.properties == {"qux": 4}
  325. assert submission_2.properties == {"qux": 4}
  326. submission_2._properties["qux"] = 5
  327. assert submission_1.properties["qux"] == 5
  328. assert submission_2.properties["qux"] == 5
  329. submission_1.properties["temp_key_1"] = "temp_value_1"
  330. submission_1.properties["temp_key_2"] = "temp_value_2"
  331. assert submission_1.properties == {"qux": 5, "temp_key_1": "temp_value_1", "temp_key_2": "temp_value_2"}
  332. assert submission_2.properties == {"qux": 5, "temp_key_1": "temp_value_1", "temp_key_2": "temp_value_2"}
  333. submission_1.properties.pop("temp_key_1")
  334. assert "temp_key_1" not in submission_1.properties.keys()
  335. assert "temp_key_1" not in submission_1.properties.keys()
  336. assert submission_1.properties == {"qux": 5, "temp_key_2": "temp_value_2"}
  337. assert submission_2.properties == {"qux": 5, "temp_key_2": "temp_value_2"}
  338. submission_2.properties.pop("temp_key_2")
  339. assert submission_1.properties == {"qux": 5}
  340. assert submission_2.properties == {"qux": 5}
  341. assert "temp_key_2" not in submission_1.properties.keys()
  342. assert "temp_key_2" not in submission_2.properties.keys()
  343. submission_1.properties["temp_key_3"] = 0
  344. assert submission_1.properties == {"qux": 5, "temp_key_3": 0}
  345. assert submission_2.properties == {"qux": 5, "temp_key_3": 0}
  346. submission_1.properties.update({"temp_key_3": 1})
  347. assert submission_1.properties == {"qux": 5, "temp_key_3": 1}
  348. assert submission_2.properties == {"qux": 5, "temp_key_3": 1}
  349. submission_1.properties.update({})
  350. assert submission_1.properties == {"qux": 5, "temp_key_3": 1}
  351. assert submission_2.properties == {"qux": 5, "temp_key_3": 1}
  352. submission_1.properties["temp_key_4"] = 0
  353. submission_1.properties["temp_key_5"] = 0
  354. with submission_1 as submission:
  355. assert submission.properties["qux"] == 5
  356. assert submission.properties["temp_key_3"] == 1
  357. assert submission.properties["temp_key_4"] == 0
  358. assert submission.properties["temp_key_5"] == 0
  359. submission.properties["qux"] = 9
  360. submission.properties.pop("temp_key_3")
  361. submission.properties.pop("temp_key_4")
  362. submission.properties.update({"temp_key_4": 1})
  363. submission.properties.update({"temp_key_5": 2})
  364. submission.properties.pop("temp_key_5")
  365. submission.properties.update({})
  366. assert submission.properties["qux"] == 5
  367. assert submission.properties["temp_key_3"] == 1
  368. assert submission.properties["temp_key_4"] == 0
  369. assert submission.properties["temp_key_5"] == 0
  370. assert submission_1.properties["qux"] == 9
  371. assert "temp_key_3" not in submission_1.properties.keys()
  372. assert submission_1.properties["temp_key_4"] == 1
  373. assert "temp_key_5" not in submission_1.properties.keys()
  374. @pytest.mark.parametrize(
  375. "job_statuses, expected_submission_statuses",
  376. [
  377. (
  378. [Status.SUBMITTED, Status.PENDING, Status.RUNNING, Status.COMPLETED],
  379. [SubmissionStatus.PENDING, SubmissionStatus.PENDING, SubmissionStatus.RUNNING, SubmissionStatus.COMPLETED],
  380. ),
  381. (
  382. [Status.SUBMITTED, Status.PENDING, Status.RUNNING, Status.SKIPPED],
  383. [SubmissionStatus.PENDING, SubmissionStatus.PENDING, SubmissionStatus.RUNNING, SubmissionStatus.COMPLETED],
  384. ),
  385. (
  386. [Status.SUBMITTED, Status.PENDING, Status.RUNNING, Status.FAILED],
  387. [SubmissionStatus.PENDING, SubmissionStatus.PENDING, SubmissionStatus.RUNNING, SubmissionStatus.FAILED],
  388. ),
  389. (
  390. [Status.SUBMITTED, Status.PENDING, Status.CANCELED],
  391. [SubmissionStatus.PENDING, SubmissionStatus.PENDING, SubmissionStatus.CANCELED],
  392. ),
  393. (
  394. [Status.SUBMITTED, Status.PENDING, Status.RUNNING, Status.CANCELED],
  395. [SubmissionStatus.PENDING, SubmissionStatus.PENDING, SubmissionStatus.RUNNING, SubmissionStatus.CANCELED],
  396. ),
  397. ([Status.SUBMITTED, Status.BLOCKED], [SubmissionStatus.PENDING, SubmissionStatus.BLOCKED]),
  398. ([Status.SUBMITTED, Status.SKIPPED], [SubmissionStatus.PENDING, SubmissionStatus.COMPLETED]),
  399. ],
  400. )
  401. def test_update_submission_status_with_single_job_completed(job_statuses, expected_submission_statuses):
  402. job = MockJob("job_id", Status.SUBMITTED)
  403. submission = Submission("submission_id", "ENTITY_TYPE", "entity_config_id")
  404. _SubmissionManagerFactory._build_manager()._set(submission)
  405. assert submission.submission_status == SubmissionStatus.SUBMITTED
  406. for job_status, submission_status in zip(job_statuses, expected_submission_statuses):
  407. job.status = job_status
  408. submission._update_submission_status(job)
  409. assert submission.submission_status == submission_status
  410. def __test_update_submission_status_with_two_jobs(job_ids, job_statuses, expected_submission_statuses):
  411. jobs = {job_id: MockJob(job_id, Status.SUBMITTED) for job_id in job_ids}
  412. submission = Submission("submission_id", "ENTITY_TYPE", "entity_config_id")
  413. _SubmissionManagerFactory._build_manager()._set(submission)
  414. assert submission.submission_status == SubmissionStatus.SUBMITTED
  415. for (job_id, job_status), submission_status in zip(job_statuses, expected_submission_statuses):
  416. job = jobs[job_id]
  417. job.status = job_status
  418. submission._update_submission_status(job)
  419. assert submission.submission_status == submission_status
  420. @pytest.mark.parametrize(
  421. "job_ids, job_statuses, expected_submission_statuses",
  422. [
  423. (
  424. ["job_1", "job_2"],
  425. [
  426. ("job_1", Status.SUBMITTED),
  427. ("job_2", Status.SUBMITTED),
  428. ("job_1", Status.PENDING),
  429. ("job_2", Status.PENDING),
  430. ("job_1", Status.RUNNING),
  431. ("job_2", Status.RUNNING),
  432. ("job_1", Status.COMPLETED),
  433. ("job_2", Status.COMPLETED),
  434. ],
  435. [
  436. SubmissionStatus.PENDING,
  437. SubmissionStatus.PENDING,
  438. SubmissionStatus.PENDING,
  439. SubmissionStatus.PENDING,
  440. SubmissionStatus.RUNNING,
  441. SubmissionStatus.RUNNING,
  442. SubmissionStatus.RUNNING,
  443. SubmissionStatus.COMPLETED,
  444. ],
  445. ),
  446. (
  447. ["job_1", "job_2"],
  448. [
  449. ("job_1", Status.SUBMITTED),
  450. ("job_2", Status.SUBMITTED),
  451. ("job_1", Status.PENDING),
  452. ("job_1", Status.RUNNING),
  453. ("job_2", Status.PENDING),
  454. ("job_2", Status.RUNNING),
  455. ("job_1", Status.COMPLETED),
  456. ("job_2", Status.COMPLETED),
  457. ],
  458. [
  459. SubmissionStatus.PENDING,
  460. SubmissionStatus.PENDING,
  461. SubmissionStatus.PENDING,
  462. SubmissionStatus.RUNNING,
  463. SubmissionStatus.RUNNING,
  464. SubmissionStatus.RUNNING,
  465. SubmissionStatus.RUNNING,
  466. SubmissionStatus.COMPLETED,
  467. ],
  468. ),
  469. (
  470. ["job_1", "job_2"],
  471. [
  472. ("job_1", Status.SUBMITTED),
  473. ("job_2", Status.SUBMITTED),
  474. ("job_1", Status.BLOCKED),
  475. ("job_2", Status.PENDING),
  476. ("job_2", Status.RUNNING),
  477. ("job_2", Status.COMPLETED),
  478. ("job_1", Status.PENDING),
  479. ("job_1", Status.RUNNING),
  480. ("job_1", Status.COMPLETED),
  481. ],
  482. [
  483. SubmissionStatus.PENDING,
  484. SubmissionStatus.PENDING,
  485. SubmissionStatus.PENDING,
  486. SubmissionStatus.PENDING,
  487. SubmissionStatus.RUNNING,
  488. SubmissionStatus.BLOCKED,
  489. SubmissionStatus.PENDING,
  490. SubmissionStatus.RUNNING,
  491. SubmissionStatus.COMPLETED,
  492. ],
  493. ),
  494. ],
  495. )
  496. def test_update_submission_status_with_two_jobs_completed(job_ids, job_statuses, expected_submission_statuses):
  497. __test_update_submission_status_with_two_jobs(job_ids, job_statuses, expected_submission_statuses)
  498. @pytest.mark.parametrize(
  499. "job_ids, job_statuses, expected_submission_statuses",
  500. [
  501. (
  502. ["job_1", "job_2"],
  503. [
  504. ("job_1", Status.SUBMITTED),
  505. ("job_2", Status.SUBMITTED),
  506. ("job_1", Status.PENDING),
  507. ("job_2", Status.PENDING),
  508. ("job_1", Status.RUNNING),
  509. ("job_2", Status.SKIPPED),
  510. ("job_1", Status.COMPLETED),
  511. ],
  512. [
  513. SubmissionStatus.PENDING,
  514. SubmissionStatus.PENDING,
  515. SubmissionStatus.PENDING,
  516. SubmissionStatus.PENDING,
  517. SubmissionStatus.RUNNING,
  518. SubmissionStatus.RUNNING,
  519. SubmissionStatus.COMPLETED,
  520. ],
  521. ),
  522. (
  523. ["job_1", "job_2"],
  524. [
  525. ("job_1", Status.SUBMITTED),
  526. ("job_2", Status.SUBMITTED),
  527. ("job_1", Status.PENDING),
  528. ("job_1", Status.RUNNING),
  529. ("job_2", Status.PENDING),
  530. ("job_2", Status.SKIPPED),
  531. ("job_1", Status.COMPLETED),
  532. ],
  533. [
  534. SubmissionStatus.PENDING,
  535. SubmissionStatus.PENDING,
  536. SubmissionStatus.PENDING,
  537. SubmissionStatus.RUNNING,
  538. SubmissionStatus.RUNNING,
  539. SubmissionStatus.RUNNING,
  540. SubmissionStatus.COMPLETED,
  541. ],
  542. ),
  543. (
  544. ["job_1", "job_2"],
  545. [
  546. ("job_1", Status.SUBMITTED),
  547. ("job_2", Status.SUBMITTED),
  548. ("job_1", Status.BLOCKED),
  549. ("job_2", Status.PENDING),
  550. ("job_2", Status.RUNNING),
  551. ("job_2", Status.COMPLETED),
  552. ("job_1", Status.PENDING),
  553. ("job_1", Status.SKIPPED),
  554. ],
  555. [
  556. SubmissionStatus.PENDING,
  557. SubmissionStatus.PENDING,
  558. SubmissionStatus.PENDING,
  559. SubmissionStatus.PENDING,
  560. SubmissionStatus.RUNNING,
  561. SubmissionStatus.BLOCKED,
  562. SubmissionStatus.PENDING,
  563. SubmissionStatus.COMPLETED,
  564. ],
  565. ),
  566. (
  567. ["job_1", "job_2"],
  568. [
  569. ("job_1", Status.SUBMITTED),
  570. ("job_2", Status.SUBMITTED),
  571. ("job_1", Status.PENDING),
  572. ("job_2", Status.PENDING),
  573. ("job_1", Status.SKIPPED),
  574. ("job_2", Status.SKIPPED),
  575. ],
  576. [
  577. SubmissionStatus.PENDING,
  578. SubmissionStatus.PENDING,
  579. SubmissionStatus.PENDING,
  580. SubmissionStatus.PENDING,
  581. SubmissionStatus.PENDING,
  582. SubmissionStatus.COMPLETED,
  583. ],
  584. ),
  585. (
  586. ["job_1", "job_2"],
  587. [
  588. ("job_1", Status.SUBMITTED),
  589. ("job_2", Status.SUBMITTED),
  590. ("job_1", Status.PENDING),
  591. ("job_1", Status.SKIPPED),
  592. ("job_2", Status.PENDING),
  593. ("job_2", Status.SKIPPED),
  594. ],
  595. [
  596. SubmissionStatus.PENDING,
  597. SubmissionStatus.PENDING,
  598. SubmissionStatus.PENDING,
  599. SubmissionStatus.PENDING,
  600. SubmissionStatus.PENDING,
  601. SubmissionStatus.COMPLETED,
  602. ],
  603. ),
  604. (
  605. ["job_1", "job_2"],
  606. [
  607. ("job_1", Status.SUBMITTED),
  608. ("job_2", Status.SUBMITTED),
  609. ("job_1", Status.BLOCKED),
  610. ("job_2", Status.PENDING),
  611. ("job_2", Status.SKIPPED),
  612. ("job_1", Status.PENDING),
  613. ("job_1", Status.SKIPPED),
  614. ],
  615. [
  616. SubmissionStatus.PENDING,
  617. SubmissionStatus.PENDING,
  618. SubmissionStatus.PENDING,
  619. SubmissionStatus.PENDING,
  620. SubmissionStatus.BLOCKED,
  621. SubmissionStatus.PENDING,
  622. SubmissionStatus.COMPLETED,
  623. ],
  624. ),
  625. ],
  626. )
  627. def test_update_submission_status_with_two_jobs_skipped(job_ids, job_statuses, expected_submission_statuses):
  628. __test_update_submission_status_with_two_jobs(job_ids, job_statuses, expected_submission_statuses)
  629. @pytest.mark.parametrize(
  630. "job_ids, job_statuses, expected_submission_statuses",
  631. [
  632. (
  633. ["job_1", "job_2"],
  634. [
  635. ("job_1", Status.SUBMITTED),
  636. ("job_2", Status.SUBMITTED),
  637. ("job_1", Status.PENDING),
  638. ("job_2", Status.PENDING),
  639. ("job_1", Status.RUNNING),
  640. ("job_2", Status.RUNNING),
  641. ("job_1", Status.FAILED),
  642. ("job_2", Status.COMPLETED),
  643. ],
  644. [
  645. SubmissionStatus.PENDING,
  646. SubmissionStatus.PENDING,
  647. SubmissionStatus.PENDING,
  648. SubmissionStatus.PENDING,
  649. SubmissionStatus.RUNNING,
  650. SubmissionStatus.RUNNING,
  651. SubmissionStatus.FAILED,
  652. SubmissionStatus.FAILED,
  653. ],
  654. ),
  655. (
  656. ["job_1", "job_2"],
  657. [
  658. ("job_1", Status.SUBMITTED),
  659. ("job_2", Status.SUBMITTED),
  660. ("job_1", Status.PENDING),
  661. ("job_1", Status.RUNNING),
  662. ("job_2", Status.PENDING),
  663. ("job_2", Status.RUNNING),
  664. ("job_1", Status.COMPLETED),
  665. ("job_2", Status.FAILED),
  666. ],
  667. [
  668. SubmissionStatus.PENDING,
  669. SubmissionStatus.PENDING,
  670. SubmissionStatus.PENDING,
  671. SubmissionStatus.RUNNING,
  672. SubmissionStatus.RUNNING,
  673. SubmissionStatus.RUNNING,
  674. SubmissionStatus.RUNNING,
  675. SubmissionStatus.FAILED,
  676. ],
  677. ),
  678. (
  679. ["job_1", "job_2"],
  680. [
  681. ("job_1", Status.SUBMITTED),
  682. ("job_2", Status.SUBMITTED),
  683. ("job_1", Status.BLOCKED),
  684. ("job_2", Status.PENDING),
  685. ("job_2", Status.RUNNING),
  686. ("job_2", Status.FAILED),
  687. ("job_1", Status.ABANDONED),
  688. ],
  689. [
  690. SubmissionStatus.PENDING,
  691. SubmissionStatus.PENDING,
  692. SubmissionStatus.PENDING,
  693. SubmissionStatus.PENDING,
  694. SubmissionStatus.RUNNING,
  695. SubmissionStatus.FAILED,
  696. SubmissionStatus.FAILED,
  697. ],
  698. ),
  699. ],
  700. )
  701. def test_update_submission_status_with_two_jobs_failed(job_ids, job_statuses, expected_submission_statuses):
  702. __test_update_submission_status_with_two_jobs(job_ids, job_statuses, expected_submission_statuses)
  703. @pytest.mark.parametrize(
  704. "job_ids, job_statuses, expected_submission_statuses",
  705. [
  706. (
  707. ["job_1", "job_2"],
  708. [
  709. ("job_1", Status.SUBMITTED),
  710. ("job_2", Status.SUBMITTED),
  711. ("job_1", Status.PENDING),
  712. ("job_2", Status.PENDING),
  713. ("job_1", Status.RUNNING),
  714. ("job_2", Status.RUNNING),
  715. ("job_1", Status.CANCELED),
  716. ("job_2", Status.COMPLETED),
  717. ],
  718. [
  719. SubmissionStatus.PENDING,
  720. SubmissionStatus.PENDING,
  721. SubmissionStatus.PENDING,
  722. SubmissionStatus.PENDING,
  723. SubmissionStatus.RUNNING,
  724. SubmissionStatus.RUNNING,
  725. SubmissionStatus.CANCELED,
  726. SubmissionStatus.CANCELED,
  727. ],
  728. ),
  729. (
  730. ["job_1", "job_2"],
  731. [
  732. ("job_1", Status.SUBMITTED),
  733. ("job_2", Status.SUBMITTED),
  734. ("job_1", Status.PENDING),
  735. ("job_1", Status.RUNNING),
  736. ("job_2", Status.PENDING),
  737. ("job_2", Status.RUNNING),
  738. ("job_1", Status.COMPLETED),
  739. ("job_2", Status.CANCELED),
  740. ],
  741. [
  742. SubmissionStatus.PENDING,
  743. SubmissionStatus.PENDING,
  744. SubmissionStatus.PENDING,
  745. SubmissionStatus.RUNNING,
  746. SubmissionStatus.RUNNING,
  747. SubmissionStatus.RUNNING,
  748. SubmissionStatus.RUNNING,
  749. SubmissionStatus.CANCELED,
  750. ],
  751. ),
  752. (
  753. ["job_1", "job_2"],
  754. [
  755. ("job_1", Status.SUBMITTED),
  756. ("job_2", Status.SUBMITTED),
  757. ("job_1", Status.BLOCKED),
  758. ("job_2", Status.PENDING),
  759. ("job_2", Status.RUNNING),
  760. ("job_2", Status.CANCELED),
  761. ("job_1", Status.ABANDONED),
  762. ],
  763. [
  764. SubmissionStatus.PENDING,
  765. SubmissionStatus.PENDING,
  766. SubmissionStatus.PENDING,
  767. SubmissionStatus.PENDING,
  768. SubmissionStatus.RUNNING,
  769. SubmissionStatus.CANCELED,
  770. SubmissionStatus.CANCELED,
  771. ],
  772. ),
  773. ],
  774. )
  775. def test_update_submission_status_with_two_jobs_canceled(job_ids, job_statuses, expected_submission_statuses):
  776. __test_update_submission_status_with_two_jobs(job_ids, job_statuses, expected_submission_statuses)
  777. def test_is_finished():
  778. submission_manager = _SubmissionManagerFactory._build_manager()
  779. submission = Submission("entity_id", "entity_type", "entity_config_id", "submission_id")
  780. submission_manager._set(submission)
  781. assert len(submission_manager._get_all()) == 1
  782. assert submission._submission_status == SubmissionStatus.SUBMITTED
  783. assert not submission.is_finished()
  784. submission.submission_status = SubmissionStatus.UNDEFINED
  785. assert submission.submission_status == SubmissionStatus.UNDEFINED
  786. assert not submission.is_finished()
  787. submission.submission_status = SubmissionStatus.CANCELED
  788. assert submission.submission_status == SubmissionStatus.CANCELED
  789. assert submission.is_finished()
  790. submission.submission_status = SubmissionStatus.FAILED
  791. assert submission.submission_status == SubmissionStatus.FAILED
  792. assert submission.is_finished()
  793. submission.submission_status = SubmissionStatus.BLOCKED
  794. assert submission.submission_status == SubmissionStatus.BLOCKED
  795. assert not submission.is_finished()
  796. submission.submission_status = SubmissionStatus.RUNNING
  797. assert submission.submission_status == SubmissionStatus.RUNNING
  798. assert not submission.is_finished()
  799. submission.submission_status = SubmissionStatus.PENDING
  800. assert submission.submission_status == SubmissionStatus.PENDING
  801. assert not submission.is_finished()
  802. submission.submission_status = SubmissionStatus.COMPLETED
  803. assert submission.submission_status == SubmissionStatus.COMPLETED
  804. assert submission.is_finished()