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() |
|
|
|
|
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() |
|
|
|
|
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() |
|
|
|
|
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() |
|
|
|
|
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() |
|
|
|
|
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() |
|
|
|
|
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() |
|
|
|
|
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() |
|
|
|
|
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
|
|
|
|
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.