Merge pull request #21865 from colemanw/SearchKitTags
[civicrm-core.git] / tests / phpunit / CRM / Queue / RunnerTest.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_RunnerTest extends CiviUnitTestCase {
17
18 public function setUp(): void {
19 parent::setUp();
20 $this->queueService = CRM_Queue_Service::singleton(TRUE);
21 $this->queue = $this->queueService->create([
22 'type' => 'Sql',
23 'name' => 'test-queue',
24 ]);
25 self::$_recordedValues = [];
26 }
27
28 public function tearDown(): void {
29 unset($this->queue);
30 unset($this->queueService);
31
32 CRM_Utils_Time::resetTime();
33
34 $tablesToTruncate = ['civicrm_queue_item'];
35 $this->quickCleanup($tablesToTruncate);
36 parent::tearDown();
37 }
38
39 public function testRunAllNormal() {
40 // prepare a list of tasks with an error in the middle
41 $this->queue->createItem(new CRM_Queue_Task(
42 ['CRM_Queue_RunnerTest', '_recordValue'],
43 ['a'],
44 'Add "a"'
45 ));
46 $this->queue->createItem(new CRM_Queue_Task(
47 ['CRM_Queue_RunnerTest', '_recordValue'],
48 ['b'],
49 'Add "b"'
50 ));
51 $this->queue->createItem(new CRM_Queue_Task(
52 ['CRM_Queue_RunnerTest', '_recordValue'],
53 ['c'],
54 'Add "c"'
55 ));
56
57 // run the list of tasks
58 $runner = new CRM_Queue_Runner([
59 'queue' => $this->queue,
60 'errorMode' => CRM_Queue_Runner::ERROR_ABORT,
61 ]);
62 $this->assertEquals(self::$_recordedValues, []);
63 $this->assertEquals(3, $this->queue->numberOfItems());
64 $result = $runner->runAll();
65 $this->assertEquals(TRUE, $result);
66 $this->assertEquals(self::$_recordedValues, ['a', 'b', 'c']);
67 $this->assertEquals(0, $this->queue->numberOfItems());
68 }
69
70 /**
71 * Run a series of tasks.
72 *
73 * One of the tasks will insert more TODOs at the start of the list.
74 */
75 public function testRunAll_AddMore() {
76 // Prepare a list of tasks with an error in the middle.
77 $this->queue->createItem(new CRM_Queue_Task(
78 ['CRM_Queue_RunnerTest', '_recordValue'],
79 ['a'],
80 'Add "a"'
81 ));
82 $this->queue->createItem(new CRM_Queue_Task(
83 ['CRM_Queue_RunnerTest', '_enqueueNumbers'],
84 [1, 3],
85 'Add more'
86 ));
87 $this->queue->createItem(new CRM_Queue_Task(
88 ['CRM_Queue_RunnerTest', '_recordValue'],
89 ['b'],
90 'Add "b"'
91 ));
92
93 // run the list of tasks
94 $runner = new CRM_Queue_Runner([
95 'queue' => $this->queue,
96 'errorMode' => CRM_Queue_Runner::ERROR_ABORT,
97 ]);
98 $this->assertEquals(self::$_recordedValues, []);
99 $this->assertEquals(3, $this->queue->numberOfItems());
100 $result = $runner->runAll();
101 $this->assertEquals(TRUE, $result);
102 $this->assertEquals(self::$_recordedValues, ['a', 1, 2, 3, 'b']);
103 $this->assertEquals(0, $this->queue->numberOfItems());
104 }
105
106 /**
107 * Run a series of tasks; when one throws an
108 * exception, ignore it and continue
109 */
110 public function testRunAll_Continue_Exception() {
111 // prepare a list of tasks with an error in the middle
112 $this->queue->createItem(new CRM_Queue_Task(
113 ['CRM_Queue_RunnerTest', '_recordValue'],
114 ['a'],
115 'Add "a"'
116 ));
117 $this->queue->createItem(new CRM_Queue_Task(
118 ['CRM_Queue_RunnerTest', '_throwException'],
119 ['b'],
120 'Throw exception'
121 ));
122 $this->queue->createItem(new CRM_Queue_Task(
123 ['CRM_Queue_RunnerTest', '_recordValue'],
124 ['c'],
125 'Add "c"'
126 ));
127
128 // run the list of tasks
129 $runner = new CRM_Queue_Runner([
130 'queue' => $this->queue,
131 'errorMode' => CRM_Queue_Runner::ERROR_CONTINUE,
132 ]);
133 $this->assertEquals(self::$_recordedValues, []);
134 $this->assertEquals(3, $this->queue->numberOfItems());
135 $result = $runner->runAll();
136 // FIXME useless return
137 $this->assertEquals(TRUE, $result);
138 $this->assertEquals(self::$_recordedValues, ['a', 'c']);
139 $this->assertEquals(0, $this->queue->numberOfItems());
140 }
141
142 /**
143 * Run a series of tasks; when one throws an exception,
144 * abort processing and return it to the queue.
145 */
146 public function testRunAll_Abort_Exception() {
147 // prepare a list of tasks with an error in the middle
148 $this->queue->createItem(new CRM_Queue_Task(
149 ['CRM_Queue_RunnerTest', '_recordValue'],
150 ['a'],
151 'Add "a"'
152 ));
153 $this->queue->createItem(new CRM_Queue_Task(
154 ['CRM_Queue_RunnerTest', '_throwException'],
155 ['b'],
156 'Throw exception'
157 ));
158 $this->queue->createItem(new CRM_Queue_Task(
159 ['CRM_Queue_RunnerTest', '_recordValue'],
160 ['c'],
161 'Add "c"'
162 ));
163
164 // run the list of tasks
165 $runner = new CRM_Queue_Runner([
166 'queue' => $this->queue,
167 'errorMode' => CRM_Queue_Runner::ERROR_ABORT,
168 ]);
169 $this->assertEquals(self::$_recordedValues, []);
170 $this->assertEquals(3, $this->queue->numberOfItems());
171 $result = $runner->runAll();
172 $this->assertEquals(1, $result['is_error']);
173 // nothing from 'c'
174 $this->assertEquals(self::$_recordedValues, ['a']);
175 // 'b' and 'c' remain
176 $this->assertEquals(2, $this->queue->numberOfItems());
177 }
178
179 /**
180 * Run a series of tasks; when one returns false,
181 * abort processing and return it to the queue.
182 */
183 public function testRunAll_Abort_False() {
184 // prepare a list of tasks with an error in the middle
185 $this->queue->createItem(new CRM_Queue_Task(
186 ['CRM_Queue_RunnerTest', '_recordValue'],
187 ['a'],
188 'Add "a"'
189 ));
190 $this->queue->createItem(new CRM_Queue_Task(
191 ['CRM_Queue_RunnerTest', '_returnFalse'],
192 [],
193 'Return false'
194 ));
195 $this->queue->createItem(new CRM_Queue_Task(
196 ['CRM_Queue_RunnerTest', '_recordValue'],
197 ['c'],
198 'Add "c"'
199 ));
200
201 // run the list of tasks
202 $runner = new CRM_Queue_Runner([
203 'queue' => $this->queue,
204 'errorMode' => CRM_Queue_Runner::ERROR_ABORT,
205 ]);
206 $this->assertEquals(self::$_recordedValues, []);
207 $this->assertEquals(3, $this->queue->numberOfItems());
208 $result = $runner->runAll();
209 $this->assertEquals(1, $result['is_error']);
210 // nothing from 'c'
211 $this->assertEquals(self::$_recordedValues, ['a']);
212 // 'b' and 'c' remain
213 $this->assertEquals(2, $this->queue->numberOfItems());
214 }
215
216 /**
217 * Queue tasks
218 * @var array
219 */
220 protected static $_recordedValues;
221
222 /**
223 * @param $taskCtx
224 * @param $value
225 *
226 * @return bool
227 */
228 public static function _recordValue($taskCtx, $value) {
229 self::$_recordedValues[] = $value;
230 return TRUE;
231 }
232
233 /**
234 * @param $taskCtx
235 *
236 * @return bool
237 */
238 public static function _returnFalse($taskCtx) {
239 return FALSE;
240 }
241
242 /**
243 * @param $taskCtx
244 * @param $value
245 *
246 * @throws Exception
247 */
248 public static function _throwException($taskCtx, $value) {
249 throw new Exception("Manufactured error: $value");
250 }
251
252 /**
253 * @param $taskCtx
254 * @param $low
255 * @param $high
256 *
257 * @return bool
258 */
259 public static function _enqueueNumbers($taskCtx, $low, $high) {
260 for ($i = $low; $i <= $high; $i++) {
261 $taskCtx->queue->createItem(new CRM_Queue_Task(
262 ['CRM_Queue_RunnerTest', '_recordValue'],
263 [$i],
264 sprintf('Add number "%d"', $i)
265 ), [
266 'weight' => -1,
267 ]);
268 }
269 return TRUE;
270 }
271
272 }