22
33namespace App \Tests \Unit \Service ;
44
5+ use App \Entity \Contest ;
6+ use App \Entity \JudgeTask ;
7+ use App \Entity \Judging ;
8+ use App \Entity \JudgingRun ;
9+ use App \Entity \Problem ;
10+ use App \Entity \Submission ;
11+ use App \Entity \SubmissionSource ;
12+ use App \Entity \Team ;
513use App \Service \DOMJudgeService ;
6- use Symfony \Bundle \FrameworkBundle \Test \KernelTestCase ;
14+ use App \Service \SubmissionService ;
15+ use App \Tests \Unit \BaseTestCase ;
16+ use Doctrine \ORM \EntityManagerInterface ;
717use Symfony \Component \Filesystem \Filesystem ;
18+ use Symfony \Component \HttpFoundation \File \UploadedFile ;
819
9- class DOMJudgeServiceTest extends KernelTestCase
20+ class DOMJudgeServiceTest extends BaseTestCase
1021{
1122 private const ASSET_PATH = 'test-assets ' ;
1223
@@ -15,7 +26,7 @@ class DOMJudgeServiceTest extends KernelTestCase
1526
1627 protected function setUp (): void
1728 {
18- self :: bootKernel ();
29+ parent :: setUp ();
1930 $ this ->dj = static ::getContainer ()->get (DOMJudgeService::class);
2031 $ this ->assetDir = static ::getContainer ()->getParameter ('kernel.project_dir ' ) . '/public/ ' . self ::ASSET_PATH ;
2132 (new Filesystem ())->mkdir ($ this ->assetDir );
@@ -36,4 +47,65 @@ public function testGetAssetFilesMatchesOnTheExtensionOnly(): void
3647 self ::assertSame (['also-ok.css ' , 'ok.css ' ], $ this ->dj ->getAssetFiles (self ::ASSET_PATH , ['css ' ]));
3748 self ::assertSame (['image.png ' , 'script.js ' ], $ this ->dj ->getAssetFiles (self ::ASSET_PATH , ['png ' , 'js ' ]));
3849 }
50+
51+ private function em (): EntityManagerInterface
52+ {
53+ return static ::getContainer ()->get (EntityManagerInterface::class);
54+ }
55+
56+ private function addSubmission (): Submission
57+ {
58+ $ em = $ this ->em ();
59+
60+ $ message = null ;
61+ return static ::getContainer ()->get (SubmissionService::class)->submitSolution (
62+ $ em ->getRepository (Team::class)->findOneBy (['name ' => 'DOMjudge ' ]),
63+ null ,
64+ $ em ->getRepository (Problem::class)->findOneBy (['externalid ' => 'hello ' ]),
65+ $ em ->getRepository (Contest::class)->findOneBy (['shortname ' => 'demo ' ]),
66+ 'c ' ,
67+ [new UploadedFile (__FILE__ , 'foo.c ' , null , null , true )],
68+ SubmissionSource::UNKNOWN , null , null , null , null , null , $ message
69+ );
70+ }
71+
72+ /**
73+ * Judge tasks are created for a judging exactly once.
74+ *
75+ * unblockJudgeTasks() looks for judgings that have no judge tasks yet, so two callers
76+ * running at the same time - enabling a language and a problem, say - would both pass that
77+ * check. Creating a second set would violate the unique key on judging_run and leave judge
78+ * tasks behind that no judging run points at, which judgehosts then choke on.
79+ */
80+ public function testJudgeTasksAreCreatedOnlyOncePerJudging (): void
81+ {
82+ $ this ->logIn ();
83+
84+ $ submission = $ this ->addSubmission ();
85+ $ judgingId = $ submission ->getJudgings ()->first ()->getJudgingid ();
86+
87+ $ em = $ this ->em ();
88+ $ judgeTasksAfterFirst = (int )$ em ->getConnection ()->fetchOne (
89+ 'SELECT COUNT(*) FROM judgetask WHERE jobid = ? ' ,
90+ [$ judgingId ]
91+ );
92+ self ::assertGreaterThan (0 , $ judgeTasksAfterFirst , 'submitting must create judge tasks ' );
93+
94+ // A second attempt for the same judging must be a no-op rather than an error.
95+ $ judging = $ em ->getRepository (Judging::class)->find ($ judgingId );
96+ $ this ->dj ->maybeCreateJudgeTasks ($ judging );
97+
98+ self ::assertSame (
99+ $ judgeTasksAfterFirst ,
100+ (int )$ em ->getConnection ()->fetchOne ('SELECT COUNT(*) FROM judgetask WHERE jobid = ? ' , [$ judgingId ]),
101+ 'no extra judge tasks may be created '
102+ );
103+
104+ // Every judge task still has exactly one judging run, which is what judgehosts rely on.
105+ $ tasks = $ em ->getRepository (JudgeTask::class)->findBy (['jobid ' => $ judgingId ]);
106+ foreach ($ tasks as $ task ) {
107+ $ runs = $ em ->getRepository (JudgingRun::class)->findBy (['judgetaskid ' => $ task ->getJudgetaskid ()]);
108+ self ::assertCount (1 , $ runs , 'each judge task needs exactly one judging run ' );
109+ }
110+ }
39111}
0 commit comments