Merge pull request #15338 from totten/master-poc-postcommit
[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 */
16 class CRM_Queue_QueueTest extends CiviUnitTestCase {
17
18 /* ----------------------- Queue providers ----------------------- */
19
20 /* Define a list of queue providers which should be tested */
21
22 /**
23 * Return a list of persistent and transient queue providers.
24 */
25 public function getQueueSpecs() {
26 $queueSpecs = [];
27 $queueSpecs[] = [
28 [
29 'type' => 'Sql',
30 'name' => 'test-queue',
31 ],
32 ];
33 $queueSpecs[] = [
34 [
35 'type' => 'Memory',
36 'name' => 'test-queue',
37 ],
38 ];
39 return $queueSpecs;
40 }
41
42 /**
43 * Per-provider tests
44 */
45 public function setUp() {
46 parent::setUp();
47 $this->queueService = CRM_Queue_Service::singleton(TRUE);
48 }
49
50 public function tearDown() {
51 CRM_Utils_Time::resetTime();
52
53 $tablesToTruncate = ['civicrm_queue_item'];
54 $this->quickCleanup($tablesToTruncate);
55 }
56
57 /**
58 * Create a few queue items; alternately enqueue and dequeue various
59 *
60 * @dataProvider getQueueSpecs
61 * @param $queueSpec
62 */
63 public function testBasicUsage($queueSpec) {
64 $this->queue = $this->queueService->create($queueSpec);
65 $this->assertTrue($this->queue instanceof CRM_Queue_Queue);
66
67 $this->queue->createItem([
68 'test-key' => 'a',
69 ]);
70 $this->queue->createItem([
71 'test-key' => 'b',
72 ]);
73 $this->queue->createItem([
74 'test-key' => 'c',
75 ]);
76
77 $this->assertEquals(3, $this->queue->numberOfItems());
78 $item = $this->queue->claimItem();
79 $this->assertEquals('a', $item->data['test-key']);
80 $this->queue->deleteItem($item);
81
82 $this->assertEquals(2, $this->queue->numberOfItems());
83 $item = $this->queue->claimItem();
84 $this->assertEquals('b', $item->data['test-key']);
85 $this->queue->deleteItem($item);
86
87 $this->queue->createItem([
88 'test-key' => 'd',
89 ]);
90
91 $this->assertEquals(2, $this->queue->numberOfItems());
92 $item = $this->queue->claimItem();
93 $this->assertEquals('c', $item->data['test-key']);
94 $this->queue->deleteItem($item);
95
96 $this->assertEquals(1, $this->queue->numberOfItems());
97 $item = $this->queue->claimItem();
98 $this->assertEquals('d', $item->data['test-key']);
99 $this->queue->deleteItem($item);
100
101 $this->assertEquals(0, $this->queue->numberOfItems());
102 }
103
104 /**
105 * Claim an item from the queue and release it back for subsequent processing.
106 *
107 * @dataProvider getQueueSpecs
108 * @param $queueSpec
109 */
110 public function testManualRelease($queueSpec) {
111 $this->queue = $this->queueService->create($queueSpec);
112 $this->assertTrue($this->queue instanceof CRM_Queue_Queue);
113
114 $this->queue->createItem([
115 'test-key' => 'a',
116 ]);
117
118 $item = $this->queue->claimItem();
119 $this->assertEquals('a', $item->data['test-key']);
120 $this->assertEquals(1, $this->queue->numberOfItems());
121 $this->queue->releaseItem($item);
122
123 $this->assertEquals(1, $this->queue->numberOfItems());
124 $item = $this->queue->claimItem();
125 $this->assertEquals('a', $item->data['test-key']);
126 $this->queue->deleteItem($item);
127
128 $this->assertEquals(0, $this->queue->numberOfItems());
129 }
130
131 /**
132 * Test that item leases expire at the expected time.
133 *
134 * @dataProvider getQueueSpecs
135 *
136 * @param $queueSpec
137 */
138 public function testTimeoutRelease($queueSpec) {
139 $this->queue = $this->queueService->create($queueSpec);
140 $this->assertTrue($this->queue instanceof CRM_Queue_Queue);
141
142 CRM_Utils_Time::setTime('2012-04-01 1:00:00');
143 $this->queue->createItem([
144 'test-key' => 'a',
145 ]);
146
147 $item = $this->queue->claimItem();
148 $this->assertEquals('a', $item->data['test-key']);
149 $this->assertEquals(1, $this->queue->numberOfItems());
150 // forget to release
151
152 // haven't reach expiration yet
153 CRM_Utils_Time::setTime('2012-04-01 1:59:00');
154 $item2 = $this->queue->claimItem();
155 $this->assertEquals(FALSE, $item2);
156
157 // pass expiration mark
158 CRM_Utils_Time::setTime('2012-04-01 2:00:01');
159 $item3 = $this->queue->claimItem();
160 $this->assertEquals('a', $item3->data['test-key']);
161 $this->assertEquals(1, $this->queue->numberOfItems());
162 $this->queue->deleteItem($item3);
163
164 $this->assertEquals(0, $this->queue->numberOfItems());
165 }
166
167 /**
168 * Test that item leases can be ignored.
169 *
170 * @dataProvider getQueueSpecs
171 * @param $queueSpec
172 */
173 public function testStealItem($queueSpec) {
174 $this->queue = $this->queueService->create($queueSpec);
175 $this->assertTrue($this->queue instanceof CRM_Queue_Queue);
176
177 CRM_Utils_Time::setTime('2012-04-01 1:00:00');
178 $this->queue->createItem([
179 'test-key' => 'a',
180 ]);
181
182 $item = $this->queue->claimItem();
183 $this->assertEquals('a', $item->data['test-key']);
184 $this->assertEquals(1, $this->queue->numberOfItems());
185 // forget to release
186
187 // haven't reached expiration yet, so claimItem fails
188 CRM_Utils_Time::setTime('2012-04-01 1:59:00');
189 $item2 = $this->queue->claimItem();
190 $this->assertEquals(FALSE, $item2);
191
192 // but stealItem works
193 $item3 = $this->queue->stealItem();
194 $this->assertEquals('a', $item3->data['test-key']);
195 $this->assertEquals(1, $this->queue->numberOfItems());
196 $this->queue->deleteItem($item3);
197
198 $this->assertEquals(0, $this->queue->numberOfItems());
199 }
200
201 /**
202 * Test that queue content is reset when reset=>TRUE
203 *
204 * @dataProvider getQueueSpecs
205 * @param $queueSpec
206 */
207 public function testCreateResetTrue($queueSpec) {
208 $this->queue = $this->queueService->create($queueSpec);
209 $this->queue->createItem([
210 'test-key' => 'a',
211 ]);
212 $this->queue->createItem([
213 'test-key' => 'b',
214 ]);
215 $this->assertEquals(2, $this->queue->numberOfItems());
216 unset($this->queue);
217
218 $queue2 = $this->queueService->create(
219 $queueSpec + ['reset' => TRUE]
220 );
221 $this->assertEquals(0, $queue2->numberOfItems());
222 }
223
224 /**
225 * Test that queue content is not reset when reset is omitted.
226 *
227 * @dataProvider getQueueSpecs
228 * @param $queueSpec
229 */
230 public function testCreateResetFalse($queueSpec) {
231 $this->queue = $this->queueService->create($queueSpec);
232 $this->queue->createItem([
233 'test-key' => 'a',
234 ]);
235 $this->queue->createItem([
236 'test-key' => 'b',
237 ]);
238 $this->assertEquals(2, $this->queue->numberOfItems());
239 unset($this->queue);
240
241 $queue2 = $this->queueService->create($queueSpec);
242 $this->assertEquals(2, $queue2->numberOfItems());
243
244 $item = $queue2->claimItem();
245 $this->assertEquals('a', $item->data['test-key']);
246 $queue2->releaseItem($item);
247 }
248
249 /**
250 * Test that queue content is not reset when using load()
251 *
252 * @dataProvider getQueueSpecs
253 * @param $queueSpec
254 */
255 public function testLoad($queueSpec) {
256 $this->queue = $this->queueService->create($queueSpec);
257 $this->queue->createItem([
258 'test-key' => 'a',
259 ]);
260 $this->queue->createItem([
261 'test-key' => 'b',
262 ]);
263 $this->assertEquals(2, $this->queue->numberOfItems());
264 unset($this->queue);
265
266 $queue2 = $this->queueService->create($queueSpec);
267 $this->assertEquals(2, $queue2->numberOfItems());
268
269 $item = $queue2->claimItem();
270 $this->assertEquals('a', $item->data['test-key']);
271 $queue2->releaseItem($item);
272 }
273
274 }