Completed
Push — optimize_byOrdinal ( 61c23d...77e489 )
by Marc
01:51
created

EnumTest::testGetEnumeratorsConstansNotDetected()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 11

Duplication

Lines 16
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 16
loc 16
rs 9.4285
c 1
b 0
f 0
cc 2
eloc 11
nc 2
nop 0
1
<?php
2
3
namespace MabeEnumTest;
4
5
use InvalidArgumentException;
6
use LogicException;
7
use MabeEnum\Enum;
8
use MabeEnumTest\TestAsset\EnumBasic;
9
use MabeEnumTest\TestAsset\EnumInheritance;
10
use MabeEnumTest\TestAsset\EnumAmbiguous;
11
use MabeEnumTest\TestAsset\EnumExtendedAmbiguous;
12
use MabeEnumTest\TestAsset\ConstVisibilityEnum;
13
use MabeEnumTest\TestAsset\ConstVisibilityEnumExtended;
14
use MabeEnumTest\TestAsset\SerializableEnum;
15
use PHPUnit_Framework_TestCase as TestCase;
16
use ReflectionClass;
17
18
/**
19
 * Unit tests for the class MabeEnum\Enum
20
 *
21
 * @link http://github.com/marc-mabe/php-enum for the canonical source repository
22
 * @copyright Copyright (c) 2015 Marc Bennewitz
23
 * @license http://github.com/marc-mabe/php-enum/blob/master/LICENSE.txt New BSD License
24
 */
25
class EnumTest extends TestCase
26
{
27
    public function setUp()
28
    {
29
        $enumRefl = new ReflectionClass(Enum::class);
30
31
        $constantsProp = $enumRefl->getProperty('constants');
32
        $namesProp = $enumRefl->getProperty('names');
33
        $instancesProp = $enumRefl->getProperty('instances');
34
35
        $constantsProp->setAccessible(true);
36
        $namesProp->setAccessible(true);
37
        $instancesProp->setAccessible(true);
38
39
        $constantsProp->setValue(null, []);
40
        $namesProp->setValue(null, []);
41
        $instancesProp->setValue(null, []);
42
    }
43
44
    public function testGetNameReturnsConstantNameOfCurrentValue()
45
    {
46
        $enum = EnumBasic::get(EnumBasic::ONE);
47
        $this->assertSame('ONE', $enum->getName());
48
    }
49
50
    public function testToStringMagicMethodReturnsName()
51
    {
52
        $enum = EnumBasic::get(EnumBasic::ONE);
53
        $this->assertSame('ONE', $enum->__toString());
54
    }
55
56
    public function testEnumInheritance()
57
    {
58
        $this->assertSame(array(
59
            'ONE'           => 1,
60
            'TWO'           => 2,
61
            'THREE'         => 3,
62
            'FOUR'          => 4,
63
            'FIVE'          => 5,
64
            'SIX'           => 6,
65
            'SEVEN'         => 7,
66
            'EIGHT'         => 8,
67
            'NINE'          => 9,
68
            'ZERO'          => 0,
69
            'FLOAT'         => 0.123,
70
            'STR'           => 'str',
71
            'STR_EMPTY'     => '',
72
            'NIL'           => null,
73
            'BOOLEAN_TRUE'  => true,
74
            'BOOLEAN_FALSE' => false,
75
            'INHERITANCE'   => 'Inheritance',
76
        ), EnumInheritance::getConstants());
77
78
        $enum = EnumInheritance::get(EnumInheritance::ONE);
79
        $this->assertSame(EnumInheritance::ONE, $enum->getValue());
80
        $this->assertSame(0, $enum->getOrdinal());
81
82
        $enum = EnumInheritance::get(EnumInheritance::INHERITANCE);
83
        $this->assertSame(EnumInheritance::INHERITANCE, $enum->getValue());
84
        $this->assertSame(16, $enum->getOrdinal());
85
    }
86
87
    public function testGetWithStrictValue()
88
    {
89
        $enum = EnumBasic::get(EnumBasic::ONE);
90
        $this->assertSame(1, $enum->getValue());
91
        $this->assertSame(0, $enum->getOrdinal());
92
    }
93
94
    public function testGetWithNonStrictValueThrowsInvalidArgumentException()
95
    {
96
        $this->setExpectedException(InvalidArgumentException::class);
97
        EnumBasic::get((string)EnumBasic::TWO);
98
    }
99
100
    public function testGetWithInvalidValueThrowsInvalidArgumentException()
101
    {
102
        $this->setExpectedException(InvalidArgumentException::class);
103
        EnumBasic::get('unknown');
104
    }
105
106
    public function testGetWithInvalidTypeOfValueThrowsInvalidArgumentException()
107
    {
108
        $this->setExpectedException(InvalidArgumentException::class);
109
        EnumBasic::get(array());
110
    }
111
112
    public function testGetByInstance()
113
    {
114
        $enum1 = EnumBasic::get(EnumBasic::ONE);
115
        $enum2 = EnumBasic::get($enum1);
116
        $this->assertSame($enum1, $enum2);
117
    }
118
119
    public function testGetByExtendedInstanceOfKnownValue()
120
    {
121
        $enum = EnumInheritance::get(EnumInheritance::ONE);
122
123
        $this->setExpectedException(InvalidArgumentException::class);
124
        EnumBasic::get($enum);
125
    }
126
127 View Code Duplication
    public function testGetEnumeratorsConstansAlreadyDetected()
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...
128
    {
129
        $constants   = EnumInheritance::getConstants();
130
        $enumerators = EnumInheritance::getEnumerators();
131
        $count       = count($enumerators);
132
133
        $this->assertSame(count($constants), $count);
134
        for ($i = 0; $i < $count; ++$i) {
135
            $this->assertArrayHasKey($i, $enumerators);
136
            $this->assertInstanceOf(EnumInheritance::class, $enumerators[$i]);
137
138
            $enumerator = $enumerators[$i];
139
            $this->assertArrayHasKey($enumerator->getName(), $constants);
140
            $this->assertSame($constants[$enumerator->getName()], $enumerator->getValue());
141
        }
142
    }
143
144 View Code Duplication
    public function testGetEnumeratorsConstansNotDetected()
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...
145
    {
146
        $enumerators = EnumInheritance::getEnumerators();
147
        $constants   = EnumInheritance::getConstants();
148
        $count       = count($enumerators);
149
150
        $this->assertSame(count($constants), $count);
151
        for ($i = 0; $i < $count; ++$i) {
152
            $this->assertArrayHasKey($i, $enumerators);
153
            $this->assertInstanceOf(EnumInheritance::class, $enumerators[$i]);
154
155
            $enumerator = $enumerators[$i];
156
            $this->assertArrayHasKey($enumerator->getName(), $constants);
157
            $this->assertSame($constants[$enumerator->getName()], $enumerator->getValue());
158
        }
159
    }
160
161 View Code Duplication
    public function testGetValues()
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...
162
    {
163
        $expectedValues = array_values(EnumInheritance::getConstants());
164
        $values         = EnumInheritance::getValues();
165
        $count          = count($values);
166
167
        $this->assertSame(count($expectedValues), $count);
168
        for ($i = 0; $i < $count; ++$i) {
169
            $this->assertArrayHasKey($i, $values);
170
            $this->assertSame($expectedValues[$i], $values[$i]);
171
        }
172
    }
173
174 View Code Duplication
    public function testGetNamesConstantsAlreadyDetected()
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...
175
    {
176
        $expectedNames = array_keys(EnumInheritance::getConstants());
177
        $names         = EnumInheritance::getNames();
178
        $count         = count($names);
179
180
        $this->assertSame(count($expectedNames), $count);
181
        for ($i = 0; $i < $count; ++$i) {
182
            $this->assertArrayHasKey($i, $names);
183
            $this->assertSame($expectedNames[$i], $names[$i]);
184
        }
185
    }
186
187 View Code Duplication
    public function testGetNamesConstantsNotDetected()
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...
188
    {
189
        $names         = EnumInheritance::getNames();
190
        $expectedNames = array_keys(EnumInheritance::getConstants());
191
        $count         = count($names);
192
193
        $this->assertSame(count($expectedNames), $count);
194
        for ($i = 0; $i < $count; ++$i) {
195
            $this->assertArrayHasKey($i, $names);
196
            $this->assertSame($expectedNames[$i], $names[$i]);
197
        }
198
    }
199
    
200 View Code Duplication
    public function testGetOrdinals()
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...
201
    {
202
        $constants = EnumInheritance::getConstants();
203
        $ordinals  = EnumInheritance::getOrdinals();
204
        $count     = count($ordinals);
205
206
        $this->assertSame(count($constants), $count);
207
        for ($i = 0; $i < $count; ++$i) {
208
            $this->assertArrayHasKey($i, $ordinals);
209
            $this->assertSame($i, $ordinals[$i]);
210
        }
211
    }
212
213
    public function testGetAllValues()
214
    {
215
        $constants = EnumBasic::getConstants();
216
        foreach ($constants as $name => $value) {
217
            $enum = EnumBasic::get($value);
218
            $this->assertSame($value, $enum->getValue());
219
            $this->assertSame($name, $enum->getName());
220
        }
221
    }
222
223 View Code Duplication
    public function testIsBasic()
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...
224
    {
225
        $enum = EnumBasic::ONE();
226
227
        // by value
228
        $this->assertTrue($enum->is(EnumBasic::ONE));   // same
229
        $this->assertFalse($enum->is('1'));             // wrong value by strict comparison
230
231
        // by instance
232
        $this->assertTrue($enum->is(EnumBasic::ONE()));        // same
233
        $this->assertFalse($enum->is(EnumBasic::TWO()));       // different enumerators
234
        $this->assertFalse($enum->is(EnumInheritance::ONE())); // different enumeration type
235
    }
236
237
    public function testCallingGetOrdinalTwoTimesWillResultTheSameValue()
238
    {
239
        $enum = EnumBasic::get(EnumBasic::TWO);
240
        $this->assertSame(1, $enum->getOrdinal());
241
        $this->assertSame(1, $enum->getOrdinal());
242
    }
243
244
    public function testInstantiateUsingOrdinalNumber()
245
    {
246
        $enum = EnumInheritance::byOrdinal(16);
247
        $this->assertSame(16, $enum->getOrdinal());
248
        $this->assertSame('INHERITANCE', $enum->getName());
249
    }
250
251
    public function testInstantiateUsingInvalidOrdinalNumberThrowsInvalidArgumentException()
252
    {
253
        $this->setExpectedException(InvalidArgumentException::class);
254
        EnumInheritance::byOrdinal(17);
255
    }
256
257
    public function testInstantiateByName()
258
    {
259
        $enum = EnumInheritance::byName('ONE');
260
        $this->assertInstanceOf(EnumInheritance::class, $enum);
261
        $this->assertSame(EnumInheritance::ONE, $enum->getValue());
262
    }
263
264
    public function testInstantiateByUnknownNameThrowsInvalidArgumentException()
265
    {
266
        $this->setExpectedException(InvalidArgumentException::class);
267
        EnumInheritance::byName('UNKNOWN');
268
    }
269
270
    public function testInstantiateUsingMagicMethod()
271
    {
272
        $enum = EnumInheritance::ONE();
273
        $this->assertInstanceOf(EnumInheritance::class, $enum);
274
        $this->assertSame(EnumInheritance::ONE, $enum->getValue());
275
    }
276
277
    public function testAmbiguousConstantsThrowsLogicException()
278
    {
279
        $this->setExpectedException(LogicException::class);
280
        EnumAmbiguous::get('unknown');
281
    }
282
283
    public function testExtendedAmbiguousCanstantsThrowsLogicException()
284
    {
285
        $this->setExpectedException(LogicException::class);
286
        EnumExtendedAmbiguous::get('unknown');
287
    }
288
289
    public function testSingleton()
290
    {
291
        $enum1 = EnumBasic::get(EnumBasic::ONE);
292
        $enum2 = EnumBasic::ONE();
293
        $this->assertSame($enum1, $enum2);
294
    }
295
296
    public function testCloneNotCallableAndThrowsLogicException()
297
    {
298
        $enum = EnumBasic::ONE();
299
300
        $reflectionClass  = new ReflectionClass($enum);
301
        $reflectionMethod = $reflectionClass->getMethod('__clone');
302
        $this->assertTrue($reflectionMethod->isPrivate(), 'The method __clone must be private');
303
        $this->assertTrue($reflectionMethod->isFinal(), 'The method __clone must be final');
304
305
        $reflectionMethod->setAccessible(true);
306
        $this->setExpectedException(LogicException::class);
307
        $reflectionMethod->invoke($enum);
308
    }
309
310
    public function testNotSerializable()
311
    {
312
        $enum = EnumBasic::ONE();
313
314
        $this->setExpectedException(LogicException::class);
315
        serialize($enum);
316
    }
317
318
    public function testNotUnserializable()
319
    {
320
        $this->setExpectedException(LogicException::class);
321
        unserialize('O:' . strlen(EnumBasic::class) . ':"' . EnumBasic::class . '":0:{}');
322
    }
323
324 View Code Duplication
    public function testHas()
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...
325
    {
326
        $enum = EnumBasic::ONE();
327
328
        $this->assertFalse($enum->has('invalid'));
329
        $this->assertFalse($enum->has(EnumInheritance::ONE()));
330
        $this->assertTrue($enum->has(EnumBasic::ONE()));
331
        $this->assertTrue($enum->has(EnumBasic::ONE));
332
    }
333
    
334
    public function testConstVisibility()
335
    {
336
        if (PHP_VERSION_ID < 70100) {
337
            $this->markTestSkipped('This test is for PHP-7.1 and upper only');
338
        }
339
340
        $constants = ConstVisibilityEnum::getConstants();
341
        $this->assertSame(array(
342
            'IPUB' => ConstVisibilityEnum::IPUB,
343
            'PUB'  => ConstVisibilityEnum::PUB,
344
        ), $constants);
345
    }
346
    
347
    public function testConstVisibilityExtended()
348
    {
349
        if (PHP_VERSION_ID < 70100) {
350
            $this->markTestSkipped('This test is for PHP-7.1 and upper only');
351
        }
352
353
        $constants = ConstVisibilityEnumExtended::getConstants();
354
        $this->assertSame(array(
355
            'IPUB'  => ConstVisibilityEnumExtended::IPUB,
356
            'PUB'   => ConstVisibilityEnumExtended::PUB,
357
            'IPUB2' => ConstVisibilityEnumExtended::IPUB2,
358
            'PUB2'  => ConstVisibilityEnumExtended::PUB2,
359
        ), $constants);
360
    }
361
362
    public function testIsSerializableIssue()
363
    {
364
        if (PHP_VERSION_ID < 50400) {
365
            $this->markTestSkipped('This test is for PHP-5.4 and upper only');
366
        }
367
368
        $enum1 = SerializableEnum::INT();
369
        $enum2 = unserialize(serialize($enum1));
370
371
        $this->assertFalse($enum1 === $enum2, 'Wrong test implementation');
372
        $this->assertTrue($enum1->is($enum2), 'Two different instances of exact the same enumerator should be equal');
373
    }
374
}
375