1 | /* |
2 | * Copyright (c) 2001-2009, Jean Tessier |
3 | * All rights reserved. |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions |
7 | * are met: |
8 | * |
9 | * * Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. |
11 | * |
12 | * * Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. |
15 | * |
16 | * * Neither the name of Jean Tessier nor the names of his contributors |
17 | * may be used to endorse or promote products derived from this software |
18 | * without specific prior written permission. |
19 | * |
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
23 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR |
24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31 | */ |
32 | |
33 | package com.jeantessier.classreader.impl; |
34 | |
35 | import com.jeantessier.classreader.ClassfileLoader; |
36 | import org.jmock.Expectations; |
37 | import org.jmock.Mockery; |
38 | import org.jmock.integration.junit4.JMock; |
39 | import org.jmock.lib.legacy.ClassImposteriser; |
40 | import org.junit.Before; |
41 | import org.junit.Test; |
42 | import org.junit.runner.RunWith; |
43 | |
44 | import java.util.Collection; |
45 | import java.util.Collections; |
46 | |
47 | import static org.hamcrest.Matchers.is; |
48 | import static org.hamcrest.Matchers.nullValue; |
49 | import static org.junit.Assert.assertThat; |
50 | |
51 | @RunWith(JMock.class) |
52 | public class TestClassfile { |
53 | private static final String TEST_PACKAGE_NAME = "foo"; |
54 | private static final String TEST_CLASS_NAME = TEST_PACKAGE_NAME + ".Foo"; |
55 | private static final String TEST_FIELD_NAME = TEST_CLASS_NAME + ".foo"; |
56 | private static final String TEST_METHOD_SIGNATURE = TEST_CLASS_NAME + ".foo()"; |
57 | |
58 | private Mockery context; |
59 | |
60 | private ClassfileLoader loader; |
61 | private ConstantPool constantPool; |
62 | |
63 | @Before |
64 | public void setUp() throws Exception { |
65 | context = new Mockery(); |
66 | context.setImposteriser(ClassImposteriser.INSTANCE); |
67 | |
68 | loader = context.mock(ClassfileLoader.class); |
69 | constantPool = context.mock(ConstantPool.class); |
70 | } |
71 | |
72 | @Test |
73 | public void testGetPackageName() { |
74 | final Class_info classInfo = context.mock(Class_info.class); |
75 | |
76 | context.checking(new Expectations() {{ |
77 | one (constantPool).get(1); |
78 | will(returnValue(classInfo)); |
79 | one (classInfo).getPackageName(); |
80 | will(returnValue(TEST_PACKAGE_NAME)); |
81 | }}); |
82 | |
83 | Classfile sut = new Classfile(loader, constantPool, 0x0, 1, 2, Collections.<Class_info>emptyList(), Collections.<Field_info>emptyList(), Collections.<Method_info>emptyList(), Collections.<Attribute_info>emptyList()); |
84 | |
85 | String actualValue = sut.getPackageName(); |
86 | assertThat("package name", actualValue, is(TEST_PACKAGE_NAME)); |
87 | } |
88 | |
89 | @Test |
90 | public void testLocateField_localField_succeed() throws Exception { |
91 | final Field_info expectedField = context.mock(Field_info.class, "located field"); |
92 | |
93 | Collection<Field_info> fields = Collections.singletonList(expectedField); |
94 | |
95 | context.checking(new Expectations() {{ |
96 | one (expectedField).getName(); |
97 | will(returnValue(TEST_FIELD_NAME)); |
98 | }}); |
99 | |
100 | Classfile sut = new Classfile(loader, constantPool, 0x0, 1, 2, Collections.<Class_info>emptyList(), fields, Collections.<Method_info>emptyList(), Collections.<Attribute_info>emptyList()); |
101 | |
102 | Field_info actualField = (Field_info) sut.locateField(TEST_FIELD_NAME); |
103 | assertThat("local field", actualField, is(expectedField)); |
104 | } |
105 | |
106 | @Test |
107 | public void testLocateField_publicInheritedField_succeed() throws Exception { |
108 | final String superclassName = "superclass"; |
109 | final Classfile superclass = context.mock(Classfile.class, "superclass"); |
110 | final Field_info expectedField = context.mock(Field_info.class, "located field"); |
111 | |
112 | expectClassNameLookup(2, superclassName); |
113 | |
114 | context.checking(new Expectations() {{ |
115 | one (loader).getClassfile(superclassName); |
116 | will(returnValue(superclass)); |
117 | one (superclass).locateField(TEST_FIELD_NAME); |
118 | will(returnValue(expectedField)); |
119 | one (expectedField).isPublic(); |
120 | will(returnValue(true)); |
121 | }}); |
122 | |
123 | Classfile sut = new Classfile(loader, constantPool, 0x0, 1, 2, Collections.<Class_info>emptyList(), Collections.<Field_info>emptyList(), Collections.<Method_info>emptyList(), Collections.<Attribute_info>emptyList()); |
124 | |
125 | Field_info actualField = (Field_info) sut.locateField(TEST_FIELD_NAME); |
126 | assertThat("public field", actualField, is(expectedField)); |
127 | } |
128 | |
129 | @Test |
130 | public void testLocateField_protectedInheritedField_succeed() throws Exception { |
131 | final String superclassName = "superclass"; |
132 | final Classfile superclass = context.mock(Classfile.class, "superclass"); |
133 | final Field_info expectedField = context.mock(Field_info.class, "located field"); |
134 | |
135 | expectClassNameLookup(2, superclassName); |
136 | |
137 | context.checking(new Expectations() {{ |
138 | one (loader).getClassfile(superclassName); |
139 | will(returnValue(superclass)); |
140 | one (superclass).locateField(TEST_FIELD_NAME); |
141 | will(returnValue(expectedField)); |
142 | one (expectedField).isPublic(); |
143 | will(returnValue(false)); |
144 | one (expectedField).isProtected(); |
145 | will(returnValue(true)); |
146 | }}); |
147 | |
148 | Classfile sut = new Classfile(loader, constantPool, 0x0, 1, 2, Collections.<Class_info>emptyList(), Collections.<Field_info>emptyList(), Collections.<Method_info>emptyList(), Collections.<Attribute_info>emptyList()); |
149 | |
150 | Field_info actualField = (Field_info) sut.locateField(TEST_FIELD_NAME); |
151 | assertThat("protected field", actualField, is(expectedField)); |
152 | } |
153 | |
154 | @Test |
155 | public void testLocateField_packageInheritedField_succeed() throws Exception { |
156 | final Class_info classInfo = context.mock(Class_info.class, "class info"); |
157 | final String superclassName = "superclass"; |
158 | final Classfile superclass = context.mock(Classfile.class, "superclass"); |
159 | final Field_info expectedField = context.mock(Field_info.class, "located field"); |
160 | |
161 | final Classfile sut = new Classfile(loader, constantPool, 0x0, 1, 2, Collections.<Class_info>emptyList(), Collections.<Field_info>emptyList(), Collections.<Method_info>emptyList(), Collections.<Attribute_info>emptyList()); |
162 | |
163 | expectClassNameLookup(2, superclassName); |
164 | |
165 | context.checking(new Expectations() {{ |
166 | one (constantPool).get(1); |
167 | will(returnValue(classInfo)); |
168 | one (classInfo).getPackageName(); |
169 | will(returnValue(TEST_PACKAGE_NAME)); |
170 | one (loader).getClassfile(superclassName); |
171 | will(returnValue(superclass)); |
172 | one (superclass).getPackageName(); |
173 | will(returnValue(TEST_PACKAGE_NAME)); |
174 | one (superclass).locateField(TEST_FIELD_NAME); |
175 | will(returnValue(expectedField)); |
176 | one (expectedField).isPublic(); |
177 | will(returnValue(false)); |
178 | one (expectedField).isProtected(); |
179 | will(returnValue(false)); |
180 | one (expectedField).isPackage(); |
181 | will(returnValue(true)); |
182 | one (expectedField).getClassfile(); |
183 | will(returnValue(sut)); |
184 | }}); |
185 | |
186 | Field_info actualField = (Field_info) sut.locateField(TEST_FIELD_NAME); |
187 | assertThat("package field", actualField, is(expectedField)); |
188 | } |
189 | |
190 | @Test |
191 | public void testLocateField_packageInheritedField_fail() throws Exception { |
192 | final Class_info classInfo = context.mock(Class_info.class, "class info"); |
193 | final String superclassName = "superclass"; |
194 | final Classfile superclass = context.mock(Classfile.class, "superclass"); |
195 | final Field_info expectedField = context.mock(Field_info.class, "located field"); |
196 | |
197 | final Classfile sut = new Classfile(loader, constantPool, 0x0, 1, 2, Collections.<Class_info>emptyList(), Collections.<Field_info>emptyList(), Collections.<Method_info>emptyList(), Collections.<Attribute_info>emptyList()); |
198 | |
199 | expectClassNameLookup(2, superclassName); |
200 | |
201 | context.checking(new Expectations() {{ |
202 | one (constantPool).get(1); |
203 | will(returnValue(classInfo)); |
204 | one (classInfo).getPackageName(); |
205 | will(returnValue(TEST_PACKAGE_NAME)); |
206 | one (loader).getClassfile(superclassName); |
207 | will(returnValue(superclass)); |
208 | one (superclass).getPackageName(); |
209 | will(returnValue("")); |
210 | one (superclass).locateField(TEST_FIELD_NAME); |
211 | will(returnValue(expectedField)); |
212 | one (expectedField).isPublic(); |
213 | will(returnValue(false)); |
214 | one (expectedField).isProtected(); |
215 | will(returnValue(false)); |
216 | one (expectedField).isPackage(); |
217 | will(returnValue(true)); |
218 | one (expectedField).getClassfile(); |
219 | will(returnValue(sut)); |
220 | }}); |
221 | |
222 | Field_info actualField = (Field_info) sut.locateField(TEST_FIELD_NAME); |
223 | assertThat("package field", actualField, is(nullValue())); |
224 | } |
225 | |
226 | @Test |
227 | public void testLocateField_privateInheritedField_fail() throws Exception { |
228 | final String superclassName = "superclass"; |
229 | final Classfile superclass = context.mock(Classfile.class, "superclass"); |
230 | final Field_info expectedField = context.mock(Field_info.class, "located field"); |
231 | |
232 | expectClassNameLookup(2, superclassName); |
233 | |
234 | context.checking(new Expectations() {{ |
235 | one (loader).getClassfile(superclassName); |
236 | will(returnValue(superclass)); |
237 | one (superclass).locateField(TEST_FIELD_NAME); |
238 | will(returnValue(expectedField)); |
239 | one (expectedField).isPublic(); |
240 | will(returnValue(false)); |
241 | one (expectedField).isProtected(); |
242 | will(returnValue(false)); |
243 | one (expectedField).isPackage(); |
244 | will(returnValue(false)); |
245 | }}); |
246 | |
247 | Classfile sut = new Classfile(loader, constantPool, 0x0, 1, 2, Collections.<Class_info>emptyList(), Collections.<Field_info>emptyList(), Collections.<Method_info>emptyList(), Collections.<Attribute_info>emptyList()); |
248 | |
249 | Field_info actualField = (Field_info) sut.locateField(TEST_FIELD_NAME); |
250 | assertThat("local field", actualField, is(nullValue())); |
251 | } |
252 | |
253 | @Test |
254 | public void testLocateMethod_localMethod_succeed() throws Exception { |
255 | final Method_info expectedMethod = context.mock(Method_info.class, "located method"); |
256 | |
257 | Collection<Method_info> methods = Collections.singletonList(expectedMethod); |
258 | |
259 | context.checking(new Expectations() {{ |
260 | one (expectedMethod).getSignature(); |
261 | will(returnValue(TEST_METHOD_SIGNATURE)); |
262 | }}); |
263 | |
264 | Classfile sut = new Classfile(loader, constantPool, 0x0, 1, 2, Collections.<Class_info>emptyList(), Collections.<Field_info>emptyList(), methods, Collections.<Attribute_info>emptyList()); |
265 | |
266 | Method_info actualMethod = (Method_info) sut.locateMethod(TEST_METHOD_SIGNATURE); |
267 | assertThat("local method", actualMethod, is(expectedMethod)); |
268 | } |
269 | |
270 | @Test |
271 | public void testLocateMethod_publicInheritedMethod_succeed() throws Exception { |
272 | final String superclassName = "superclass"; |
273 | final Classfile superclass = context.mock(Classfile.class, "superclass"); |
274 | final Method_info expectedMethod = context.mock(Method_info.class, "located method"); |
275 | |
276 | expectClassNameLookup(2, superclassName); |
277 | |
278 | context.checking(new Expectations() {{ |
279 | one (loader).getClassfile(superclassName); |
280 | will(returnValue(superclass)); |
281 | one (superclass).locateMethod(TEST_METHOD_SIGNATURE); |
282 | will(returnValue(expectedMethod)); |
283 | one (expectedMethod).isPublic(); |
284 | will(returnValue(true)); |
285 | }}); |
286 | |
287 | Classfile sut = new Classfile(loader, constantPool, 0x0, 1, 2, Collections.<Class_info>emptyList(), Collections.<Field_info>emptyList(), Collections.<Method_info>emptyList(), Collections.<Attribute_info>emptyList()); |
288 | |
289 | Method_info actualMethod = (Method_info) sut.locateMethod(TEST_METHOD_SIGNATURE); |
290 | assertThat("public method", actualMethod, is(expectedMethod)); |
291 | } |
292 | |
293 | @Test |
294 | public void testLocateMethod_protectedInheritedMethod_succeed() throws Exception { |
295 | final String superclassName = "superclass"; |
296 | final Classfile superclass = context.mock(Classfile.class, "superclass"); |
297 | final Method_info expectedMethod = context.mock(Method_info.class, "located method"); |
298 | |
299 | expectClassNameLookup(2, superclassName); |
300 | |
301 | context.checking(new Expectations() {{ |
302 | one (loader).getClassfile(superclassName); |
303 | will(returnValue(superclass)); |
304 | one (superclass).locateMethod(TEST_METHOD_SIGNATURE); |
305 | will(returnValue(expectedMethod)); |
306 | one (expectedMethod).isPublic(); |
307 | will(returnValue(false)); |
308 | one (expectedMethod).isProtected(); |
309 | will(returnValue(true)); |
310 | }}); |
311 | |
312 | Classfile sut = new Classfile(loader, constantPool, 0x0, 1, 2, Collections.<Class_info>emptyList(), Collections.<Field_info>emptyList(), Collections.<Method_info>emptyList(), Collections.<Attribute_info>emptyList()); |
313 | |
314 | Method_info actualMethod = (Method_info) sut.locateMethod(TEST_METHOD_SIGNATURE); |
315 | assertThat("protected method", actualMethod, is(expectedMethod)); |
316 | } |
317 | |
318 | @Test |
319 | public void testLocateMethod_packageInheritedMethod_succeed() throws Exception { |
320 | final Class_info classInfo = context.mock(Class_info.class, "class info"); |
321 | final String superclassName = "superclass"; |
322 | final Classfile superclass = context.mock(Classfile.class, "superclass"); |
323 | final Method_info expectedMethod = context.mock(Method_info.class, "located method"); |
324 | |
325 | final Classfile sut = new Classfile(loader, constantPool, 0x0, 1, 2, Collections.<Class_info>emptyList(), Collections.<Field_info>emptyList(), Collections.<Method_info>emptyList(), Collections.<Attribute_info>emptyList()); |
326 | |
327 | expectClassNameLookup(2, superclassName); |
328 | |
329 | context.checking(new Expectations() {{ |
330 | one (constantPool).get(1); |
331 | will(returnValue(classInfo)); |
332 | one (classInfo).getPackageName(); |
333 | will(returnValue(TEST_PACKAGE_NAME)); |
334 | one (loader).getClassfile(superclassName); |
335 | will(returnValue(superclass)); |
336 | one (superclass).getPackageName(); |
337 | will(returnValue(TEST_PACKAGE_NAME)); |
338 | one (superclass).locateMethod(TEST_METHOD_SIGNATURE); |
339 | will(returnValue(expectedMethod)); |
340 | one (expectedMethod).isPublic(); |
341 | will(returnValue(false)); |
342 | one (expectedMethod).isProtected(); |
343 | will(returnValue(false)); |
344 | one (expectedMethod).isPackage(); |
345 | will(returnValue(true)); |
346 | one (expectedMethod).getClassfile(); |
347 | will(returnValue(sut)); |
348 | }}); |
349 | |
350 | Method_info actualMethod = (Method_info) sut.locateMethod(TEST_METHOD_SIGNATURE); |
351 | assertThat("package method", actualMethod, is(expectedMethod)); |
352 | } |
353 | |
354 | @Test |
355 | public void testLocateMethod_packageInheritedMethod_fail() throws Exception { |
356 | final Class_info classInfo = context.mock(Class_info.class, "class info"); |
357 | final String superclassName = "superclass"; |
358 | final Classfile superclass = context.mock(Classfile.class, "superclass"); |
359 | final Method_info expectedMethod = context.mock(Method_info.class, "located method"); |
360 | |
361 | final Classfile sut = new Classfile(loader, constantPool, 0x0, 1, 2, Collections.<Class_info>emptyList(), Collections.<Field_info>emptyList(), Collections.<Method_info>emptyList(), Collections.<Attribute_info>emptyList()); |
362 | |
363 | expectClassNameLookup(2, superclassName); |
364 | |
365 | context.checking(new Expectations() {{ |
366 | one (constantPool).get(1); |
367 | will(returnValue(classInfo)); |
368 | one (classInfo).getPackageName(); |
369 | will(returnValue(TEST_PACKAGE_NAME)); |
370 | one (loader).getClassfile(superclassName); |
371 | will(returnValue(superclass)); |
372 | one (superclass).getPackageName(); |
373 | will(returnValue("")); |
374 | one (superclass).locateMethod(TEST_METHOD_SIGNATURE); |
375 | will(returnValue(expectedMethod)); |
376 | one (expectedMethod).isPublic(); |
377 | will(returnValue(false)); |
378 | one (expectedMethod).isProtected(); |
379 | will(returnValue(false)); |
380 | one (expectedMethod).isPackage(); |
381 | will(returnValue(true)); |
382 | one (expectedMethod).getClassfile(); |
383 | will(returnValue(sut)); |
384 | }}); |
385 | |
386 | Method_info actualMethod = (Method_info) sut.locateMethod(TEST_METHOD_SIGNATURE); |
387 | assertThat("package method", actualMethod, is(nullValue())); |
388 | } |
389 | |
390 | @Test |
391 | public void testLocateMethod_privateInheritedMethod_fail() throws Exception { |
392 | final String superclassName = "superclass"; |
393 | final Classfile superclass = context.mock(Classfile.class, "superclass"); |
394 | final Method_info expectedMethod = context.mock(Method_info.class, "located method"); |
395 | |
396 | expectClassNameLookup(2, superclassName); |
397 | |
398 | context.checking(new Expectations() {{ |
399 | one (loader).getClassfile(superclassName); |
400 | will(returnValue(superclass)); |
401 | one (superclass).locateMethod(TEST_METHOD_SIGNATURE); |
402 | will(returnValue(expectedMethod)); |
403 | one (expectedMethod).isPublic(); |
404 | will(returnValue(false)); |
405 | one (expectedMethod).isProtected(); |
406 | will(returnValue(false)); |
407 | one (expectedMethod).isPackage(); |
408 | will(returnValue(false)); |
409 | }}); |
410 | |
411 | Classfile sut = new Classfile(loader, constantPool, 0x0, 1, 2, Collections.<Class_info>emptyList(), Collections.<Field_info>emptyList(), Collections.<Method_info>emptyList(), Collections.<Attribute_info>emptyList()); |
412 | |
413 | Method_info actualMethod = (Method_info) sut.locateMethod(TEST_METHOD_SIGNATURE); |
414 | assertThat("private method", actualMethod, is(nullValue())); |
415 | } |
416 | |
417 | @Test |
418 | public void testIsInnerClass_matchingInnerClassInfo_returnsTrue() throws Exception { |
419 | final InnerClasses_attribute innerClasses_attribute = context.mock(InnerClasses_attribute.class); |
420 | final InnerClass innerClass = context.mock(InnerClass.class); |
421 | |
422 | expectClassNameLookup(1, TEST_CLASS_NAME); |
423 | |
424 | context.checking(new Expectations() {{ |
425 | one (innerClasses_attribute).getInnerClasses(); |
426 | will(returnValue(Collections.<InnerClass>singleton(innerClass))); |
427 | one (innerClass).getInnerClassInfo(); |
428 | will(returnValue(TEST_CLASS_NAME)); |
429 | }}); |
430 | |
431 | Classfile sut = new Classfile(loader, constantPool, 0x0, 1, 2, Collections.<Class_info>emptyList(), Collections.<Field_info>emptyList(), Collections.<Method_info>emptyList(), Collections.<Attribute_info>singleton(innerClasses_attribute)); |
432 | |
433 | assertThat("inner class", sut.isInnerClass(), is(true)); |
434 | } |
435 | |
436 | @Test |
437 | public void testIsInnerClass_emptyInnerClassInfo_returnsFalse() throws Exception { |
438 | final InnerClasses_attribute innerClasses_attribute = context.mock(InnerClasses_attribute.class); |
439 | final InnerClass innerClass = context.mock(InnerClass.class); |
440 | |
441 | expectClassNameLookup(1, TEST_CLASS_NAME); |
442 | |
443 | context.checking(new Expectations() {{ |
444 | one (innerClasses_attribute).getInnerClasses(); |
445 | will(returnValue(Collections.<InnerClass>singleton(innerClass))); |
446 | one (innerClass).getInnerClassInfo(); |
447 | will(returnValue("")); |
448 | }}); |
449 | |
450 | Classfile sut = new Classfile(loader, constantPool, 0x0, 1, 2, Collections.<Class_info>emptyList(), Collections.<Field_info>emptyList(), Collections.<Method_info>emptyList(), Collections.<Attribute_info>singleton(innerClasses_attribute)); |
451 | |
452 | assertThat("inner class", sut.isInnerClass(), is(false)); |
453 | } |
454 | |
455 | @Test |
456 | public void testIsInnerClass_noInnerClassInfo_returnsFalse() throws Exception { |
457 | Classfile sut = new Classfile(loader, constantPool, 0x0, 1, 2, Collections.<Class_info>emptyList(), Collections.<Field_info>emptyList(), Collections.<Method_info>emptyList(), Collections.<Attribute_info>emptyList()); |
458 | |
459 | assertThat("inner class", sut.isInnerClass(), is(false)); |
460 | } |
461 | |
462 | private void expectClassNameLookup(final int index, final String value) { |
463 | final Class_info class_info = context.mock(Class_info.class); |
464 | |
465 | context.checking(new Expectations() {{ |
466 | one (constantPool).get(index); |
467 | will(returnValue(class_info)); |
468 | one (class_info).getName(); |
469 | will(returnValue(value)); |
470 | }}); |
471 | } |
472 | } |