Completed
Push — v0.10 ( f42b97...309689 )
by Simonas
8s
created

AbstractElasticsearchTestCase::getManager()   D

Complexity

Conditions 9
Paths 33

Size

Total Lines 41
Code Lines 22

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 41
rs 4.909
cc 9
eloc 22
nc 33
nop 3
1
<?php
2
3
/*
4
 * This file is part of the ONGR package.
5
 *
6
 * (c) NFQ Technologies UAB <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace ONGR\ElasticsearchBundle\Test;
13
14
use Elasticsearch\Common\Exceptions\ElasticsearchException;
15
use ONGR\ElasticsearchBundle\Client\Connection;
16
use ONGR\ElasticsearchBundle\ORM\Manager;
17
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
18
use Symfony\Component\DependencyInjection\ContainerInterface;
19
20
/**
21
 * Base test which creates unique connection to test with.
22
 */
23
abstract class AbstractElasticsearchTestCase extends WebTestCase
24
{
25
    /**
26
     * @var Manager[] Holds used managers.
27
     */
28
    private $managers = [];
29
30
    /**
31
     * @var ContainerInterface
32
     */
33
    private $container;
34
35
    /**
36
     * {@inheritdoc}
37
     */
38
    public function runTest()
39
    {
40
        if ($this->getNumberOfRetries() < 1) {
41
            return parent::runTest();
42
        }
43
44
        foreach (range(1, $this->getNumberOfRetries()) as $try) {
45
            try {
46
                return parent::runTest();
47
            } catch (\Exception $e) {
48
                if (!($e instanceof ElasticsearchException)) {
49
                    throw $e;
50
                }
51
                // If error was from elasticsearch re-setup tests and retry.
52
                if ($try !== $this->getNumberOfRetries()) {
53
                    $this->tearDown();
54
                    $this->setUp();
55
                }
56
            }
57
        }
58
59
        throw $e;
60
    }
61
62
    /**
63
     * {@inheritdoc}
64
     */
65
    protected function setUp()
66
    {
67
        $this->getContainer();
68
        $this->getManager();
69
    }
70
71
    /**
72
     * Returns number of retries tests should execute.
73
     *
74
     * @return int
75
     */
76
    protected function getNumberOfRetries()
77
    {
78
        return 0;
79
    }
80
81
    /**
82
     * Can be overwritten in child class to populate elasticsearch index with data.
83
     *
84
     * Example:
85
     *      "managername" =>
86
     *      [
87
     *          'acmetype' => [
88
     *              [
89
     *                  '_id' => 1,
90
     *                  'title' => 'foo',
91
     *              ],
92
     *              [
93
     *                  '_id' => 2,
94
     *                  'title' => 'bar',
95
     *              ]
96
     *          ]
97
     *      ]
98
     *
99
     * @return array
100
     */
101
    protected function getDataArray()
102
    {
103
        return [];
104
    }
105
106
    /**
107
     * Ignores versions specified.
108
     *
109
     * Returns two dimensional array, first item in sub array is version to ignore, second is comparator,
110
     * last test name. If no test name is provided it will be used on all test class.
111
     *
112
     * Comparator types can be found in `version_compare` documentation.
113
     *
114
     * Example: [
115
     *   ['1.2.7', '<='],
116
     *   ['1.2.9', '==', 'testSmth']
117
     * ]
118
     *
119
     * @return array
120
     */
121
    protected function getIgnoredVersions()
122
    {
123
        return [];
124
    }
125
126
    /**
127
     * Ignores version specified.
128
     *
129
     * @param Connection $connection
130
     */
131
    protected function ignoreVersions(Connection $connection)
132
    {
133
        $currentVersion = $connection->getVersionNumber();
134
        $ignore = null;
135
136
        foreach ($this->getIgnoredVersions() as $ignoredVersion) {
137
            if (version_compare($currentVersion, $ignoredVersion[0], $ignoredVersion[1]) === true) {
138
                $ignore = true;
139
                if (isset($ignoredVersion[2])) {
140
                    if ($ignoredVersion[2] === $this->getName()) {
141
                        break;
142
                    }
143
                    $ignore = false;
144
                }
145
            }
146
        }
147
148
        if ($ignore === true) {
149
            $this->markTestSkipped("Elasticsearch version {$currentVersion} not supported by this test.");
150
        }
151
    }
152
153
    /**
154
     * Removes manager from local cache and drops its index.
155
     *
156
     * @param string $name
157
     */
158
    protected function removeManager($name)
159
    {
160
        if (isset($this->managers[$name])) {
161
            $this->managers[$name]->getConnection()->dropIndex();
162
            unset($this->managers[$name]);
163
        }
164
    }
165
166
    /**
167
     * Populates elasticsearch with data.
168
     *
169
     * @param Manager $manager
170
     * @param array   $data
171
     */
172
    protected function populateElasticsearchWithData($manager, array $data)
173
    {
174
        if (!empty($data)) {
175
            foreach ($data as $type => $documents) {
176
                foreach ($documents as $document) {
177
                    $manager->getConnection()->bulk('index', $type, $document);
178
                }
179
            }
180
            $manager->commit();
181
        }
182
    }
183
184
    /**
185
     * {@inheritdoc}
186
     */
187
    protected function tearDown()
188
    {
189
        parent::tearDown();
190
191
        foreach ($this->managers as $name => $manager) {
192
            try {
193
                $manager->getConnection()->dropIndex();
194
            } catch (\Exception $e) {
195
                // Do nothing.
196
            }
197
        }
198
    }
199
200
    /**
201
     * Returns service container.
202
     *
203
     * @param bool  $reinitialize  Force kernel reinitialization.
204
     * @param array $kernelOptions Options used passed to kernel if it needs to be initialized.
205
     *
206
     * @return ContainerInterface
207
     */
208
    protected function getContainer($reinitialize = false, $kernelOptions = [])
209
    {
210
        if (!$this->container || $reinitialize) {
211
            static::bootKernel($kernelOptions);
212
            $this->container = static::$kernel->getContainer();
213
        }
214
215
        return $this->container;
216
    }
217
218
    /**
219
     * Returns manager instance with injected connection if does not exist creates new one.
220
     *
221
     * @param string $name          Manager name.
222
     * @param bool   $createIndex   Create index or not.
223
     * @param array  $customMapping Custom index mapping config.
224
     *
225
     * @return Manager
226
     *
227
     * @throws \LogicException
228
     */
229
    protected function getManager($name = 'default', $createIndex = true, array $customMapping = [])
230
    {
231
        $serviceName = sprintf('es.manager.%s', $name);
232
233
        // Looks for cached manager.
234
        if (array_key_exists($name, $this->managers)) {
235
            $manager = $this->managers[$name];
236
        } elseif ($this->getContainer()->has($serviceName)) {
237
            /** @var Manager $manager */
238
            $manager = $this
239
                ->getContainer()
240
                ->get($serviceName);
241
            $this->managers[$name] = $manager;
242
        } else {
243
            throw new \LogicException(sprintf("Manager '%s' does not exist", $name));
244
        }
245
246
        $connection = $manager->getConnection();
247
248
        if ($connection instanceof Connection) {
249
            $this->ignoreVersions($connection);
250
        }
251
252
        // Updates settings.
253
        if (!empty($customMapping)) {
254
            $connection->updateSettings(['body' => ['mappings' => $customMapping]]);
255
        }
256
257
        // Drops and creates index.
258
        if ($createIndex) {
259
            $connection->dropAndCreateIndex();
260
        }
261
262
        // Populates elasticsearch index with data.
263
        $data = $this->getDataArray();
264
        if ($createIndex && isset($data[$name]) && !empty($data[$name])) {
265
            $this->populateElasticsearchWithData($manager, $data[$name]);
266
        }
267
268
        return $manager;
269
    }
270
}
271