Merge pull request #14673 from eileenmcnaughton/payment_create
[civicrm-core.git] / tests / phpunit / CRM / Queue / RunnerTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 * Ensure that various queue implementations comply with the interface
30 * @group headless
31 */
32 class CRM_Queue_RunnerTest extends CiviUnitTestCase {
33
34 public function setUp() {
35 parent::setUp();
36 $this->queueService = CRM_Queue_Service::singleton(TRUE);
37 $this->queue = $this->queueService->create([
38 'type' => 'Sql',
39 'name' => 'test-queue',
40 ]);
41 self::$_recordedValues = [];
42 }
43
44 public function tearDown() {
45 unset($this->queue);
46 unset($this->queueService);
47
48 CRM_Utils_Time::resetTime();
49
50 $tablesToTruncate = ['civicrm_queue_item'];
51 $this->quickCleanup($tablesToTruncate);
52 }
53
54 public function testRunAllNormal() {
55 // prepare a list of tasks with an error in the middle
56 $this->queue->createItem(new CRM_Queue_Task(
57 ['CRM_Queue_RunnerTest', '_recordValue'],
58 ['a'],
59 'Add "a"'
60 ));
61 $this->queue->createItem(new CRM_Queue_Task(
62 ['CRM_Queue_RunnerTest', '_recordValue'],
63 ['b'],
64 'Add "b"'
65 ));
66 $this->queue->createItem(new CRM_Queue_Task(
67 ['CRM_Queue_RunnerTest', '_recordValue'],
68 ['c'],
69 'Add "c"'
70 ));
71
72 // run the list of tasks
73 $runner = new CRM_Queue_Runner([
74 'queue' => $this->queue,
75 'errorMode' => CRM_Queue_Runner::ERROR_ABORT,
76 ]);
77 $this->assertEquals(self::$_recordedValues, []);
78 $this->assertEquals(3, $this->queue->numberOfItems());
79 $result = $runner->runAll();
80 $this->assertEquals(TRUE, $result);
81 $this->assertEquals(self::$_recordedValues, ['a', 'b', 'c']);
82 $this->assertEquals(0, $this->queue->numberOfItems());
83 }
84
85 /**
86 * Run a series of tasks.
87 *
88 * One of the tasks will insert more TODOs at the start of the list.
89 */
90 public function testRunAll_AddMore() {
91 // Prepare a list of tasks with an error in the middle.
92 $this->queue->createItem(new CRM_Queue_Task(
93 ['CRM_Queue_RunnerTest', '_recordValue'],
94 ['a'],
95 'Add "a"'
96 ));
97 $this->queue->createItem(new CRM_Queue_Task(
98 ['CRM_Queue_RunnerTest', '_enqueueNumbers'],
99 [1, 3],
100 'Add more'
101 ));
102 $this->queue->createItem(new CRM_Queue_Task(
103 ['CRM_Queue_RunnerTest', '_recordValue'],
104 ['b'],
105 'Add "b"'
106 ));
107
108 // run the list of tasks
109 $runner = new CRM_Queue_Runner([
110 'queue' => $this->queue,
111 'errorMode' => CRM_Queue_Runner::ERROR_ABORT,
112 ]);
113 $this->assertEquals(self::$_recordedValues, []);
114 $this->assertEquals(3, $this->queue->numberOfItems());
115 $result = $runner->runAll();
116 $this->assertEquals(TRUE, $result);
117 $this->assertEquals(self::$_recordedValues, ['a', 1, 2, 3, 'b']);
118 $this->assertEquals(0, $this->queue->numberOfItems());
119 }
120
121 /**
122 * Run a series of tasks; when one throws an
123 * exception, ignore it and continue
124 */
125 public function testRunAll_Continue_Exception() {
126 // prepare a list of tasks with an error in the middle
127 $this->queue->createItem(new CRM_Queue_Task(
128 ['CRM_Queue_RunnerTest', '_recordValue'],
129 ['a'],
130 'Add "a"'
131 ));
132 $this->queue->createItem(new CRM_Queue_Task(
133 ['CRM_Queue_RunnerTest', '_throwException'],
134 ['b'],
135 'Throw exception'
136 ));
137 $this->queue->createItem(new CRM_Queue_Task(
138 ['CRM_Queue_RunnerTest', '_recordValue'],
139 ['c'],
140 'Add "c"'
141 ));
142
143 // run the list of tasks
144 $runner = new CRM_Queue_Runner([
145 'queue' => $this->queue,
146 'errorMode' => CRM_Queue_Runner::ERROR_CONTINUE,
147 ]);
148 $this->assertEquals(self::$_recordedValues, []);
149 $this->assertEquals(3, $this->queue->numberOfItems());
150 $result = $runner->runAll();
151 // FIXME useless return
152 $this->assertEquals(TRUE, $result);
153 $this->assertEquals(self::$_recordedValues, ['a', 'c']);
154 $this->assertEquals(0, $this->queue->numberOfItems());
155 }
156
157 /**
158 * Run a series of tasks; when one throws an exception,
159 * abort processing and return it to the queue.
160 */
161 public function testRunAll_Abort_Exception() {
162 // prepare a list of tasks with an error in the middle
163 $this->queue->createItem(new CRM_Queue_Task(
164 ['CRM_Queue_RunnerTest', '_recordValue'],
165 ['a'],
166 'Add "a"'
167 ));
168 $this->queue->createItem(new CRM_Queue_Task(
169 ['CRM_Queue_RunnerTest', '_throwException'],
170 ['b'],
171 'Throw exception'
172 ));
173 $this->queue->createItem(new CRM_Queue_Task(
174 ['CRM_Queue_RunnerTest', '_recordValue'],
175 ['c'],
176 'Add "c"'
177 ));
178
179 // run the list of tasks
180 $runner = new CRM_Queue_Runner([
181 'queue' => $this->queue,
182 'errorMode' => CRM_Queue_Runner::ERROR_ABORT,
183 ]);
184 $this->assertEquals(self::$_recordedValues, []);
185 $this->assertEquals(3, $this->queue->numberOfItems());
186 $result = $runner->runAll();
187 $this->assertEquals(1, $result['is_error']);
188 // nothing from 'c'
189 $this->assertEquals(self::$_recordedValues, ['a']);
190 // 'b' and 'c' remain
191 $this->assertEquals(2, $this->queue->numberOfItems());
192 }
193
194 /**
195 * Run a series of tasks; when one returns false,
196 * abort processing and return it to the queue.
197 */
198 public function testRunAll_Abort_False() {
199 // prepare a list of tasks with an error in the middle
200 $this->queue->createItem(new CRM_Queue_Task(
201 ['CRM_Queue_RunnerTest', '_recordValue'],
202 ['a'],
203 'Add "a"'
204 ));
205 $this->queue->createItem(new CRM_Queue_Task(
206 ['CRM_Queue_RunnerTest', '_returnFalse'],
207 [],
208 'Return false'
209 ));
210 $this->queue->createItem(new CRM_Queue_Task(
211 ['CRM_Queue_RunnerTest', '_recordValue'],
212 ['c'],
213 'Add "c"'
214 ));
215
216 // run the list of tasks
217 $runner = new CRM_Queue_Runner([
218 'queue' => $this->queue,
219 'errorMode' => CRM_Queue_Runner::ERROR_ABORT,
220 ]);
221 $this->assertEquals(self::$_recordedValues, []);
222 $this->assertEquals(3, $this->queue->numberOfItems());
223 $result = $runner->runAll();
224 $this->assertEquals(1, $result['is_error']);
225 // nothing from 'c'
226 $this->assertEquals(self::$_recordedValues, ['a']);
227 // 'b' and 'c' remain
228 $this->assertEquals(2, $this->queue->numberOfItems());
229 }
230
231 /**
232 * Queue tasks
233 * @var array
234 */
235 protected static $_recordedValues;
236
237 /**
238 * @param $taskCtx
239 * @param $value
240 *
241 * @return bool
242 */
243 public static function _recordValue($taskCtx, $value) {
244 self::$_recordedValues[] = $value;
245 return TRUE;
246 }
247
248 /**
249 * @param $taskCtx
250 *
251 * @return bool
252 */
253 public static function _returnFalse($taskCtx) {
254 return FALSE;
255 }
256
257 /**
258 * @param $taskCtx
259 * @param $value
260 *
261 * @throws Exception
262 */
263 public static function _throwException($taskCtx, $value) {
264 throw new Exception("Manufactured error: $value");
265 }
266
267 /**
268 * @param $taskCtx
269 * @param $low
270 * @param $high
271 *
272 * @return bool
273 */
274 public static function _enqueueNumbers($taskCtx, $low, $high) {
275 for ($i = $low; $i <= $high; $i++) {
276 $taskCtx->queue->createItem(new CRM_Queue_Task(
277 ['CRM_Queue_RunnerTest', '_recordValue'],
278 [$i],
279 sprintf('Add number "%d"', $i)
280 ), [
281 'weight' => -1,
282 ]);
283 }
284 return TRUE;
285 }
286
287 }