loadInc(); $now = time(); // Insert an exam active now, bound to location 2 Database::exec('INSERT INTO exams (examid, lectureid, autologin, starttime, endtime, description) VALUES (1, :l, :a, :s, :e, :d)', [ 'l' => 'L-1', 'a' => 'auto1', 's' => $now - 3600, 'e' => $now + 3600, 'd' => 'Exam in A' ]); Database::exec('INSERT INTO exams_x_location (examid, locationid) VALUES (1, 2)'); // No active exam window for location 3 then $lecture = $auto = null; $this->assertFalse(Exams::isInExamMode([3], $lecture, $auto)); // Insert a global exam (NULL location) Database::exec('INSERT INTO exams (examid, lectureid, autologin, starttime, endtime, description) VALUES (2, :l, :a, :s, :e, :d)', [ 'l' => 'L-2', 'a' => 'auto2', 's' => $now - 1800, 'e' => $now + 1800, 'd' => 'Global Exam' ]); Database::exec('INSERT INTO exams_x_location (examid, locationid) VALUES (2, NULL)'); $lecture = null; $auto = null; // Specific location match $this->assertTrue(Exams::isInExamMode([2], $lecture, $auto)); $this->assertSame('L-1', $lecture); $this->assertSame('auto1', $auto); // Global match when no specific exam in list $lecture = $auto = null; $this->assertTrue(Exams::isInExamMode([999], $lecture, $auto)); $this->assertSame('L-2', $lecture); $this->assertSame('auto2', $auto); } public function testPlausiblyInExamModeFiltersByDurationAndMachines(): void { $this->loadInc(); $now = time(); // Seed one ONLINE machine in location 2 Database::exec("INSERT INTO machine (machineuuid, subnetlocationid, locationid, fixedlocationid, hostname, clientip, state) VALUES ('ex1', 2, 2, 2, 'host-ex1', '10.0.0.20', 'ONLINE')"); // Exam too long (> 1 day) but lecture bounds should limit when lecture is active -> keep Database::exec('INSERT INTO exams (examid, lectureid, autologin, starttime, endtime, description) VALUES (10, :l, :a, :s, :e, :d)', [ 'l' => 'L-keep', 's' => $now - 2 * 86400, 'e' => $now + 2 * 86400, 'd' => 'Long but bounded' ]); Database::exec('INSERT INTO exams_x_location (examid, locationid) VALUES (10, 2)'); Database::exec('INSERT INTO sat_user (userid, firstname, lastname, email) VALUES (1, "A", "B", "a@b")'); Database::exec('INSERT INTO sat_lecture (lectureid, ownerid, displayname, starttime, endtime, isexam, isenabled) VALUES (:id, 1, :n, :ls, :le, 1, 1)', [ 'id' => 'L-keep', 'n' => 'Lecture Window', 'ls' => $now - 300, 'le' => $now + 300 ]); Database::exec('INSERT INTO sat_lecture_x_location (lectureid, locationid) VALUES (:id, 2)', ['id' => 'L-keep']); // Exam too long and zero machines -> should be skipped Database::exec('INSERT INTO exams (examid, lectureid, autologin, starttime, endtime, description) VALUES (11, :l, :a, :s, :e, :d)', [ 'l' => 'L-skip', 's' => $now - 3 * 86400, 'e' => $now + 3 * 86400, 'd' => 'Long and no machines' ]); Database::exec('INSERT INTO exams_x_location (examid, locationid) VALUES (11, 5)'); Database::exec('INSERT INTO sat_lecture (lectureid, ownerid, displayname, starttime, endtime, isexam, isenabled) VALUES (:id, 1, :n, :ls, :le, 1, 1)', [ 'id' => 'L-skip', 'n' => 'Lecture Long', 'ls' => $now - 100000, 'le' => $now + 100000 ]); $out = Exams::plausiblyInExamMode(); $names = array_column($out, 'examtitle'); $this->assertContains('Long but bounded', $names); $this->assertNotContains('Long and no machines', $names); } }