summaryrefslogtreecommitdiffstats
path: root/tests/Modules/Exams/ExamsIncTest.php
blob: 1ad02f5f8ef28f01e50cca530a90d72f65cacad8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<?php

use PHPUnit\Framework\TestCase;

/**
 * Tests for modules-available/exams/inc/exams.inc.php using the SQLite-backed DB.
 *
 */
class ExamsIncTest extends TestCase
{
	protected function setUp(): void
	{
		Database::resetSchema();
	}

	private function loadInc(): void
	{
		require_once __DIR__ . '/../../../modules-available/exams/inc/exams.inc.php';
	}

	public function testIsInExamModeMatchesSpecificLocationAndGlobal(): void
	{
		$this->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);
	}
}