Completed
Push — master ( 0136c1...94aca9 )
by Lukas Kahwe
03:29
created

AwsS3ResolverTest   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 420
Duplicated Lines 20 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 2
Bugs 1 Features 0
Metric Value
wmc 19
c 2
b 1
f 0
lcom 1
cbo 3
dl 84
loc 420
rs 10

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace Liip\ImagineBundle\Tests\Imagine\Cache\Resolver;
4
5
use Liip\ImagineBundle\Imagine\Cache\Resolver\AwsS3Resolver;
6
use Liip\ImagineBundle\Model\Binary;
7
use Liip\ImagineBundle\Tests\AbstractTest;
8
9
/**
10
 * @covers Liip\ImagineBundle\Imagine\Cache\Resolver\AwsS3Resolver
11
 */
12
class AwsS3ResolverTest extends AbstractTest
13
{
14
    public function testImplementsResolverInterface()
15
    {
16
        $rc = new \ReflectionClass('Liip\ImagineBundle\Imagine\Cache\Resolver\AwsS3Resolver');
17
18
        $this->assertTrue($rc->implementsInterface('Liip\ImagineBundle\Imagine\Cache\Resolver\ResolverInterface'));
19
    }
20
21
    public function testNoDoubleSlashesInObjectUrlOnResolve()
22
    {
23
        $s3 = $this->getS3ClientMock();
24
        $s3
25
            ->expects($this->once())
26
            ->method('getObjectUrl')
27
            ->with('images.example.com', 'thumb/some-folder/path.jpg')
28
        ;
29
30
        $resolver = new AwsS3Resolver($s3, 'images.example.com');
31
        $resolver->resolve('/some-folder/path.jpg', 'thumb');
32
    }
33
34
    public function testObjUrlOptionsPassedToS3ClintOnResolve()
35
    {
36
        $s3 = $this->getS3ClientMock();
37
        $s3
38
            ->expects($this->once())
39
            ->method('getObjectUrl')
40
            ->with('images.example.com', 'thumb/some-folder/path.jpg', 0, array('torrent' => true))
41
        ;
42
43
        $resolver = new AwsS3Resolver($s3, 'images.example.com');
44
        $resolver->setObjectUrlOption('torrent', true);
45
        $resolver->resolve('/some-folder/path.jpg', 'thumb');
46
    }
47
48
    public function testLogNotCreatedObjects()
49
    {
50
        $binary = new Binary('aContent', 'image/jpeg', 'jpeg');
51
52
        $s3 = $this->getS3ClientMock();
53
        $s3
54
            ->expects($this->once())
55
            ->method('putObject')
56
            ->will($this->throwException(new \Exception('Put object on amazon failed')))
57
        ;
58
59
        $logger = $this->getMock('Psr\Log\LoggerInterface');
60
        $logger
61
            ->expects($this->once())
62
            ->method('error')
63
        ;
64
65
        $resolver = new AwsS3Resolver($s3, 'images.example.com');
66
        $resolver->setLogger($logger);
67
68
        $this->setExpectedException(
69
            'Liip\ImagineBundle\Exception\Imagine\Cache\Resolver\NotStorableException',
70
            'The object could not be created on Amazon S3.'
71
        );
72
        $resolver->store($binary, 'foobar.jpg', 'thumb');
73
    }
74
75
    public function testCreateObjectOnAmazon()
76
    {
77
        $binary = new Binary('aContent', 'image/jpeg', 'jpeg');
78
79
        $s3 = $this->getS3ClientMock();
80
        $s3
81
            ->expects($this->once())
82
            ->method('putObject')
83
            ->will($this->returnValue($this->getS3ResponseMock()))
84
        ;
85
86
        $resolver = new AwsS3Resolver($s3, 'images.example.com');
87
88
        $this->assertNull($resolver->store($binary, 'thumb/foobar.jpg', 'thumb'));
89
    }
90
91
    public function testObjectOptionsPassedToS3ClintOnCreate()
92
    {
93
        $binary = new Binary('aContent', 'image/jpeg', 'jpeg');
94
95
        $s3 = $this->getS3ClientMock();
96
        $s3
97
            ->expects($this->once())
98
            ->method('putObject')
99
            ->with(array(
100
                'CacheControl' => 'max-age=86400',
101
                'ACL' => 'public-read',
102
                'Bucket' => 'images.example.com',
103
                'Key' => 'filter/images/foobar.jpg',
104
                'Body' => 'aContent',
105
                'ContentType' => 'image/jpeg',
106
            ))
107
        ;
108
109
        $resolver = new AwsS3Resolver($s3, 'images.example.com');
110
        $resolver->setPutOption('CacheControl', 'max-age=86400');
111
        $resolver->store($binary, 'images/foobar.jpg', 'filter');
112
    }
113
114
    public function testIsStoredChecksObjectExistence()
115
    {
116
        $s3 = $this->getS3ClientMock();
117
        $s3
118
            ->expects($this->once())
119
            ->method('doesObjectExist')
120
            ->will($this->returnValue(false))
121
        ;
122
123
        $resolver = new AwsS3Resolver($s3, 'images.example.com');
124
125
        $this->assertFalse($resolver->isStored('/some-folder/path.jpg', 'thumb'));
126
    }
127
128
    public function testReturnResolvedImageUrlOnResolve()
129
    {
130
        $s3 = $this->getS3ClientMock();
131
        $s3
132
            ->expects($this->once())
133
            ->method('getObjectUrl')
134
            ->with('images.example.com', 'thumb/some-folder/path.jpg', 0, array())
135
            ->will($this->returnValue('http://images.example.com/some-folder/path.jpg'))
136
        ;
137
138
        $resolver = new AwsS3Resolver($s3, 'images.example.com');
139
140
        $this->assertEquals(
141
            'http://images.example.com/some-folder/path.jpg',
142
            $resolver->resolve('/some-folder/path.jpg', 'thumb')
143
        );
144
    }
145
146
    public function testDoNothingIfFiltersAndPathsEmptyOnRemove()
147
    {
148
        $s3 = $this->getS3ClientMock();
149
        $s3
150
            ->expects($this->never())
151
            ->method('doesObjectExist')
152
        ;
153
        $s3
154
            ->expects($this->never())
155
            ->method('deleteObject')
156
        ;
157
        $s3
158
            ->expects($this->never())
159
            ->method('deleteMatchingObjects')
160
        ;
161
162
        $resolver = new AwsS3Resolver($s3, 'images.example.com');
163
164
        $resolver->remove(array(), array());
165
    }
166
167
    public function testRemoveCacheForPathAndFilterOnRemove()
168
    {
169
        $s3 = $this->getS3ClientMock();
170
        $s3
171
            ->expects($this->once())
172
            ->method('doesObjectExist')
173
            ->with('images.example.com', 'thumb/some-folder/path.jpg')
174
            ->will($this->returnValue(true))
175
        ;
176
        $s3
177
            ->expects($this->once())
178
            ->method('deleteObject')
179
            ->with(array(
180
                'Bucket' => 'images.example.com',
181
                'Key' => 'thumb/some-folder/path.jpg',
182
            ))
183
            ->will($this->returnValue($this->getS3ResponseMock(true)))
184
        ;
185
186
        $resolver = new AwsS3Resolver($s3, 'images.example.com');
187
188
        $resolver->remove(array('some-folder/path.jpg'), array('thumb'));
189
    }
190
191
    public function testRemoveCacheForSomePathsAndFilterOnRemove()
192
    {
193
        $s3 = $this->getS3ClientMock();
194
        $s3
195
            ->expects($this->at(0))
196
            ->method('doesObjectExist')
197
            ->with('images.example.com', 'thumb/pathOne.jpg')
198
            ->will($this->returnValue(true))
199
        ;
200
        $s3
201
            ->expects($this->at(1))
202
            ->method('deleteObject')
203
            ->with(array(
204
                'Bucket' => 'images.example.com',
205
                'Key' => 'thumb/pathOne.jpg',
206
            ))
207
            ->will($this->returnValue($this->getS3ResponseMock(true)))
208
        ;
209
        $s3
210
            ->expects($this->at(2))
211
            ->method('doesObjectExist')
212
            ->with('images.example.com', 'thumb/pathTwo.jpg')
213
            ->will($this->returnValue(true))
214
        ;
215
        $s3
216
            ->expects($this->at(3))
217
            ->method('deleteObject')
218
            ->with(array(
219
                'Bucket' => 'images.example.com',
220
                'Key' => 'thumb/pathTwo.jpg',
221
            ))
222
            ->will($this->returnValue($this->getS3ResponseMock(true)))
223
        ;
224
225
        $resolver = new AwsS3Resolver($s3, 'images.example.com');
226
227
        $resolver->remove(
228
            array('pathOne.jpg', 'pathTwo.jpg'),
229
            array('thumb')
230
        );
231
    }
232
233
    public function testRemoveCacheForSomePathsAndSomeFiltersOnRemove()
234
    {
235
        $s3 = $this->getS3ClientMock();
236
        $s3
237
            ->expects($this->at(0))
238
            ->method('doesObjectExist')
239
            ->with('images.example.com', 'filterOne/pathOne.jpg')
240
            ->will($this->returnValue(true))
241
        ;
242
        $s3
243
            ->expects($this->at(1))
244
            ->method('deleteObject')
245
            ->with(array(
246
                'Bucket' => 'images.example.com',
247
                'Key' => 'filterOne/pathOne.jpg',
248
            ))
249
            ->will($this->returnValue($this->getS3ResponseMock(true)))
250
        ;
251
        $s3
252
            ->expects($this->at(2))
253
            ->method('doesObjectExist')
254
            ->with('images.example.com', 'filterOne/pathTwo.jpg')
255
            ->will($this->returnValue(true))
256
        ;
257
        $s3
258
            ->expects($this->at(3))
259
            ->method('deleteObject')
260
            ->with(array(
261
                'Bucket' => 'images.example.com',
262
                'Key' => 'filterOne/pathTwo.jpg',
263
            ))
264
            ->will($this->returnValue($this->getS3ResponseMock(true)))
265
        ;
266
        $s3
267
            ->expects($this->at(4))
268
            ->method('doesObjectExist')
269
            ->with('images.example.com', 'filterTwo/pathOne.jpg')
270
            ->will($this->returnValue(true))
271
        ;
272
        $s3
273
            ->expects($this->at(5))
274
            ->method('deleteObject')
275
            ->with(array(
276
                'Bucket' => 'images.example.com',
277
                'Key' => 'filterTwo/pathOne.jpg',
278
            ))
279
            ->will($this->returnValue($this->getS3ResponseMock(true)))
280
        ;
281
        $s3
282
            ->expects($this->at(6))
283
            ->method('doesObjectExist')
284
            ->with('images.example.com', 'filterTwo/pathTwo.jpg')
285
            ->will($this->returnValue(true))
286
        ;
287
        $s3
288
            ->expects($this->at(7))
289
            ->method('deleteObject')
290
            ->with(array(
291
                'Bucket' => 'images.example.com',
292
                'Key' => 'filterTwo/pathTwo.jpg',
293
            ))
294
            ->will($this->returnValue($this->getS3ResponseMock(true)))
295
        ;
296
297
        $resolver = new AwsS3Resolver($s3, 'images.example.com');
298
299
        $resolver->remove(
300
            array('pathOne.jpg', 'pathTwo.jpg'),
301
            array('filterOne', 'filterTwo')
302
        );
303
    }
304
305
    public function testDoNothingWhenObjectNotExistForPathAndFilterOnRemove()
306
    {
307
        $s3 = $this->getS3ClientMock();
308
        $s3
309
            ->expects($this->once())
310
            ->method('doesObjectExist')
311
            ->with('images.example.com', 'thumb/some-folder/path.jpg')
312
            ->will($this->returnValue(false))
313
        ;
314
        $s3
315
            ->expects($this->never())
316
            ->method('deleteObject')
317
        ;
318
319
        $resolver = new AwsS3Resolver($s3, 'images.example.com');
320
        $resolver->remove(array('some-folder/path.jpg'), array('thumb'));
321
    }
322
323
    public function testCatchAndLogExceptionsForPathAndFilterOnRemove()
324
    {
325
        $s3 = $this->getS3ClientMock();
326
        $s3
327
            ->expects($this->once())
328
            ->method('doesObjectExist')
329
            ->with('images.example.com', 'thumb/some-folder/path.jpg')
330
            ->will($this->returnValue(true))
331
        ;
332
        $s3
333
            ->expects($this->once())
334
            ->method('deleteObject')
335
            ->will($this->throwException(new \Exception()))
336
        ;
337
338
        $logger = $this->getMock('Psr\Log\LoggerInterface');
339
        $logger
340
            ->expects($this->once())
341
            ->method('error')
342
        ;
343
344
        $resolver = new AwsS3Resolver($s3, 'images.example.com');
345
        $resolver->setLogger($logger);
346
        $resolver->remove(array('some-folder/path.jpg'), array('thumb'));
347
    }
348
349
    public function testRemoveCacheForFilterOnRemove()
350
    {
351
        $expectedBucket = 'images.example.com';
352
        $expectedFilter = 'theFilter';
353
354
        $s3 = $this->getS3ClientMock();
355
        $s3
356
            ->expects($this->once())
357
            ->method('deleteMatchingObjects')
358
            ->with($expectedBucket, null, "/$expectedFilter/i")
359
        ;
360
361
        $resolver = new AwsS3Resolver($s3, $expectedBucket);
362
363
        $resolver->remove(array(), array($expectedFilter));
364
    }
365
366
    public function testRemoveCacheForSomeFiltersOnRemove()
367
    {
368
        $expectedBucket = 'images.example.com';
369
        $expectedFilterOne = 'theFilterOne';
370
        $expectedFilterTwo = 'theFilterTwo';
371
372
        $s3 = $this->getS3ClientMock();
373
        $s3
374
            ->expects($this->once())
375
            ->method('deleteMatchingObjects')
376
            ->with($expectedBucket, null, "/{$expectedFilterOne}|{$expectedFilterTwo}/i")
377
        ;
378
379
        $resolver = new AwsS3Resolver($s3, $expectedBucket);
380
381
        $resolver->remove(array(), array($expectedFilterOne, $expectedFilterTwo));
382
    }
383
384
    public function testCatchAndLogExceptionForFilterOnRemove()
385
    {
386
        $expectedBucket = 'images.example.com';
387
        $expectedFilter = 'theFilter';
388
389
        $s3 = $this->getS3ClientMock();
390
        $s3
391
            ->expects($this->once())
392
            ->method('deleteMatchingObjects')
393
            ->will($this->throwException(new \Exception()))
394
        ;
395
396
        $logger = $this->getMock('Psr\Log\LoggerInterface');
397
        $logger
398
            ->expects($this->once())
399
            ->method('error')
400
        ;
401
402
        $resolver = new AwsS3Resolver($s3, $expectedBucket);
403
        $resolver->setLogger($logger);
404
405
        $resolver->remove(array(), array($expectedFilter));
406
    }
407
408
    protected function getS3ResponseMock($ok = true)
409
    {
410
        $s3Response = $this->getMock('Guzzle\Service\Resource\Model');
411
412
        return $s3Response;
413
    }
414
415
    /**
416
     * @return \PHPUnit_Framework_MockObject_MockObject|\Aws\S3\S3Client
417
     */
418
    protected function getS3ClientMock()
419
    {
420
        $mockedMethods = array(
421
            'deleteObject',
422
            'deleteMatchingObjects',
423
            'createObject',
424
            'putObject',
425
            'doesObjectExist',
426
            'getObjectUrl',
427
        );
428
429
        return $this->getMock('Aws\S3\S3Client', $mockedMethods, array(), '', false);
430
    }
431
}
432