1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the FOSElasticaBundle package. |
5
|
|
|
* |
6
|
|
|
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/> |
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 FOS\ElasticaBundle\Tests\Doctrine; |
13
|
|
|
|
14
|
|
|
use Elastica\Bulk\ResponseSet; |
15
|
|
|
use Elastica\Response; |
16
|
|
|
|
17
|
|
|
class AbstractProviderTest extends \PHPUnit_Framework_TestCase |
18
|
|
|
{ |
19
|
|
|
private $objectClass; |
20
|
|
|
private $objectManager; |
21
|
|
|
private $objectPersister; |
22
|
|
|
private $options; |
23
|
|
|
private $managerRegistry; |
24
|
|
|
private $indexable; |
25
|
|
|
private $sliceFetcher; |
26
|
|
|
|
27
|
|
|
public function setUp() |
28
|
|
|
{ |
29
|
|
|
$this->objectClass = 'objectClass'; |
30
|
|
|
$this->options = ['debug_logging' => true, 'indexName' => 'index', 'typeName' => 'type']; |
31
|
|
|
|
32
|
|
|
$this->objectPersister = $this->getMockObjectPersister(); |
33
|
|
|
$this->managerRegistry = $this->getMockManagerRegistry(); |
34
|
|
|
$this->objectManager = $this->getMockObjectManager(); |
35
|
|
|
$this->indexable = $this->getMockIndexable(); |
36
|
|
|
|
37
|
|
|
$this->managerRegistry->expects($this->any()) |
38
|
|
|
->method('getManagerForClass') |
39
|
|
|
->with($this->objectClass) |
40
|
|
|
->will($this->returnValue($this->objectManager)); |
41
|
|
|
|
42
|
|
|
$this->sliceFetcher = $this->getMockSliceFetcher(); |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* @dataProvider providePopulateIterations |
47
|
|
|
*/ |
48
|
|
|
public function testPopulateIterations($nbObjects, $objectsByIteration, $batchSize, $limit) |
49
|
|
|
{ |
50
|
|
|
$this->options['batch_size'] = $batchSize; |
51
|
|
|
$this->options['limit'] = $limit; |
52
|
|
|
|
53
|
|
|
$provider = $this->getMockAbstractProvider(); |
54
|
|
|
|
55
|
|
|
$queryBuilder = new \stdClass(); |
56
|
|
|
|
57
|
|
|
$provider->expects($this->once()) |
58
|
|
|
->method('createQueryBuilder') |
59
|
|
|
->will($this->returnValue($queryBuilder)); |
60
|
|
|
|
61
|
|
|
$provider->expects($this->once()) |
62
|
|
|
->method('countObjects') |
63
|
|
|
->with($queryBuilder) |
64
|
|
|
->will($this->returnValue($nbObjects)); |
65
|
|
|
|
66
|
|
|
$this->indexable->expects($this->any()) |
67
|
|
|
->method('isObjectIndexable') |
68
|
|
|
->with('index', 'type', $this->anything()) |
69
|
|
|
->will($this->returnValue(true)); |
70
|
|
|
|
71
|
|
|
$previousSlice = []; |
72
|
|
|
|
73
|
|
View Code Duplication |
foreach ($objectsByIteration as $i => $objects) { |
74
|
|
|
$offset = $objects[0] - 1; |
75
|
|
|
|
76
|
|
|
$this->sliceFetcher->expects($this->at($i)) |
77
|
|
|
->method('fetch') |
78
|
|
|
->with($queryBuilder, $batchSize, $offset, $previousSlice, ['id']) |
79
|
|
|
->will($this->returnValue($objects)); |
80
|
|
|
|
81
|
|
|
$this->objectManager->expects($this->at($i)) |
82
|
|
|
->method('clear'); |
83
|
|
|
|
84
|
|
|
$previousSlice = $objects; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
$this->objectPersister->expects($this->exactly(count($objectsByIteration))) |
88
|
|
|
->method('insertMany'); |
89
|
|
|
|
90
|
|
|
$provider->populate(); |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* @dataProvider providePopulateIterations |
95
|
|
|
*/ |
96
|
|
|
public function testPopulateIterationsWithoutSliceFetcher($nbObjects, $objectsByIteration, $batchSize, $limit) |
97
|
|
|
{ |
98
|
|
|
$this->options['batch_size'] = $batchSize; |
99
|
|
|
$this->options['limit'] = $limit; |
100
|
|
|
|
101
|
|
|
$provider = $this->getMockAbstractProvider(false); |
102
|
|
|
|
103
|
|
|
$queryBuilder = new \stdClass(); |
104
|
|
|
|
105
|
|
|
$provider->expects($this->once()) |
106
|
|
|
->method('createQueryBuilder') |
107
|
|
|
->will($this->returnValue($queryBuilder)); |
108
|
|
|
|
109
|
|
|
$provider->expects($this->once()) |
110
|
|
|
->method('countObjects') |
111
|
|
|
->with($queryBuilder) |
112
|
|
|
->will($this->returnValue($nbObjects)); |
113
|
|
|
|
114
|
|
|
$this->indexable->expects($this->any()) |
115
|
|
|
->method('isObjectIndexable') |
116
|
|
|
->with('index', 'type', $this->anything()) |
117
|
|
|
->will($this->returnValue(true)); |
118
|
|
|
|
119
|
|
|
$providerInvocationOffset = 2; |
120
|
|
|
|
121
|
|
View Code Duplication |
foreach ($objectsByIteration as $i => $objects) { |
122
|
|
|
$offset = $objects[0] - 1; |
123
|
|
|
|
124
|
|
|
$provider->expects($this->at($providerInvocationOffset + $i)) |
125
|
|
|
->method('fetchSlice') |
126
|
|
|
->with($queryBuilder, $batchSize, $offset) |
127
|
|
|
->will($this->returnValue($objects)); |
128
|
|
|
|
129
|
|
|
$this->objectManager->expects($this->at($i)) |
130
|
|
|
->method('clear'); |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
$this->objectPersister->expects($this->exactly(count($objectsByIteration))) |
134
|
|
|
->method('insertMany'); |
135
|
|
|
|
136
|
|
|
$provider->populate(); |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
public function providePopulateIterations() |
140
|
|
|
{ |
141
|
|
|
return [ |
142
|
|
|
[ |
143
|
|
|
100, |
144
|
|
|
[range(1, 100)], |
145
|
|
|
100, |
146
|
|
|
null |
147
|
|
|
], |
148
|
|
|
[ |
149
|
|
|
105, |
150
|
|
|
[range(1, 50), range(51, 100), range(101, 105)], |
151
|
|
|
50, |
152
|
|
|
null |
153
|
|
|
], |
154
|
|
|
[ |
155
|
|
|
105, |
156
|
|
|
[range(1, 50), range(51, 100)], |
157
|
|
|
50, |
158
|
|
|
100 |
159
|
|
|
], |
160
|
|
|
[ |
161
|
|
|
95, |
162
|
|
|
[range(1, 50), range(51, 95)], |
163
|
|
|
50, |
164
|
|
|
100 |
165
|
|
|
], |
166
|
|
|
]; |
167
|
|
|
} |
168
|
|
|
|
169
|
|
View Code Duplication |
public function testPopulateShouldNotClearObjectManager() |
170
|
|
|
{ |
171
|
|
|
$nbObjects = 1; |
172
|
|
|
$objects = [1]; |
173
|
|
|
$this->options['clear_object_manager'] = false; |
174
|
|
|
|
175
|
|
|
$provider = $this->getMockAbstractProvider(); |
176
|
|
|
|
177
|
|
|
$provider->expects($this->any()) |
178
|
|
|
->method('countObjects') |
179
|
|
|
->will($this->returnValue($nbObjects)); |
180
|
|
|
|
181
|
|
|
$this->sliceFetcher->expects($this->any()) |
182
|
|
|
->method('fetch') |
183
|
|
|
->will($this->returnValue($objects)); |
184
|
|
|
|
185
|
|
|
$this->indexable->expects($this->any()) |
186
|
|
|
->method('isObjectIndexable') |
187
|
|
|
->with('index', 'type', $this->anything()) |
188
|
|
|
->will($this->returnValue(true)); |
189
|
|
|
|
190
|
|
|
$this->objectManager->expects($this->never()) |
191
|
|
|
->method('clear'); |
192
|
|
|
|
193
|
|
|
$provider->populate(); |
194
|
|
|
} |
195
|
|
|
|
196
|
|
View Code Duplication |
public function testPopulateShouldClearObjectManagerForFilteredBatch() |
197
|
|
|
{ |
198
|
|
|
$nbObjects = 1; |
199
|
|
|
$objects = [1]; |
200
|
|
|
|
201
|
|
|
$provider = $this->getMockAbstractProvider(true); |
202
|
|
|
|
203
|
|
|
$provider->expects($this->any()) |
204
|
|
|
->method('countObjects') |
205
|
|
|
->will($this->returnValue($nbObjects)); |
206
|
|
|
|
207
|
|
|
$this->sliceFetcher->expects($this->any()) |
208
|
|
|
->method('fetch') |
209
|
|
|
->will($this->returnValue($objects)); |
210
|
|
|
|
211
|
|
|
$this->indexable->expects($this->any()) |
212
|
|
|
->method('isObjectIndexable') |
213
|
|
|
->with('index', 'type', $this->anything()) |
214
|
|
|
->will($this->returnValue(false)); |
215
|
|
|
|
216
|
|
|
$this->objectManager->expects($this->once()) |
217
|
|
|
->method('clear'); |
218
|
|
|
|
219
|
|
|
$provider->populate(); |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
public function testPopulateInvokesLoggerClosure() |
223
|
|
|
{ |
224
|
|
|
$nbObjects = 1; |
225
|
|
|
$objects = [1]; |
226
|
|
|
|
227
|
|
|
$provider = $this->getMockAbstractProvider(); |
228
|
|
|
|
229
|
|
|
$provider->expects($this->any()) |
230
|
|
|
->method('countObjects') |
231
|
|
|
->will($this->returnValue($nbObjects)); |
232
|
|
|
|
233
|
|
|
$this->sliceFetcher->expects($this->any()) |
234
|
|
|
->method('fetch') |
235
|
|
|
->will($this->returnValue($objects)); |
236
|
|
|
|
237
|
|
|
$this->indexable->expects($this->any()) |
238
|
|
|
->method('isObjectIndexable') |
239
|
|
|
->with('index', 'type', $this->anything()) |
240
|
|
|
->will($this->returnValue(true)); |
241
|
|
|
|
242
|
|
|
$loggerClosureInvoked = false; |
243
|
|
|
$loggerClosure = function () use (&$loggerClosureInvoked) { |
244
|
|
|
$loggerClosureInvoked = true; |
245
|
|
|
}; |
246
|
|
|
|
247
|
|
|
$provider->populate(); |
248
|
|
|
$this->assertFalse($loggerClosureInvoked); |
249
|
|
|
|
250
|
|
|
$provider->populate($loggerClosure); |
251
|
|
|
$this->assertTrue($loggerClosureInvoked); |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
public function testPopulateNotStopOnError() |
255
|
|
|
{ |
256
|
|
|
$nbObjects = 1; |
257
|
|
|
$objects = [1]; |
258
|
|
|
|
259
|
|
|
$provider = $this->getMockAbstractProvider(); |
260
|
|
|
|
261
|
|
|
$provider->expects($this->any()) |
262
|
|
|
->method('countObjects') |
263
|
|
|
->will($this->returnValue($nbObjects)); |
264
|
|
|
|
265
|
|
|
$this->sliceFetcher->expects($this->any()) |
266
|
|
|
->method('fetch') |
267
|
|
|
->will($this->returnValue($objects)); |
268
|
|
|
|
269
|
|
|
$this->indexable->expects($this->any()) |
270
|
|
|
->method('isObjectIndexable') |
271
|
|
|
->with('index', 'type', $this->anything()) |
272
|
|
|
->will($this->returnValue(true)); |
273
|
|
|
|
274
|
|
|
$this->objectPersister->expects($this->any()) |
275
|
|
|
->method('insertMany') |
276
|
|
|
->will($this->throwException($this->getMockBulkResponseException())); |
277
|
|
|
|
278
|
|
|
$this->setExpectedException('Elastica\Exception\Bulk\ResponseException'); |
|
|
|
|
279
|
|
|
|
280
|
|
|
$provider->populate(null, ['ignore_errors' => false]); |
281
|
|
|
} |
282
|
|
|
|
283
|
|
|
public function testPopulateRunsIndexCallable() |
284
|
|
|
{ |
285
|
|
|
$nbObjects = 2; |
286
|
|
|
$objects = [1, 2]; |
287
|
|
|
|
288
|
|
|
$provider = $this->getMockAbstractProvider(); |
289
|
|
|
$provider->expects($this->any()) |
290
|
|
|
->method('countObjects') |
291
|
|
|
->will($this->returnValue($nbObjects)); |
292
|
|
|
|
293
|
|
|
$this->sliceFetcher->expects($this->any()) |
294
|
|
|
->method('fetch') |
295
|
|
|
->will($this->returnValue($objects)); |
296
|
|
|
|
297
|
|
|
$this->indexable->expects($this->at(0)) |
298
|
|
|
->method('isObjectIndexable') |
299
|
|
|
->with('index', 'type', 1) |
300
|
|
|
->will($this->returnValue(false)); |
301
|
|
|
$this->indexable->expects($this->at(1)) |
302
|
|
|
->method('isObjectIndexable') |
303
|
|
|
->with('index', 'type', 2) |
304
|
|
|
->will($this->returnValue(true)); |
305
|
|
|
|
306
|
|
|
$this->objectPersister->expects($this->once()) |
307
|
|
|
->method('insertMany') |
308
|
|
|
->with([2]); |
309
|
|
|
|
310
|
|
|
$provider->populate(); |
311
|
|
|
} |
312
|
|
|
|
313
|
|
|
/** |
314
|
|
|
* @param bool $setSliceFetcher Whether or not to set the slice fetcher |
315
|
|
|
* |
316
|
|
|
* @return \FOS\ElasticaBundle\Doctrine\AbstractProvider|\PHPUnit_Framework_MockObject_MockObject |
317
|
|
|
*/ |
318
|
|
|
private function getMockAbstractProvider($setSliceFetcher = true) |
319
|
|
|
{ |
320
|
|
|
return $this->getMockForAbstractClass('FOS\ElasticaBundle\Doctrine\AbstractProvider', [ |
321
|
|
|
$this->objectPersister, |
322
|
|
|
$this->indexable, |
323
|
|
|
$this->objectClass, |
324
|
|
|
$this->options, |
325
|
|
|
$this->managerRegistry, |
326
|
|
|
$setSliceFetcher ? $this->sliceFetcher : null, |
327
|
|
|
]); |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
/** |
331
|
|
|
* @return \Elastica\Exception\Bulk\ResponseException |
332
|
|
|
*/ |
333
|
|
|
private function getMockBulkResponseException() |
334
|
|
|
{ |
335
|
|
|
return $this->getMockBuilder('Elastica\Exception\Bulk\ResponseException') |
336
|
|
|
->setConstructorArgs([ |
337
|
|
|
new ResponseSet(new Response([]), []), ] |
338
|
|
|
) |
339
|
|
|
->getMock(); |
340
|
|
|
} |
341
|
|
|
|
342
|
|
|
/** |
343
|
|
|
* @return \Doctrine\Common\Persistence\ManagerRegistry|\PHPUnit_Framework_MockObject_MockObject |
344
|
|
|
*/ |
345
|
|
|
private function getMockManagerRegistry() |
346
|
|
|
{ |
347
|
|
|
return $this->getMockBuilder('Doctrine\Common\Persistence\ManagerRegistry')->getMock(); |
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
/** |
351
|
|
|
* @return ObjectManager|\PHPUnit_Framework_MockObject_MockObject |
352
|
|
|
*/ |
353
|
|
|
private function getMockObjectManager() |
354
|
|
|
{ |
355
|
|
|
$mock = $this->getMockBuilder(__NAMESPACE__.'\ObjectManager')->getMock(); |
356
|
|
|
|
357
|
|
|
$mock->expects($this->any()) |
358
|
|
|
->method('getClassMetadata') |
359
|
|
|
->will($this->returnSelf()); |
360
|
|
|
|
361
|
|
|
$mock->expects($this->any()) |
362
|
|
|
->method('getIdentifierFieldNames') |
363
|
|
|
->will($this->returnValue(['id'])); |
364
|
|
|
|
365
|
|
|
return $mock; |
366
|
|
|
} |
367
|
|
|
|
368
|
|
|
/** |
369
|
|
|
* @return \FOS\ElasticaBundle\Persister\ObjectPersisterInterface|\PHPUnit_Framework_MockObject_MockObject |
370
|
|
|
*/ |
371
|
|
|
private function getMockObjectPersister() |
372
|
|
|
{ |
373
|
|
|
return $this->getMockBuilder('FOS\ElasticaBundle\Persister\ObjectPersisterInterface')->getMock(); |
374
|
|
|
} |
375
|
|
|
|
376
|
|
|
/** |
377
|
|
|
* @return \FOS\ElasticaBundle\Provider\IndexableInterface|\PHPUnit_Framework_MockObject_MockObject |
378
|
|
|
*/ |
379
|
|
|
private function getMockIndexable() |
380
|
|
|
{ |
381
|
|
|
return $this->getMockBuilder('FOS\ElasticaBundle\Provider\IndexableInterface')->getMock(); |
382
|
|
|
} |
383
|
|
|
|
384
|
|
|
/** |
385
|
|
|
* @return \FOS\ElasticaBundle\Doctrine\SliceFetcherInterface|\PHPUnit_Framework_MockObject_MockObject |
386
|
|
|
*/ |
387
|
|
|
private function getMockSliceFetcher() |
388
|
|
|
{ |
389
|
|
|
return $this->getMockBuilder('FOS\ElasticaBundle\Doctrine\SliceFetcherInterface')->getMock(); |
390
|
|
|
} |
391
|
|
|
} |
392
|
|
|
|
393
|
|
|
/** |
394
|
|
|
* Doctrine\Common\Persistence\ObjectManager does not include a clear() method |
395
|
|
|
* in its interface, so create a new interface for mocking. |
396
|
|
|
*/ |
397
|
|
|
interface ObjectManager |
398
|
|
|
{ |
399
|
|
|
public function clear(); |
400
|
|
|
public function getClassMetadata(); |
401
|
|
|
public function getIdentifierFieldNames(); |
402
|
|
|
} |
403
|
|
|
|
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.