summaryrefslogtreecommitdiffstats
path: root/common-parameters
diff options
context:
space:
mode:
Diffstat (limited to 'common-parameters')
-rw-r--r--common-parameters/pom.xml12
-rw-r--r--common-parameters/src/main/java/org/onap/policy/common/parameters/BeanValidator.java23
-rw-r--r--common-parameters/src/main/java/org/onap/policy/common/parameters/FieldValidator.java9
-rw-r--r--common-parameters/src/main/java/org/onap/policy/common/parameters/ItemValidator.java12
-rw-r--r--common-parameters/src/main/java/org/onap/policy/common/parameters/ValueValidator.java8
-rw-r--r--common-parameters/src/test/java/org/onap/policy/common/parameters/TestBeanValidator.java409
-rw-r--r--common-parameters/src/test/java/org/onap/policy/common/parameters/TestEntryValidator.java108
-rw-r--r--common-parameters/src/test/java/org/onap/policy/common/parameters/TestFieldValidator.java274
-rw-r--r--common-parameters/src/test/java/org/onap/policy/common/parameters/TestItemValidator.java161
-rw-r--r--common-parameters/src/test/java/org/onap/policy/common/parameters/TestValueValidator.java142
-rw-r--r--common-parameters/src/test/java/org/onap/policy/common/parameters/ValidatorUtil.java72
11 files changed, 946 insertions, 284 deletions
diff --git a/common-parameters/pom.xml b/common-parameters/pom.xml
index c0efcf70..02765df4 100644
--- a/common-parameters/pom.xml
+++ b/common-parameters/pom.xml
@@ -1,7 +1,7 @@
<!--
============LICENSE_START=======================================================
Copyright (C) 2018 Ericsson. All rights reserved.
- Modifications Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ Modifications Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved.
================================================================================
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -40,6 +40,16 @@
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
diff --git a/common-parameters/src/main/java/org/onap/policy/common/parameters/BeanValidator.java b/common-parameters/src/main/java/org/onap/policy/common/parameters/BeanValidator.java
index 3f5abccc..51b11402 100644
--- a/common-parameters/src/main/java/org/onap/policy/common/parameters/BeanValidator.java
+++ b/common-parameters/src/main/java/org/onap/policy/common/parameters/BeanValidator.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* ONAP
* ================================================================================
- * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,11 +34,14 @@ import org.onap.policy.common.parameters.annotations.NotBlank;
import org.onap.policy.common.parameters.annotations.NotNull;
import org.onap.policy.common.parameters.annotations.Pattern;
import org.onap.policy.common.parameters.annotations.Valid;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Bean validator, supporting the parameter annotations.
*/
public class BeanValidator {
+ public static final Logger logger = LoggerFactory.getLogger(BeanValidator.class);
/**
* Validates top level fields within an object. For each annotated field, it retrieves
@@ -147,18 +150,18 @@ public class BeanValidator {
*/
public boolean verRegex(BeanValidationResult result, String fieldName, Pattern annot, Object value) {
try {
- if (value instanceof String && !com.google.re2j.Pattern.matches(annot.regexp(), value.toString())) {
- ObjectValidationResult result2 = new ObjectValidationResult(fieldName, xlate(value),
- ValidationStatus.INVALID, "does not match regular expression " + annot.regexp());
- result.addResult(result2);
- return false;
+ if (value instanceof String && com.google.re2j.Pattern.matches(annot.regexp(), value.toString())) {
+ return true;
}
+
} catch (RuntimeException e) {
- // TODO log at trace level
- return true;
+ logger.warn("validation error for regular expression: {}", annot.regexp(), e);
}
- return true;
+ ObjectValidationResult result2 = new ObjectValidationResult(fieldName, xlate(value), ValidationStatus.INVALID,
+ "does not match regular expression " + annot.regexp());
+ result.addResult(result2);
+ return false;
}
/**
@@ -352,7 +355,7 @@ public class BeanValidator {
*/
public boolean verMap(BeanValidationResult result, String fieldName, EntryValidator entryValidator, Object value) {
- if (!(value instanceof Map)) {
+ if (!(value instanceof Map) || entryValidator.isEmpty()) {
return true;
}
diff --git a/common-parameters/src/main/java/org/onap/policy/common/parameters/FieldValidator.java b/common-parameters/src/main/java/org/onap/policy/common/parameters/FieldValidator.java
index e762dc0e..249185c7 100644
--- a/common-parameters/src/main/java/org/onap/policy/common/parameters/FieldValidator.java
+++ b/common-parameters/src/main/java/org/onap/policy/common/parameters/FieldValidator.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* ONAP
* ================================================================================
- * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -157,6 +157,7 @@ public class FieldValidator extends ValueValidator {
* @return the annotation, or {@code null} if neither the field nor the class has the
* desired annotation
*/
+ @Override
public <T extends Annotation> T getAnnotation(Class<T> annotClass) {
// field annotation takes precedence over class annotation
@@ -178,9 +179,9 @@ public class FieldValidator extends ValueValidator {
*/
private Method getAccessor(Class<?> clazz, String fieldName) {
String capname = StringUtils.capitalize(fieldName);
- Method accessor = getMethod(clazz, "get" + capname);
- if (accessor != null) {
- return accessor;
+ Method accessor2 = getMethod(clazz, "get" + capname);
+ if (accessor2 != null) {
+ return accessor2;
}
return getMethod(clazz, "is" + capname);
diff --git a/common-parameters/src/main/java/org/onap/policy/common/parameters/ItemValidator.java b/common-parameters/src/main/java/org/onap/policy/common/parameters/ItemValidator.java
index d0c027c1..07efebbe 100644
--- a/common-parameters/src/main/java/org/onap/policy/common/parameters/ItemValidator.java
+++ b/common-parameters/src/main/java/org/onap/policy/common/parameters/ItemValidator.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* ONAP
* ================================================================================
- * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -65,6 +65,7 @@ public class ItemValidator extends ValueValidator {
* @return the annotation, or {@code null} if the {@link #annotationContainer} does
* not contain the desired annotation
*/
+ @Override
public <T extends Annotation> T getAnnotation(Class<T> annotClass) {
try {
for (Method meth : annotationContainer.getClass().getDeclaredMethods()) {
@@ -80,7 +81,10 @@ public class ItemValidator extends ValueValidator {
return null;
}
- private <T extends Annotation> T getAnnotation2(Class<T> annotClass, Method method)
+ /**
+ * Note: this is only marked "protected" so it can be overridden for junit testing.
+ */
+ protected <T extends Annotation> T getAnnotation2(Class<T> annotClass, Method method)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class<?> ret = method.getReturnType();
@@ -101,7 +105,9 @@ public class ItemValidator extends ValueValidator {
return null;
}
- // TODO log if there's more than one item
+ if (arrobj.length > 1) {
+ throw new IllegalArgumentException("extra item annotations of type: " + annotClass.getName());
+ }
return arrobj[0];
}
diff --git a/common-parameters/src/main/java/org/onap/policy/common/parameters/ValueValidator.java b/common-parameters/src/main/java/org/onap/policy/common/parameters/ValueValidator.java
index 9095bfd0..6a641a17 100644
--- a/common-parameters/src/main/java/org/onap/policy/common/parameters/ValueValidator.java
+++ b/common-parameters/src/main/java/org/onap/policy/common/parameters/ValueValidator.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* ONAP
* ================================================================================
- * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,12 +37,6 @@ import org.onap.policy.common.parameters.annotations.NotNull;
public class ValueValidator {
/**
- * {@code True} if there is a field-level annotation, {@code false} otherwise.
- */
- @Setter(AccessLevel.PROTECTED)
- private boolean fieldIsAnnotated = false;
-
- /**
* {@code True} if the value is allowed to be {@code null}, {@code false} otherwise.
* Subclasses are expected to set this, typically based on the validation annotations
* associated with the value.
diff --git a/common-parameters/src/test/java/org/onap/policy/common/parameters/TestBeanValidator.java b/common-parameters/src/test/java/org/onap/policy/common/parameters/TestBeanValidator.java
index f1e468b0..5d539260 100644
--- a/common-parameters/src/test/java/org/onap/policy/common/parameters/TestBeanValidator.java
+++ b/common-parameters/src/test/java/org/onap/policy/common/parameters/TestBeanValidator.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* ONAP
* ================================================================================
- * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,30 +20,30 @@
package org.onap.policy.common.parameters;
-import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertTrue;
+import java.util.List;
+import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
-import lombok.AccessLevel;
import lombok.Getter;
import org.junit.Before;
import org.junit.Test;
+import org.onap.policy.common.parameters.annotations.Entries;
+import org.onap.policy.common.parameters.annotations.Items;
import org.onap.policy.common.parameters.annotations.Max;
import org.onap.policy.common.parameters.annotations.Min;
import org.onap.policy.common.parameters.annotations.NotBlank;
import org.onap.policy.common.parameters.annotations.NotNull;
+import org.onap.policy.common.parameters.annotations.Pattern;
+import org.onap.policy.common.parameters.annotations.Valid;
public class TestBeanValidator {
- private static final String GET_MSG = "\"get\"";
- private static final IllegalStateException EXPECTED_EXCEPTION = new IllegalStateException("expected exception");
private static final String TOP = "top";
private static final String STR_FIELD = "strValue";
private static final String INT_FIELD = "intValue";
private static final String NUM_FIELD = "numValue";
- private static final String BOOL_FIELD = "boolValue";
private static final String STRING_VALUE = "string value";
private static final int INT_VALUE = 20;
@@ -114,115 +114,6 @@ public class TestBeanValidator {
}
@Test
- public void testValidateField() {
- /*
- * Note: nested classes contain fields like "$this", thus the check for "$" in the
- * variable name is already covered by the other tests.
- */
-
- /*
- * Class with no annotations.
- */
- class NoAnnotations {
- @SuppressWarnings("unused")
- String strValue;
- }
-
- NoAnnotations noAnnot = new NoAnnotations();
- noAnnot.strValue = null;
- assertTrue(validator.validateTop(TOP, noAnnot).isValid());
-
- /*
- * Class containing a static field with an annotation.
- */
- AnnotFieldStatic annotFieldStatic = new AnnotFieldStatic();
- assertThatIllegalArgumentException().isThrownBy(() -> validator.validateTop(TOP, annotFieldStatic))
- .withMessageContaining(STR_FIELD).withMessageContaining("static");
-
- /*
- * Class containing a static field, with an annotation at the class level.
- */
- AnnotClassStatic annotClassStatic = new AnnotClassStatic();
- assertTrue(validator.validateTop(TOP, annotClassStatic).isValid());
-
- /*
- * Class with no getter method, with field-level annotation.
- */
- class NoGetter {
- @NotNull
- String strValue;
- }
-
- NoGetter noGetter = new NoGetter();
- assertThatIllegalArgumentException().isThrownBy(() -> validator.validateTop(TOP, noGetter))
- .withMessageContaining(STR_FIELD).withMessageContaining(GET_MSG);
-
- /*
- * Class with no getter method, with class-level annotation.
- */
- @NotNull
- class ClassNoGetter {
- @SuppressWarnings("unused")
- String strValue;
- }
-
- ClassNoGetter classNoGetter = new ClassNoGetter();
- assertTrue(validator.validateTop(TOP, classNoGetter).isValid());
-
- /*
- * Class with "blank", but no "null" check. Value is null.
- */
- class NoNullCheck {
- @NotBlank
- @Getter
- String strValue;
- }
-
- NoNullCheck noNullCheck = new NoNullCheck();
- assertTrue(validator.validateTop(TOP, noNullCheck).isValid());
-
- /*
- * Class with conflicting minimum and maximum, where the value doesn't satisfy
- * either of them. This should only generate one result, rather than one for each
- * check. Note: the "max" check occurs before the "min" check, so that's the one
- * we expect in the result.
- */
- class MinAndMax {
- @Getter
- @Min(200)
- @Max(100)
- Integer intValue;
- }
-
- MinAndMax minAndMax = new MinAndMax();
- minAndMax.intValue = 150;
- BeanValidationResult result = validator.validateTop(INT_FIELD, minAndMax);
- assertFalse(result.isValid());
- assertInvalid("testValidateField", result, INT_FIELD, "maximum");
- assertFalse(result.getResult().contains("minimum"));
- }
-
- @Test
- public void testGetValue() {
- /*
- * Class where the getter throws an exception.
- */
- class GetExcept {
- @NotNull
- String strValue;
-
- @SuppressWarnings("unused")
- public String getStrValue() {
- throw EXPECTED_EXCEPTION;
- }
- }
-
- GetExcept getExcept = new GetExcept();
- assertThatIllegalArgumentException().isThrownBy(() -> validator.validateTop(TOP, getExcept))
- .withMessageContaining(STR_FIELD).withMessageContaining("accessor threw");
- }
-
- @Test
public void testVerNotNull() {
class NotNullCheck {
@Getter
@@ -281,6 +172,58 @@ public class TestBeanValidator {
}
@Test
+ public void testVerRegex() {
+ class RegexCheck {
+ @Getter
+ @Pattern(regexp = "[a-f]*")
+ String strValue;
+ }
+
+ RegexCheck regexCheck = new RegexCheck();
+
+ // does not match
+ regexCheck.strValue = "xyz";
+ assertInvalid("testVerRegex", validator.validateTop(TOP, regexCheck), STR_FIELD,
+ "does not match regular expression [a-f]");
+
+ // matches
+ regexCheck.strValue = "abcabc";
+ assertTrue(validator.validateTop(TOP, regexCheck).isValid());
+
+ // invalid regex
+ class InvalidRegexCheck {
+ @Getter
+ @Pattern(regexp = "[a-f")
+ String strValue;
+ }
+
+ InvalidRegexCheck invalidRegexCheck = new InvalidRegexCheck();
+
+ // does not match
+ invalidRegexCheck.strValue = "abc";
+ assertInvalid("testVerRegex", validator.validateTop(TOP, invalidRegexCheck), STR_FIELD,
+ "does not match regular expression [a-f");
+
+ // matches
+ regexCheck.strValue = "abcabc";
+ assertTrue(validator.validateTop(TOP, regexCheck).isValid());
+
+ /*
+ * Class with "regex" annotation on an integer.
+ */
+ class RegexInt {
+ @Getter
+ @Pattern(regexp = "[a-f]*")
+ int intValue;
+ }
+
+ RegexInt regexInt = new RegexInt();
+ regexInt.intValue = 0;
+ assertInvalid("testVerRegex", validator.validateTop(TOP, regexInt), INT_FIELD,
+ "does not match regular expression [a-f]");
+ }
+
+ @Test
public void testVerMax() {
/*
* Field is not a number.
@@ -468,184 +411,132 @@ public class TestBeanValidator {
assertTrue(validator.validateTop(TOP, atomIntField).isValid());
}
- private <T> void assertNumeric(String testName, T object, Consumer<Integer> setter, String fieldName,
- String expectedText, int inside, int edge, int outside) {
- setter.accept(inside);
- assertTrue(validator.validateTop(TOP, object).isValid());
-
- // on the edge
- setter.accept(edge);
- assertTrue(validator.validateTop(TOP, object).isValid());
+ @Test
+ public void testVerCascade() {
+ class Item {
+ @Getter
+ @NotNull
+ Integer intValue;
+ }
- // invalid
- setter.accept(outside);
- assertInvalid("testVerNotNull", validator.validateTop(TOP, object), fieldName, expectedText);
- }
+ @Getter
+ class Container {
+ @Valid
+ Item checked;
- @Test
- public void testGetAccessor() {
- /*
- * Class with "get" method has been tested through-out this junit, so no need to
- * do more.
- */
+ Item unchecked;
- /*
- * Class with "is" method.
- */
- class IsField {
- @NotNull
- Boolean boolValue;
+ @Valid
+ List<Item> items;
- @SuppressWarnings("unused")
- public Boolean isBoolValue() {
- return boolValue;
- }
+ @Valid
+ Map<String, Item> itemMap;
}
- // ok value
- IsField isField = new IsField();
- isField.boolValue = true;
- assertTrue(validator.validateTop(TOP, isField).isValid());
+ Container cont = new Container();
+ cont.unchecked = new Item();
+ cont.items = List.of(new Item());
+ cont.itemMap = Map.of(STRING_VALUE, new Item());
- // invalid value
- isField.boolValue = null;
- assertInvalid("testGetAccessor", validator.validateTop(TOP, isField), BOOL_FIELD, "null");
- }
+ cont.checked = null;
+ assertTrue(validator.validateTop(TOP, cont).isValid());
- @Test
- public void testGetMethod() {
- /*
- * Class with some fields annotated and some not.
- */
- @Getter
- class Mixed {
- Integer intValue;
+ cont.checked = new Item();
- @NotNull
- String strValue;
- }
+ assertInvalid("testVerCascade", validator.validateTop(TOP, cont), INT_FIELD, "null");
- // invalid
- Mixed mixed = new Mixed();
- BeanValidationResult result = validator.validateTop(TOP, mixed);
- assertInvalid("testGetMethod", result, STR_FIELD, "null");
- assertFalse(result.getResult().contains(INT_FIELD));
-
- // intValue is null, but it isn't annotated so this should be valid
- mixed.strValue = STRING_VALUE;
- assertTrue(validator.validateTop(TOP, mixed).isValid());
+ cont.checked.intValue = INT_VALUE;
+ assertTrue(validator.validateTop(TOP, cont).isValid());
}
@Test
- public void testValidMethod() {
+ public void testVerCollection() {
+ @Getter
+ class Container {
+ @Items(min = @Min(5))
+ List<Integer> items;
- /*
- * Plain getter.
- */
- class PlainGetter {
- @NotNull
- @Getter
+ // not a collection - should not be checked
+ @Items(valid = {@Valid})
String strValue;
+
+ String noAnnotations;
}
- // invalid
- PlainGetter plainGetter = new PlainGetter();
- assertInvalid("testValidMethod", validator.validateTop(TOP, plainGetter), STR_FIELD, "null");
+ Container cont = new Container();
+ cont.strValue = STRING_VALUE;
+ cont.noAnnotations = STRING_VALUE;
- // valid
- plainGetter.strValue = STRING_VALUE;
- assertTrue(validator.validateTop(TOP, plainGetter).isValid());
+ // null collection - always valid
+ assertTrue(validator.validateTop(TOP, cont).isValid());
- /*
- * Static getter - should throw an exception.
- */
- StaticGetter staticGetter = new StaticGetter();
- assertThatIllegalArgumentException().isThrownBy(() -> validator.validateTop(TOP, staticGetter))
- .withMessageContaining(STR_FIELD).withMessageContaining(GET_MSG);
+ // empty collection - always valid
+ cont.items = List.of();
+ assertTrue(validator.validateTop(TOP, cont).isValid());
- /*
- * Protected getter - should throw an exception.
- */
- class ProtectedGetter {
- @NotNull
- @Getter(AccessLevel.PROTECTED)
- String strValue;
- }
+ cont.items = List.of(-10, -20);
+ assertThat(validator.validateTop(TOP, cont).getResult()).contains("\"0\"", "-10", "\"1\"", "-20", "minimum");
- ProtectedGetter protectedGetter = new ProtectedGetter();
- assertThatIllegalArgumentException().isThrownBy(() -> validator.validateTop(TOP, protectedGetter))
- .withMessageContaining(STR_FIELD).withMessageContaining(GET_MSG);
+ cont.items = List.of(10, -30);
+ assertThat(validator.validateTop(TOP, cont).getResult()).contains("\"1\"", "-30", "minimum")
+ .doesNotContain("\"0\"");
- /*
- * getter is a "void" function - should throw an exception.
- */
- class VoidGetter {
- @NotNull
+ cont.items = List.of(10, 20);
+ assertTrue(validator.validateTop(TOP, cont).isValid());
+ }
+
+ @Test
+ public void testVerMap() {
+ @Getter
+ class Container {
+ @Entries(key = @Items(), value = @Items(min = {@Min(5)}))
+ Map<String, Integer> items;
+
+ // not a map - should not be checked
+ @Entries(key = @Items(), value = @Items(min = {@Min(5)}))
String strValue;
- @SuppressWarnings("unused")
- public void getStrValue() {
- // do nothing
- }
+ String noAnnotations;
}
- VoidGetter voidGetter = new VoidGetter();
- assertThatIllegalArgumentException().isThrownBy(() -> validator.validateTop(TOP, voidGetter))
- .withMessageContaining(STR_FIELD).withMessageContaining(GET_MSG);
+ Container cont = new Container();
+ cont.strValue = STRING_VALUE;
+ cont.noAnnotations = STRING_VALUE;
- /*
- * getter takes an argument - should throw an exception.
- */
- class ArgGetter {
- @NotNull
- String strValue;
+ // null map - always valid
+ assertTrue(validator.validateTop(TOP, cont).isValid());
- @SuppressWarnings("unused")
- public String getStrValue(String echo) {
- return echo;
- }
- }
+ // empty map - always valid
+ cont.items = Map.of();
+ assertTrue(validator.validateTop(TOP, cont).isValid());
- ArgGetter argGetter = new ArgGetter();
- assertThatIllegalArgumentException().isThrownBy(() -> validator.validateTop(TOP, argGetter))
- .withMessageContaining(STR_FIELD).withMessageContaining(GET_MSG);
- }
+ cont.items = Map.of("abc", -10, "def", -20);
+ assertThat(validator.validateTop(TOP, cont).getResult()).contains("abc", "-10", "def", "-20", "minimum");
+ cont.items = Map.of("abc", 10, "def", -30);
+ assertThat(validator.validateTop(TOP, cont).getResult()).contains("def", "-30", "minimum")
+ .doesNotContain("abc");
- private void assertInvalid(String testName, BeanValidationResult result, String fieldName, String message) {
- String text = result.getResult();
- assertNotNull(testName, text);
- assertTrue(testName, text.contains(fieldName));
- assertTrue(testName, text.contains(message));
+ cont.items = Map.of("abc", 10, "def", 20);
+ assertTrue(validator.validateTop(TOP, cont).isValid());
}
- /**
- * Annotated static field.
- */
- private static class AnnotFieldStatic {
- @NotNull
- static String strValue;
- }
+ private <T> void assertNumeric(String testName, T object, Consumer<Integer> setter, String fieldName,
+ String expectedText, int inside, int edge, int outside) {
+ setter.accept(inside);
+ assertTrue(validator.validateTop(TOP, object).isValid());
- /**
- * Annotated class with a static field.
- */
- @NotNull
- private static class AnnotClassStatic {
- @SuppressWarnings("unused")
- static String strValue;
+ // on the edge
+ setter.accept(edge);
+ assertTrue(validator.validateTop(TOP, object).isValid());
+
+ // invalid
+ setter.accept(outside);
+ assertInvalid("testVerNotNull", validator.validateTop(TOP, object), fieldName, expectedText);
}
- /**
- * Class with an annotated field, but a static "getter".
- */
- private static class StaticGetter {
- @NotNull
- String strValue;
- @SuppressWarnings("unused")
- public static String getStrValue() {
- return STRING_VALUE;
- }
+ private void assertInvalid(String testName, BeanValidationResult result, String... text) {
+ assertThat(result.getResult()).describedAs(testName).contains(text);
}
}
diff --git a/common-parameters/src/test/java/org/onap/policy/common/parameters/TestEntryValidator.java b/common-parameters/src/test/java/org/onap/policy/common/parameters/TestEntryValidator.java
new file mode 100644
index 00000000..1c93d6c8
--- /dev/null
+++ b/common-parameters/src/test/java/org/onap/policy/common/parameters/TestEntryValidator.java
@@ -0,0 +1,108 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.parameters;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.common.parameters.annotations.Items;
+import org.onap.policy.common.parameters.annotations.Min;
+import org.onap.policy.common.parameters.annotations.NotBlank;
+
+public class TestEntryValidator extends ValidatorUtil {
+
+ // annotations for keys and values
+
+ @Items()
+ private int emptyAnnot;
+
+ @Items(notBlank = {@NotBlank})
+ private int keyAnnot;
+
+ @Items(min = {@Min(5)})
+ private int valueAnnot;
+
+
+ @Before
+ public void setUp() {
+ bean = new BeanValidator();
+ }
+
+ @Test
+ public void testIsEmpty() {
+ // no annotations for key or value
+ assertThat(new EntryValidator(bean, getAnnot("emptyAnnot"), getAnnot("emptyAnnot")).isEmpty()).isTrue();
+
+ // annotations for key, value, or both
+ assertThat(new EntryValidator(bean, getAnnot("keyAnnot"), getAnnot("emptyAnnot")).isEmpty()).isFalse();
+ assertThat(new EntryValidator(bean, getAnnot("emptyAnnot"), getAnnot("valueAnnot")).isEmpty()).isFalse();
+ assertThat(new EntryValidator(bean, getAnnot("keyAnnot"), getAnnot("valueAnnot")).isEmpty()).isFalse();
+ }
+
+ @Test
+ public void testValidateEntry() {
+ EntryValidator validator = new EntryValidator(bean, getAnnot("keyAnnot"), getAnnot("valueAnnot"));
+
+ // valid key & value
+ BeanValidationResult result = new BeanValidationResult(MY_NAME, this);
+ validator.validateEntry(result, makeEntry(HELLO, 10));
+ assertThat(result.getResult()).isNull();
+
+ // invalid key
+ result = new BeanValidationResult(MY_NAME, this);
+ validator.validateEntry(result, makeEntry("", 20));
+ assertThat(result.getResult()).doesNotContain("\"value\"").contains("\"key\"", "blank");
+
+ // invalid value
+ result = new BeanValidationResult(MY_NAME, this);
+ validator.validateEntry(result, makeEntry(HELLO, -10));
+ assertThat(result.getResult()).contains(HELLO, "\"value\"", "-10").doesNotContain("\"key\"");
+
+ // both invalid
+ result = new BeanValidationResult(MY_NAME, this);
+ validator.validateEntry(result, makeEntry("", -100));
+ assertThat(result.getResult()).contains("\"key\"", "blank", "\"value\"", "-100");
+ }
+
+ @Test
+ public void testGetName() {
+ EntryValidator validator = new EntryValidator(bean, getAnnot("emptyAnnot"), getAnnot("emptyAnnot"));
+ assertThat(validator.getName(makeEntry(null, 0))).isEmpty();
+ assertThat(validator.getName(makeEntry("", 0))).isEmpty();
+ assertThat(validator.getName(makeEntry(HELLO, 0))).isEqualTo(HELLO);
+ }
+
+ /**
+ * Makes a Map entry with the given key and value.
+ *
+ * @param key desired key
+ * @param value desired value
+ * @return a new Map entry
+ */
+ Map.Entry<String, Integer> makeEntry(String key, int value) {
+ HashMap<String, Integer> map = new HashMap<>();
+ map.put(key, value);
+ return map.entrySet().iterator().next();
+ }
+}
diff --git a/common-parameters/src/test/java/org/onap/policy/common/parameters/TestFieldValidator.java b/common-parameters/src/test/java/org/onap/policy/common/parameters/TestFieldValidator.java
new file mode 100644
index 00000000..e4432c8d
--- /dev/null
+++ b/common-parameters/src/test/java/org/onap/policy/common/parameters/TestFieldValidator.java
@@ -0,0 +1,274 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.parameters;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import lombok.Getter;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.common.parameters.annotations.Min;
+import org.onap.policy.common.parameters.annotations.NotNull;
+
+public class TestFieldValidator extends ValidatorUtil {
+ private static final String UNANNOTATED_FIELD = "unannotated";
+ private static final String INT_FIELD = "intValue";
+ private static final int VALID_INT = 10;
+ private static final int INVALID_INT = -10;
+
+ @Getter
+ private int unannotated;
+
+ @Min(0)
+ @Getter
+ private int intValue;
+
+ @NotNull
+ @Getter
+ private boolean boolValue;
+
+ @NotNull
+ @Getter
+ private String notNullValue;
+
+ @Min(0)
+ @Getter
+ private static int staticField;
+
+ /**
+ * Has no accessor.
+ */
+ @Min(0)
+ private int noMethod;
+
+ /**
+ * Accessor is {@link #getStaticMethod()}, which is static.
+ */
+ @Min(0)
+ private int staticMethod;
+
+ /**
+ * Accessor is {@link #getVoidMethod()}, which returns a void.
+ */
+ @Min(0)
+ private int voidMethod;
+
+ /**
+ * Accessor is {@link #getParameterizedMethod()}, which requires a parameter.
+ */
+ @Min(0)
+ private int parameterizedMethod;
+
+ /**
+ * Accessor is {@link #getExMethod()}, which throws an exception.
+ */
+ @Min(0)
+ private int exMethod;
+
+
+ @Before
+ public void setUp() {
+ bean = new BeanValidator();
+ }
+
+ @Test
+ public void testGetAnnotation() {
+ // field-level annotation
+ assertThat(new FieldValidator(bean, TestFieldValidator.class, getField(INT_FIELD)).isEmpty()).isFalse();
+
+ // class-level annotation
+ assertThat(new FieldValidator(bean, ClassAnnot.class, getField(ClassAnnot.class, "text")).isEmpty()).isFalse();
+ }
+
+ @Test
+ public void testFieldValidator() throws NoSuchFieldException, SecurityException {
+ /*
+ * Note: nested classes contain fields like "$this", thus the check for "$" in the
+ * variable name is already covered by the other tests.
+ */
+
+ /*
+ * Class with no annotations.
+ */
+ @NotNull
+ class NoAnnotations {
+ @SuppressWarnings("unused")
+ String strValue;
+ }
+
+ Field field = NoAnnotations.class.getDeclaredField("this$0");
+
+ assertThat(new FieldValidator(bean, NoAnnotations.class, field).isEmpty()).isTrue();
+
+ // unannotated
+ assertThat(new FieldValidator(bean, TestFieldValidator.class, getField("unannotated")).isEmpty()).isTrue();
+
+ // these are invalid for various reasons
+
+ Field staticField2 = getField("staticField");
+ assertThatThrownBy(() -> new FieldValidator(bean, TestFieldValidator.class, staticField2))
+ .isInstanceOf(IllegalArgumentException.class);
+
+ Field noMethodField = getField("noMethod");
+ assertThatThrownBy(() -> new FieldValidator(bean, TestFieldValidator.class, noMethodField))
+ .isInstanceOf(IllegalArgumentException.class);
+
+ // annotated
+ assertThat(new FieldValidator(bean, TestFieldValidator.class, getField(INT_FIELD)).isEmpty()).isFalse();
+ }
+
+ @Test
+ public void testFieldValidator_SetNullAllowed() {
+ // default - null is allowed
+ assertThat(new FieldValidator(bean, TestFieldValidator.class, getField(INT_FIELD)).isNullAllowed()).isTrue();
+
+ // field-level NotNull
+ assertThat(new FieldValidator(bean, TestFieldValidator.class, getField("notNullValue")).isNullAllowed())
+ .isFalse();
+
+ // class-level NotNull
+ assertThat(new FieldValidator(bean, ClassAnnot.class, getField(ClassAnnot.class, "noMethod")).isNullAllowed())
+ .isFalse();
+ }
+
+ @Test
+ public void testValidateField_testGetValue() {
+ // unannotated
+ BeanValidationResult result = new BeanValidationResult(MY_NAME, this);
+ new FieldValidator(bean, getClass(), getField(UNANNOTATED_FIELD)).validateField(result, this);
+ assertThat(result.getResult()).isNull();
+
+ // valid
+ intValue = VALID_INT;
+ result = new BeanValidationResult(MY_NAME, this);
+ new FieldValidator(bean, getClass(), getField(INT_FIELD)).validateField(result, this);
+ assertThat(result.getResult()).isNull();
+
+ // invalid
+ intValue = INVALID_INT;
+ result = new BeanValidationResult(MY_NAME, this);
+ new FieldValidator(bean, getClass(), getField(INT_FIELD)).validateField(result, this);
+ assertThat(result.getResult()).contains(INT_FIELD);
+
+ // throws an exception
+ FieldValidator validator = new FieldValidator(bean, TestFieldValidator.class, getField("exMethod"));
+ BeanValidationResult result2 = new BeanValidationResult(MY_NAME, this);
+ assertThatThrownBy(() -> validator.validateField(result2, this)).isInstanceOf(IllegalArgumentException.class)
+ .getCause().isInstanceOf(InvocationTargetException.class).getCause()
+ .hasMessage("expected exception");
+ }
+
+ @Test
+ public void testClassOnly() {
+ // class-level annotation has no bearing on a static field
+ assertThat(new FieldValidator(bean, ClassAnnot.class, getField(ClassAnnot.class, "staticValue")).isEmpty())
+ .isTrue();
+
+ // field-level annotation on a static field
+ Field staticField2 = getField("staticField");
+ assertThatThrownBy(() -> new FieldValidator(bean, TestFieldValidator.class, staticField2))
+ .isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void testGetAccessor() {
+ // uses "getXxx"
+ assertThat(new FieldValidator(bean, TestFieldValidator.class, getField(INT_FIELD)).isEmpty()).isFalse();
+
+ // uses "isXxx"
+ assertThat(new FieldValidator(bean, TestFieldValidator.class, getField("boolValue")).isEmpty()).isFalse();
+ }
+
+ @Test
+ public void testGetMethod() {
+ assertThat(new FieldValidator(bean, TestFieldValidator.class, getField(INT_FIELD)).isEmpty()).isFalse();
+
+ // these are invalid for various reasons
+
+ Field noMethodField = getField("noMethod");
+ assertThatThrownBy(() -> new FieldValidator(bean, TestFieldValidator.class, noMethodField))
+ .isInstanceOf(IllegalArgumentException.class);
+
+ Field staticMethodField = getField("staticMethod");
+ assertThatThrownBy(() -> new FieldValidator(bean, TestFieldValidator.class, staticMethodField))
+ .isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void testValidMethod() {
+ assertThat(new FieldValidator(bean, TestFieldValidator.class, getField(INT_FIELD)).isEmpty()).isFalse();
+
+ // these are invalid for various reasons
+
+ Field staticMethodField = getField("staticMethod");
+ assertThatThrownBy(() -> new FieldValidator(bean, TestFieldValidator.class, staticMethodField))
+ .isInstanceOf(IllegalArgumentException.class);
+
+ Field voidMethodField = getField("voidMethod");
+ assertThatThrownBy(() -> new FieldValidator(bean, TestFieldValidator.class, voidMethodField))
+ .isInstanceOf(IllegalArgumentException.class);
+
+ Field paramMethodField = getField("parameterizedMethod");
+ assertThatThrownBy(() -> new FieldValidator(bean, TestFieldValidator.class, paramMethodField))
+ .isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void testIsFieldAnnotated_testSetFieldAnnotated() {
+ // annotated at the field level
+ assertThat(new FieldValidator(bean, getClass(), getField(INT_FIELD)).isFieldAnnotated()).isTrue();
+
+ // unannotated
+ assertThat(new FieldValidator(bean, getClass(), getField(UNANNOTATED_FIELD)).isFieldAnnotated()).isFalse();
+ }
+
+ public static int getStaticMethod() {
+ return -1000;
+ }
+
+ public void getVoidMethod() {
+ // do nothing
+ }
+
+ public int getParameterizedMethod(boolean flag) {
+ return 0;
+ }
+
+ public int getExMethod() {
+ throw new RuntimeException("expected exception");
+ }
+
+ @NotNull
+ public static class ClassAnnot {
+ @Getter
+ private String text;
+
+ // no "get" method
+ @SuppressWarnings("unused")
+ private String noMethod;
+
+ @Getter
+ private static int staticValue;
+ }
+}
diff --git a/common-parameters/src/test/java/org/onap/policy/common/parameters/TestItemValidator.java b/common-parameters/src/test/java/org/onap/policy/common/parameters/TestItemValidator.java
new file mode 100644
index 00000000..2a0394dc
--- /dev/null
+++ b/common-parameters/src/test/java/org/onap/policy/common/parameters/TestItemValidator.java
@@ -0,0 +1,161 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.parameters;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.reflect.Method;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.common.parameters.annotations.Items;
+import org.onap.policy.common.parameters.annotations.Min;
+import org.onap.policy.common.parameters.annotations.NotBlank;
+import org.onap.policy.common.parameters.annotations.NotNull;
+
+public class TestItemValidator extends ValidatorUtil {
+
+ // annotated fields - each field must have exactly one annotation
+
+ /**
+ * This annotation does not contain a method returning an array.
+ */
+ @Min(value = 0)
+ private int notArray;
+
+ /**
+ * This annotation doesn't contain any annotations that the {@link BeanValidator}
+ * recognizes.
+ */
+ @SimpleItems(simple = {@Simple})
+ private int mismatch;
+
+ /**
+ * Annotation with no sub-annotations.
+ */
+ @Items()
+ private int noAnnotations;
+
+ /**
+ * One matching sub-annotation.
+ */
+ @Items(notNull = {@NotNull})
+ private int match;
+
+ /**
+ * Excess matching sub-annotations of a single type.
+ */
+ @Items(notNull = {@NotNull, @NotNull})
+ private int excess;
+
+ /**
+ * Multiple matching annotations.
+ */
+ @Items(notNull = {@NotNull}, notBlank = {@NotBlank})
+ private String multiMatch;
+
+
+ @Before
+ public void setUp() {
+ bean = new BeanValidator();
+ }
+
+ @Test
+ public void testGetAnnotation() {
+ // no matches
+ assertThat(new ItemValidator(bean, getAnnot("noAnnotations"), true).isEmpty()).isTrue();
+
+ // had a match
+ assertThat(new ItemValidator(bean, getAnnot("match"), true).isEmpty()).isFalse();
+
+ // with an exception
+ IllegalAccessException ex = new IllegalAccessException("expected exception");
+
+ assertThatThrownBy(() -> new ItemValidator(bean, getAnnot("match"), true) {
+ @Override
+ protected <T extends Annotation> T getAnnotation2(Class<T> annotClass, Method method)
+ throws IllegalAccessException {
+ throw ex;
+ }
+ }).hasCause(ex);
+
+ // multiple matches
+ ItemValidator validator = new ItemValidator(bean, getAnnot("multiMatch"), true);
+
+ BeanValidationResult result = new BeanValidationResult(MY_NAME, this);
+ validator.validateValue(result, MY_FIELD, HELLO);
+ assertThat(result.getResult()).isNull();
+
+ result = new BeanValidationResult(MY_NAME, this);
+ validator.validateValue(result, MY_FIELD, null);
+ assertThat(result.getResult()).isNotNull();
+
+ result = new BeanValidationResult(MY_NAME, this);
+ validator.validateValue(result, MY_FIELD, "");
+ assertThat(result.getResult()).isNotNull();
+ }
+
+ @Test
+ public void testItemValidatorBeanValidatorAnnotation() {
+ assertThat(new ItemValidator(bean, getAnnot("match")).isEmpty()).isFalse();
+ }
+
+ @Test
+ public void testItemValidatorBeanValidatorAnnotationBoolean() {
+ assertThat(new ItemValidator(bean, getAnnot("match"), true).isEmpty()).isFalse();
+
+ assertThat(new ItemValidator(bean, getAnnot("match"), false).isEmpty()).isTrue();
+ }
+
+ @Test
+ public void testGetAnnotation2() {
+ assertThat(new ItemValidator(bean, getAnnot("notArray"), true).isEmpty()).isTrue();
+ assertThat(new ItemValidator(bean, getAnnot("mismatch"), true).isEmpty()).isTrue();
+ assertThat(new ItemValidator(bean, getAnnot("noAnnotations"), true).isEmpty()).isTrue();
+
+ assertThat(new ItemValidator(bean, getAnnot("match"), true).isEmpty()).isFalse();
+
+ Annotation excess = getAnnot("excess");
+ assertThatThrownBy(() -> new ItemValidator(bean, excess, true)).isInstanceOf(IllegalArgumentException.class);
+ }
+
+ // these annotations are not recognized by the BeanValidator
+
+ @Retention(RUNTIME)
+ @Target(FIELD)
+ public @interface Simple {
+
+ }
+
+ @Retention(RUNTIME)
+ @Target(FIELD)
+ public @interface SimpleItems {
+ /**
+ * Validates that it's simple.
+ */
+ Simple[] simple() default {};
+ }
+}
diff --git a/common-parameters/src/test/java/org/onap/policy/common/parameters/TestValueValidator.java b/common-parameters/src/test/java/org/onap/policy/common/parameters/TestValueValidator.java
new file mode 100644
index 00000000..dcf08695
--- /dev/null
+++ b/common-parameters/src/test/java/org/onap/policy/common/parameters/TestValueValidator.java
@@ -0,0 +1,142 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.parameters;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.lang.annotation.Annotation;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.common.parameters.annotations.Min;
+import org.onap.policy.common.parameters.annotations.NotBlank;
+import org.onap.policy.common.parameters.annotations.NotNull;
+
+public class TestValueValidator extends ValidatorUtil {
+
+ private ValueValidator validator;
+
+ // these fields just provide place-holders for annotations
+
+ @NotNull
+ @NotBlank
+ private final int annotField = 1;
+
+
+ @Before
+ public void setUp() {
+ validator = new MyValueValidator();
+ }
+
+ @Test
+ public void testIsEmpty() {
+ assertThat(validator.isEmpty()).isTrue();
+
+ validator.addAnnotation(NotNull.class, (result2, fieldName, value) -> true);
+ assertThat(validator.isEmpty()).isFalse();
+ }
+
+ @Test
+ public void testValidateValue_NullValue() {
+ BeanValidationResult result = new BeanValidationResult(MY_NAME, this);
+
+ validator.validateValue(result, MY_FIELD, null);
+ assertThat(result.getResult()).isNull();
+
+ validator.addAnnotation(NotNull.class,
+ (result2, fieldName, value) -> result2.validateNotNull(fieldName, value));
+ validator.validateValue(result, MY_FIELD, null);
+ assertThat(result.getResult()).contains(MY_FIELD, "null");
+ }
+
+ @Test
+ public void testValidateValue_NotNullValue() {
+ BeanValidationResult result = new BeanValidationResult(MY_NAME, this);
+
+ validator.validateValue(result, MY_FIELD, HELLO);
+ assertThat(result.getResult()).isNull();
+
+ validator.addAnnotation(NotNull.class,
+ (result2, fieldName, value) -> result2.validateNotNull(fieldName, value));
+ validator.validateValue(result, MY_FIELD, HELLO);
+ assertThat(result.getResult()).isNull();
+ }
+
+ @Test
+ public void testAddAnnotationClassOfTChecker() {
+ // the field does not have this annotation
+ validator.addAnnotation(Min.class, (result2, fieldName, value) -> true);
+ assertThat(validator.isEmpty()).isTrue();
+
+ // "null" flag should stay true with this annotation
+ assertThat(validator.isNullAllowed()).isTrue();
+ validator.addAnnotation(NotBlank.class, (result2, fieldName, value) -> true);
+ assertThat(validator.isNullAllowed()).isTrue();
+
+ // "null" flag should become false with this annotation
+ assertThat(validator.isNullAllowed()).isTrue();
+ validator.addAnnotation(NotNull.class, (result2, fieldName, value) -> true);
+ assertThat(validator.isNullAllowed()).isFalse();
+ }
+
+ @Test
+ public void testAddAnnotationClassOfTCheckerWithAnnotOfT() {
+ // the field does not have this annotation
+ validator.addAnnotation(Min.class, (result2, fieldName, annot, value) -> true);
+ assertThat(validator.isEmpty()).isTrue();
+
+ // indicates the annotation value
+ AtomicBoolean wasNull = new AtomicBoolean(false);
+
+ // the field DOES have this annotation
+ validator.addAnnotation(NotNull.class, (result2, fieldName, annot, value) -> {
+ wasNull.set(annot instanceof NotNull);
+ return result2.validateNotNull(fieldName, value);
+ });
+ assertThat(validator.isEmpty()).isFalse();
+
+ // ensure that the checker is invoked
+ BeanValidationResult result = new BeanValidationResult(MY_NAME, this);
+ validator.validateValue(result, MY_FIELD, HELLO);
+ assertThat(result.getResult()).isNull();
+
+ assertThat(wasNull.get()).isTrue();
+ }
+
+ @Test
+ public void testGetAnnotation() {
+ assertThat(new ValueValidator().getAnnotation(NotNull.class)).isNull();
+ }
+
+ /**
+ * Checks for annotations on the "annotField" field.
+ */
+ private static class MyValueValidator extends ValueValidator {
+ @Override
+ public <T extends Annotation> T getAnnotation(Class<T> annotClass) {
+ try {
+ return TestValueValidator.class.getDeclaredField("annotField").getAnnotation(annotClass);
+ } catch (NoSuchFieldException | SecurityException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+}
diff --git a/common-parameters/src/test/java/org/onap/policy/common/parameters/ValidatorUtil.java b/common-parameters/src/test/java/org/onap/policy/common/parameters/ValidatorUtil.java
new file mode 100644
index 00000000..4df014f7
--- /dev/null
+++ b/common-parameters/src/test/java/org/onap/policy/common/parameters/ValidatorUtil.java
@@ -0,0 +1,72 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.parameters;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+
+/**
+ * Utilities for validator tests.
+ */
+public class ValidatorUtil {
+ protected static final String MY_NAME = "My-Name";
+ protected static final String MY_FIELD = "My-Field";
+ protected static final String HELLO = "hello";
+
+ protected BeanValidator bean;
+
+ /**
+ * Gets the single annotation for a given field.
+ *
+ * @param fieldName name of the field having the desired annotation
+ * @return the given field's annotation
+ */
+ protected Annotation getAnnot(String fieldName) {
+ return getField(fieldName).getAnnotations()[0];
+ }
+
+ /**
+ * Gets a field from this object.
+ *
+ * @param fieldName name of the field of interest
+ * @return the given field
+ */
+ protected Field getField(String fieldName) {
+ return getField(getClass(), fieldName);
+ }
+
+ /**
+ * Gets a field from a given class.
+ *
+ * @param clazz class containing the field
+ * @param fieldName name of the field of interest
+ * @return the given field
+ */
+ protected Field getField(Class<?> clazz, String fieldName) {
+ try {
+ return clazz.getDeclaredField(fieldName);
+
+ } catch (NoSuchFieldException | SecurityException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}