QueuedTaskTest::testNotBeforeOrder()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 49
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
cc 2
eloc 29
c 5
b 0
f 0
nc 2
nop 0
dl 0
loc 49
rs 9.456
1
<?php
2
App::uses('QueuedTask', 'Queue.Model');
3
4
/**
5
 * QueuedTask Test.
6
 *
7
 * @property Queue.QueuedTask $QueuedTask
8
 */
0 ignored issues
show
Documentation Bug introduced by
The doc comment Queue.QueuedTask at position 0 could not be parsed: Unknown type name 'Queue.QueuedTask' at position 0 in Queue.QueuedTask.
Loading history...
9
class QueuedTaskTest extends CakeTestCase {
0 ignored issues
show
Bug introduced by
The type CakeTestCase was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
11
/**
12
 * Fixtures to load.
13
 *
14
 * @var array
15
 */
16
	public $fixtures = ['plugin.queue.queued_task'];
17
18
/**
19
 * setUp method.
20
 *
21
 * @return void
22
 */
23
	public function setUp() {
24
		parent::setUp();
25
26
		$this->QueuedTask = ClassRegistry::init('Queue.QueuedTask');
0 ignored issues
show
Bug Best Practice introduced by
The property QueuedTask does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
Bug introduced by
The type ClassRegistry was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
27
	}
28
29
/**
30
 * tearDown method.
31
 *
32
 * @return void
33
 */
34
	public function tearDown() {
35
		parent::tearDown();
36
37
		unset($this->QueuedTask);
38
	}
39
40
/**
41
 * Tests `QueuedTask` object type.
42
 *
43
 * @return void
44
 */
45
	public function testQueueInstance() {
46
		$this->assertTrue(is_a($this->QueuedTask, 'QueuedTask'));
47
	}
48
49
/**
50
 * Tests the basic create and length evaluation functions.
51
 *
52
 * @return void
53
 */
54
	public function testCreateAndCount() {
55
		// At first, the queue should contain 0 items
56
		$this->assertEqual($this->QueuedTask->getLength(), 0);
57
58
		// Create a task
59
		$this->assertTrue((bool)$this->QueuedTask->createJob('test1', [
60
			'some' => 'random',
61
			'test' => 'data'
62
		]));
63
64
		// Test if queue Length is 1 now
65
		$this->assertEqual($this->QueuedTask->getLength(), 1);
66
67
		// Create some more tasks
68
		$this->assertTrue((bool)$this->QueuedTask->createJob('test2', ['some' => 'random', 'test' => 'data2']));
69
		$this->assertTrue((bool)$this->QueuedTask->createJob('test2', ['some' => 'random', 'test' => 'data3']));
70
		$this->assertTrue((bool)$this->QueuedTask->createJob('test3', ['some' => 'random', 'test' => 'data4']));
71
72
		// Overall queueLength shpould now be 4
73
		$this->assertEqual($this->QueuedTask->getLength(), 4);
74
75
		// There should be 1 task of type 'test1', one of type 'test3' and 2 of type 'test2'
76
		$this->assertEqual($this->QueuedTask->getLength('test1'), 1);
77
		$this->assertEqual($this->QueuedTask->getLength('test2'), 2);
78
		$this->assertEqual($this->QueuedTask->getLength('test3'), 1);
79
	}
80
81
/**
82
 * Tests creation and fetching of tasks.
83
 *
84
 * @return void
85
 */
86
	public function testCreateAndFetch() {
87
		// Capabilities is a list of tasks the worker can run
88
		$capabilities = [
89
			'task1' => [
90
				'name' => 'task1',
91
				'timeout' => 100,
92
				'retries' => 2
93
			]
94
		];
95
		$testData = [
96
			'x1' => 'y1',
97
			'x2' => 'y2',
98
			'x3' => 'y3',
99
			'x4' => 'y4'
100
		];
101
102
		// Start off empty
103
		$this->QueuedTask->deleteAll(['1 = 1']);
104
105
		$this->assertEqual($this->QueuedTask->find('all'), []);
106
		// At first, the queue should contain 0 items
107
		$this->assertEqual($this->QueuedTask->getLength(), 0);
108
		// There are no tasks, so we cant fetch any
109
		$this->assertFalse($this->QueuedTask->requestJob($capabilities));
110
		// Insert one task
111
		$this->assertTrue((bool)$this->QueuedTask->createJob('task1', $testData));
112
113
		// Fetch and check the first task
114
		$data = $this->QueuedTask->requestJob($capabilities);
115
		$this->assertEqual($data['id'], 5);
116
		$this->assertEqual('task1', $data['task']);
117
		$this->assertEqual($data['failed_count'], 0);
118
		$this->assertNull($data['completed']);
119
		$this->assertEqual(unserialize($data['data']), $testData);
120
121
		// After this task has been fetched, it may not be reassigned
122
		$this->assertFalse($this->QueuedTask->requestJob($capabilities));
123
124
		// Queue length is still 1 since the first task did not finish
125
		$this->assertEqual($this->QueuedTask->getLength(), 1);
126
127
		// Now mark Task 5 as done
128
		$this->assertTrue((bool)$this->QueuedTask->markJobDone(5));
129
		// Should be 0 again
130
		$this->assertEqual($this->QueuedTask->getLength(), 0);
131
	}
132
133
/**
134
 * Test the delivery of tasks in sequence, skipping fetched but not completed tasks.
135
 *
136
 * @return void
137
 */
138
	public function testSequence() {
139
		// Capabilities is a list of tasks the worker can run
140
		$capabilities = [
141
			'task1' => [
142
				'name' => 'task1',
143
				'timeout' => 100,
144
				'retries' => 2
145
			]
146
		];
147
		// At first, the queue should contain 0 items
148
		$this->assertEqual($this->QueuedTask->getLength(), 0);
149
		// Create some more tasks
150
		foreach (range(0, 9) as $num) {
151
			$this->assertTrue((bool)$this->QueuedTask->createJob('task1', [
152
				'tasknum' => $num
153
			]));
154
		}
155
		// 10 tasks in the queue
156
		$this->assertEqual($this->QueuedTask->getLength(), 10);
157
158
		// Tasks should be fetched in the original sequence
159
		foreach (range(0, 4) as $num) {
160
			$job = $this->QueuedTask->requestJob($capabilities);
161
			$jobData = unserialize($job['data']);
162
			$this->assertEqual($jobData['tasknum'], $num);
163
		}
164
		// Now mark them as done
165
		foreach (range(0, 4) as $num) {
166
			$this->assertTrue((bool)$this->QueuedTask->markJobDone($num + 5));
167
			$this->assertEqual($this->QueuedTask->getLength(), 9 - $num);
168
		}
169
170
		// Tasks should be fetched in the original sequence
171
		foreach (range(5, 9) as $num) {
172
			$job = $this->QueuedTask->requestJob($capabilities);
173
			$jobData = unserialize($job['data']);
174
			$this->assertEqual($jobData['tasknum'], $num);
175
			$this->assertTrue((bool)$this->QueuedTask->markJobDone($job['id']));
176
			$this->assertEqual($this->QueuedTask->getLength(), 9 - $num);
177
		}
178
	}
179
180
/**
181
 * Test creating Tasks to run close to a specified time, and strtotime parsing.
182
 *
183
 * @return void
184
 */
185
	public function testNotBefore() {
186
		$this->assertTrue((bool)$this->QueuedTask->createJob('task1', [], '+ 1 Min'));
187
		$this->assertTrue((bool)$this->QueuedTask->createJob('task1', [], '+ 1 Day'));
188
		$this->assertTrue((bool)$this->QueuedTask->createJob('task1', [], '2009-07-01 12:00:00'));
189
		$data = $this->QueuedTask->find('all');
190
		$this->assertEqual($data[4]['QueuedTask']['not_before'], date('Y-m-d H:i:s', strtotime('+ 1 Min')));
191
		$this->assertEqual($data[5]['QueuedTask']['not_before'], date('Y-m-d H:i:s', strtotime('+ 1 Day')));
192
		$this->assertEqual($data[6]['QueuedTask']['not_before'], '2009-07-01 12:00:00');
193
	}
194
195
/**
196
 * Test Job reordering depending on 'notBefore' field.
197
 *
198
 *  Jobs with an expired notbefore field should be executed before any other job without specific timing info.
199
 *
200
 * @return void
201
 */
202
	public function testNotBeforeOrder() {
203
		$capabilities = [
204
			'task1' => [
205
				'name' => 'task1',
206
				'timeout' => 100,
207
				'retries' => 2
208
			],
209
			'dummytask' => [
210
				'name' => 'dummytask',
211
				'timeout' => 100,
212
				'retries' => 2
213
			]
214
		];
215
		$this->assertTrue((bool)$this->QueuedTask->createJob('dummytask', []));
216
		$this->assertTrue((bool)$this->QueuedTask->createJob('dummytask', []));
217
		// Create a task with it's execution target some seconds in the past, so it should jump to the top of the list
218
		$this->assertTrue((bool)$this->QueuedTask->createJob('task1', ['three'], '- 3 Seconds'));
219
		$this->assertTrue((bool)$this->QueuedTask->createJob('task1', ['two'], '- 4 Seconds'));
220
		$this->assertTrue((bool)$this->QueuedTask->createJob('task1', ['one'], '- 5 Seconds'));
221
222
		// When usin requestJob, the jobs we just created should be delivered in this order,
223
		// NOT the order in which they where created
224
		$expected = [
225
			[
226
				'name' => 'task1',
227
				'data' => ['one']
228
			],
229
			[
230
				'name' => 'task1',
231
				'data' => ['two']
232
			],
233
			[
234
				'name' => 'task1',
235
				'data' => ['three']
236
			],
237
			[
238
				'name' => 'dummytask',
239
				'data' => []
240
			],
241
			[
242
				'name' => 'dummytask',
243
				'data' => []
244
			]
245
		];
246
247
		foreach ($expected as $item) {
248
			$tmp = $this->QueuedTask->requestJob($capabilities);
249
			$this->assertEqual($tmp['task'], $item['name']);
250
			$this->assertEqual(unserialize($tmp['data']), $item['data']);
251
		}
252
	}
253
254
/**
255
 * Tests requeueing after timeout is reached.
256
 *
257
 * @return void
258
 */
259
	public function testRequeueAfterTimeout() {
260
		$capabilities = [
261
			'task1' => [
262
				'name' => 'task1',
263
				'timeout' => 1,
264
				'retries' => 2
265
			]
266
		];
267
268
		$this->assertTrue((bool)$this->QueuedTask->createJob('task1', ['1']));
269
		$tmp = $this->QueuedTask->requestJob($capabilities);
270
		$this->assertEqual($tmp['task'], 'task1');
271
		$this->assertEqual(unserialize($tmp['data']), ['1']);
272
		$this->assertEqual($tmp['failed_count'], '0');
273
		sleep(2);
274
		$tmp = $this->QueuedTask->requestJob($capabilities);
275
		$this->assertEqual($tmp['task'], 'task1');
276
		$this->assertEqual(unserialize($tmp['data']), ['1']);
277
		$this->assertEqual($tmp['failed_count'], '1');
278
		$this->assertEqual($tmp['failure_message'], 'Restart after timeout');
279
	}
280
281
/**
282
 * Tests `QueuedTask::markJobFailed`.
283
 *
284
 * @return void
285
 */
286
	public function testMarkJobFailed() {
287
		$this->QueuedTask->createJob('dummytask', []);
288
		$id = $this->QueuedTask->id;
289
		$expected = 'Timeout: 100';
290
		$this->QueuedTask->markJobFailed($id, $expected);
291
		$result = $this->QueuedTask->field('failure_message');
292
		$this->assertEqual($result, $expected);
293
	}
294
295
}
296