[REF] Remove handling for non-existent 'savedMapping' field
[civicrm-core.git] / tests / phpunit / CRM / Queue / QueueTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 * Ensure that various queue implementations comply with the interface
14 * @group headless
15 * @group queue
16 */
17 class CRM_Queue_QueueTest extends CiviUnitTestCase {
18
19 /* ----------------------- Queue providers ----------------------- */
20
21 /* Define a list of queue providers which should be tested */
22
23 /**
24 * Return a list of persistent and transient queue providers.
25 */
26 public function getQueueSpecs() {
27 $queueSpecs = [];
28 $queueSpecs[] = [
29 [
30 'type' => 'Sql',
31 'name' => 'test-queue-sql',
32 ],
33 ];
34 $queueSpecs[] = [
35 [
36 'type' => 'Memory',
37 'name' => 'test-queue-mem',
38 ],
39 ];
40 $queueSpecs[] = [
41 [
42 'type' => 'SqlParallel',
43 'name' => 'test-queue-sqlparallel',
44 ],
45 ];
46 return $queueSpecs;
47 }
48
49 /**
50 * Per-provider tests
51 */
52 public function setUp(): void {
53 parent::setUp();
54 $this->queueService = CRM_Queue_Service::singleton(TRUE);
55 }
56
57 public function tearDown(): void {
58 CRM_Utils_Time::resetTime();
59
60 $tablesToTruncate = ['civicrm_queue_item', 'civicrm_queue'];
61 $this->quickCleanup($tablesToTruncate);
62 parent::tearDown();
63 }
64
65 /**
66 * Create a few queue items; alternately enqueue and dequeue various
67 *
68 * @dataProvider getQueueSpecs
69 * @param $queueSpec
70 */
71 public function testBasicUsage($queueSpec) {
72 $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_queue');
73 $this->queue = $this->queueService->create($queueSpec);
74 $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_queue');
75 $this->assertTrue($this->queue instanceof CRM_Queue_Queue);
76 $this->assertEquals($queueSpec['name'], $this->queue->getSpec('name'));
77 $this->assertEquals($queueSpec['type'], $this->queue->getSpec('type'));
78
79 $this->queue->createItem([
80 'test-key' => 'a',
81 ]);
82 $this->queue->createItem([
83 'test-key' => 'b',
84 ]);
85 $this->queue->createItem([
86 'test-key' => 'c',
87 ]);
88
89 $this->assertEquals(3, $this->queue->numberOfItems());
90 $item = $this->queue->claimItem();
91 $this->assertEquals('a', $item->data['test-key']);
92 $this->queue->deleteItem($item);
93
94 $this->assertEquals(2, $this->queue->numberOfItems());
95 $item = $this->queue->claimItem();
96 $this->assertEquals('b', $item->data['test-key']);
97 $this->queue->deleteItem($item);
98
99 $this->queue->createItem([
100 'test-key' => 'd',
101 ]);
102
103 $this->assertEquals(2, $this->queue->numberOfItems());
104 $item = $this->queue->claimItem();
105 $this->assertEquals('c', $item->data['test-key']);
106 $this->queue->deleteItem($item);
107
108 $this->assertEquals(1, $this->queue->numberOfItems());
109 $item = $this->queue->claimItem();
110 $this->assertEquals('d', $item->data['test-key']);
111 $this->queue->deleteItem($item);
112
113 $this->assertEquals(0, $this->queue->numberOfItems());
114 }
115
116 /**
117 * Claim an item from the queue and release it back for subsequent processing.
118 *
119 * @dataProvider getQueueSpecs
120 * @param $queueSpec
121 */
122 public function testManualRelease($queueSpec) {
123 $this->queue = $this->queueService->create($queueSpec);
124 $this->assertTrue($this->queue instanceof CRM_Queue_Queue);
125
126 $this->queue->createItem([
127 'test-key' => 'a',
128 ]);
129
130 $item = $this->queue->claimItem();
131 $this->assertEquals('a', $item->data['test-key']);
132 $this->assertEquals(1, $this->queue->numberOfItems());
133 $this->queue->releaseItem($item);
134
135 $this->assertEquals(1, $this->queue->numberOfItems());
136 $item = $this->queue->claimItem();
137 $this->assertEquals('a', $item->data['test-key']);
138 $this->queue->deleteItem($item);
139
140 $this->assertEquals(0, $this->queue->numberOfItems());
141 }
142
143 /**
144 * Test that item leases expire at the expected time.
145 *
146 * @dataProvider getQueueSpecs
147 *
148 * @param $queueSpec
149 */
150 public function testTimeoutRelease($queueSpec) {
151 $this->queue = $this->queueService->create($queueSpec);
152 $this->assertTrue($this->queue instanceof CRM_Queue_Queue);
153
154 CRM_Utils_Time::setTime('2012-04-01 1:00:00');
155 $this->queue->createItem([
156 'test-key' => 'a',
157 ]);
158
159 $item = $this->queue->claimItem();
160 $this->assertEquals('a', $item->data['test-key']);
161 $this->assertEquals(1, $this->queue->numberOfItems());
162 // forget to release
163
164 // haven't reach expiration yet
165 CRM_Utils_Time::setTime('2012-04-01 1:59:00');
166 $item2 = $this->queue->claimItem();
167 $this->assertEquals(FALSE, $item2);
168
169 // pass expiration mark
170 CRM_Utils_Time::setTime('2012-04-01 2:00:03');
171 $item3 = $this->queue->claimItem();
172 $this->assertEquals('a', $item3->data['test-key']);
173 $this->assertEquals(1, $this->queue->numberOfItems());
174 $this->queue->deleteItem($item3);
175
176 $this->assertEquals(0, $this->queue->numberOfItems());
177 }
178
179 /**
180 * Test that item leases can be ignored.
181 *
182 * @dataProvider getQueueSpecs
183 * @param $queueSpec
184 */
185 public function testStealItem($queueSpec) {
186 $this->queue = $this->queueService->create($queueSpec);
187 $this->assertTrue($this->queue instanceof CRM_Queue_Queue);
188
189 CRM_Utils_Time::setTime('2012-04-01 1:00:00');
190 $this->queue->createItem([
191 'test-key' => 'a',
192 ]);
193
194 $item = $this->queue->claimItem();
195 $this->assertEquals('a', $item->data['test-key']);
196 $this->assertEquals(1, $this->queue->numberOfItems());
197 // forget to release
198
199 // haven't reached expiration yet, so claimItem fails
200 CRM_Utils_Time::setTime('2012-04-01 1:59:00');
201 $item2 = $this->queue->claimItem();
202 $this->assertEquals(FALSE, $item2);
203
204 // but stealItem works
205 $item3 = $this->queue->stealItem();
206 $this->assertEquals('a', $item3->data['test-key']);
207 $this->assertEquals(1, $this->queue->numberOfItems());
208 $this->queue->deleteItem($item3);
209
210 $this->assertEquals(0, $this->queue->numberOfItems());
211 }
212
213 /**
214 * Create a persistent queue via CRM_Queue_Service. Get a queue object with Civi::queue().
215 *
216 * @dataProvider getQueueSpecs
217 * @param $queueSpec
218 */
219 public function testPersistentUsage_service($queueSpec) {
220 $this->assertTrue(!empty($queueSpec['name']));
221 $this->assertTrue(!empty($queueSpec['type']));
222
223 $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_queue');
224 $q1 = CRM_Queue_Service::singleton()->create($queueSpec + [
225 'is_persistent' => TRUE,
226 ]);
227 $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_queue');
228
229 $q2 = Civi::queue($queueSpec['name']);
230 $this->assertInstanceOf('CRM_Queue_Queue_' . $queueSpec['type'], $q2);
231 $this->assertTrue($q1 === $q2);
232 }
233
234 /**
235 * Create a persistent queue via APIv4. Get a queue object with Civi::queue().
236 *
237 * @dataProvider getQueueSpecs
238 * @param $queueSpec
239 */
240 public function testPersistentUsage_api4($queueSpec) {
241 $this->assertTrue(!empty($queueSpec['name']));
242 $this->assertTrue(!empty($queueSpec['type']));
243
244 \Civi\Api4\Queue::create(0)
245 ->setValues($queueSpec)
246 ->execute();
247
248 $q1 = Civi::queue($queueSpec['name']);
249 $this->assertInstanceOf('CRM_Queue_Queue_' . $queueSpec['type'], $q1);
250
251 if ($queueSpec['type'] !== 'Memory') {
252 CRM_Queue_Service::singleton(TRUE);
253 $q2 = CRM_Queue_Service::singleton()->load([
254 'name' => $queueSpec['name'],
255 'is_persistent' => TRUE,
256 ]);
257 $this->assertInstanceOf('CRM_Queue_Queue_' . $queueSpec['type'], $q1);
258 }
259 }
260
261 public function testFacadeAutoCreate() {
262 $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_queue');
263 $q1 = Civi::queue('testFacadeAutoCreate_q1', [
264 'type' => 'Sql',
265 ]);
266 $q2 = Civi::queue('testFacadeAutoCreate_q2', [
267 'type' => 'SqlParallel',
268 ]);
269 $q1Reload = Civi::queue('testFacadeAutoCreate_q1', [
270 /* q1 already exists, so it doesn't matter what type you give. */
271 'type' => 'ZoombaroombaFaketypeGoombapoompa',
272 ]);
273 $this->assertDBQuery(2, 'SELECT count(*) FROM civicrm_queue');
274 $this->assertInstanceOf('CRM_Queue_Queue_Sql', $q1);
275 $this->assertInstanceOf('CRM_Queue_Queue_SqlParallel', $q2);
276 $this->assertInstanceOf('CRM_Queue_Queue_Sql', $q1Reload);
277
278 try {
279 Civi::queue('testFacadeAutoCreate_q3' /* missing type */);
280 $this->fail('Queue lookup should fail. There is neither pre-existing registration nor new details.');
281 }
282 catch (CRM_Core_Exception $e) {
283 $this->assertRegExp(';Missing field "type";', $e->getMessage());
284 }
285 }
286
287 /**
288 * Test that queue content is reset when reset=>TRUE
289 *
290 * @dataProvider getQueueSpecs
291 * @param $queueSpec
292 */
293 public function testCreateResetTrue($queueSpec) {
294 $this->queue = $this->queueService->create($queueSpec);
295 $this->queue->createItem([
296 'test-key' => 'a',
297 ]);
298 $this->queue->createItem([
299 'test-key' => 'b',
300 ]);
301 $this->assertEquals(2, $this->queue->numberOfItems());
302 unset($this->queue);
303
304 $queue2 = $this->queueService->create(
305 $queueSpec + ['reset' => TRUE]
306 );
307 $this->assertEquals(0, $queue2->numberOfItems());
308 }
309
310 /**
311 * Test that queue content is not reset when reset is omitted.
312 *
313 * @dataProvider getQueueSpecs
314 * @param $queueSpec
315 */
316 public function testCreateResetFalse($queueSpec) {
317 $this->queue = $this->queueService->create($queueSpec);
318 $this->queue->createItem([
319 'test-key' => 'a',
320 ]);
321 $this->queue->createItem([
322 'test-key' => 'b',
323 ]);
324 $this->assertEquals(2, $this->queue->numberOfItems());
325 unset($this->queue);
326
327 $queue2 = $this->queueService->create($queueSpec);
328 $this->assertEquals(2, $queue2->numberOfItems());
329
330 $item = $queue2->claimItem();
331 $this->assertEquals('a', $item->data['test-key']);
332 $queue2->releaseItem($item);
333 }
334
335 /**
336 * Test that queue content is not reset when using load()
337 *
338 * @dataProvider getQueueSpecs
339 * @param $queueSpec
340 */
341 public function testLoad($queueSpec) {
342 $this->queue = $this->queueService->create($queueSpec);
343 $this->queue->createItem([
344 'test-key' => 'a',
345 ]);
346 $this->queue->createItem([
347 'test-key' => 'b',
348 ]);
349 $this->assertEquals(2, $this->queue->numberOfItems());
350 unset($this->queue);
351
352 $queue2 = $this->queueService->create($queueSpec);
353 $this->assertEquals(2, $queue2->numberOfItems());
354
355 $item = $queue2->claimItem();
356 $this->assertEquals('a', $item->data['test-key']);
357 $queue2->releaseItem($item);
358 }
359
360 }