Skip to content

Commit f09b078

Browse files
authored
Merge pull request #500 from siom79/claude/refactor-compatibility-tests-oFcgX
Refactor: split CompatibilityChangesTest into thematic test classes
2 parents 4870f6b + bfbdfd4 commit f09b078

11 files changed

Lines changed: 3239 additions & 3068 deletions

japicmp/src/test/java/japicmp/compat/AnnotationCompatibilityTest.java

Lines changed: 381 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
package japicmp.compat;
2+
3+
import japicmp.cmp.ClassesHelper;
4+
import japicmp.cmp.JarArchiveComparatorOptions;
5+
import japicmp.model.*;
6+
import japicmp.util.*;
7+
import javassist.*;
8+
import org.junit.jupiter.api.Test;
9+
10+
import java.util.Arrays;
11+
import java.util.Collections;
12+
import java.util.List;
13+
14+
import static japicmp.util.Helper.*;
15+
import static org.hamcrest.CoreMatchers.*;
16+
import static org.hamcrest.MatcherAssert.assertThat;
17+
import static org.hamcrest.Matchers.hasSize;
18+
19+
class ClassCompatibilityTest {
20+
21+
@Test
22+
void testClassRemoved() throws Exception {
23+
JarArchiveComparatorOptions options = new JarArchiveComparatorOptions();
24+
options.setIncludeSynthetic(true);
25+
List<JApiClass> jApiClasses = ClassesHelper.compareClasses(options, new ClassesHelper.ClassesGenerator() {
26+
@Override
27+
public List<CtClass> createOldClasses(ClassPool classPool) {
28+
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").addToClassPool(classPool);
29+
return Collections.singletonList(ctClass);
30+
}
31+
32+
@Override
33+
public List<CtClass> createNewClasses(ClassPool classPool) {
34+
return Collections.emptyList();
35+
}
36+
});
37+
JApiClass jApiClass = getJApiClass(jApiClasses, "japicmp.Test");
38+
assertThat(jApiClass.getChangeStatus(), is(JApiChangeStatus.REMOVED));
39+
assertThat(jApiClass.getCompatibilityChanges(), hasItem(new JApiCompatibilityChange(JApiCompatibilityChangeType.CLASS_REMOVED)));
40+
assertThat(jApiClass.isBinaryCompatible(), is(false));
41+
}
42+
43+
@Test
44+
void testClassNowAbstract() throws Exception {
45+
JarArchiveComparatorOptions options = new JarArchiveComparatorOptions();
46+
options.setIncludeSynthetic(true);
47+
List<JApiClass> jApiClasses = ClassesHelper.compareClasses(options, new ClassesHelper.ClassesGenerator() {
48+
@Override
49+
public List<CtClass> createOldClasses(ClassPool classPool) {
50+
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").addToClassPool(classPool);
51+
return Collections.singletonList(ctClass);
52+
}
53+
54+
@Override
55+
public List<CtClass> createNewClasses(ClassPool classPool) {
56+
CtClass ctClass = CtClassBuilder.create().abstractModifier().name("japicmp.Test").addToClassPool(classPool);
57+
return Collections.singletonList(ctClass);
58+
}
59+
});
60+
JApiClass jApiClass = getJApiClass(jApiClasses, "japicmp.Test");
61+
assertThat(jApiClass.getChangeStatus(), is(JApiChangeStatus.MODIFIED));
62+
assertThat(jApiClass.getCompatibilityChanges(), hasItem(new JApiCompatibilityChange(JApiCompatibilityChangeType.CLASS_NOW_ABSTRACT)));
63+
assertThat(jApiClass.isBinaryCompatible(), is(false));
64+
}
65+
66+
@Test
67+
void testClassNowFinal() throws Exception {
68+
JarArchiveComparatorOptions options = new JarArchiveComparatorOptions();
69+
options.setIncludeSynthetic(true);
70+
List<JApiClass> jApiClasses = ClassesHelper.compareClasses(options, new ClassesHelper.ClassesGenerator() {
71+
@Override
72+
public List<CtClass> createOldClasses(ClassPool classPool) {
73+
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").addToClassPool(classPool);
74+
return Collections.singletonList(ctClass);
75+
}
76+
77+
@Override
78+
public List<CtClass> createNewClasses(ClassPool classPool) {
79+
CtClass ctClass = CtClassBuilder.create().finalModifier().name("japicmp.Test").addToClassPool(classPool);
80+
return Collections.singletonList(ctClass);
81+
}
82+
});
83+
JApiClass jApiClass = getJApiClass(jApiClasses, "japicmp.Test");
84+
assertThat(jApiClass.getChangeStatus(), is(JApiChangeStatus.MODIFIED));
85+
assertThat(jApiClass.getCompatibilityChanges(), hasItem(new JApiCompatibilityChange(JApiCompatibilityChangeType.CLASS_NOW_NOT_EXTENDABLE)));
86+
assertThat(jApiClass.isBinaryCompatible(), is(false));
87+
assertThat(jApiClass.isSourceCompatible(), is(false));
88+
}
89+
90+
@Test
91+
void testClassNowOnlyPrivateConstructors() throws Exception {
92+
JarArchiveComparatorOptions options = new JarArchiveComparatorOptions();
93+
options.setIncludeSynthetic(true);
94+
List<JApiClass> jApiClasses = ClassesHelper.compareClasses(options, new ClassesHelper.ClassesGenerator() {
95+
@Override
96+
public List<CtClass> createOldClasses(ClassPool classPool) throws CannotCompileException {
97+
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").addToClassPool(classPool);
98+
CtConstructorBuilder.create().publicAccess().parameter(CtClass.intType).addToClass(ctClass);
99+
return Collections.singletonList(ctClass);
100+
}
101+
102+
@Override
103+
public List<CtClass> createNewClasses(ClassPool classPool) throws CannotCompileException {
104+
CtClass ctClass = CtClassBuilder.create().finalModifier().name("japicmp.Test").addToClassPool(classPool);
105+
CtConstructorBuilder.create().privateAccess().parameter(CtClass.intType).addToClass(ctClass);
106+
return Collections.singletonList(ctClass);
107+
}
108+
});
109+
JApiClass jApiClass = getJApiClass(jApiClasses, "japicmp.Test");
110+
assertThat(jApiClass.getChangeStatus(), is(JApiChangeStatus.MODIFIED));
111+
assertThat(jApiClass.getCompatibilityChanges(), hasItem(new JApiCompatibilityChange(JApiCompatibilityChangeType.CLASS_NOW_NOT_EXTENDABLE)));
112+
assertThat(jApiClass.isBinaryCompatible(), is(false));
113+
assertThat(jApiClass.isSourceCompatible(), is(false));
114+
}
115+
116+
@Test
117+
void testClassNoLongerPublic() throws Exception {
118+
JarArchiveComparatorOptions options = new JarArchiveComparatorOptions();
119+
options.setIncludeSynthetic(true);
120+
List<JApiClass> jApiClasses = ClassesHelper.compareClasses(options, new ClassesHelper.ClassesGenerator() {
121+
@Override
122+
public List<CtClass> createOldClasses(ClassPool classPool) {
123+
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").addToClassPool(classPool);
124+
return Collections.singletonList(ctClass);
125+
}
126+
127+
@Override
128+
public List<CtClass> createNewClasses(ClassPool classPool) {
129+
CtClass ctClass = CtClassBuilder.create().notPublicModifier().name("japicmp.Test").addToClassPool(classPool);
130+
return Collections.singletonList(ctClass);
131+
}
132+
});
133+
JApiClass jApiClass = getJApiClass(jApiClasses, "japicmp.Test");
134+
assertThat(jApiClass.getChangeStatus(), is(JApiChangeStatus.MODIFIED));
135+
assertThat(jApiClass.getCompatibilityChanges(), hasItem(new JApiCompatibilityChange(JApiCompatibilityChangeType.CLASS_NO_LONGER_PUBLIC)));
136+
assertThat(jApiClass.isBinaryCompatible(), is(false));
137+
}
138+
139+
@Test
140+
void testClassTypeChanged() throws Exception {
141+
JarArchiveComparatorOptions options = new JarArchiveComparatorOptions();
142+
options.setIncludeSynthetic(true);
143+
List<JApiClass> jApiClasses = ClassesHelper.compareClasses(options, new ClassesHelper.ClassesGenerator() {
144+
@Override
145+
public List<CtClass> createOldClasses(ClassPool classPool) {
146+
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").addToClassPool(classPool);
147+
return Collections.singletonList(ctClass);
148+
}
149+
150+
@Override
151+
public List<CtClass> createNewClasses(ClassPool classPool) throws Exception {
152+
CtClass ctClass = CtInterfaceBuilder.create().name("japicmp.Test").addToClassPool(classPool);
153+
return Collections.singletonList(ctClass);
154+
}
155+
});
156+
JApiClass jApiClass = getJApiClass(jApiClasses, "japicmp.Test");
157+
assertThat(jApiClass.getChangeStatus(), is(JApiChangeStatus.MODIFIED));
158+
assertThat(jApiClass.getCompatibilityChanges(), hasItem(new JApiCompatibilityChange(JApiCompatibilityChangeType.CLASS_TYPE_CHANGED)));
159+
assertThat(jApiClass.isBinaryCompatible(), is(false));
160+
}
161+
162+
@Test
163+
void testClassLessAccessiblePublicToPrivate() throws Exception {
164+
JarArchiveComparatorOptions options = new JarArchiveComparatorOptions();
165+
options.setIncludeSynthetic(true);
166+
List<JApiClass> jApiClasses = ClassesHelper.compareClasses(options, new ClassesHelper.ClassesGenerator() {
167+
@Override
168+
public List<CtClass> createOldClasses(ClassPool classPool) {
169+
CtClass ctClass = CtClassBuilder.create().name("japicmp.Test").addToClassPool(classPool);
170+
return Collections.singletonList(ctClass);
171+
}
172+
173+
@Override
174+
public List<CtClass> createNewClasses(ClassPool classPool) {
175+
CtClass ctClass = CtClassBuilder.create().notPublicModifier().name("japicmp.Test").addToClassPool(classPool);
176+
return Collections.singletonList(ctClass);
177+
}
178+
});
179+
JApiClass jApiClass = getJApiClass(jApiClasses, "japicmp.Test");
180+
assertThat(jApiClass.getChangeStatus(), is(JApiChangeStatus.MODIFIED));
181+
assertThat(jApiClass.isBinaryCompatible(), is(false));
182+
assertThat(jApiClass.getCompatibilityChanges(), hasItem(new JApiCompatibilityChange(JApiCompatibilityChangeType.CLASS_LESS_ACCESSIBLE)));
183+
}
184+
185+
@Test
186+
void testClassNotExtendablePrivateConstructorsProtectedMethodToPackagePrivate() throws Exception {
187+
JarArchiveComparatorOptions options = new JarArchiveComparatorOptions();
188+
List<JApiClass> jApiClasses = ClassesHelper.compareClasses(options, new ClassesHelper.ClassesGenerator() {
189+
@Override
190+
public List<CtClass> createOldClasses(ClassPool classPool) throws Exception {
191+
CtClass aClass = CtClassBuilder.create().name("japicmp.Test").addToClassPool(classPool);
192+
CtConstructorBuilder.create().privateAccess().addToClass(aClass);
193+
CtFieldBuilder.create().protectedAccess().name("field").addToClass(aClass);
194+
CtMethodBuilder.create().protectedAccess().name("method").addToClass(aClass);
195+
return Collections.singletonList(aClass);
196+
}
197+
198+
@Override
199+
public List<CtClass> createNewClasses(ClassPool classPool) throws Exception {
200+
CtClass aClass = CtClassBuilder.create().name("japicmp.Test").addToClassPool(classPool);
201+
CtConstructorBuilder.create().privateAccess().addToClass(aClass);
202+
CtFieldBuilder.create().packageProtectedAccess().name("field").addToClass(aClass);
203+
CtMethodBuilder.create().packageProtectedAccess().name("method").addToClass(aClass);
204+
return Collections.singletonList(aClass);
205+
}
206+
});
207+
JApiClass jApiClass = getJApiClass(jApiClasses, "japicmp.Test");
208+
JApiField jApiField = getJApiField(jApiClass.getFields(), "field");
209+
assertThat(jApiField.getCompatibilityChanges(), hasSize(0));
210+
JApiMethod jApiMethod = getJApiMethod(jApiClass.getMethods(), "method");
211+
assertThat(jApiMethod.getCompatibilityChanges(), hasSize(0));
212+
}
213+
214+
@Test
215+
void testClassNotExtendableFinalProtectedMethodToPackagePrivate() throws Exception {
216+
JarArchiveComparatorOptions options = new JarArchiveComparatorOptions();
217+
List<JApiClass> jApiClasses = ClassesHelper.compareClasses(options, new ClassesHelper.ClassesGenerator() {
218+
@Override
219+
public List<CtClass> createOldClasses(ClassPool classPool) throws Exception {
220+
CtClass aClass = CtClassBuilder.create().finalModifier().name("japicmp.Test").addToClassPool(classPool);
221+
CtFieldBuilder.create().protectedAccess().name("field").addToClass(aClass);
222+
CtMethodBuilder.create().protectedAccess().name("method").addToClass(aClass);
223+
return Collections.singletonList(aClass);
224+
}
225+
226+
@Override
227+
public List<CtClass> createNewClasses(ClassPool classPool) throws Exception {
228+
CtClass aClass = CtClassBuilder.create().finalModifier().name("japicmp.Test").addToClassPool(classPool);
229+
CtFieldBuilder.create().packageProtectedAccess().name("field").addToClass(aClass);
230+
CtMethodBuilder.create().packageProtectedAccess().name("method").addToClass(aClass);
231+
return Collections.singletonList(aClass);
232+
}
233+
});
234+
JApiClass jApiClass = getJApiClass(jApiClasses, "japicmp.Test");
235+
JApiField jApiField = getJApiField(jApiClass.getFields(), "field");
236+
assertThat(jApiField.getCompatibilityChanges(), hasSize(0));
237+
JApiMethod jApiMethod = getJApiMethod(jApiClass.getMethods(), "method");
238+
assertThat(jApiMethod.getCompatibilityChanges(), hasSize(0));
239+
}
240+
241+
@Test
242+
void testNewClassExtendsExistingAbstractClass() throws Exception {
243+
JarArchiveComparatorOptions options = new JarArchiveComparatorOptions();
244+
List<JApiClass> jApiClasses = ClassesHelper.compareClasses(options, new ClassesHelper.ClassesGenerator() {
245+
@Override
246+
public List<CtClass> createOldClasses(ClassPool classPool) {
247+
CtClass c1 = CtClassBuilder.create().name("CA").abstractModifier().addToClassPool(classPool);
248+
return Collections.singletonList(c1);
249+
}
250+
251+
@Override
252+
public List<CtClass> createNewClasses(ClassPool classPool) {
253+
CtClass c1 = CtClassBuilder.create().name("CA").abstractModifier().addToClassPool(classPool);
254+
CtClass c = CtClassBuilder.create().name("C").withSuperclass(c1).addToClassPool(classPool);
255+
return Arrays.asList(c1, c);
256+
}
257+
});
258+
JApiClass jApiClass = getJApiClass(jApiClasses, "C");
259+
assertThat(jApiClass.getChangeStatus(), is(JApiChangeStatus.NEW));
260+
assertThat(jApiClass.isBinaryCompatible(), is(true));
261+
assertThat(jApiClass.isSourceCompatible(), is(true));
262+
assertThat(jApiClass.getCompatibilityChanges(), not(hasItem(new JApiCompatibilityChange(JApiCompatibilityChangeType.METHOD_ABSTRACT_ADDED_IN_IMPLEMENTED_INTERFACE))));
263+
}
264+
265+
@Test
266+
void testClassBecomesInterfacesAndInterfaceClass() throws Exception {
267+
JarArchiveComparatorOptions jarArchiveComparatorOptions = new JarArchiveComparatorOptions();
268+
jarArchiveComparatorOptions.setAccessModifier(AccessModifier.PRIVATE);
269+
List<JApiClass> jApiClasses = ClassesHelper.compareClasses(jarArchiveComparatorOptions, new ClassesHelper.ClassesGenerator() {
270+
@Override
271+
public List<CtClass> createOldClasses(ClassPool classPool) throws Exception {
272+
CtClass superInterface = CtInterfaceBuilder.create().name("I").addToClassPool(classPool);
273+
CtMethodBuilder.create().returnType(CtClass.voidType).publicAccess().abstractMethod().name("method").addToClass(superInterface);
274+
CtClass subClass = CtClassBuilder.create().name("C").implementsInterface(superInterface).addToClassPool(classPool);
275+
return Arrays.asList(superInterface, subClass);
276+
}
277+
278+
@Override
279+
public List<CtClass> createNewClasses(ClassPool classPool) throws Exception {
280+
CtClass superInterface = CtInterfaceBuilder.create().name("C").addToClassPool(classPool);
281+
CtMethodBuilder.create().returnType(CtClass.voidType).publicAccess().abstractMethod().name("method").addToClass(superInterface);
282+
CtClass subClass = CtClassBuilder.create().name("I").implementsInterface(superInterface).addToClassPool(classPool);
283+
return Arrays.asList(superInterface, subClass);
284+
}
285+
});
286+
JApiClass jApiClass = getJApiClass(jApiClasses, "I");
287+
assertThat(jApiClass.getCompatibilityChanges(), hasItem(new JApiCompatibilityChange(JApiCompatibilityChangeType.CLASS_TYPE_CHANGED)));
288+
JApiMethod jApiMethod = getJApiMethod(jApiClass.getMethods(), "method");
289+
assertThat(jApiMethod.getCompatibilityChanges().size(), is(0));
290+
jApiClass = getJApiClass(jApiClasses, "C");
291+
assertThat(jApiClass.getCompatibilityChanges(), hasItem(new JApiCompatibilityChange(JApiCompatibilityChangeType.CLASS_TYPE_CHANGED)));
292+
}
293+
}

0 commit comments

Comments
 (0)