Skip to content

Commit 3ea736c

Browse files
authored
[full-ci][tests-only] test: check last email content with retries as emails can be delayed (#2038)
* test: check last email content with retries Signed-off-by: Saw-jan <saw.jan.grg3e@gmail.com> * test: cleanup unused const Signed-off-by: Saw-jan <saw.jan.grg3e@gmail.com> --------- Signed-off-by: Saw-jan <saw.jan.grg3e@gmail.com>
1 parent eb1545c commit 3ea736c

4 files changed

Lines changed: 77 additions & 87 deletions

File tree

tests/acceptance/TestHelpers/EmailHelper.php

Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,10 @@ public static function getBodyOfAnEmailById(
127127
}
128128

129129
/**
130-
* Returns the body of the last received email for the provided receiver according to the provided email address and the serial number
131-
* For email number, 1 means the latest one
130+
* Returns the body of the last received email for the provided receiver
132131
*
133132
* @param string $emailAddress
134-
* @param string|null $xRequestId
135-
* @param int|null $emailNumber For email number, 1 means the latest one
136-
* @param int|null $waitTimeSec Time to wait for the email if the email has been delivered
133+
* @param string $xRequestId
137134
*
138135
* @return string
139136
* @throws GuzzleException
@@ -142,48 +139,40 @@ public static function getBodyOfAnEmailById(
142139
public static function getBodyOfLastEmail(
143140
string $emailAddress,
144141
string $xRequestId,
145-
?int $emailNumber = 1,
146-
?int $waitTimeSec = EMAIL_WAIT_TIMEOUT_SEC
147142
): string {
148-
$currentTime = \time();
149-
$endTime = $currentTime + $waitTimeSec;
150143
$mailBox = self::getMailBoxFromEmail($emailAddress);
151-
while ($currentTime <= $endTime) {
152-
$mailboxResponse = self::getMailboxInformation($mailBox, $xRequestId);
153-
if (!empty($mailboxResponse) && \sizeof($mailboxResponse) >= $emailNumber) {
154-
$mailboxId = $mailboxResponse[\sizeof($mailboxResponse) - $emailNumber]->id;
155-
$response = self::getBodyOfAnEmailById($mailBox, $mailboxId, $xRequestId);
156-
$body = \str_replace(
157-
"\r\n",
158-
"\n",
159-
\quoted_printable_decode($response->body->text . "\n" . $response->body->html)
160-
);
161-
return $body;
162-
}
163-
\usleep(STANDARD_SLEEP_TIME_MICROSEC * 50);
164-
$currentTime = \time();
144+
$emails = self::getMailboxInformation($mailBox, $xRequestId);
145+
if (!empty($emails)) {
146+
$emailId = \array_pop($emails)->id;
147+
$response = self::getBodyOfAnEmailById($mailBox, $emailId, $xRequestId);
148+
$body = \str_replace(
149+
"\r\n",
150+
"\n",
151+
\quoted_printable_decode($response->body->text . "\n" . $response->body->html)
152+
);
153+
return $body;
165154
}
166-
throw new Exception("Could not find the email to the address: " . $emailAddress);
155+
return "";
167156
}
168157

169158
/**
170159
* Deletes all the emails for the provided mailbox
171160
*
172-
* @param string $localInbucketUrl
173-
* @param string|null $xRequestId
161+
* @param string $url
174162
* @param string $mailBox
163+
* @param string $xRequestId
175164
*
176165
* @return ResponseInterface
177166
* @throws GuzzleException
178167
*/
179-
public static function deleteAllEmailsForAMailbox(
180-
string $localInbucketUrl,
181-
?string $xRequestId,
182-
string $mailBox
168+
public static function deleteAllEmails(
169+
string $url,
170+
string $mailBox,
171+
string $xRequestId,
183172
): ResponseInterface {
184173
return HttpRequestHelper::delete(
185-
$localInbucketUrl . "/api/v1/mailbox/" . $mailBox,
186-
$xRequestId
174+
$url . "/api/v1/mailbox/" . $mailBox,
175+
$xRequestId,
187176
);
188177
}
189178
}

tests/acceptance/TestHelpers/HttpRequestHelper.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class HttpRequestHelper {
5757
public static function numRetriesOnHttpTooEarly(): int {
5858
// Currently reva and OpenCloud may return HTTP_TOO_EARLY
5959
// So try up to 10 times before giving up.
60-
return 10;
60+
return STANDARD_RETRY_COUNT;
6161
}
6262

6363
/**
@@ -732,7 +732,7 @@ public static function parseResponseAsXml(ResponseInterface $response): array {
732732
*/
733733
public static function getRequestTimeout(): int {
734734
$timeout = \getenv("REQUEST_TIMEOUT");
735-
return (int)$timeout ?: 60;
735+
return (int)$timeout ?: HTTP_REQUEST_TIMEOUT;
736736
}
737737

738738
/**

tests/acceptance/bootstrap/NotificationContext.php

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -589,36 +589,68 @@ public function assertEmailContains(
589589
): void {
590590
$address = $this->featureContext->getEmailAddressForUser($user);
591591
$this->featureContext->pushEmailRecipientAsMailBox($address);
592-
$actualEmailBodyContent = EmailHelper::getBodyOfLastEmail($address, $this->featureContext->getStepLineRef());
593-
if ($ignoreWhiteSpace) {
594-
$expectedEmailBodyContent = preg_replace('/\s+/', '', $expectedEmailBodyContent);
595-
$actualEmailBodyContent = preg_replace('/\s+/', '', $actualEmailBodyContent);
596-
}
592+
593+
// assert with retries as email delivery might be delayed
594+
$retried = 0;
595+
do {
596+
$actualEmailBodyContent = EmailHelper::getBodyOfLastEmail(
597+
$address,
598+
$this->featureContext->getStepLineRef()
599+
);
600+
if ($ignoreWhiteSpace) {
601+
$expectedEmailBodyContent = preg_replace('/\s+/', '', $expectedEmailBodyContent);
602+
$actualEmailBodyContent = preg_replace('/\s+/', '', $actualEmailBodyContent);
603+
}
604+
$tryAgain = !\str_contains($actualEmailBodyContent, $expectedEmailBodyContent)
605+
&& $retried <= STANDARD_RETRY_COUNT;
606+
$retried++;
607+
if ($tryAgain) {
608+
$mailBox = EmailHelper::getMailBoxFromEmail($address);
609+
echo "[INFO] Checking last email content for '$mailBox'. (Retry $retried)\n";
610+
// wait for 1 second before trying again
611+
sleep(1);
612+
}
613+
} while ($tryAgain);
597614
Assert::assertStringContainsString(
598615
$expectedEmailBodyContent,
599616
$actualEmailBodyContent,
600617
"The email address '$address' should have received an"
601-
. "email with the body containing $expectedEmailBodyContent
602-
but the received email is $actualEmailBodyContent"
618+
. " email with the body containing '$expectedEmailBodyContent'"
619+
. " but the received email is '$actualEmailBodyContent'"
603620
);
604621
}
605622

606623
/**
607-
* Delete all the inbucket emails
624+
* Delete all emails from the mailboxes
608625
*
609626
* @AfterScenario @email
610627
*
611628
* @return void
612629
*/
613-
public function clearInbucketMessages(): void {
630+
public function clearMailboxes(): void {
631+
$users = \array_keys($this->featureContext->getCreatedUsers());
614632
try {
615-
if (!empty($this->featureContext->emailRecipients)) {
616-
foreach ($this->featureContext->emailRecipients as $emailRecipient) {
617-
EmailHelper::deleteAllEmailsForAMailbox(
618-
EmailHelper::getLocalEmailUrl(),
619-
$this->featureContext->getStepLineRef(),
620-
$emailRecipient
621-
);
633+
if (!empty($users)) {
634+
foreach ($users as $emailRecipient) {
635+
$retried = 0;
636+
do {
637+
$res = EmailHelper::deleteAllEmails(
638+
EmailHelper::getLocalEmailUrl(),
639+
$emailRecipient,
640+
$this->featureContext->getStepLineRef(),
641+
);
642+
$deleteStatus = $res->getStatusCode();
643+
$mailBox = EmailHelper::getMailboxInformation($emailRecipient);
644+
$tryAgain = ($deleteStatus !== 200 || !empty($mailBox)) && $retried <= STANDARD_RETRY_COUNT;
645+
$retried++;
646+
if ($tryAgain) {
647+
echo "[INFO] Clearing mailbox '$emailRecipient'."
648+
. " Status: $deleteStatus. Emails: " . \count($mailBox) . "."
649+
. " (Retry $retried)\n";
650+
// wait for 1 second before trying again
651+
sleep(1);
652+
}
653+
} while ($tryAgain);
622654
}
623655
}
624656
} catch (Exception $e) {

tests/acceptance/bootstrap/bootstrap.php

Lines changed: 6 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -27,51 +27,20 @@
2727

2828
$classLoader->register();
2929

30-
// Sleep for 10 milliseconds
31-
if (!\defined('STANDARD_SLEEP_TIME_MILLISEC')) {
32-
\define('STANDARD_SLEEP_TIME_MILLISEC', 10);
33-
}
34-
35-
if (!\defined('STANDARD_SLEEP_TIME_MICROSEC')) {
36-
\define('STANDARD_SLEEP_TIME_MICROSEC', STANDARD_SLEEP_TIME_MILLISEC * 1000);
37-
}
38-
39-
// Long timeout for use in code that needs to wait for known slow UI
40-
if (!\defined('LONG_UI_WAIT_TIMEOUT_MILLISEC')) {
41-
\define('LONG_UI_WAIT_TIMEOUT_MILLISEC', 60000);
42-
}
43-
44-
// Default timeout for use in code that needs to wait for the UI
45-
if (!\defined('STANDARD_UI_WAIT_TIMEOUT_MILLISEC')) {
46-
\define('STANDARD_UI_WAIT_TIMEOUT_MILLISEC', 10000);
47-
}
48-
49-
// Minimum timeout for use in code that needs to wait for the UI
50-
if (!\defined('MINIMUM_UI_WAIT_TIMEOUT_MILLISEC')) {
51-
\define('MINIMUM_UI_WAIT_TIMEOUT_MILLISEC', 500);
52-
}
53-
54-
if (!\defined('MINIMUM_UI_WAIT_TIMEOUT_MICROSEC')) {
55-
\define('MINIMUM_UI_WAIT_TIMEOUT_MICROSEC', MINIMUM_UI_WAIT_TIMEOUT_MILLISEC * 1000);
56-
}
57-
58-
// Minimum timeout for emails
59-
if (!\defined('EMAIL_WAIT_TIMEOUT_SEC')) {
60-
\define('EMAIL_WAIT_TIMEOUT_SEC', 10);
61-
}
62-
if (!\defined('EMAIL_WAIT_TIMEOUT_MILLISEC')) {
63-
\define('EMAIL_WAIT_TIMEOUT_MILLISEC', EMAIL_WAIT_TIMEOUT_SEC * 1000);
64-
}
65-
6630
// Default number of times to retry where retries are useful
6731
if (!\defined('STANDARD_RETRY_COUNT')) {
68-
\define('STANDARD_RETRY_COUNT', 5);
32+
\define('STANDARD_RETRY_COUNT', 10);
6933
}
7034
// Minimum number of times to retry where retries are useful
7135
if (!\defined('MINIMUM_RETRY_COUNT')) {
7236
\define('MINIMUM_RETRY_COUNT', 2);
7337
}
7438

39+
// Minimum number of times to retry where retries are useful
40+
if (!\defined('HTTP_REQUEST_TIMEOUT')) {
41+
\define('HTTP_REQUEST_TIMEOUT', 60);
42+
}
43+
7544
// The remote server-under-test might or might not happen to have this directory.
7645
// If it does not exist, then the tests may end up creating it.
7746
if (!\defined('ACCEPTANCE_TEST_DIR_ON_REMOTE_SERVER')) {

0 commit comments

Comments
 (0)