From d7f919f5dfb03b6b02cc8295c369f6fe67f71c89 Mon Sep 17 00:00:00 2001
From: Chloe Liban <chloe.liban@gmail.com>
Date: Fri, 26 Mar 2021 11:46:11 +0100
Subject: [PATCH] chore(CTS): fix flakiness

---
 src/SearchClient.php                      |  2 +-
 tests/Integration/AnalyticsClientTest.php | 10 +++-
 tests/Integration/BaseTest.php            |  1 +
 tests/Integration/SearchClientTest.php    | 63 +++++------------------
 tests/Integration/SecuredApiKeysTest.php  |  5 +-
 tests/TestHelper.php                      | 15 ++++++
 6 files changed, 43 insertions(+), 53 deletions(-)

diff --git a/src/SearchClient.php b/src/SearchClient.php
index fbd23a70c..ad2b77906 100644
--- a/src/SearchClient.php
+++ b/src/SearchClient.php
@@ -155,7 +155,7 @@ public function isAlive($requestOptions = array())
 
     public function multipleQueries($queries, $requestOptions = array())
     {
-        $queries = array_map(function($query) {
+        $queries = array_map(function ($query) {
             $query['params'] = isset($query['params']) ?
                 Helpers::serializeQueryParameters($query['params']) :
                 Helpers::serializeQueryParameters(array());
diff --git a/tests/Integration/AnalyticsClientTest.php b/tests/Integration/AnalyticsClientTest.php
index d1842198f..cf1ab1869 100644
--- a/tests/Integration/AnalyticsClientTest.php
+++ b/tests/Integration/AnalyticsClientTest.php
@@ -61,7 +61,10 @@ public function testAbTesting()
             $cpt++;
         } while (false);
 
-        $response = $analyticsClient->addABTest($abTest);
+        $response = TestHelper::retry(function () use ($analyticsClient, $abTest) {
+            return $analyticsClient->addABTest($abTest);
+        }, 1000, 30);
+
         $abTestId = $response['abTestID'];
         $index->waitTask($response['taskID']);
 
@@ -160,7 +163,10 @@ public function testAaTesting()
             $cpt++;
         } while (false);
 
-        $response = $analyticsClient->addABTest($aaTest);
+        $response = TestHelper::retry(function () use ($analyticsClient, $aaTest) {
+            return $analyticsClient->addABTest($aaTest);
+        }, 1000, 30);
+
         $aaTestId = $response['abTestID'];
         TestHelper::getClient()->waitTask($this->indexes['aa_testing'], $response['taskID']);
 
diff --git a/tests/Integration/BaseTest.php b/tests/Integration/BaseTest.php
index 805668293..910330cd5 100644
--- a/tests/Integration/BaseTest.php
+++ b/tests/Integration/BaseTest.php
@@ -15,6 +15,7 @@ public static function setUpBeforeClass()
             TestHelper::checkEnvironmentVariables();
         } catch (\Exception $e) {
             echo $e->getMessage()."\n";
+
             return;
         }
 
diff --git a/tests/Integration/SearchClientTest.php b/tests/Integration/SearchClientTest.php
index 266710475..7bb62d481 100644
--- a/tests/Integration/SearchClientTest.php
+++ b/tests/Integration/SearchClientTest.php
@@ -2,7 +2,6 @@
 
 namespace Algolia\AlgoliaSearch\Tests\Integration;
 
-use Algolia\AlgoliaSearch\Exceptions\NotFoundException;
 use Algolia\AlgoliaSearch\Response\MultiResponse;
 use Algolia\AlgoliaSearch\SearchClient;
 use Algolia\AlgoliaSearch\SearchIndex;
@@ -271,29 +270,13 @@ public function testApiKeys()
 
         TestHelper::getClient()->updateApiKey($res['key'], $newParams)->wait();
 
-        $retry = 1;
-        $time = 100000;
-        $maxRetries = 100;
-        do {
-            if ($retry >= $maxRetries) {
-                break;
-            }
-
-            try {
-                $updatedApiKey = TestHelper::getClient()->getApiKey($res['key']);
-
-                if ($updatedApiKey['maxHitsPerQuery'] !== $apiKey['maxHitsPerQuery']) {
-                    $this->assertEquals(42, $updatedApiKey['maxHitsPerQuery']);
-                    break;
-                }
-            } catch (NotFoundException $e) {
-                // Try again
-            }
+        $updatedApiKey = TestHelper::retry(function () use ($res) {
+            return TestHelper::getClient()->getApiKey($res['key']);
+        }, 1000, 30);
 
-            $retry++;
-            $factor = ceil($retry / 10);
-            usleep($factor * $time); // 0.1 second
-        } while (true);
+        if ($updatedApiKey['maxHitsPerQuery'] !== $apiKey['maxHitsPerQuery']) {
+            $this->assertEquals(42, $updatedApiKey['maxHitsPerQuery']);
+        }
 
         TestHelper::getClient()->deleteApiKey($res['key'])->wait();
 
@@ -303,34 +286,16 @@ public function testApiKeys()
             $this->assertInstanceOf('Algolia\AlgoliaSearch\Exceptions\NotFoundException', $e);
         }
 
-        $retry = 1;
-        $time = 100000;
-        $maxRetries = 100;
-        do {
-            try {
-                TestHelper::getClient()->restoreApiKey($res['key'])->wait();
-            } catch (NotFoundException $e) {
-                $retry++;
-                $factor = ceil($retry / 10);
-                usleep($factor * $time); // 0.1 second
-                continue;
-            }
+        TestHelper::retry(function () use ($res) {
+            TestHelper::getClient()->restoreApiKey($res['key'])->wait();
+        }, 1000, 30);
 
-        } while ($retry >= $maxRetries);
-
-        do {
-            try {
-                $restoredApiKey = TestHelper::getClient()->getApiKey($res['key']);
-                $this->assertEquals($acl, $restoredApiKey['acl']);
-                $this->assertEquals($params['description'], $restoredApiKey['description']);
-            } catch (NotFoundException $e) {
-                $retry++;
-                $factor = ceil($retry / 10);
-                usleep($factor * $time); // 0.1 second
-                continue;
-            }
+        $restoredApiKey = TestHelper::retry(function () use ($res) {
+            return TestHelper::getClient()->getApiKey($res['key']);
+        }, 1000, 30);
 
-        } while ($retry >= $maxRetries);
+        $this->assertEquals($acl, $restoredApiKey['acl']);
+        $this->assertEquals($params['description'], $restoredApiKey['description']);
 
         TestHelper::getClient()->deleteApiKey($res['key'])->wait();
     }
diff --git a/tests/Integration/SecuredApiKeysTest.php b/tests/Integration/SecuredApiKeysTest.php
index 7037101e8..dff7369ae 100644
--- a/tests/Integration/SecuredApiKeysTest.php
+++ b/tests/Integration/SecuredApiKeysTest.php
@@ -52,7 +52,10 @@ public function testSecuredApiKeys()
         /** @var SearchIndex $securedIndexDev */
         $securedIndexDev = $securedClient->initIndex($this->indexes['secured_api_keys_dev']);
 
-        $res = $securedIndex->search('');
+        $res = TestHelper::retry(function () use ($securedIndex) {
+            return $securedIndex->search('');
+        }, 1000, 30);
+
         $this->assertCount(1, $res['hits']);
 
         try {
diff --git a/tests/TestHelper.php b/tests/TestHelper.php
index a9ed06a00..a7697b92b 100644
--- a/tests/TestHelper.php
+++ b/tests/TestHelper.php
@@ -3,6 +3,7 @@
 namespace Algolia\AlgoliaSearch\Tests;
 
 use Algolia\AlgoliaSearch\Config\SearchConfig;
+use Algolia\AlgoliaSearch\Exceptions\NotFoundException;
 use Algolia\AlgoliaSearch\SearchClient;
 use Faker\Factory;
 
@@ -107,4 +108,18 @@ public static function formatRule($rule)
 
         return $rule;
     }
+
+    public static function retry($function, $delay, $maxRetries)
+    {
+        for ($i = 1; $i < $maxRetries; $i++) {
+            try {
+                return $function();
+            } catch (NotFoundException $e) {
+                usleep($delay * $i);
+                continue;
+            }
+        }
+
+        throw new \Exception('reached the maximum number of retries');
+    }
 }