Skip to content

Commit

Permalink
fixes tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Gunda Abhishek committed Dec 11, 2024
1 parent 33b3517 commit f40f681
Show file tree
Hide file tree
Showing 14 changed files with 511 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,16 @@
import com.google.common.collect.Sets;
import com.grookage.leia.common.violation.LeiaSchemaViolation;
import com.grookage.leia.common.violation.ViolationContext;
import com.grookage.leia.models.attributes.ArrayAttribute;
import com.grookage.leia.models.attributes.MapAttribute;
import com.grookage.leia.models.attributes.ObjectAttribute;
import com.grookage.leia.models.attributes.SchemaAttribute;
import com.grookage.leia.models.attributes.SchemaAttributeHandler;
import com.grookage.leia.models.attributes.*;
import com.grookage.leia.models.schema.SchemaDetails;
import com.grookage.leia.models.schema.SchemaValidationType;
import com.grookage.leia.models.schema.SchemaValidationVisitor;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ClassUtils;

import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.lang.reflect.*;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

Expand All @@ -48,7 +38,7 @@ public class SchemaValidationUtils {
static Function<Class<?>, Function<SchemaAttribute, Boolean>> assignableCheckFunction =
klass -> attribute -> ClassUtils.isAssignable(klass, attribute.getType().getAssignableClass());

private static final String TYPE_VIOLATION = "Incompatible Type, expected: %s, provided: %s";
private static final String TYPE_MISMATCH_MESSAGE = "Type mismatch, expected: %s, provided: %s";

public List<LeiaSchemaViolation> valid(final SchemaDetails schemaDetails,
final Class<?> klass) {
Expand All @@ -61,7 +51,7 @@ public List<LeiaSchemaViolation> valid(final SchemaValidationType validationType
final ViolationContext context) {
context.pushClass(klass);
final var fields = FieldUtils.getAllFields(klass);
validSchema(validationType, attributes, fields, klass, context);
validSchema(validationType, attributes, fields, context);
attributes.forEach(each -> validAttribute(each, fields, validationType, context));
context.popClass();
return context.getViolations();
Expand All @@ -70,7 +60,6 @@ public List<LeiaSchemaViolation> valid(final SchemaValidationType validationType
private void validSchema(final SchemaValidationType validationType,
final Set<SchemaAttribute> attributes,
final List<Field> fields,
final Class<?> klass,
final ViolationContext context) {
final var fieldNames = fields.stream()
.map(Field::getName)
Expand Down Expand Up @@ -136,18 +125,20 @@ private void valid(final SchemaValidationType validationType,
final Class<?> klass,
final ViolationContext context) {
if (!isMatchingType(klass, schemaAttribute)) {
context.addViolation(String.format(TYPE_VIOLATION, schemaAttribute.getType(), klass.getSimpleName()),
context.addViolation(String.format(TYPE_MISMATCH_MESSAGE, schemaAttribute.getType(), klass.getSimpleName()),
schemaAttribute.getName());
return;
}

schemaAttribute.accept(new SchemaAttributeHandler<Void>(a -> null) {
@Override
public Void accept(ArrayAttribute attribute) {
if (klass.isArray()) {
valid(validationType, attribute.getElementAttribute(), klass.getComponentType(), context);
return null;
} else if (!Objects.isNull(attribute.getElementAttribute())) {
if (Objects.nonNull(attribute.getElementAttribute())) {
if (klass.isArray()) {
valid(validationType, attribute.getElementAttribute(), klass.getComponentType(), context);
return null;
}
// Provided List, Set expected List<?>, Set<?>
context.addViolation(String.format("Missing Type arguments, expected ParameterizedType:%s",
attribute.getElementAttribute().getType()), attribute.getName());
}
Expand All @@ -156,7 +147,8 @@ public Void accept(ArrayAttribute attribute) {

@Override
public Void accept(MapAttribute attribute) {
if (!Objects.isNull(attribute.getKeyAttribute()) || !Objects.isNull(attribute.getValueAttribute())) {
if (Objects.nonNull(attribute.getKeyAttribute()) || Objects.nonNull(attribute.getValueAttribute())) {
// Provided Map, expected Map<?,?>
context.addViolation(String.format("Missing Type Arguments, expected parameterized Types key:%s value:%s",
attribute.getKeyAttribute().getType(), attribute.getValueAttribute().getType()), attribute.getName());
}
Expand All @@ -165,7 +157,9 @@ public Void accept(MapAttribute attribute) {

@Override
public Void accept(ObjectAttribute attribute) {
valid(validationType, attribute.getNestedAttributes(), klass, context);
if (Objects.nonNull(attribute.getNestedAttributes())) {
valid(validationType, attribute.getNestedAttributes(), klass, context);
}
return null;
}
});
Expand All @@ -189,7 +183,7 @@ private void valid(final SchemaValidationType validationType,
valid(validationType, mapAttribute.getKeyAttribute(), typeArguments[0], context);
valid(validationType, mapAttribute.getValueAttribute(), typeArguments[1], context);
} else {
context.addViolation(String.format(TYPE_VIOLATION, attribute.getType(), parameterizedType), attribute.getName());
context.addViolation(String.format(TYPE_MISMATCH_MESSAGE, attribute.getType(), parameterizedType), attribute.getName());
}
}

Expand All @@ -201,7 +195,7 @@ private void valid(final SchemaValidationType validationType,
valid(validationType, arrayAttribute.getElementAttribute(), arrayType.getGenericComponentType(), context);
return;
}
context.addViolation(String.format(TYPE_VIOLATION, attribute.getType(), arrayType), attribute.getName());
context.addViolation(String.format(TYPE_MISMATCH_MESSAGE, attribute.getType(), arrayType), attribute.getName());
}

private boolean isMatchingType(final Class<?> klass,
Expand All @@ -214,7 +208,7 @@ public Boolean accept(ArrayAttribute attribute) {

@Override
public Boolean accept(ObjectAttribute attribute) {
if (klass.equals(Object.class) && !Objects.isNull(attribute.getNestedAttributes())) {
if (klass.equals(Object.class) && Objects.nonNull(attribute.getNestedAttributes())) {
return false;
}
return true;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
package com.grookage.leia.common.violation;

public interface LeiaSchemaViolation {

/**
* @return Error message for the violation
*/
String message();

/**
* @return Relative path of the field being validated from the {@code rootKlass}
*/
String fieldPath();

/**
* @return Class of the field being validated
*/
Class<?> rootKlass();
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.grookage.leia.common.violation;

import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
Expand Down Expand Up @@ -31,8 +32,10 @@ public Class<?> rootKlass() {
}

public String toString() {
return Joiner.on(":")
.skipNulls()
.join(rootKlass, fieldPath, message);
if (Strings.isNullOrEmpty(fieldPath)) {
return String.format("[LeiaSchemaViolation] %s, message = %s", rootKlass, message);
}
return String.format("[LeiaSchemaViolation] %s, fieldPath = %s, message = %s", rootKlass,
fieldPath, message);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.grookage.leia.common.utils;

import com.grookage.leia.common.exception.ValidationErrorCode;
import com.grookage.leia.common.stubs.NestedStub;
import com.grookage.leia.common.stubs.PIIData;
import com.grookage.leia.common.violation.ViolationContext;
import com.grookage.leia.models.ResourceHelper;
import com.grookage.leia.models.attributes.ArrayAttribute;
Expand Down Expand Up @@ -108,14 +110,14 @@ void testParametrizedArray() {
@Test
void testRawArray() {
final var arrayAttribute = new ArrayAttribute("arrayAttribute", true, null, null);
// Assertions.assertTrue(SchemaValidationUtils.valid(SchemaValidationType.MATCHING,
// Set.of(arrayAttribute), RawSetTestClass.class, new ViolationContext()).isEmpty());
Assertions.assertTrue(SchemaValidationUtils.valid(SchemaValidationType.MATCHING,
Set.of(arrayAttribute), RawSetTestClass.class, new ViolationContext()).isEmpty());
Assertions.assertTrue(SchemaValidationUtils.valid(SchemaValidationType.MATCHING,
Set.of(arrayAttribute), SetTestClass.class, new ViolationContext()).isEmpty());
// Assertions.assertTrue(SchemaValidationUtils.valid(SchemaValidationType.MATCHING,
// Set.of(arrayAttribute), ListTestClass.class, new ViolationContext()).isEmpty());
// Assertions.assertTrue(SchemaValidationUtils.valid(SchemaValidationType.MATCHING,
// Set.of(arrayAttribute), ArrayTestClass.class, new ViolationContext()).isEmpty());
Assertions.assertTrue(SchemaValidationUtils.valid(SchemaValidationType.MATCHING,
Set.of(arrayAttribute), ListTestClass.class, new ViolationContext()).isEmpty());
Assertions.assertTrue(SchemaValidationUtils.valid(SchemaValidationType.MATCHING,
Set.of(arrayAttribute), ArrayTestClass.class, new ViolationContext()).isEmpty());
}

@Test
Expand Down Expand Up @@ -161,6 +163,23 @@ void testGenericArrayType() {
GenericArrayTestClass.class, new ViolationContext()).isEmpty());
}

@SneakyThrows
@Test
void testInvalidNestedStubSchema() {
final var schemaDetails = ResourceHelper.getResource("invalidNestedStubSchema.json", SchemaDetails.class);
final var violations = SchemaValidationUtils.valid(schemaDetails, NestedStub.class);
Assertions.assertFalse(violations.isEmpty());
Assertions.assertEquals(4, violations.size());
final var nestedStubViolations = violations.stream()
.filter(leiaSchemaViolation -> leiaSchemaViolation.rootKlass().equals(NestedStub.class))
.toList();
Assertions.assertEquals(3, nestedStubViolations.size());
final var piiDataViolations = violations.stream()
.filter(leiaSchemaViolation -> leiaSchemaViolation.rootKlass().equals(PIIData.class))
.toList();
Assertions.assertEquals(1, piiDataViolations.size());
}

enum TestEnum {
TEST_ENUM
}
Expand Down
92 changes: 92 additions & 0 deletions leia-common/src/test/resources/invalidNestedStubSchema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
{
"namespace": "testNamespace",
"schemaName": "NestedStub",
"version": "V1234",
"schemaState": "CREATED",
"schemaType": "JSON",
"validationType": "STRICT",
"schemaMeta": {
"createdBy": "testUser"
},
"attributes": [
{
"type": "INTEGER",
"name": "phoneNumber",
"optional": false,
"qualifiers": [
{
"type": "PII"
}
]
},
{
"type": "OBJECT",
"name": "piiData",
"optional": false,
"qualifiers": [
{
"type": "ENCRYPTED"
},
{
"type": "PII"
}
],
"nestedAttributes": [
{
"type": "STRING",
"name": "accountNumber",
"optional": false,
"qualifiers": [
{
"type": "ENCRYPTED"
}
]
}
]
},
{
"type": "LONG",
"name": "id",
"optional": false,
"qualifiers": []
},
{
"type": "ENUM",
"name": "enumClass",
"optional": false,
"qualifiers": [],
"values": [
"ONE",
"TWO"
]
},
{
"type": "OBJECT",
"name": "recordStub",
"optional": false,
"qualifiers": [
{
"type": "ENCRYPTED"
}
],
"nestedAttributes": [
{
"type": "INTEGER",
"name": "id",
"optional": true,
"qualifiers": []
},
{
"type": "STRING",
"name": "name",
"optional": false,
"qualifiers": [
{
"type": "PII"
}
]
}
]
}
]
}
11 changes: 11 additions & 0 deletions leia-schema-validator/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@
<artifactId>commons-lang3</artifactId>
<version>${lang3.version}</version>
</dependency>
<dependency>
<groupId>com.grookage.leia</groupId>
<artifactId>leia-models</artifactId>
<type>test-jar</type>
<exclusions>
<exclusion>
<artifactId>*</artifactId>
<groupId>*</groupId>
</exclusion>
</exclusions>
</dependency>

</dependencies>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ private List<LeiaSchemaViolation> validate(final SchemaKey schemaKey, Class<?> k
final var details = supplier.get().stream()
.filter(each -> each.match(schemaKey)).findFirst().orElse(null);
if (null == details) {
throw SchemaValidationException.error(ValidationErrorCode.NO_SCHEMA_FOUND);
throw SchemaValidationException.error(ValidationErrorCode.NO_SCHEMA_FOUND,
String.format("No schema found with key: %s", schemaKey.getReferenceId()));
}
return SchemaValidationUtils.valid(details, klass);
}
Expand Down Expand Up @@ -85,7 +86,10 @@ public void start() {
});
if (!violations.isEmpty()) {
log.error("Found invalid schemas. Please fix the following schemas to start the bundle {}", violations);
throw SchemaValidationException.error(ValidationErrorCode.INVALID_SCHEMAS);
throw SchemaValidationException.builder()
.errorCode(ValidationErrorCode.INVALID_SCHEMAS)
.context(Map.of("schemaViolations", violations))
.build();
}
}

Expand Down
Loading

0 comments on commit f40f681

Please sign in to comment.