Skip to content

Commit d8440b7

Browse files
committed
Added more tests and remove dead code
1 parent c101b42 commit d8440b7

2 files changed

Lines changed: 287 additions & 12 deletions

File tree

plugin/src/main/java/io/jenkins/plugins/casc/BaseConfigurator.java

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -587,15 +587,12 @@ private Method resolveBestSetter(List<Method> methods, Class<?> getterRawType) {
587587
boolean currentMatch = (getterRawType != null && getterRawType.isAssignableFrom(currentType));
588588
boolean bestMatch = (getterRawType != null && getterRawType.isAssignableFrom(bestType));
589589

590-
if (currentMatch && !bestMatch) {
590+
if (currentMatch == bestMatch
591+
&& ((!currentType.isInterface() && bestType.isInterface())
592+
|| (currentType.getName().compareTo(bestType.getName()) < 0))) {
593+
591594
best = m;
592595
bestType = currentType;
593-
} else if (currentMatch == bestMatch) {
594-
if ((!currentType.isInterface() && bestType.isInterface())
595-
|| (currentType.getName().compareTo(bestType.getName()) < 0)) {
596-
best = m;
597-
bestType = currentType;
598-
}
599596
}
600597
}
601598
}
@@ -606,9 +603,6 @@ private boolean isSameType(Class<?> a, Class<?> b) {
606603
if (a == b) {
607604
return true;
608605
}
609-
if (a == null || b == null) {
610-
return false;
611-
}
612606
if (a.isPrimitive() && !b.isPrimitive()) {
613607
return isWrapper(b, a);
614608
}

plugin/src/test/java/io/jenkins/plugins/casc/BaseConfiguratorTest.java

Lines changed: 283 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
package io.jenkins.plugins.casc;
22

3+
import static org.junit.Assert.assertArrayEquals;
34
import static org.junit.Assert.assertEquals;
5+
import static org.junit.Assert.assertNotNull;
6+
import static org.junit.Assert.assertTrue;
47

58
import io.jenkins.plugins.casc.model.Mapping;
9+
import java.util.Arrays;
10+
import java.util.List;
611
import java.util.Map;
712
import java.util.Set;
813
import java.util.stream.Collectors;
@@ -20,9 +25,33 @@ public static class Vehicle {}
2025

2126
public static class Car extends Vehicle {}
2227

28+
public static class FakeSecret {}
29+
30+
public static class A_Shape {}
31+
32+
public static class B_Polygon extends A_Shape {}
33+
34+
public static class C_Square extends B_Polygon {}
35+
36+
public interface Z_Interface {}
37+
38+
public static class A_Concrete {}
39+
40+
public static class V_Class {}
41+
42+
public static class W_Class {}
43+
44+
public static class X_Class {}
45+
46+
public static class Y_Class {}
47+
48+
public static class Z_Class {}
49+
2350
@SuppressWarnings("unused")
2451
public static class DummyTarget {
2552

53+
private String[] items;
54+
2655
public String getStandard() {
2756
return null;
2857
}
@@ -56,6 +85,120 @@ public Animal getAmbiguous() {
5685
public void setAmbiguous(Dog dog) {}
5786

5887
public void setAmbiguous(Cat cat) {}
88+
89+
public void setWriteOnly(String val) {}
90+
91+
public FakeSecret getMismatchedToken() {
92+
return null;
93+
}
94+
95+
public void setMismatchedToken(String val) {}
96+
97+
public String[] getItems() {
98+
return items;
99+
}
100+
101+
public void setItems(String[] items) {
102+
this.items = items;
103+
}
104+
105+
public List<String> getArrayFallback() {
106+
return null;
107+
}
108+
109+
public void setArrayFallback(String val) {}
110+
111+
public void setArrayFallback(String[] val) {}
112+
113+
public FakeSecret getShapeSubtype() {
114+
return null;
115+
}
116+
117+
public void setShapeSubtype(A_Shape val) {}
118+
119+
public void setShapeSubtype(B_Polygon val) {}
120+
121+
public void setShapeSubtype(C_Square val) {}
122+
123+
public Object getConcreteWins() {
124+
return null;
125+
}
126+
127+
public void setConcreteWins(Z_Interface val) {}
128+
129+
public void setConcreteWins(A_Concrete val) {}
130+
131+
public Object getReverseAlphabetical() {
132+
return null;
133+
}
134+
135+
public void setReverseAlphabetical(Z_Class val) {}
136+
137+
public void setReverseAlphabetical(Y_Class val) {}
138+
139+
public void setReverseAlphabetical(X_Class val) {}
140+
141+
public void setReverseAlphabetical(W_Class val) {}
142+
143+
public void setReverseAlphabetical(V_Class val) {}
144+
145+
public Integer getPrimitiveSetter() {
146+
return null;
147+
}
148+
149+
public void setPrimitiveSetter(int val) {}
150+
151+
public int getWrapperSetter() {
152+
return 0;
153+
}
154+
155+
public void setWrapperSetter(Integer val) {}
156+
157+
public Boolean getPrimitiveBoolean() {
158+
return null;
159+
}
160+
161+
public void setPrimitiveBoolean(boolean val) {}
162+
163+
public Long getPrimitiveLong() {
164+
return null;
165+
}
166+
167+
public void setPrimitiveLong(long val) {}
168+
169+
public Double getPrimitiveDouble() {
170+
return null;
171+
}
172+
173+
public void setPrimitiveDouble(double val) {}
174+
175+
public Float getPrimitiveFloat() {
176+
return null;
177+
}
178+
179+
public void setPrimitiveFloat(float val) {}
180+
181+
public Byte getPrimitiveByte() {
182+
return null;
183+
}
184+
185+
public void setPrimitiveByte(byte val) {}
186+
187+
public Character getPrimitiveChar() {
188+
return null;
189+
}
190+
191+
public void setPrimitiveChar(char val) {}
192+
193+
public Short getPrimitiveShort() {
194+
return null;
195+
}
196+
197+
public void setPrimitiveShort(short val) {}
198+
199+
public void getVoidEdgeCase() {}
200+
201+
public void setVoidEdgeCase(String val) {}
59202
}
60203

61204
public static class DummyConfigurator extends BaseConfigurator<DummyTarget> {
@@ -70,6 +213,35 @@ protected DummyTarget instance(Mapping mapping, ConfigurationContext context) {
70213
}
71214
}
72215

216+
@SuppressWarnings("unused")
217+
public static class NoGetterTarget {
218+
public void setCompletelyMissing(String val) {}
219+
220+
public void setRequiresParam(String val) {}
221+
222+
public String getRequiresParam(String param) {
223+
return param;
224+
}
225+
226+
public void setFakeBoolean(String val) {}
227+
228+
public String isFakeBoolean() {
229+
return "I am a String, not a boolean";
230+
}
231+
}
232+
233+
public static class NoGetterConfigurator extends BaseConfigurator<NoGetterTarget> {
234+
@Override
235+
public Class<NoGetterTarget> getTarget() {
236+
return NoGetterTarget.class;
237+
}
238+
239+
@Override
240+
protected NoGetterTarget instance(Mapping mapping, ConfigurationContext context) {
241+
return new NoGetterTarget();
242+
}
243+
}
244+
73245
@Test
74246
public void testDescribeResolvesBestSetters() {
75247
DummyConfigurator configurator = new DummyConfigurator();
@@ -78,7 +250,7 @@ public void testDescribeResolvesBestSetters() {
78250
Map<String, Class<?>> resolvedAttributes =
79251
attributes.stream().collect(Collectors.toMap(Attribute::getName, attr -> (Class<?>) attr.getType()));
80252

81-
assertEquals("Should discover exactly 4 configurable properties", 4, resolvedAttributes.size());
253+
assertEquals("Should discover exactly 20 configurable properties", 20, resolvedAttributes.size());
82254

83255
assertEquals("Standard setter should resolve to String", String.class, resolvedAttributes.get("standard"));
84256

@@ -93,6 +265,115 @@ public void testDescribeResolvesBestSetters() {
93265
Cat.class,
94266
resolvedAttributes.get("ambiguous"));
95267

96-
assertEquals(Set.of("standard", "ride", "pet", "ambiguous"), resolvedAttributes.keySet());
268+
assertEquals(
269+
"Disjoint getter/setter types should fallback to the available setter parameter type",
270+
String.class,
271+
resolvedAttributes.get("mismatchedToken"));
272+
273+
assertEquals(
274+
"Array types should be resolved to their component type",
275+
String.class,
276+
resolvedAttributes.get("items"));
277+
278+
assertEquals(
279+
"When no exact match exists between getters and setters, array setters should be preferred",
280+
String.class,
281+
resolvedAttributes.get("arrayFallback"));
282+
283+
assertEquals(
284+
"When multiple setters exist in an inheritance hierarchy, the most specific subtype should win",
285+
C_Square.class,
286+
resolvedAttributes.get("shapeSubtype"));
287+
288+
assertEquals(
289+
"Concrete class should win over interface when both are candidates",
290+
A_Concrete.class,
291+
resolvedAttributes.get("concreteWins"));
292+
293+
assertEquals(
294+
"Alphabetical fallback should resolve to the alphabetically first class",
295+
V_Class.class,
296+
resolvedAttributes.get("reverseAlphabetical"));
297+
298+
assertEquals(
299+
"Should map primitive setter with wrapper getter",
300+
int.class,
301+
resolvedAttributes.get("primitiveSetter"));
302+
303+
assertEquals(
304+
"Should map wrapper setter with primitive getter",
305+
Integer.class,
306+
resolvedAttributes.get("wrapperSetter"));
307+
308+
assertEquals(boolean.class, resolvedAttributes.get("primitiveBoolean"));
309+
assertEquals(long.class, resolvedAttributes.get("primitiveLong"));
310+
assertEquals(double.class, resolvedAttributes.get("primitiveDouble"));
311+
assertEquals(float.class, resolvedAttributes.get("primitiveFloat"));
312+
assertEquals(byte.class, resolvedAttributes.get("primitiveByte"));
313+
assertEquals(char.class, resolvedAttributes.get("primitiveChar"));
314+
assertEquals(short.class, resolvedAttributes.get("primitiveShort"));
315+
assertEquals(String.class, resolvedAttributes.get("voidEdgeCase"));
316+
317+
Attribute<DummyTarget, ?> itemsAttr = attributes.stream()
318+
.filter(a -> a.getName().equals("items"))
319+
.findFirst()
320+
.orElseThrow(() -> new AssertionError("items attribute not found"));
321+
assertTrue("items attribute should be marked as multiple", itemsAttr.isMultiple());
322+
323+
assertEquals(
324+
Set.of(
325+
"standard",
326+
"ride",
327+
"pet",
328+
"ambiguous",
329+
"mismatchedToken",
330+
"items",
331+
"arrayFallback",
332+
"shapeSubtype",
333+
"concreteWins",
334+
"reverseAlphabetical",
335+
"primitiveSetter",
336+
"wrapperSetter",
337+
"primitiveBoolean",
338+
"primitiveLong",
339+
"primitiveDouble",
340+
"primitiveFloat",
341+
"primitiveByte",
342+
"primitiveChar",
343+
"primitiveShort",
344+
"voidEdgeCase"),
345+
resolvedAttributes.keySet());
346+
}
347+
348+
@Test
349+
@SuppressWarnings({"unchecked", "rawtypes"})
350+
public void testCollectionToArrayConversion() throws Exception {
351+
DummyConfigurator configurator = new DummyConfigurator();
352+
Set<Attribute<DummyTarget, ?>> attributes = configurator.describe();
353+
354+
Attribute<DummyTarget, ?> itemsAttr = attributes.stream()
355+
.filter(a -> a.getName().equals("items"))
356+
.findFirst()
357+
.orElseThrow(() -> new AssertionError("items attribute not found"));
358+
359+
DummyTarget target = new DummyTarget();
360+
361+
List<String> inputCollection = Arrays.asList("foo", "bar", "baz");
362+
363+
((Attribute) itemsAttr).setValue(target, inputCollection);
364+
365+
String[] result = target.getItems();
366+
assertNotNull("Array should have been set", result);
367+
assertEquals("Array should have the same size as the collection", 3, result.length);
368+
assertArrayEquals(new String[] {"foo", "bar", "baz"}, result);
369+
}
370+
371+
@Test
372+
public void testFindGetterReturnsNullForMissingOrInvalidGetters() {
373+
NoGetterConfigurator configurator = new NoGetterConfigurator();
374+
375+
Set<Attribute<NoGetterTarget, ?>> attributes = configurator.describe();
376+
377+
assertTrue("Properties without valid getters should yield no attributes", attributes.isEmpty());
97378
}
98379
}

0 commit comments

Comments
 (0)