Completed
Push — master ( c5cc72...7c6f56 )
by Jean-Christophe
02:02
created

Example   A

Complexity

Total Complexity 3

Size/Duplication

Total Lines 14
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 1

Importance

Changes 0
Metric Value
wmc 3
lcom 0
cbo 1
dl 0
loc 14
rs 10
c 0
b 0
f 0
1
<?php
2
	require_once('simpletest/autorun.php');
3
	require_once('simpletest/mock_objects.php');
4
	
5
	require_once(dirname(__FILE__).'/../../annotations.php');
6
	
7
	interface DummyInterface {}
8
	
9
	class ParentExample {}
10
	
11
	/** @FirstAnnotation @SecondAnnotation */
12
	class Example extends ParentExample implements DummyInterface {
13
		/** @SecondAnnotation */
14
		private $exampleProperty;
15
		
16
		public $publicOne;
17
		
18
		public function __construct() {}
19
		
20
		/** @FirstAnnotation */
21
		public function exampleMethod() {
22
		}
23
		
24
		private function justPrivate() {}
25
	}
26
	
27
	/** @FirstAnnotation(1) @FirstAnnotation(2) @SecondAnnotation(3) */
28
	class MultiExample {
29
		/** @FirstAnnotation(1) @FirstAnnotation(2) @SecondAnnotation(3) */
30
		public $property;
31
		
32
		/** @FirstAnnotation(1) @FirstAnnotation(2) @SecondAnnotation(3) */
33
		public function aMethod() {}
34
	}
35
	
36
	class FirstAnnotation extends Annotation {
37
		public $key;
38
	}
39
40
	class SecondAnnotation extends Annotation {}
41
42
	class NoAnnotation {}
43
44
	/** @NoAnnotation @FirstAnnotation */
45
	class ExampleWithInvalidAnnotation {}
46
47
	/** @SelfReferencingAnnotation */
48
	class SelfReferencingAnnotation extends Annotation {}
49
50
	/** @IndirectReferenceLoopAnnotationHelper */
51
	class IndirectReferenceLoopAnnotation extends Annotation {}
52
53
	/** @IndirectReferenceLoopAnnotation */
54
	class IndirectReferenceLoopAnnotationHelper extends Annotation {}
55
56
57
	class Statics {
58
		const A_CONSTANT = 'constant';
59
		static public $static = 'static';
60
	}
61
62
	/** @FirstAnnotation(Statics::A_CONSTANT) */
63
	class ClassAnnotatedWithStaticConstant {}
64
65
	/** @FirstAnnotation(Statics::UNKNOWN_CONSTANT) */
66
	class ClassAnnotatedWithNonExistingConstant {}
67
68
	/** @FirstAnnotation(key = @SecondAnnotation(3.14)) */
69
	class ClassAnnotatedWithNestedAnnotations {}
70
71
	class Namespace_AnnotationWithNamespace extends Annotation {}
72
73
	/** @AnnotationWithNamespace */
74
	class ClassAnnotatedWithNamespacedAnnotation {}
75
	
76
	class TestOfAnnotations extends UnitTestCase {
77
		public function testReflectionAnnotatedClass() {
78
			$reflection = new ReflectionAnnotatedClass('Example');
79
			$this->assertTrue($reflection->hasAnnotation('FirstAnnotation'));
80
			$this->assertTrue($reflection->hasAnnotation('SecondAnnotation'));
81
			$this->assertFalse($reflection->hasAnnotation('NonExistentAnnotation'));
82
			$this->assertIsA($reflection->getAnnotation('FirstAnnotation'), 'FirstAnnotation');
83
			$this->assertIsA($reflection->getAnnotation('SecondAnnotation'), 'SecondAnnotation');
84
			
85
			$annotations = $reflection->getAnnotations();
86
			$this->assertEqual(count($annotations), 2);
87
			$this->assertIsA($annotations[0], 'FirstAnnotation');
88
			$this->assertIsA($annotations[1], 'SecondAnnotation');
89
			$this->assertFalse($reflection->getAnnotation('NonExistentAnnotation'));
90
			
91
			$this->assertIsA($reflection->getConstructor(), 'ReflectionAnnotatedMethod');
92
			$this->assertIsA($reflection->getMethod('exampleMethod'), 'ReflectionAnnotatedMethod');
93
			foreach($reflection->getMethods() as $method) {
94
				$this->assertIsA($method, 'ReflectionAnnotatedMethod');
95
			}
96
			
97
			$this->assertIsA($reflection->getProperty('exampleProperty'), 'ReflectionAnnotatedProperty');
98
			foreach($reflection->getProperties() as $property) {
99
				$this->assertIsA($property, 'ReflectionAnnotatedProperty');
100
			}
101
			
102
			foreach($reflection->getInterfaces() as $interface) {
103
				$this->assertIsA($interface, 'ReflectionAnnotatedClass');
104
			}
105
			
106
			$this->assertIsA($reflection->getParentClass(), 'ReflectionAnnotatedClass');
107
		}
108
		
109
		public function testReflectionAnnotatedMethod() {
110
			$reflection = new ReflectionAnnotatedMethod('Example', 'exampleMethod');
111
			$this->assertTrue($reflection->hasAnnotation('FirstAnnotation'));
112
			$this->assertFalse($reflection->hasAnnotation('NonExistentAnnotation'));
113
			$this->assertIsA($reflection->getAnnotation('FirstAnnotation'), 'FirstAnnotation');
114
			$this->assertFalse($reflection->getAnnotation('NonExistentAnnotation'));
115
			
116
			$annotations = $reflection->getAnnotations();
117
			$this->assertEqual(count($annotations), 1);
118
			$this->assertIsA($annotations[0], 'FirstAnnotation');
119
			
120
			$this->assertIsA($reflection->getDeclaringClass(), 'ReflectionAnnotatedClass');
121
		}
122
		
123
		public function testReflectionAnnotatedProperty() {
124
			$reflection = new ReflectionAnnotatedProperty('Example', 'exampleProperty');
125
			$this->assertTrue($reflection->hasAnnotation('SecondAnnotation'));
126
			$this->assertFalse($reflection->hasAnnotation('FirstAnnotation'));
127
			$this->assertIsA($reflection->getAnnotation('SecondAnnotation'), 'SecondAnnotation');
128
			$this->assertFalse($reflection->getAnnotation('NonExistentAnnotation'));
129
			
130
			$annotations = $reflection->getAnnotations();
131
			$this->assertEqual(count($annotations), 1);
132
			$this->assertIsA($annotations[0], 'SecondAnnotation');
133
			
134
			$this->assertIsA($reflection->getDeclaringClass(), 'ReflectionAnnotatedClass');
135
		}
136
		
137
		public function testReflectionClassCanFilterMethodsByAccess() {
138
			$reflection = new ReflectionAnnotatedClass('Example');
139
			$privateMethods = $reflection->getMethods(ReflectionMethod::IS_PRIVATE);
140
			$this->assertEqual(count($privateMethods), 1);
141
			$this->assertEqual($privateMethods[0]->getName(), 'justPrivate');
142
		}
143
		
144
		public function testReflectionClassCanFilterPropertiesByAccess() {
145
			$reflection = new ReflectionAnnotatedClass('Example');
146
			$privateProperties = $reflection->getProperties(ReflectionProperty::IS_PUBLIC);
147
			$this->assertEqual(count($privateProperties), 1);
148
			$this->assertEqual($privateProperties[0]->getName(), 'publicOne');
149
		}
150
		
151
		public function testReflectionClassShouldReturnAllMethodsWithNoFilter() {
152
			$reflection = new ReflectionAnnotatedClass('Example');
153
			$methods = $reflection->getMethods();
154
			$this->assertEqual(count($methods), 3);
155
		}
156
		
157
		public function testReflectionClassShouldReturnAllPropertiesWithNoFilter() {
158
			$reflection = new ReflectionAnnotatedClass('Example');
159
			$properties = $reflection->getProperties();
160
			$this->assertEqual(count($properties), 2);
161
		}
162
		
163
		public function testMultipleAnnotationsOnClass() {
164
			$reflection = new ReflectionAnnotatedClass('MultiExample');
165
			$annotations = $reflection->getAllAnnotations();
166
			$this->assertEqual(count($annotations), 3);
167
			$this->assertEqual($annotations[0]->value, 1);
168
			$this->assertEqual($annotations[1]->value, 2);
169
			$this->assertEqual($annotations[2]->value, 3);
170
			$this->assertIsA($annotations[0], 'FirstAnnotation');
171
			$this->assertIsA($annotations[1], 'FirstAnnotation');
172
			$this->assertIsA($annotations[2], 'SecondAnnotation');
173
		}
174
		
175
		public function testMultipleAnnotationsOnClassWithRestriction() {
176
			$reflection = new ReflectionAnnotatedClass('MultiExample');
177
			$annotations = $reflection->getAllAnnotations('FirstAnnotation');
178
			$this->assertEqual(count($annotations), 2);
179
			$this->assertEqual($annotations[0]->value, 1);
180
			$this->assertEqual($annotations[1]->value, 2);
181
			$this->assertIsA($annotations[0], 'FirstAnnotation');
182
			$this->assertIsA($annotations[1], 'FirstAnnotation');
183
		}
184
		
185
		public function testMultipleAnnotationsOnProperty() {
186
			$reflection = new ReflectionAnnotatedClass('MultiExample');
187
			$reflection = $reflection->getProperty('property');
188
			$annotations = $reflection->getAllAnnotations();
189
			$this->assertEqual(count($annotations), 3);
190
			$this->assertEqual($annotations[0]->value, 1);
191
			$this->assertEqual($annotations[1]->value, 2);
192
			$this->assertEqual($annotations[2]->value, 3);
193
			$this->assertIsA($annotations[0], 'FirstAnnotation');
194
			$this->assertIsA($annotations[1], 'FirstAnnotation');
195
			$this->assertIsA($annotations[2], 'SecondAnnotation');
196
		}
197
198
		public function testMultipleAnnotationsOnPropertyWithRestriction() {
199
			$reflection = new ReflectionAnnotatedClass('MultiExample');
200
			$reflection = $reflection->getProperty('property');
201
			$annotations = $reflection->getAllAnnotations('FirstAnnotation');
202
			$this->assertEqual(count($annotations), 2);
203
			$this->assertEqual($annotations[0]->value, 1);
204
			$this->assertEqual($annotations[1]->value, 2);
205
			$this->assertIsA($annotations[0], 'FirstAnnotation');
206
			$this->assertIsA($annotations[1], 'FirstAnnotation');
207
		}
208
		
209
		public function testMultipleAnnotationsOnMethod() {
210
			$reflection = new ReflectionAnnotatedClass('MultiExample');
211
			$reflection = $reflection->getMethod('aMethod');
212
			$annotations = $reflection->getAllAnnotations();
213
			$this->assertEqual(count($annotations), 3);
214
			$this->assertEqual($annotations[0]->value, 1);
215
			$this->assertEqual($annotations[1]->value, 2);
216
			$this->assertEqual($annotations[2]->value, 3);
217
			$this->assertIsA($annotations[0], 'FirstAnnotation');
218
			$this->assertIsA($annotations[1], 'FirstAnnotation');
219
			$this->assertIsA($annotations[2], 'SecondAnnotation');
220
		}
221
222
		public function testMultipleAnnotationsOnMethodWithRestriction() {
223
			$reflection = new ReflectionAnnotatedClass('MultiExample');
224
			$reflection = $reflection->getMethod('aMethod');
225
			$annotations = $reflection->getAllAnnotations('FirstAnnotation');
226
			$this->assertEqual(count($annotations), 2);
227
			$this->assertEqual($annotations[0]->value, 1);
228
			$this->assertEqual($annotations[1]->value, 2);
229
			$this->assertIsA($annotations[0], 'FirstAnnotation');
230
			$this->assertIsA($annotations[1], 'FirstAnnotation');
231
		}
232
233
		public function testClassWithNoAnnotationParentShouldNotBeParsed() {
234
			$reflection = new ReflectionAnnotatedClass('ExampleWithInvalidAnnotation');
235
			$annotations = $reflection = $reflection->getAnnotations();
236
			$this->assertEqual(count($annotations), 1);
237
			$this->assertIsA($annotations[0], 'FirstAnnotation');
238
		}
239
240
		public function testCircularReferenceShouldThrowError() {
241
			$this->expectError("Circular annotation reference on 'SelfReferencingAnnotation'");
242
			$reflection = new ReflectionAnnotatedClass('SelfReferencingAnnotation');
243
			$reflection->getAnnotations();
244
245
			$this->expectError("Circular annotation reference on 'IndirectReferenceLoopAnnotationHelper'");
246
			$reflection = new ReflectionAnnotatedClass('IndirectReferenceLoopAnnotation');
247
			$reflection->getAnnotations();
248
		}
249
250
		public function testConstInAnnotationShouldReturnCorrectValue() {
251
			$reflection = new ReflectionAnnotatedClass('ClassAnnotatedWithStaticConstant');
252
			$annotation = $reflection->getAnnotation('FirstAnnotation');
253
			$this->assertEqual($annotation->value, Statics::A_CONSTANT);
254
		}
255
256
		public function testBadConstInAnnotationShouldCauseError() {
257
			$this->expectError("Constant 'Statics::UNKNOWN_CONSTANT' used in annotation was not defined.");
258
			$reflection = new ReflectionAnnotatedClass('ClassAnnotatedWithNonExistingConstant');
259
			$annotation = $reflection->getAnnotation('FirstAnnotation');
260
		}
261
262
		public function testNestedAnnotationSupport() {
263
			$reflection = new ReflectionAnnotatedClass('ClassAnnotatedWithNestedAnnotations');
264
			$this->assertEqual(count($reflection->getAnnotations()), 1);
265
			$annotation = $reflection->getAnnotation('FirstAnnotation');
266
			$this->assertIsA($annotation, 'FirstAnnotation');
267
			$this->assertIsA($annotation->key, 'SecondAnnotation');
268
			$this->assertEqual($annotation->key->value, 3.14);
269
		}
270
271
		public function testAnnotationWithoutNamespaceShouldBeRecognized() {
272
			$reflection = new ReflectionAnnotatedClass('ClassAnnotatedWithNamespacedAnnotation');
273
			$this->assertTrue($reflection->hasAnnotation('AnnotationWithNamespace'));
274
		}
275
	}
276
	
277
	Mock::generatePartial('AnnotationsBuilder', 'MockedAnnotationsBuilder', array('getDocComment'));
278
	
279
	class TestOfPerformanceFeatures extends UnitTestCase {
280
		public function setUp() {
281
			AnnotationsBuilder::clearCache();
282
		}
283
284
		public function tearDown() {
285
			AnnotationsBuilder::clearCache();
286
		}
287
	
288
		public function testBuilderShouldCacheResults() {
289
			$builder = new MockedAnnotationsBuilder;
290
			$reflection = new ReflectionClass('Example');
291
			$builder->build($reflection);
292
			$builder->build($reflection);
293
			$builder->expectOnce('getDocComment');
294
		}
295
	}
296
	
297
	class TestOfSupportingFeatures extends UnitTestCase {
298
		public function setUp() {
299
			Addendum::resetIgnoredAnnotations();
300
		}
301
		
302
		public function tearDown() {
303
			Addendum::resetIgnoredAnnotations();
304
		}
305
	
306
		public function testIgnoredAnnotationsAreNotUsed() {
307
			Addendum::ignore('FirstAnnotation', 'SecondAnnotation');
308
			$reflection = new ReflectionAnnotatedClass('Example');
309
			$this->assertFalse($reflection->hasAnnotation('FirstAnnotation'));
310
			$this->assertFalse($reflection->hasAnnotation('SecondAnnotation'));
311
		}
312
	}
313
?>
314