Completed
Pull Request — develop (#24)
by Ben
06:57 queued 04:18
created

DeepCopyTest::assertDeepCopyOf()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 27
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 27
rs 8.439
c 0
b 0
f 0
cc 6
eloc 20
nc 6
nop 2
1
<?php
2
3
use GroupByInc\API\Util\DeepCopy;
4
5
class DeepCopyTest extends PHPUnit_Framework_TestCase
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
6
{
7
    public function testSimpleObjectCopy()
8
    {
9
        $o = new A();
10
11
        $deepCopy = new DeepCopy();
12
13
        $this->assertDeepCopyOf($o, $deepCopy->copy($o));
14
    }
15
16
    public function testPropertyScalarCopy()
17
    {
18
        $o = new A();
19
        $o->property1 = 'foo';
20
21
        $deepCopy = new DeepCopy();
22
23
        $this->assertDeepCopyOf($o, $deepCopy->copy($o));
24
    }
25
26 View Code Duplication
    public function testPropertyObjectCopy()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
27
    {
28
        $o = new A();
29
        $o->property1 = new B();
30
31
        $deepCopy = new DeepCopy();
32
33
        $this->assertDeepCopyOf($o, $deepCopy->copy($o));
34
    }
35
36 View Code Duplication
    public function testPropertyArrayCopy()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
37
    {
38
        $o = new A();
39
        $o->property1 = [new B()];
40
41
        $deepCopy = new DeepCopy();
42
43
        $this->assertDeepCopyOf($o, $deepCopy->copy($o));
44
    }
45
46
    public function testCycleCopy1()
47
    {
48
        $a = new A();
49
        $b = new B();
50
        $c = new B();
51
        $a->property1 = $b;
52
        $a->property2 = $c;
53
        $b->property = $c;
54
55
        $deepCopy = new DeepCopy();
56
        /** @var A $a2 */
57
        $a2 = $deepCopy->copy($a);
58
59
        $this->assertDeepCopyOf($a, $a2);
60
61
        $this->assertSame($a2->property1->property, $a2->property2);
62
    }
63
64
    public function testCycleCopy2()
65
    {
66
        $a = new B();
67
        $b = new B();
68
        $a->property = $b;
69
        $b->property = $a;
70
71
        $deepCopy = new DeepCopy();
72
        /** @var B $a2 */
73
        $a2 = $deepCopy->copy($a);
74
75
        $this->assertSame($a2, $a2->property->property);
76
    }
77
78
    /**
79
     * Dynamic properties should be cloned
80
     */
81
    public function testDynamicProperties()
82
    {
83
        $a = new \stdClass();
84
        $a->b = new \stdClass();
85
86
        $deepCopy = new DeepCopy();
87
        $a2 = $deepCopy->copy($a);
88
        $this->assertNotSame($a->b, $a2->b);
89
        $this->assertDeepCopyOf($a, $a2);
90
    }
91
92
    public function testNonClonableItems()
93
    {
94
        $a = new \ReflectionClass('\A');
95
        $deepCopy = new DeepCopy();
96
        $a2 = $deepCopy->skipUncloneable()->copy($a);
97
        $this->assertSame($a, $a2);
98
    }
99
100
    /**
101
     * @expectedException \Exception
102
     * @expectedExceptionMessage Class "C" is not cloneable.
103
     */
104
    public function testCloneException()
105
    {
106
        $o = new \ReflectionClass('\C');
107
        $deepCopy = new DeepCopy();
108
        $deepCopy->copy($o);
109
    }
110
111
    protected function assertDeepCopyOf($expected, $actual)
112
    {
113
        if (is_null($expected)) {
114
            $this->assertNull($actual);
115
            return;
116
        }
117
        $this->assertInternalType(gettype($expected), $actual);
118
        if (is_array($expected)) {
119
            $this->assertInternalType('array', $actual);
120
            $this->assertCount(count($expected), $actual);
121
            foreach ($actual as $i => $item) {
122
                $this->assertDeepCopyOf($expected[$i], $item);
123
            }
124
            return;
125
        }
126
        if (!is_object($expected)) {
127
            $this->assertSame($expected, $actual);
128
            return;
129
        }
130
        $this->assertNotSame($expected, $actual);
131
        $this->assertInstanceOf(get_class($expected), $actual);
132
        $class = new \ReflectionClass($actual);
133
        foreach ($class->getProperties() as $property) {
134
            $property->setAccessible(true);
135
            $this->assertDeepCopyOf($property->getValue($expected), $property->getValue($actual));
136
        }
137
    }
138
}
139
140
class A
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
141
{
142
    public $property1;
143
    public $property2;
144
}
145
146
class B
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
147
{
148
    public $property;
149
}
150
151
class C
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
152
{
153
    private function __clone(){}
154
}