SyncTest::testDirSync()   B
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 46
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 46
rs 8.9411
c 1
b 0
f 0
cc 2
eloc 28
nc 2
nop 0
1
<?php
2
namespace Tests\AppBundle\Sync;
3
4
use AppBundle\Sync\Entity\Filter\Path;
5
use AppBundle\Sync\Storage\Local;
6
use AppBundle\Sync\Sync;
7
use Hope\Locker\FileLocker;
8
use org\bovigo\vfs\vfsStream;
9
use org\bovigo\vfs\vfsStreamDirectory;
10
use org\bovigo\vfs\visitor\vfsStreamStructureVisitor;
11
12
/**
13
 * Sync tests
14
 *
15
 * @author Sergey Sadovoi <[email protected]>
16
 */
17
class SyncTest extends \PHPUnit_Framework_TestCase
18
{
19
    /**
20
     * Root directory of virtual FS
21
     *
22
     * @var vfsStreamDirectory
23
     */
24
    protected $root;
25
26
    public function setUp()
27
    {
28
        $tree = [
29
            'source' => [
30
                'TEST' => [
31
                    'stream' => [
32
                        'TEST00213.mov' => 'test stream content',
33
                        'TEST00313.mov' => 'test stream content',
34
                    ],
35
                    'source' => [
36
                        'TEST00213.mov' => 'test source content',
37
                    ],
38
                ],
39
                'ZZZZ' => [
40
                    'stream' => [
41
                        'ZZZZ00113.mov' => 'test stream content',
42
                    ],
43
                    'source' => [
44
                        'ZZZZ00313.mov' => 'test source content',
45
                    ],
46
                ]
47
            ],
48
            'dest' => [
49
                'TEST' => [
50
                    'TEST00213.mov' => 'test stream content',
51
                    'TEST00313.mov' => 'test stream content 2',
52
                    'TEST00413.mov' => 'test stream content 2',
53
                ],
54
            ],
55
            'lock' => [
56
                'lock.tmp' => '',
57
            ],
58
        ];
59
        // Init virtual FS
60
        $this->root = vfsStream::setup('root', null, $tree);
61
    }
62
63
    public function testDirSync()
64
    {
65
        $sync = new Sync();
66
67
        // Set up Master
68
        $pathFilter = new Path();
69
        $pathFilter->setPattern('~[A-Z]{4}/stream/.*\.mov~');
70
71
        $masterStorage = new Local();
72
        $masterPath    = 'root/source';
73
        $masterFilters = [$pathFilter];
74
75
        $sync->setMasterStorage($masterStorage);
76
        $sync->setMasterPath(vfsStream::url($masterPath));
77
        $sync->setMasterFilters($masterFilters);
78
79
        // Set up Slave
80
        $slaveStorage = new Local();
81
        $slavePath    = 'root/dest';
82
        $slavePathTpl = $slavePath . '/__program__/__uid__';
83
84
        $sync->setSlaveStorage($slaveStorage);
85
        $sync->setSlavePath(vfsStream::url($slavePath));
86
        $sync->setSlavePathTpl(vfsStream::url($slavePathTpl));
87
88
        $locker = new FileLocker('test-sync', vfsStream::url('root/lock'));
89
        $sync->setLocker($locker);
90
91
        // Run
92
        $sync->run();
93
94
        // Test
95
        $files = [
96
            'root/dest/TEST/TEST00213.mov' => 'test stream content',
97
            'root/dest/TEST/TEST00313.mov' => 'test stream content',
98
            'root/dest/ZZZZ/ZZZZ00113.mov' => 'test stream content',
99
        ];
100
        $removed = 'root/dest/TEST/TEST00413.mov';
101
102
        foreach ($files as $path => $content) {
103
            $this->assertTrue($this->root->hasChild($path));
104
            $this->assertEquals($content, $this->root->getChild($path)->getContent());
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface org\bovigo\vfs\vfsStreamContent as the method getContent() does only exist in the following implementations of said interface: org\bovigo\vfs\vfsStreamBlock, org\bovigo\vfs\vfsStreamFile.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
105
        }
106
107
        $this->assertFalse($this->root->hasChild($removed));
108
    }
109
}
110