Skip to content

Commit 94aba48

Browse files
committed
Unit test to check if we cover all the overrider methods
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
1 parent 8489013 commit 94aba48

File tree

2 files changed

+118
-31
lines changed

2 files changed

+118
-31
lines changed

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/loader/ConfigLoader.java

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public static ConfigLoader getDefault() {
5050
// included. Complex objects (KubernetesClient, ExecutorService, …) must be
5151
// configured programmatically and are intentionally omitted.
5252
// ---------------------------------------------------------------------------
53-
private static final List<ConfigBinding<ConfigurationServiceOverrider, ?>> OPERATOR_BINDINGS =
53+
static final List<ConfigBinding<ConfigurationServiceOverrider, ?>> OPERATOR_BINDINGS =
5454
List.of(
5555
new ConfigBinding<>(
5656
"check-crd",
@@ -106,35 +106,30 @@ public static ConfigLoader getDefault() {
106106
// The key used at runtime is built as:
107107
// CONTROLLER_KEY_PREFIX + controllerName + "." + <suffix>
108108
// ---------------------------------------------------------------------------
109-
private static final List<ConfigBinding<ControllerConfigurationOverrider<?>, ?>>
110-
CONTROLLER_BINDINGS =
111-
List.of(
112-
new ConfigBinding<>(
113-
"finalizer", String.class, ControllerConfigurationOverrider::withFinalizer),
114-
new ConfigBinding<>(
115-
"generation-aware",
116-
Boolean.class,
117-
ControllerConfigurationOverrider::withGenerationAware),
118-
new ConfigBinding<>(
119-
"label-selector",
120-
String.class,
121-
ControllerConfigurationOverrider::withLabelSelector),
122-
new ConfigBinding<>(
123-
"max-reconciliation-interval",
124-
Duration.class,
125-
ControllerConfigurationOverrider::withReconciliationMaxInterval),
126-
new ConfigBinding<>(
127-
"field-manager",
128-
String.class,
129-
ControllerConfigurationOverrider::withFieldManager),
130-
new ConfigBinding<>(
131-
"trigger-reconciler-on-all-events",
132-
Boolean.class,
133-
ControllerConfigurationOverrider::withTriggerReconcilerOnAllEvents),
134-
new ConfigBinding<>(
135-
"informer-list-limit",
136-
Long.class,
137-
ControllerConfigurationOverrider::withInformerListLimit));
109+
static final List<ConfigBinding<ControllerConfigurationOverrider<?>, ?>> CONTROLLER_BINDINGS =
110+
List.of(
111+
new ConfigBinding<>(
112+
"finalizer", String.class, ControllerConfigurationOverrider::withFinalizer),
113+
new ConfigBinding<>(
114+
"generation-aware",
115+
Boolean.class,
116+
ControllerConfigurationOverrider::withGenerationAware),
117+
new ConfigBinding<>(
118+
"label-selector", String.class, ControllerConfigurationOverrider::withLabelSelector),
119+
new ConfigBinding<>(
120+
"max-reconciliation-interval",
121+
Duration.class,
122+
ControllerConfigurationOverrider::withReconciliationMaxInterval),
123+
new ConfigBinding<>(
124+
"field-manager", String.class, ControllerConfigurationOverrider::withFieldManager),
125+
new ConfigBinding<>(
126+
"trigger-reconciler-on-all-events",
127+
Boolean.class,
128+
ControllerConfigurationOverrider::withTriggerReconcilerOnAllEvents),
129+
new ConfigBinding<>(
130+
"informer-list-limit",
131+
Long.class,
132+
ControllerConfigurationOverrider::withInformerListLimit));
138133

139134
private final ConfigProvider configProvider;
140135

operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/loader/ConfigLoaderTest.java

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,19 @@
1717

1818
import java.time.Duration;
1919
import java.util.ArrayList;
20+
import java.util.Arrays;
2021
import java.util.HashMap;
2122
import java.util.Map;
2223
import java.util.Optional;
24+
import java.util.Set;
25+
import java.util.stream.Collectors;
2326

2427
import org.junit.jupiter.api.Test;
2528

2629
import io.javaoperatorsdk.operator.api.config.BaseConfigurationService;
2730
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
31+
import io.javaoperatorsdk.operator.api.config.ConfigurationServiceOverrider;
32+
import io.javaoperatorsdk.operator.api.config.ControllerConfigurationOverrider;
2833

2934
import static org.assertj.core.api.Assertions.assertThat;
3035

@@ -200,7 +205,94 @@ public <T> Optional<T> getValue(String key, Class<T> type) {
200205
"josdk.controller.ctrl.informer-list-limit");
201206
}
202207

203-
// -- key prefix constants ---------------------------------------------------
208+
// -- binding coverage -------------------------------------------------------
209+
210+
/**
211+
* Supported scalar types that DefaultConfigProvider can parse from a string. Every binding's type
212+
* must be one of these.
213+
*/
214+
private static final Set<Class<?>> SUPPORTED_TYPES =
215+
Set.of(
216+
Boolean.class,
217+
boolean.class,
218+
Integer.class,
219+
int.class,
220+
Long.class,
221+
long.class,
222+
Double.class,
223+
double.class,
224+
Duration.class,
225+
String.class);
226+
227+
@Test
228+
void operatorBindingsCoverAllSingleScalarSettersOnConfigurationServiceOverrider() {
229+
Set<String> expectedSetters =
230+
Arrays.stream(ConfigurationServiceOverrider.class.getMethods())
231+
.filter(m -> m.getParameterCount() == 1)
232+
.filter(m -> SUPPORTED_TYPES.contains(m.getParameterTypes()[0]))
233+
.filter(m -> m.getReturnType() == ConfigurationServiceOverrider.class)
234+
.map(java.lang.reflect.Method::getName)
235+
.collect(Collectors.toSet());
236+
237+
Set<String> boundMethodNames =
238+
ConfigLoader.OPERATOR_BINDINGS.stream()
239+
.flatMap(
240+
b ->
241+
Arrays.stream(ConfigurationServiceOverrider.class.getMethods())
242+
.filter(m -> m.getParameterCount() == 1)
243+
.filter(m -> isTypeCompatible(m.getParameterTypes()[0], b.type()))
244+
.filter(m -> m.getReturnType() == ConfigurationServiceOverrider.class)
245+
.map(java.lang.reflect.Method::getName))
246+
.collect(Collectors.toSet());
247+
248+
assertThat(boundMethodNames)
249+
.as("Every scalar setter on ConfigurationServiceOverrider must be covered by a binding")
250+
.containsExactlyInAnyOrderElementsOf(expectedSetters);
251+
}
252+
253+
@Test
254+
void controllerBindingsCoverAllSingleScalarSettersOnControllerConfigurationOverrider() {
255+
Set<String> expectedSetters =
256+
Arrays.stream(ControllerConfigurationOverrider.class.getMethods())
257+
.filter(m -> m.getParameterCount() == 1)
258+
.filter(m -> SUPPORTED_TYPES.contains(m.getParameterTypes()[0]))
259+
.filter(m -> m.getReturnType() == ControllerConfigurationOverrider.class)
260+
.filter(m -> m.getAnnotation(Deprecated.class) == null)
261+
.map(java.lang.reflect.Method::getName)
262+
.collect(Collectors.toSet());
263+
264+
Set<String> boundMethodNames =
265+
ConfigLoader.CONTROLLER_BINDINGS.stream()
266+
.flatMap(
267+
b ->
268+
Arrays.stream(ControllerConfigurationOverrider.class.getMethods())
269+
.filter(m -> m.getParameterCount() == 1)
270+
.filter(m -> isTypeCompatible(m.getParameterTypes()[0], b.type()))
271+
.filter(m -> m.getReturnType() == ControllerConfigurationOverrider.class)
272+
.filter(m -> m.getAnnotation(Deprecated.class) == null)
273+
.map(java.lang.reflect.Method::getName))
274+
.collect(Collectors.toSet());
275+
276+
assertThat(boundMethodNames)
277+
.as(
278+
"Every scalar setter on ControllerConfigurationOverrider should be covered by a"
279+
+ " binding")
280+
.containsExactlyInAnyOrderElementsOf(expectedSetters);
281+
}
282+
283+
/** Returns true when the two types are the same or one is the boxed/unboxed form of the other. */
284+
private static boolean isTypeCompatible(Class<?> methodParam, Class<?> bindingType) {
285+
if (methodParam == bindingType) return true;
286+
if (methodParam == boolean.class && bindingType == Boolean.class) return true;
287+
if (methodParam == Boolean.class && bindingType == boolean.class) return true;
288+
if (methodParam == int.class && bindingType == Integer.class) return true;
289+
if (methodParam == Integer.class && bindingType == int.class) return true;
290+
if (methodParam == long.class && bindingType == Long.class) return true;
291+
if (methodParam == Long.class && bindingType == long.class) return true;
292+
if (methodParam == double.class && bindingType == Double.class) return true;
293+
if (methodParam == Double.class && bindingType == double.class) return true;
294+
return false;
295+
}
204296

205297
@Test
206298
void operatorKeyPrefixIsJosdkDot() {

0 commit comments

Comments
 (0)