Completed
Push — master ( 25953d...e2e6d9 )
by Joschi
02:32
created

RepositoryTest   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 374
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 5
Bugs 1 Features 0
Metric Value
wmc 27
c 5
b 1
f 0
lcom 1
cbo 8
dl 0
loc 374
rs 10

20 Methods

Rating   Name   Duplication   Size   Complexity  
B setUpBeforeClass() 0 57 6
A tearDownAfterClass() 0 12 3
A testInvalidSchemaBareUrl() 0 4 1
A testInvalidQueryBareUrl() 0 4 1
A testInvalidFragmentBareUrl() 0 4 1
A testUseAutoconnect() 0 4 1
A testRegisterInvalidQueryRepositoryUrl() 0 4 1
A testInstantiateInvalidQueryRepositoryUrl() 0 11 1
A testInstantiateUnknownRepositoryUrl() 0 4 1
A testEmptyRepositoryConfig() 0 4 1
A testEmptyAdapterStrategyConfig() 0 4 1
A testInvalidAdapterStrategyType() 0 8 1
A testFileAdapterStrategy() 0 11 1
A testMissingFileStrategyRoot() 0 10 1
A testEmptyFileStrategyRoot() 0 11 1
A testInvalidFileStrategyRoot() 0 11 1
A testUnknownRepositoryUrlInstance() 0 11 1
A testFileRepository() 0 18 1
A testFileRepositoryRevisions() 0 16 1
A testRepositoryPath() 0 14 1
1
<?php
2
3
/**
4
 * apparat-object
5
 *
6
 * @category    Apparat
7
 * @package     Apparat\Object
8
 * @subpackage  Apparat\Object\Infrastructure
9
 * @author      Joschi Kuphal <[email protected]> / @jkphl
10
 * @copyright   Copyright © 2016 Joschi Kuphal <[email protected]> / @jkphl
11
 * @license     http://opensource.org/licenses/MIT	The MIT License (MIT)
0 ignored issues
show
Coding Style introduced by
Spaces must be used for alignment; tabs are not allowed
Loading history...
12
 */
13
14
/***********************************************************************************
15
 *  The MIT License (MIT)
16
 *
17
 *  Copyright © 2016 Joschi Kuphal <[email protected]> / @jkphl
18
 *
19
 *  Permission is hereby granted, free of charge, to any person obtaining a copy of
20
 *  this software and associated documentation files (the "Software"), to deal in
21
 *  the Software without restriction, including without limitation the rights to
22
 *  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
23
 *  the Software, and to permit persons to whom the Software is furnished to do so,
24
 *  subject to the following conditions:
25
 *
26
 *  The above copyright notice and this permission notice shall be included in all
27
 *  copies or substantial portions of the Software.
28
 *
29
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
31
 *  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
32
 *  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
33
 *  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34
 *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35
 ***********************************************************************************/
36
37
namespace Apparat\Object\Tests;
38
39
use Apparat\Kernel\Ports\Kernel;
40
use Apparat\Kernel\Tests\AbstractTest;
41
use Apparat\Object\Domain\Factory\SelectorFactory;
42
use Apparat\Object\Domain\Model\Object\Collection;
43
use Apparat\Object\Domain\Model\Path\RepositoryPath;
44
use Apparat\Object\Domain\Repository\Repository;
45
use Apparat\Object\Domain\Repository\SelectorInterface;
46
use Apparat\Object\Domain\Repository\Service;
47
use Apparat\Object\Infrastructure\Factory\AdapterStrategyFactory;
48
use Apparat\Object\Infrastructure\Repository\FileAdapterStrategy;
49
use Apparat\Object\Module;
50
use Apparat\Object\Ports\Repository as RepositoryFactory;
51
52
/**
53
 * Repository test
54
 *
55
 * @package Apparat\Object
56
 * @subpackage ApparatTest
57
 */
58
class RepositoryTest extends AbstractTest
59
{
60
    /**
61
     * Temporary glob directory
62
     *
63
     * @var string
64
     */
65
    protected static $_globBase = null;
66
    /**
67
     * Created temporary files
68
     *
69
     * @var array
70
     */
71
    protected static $_globFiles = [];
72
    /**
73
     * Created temporary directories
74
     *
75
     * @var array
76
     */
77
    protected static $_globDirs = [];
78
    /**
79
     * Type counter
80
     *
81
     * @var array
82
     */
83
    protected static $_globTypes = ['event' => 0, 'article' => 0, 'note' => 0];
84
    /**
85
     * Revision counter
86
     *
87
     * @var array
88
     */
89
    protected static $_globRevisions = ['' => 0, '-0' => 0, '-1' => 0];
90
91
    /**
92
     * Setup
93
     */
94
    public static function setUpBeforeClass()
95
    {
96
        parent::setUpBeforeClass();
97
        self::$_globDirs[] =
98
        self::$_globBase = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'glob';
99
100
        $types = array_keys(self::$_globTypes);
101
        $revisions = array_keys(self::$_globRevisions);
102
        $index = 0;
103
104
        // Setup test directories & files
105
        for ($currentYear = intval(date('Y')), $year = $currentYear; $year < $currentYear + 3; ++$year) {
106
            self::$_globDirs[] =
107
            $yearDir = self::$_globBase . DIRECTORY_SEPARATOR . $year;
108
            for ($month = 1; $month < 13; ++$month) {
109
                self::$_globDirs[] =
110
                $monthDir = $yearDir . DIRECTORY_SEPARATOR . str_pad($month, 2, '0', STR_PAD_LEFT);
111
                $days = [];
112
                while (count($days) < 3) {
113
                    $day = rand(1, date('t', mktime(0, 0, 0, $month, 1, $year)));
114
                    $days[$day] = $day;
115
                }
116
                foreach ($days as $day) {
117
                    self::$_globDirs[] =
118
                    $dayDir = $monthDir . DIRECTORY_SEPARATOR . str_pad($day, 2, '0', STR_PAD_LEFT);
119
                    mkdir($dayDir, 0777, true);
120
                    self::$_globDirs[] =
121
                    $hourDir = $dayDir . DIRECTORY_SEPARATOR . '00';
122
                    mkdir($hourDir, 0777, true);
123
                    self::$_globDirs[] =
124
                    $minuteDir = $hourDir . DIRECTORY_SEPARATOR . '00';
125
                    mkdir($minuteDir, 0777, true);
126
                    self::$_globDirs[] =
127
                    $secondDir = $minuteDir . DIRECTORY_SEPARATOR . '00';
128
                    mkdir($secondDir, 0777, true);
129
130
131
                    // Create random subfolders and object files
132
                    for ($object = 1; $object < 3; ++$object) {
133
                        ++$index;
134
                        $type = $types[rand(0, 2)];
135
                        $revision = $revisions[rand(0, 2)];
136
                        ++self::$_globTypes[$type];
137
                        ++self::$_globRevisions[$revision];
138
                        self::$_globDirs[] =
139
                        $objectDir = $secondDir . DIRECTORY_SEPARATOR . $index . '.' . $type;
140
                        mkdir($objectDir);
141
                        self::$_globFiles[] =
142
                        $objectFile = $objectDir . DIRECTORY_SEPARATOR . $index . $revision;
143
                        touch($objectFile);
144
                    }
145
                }
146
            }
147
        }
148
149
        putenv('OBJECT_DATE_PRECISION=6');
150
    }
151
152
    /**
153
     * Teardown
154
     */
155
    public static function tearDownAfterClass()
156
    {
157
        parent::tearDownAfterClass();
158
        foreach (self::$_globFiles as $globFile) {
159
            @unlink($globFile);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
160
        }
161
        foreach (array_reverse(self::$_globDirs) as $globDir) {
162
            @rmdir($globDir);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
163
        }
164
165
        putenv('OBJECT_DATE_PRECISION=3');
166
    }
167
168
    /**
169
     * Test a bare URL with invalid schema
170
     *
171
     * @expectedException \RuntimeException
172
     * @expectedExceptionCode 1451776352
173
     */
174
    public static function testInvalidSchemaBareUrl()
175
    {
176
        Module::isAbsoluteBareUrl('ftp://example.com');
177
    }
178
179
    /**
180
     * Test a bare URL with query
181
     *
182
     * @expectedException \RuntimeException
183
     * @expectedExceptionCode 1451776509
184
     */
185
    public static function testInvalidQueryBareUrl()
186
    {
187
        Module::isAbsoluteBareUrl('http://example.com/?a=1');
188
    }
189
190
    /**
191
     * Test a bare URL with fragment
192
     *
193
     * @expectedException \RuntimeException
194
     * @expectedExceptionCode 1451776570
195
     */
196
    public static function testInvalidFragmentBareUrl()
197
    {
198
        Module::isAbsoluteBareUrl('http://example.com/#1');
199
    }
200
201
    /**
202
     * Test disabling of repository auto-connection
203
     */
204
    public function testUseAutoconnect()
205
    {
206
        $this->assertFalse(Kernel::create(Service::class)->useAutoConnect(false));
207
    }
208
209
    /**
210
     * Test invalid query repository URL registration
211
     *
212
     * @expectedException \Apparat\Object\Infrastructure\Repository\InvalidArgumentException
213
     * @expectedExceptionCode 1451776509
214
     */
215
    public function testRegisterInvalidQueryRepositoryUrl()
216
    {
217
        RepositoryFactory::register(getenv('REPOSITORY_URL') . '?a=1', []);
218
    }
219
220
    /**
221
     * Test invalid query repository URL registration
222
     *
223
     * @expectedException \Apparat\Object\Infrastructure\Repository\InvalidArgumentException
224
     * @expectedExceptionCode 1451776509
225
     */
226
    public function testInstantiateInvalidQueryRepositoryUrl()
227
    {
228
        RepositoryFactory::register(
229
            getenv('REPOSITORY_URL'),
230
            [
231
                'type' => FileAdapterStrategy::TYPE,
232
                'root' => __DIR__,
233
            ]
234
        );
235
        RepositoryFactory::instance(getenv('REPOSITORY_URL') . '?a=1');
236
    }
237
238
    /**
239
     * Test unknown public repository URL instantiation
240
     *
241
     * @expectedException \Apparat\Object\Infrastructure\Repository\InvalidArgumentException
242
     * @expectedExceptionCode 1451771889
243
     */
244
    public function testInstantiateUnknownRepositoryUrl()
245
    {
246
        RepositoryFactory::instance('unknown');
247
    }
248
249
    /**
250
     * Test empty repository config
251
     *
252
     * @expectedException \Apparat\Object\Infrastructure\Factory\InvalidArgumentException
253
     * @expectedExceptionCode 1449956347
254
     */
255
    public function testEmptyRepositoryConfig()
256
    {
257
        RepositoryFactory::register(getenv('REPOSITORY_URL'), []);
258
    }
259
260
    /**
261
     * Test empty adapter strategy configuration
262
     *
263
     * @expectedException \Apparat\Object\Infrastructure\Factory\InvalidArgumentException
264
     * @expectedExceptionCode 1449956347
265
     */
266
    public function testEmptyAdapterStrategyConfig()
267
    {
268
        (new AdapterStrategyFactory)->createFromConfig([]);
269
    }
270
271
    /**
272
     * Test invalid adapter strategy type
273
     *
274
     * @expectedException \Apparat\Object\Infrastructure\Factory\InvalidArgumentException
275
     * @expectedExceptionCode 1449956471
276
     */
277
    public function testInvalidAdapterStrategyType()
278
    {
279
        (new AdapterStrategyFactory)->createFromConfig(
280
            [
281
                'type' => 'invalid',
282
            ]
283
        );
284
    }
285
286
    /**
287
     * Test file adapter strategy type
288
     */
289
    public function testFileAdapterStrategy()
290
    {
291
        $fileAdapterStrategy = (new AdapterStrategyFactory)->createFromConfig(
292
            [
293
                'type' => FileAdapterStrategy::TYPE,
294
                'root' => __DIR__,
295
            ]
296
        );
297
        $this->assertInstanceOf(FileAdapterStrategy::class, $fileAdapterStrategy);
298
        $this->assertEquals(FileAdapterStrategy::TYPE, $fileAdapterStrategy->getType());
299
    }
300
301
    /**
302
     * Test invalid file adapter strategy root
303
     *
304
     * @expectedException \Apparat\Object\Domain\Repository\InvalidArgumentException
305
     * @expectedExceptionCode 1450136346
306
     */
307
    public function testMissingFileStrategyRoot()
308
    {
309
        RepositoryFactory::register(
310
            getenv('REPOSITORY_URL'),
311
            [
312
                'type' => FileAdapterStrategy::TYPE,
313
            ]
314
        );
315
        RepositoryFactory::instance(getenv('REPOSITORY_URL'));
316
    }
317
318
    /**
319
     * Test empty file adapter strategy root
320
     *
321
     * @expectedException \Apparat\Object\Infrastructure\Repository\InvalidArgumentException
322
     * @expectedExceptionCode 1449956977
323
     */
324
    public function testEmptyFileStrategyRoot()
325
    {
326
        RepositoryFactory::register(
327
            getenv('REPOSITORY_URL'),
328
            [
329
                'type' => FileAdapterStrategy::TYPE,
330
                'root' => '',
331
            ]
332
        );
333
        RepositoryFactory::instance(getenv('REPOSITORY_URL'));
334
    }
335
336
    /**
337
     * Test invalid file adapter strategy root
338
     *
339
     * @expectedException \Apparat\Object\Infrastructure\Repository\InvalidArgumentException
340
     * @expectedExceptionCode 1449957017
341
     */
342
    public function testInvalidFileStrategyRoot()
343
    {
344
        RepositoryFactory::register(
345
            getenv('REPOSITORY_URL'),
346
            [
347
                'type' => FileAdapterStrategy::TYPE,
348
                'root' => '__FILE__',
349
            ]
350
        );
351
        RepositoryFactory::instance(getenv('REPOSITORY_URL'));
352
    }
353
354
    /**
355
     * Test invalid repository URL during instantiation
356
     *
357
     * @expectedException \Apparat\Object\Domain\Repository\InvalidArgumentException
358
     * @expectedExceptionCode 1451771889
359
     */
360
    public function testUnknownRepositoryUrlInstance()
361
    {
362
        RepositoryFactory::register(
363
            getenv('REPOSITORY_URL'),
364
            [
365
                'type' => FileAdapterStrategy::TYPE,
366
                'root' => self::$_globBase,
367
            ]
368
        );
369
        RepositoryFactory::instance('http://example.com');
370
    }
371
372
    /**
373
     * Test file repository
374
     */
375
    public function testFileRepository()
376
    {
377
        RepositoryFactory::register(
378
            getenv('REPOSITORY_URL'),
379
            [
380
                'type' => FileAdapterStrategy::TYPE,
381
                'root' => self::$_globBase,
382
            ]
383
        );
384
        $fileRepository = RepositoryFactory::instance(getenv('REPOSITORY_URL'));
385
        $this->assertInstanceOf(Repository::class, $fileRepository);
386
387
        $selector = SelectorFactory::createFromString('/*');
388
        $this->assertInstanceOf(SelectorInterface::class, $selector);
389
        $collection = $fileRepository->findObjects($selector);
390
        $this->assertInstanceOf(Collection::class, $collection);
391
        $this->assertEquals(array_sum(self::$_globTypes), count($collection));
392
    }
393
394
    /**
395
     * Test file repository with revisions
396
     */
397
    public function testFileRepositoryRevisions()
398
    {
399
        RepositoryFactory::register(
400
            getenv('REPOSITORY_URL'),
401
            [
402
                'type' => FileAdapterStrategy::TYPE,
403
                'root' => self::$_globBase,
404
            ]
405
        );
406
        $fileRepository = RepositoryFactory::instance(getenv('REPOSITORY_URL'));
407
408
        $selector = SelectorFactory::createFromString('/*/*/*/*/*/*/*.*/*-1');
409
        $collection = $fileRepository->findObjects($selector);
410
        $this->assertInstanceOf(Collection::class, $collection);
411
        $this->assertEquals(self::$_globRevisions['-1'], count($collection));
412
    }
413
414
    /**
415
     * Test a repository path
416
     */
417
    public function testRepositoryPath()
418
    {
419
        RepositoryFactory::register(
420
            getenv('REPOSITORY_URL'),
421
            [
422
                'type' => FileAdapterStrategy::TYPE,
423
                'root' => self::$_globBase,
424
            ]
425
        );
426
        $fileRepository = RepositoryFactory::instance(getenv('REPOSITORY_URL'));
427
        $repositoryPath = new RepositoryPath($fileRepository, '/2015/10/01/00/00/00/36704.event/36704-1');
428
        $this->assertInstanceOf(RepositoryPath::class, $repositoryPath);
429
        $this->assertEquals($fileRepository, $repositoryPath->getRepository());
430
    }
431
}
432