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