test_submission.py 28 KB

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