Commit | Line | Data |
---|---|---|
07c09ae4 EM |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
7d61e75f | 4 | | Copyright CiviCRM LLC. All rights reserved. | |
07c09ae4 | 5 | | | |
7d61e75f TO |
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 | | |
07c09ae4 EM |
9 | +--------------------------------------------------------------------+ |
10 | */ | |
11 | ||
12 | /** | |
13 | * File for the CiviCRM APIv3 job functions | |
14 | * | |
15 | * @package CiviCRM_APIv3 | |
16 | * @subpackage API_Job | |
17 | * | |
ca5cec67 | 18 | * @copyright CiviCRM LLC https://civicrm.org/licensing |
07c09ae4 EM |
19 | * @version $Id: Job.php 30879 2010-11-22 15:45:55Z shot $ |
20 | * | |
21 | */ | |
0eea664b | 22 | |
07c09ae4 EM |
23 | /** |
24 | * Class api_v3_JobTest | |
acb109b7 | 25 | * @group headless |
b4a332a9 | 26 | * @group civimail |
07c09ae4 EM |
27 | */ |
28 | class api_v3_JobProcessMailingTest extends CiviUnitTestCase { | |
29 | protected $_apiversion = 3; | |
30 | ||
31 | public $DBResetRequired = FALSE; | |
32 | public $_entity = 'Job'; | |
9099cab3 | 33 | public $_params = []; |
07c09ae4 EM |
34 | private $_groupID; |
35 | private $_email; | |
36 | ||
d667a9ba TO |
37 | protected $defaultSettings; |
38 | ||
07c09ae4 EM |
39 | /** |
40 | * @var CiviMailUtils | |
41 | */ | |
42 | private $_mut; | |
43 | ||
00be9182 | 44 | public function setUp() { |
d667a9ba | 45 | $this->cleanupMailingTest(); |
07c09ae4 | 46 | parent::setUp(); |
39b959db SL |
47 | // DGW |
48 | CRM_Mailing_BAO_MailingJob::$mailsProcessed = 0; | |
07c09ae4 EM |
49 | $this->_groupID = $this->groupCreate(); |
50 | $this->_email = 'test@test.test'; | |
9099cab3 | 51 | $this->_params = [ |
07c09ae4 | 52 | 'subject' => 'Accidents in cars cause children', |
21b09c13 | 53 | 'body_text' => 'BEWARE children need regular infusions of toys. Santa knows your {domain.address}. There is no {action.optOutUrl}.', |
07c09ae4 EM |
54 | 'name' => 'mailing name', |
55 | 'created_id' => 1, | |
9099cab3 | 56 | 'groups' => ['include' => [$this->_groupID]], |
5f445749 | 57 | 'scheduled_date' => 'now', |
9099cab3 CW |
58 | ]; |
59 | $this->defaultSettings = [ | |
39b959db SL |
60 | // int, #mailings to send |
61 | 'mailings' => 1, | |
62 | // int, #contacts to receive mailing | |
63 | 'recipients' => 20, | |
64 | // int, #concurrent cron jobs | |
65 | 'workers' => 1, | |
66 | // int, #times to spawn all the workers | |
67 | 'iterations' => 1, | |
68 | // int, #extra seconds each cron job should hold lock | |
69 | 'lockHold' => 0, | |
70 | // int, max# recipients to send in a given cron run | |
71 | 'mailerBatchLimit' => 0, | |
72 | // int, max# concurrent jobs | |
73 | 'mailerJobsMax' => 0, | |
74 | // int, max# recipients in each job | |
75 | 'mailerJobSize' => 0, | |
76 | // int, microseconds separating messages | |
77 | 'mailThrottleTime' => 0, | |
9099cab3 | 78 | ]; |
481a74f4 | 79 | $this->_mut = new CiviMailUtils($this, TRUE); |
9099cab3 | 80 | $this->callAPISuccess('mail_settings', 'get', ['api.mail_settings.create' => ['domain' => 'chaos.org']]); |
07c09ae4 EM |
81 | } |
82 | ||
83 | /** | |
07c09ae4 | 84 | */ |
00be9182 | 85 | public function tearDown() { |
d667a9ba | 86 | //$this->_mut->clearMessages(); |
07c09ae4 | 87 | $this->_mut->stop(); |
07c09ae4 | 88 | CRM_Utils_Hook::singleton()->reset(); |
39b959db SL |
89 | // DGW |
90 | CRM_Mailing_BAO_MailingJob::$mailsProcessed = 0; | |
d667a9ba | 91 | //$this->cleanupMailingTest(); |
07c09ae4 | 92 | parent::tearDown(); |
07c09ae4 EM |
93 | } |
94 | ||
d667a9ba | 95 | public function testBasic() { |
07c09ae4 | 96 | $this->createContactsInGroup(10, $this->_groupID); |
9099cab3 | 97 | Civi::settings()->add([ |
d667a9ba | 98 | 'mailerBatchLimit' => 2, |
9099cab3 | 99 | ]); |
07c09ae4 | 100 | $this->callAPISuccess('mailing', 'create', $this->_params); |
9099cab3 CW |
101 | $this->_mut->assertRecipients([]); |
102 | $this->callAPISuccess('job', 'process_mailing', []); | |
07c09ae4 | 103 | $this->_mut->assertRecipients($this->getRecipients(1, 2)); |
4aa8f804 JP |
104 | } |
105 | ||
acaec976 SL |
106 | /** |
107 | * Test what happens when a contact is set to decesaed | |
108 | */ | |
109 | public function testDecesasedRecepient() { | |
110 | $contactID = $this->individualCreate(['first_name' => 'test dead recipeint', 'email' => 'mailtestdead@civicrm.org']); | |
111 | $this->callAPISuccess('group_contact', 'create', [ | |
112 | 'contact_id' => $contactID, | |
113 | 'group_id' => $this->_groupID, | |
114 | 'status' => 'Added', | |
115 | ]); | |
116 | $this->createContactsInGroup(2, $this->_groupID); | |
117 | Civi::settings()->add([ | |
118 | 'mailerBatchLimit' => 2, | |
119 | ]); | |
120 | $mailing = $this->callAPISuccess('mailing', 'create', $this->_params); | |
121 | $this->assertEquals(3, $this->callAPISuccess('MailingRecipients', 'get', ['mailing_id' => $mailing['id']])['count']); | |
122 | $this->_mut->assertRecipients([]); | |
123 | $this->callAPISuccess('Contact', 'create', ['id' => $contactID, 'is_deceased' => 1, 'contact_type' => 'Individual']); | |
124 | $this->callAPISuccess('job', 'process_mailing', []); | |
125 | // Check that the deceased contact is not found in the mailing. | |
126 | $this->_mut->assertRecipients($this->getRecipients(1, 2)); | |
127 | ||
128 | } | |
129 | ||
50efb875 JG |
130 | /** |
131 | * Test that "multiple bulk email recipients" setting is respected. | |
132 | */ | |
133 | public function testMultipleBulkRecipients() { | |
134 | Civi::settings()->add([ | |
135 | 'civimail_multiple_bulk_emails' => 1, | |
136 | ]); | |
137 | $contactID = $this->individualCreate(['first_name' => 'test recipient']); | |
138 | $email1 = $this->callAPISuccess('email', 'create', [ | |
139 | 'contact_id' => $contactID, | |
140 | 'email' => 'mail1@example.org', | |
141 | 'is_bulkmail' => 1, | |
142 | ]); | |
143 | $email2 = $this->callAPISuccess('email', 'create', [ | |
144 | 'contact_id' => $contactID, | |
145 | 'email' => 'mail2@example.org', | |
146 | 'is_bulkmail' => 1, | |
147 | ]); | |
148 | $this->callAPISuccess('group_contact', 'create', [ | |
149 | 'contact_id' => $contactID, | |
150 | 'group_id' => $this->_groupID, | |
151 | 'status' => 'Added', | |
152 | ]); | |
153 | $mailing = $this->callAPISuccess('mailing', 'create', $this->_params); | |
154 | $this->assertEquals(2, $this->callAPISuccess('MailingRecipients', 'get', ['mailing_id' => $mailing['id']])['count']); | |
155 | $this->callAPISuccess('job', 'process_mailing', []); | |
156 | $this->_mut->assertRecipients([['mail1@example.org'], ['mail2@example.org']]); | |
157 | // Don't leave data lying around for other tests to screw up on. | |
158 | $this->callAPISuccess('Email', 'delete', ['id' => $email1['id']]); | |
159 | $this->callAPISuccess('Email', 'delete', ['id' => $email2['id']]); | |
160 | } | |
161 | ||
4aa8f804 JP |
162 | /** |
163 | * Test pause and resume on Mailing. | |
164 | */ | |
165 | public function testPauseAndResumeMailing() { | |
166 | $this->createContactsInGroup(10, $this->_groupID); | |
9099cab3 | 167 | Civi::settings()->add([ |
4aa8f804 | 168 | 'mailerBatchLimit' => 2, |
9099cab3 | 169 | ]); |
67d4ed51 | 170 | $this->_mut->clearMessages(); |
4aa8f804 JP |
171 | //Create a test mailing and check if the status is set to Scheduled. |
172 | $result = $this->callAPISuccess('mailing', 'create', $this->_params); | |
9099cab3 | 173 | $jobs = $this->callAPISuccess('mailing_job', 'get', ['mailing_id' => $result['id']]); |
4aa8f804 JP |
174 | $this->assertEquals('Scheduled', $jobs['values'][$jobs['id']]['status']); |
175 | ||
67d4ed51 | 176 | //Pause the mailing. |
4aa8f804 | 177 | CRM_Mailing_BAO_MailingJob::pause($result['id']); |
9099cab3 | 178 | $jobs = $this->callAPISuccess('mailing_job', 'get', ['mailing_id' => $result['id']]); |
4aa8f804 JP |
179 | $this->assertEquals('Paused', $jobs['values'][$jobs['id']]['status']); |
180 | ||
181 | //Verify if Paused mailing isn't considered in process_mailing job. | |
9099cab3 | 182 | $this->callAPISuccess('job', 'process_mailing', []); |
67d4ed51 JP |
183 | //Check if mail log is empty. |
184 | $this->_mut->assertMailLogEmpty(); | |
9099cab3 | 185 | $jobs = $this->callAPISuccess('mailing_job', 'get', ['mailing_id' => $result['id']]); |
4aa8f804 JP |
186 | $this->assertEquals('Paused', $jobs['values'][$jobs['id']]['status']); |
187 | ||
188 | //Resume should set the status back to Scheduled. | |
189 | CRM_Mailing_BAO_MailingJob::resume($result['id']); | |
9099cab3 | 190 | $jobs = $this->callAPISuccess('mailing_job', 'get', ['mailing_id' => $result['id']]); |
4aa8f804 | 191 | $this->assertEquals('Scheduled', $jobs['values'][$jobs['id']]['status']); |
67d4ed51 JP |
192 | |
193 | //Execute the job and it should send the mailing to the recipients now. | |
9099cab3 | 194 | $this->callAPISuccess('job', 'process_mailing', []); |
67d4ed51 | 195 | $this->_mut->assertRecipients($this->getRecipients(1, 2)); |
00cc2e4b SL |
196 | // Ensure that loading the report produces no errors. |
197 | $report = CRM_Mailing_BAO_Mailing::report($result['id']); | |
198 | // dev/mailing#56 dev/mailing#57 Ensure that for completed mailings the jobs array is not empty. | |
199 | $this->assertTrue(!empty($report['jobs'])); | |
200 | // Ensure that mailing name is correctly stored in the report. | |
201 | $this->assertEquals('mailing name', $report['mailing']['name']); | |
07c09ae4 EM |
202 | } |
203 | ||
f008885c E |
204 | /** |
205 | * Test mail when in non-production environment. | |
206 | * | |
207 | */ | |
208 | public function testMailNonProductionRun() { | |
209 | // Test in non-production mode. | |
9099cab3 | 210 | $params = [ |
f008885c | 211 | 'environment' => 'Staging', |
9099cab3 | 212 | ]; |
f008885c | 213 | $this->callAPISuccess('Setting', 'create', $params); |
288e5f75 JP |
214 | //Assert if outbound mail is disabled. |
215 | $mailingBackend = Civi::settings()->get('mailing_backend'); | |
216 | $this->assertEquals($mailingBackend['outBound_option'], CRM_Mailing_Config::OUTBOUND_OPTION_DISABLED); | |
217 | ||
f008885c | 218 | $this->createContactsInGroup(10, $this->_groupID); |
9099cab3 | 219 | Civi::settings()->add([ |
f008885c | 220 | 'mailerBatchLimit' => 2, |
9099cab3 | 221 | ]); |
f008885c | 222 | $this->callAPISuccess('mailing', 'create', $this->_params); |
9099cab3 | 223 | $this->_mut->assertRecipients([]); |
3241b690 | 224 | $result = $this->callAPIFailure('job', 'process_mailing', []); |
225 | $this->assertEquals($result['error_message'], "Job has not been executed as it is a Staging (non-production) environment."); | |
f008885c E |
226 | |
227 | // Test with runInNonProductionEnvironment param. | |
9099cab3 | 228 | $this->callAPISuccess('job', 'process_mailing', ['runInNonProductionEnvironment' => TRUE]); |
f008885c E |
229 | $this->_mut->assertRecipients($this->getRecipients(1, 2)); |
230 | ||
9099cab3 | 231 | $jobId = $this->callAPISuccessGetValue('Job', [ |
288e5f75 JP |
232 | 'return' => "id", |
233 | 'api_action' => "group_rebuild", | |
9099cab3 CW |
234 | ]); |
235 | $this->callAPISuccess('Job', 'create', [ | |
288e5f75 JP |
236 | 'id' => $jobId, |
237 | 'parameters' => "runInNonProductionEnvironment=TRUE", | |
9099cab3 | 238 | ]); |
288e5f75 JP |
239 | $jobManager = new CRM_Core_JobManager(); |
240 | $jobManager->executeJobById($jobId); | |
241 | ||
242 | //Assert if outbound mail is still disabled. | |
243 | $mailingBackend = Civi::settings()->get('mailing_backend'); | |
244 | $this->assertEquals($mailingBackend['outBound_option'], CRM_Mailing_Config::OUTBOUND_OPTION_DISABLED); | |
245 | ||
f008885c | 246 | // Test in production mode. |
9099cab3 | 247 | $params = [ |
f008885c | 248 | 'environment' => 'Production', |
9099cab3 | 249 | ]; |
f008885c | 250 | $this->callAPISuccess('Setting', 'create', $params); |
9099cab3 | 251 | $this->callAPISuccess('job', 'process_mailing', []); |
f008885c E |
252 | $this->_mut->assertRecipients($this->getRecipients(1, 2)); |
253 | } | |
254 | ||
d667a9ba | 255 | public function concurrencyExamples() { |
9099cab3 | 256 | $es = []; |
d667a9ba TO |
257 | |
258 | // Launch 3 workers, but mailerJobsMax limits us to 1 worker. | |
9099cab3 CW |
259 | $es[0] = [ |
260 | [ | |
d667a9ba TO |
261 | 'recipients' => 20, |
262 | 'workers' => 3, | |
a2341a99 TO |
263 | // FIXME: lockHold is unrealistic/unrepresentative. In reality, this situation fails because |
264 | // the data.* locks trample the worker.* locks. However, setting lockHold allows us to | |
265 | // approximate the behavior of what would happen *if* the lock-implementation didn't suffer | |
266 | // trampling effects. | |
d667a9ba TO |
267 | 'lockHold' => 10, |
268 | 'mailerBatchLimit' => 4, | |
269 | 'mailerJobsMax' => 1, | |
9099cab3 CW |
270 | ], |
271 | [ | |
39b9dbb3 | 272 | // 2 jobs which produce 0 messages |
39b959db | 273 | 0 => 2, |
39b9dbb3 | 274 | // 1 job which produces 4 messages |
39b959db | 275 | 4 => 1, |
9099cab3 | 276 | ], |
d667a9ba | 277 | 4, |
9099cab3 | 278 | ]; |
d667a9ba TO |
279 | |
280 | // Launch 3 workers, but mailerJobsMax limits us to 2 workers. | |
9099cab3 | 281 | $es[1] = [ |
39b959db | 282 | // Settings. |
9099cab3 | 283 | [ |
d667a9ba TO |
284 | 'recipients' => 20, |
285 | 'workers' => 3, | |
a2341a99 TO |
286 | // FIXME: lockHold is unrealistic/unrepresentative. In reality, this situation fails because |
287 | // the data.* locks trample the worker.* locks. However, setting lockHold allows us to | |
288 | // approximate the behavior of what would happen *if* the lock-implementation didn't suffer | |
289 | // trampling effects. | |
d667a9ba TO |
290 | 'lockHold' => 10, |
291 | 'mailerBatchLimit' => 5, | |
292 | 'mailerJobsMax' => 2, | |
9099cab3 | 293 | ], |
39b959db | 294 | // Tallies. |
9099cab3 | 295 | [ |
39b959db SL |
296 | // 1 job which produce 0 messages |
297 | 0 => 1, | |
298 | // 2 jobs which produce 5 messages | |
299 | 5 => 2, | |
9099cab3 | 300 | ], |
39b959db SL |
301 | // Total sent. |
302 | 10, | |
9099cab3 | 303 | ]; |
d667a9ba TO |
304 | |
305 | // Launch 3 workers and saturate them (mailerJobsMax=3) | |
9099cab3 | 306 | $es[2] = [ |
39b959db | 307 | // Settings. |
9099cab3 | 308 | [ |
d667a9ba TO |
309 | 'recipients' => 20, |
310 | 'workers' => 3, | |
d667a9ba TO |
311 | 'mailerBatchLimit' => 6, |
312 | 'mailerJobsMax' => 3, | |
9099cab3 | 313 | ], |
39b959db | 314 | // Tallies. |
9099cab3 | 315 | [ |
39b959db SL |
316 | // 3 jobs which produce 6 messages |
317 | 6 => 3, | |
9099cab3 | 318 | ], |
39b959db SL |
319 | // Total sent. |
320 | 18, | |
9099cab3 | 321 | ]; |
d667a9ba TO |
322 | |
323 | // Launch 4 workers and saturate them (mailerJobsMax=0) | |
9099cab3 | 324 | $es[3] = [ |
39b959db | 325 | // Settings. |
9099cab3 | 326 | [ |
d667a9ba TO |
327 | 'recipients' => 20, |
328 | 'workers' => 4, | |
d667a9ba TO |
329 | 'mailerBatchLimit' => 6, |
330 | 'mailerJobsMax' => 0, | |
9099cab3 | 331 | ], |
39b959db | 332 | // Tallies. |
9099cab3 | 333 | [ |
39b959db SL |
334 | // 3 jobs which produce 6 messages |
335 | 6 => 3, | |
336 | // 1 job which produces 2 messages | |
337 | 2 => 1, | |
9099cab3 | 338 | ], |
39b959db SL |
339 | // Total sent. |
340 | 20, | |
9099cab3 | 341 | ]; |
d667a9ba TO |
342 | |
343 | // Launch 1 worker, 3 times in a row. Deliver everything. | |
9099cab3 | 344 | $es[4] = [ |
39b959db | 345 | // Settings. |
9099cab3 | 346 | [ |
d667a9ba TO |
347 | 'recipients' => 10, |
348 | 'workers' => 1, | |
349 | 'iterations' => 3, | |
350 | 'mailerBatchLimit' => 7, | |
9099cab3 | 351 | ], |
39b959db | 352 | // Tallies. |
9099cab3 | 353 | [ |
39b959db SL |
354 | // 1 job which produces 7 messages |
355 | 7 => 1, | |
356 | // 1 job which produces 3 messages | |
357 | 3 => 1, | |
358 | // 1 job which produces 0 messages | |
359 | 0 => 1, | |
9099cab3 | 360 | ], |
39b959db SL |
361 | // Total sent. |
362 | 10, | |
9099cab3 | 363 | ]; |
d667a9ba TO |
364 | |
365 | // Launch 2 worker, 3 times in a row. Deliver everything. | |
9099cab3 | 366 | $es[5] = [ |
39b959db | 367 | // Settings. |
9099cab3 | 368 | [ |
d667a9ba TO |
369 | 'recipients' => 10, |
370 | 'workers' => 2, | |
371 | 'iterations' => 3, | |
372 | 'mailerBatchLimit' => 3, | |
9099cab3 | 373 | ], |
39b959db | 374 | // Tallies. |
9099cab3 | 375 | [ |
39b959db SL |
376 | // 3 jobs which produce 3 messages |
377 | 3 => 3, | |
378 | // 1 job which produces 1 messages | |
379 | 1 => 1, | |
380 | // 2 jobs which produce 0 messages | |
381 | 0 => 2, | |
9099cab3 | 382 | ], |
39b959db SL |
383 | // Total sent. |
384 | 10, | |
9099cab3 | 385 | ]; |
d667a9ba | 386 | |
502eefb0 | 387 | // For two mailings, launch 1 worker, 5 times in a row. Deliver everything. |
9099cab3 | 388 | $es[6] = [ |
39b959db | 389 | // Settings. |
9099cab3 | 390 | [ |
502eefb0 TO |
391 | 'mailings' => 2, |
392 | 'recipients' => 10, | |
393 | 'workers' => 1, | |
394 | 'iterations' => 5, | |
395 | 'mailerBatchLimit' => 6, | |
9099cab3 | 396 | ], |
39b959db | 397 | // Tallies. |
9099cab3 | 398 | [ |
502eefb0 | 399 | // x6 => x4+x2 => x6 => x2 => x0 |
39b959db SL |
400 | // 3 jobs which produce 6 messages |
401 | 6 => 3, | |
402 | // 1 job which produces 2 messages | |
403 | 2 => 1, | |
404 | // 1 job which produces 0 messages | |
405 | 0 => 1, | |
9099cab3 | 406 | ], |
39b959db SL |
407 | // Total sent. |
408 | 20, | |
9099cab3 | 409 | ]; |
502eefb0 | 410 | |
d667a9ba TO |
411 | return $es; |
412 | } | |
413 | ||
414 | /** | |
415 | * Setup various mail configuration options (eg $mailerBatchLimit, | |
416 | * $mailerJobMax) and spawn multiple worker threads ($workers). | |
417 | * Allow the threads to complete. (Optionally, repeat the above | |
418 | * process.) Finally, check to see if the right number of | |
419 | * jobs delivered the right number of messages. | |
420 | * | |
421 | * @param array $settings | |
422 | * An array of settings (eg mailerBatchLimit, workers). See comments | |
423 | * for $this->defaultSettings. | |
424 | * @param array $expectedTallies | |
425 | * A listing of the number cron-runs keyed by their size. | |
426 | * For example, array(10=>2) means that there 2 cron-runs | |
427 | * which delivered 10 messages each. | |
428 | * @param int $expectedTotal | |
429 | * The total number of contacts for whom messages should have | |
430 | * been sent. | |
431 | * @dataProvider concurrencyExamples | |
432 | */ | |
433 | public function testConcurrency($settings, $expectedTallies, $expectedTotal) { | |
434 | $settings = array_merge($this->defaultSettings, $settings); | |
435 | ||
436 | $this->createContactsInGroup($settings['recipients'], $this->_groupID); | |
9099cab3 | 437 | Civi::settings()->add(CRM_Utils_Array::subset($settings, [ |
d667a9ba TO |
438 | 'mailerBatchLimit', |
439 | 'mailerJobsMax', | |
440 | 'mailThrottleTime', | |
9099cab3 | 441 | ])); |
d667a9ba | 442 | |
502eefb0 TO |
443 | for ($i = 0; $i < $settings['mailings']; $i++) { |
444 | $this->callAPISuccess('mailing', 'create', $this->_params); | |
445 | } | |
d667a9ba | 446 | |
9099cab3 | 447 | $this->_mut->assertRecipients([]); |
d667a9ba | 448 | |
9099cab3 | 449 | $allApiResults = []; |
d667a9ba TO |
450 | for ($iterationId = 0; $iterationId < $settings['iterations']; $iterationId++) { |
451 | $apiCalls = $this->createExternalAPI(); | |
9099cab3 | 452 | $apiCalls->addEnv(['CIVICRM_CRON_HOLD' => $settings['lockHold']]); |
d667a9ba | 453 | for ($workerId = 0; $workerId < $settings['workers']; $workerId++) { |
9099cab3 | 454 | $apiCalls->addCall('job', 'process_mailing', []); |
d667a9ba TO |
455 | } |
456 | $apiCalls->start(); | |
457 | $this->assertEquals($settings['workers'], $apiCalls->getRunningCount()); | |
458 | ||
459 | $apiCalls->wait(); | |
460 | $allApiResults = array_merge($allApiResults, $apiCalls->getResults()); | |
461 | } | |
462 | ||
463 | $actualTallies = $this->tallyApiResults($allApiResults); | |
9099cab3 | 464 | $this->assertEquals($expectedTallies, $actualTallies, 'API tallies should match.' . print_r([ |
39b959db SL |
465 | 'expectedTallies' => $expectedTallies, |
466 | 'actualTallies' => $actualTallies, | |
467 | 'apiResults' => $allApiResults, | |
9099cab3 | 468 | ], TRUE)); |
502eefb0 | 469 | $this->_mut->assertRecipients($this->getRecipients(1, $expectedTotal / $settings['mailings'], 'nul.example.com', $settings['mailings'])); |
d667a9ba TO |
470 | $this->assertEquals(0, $apiCalls->getRunningCount()); |
471 | } | |
472 | ||
07c09ae4 | 473 | /** |
54957108 | 474 | * Create contacts in group. |
475 | * | |
e16033b4 TO |
476 | * @param int $count |
477 | * @param int $groupID | |
54957108 | 478 | * @param string $domain |
07c09ae4 | 479 | */ |
d667a9ba | 480 | public function createContactsInGroup($count, $groupID, $domain = 'nul.example.com') { |
481a74f4 | 481 | for ($i = 1; $i <= $count; $i++) { |
9099cab3 CW |
482 | $contactID = $this->individualCreate(['first_name' => $count, 'email' => 'mail' . $i . '@' . $domain]); |
483 | $this->callAPISuccess('group_contact', 'create', [ | |
d667a9ba TO |
484 | 'contact_id' => $contactID, |
485 | 'group_id' => $groupID, | |
486 | 'status' => 'Added', | |
9099cab3 | 487 | ]); |
07c09ae4 EM |
488 | } |
489 | } | |
490 | ||
491 | /** | |
d667a9ba TO |
492 | * Construct the list of email addresses for $count recipients. |
493 | * | |
e16033b4 TO |
494 | * @param int $start |
495 | * @param int $count | |
502eefb0 TO |
496 | * @param string $domain |
497 | * @param int $mailings | |
07c09ae4 EM |
498 | * |
499 | * @return array | |
500 | */ | |
502eefb0 | 501 | public function getRecipients($start, $count, $domain = 'nul.example.com', $mailings = 1) { |
9099cab3 | 502 | $recipients = []; |
502eefb0 TO |
503 | for ($m = 0; $m < $mailings; $m++) { |
504 | for ($i = $start; $i < ($start + $count); $i++) { | |
505 | $recipients[][0] = 'mail' . $i . '@' . $domain; | |
506 | } | |
07c09ae4 EM |
507 | } |
508 | return $recipients; | |
509 | } | |
96025800 | 510 | |
d667a9ba | 511 | protected function cleanupMailingTest() { |
9099cab3 | 512 | $this->quickCleanup([ |
d667a9ba TO |
513 | 'civicrm_mailing', |
514 | 'civicrm_mailing_job', | |
515 | 'civicrm_mailing_spool', | |
516 | 'civicrm_mailing_group', | |
517 | 'civicrm_mailing_recipients', | |
518 | 'civicrm_mailing_event_queue', | |
519 | 'civicrm_mailing_event_bounce', | |
520 | 'civicrm_mailing_event_delivered', | |
521 | 'civicrm_group', | |
522 | 'civicrm_group_contact', | |
523 | 'civicrm_contact', | |
9099cab3 | 524 | ]); |
d667a9ba TO |
525 | } |
526 | ||
527 | /** | |
528 | * Categorize results based on (a) whether they succeeded | |
529 | * and (b) the number of messages sent. | |
530 | * | |
531 | * @param array $apiResults | |
532 | * @return array | |
533 | * One key 'error' for all failures. | |
534 | * A separate key for each distinct quantity. | |
535 | */ | |
536 | protected function tallyApiResults($apiResults) { | |
9099cab3 | 537 | $ret = []; |
d667a9ba TO |
538 | foreach ($apiResults as $apiResult) { |
539 | $key = !empty($apiResult['is_error']) ? 'error' : $apiResult['values']['processed']; | |
540 | $ret[$key] = !empty($ret[$key]) ? 1 + $ret[$key] : 1; | |
541 | } | |
542 | return $ret; | |
543 | } | |
544 | ||
07c09ae4 | 545 | } |