RepositoryTest::testInvalidSchemaBareUrl()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 4
rs 10
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)
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\Object\Domain\Model\Object\Collection;
40
use Apparat\Object\Domain\Model\Uri\RepositoryLocator;
41
use Apparat\Object\Domain\Repository\Repository;
42
use Apparat\Object\Domain\Repository\SelectorInterface;
43
use Apparat\Object\Infrastructure\Factory\AdapterStrategyFactory;
44
use Apparat\Object\Infrastructure\Repository\FileAdapterStrategy;
45
use Apparat\Object\Infrastructure\Repository\Repository as InfrastructureRepository;
46
use Apparat\Object\Module;
47
use Apparat\Object\Ports\Facades\RepositoryFacade;
48
use Apparat\Object\Ports\Factory\SelectorFactory;
49
50
/**
51
 * Repository test
52
 *
53
 * @package Apparat\Object
54
 * @subpackage Apparat\Object\Test
55
 */
56
class RepositoryTest extends AbstractDisabledAutoconnectorTest
57
{
58
    /**
59
     * Temporary glob directory
60
     *
61
     * @var string
62
     */
63
    protected static $globBase = null;
64
    /**
65
     * Created temporary files
66
     *
67
     * @var array
68
     */
69
    protected static $globFiles = [];
70
    /**
71
     * Created temporary directories
72
     *
73
     * @var array
74
     */
75
    protected static $globDirs = [];
76
    /**
77
     * Type counter
78
     *
79
     * @var array
80
     */
81
    protected static $globTypes = ['event' => 0, 'article' => 0, 'note' => 0];
82
    /**
83
     * Revision counter
84
     *
85
     * @var array
86
     */
87
    protected static $globRevisions = ['' => 0, '-1' => 0, '-2' => 0];
88
89
    /**
90
     * Setup
91
     */
92
    public static function setUpBeforeClass()
93
    {
94
        parent::setUpBeforeClass();
95
        self::$globDirs[] =
96
        self::$globBase = sys_get_temp_dir().DIRECTORY_SEPARATOR.'glob';
97
98
        $types = array_keys(self::$globTypes);
99
        $revisions = array_keys(self::$globRevisions);
100
        $index = 0;
101
102
        // Setup test directories & files
103
        for ($currentYear = intval(date('Y')), $year = $currentYear; $year < $currentYear + 3; ++$year) {
104
            self::$globDirs[] =
105
            $yearDir = self::$globBase.DIRECTORY_SEPARATOR.$year;
106
            for ($month = 1; $month < 13; ++$month) {
107
                self::$globDirs[] =
108
                $monthDir = $yearDir.DIRECTORY_SEPARATOR.str_pad($month, 2, '0', STR_PAD_LEFT);
109
                $days = [];
110
                while (count($days) < 3) {
111
                    $day = rand(1, date('t', mktime(0, 0, 0, $month, 1, $year)));
112
                    $days[$day] = $day;
113
                }
114
                foreach ($days as $day) {
115
                    self::$globDirs[] =
116
                    $dayDir = $monthDir.DIRECTORY_SEPARATOR.str_pad($day, 2, '0', STR_PAD_LEFT);
117
                    mkdir($dayDir, 0777, true);
118
                    self::$globDirs[] =
119
                    $hourDir = $dayDir.DIRECTORY_SEPARATOR.'00';
120
                    mkdir($hourDir, 0777, true);
121
                    self::$globDirs[] =
122
                    $minuteDir = $hourDir.DIRECTORY_SEPARATOR.'00';
123
                    mkdir($minuteDir, 0777, true);
124
                    self::$globDirs[] =
125
                    $secondDir = $minuteDir.DIRECTORY_SEPARATOR.'00';
126
                    mkdir($secondDir, 0777, true);
127
128
129
                    // Create random sub-folders and object files
130
                    for ($object = 1; $object < 3; ++$object) {
131
                        ++$index;
132
                        $type = $types[rand(0, 2)];
133
                        $revision = $revisions[rand(0, 2)];
134
                        ++self::$globTypes[$type];
135
                        ++self::$globRevisions[$revision];
136
                        self::$globDirs[] =
137
                        $objectDir = $secondDir.DIRECTORY_SEPARATOR.$index.'-'.$type;
138
                        mkdir($objectDir);
139
                        self::$globFiles[] =
140
                        $objectFile =
141
                            $objectDir.DIRECTORY_SEPARATOR.$index.$revision.'.'.getenv('OBJECT_RESOURCE_EXTENSION');
142
                        touch($objectFile);
143
                    }
144
                }
145
            }
146
        }
147
148
        putenv('OBJECT_DATE_PRECISION=6');
149
    }
150
151
    /**
152
     * Teardown
153
     */
154
    public static function tearDownAfterClass()
155
    {
156
        parent::tearDownAfterClass();
157
        foreach (self::$globFiles as $globFile) {
158
            unlink($globFile);
159
        }
160
        foreach (array_reverse(self::$globDirs) as $globDir) {
161
            rmdir($globDir);
162
        }
163
164
        putenv('OBJECT_DATE_PRECISION=3');
165
    }
166
167
    /**
168
     * Test a bare URL with invalid schema
169
     *
170
     * @expectedException \RuntimeException
171
     * @expectedExceptionCode 1451776352
172
     */
173
    public static function testInvalidSchemaBareUrl()
174
    {
175
        Module::isAbsoluteBareUrl('ftp://example.com');
176
    }
177
178
    /**
179
     * Test a bare URL with query
180
     *
181
     * @expectedException \RuntimeException
182
     * @expectedExceptionCode 1451776509
183
     */
184
    public static function testInvalidQueryBareUrl()
185
    {
186
        Module::isAbsoluteBareUrl('http://example.com/?a=1');
187
    }
188
189
    /**
190
     * Test a bare URL with fragment
191
     *
192
     * @expectedException \RuntimeException
193
     * @expectedExceptionCode 1451776570
194
     */
195
    public static function testInvalidFragmentBareUrl()
196
    {
197
        Module::isAbsoluteBareUrl('http://example.com/#1');
198
    }
199
200
    /**
201
     * Test invalid query repository URL registration
202
     *
203
     * @expectedException \Apparat\Object\Infrastructure\Repository\InvalidArgumentException
204
     * @expectedExceptionCode 1451776509
205
     */
206
    public function testRegisterInvalidQueryRepositoryUrl()
207
    {
208
        InfrastructureRepository::register(getenv('REPOSITORY_URL').'?a=1', []);
209
    }
210
211
    /**
212
     * Test invalid query repository URL registration
213
     *
214
     * @expectedException \Apparat\Object\Infrastructure\Repository\InvalidArgumentException
215
     * @expectedExceptionCode 1451776509
216
     */
217
    public function testInstantiateInvalidQueryRepositoryUrl()
218
    {
219
        InfrastructureRepository::register(
220
            getenv('REPOSITORY_URL'),
221
            [
222
                'type' => FileAdapterStrategy::TYPE,
223
                'root' => __DIR__,
224
            ]
225
        );
226
        InfrastructureRepository::instance(getenv('REPOSITORY_URL').'?a=1');
227
    }
228
229
    /**
230
     * Test unknown public repository URL instantiation
231
     *
232
     * @expectedException \Apparat\Object\Infrastructure\Repository\InvalidArgumentException
233
     * @expectedExceptionCode 1451771889
234
     */
235
    public function testInstantiateUnknownRepositoryUrl()
236
    {
237
        InfrastructureRepository::instance('unknown');
238
    }
239
240
    /**
241
     * Test empty repository config
242
     *
243
     * @expectedException \Apparat\Object\Infrastructure\Factory\InvalidArgumentException
244
     * @expectedExceptionCode 1449956347
245
     */
246
    public function testEmptyRepositoryConfig()
247
    {
248
        InfrastructureRepository::register(getenv('REPOSITORY_URL'), []);
249
    }
250
251
    /**
252
     * Test empty adapter strategy configuration
253
     *
254
     * @expectedException \Apparat\Object\Infrastructure\Factory\InvalidArgumentException
255
     * @expectedExceptionCode 1449956347
256
     */
257
    public function testEmptyAdapterStrategyConfig()
258
    {
259
        (new AdapterStrategyFactory)->createFromConfig([]);
260
    }
261
262
    /**
263
     * Test invalid adapter strategy type
264
     *
265
     * @expectedException \Apparat\Object\Infrastructure\Factory\InvalidArgumentException
266
     * @expectedExceptionCode 1449956471
267
     */
268
    public function testInvalidAdapterStrategyType()
269
    {
270
        (new AdapterStrategyFactory)->createFromConfig(
271
            [
272
                'type' => 'invalid',
273
            ]
274
        );
275
    }
276
277
    /**
278
     * Test file adapter strategy type
279
     */
280
    public function testFileAdapterStrategy()
281
    {
282
        $fileAdapterStrategy = (new AdapterStrategyFactory)->createFromConfig(
283
            [
284
                'type' => FileAdapterStrategy::TYPE,
285
                'root' => __DIR__,
286
            ]
287
        );
288
        $this->assertInstanceOf(FileAdapterStrategy::class, $fileAdapterStrategy);
289
        $this->assertEquals(FileAdapterStrategy::TYPE, $fileAdapterStrategy->getAdapterType());
290
    }
291
292
    /**
293
     * Test invalid file adapter strategy root
294
     *
295
     * @expectedException \Apparat\Object\Domain\Repository\InvalidArgumentException
296
     * @expectedExceptionCode 1450136346
297
     */
298
    public function testMissingFileStrategyRoot()
299
    {
300
        InfrastructureRepository::register(
301
            getenv('REPOSITORY_URL'),
302
            [
303
                'type' => FileAdapterStrategy::TYPE,
304
            ]
305
        );
306
        InfrastructureRepository::instance(getenv('REPOSITORY_URL'));
307
    }
308
309
    /**
310
     * Test empty file adapter strategy root
311
     *
312
     * @expectedException \Apparat\Object\Infrastructure\Repository\InvalidArgumentException
313
     * @expectedExceptionCode 1449956977
314
     */
315
    public function testEmptyFileStrategyRoot()
316
    {
317
        InfrastructureRepository::register(
318
            getenv('REPOSITORY_URL'),
319
            [
320
                'type' => FileAdapterStrategy::TYPE,
321
                'root' => '',
322
            ]
323
        );
324
        InfrastructureRepository::instance(getenv('REPOSITORY_URL'));
325
    }
326
327
    /**
328
     * Test invalid file adapter strategy root
329
     *
330
     * @expectedException \Apparat\Object\Infrastructure\Repository\InvalidArgumentException
331
     * @expectedExceptionCode 1449957017
332
     */
333
    public function testInvalidFileStrategyRoot()
334
    {
335
        InfrastructureRepository::register(
336
            getenv('REPOSITORY_URL'),
337
            [
338
                'type' => FileAdapterStrategy::TYPE,
339
                'root' => '__FILE__',
340
            ]
341
        );
342
        InfrastructureRepository::instance(getenv('REPOSITORY_URL'));
343
    }
344
345
    /**
346
     * Test invalid repository URL during instantiation
347
     *
348
     * @expectedException \Apparat\Object\Domain\Repository\InvalidArgumentException
349
     * @expectedExceptionCode 1451771889
350
     */
351
    public function testUnknownRepositoryUrlInstance()
352
    {
353
        InfrastructureRepository::register(
354
            getenv('REPOSITORY_URL'),
355
            [
356
                'type' => FileAdapterStrategy::TYPE,
357
                'root' => self::$globBase,
358
            ]
359
        );
360
        InfrastructureRepository::instance('http://example.com');
361
    }
362
363
    /**
364
     * Test file repository
365
     */
366
    public function testFileRepository()
367
    {
368
        InfrastructureRepository::register(
369
            getenv('REPOSITORY_URL'),
370
            [
371
                'type' => FileAdapterStrategy::TYPE,
372
                'root' => self::$globBase,
373
            ]
374
        );
375
        $fileRepository = InfrastructureRepository::instance(getenv('REPOSITORY_URL'));
376
        $this->assertInstanceOf(Repository::class, $fileRepository);
377
378
        $selector = SelectorFactory::createFromString('/*');
379
        $this->assertInstanceOf(SelectorInterface::class, $selector);
380
        $collection = $fileRepository->findObjects($selector);
381
        $this->assertInstanceOf(Collection::class, $collection);
382
        $this->assertEquals(self::$globRevisions[''], count($collection));
383
        $this->assertEquals(0, $fileRepository->getSize());
384
    }
385
386
    /**
387
     * Test file repository with revisions
388
     */
389
    public function testFileRepositoryRevisions()
390
    {
391
        InfrastructureRepository::register(
392
            getenv('REPOSITORY_URL'),
393
            [
394
                'type' => FileAdapterStrategy::TYPE,
395
                'root' => self::$globBase,
396
            ]
397
        );
398
        $fileRepository = InfrastructureRepository::instance(getenv('REPOSITORY_URL'));
399
400
        $selector = SelectorFactory::createFromString('/*/*/*/*/*/*/*-*/*-1');
401
        $collection = $fileRepository->findObjects($selector);
402
        $this->assertInstanceOf(Collection::class, $collection);
403
        $this->assertEquals(self::$globRevisions['-1'], count($collection));
404
    }
405
406
    /**
407
     * Test a repository locator
408
     */
409
    public function testRepositoryLocator()
410
    {
411
        InfrastructureRepository::register(
412
            getenv('REPOSITORY_URL'),
413
            [
414
                'type' => FileAdapterStrategy::TYPE,
415
                'root' => self::$globBase,
416
            ]
417
        );
418
        $fileRepository = InfrastructureRepository::instance(getenv('REPOSITORY_URL'));
419
        $repositoryLocator = new RepositoryLocator($fileRepository, '/2015/10/01/00/00/00/36704-event/36704-1');
420
        $this->assertInstanceOf(RepositoryLocator::class, $repositoryLocator);
421
        $this->assertEquals($fileRepository, $repositoryLocator->getRepository());
422
    }
423
424
    /**
425
     * Test the creation of a new repository
426
     */
427
    public function testRepositoryCreation()
428
    {
429
        $this->tmpFiles[] = $tempRepoDirectory = sys_get_temp_dir().DIRECTORY_SEPARATOR.'temp-repo';
430
        $this->tmpFiles[] = $tempRepoConfigDir = $tempRepoDirectory.DIRECTORY_SEPARATOR.'.repo';
431
        $this->tmpFiles[] = $tempRepoConfigDir.DIRECTORY_SEPARATOR.'size.txt';
432
        $fileRepository = RepositoryFacade::create(
433
            getenv('REPOSITORY_URL'),
434
            [
435
                'type' => FileAdapterStrategy::TYPE,
436
                'root' => $tempRepoDirectory,
437
            ]
438
        );
439
        $this->assertInstanceOf(RepositoryFacade::class, $fileRepository);
440
    }
441
442
    /**
443
     * Test creation of a repository over an existing file
444
     *
445
     * @expectedException \Apparat\Object\Domain\Repository\RuntimeException
446
     * @expectedExceptionCode 1461276430
447
     */
448
    public function testRepositoryCreationOverExistingFile()
449
    {
450
        $tempFile = $this->createTemporaryFile();
451
        InfrastructureRepository::create(
452
            getenv('REPOSITORY_URL'),
453
            [
454
                'type' => FileAdapterStrategy::TYPE,
455
                'root' => $tempFile,
456
            ]
457
        );
458
    }
459
460
    /**
461
     * Test creation of a repository over an existing size descriptor directory
462
     *
463
     * @expectedException \Apparat\Object\Domain\Repository\RuntimeException
464
     * @expectedExceptionCode 1461276603
465
     */
466
    public function testRepositoryCreationOverExistingSizeDescriptor()
467
    {
468
        $this->tmpFiles[] = $tempRepoDirectory = sys_get_temp_dir().DIRECTORY_SEPARATOR.'temp-repo';
469
        $this->tmpFiles[] = $tempRepoConfigDir = $tempRepoDirectory.DIRECTORY_SEPARATOR.'.repo';
470
        $this->tmpFiles[] = $tempSizeDescriptor = $tempRepoConfigDir.DIRECTORY_SEPARATOR.'size.txt';
471
        mkdir($tempSizeDescriptor, 0777, true);
472
        InfrastructureRepository::create(
473
            getenv('REPOSITORY_URL'),
474
            [
475
                'type' => FileAdapterStrategy::TYPE,
476
                'root' => $tempRepoDirectory,
477
            ]
478
        );
479
    }
480
}
481