pvillard31 commented on code in PR #11290:
URL: https://github.com/apache/nifi/pull/11290#discussion_r3539321855


##########
nifi-extension-bundles/nifi-registry-bundle/nifi-registry-service/src/test/java/org/apache/nifi/schemaregistry/services/TestAvroSchemaRegistry.java:
##########
@@ -17,93 +17,186 @@
 package org.apache.nifi.schemaregistry.services;
 
 import org.apache.nifi.components.PropertyDescriptor;
-import org.apache.nifi.components.PropertyValue;
-import org.apache.nifi.components.ValidationContext;
-import org.apache.nifi.components.ValidationResult;
-import org.apache.nifi.controller.ConfigurationContext;
+import org.apache.nifi.expression.ExpressionLanguageScope;
+import org.apache.nifi.processor.util.StandardValidators;
 import org.apache.nifi.schema.access.SchemaNotFoundException;
 import org.apache.nifi.serialization.record.RecordSchema;
 import org.apache.nifi.serialization.record.SchemaIdentifier;
+import org.apache.nifi.util.MockPropertyConfiguration;
+import org.apache.nifi.util.NoOpProcessor;
+import org.apache.nifi.util.PropertyMigrationResult;
+import org.apache.nifi.util.TestRunner;
+import org.apache.nifi.util.TestRunners;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.EnumSource;
+import org.junit.jupiter.params.provider.MethodSource;
 
-import java.util.Collection;
-import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
+import java.util.stream.Stream;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
 public class TestAvroSchemaRegistry {
-
-    @Test
-    public void validateSchemaRegistrationFromrDynamicProperties() throws 
Exception {
-        String schemaName = "fooSchema";
-
-        PropertyDescriptor fooSchema = new PropertyDescriptor.Builder()
-            .name(schemaName)
+    private static final String SCHEMA_NAME = "fooSchema";
+    private static final PropertyDescriptor 
SUPPORTED_DYNAMIC_PROPERTY_DESCRIPTOR = new PropertyDescriptor.Builder()
+            .name(SCHEMA_NAME)
+            .required(false)
+            .addValidator(StandardValidators.NON_BLANK_VALIDATOR)
             .dynamic(true)
-            .build();
-        String fooSchemaText = "{\"namespace\": \"example.avro\", " + 
"\"type\": \"record\", " + "\"name\": \"User\", "
-            + "\"fields\": [ " + "{\"name\": \"name\", \"type\": [\"string\", 
\"null\"]}, "
-            + "{\"name\": \"favorite_number\",  \"type\": [\"int\", 
\"null\"]}, "
-            + "{\"name\": \"foo\",  \"type\": [\"int\", \"null\"]}, "
-            + "{\"name\": \"favorite_color\", \"type\": [\"string\", 
\"null\"]} " + "]" + "}";
-        PropertyDescriptor barSchema = new PropertyDescriptor.Builder()
-            .name("barSchema")
-            .dynamic(false)
+            .expressionLanguageSupported(ExpressionLanguageScope.NONE)
             .build();
 
-        AvroSchemaRegistry delegate = new AvroSchemaRegistry();
-        delegate.onPropertyModified(fooSchema, null, fooSchemaText);
-        delegate.onPropertyModified(barSchema, null, "");
+    private static final String NON_PERIOD_NAMESPACE_SEPARATOR = """
+                                {"namespace": "example-avro", "type": 
"record", "name": "User",
+                                "fields": [ {"name": "name", "type": 
["string", "null"]},
+                                {"name": "favorite_number",  "type": ["int", 
"null"]},
+                                {"name": "foo",  "type": ["int", "null"]},
+                                {"name": "favorite_color", "type": ["string", 
"null"]} ]}""";
 
-        SchemaIdentifier schemaIdentifier = 
SchemaIdentifier.builder().name(schemaName).build();
-        RecordSchema locatedSchema = delegate.retrieveSchema(schemaIdentifier);
-        assertEquals(fooSchemaText, locatedSchema.getSchemaText().get());
-        assertThrows(SchemaNotFoundException.class, () -> 
delegate.retrieveSchema(SchemaIdentifier.builder().name("barSchema").build()));
+    private static final String ILLEGAL_CHARACTER_IN_RECORD_NAME = """
+                                {"namespace": "example.avro", "type": 
"record", "name": "$User",
+                                "fields": [ {"name": "name", "type": 
["string", "null"]},
+                                {"name": "favorite_number",  "type": ["int", 
"null"]},
+                                {"name": "foo",  "type": ["int", "null"]},
+                                {"name": "favorite_color", "type": ["string", 
"null"]} ]}""";
+
+    private static final String ILLEGAL_CHARACTER_IN_FIELD_NAME = """
+                                {"namespace": "example.avro", "type": 
"record", "name": "User",
+                                "fields": [ {"name": "@name", "type": 
["string", "null"]},
+                                {"name": "favorite_number",  "type": ["int", 
"null"]},
+                                {"name": "foo",  "type": ["int", "null"]},
+                                {"name": "favorite_color", "type": ["string", 
"null"]} ]}""";
+
+    private static final String NON_MATCHING_DEFAULT_TYPE = """
+                                {"namespace": "example.avro", "type": 
"record", "name": "User",
+                                "fields": [ {"name": "name", "type": 
["string", "null"]},
+                                {"name": "favorite_number",  "type": ["int", 
"null"]},
+                                {"name": "foo",  "type": "int", "default": 
"NAN"},
+                                {"name": "favorite_color", "type": ["string", 
"null"]} ]}""";
+
+    private static final String NON_MATCHING_UNION_DEFAULT_TYPE = """
+                                {"namespace": "example.avro", "type": 
"record", "name": "User",
+                                "fields": [ {"name": "name", "type": 
["string", "null"]},
+                                {"name": "favorite_number",  "type": ["int", 
"null"]},
+                                {"name": "foo",  "type": ["int", "null"], 
"default": "NAN"},
+                                {"name": "favorite_color", "type": ["string", 
"null"]} ]}""";
+
+    private TestRunner runner;
+    private AvroSchemaRegistry avroSchemaRegistry;
+
+    @BeforeEach
+    void setup() throws Exception {
+        runner = TestRunners.newTestRunner(NoOpProcessor.class);
+        avroSchemaRegistry = new AvroSchemaRegistry();
+        runner.addControllerService("avroSchemaRegistry", avroSchemaRegistry);
     }
 
     @Test
-    public void 
validateStrictAndNonStrictSchemaRegistrationFromDynamicProperties() {
+    public void testRetrievalOfNonExistentSchema() {
+        runner.assertValid(avroSchemaRegistry);
+        runner.enableControllerService(avroSchemaRegistry);
+        final SchemaIdentifier nonExistentSchemaIdentifier = 
SchemaIdentifier.builder().name("barSchema").build();
+
+        assertThrows(SchemaNotFoundException.class, () -> 
avroSchemaRegistry.retrieveSchema(nonExistentSchemaIdentifier));
+    }
+
+    @Test
+    public void validateSchemaRegistration() throws Exception {
         String schemaName = "fooSchema";
-        ConfigurationContext configContext = mock(ConfigurationContext.class);
-        Map<PropertyDescriptor, String> properties = new HashMap<>();
-        PropertyDescriptor fooSchema = new PropertyDescriptor.Builder()
-                .name(schemaName)
-                .dynamic(true)
-                .build();
-        // NOTE: name of record and name of first field are not 
Avro-compliant, verified below
-        String fooSchemaText = "{\"namespace\": \"example.avro\", " + 
"\"type\": \"record\", " + "\"name\": \"$User\", "
-                + "\"fields\": [ " + "{\"name\": \"@name\", \"type\": 
[\"string\", \"null\"]}, "
-                + "{\"name\": \"favorite_number\",  \"type\": [\"int\", 
\"null\"]}, "
-                + "{\"name\": \"foo\",  \"type\": [\"int\", \"null\"]}, "
-                + "{\"name\": \"favorite_color\", \"type\": [\"string\", 
\"null\"]} " + "]" + "}";
-        PropertyDescriptor barSchema = new PropertyDescriptor.Builder()
-                .name("barSchema")
-                .dynamic(false)
-                .build();
-        properties.put(fooSchema, fooSchemaText);
-        properties.put(barSchema, "");
-        AvroSchemaRegistry delegate = new AvroSchemaRegistry();
-        delegate.getSupportedPropertyDescriptors().forEach(prop -> 
properties.put(prop, prop.getDisplayName()));
-        when(configContext.getProperties()).thenReturn(properties);
-
-        ValidationContext validationContext = mock(ValidationContext.class);
-        when(validationContext.getProperties()).thenReturn(properties);
-        PropertyValue propertyValue = mock(PropertyValue.class);
-        
when(validationContext.getProperty(AvroSchemaRegistry.VALIDATE_FIELD_NAMES)).thenReturn(propertyValue);
-
-        // Strict parsing
-        when(propertyValue.asBoolean()).thenReturn(true);
-        Collection<ValidationResult> results = 
delegate.customValidate(validationContext);
-        assertTrue(results.stream().anyMatch(result -> !result.isValid()));
-
-        // Non-strict parsing
-        when(propertyValue.asBoolean()).thenReturn(false);
-        results = delegate.customValidate(validationContext);
-        results.forEach(result -> assertTrue(result.isValid()));
+        String fooSchemaText = """
+                {"namespace": "example.avro", "type": "record", "name": "User",
+                "fields": [ {"name": "name", "type": ["string", "null"]},
+                {"name": "favorite_number",  "type": ["int", "null"]},
+                {"name": "foo",  "type": ["int", "null"]},
+                {"name": "favorite_color", "type": ["string", "null"]} ]}""";
+
+        runner.setProperty(avroSchemaRegistry, 
SUPPORTED_DYNAMIC_PROPERTY_DESCRIPTOR, fooSchemaText);
+        runner.assertValid(avroSchemaRegistry);
+        runner.enableControllerService(avroSchemaRegistry);
+
+        final SchemaIdentifier schemaIdentifier = 
SchemaIdentifier.builder().name(schemaName).build();
+        final RecordSchema locatedSchema = 
avroSchemaRegistry.retrieveSchema(schemaIdentifier);
+        assertTrue(locatedSchema.getSchemaText().isPresent());
+        assertEquals(fooSchemaText, locatedSchema.getSchemaText().get());
+    }
+
+    @ParameterizedTest
+    @MethodSource("invalidSchemas")
+    public void testWhereSchemasValidated(String schema) {
+        runner.setProperty(avroSchemaRegistry, 
SUPPORTED_DYNAMIC_PROPERTY_DESCRIPTOR, schema);
+        runner.setProperty(avroSchemaRegistry, 
AvroSchemaRegistry.VALIDATION_STRATEGY, ValidationStrategy.VALIDATE.getValue());
+
+        runner.assertNotValid(avroSchemaRegistry);
+    }
+
+    @ParameterizedTest
+    @MethodSource("invalidSchemas")
+    public void testWhereSchemasNotValidated(String schema) {
+        runner.setProperty(avroSchemaRegistry, 
SUPPORTED_DYNAMIC_PROPERTY_DESCRIPTOR, schema);
+        runner.setProperty(avroSchemaRegistry, 
AvroSchemaRegistry.VALIDATION_STRATEGY, ValidationStrategy.NONE.getValue());
+
+        runner.assertValid(avroSchemaRegistry);
+    }
+
+    @ParameterizedTest
+    @EnumSource(ValidationStrategy.class)
+    public void 
testDuplicateFieldsInvalidRegardlessOfValidation(ValidationStrategy 
validationStrategy) {
+        final String schema = """
+                {"namespace": "example.avro", "type": "record", "name": "User",
+                "fields": [ {"name": "name", "type": ["string", "null"]},
+                {"name": "favorite_number",  "type": ["int", "null"]},
+                {"name": "foo",  "type": ["int", "null"]},
+                {"name": "foo",  "type": ["int", "null"]},
+                {"name": "favorite_color", "type": ["string", "null"]} ]}""";
+
+        runner.setProperty(avroSchemaRegistry, 
SUPPORTED_DYNAMIC_PROPERTY_DESCRIPTOR, schema);
+        runner.setProperty(avroSchemaRegistry, 
AvroSchemaRegistry.VALIDATION_STRATEGY, validationStrategy.getValue());
+
+        runner.assertNotValid(avroSchemaRegistry);
+    }
+
+    @ParameterizedTest
+    @MethodSource("migrationConfigurations")
+    void testMigrateProperties(MockPropertyConfiguration configuration) {
+        final Set<String> expectedRemoved = new 
HashSet<>(AvroSchemaRegistry.OBSOLETE_VALIDATE_FIELD_NAMES);
+        final Set<String> expectedUpdated = 
Set.of(AvroSchemaRegistry.VALIDATION_STRATEGY.getName());
+
+        final AvroSchemaRegistry service = new AvroSchemaRegistry();
+        service.migrateProperties(configuration);
+
+        final PropertyMigrationResult result = 
configuration.toPropertyMigrationResult();
+        final Set<String> propertiesRemoved = result.getPropertiesRemoved();
+        assertEquals(expectedRemoved, propertiesRemoved);
+        assertEquals(expectedUpdated, result.getPropertiesUpdated());

Review Comment:
   Should this test also assert the migrated value of Validation Strategy, so 
the true to VALIDATE and false to NONE mapping is verified and the test fails 
if that mapping ever breaks?



##########
nifi-extension-bundles/nifi-registry-bundle/nifi-registry-service/src/test/java/org/apache/nifi/schemaregistry/services/TestAvroSchemaRegistry.java:
##########
@@ -17,93 +17,186 @@
 package org.apache.nifi.schemaregistry.services;
 
 import org.apache.nifi.components.PropertyDescriptor;
-import org.apache.nifi.components.PropertyValue;
-import org.apache.nifi.components.ValidationContext;
-import org.apache.nifi.components.ValidationResult;
-import org.apache.nifi.controller.ConfigurationContext;
+import org.apache.nifi.expression.ExpressionLanguageScope;
+import org.apache.nifi.processor.util.StandardValidators;
 import org.apache.nifi.schema.access.SchemaNotFoundException;
 import org.apache.nifi.serialization.record.RecordSchema;
 import org.apache.nifi.serialization.record.SchemaIdentifier;
+import org.apache.nifi.util.MockPropertyConfiguration;
+import org.apache.nifi.util.NoOpProcessor;
+import org.apache.nifi.util.PropertyMigrationResult;
+import org.apache.nifi.util.TestRunner;
+import org.apache.nifi.util.TestRunners;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.EnumSource;
+import org.junit.jupiter.params.provider.MethodSource;
 
-import java.util.Collection;
-import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
+import java.util.stream.Stream;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
 public class TestAvroSchemaRegistry {
-
-    @Test
-    public void validateSchemaRegistrationFromrDynamicProperties() throws 
Exception {
-        String schemaName = "fooSchema";
-
-        PropertyDescriptor fooSchema = new PropertyDescriptor.Builder()
-            .name(schemaName)
+    private static final String SCHEMA_NAME = "fooSchema";
+    private static final PropertyDescriptor 
SUPPORTED_DYNAMIC_PROPERTY_DESCRIPTOR = new PropertyDescriptor.Builder()
+            .name(SCHEMA_NAME)
+            .required(false)
+            .addValidator(StandardValidators.NON_BLANK_VALIDATOR)
             .dynamic(true)
-            .build();
-        String fooSchemaText = "{\"namespace\": \"example.avro\", " + 
"\"type\": \"record\", " + "\"name\": \"User\", "
-            + "\"fields\": [ " + "{\"name\": \"name\", \"type\": [\"string\", 
\"null\"]}, "
-            + "{\"name\": \"favorite_number\",  \"type\": [\"int\", 
\"null\"]}, "
-            + "{\"name\": \"foo\",  \"type\": [\"int\", \"null\"]}, "
-            + "{\"name\": \"favorite_color\", \"type\": [\"string\", 
\"null\"]} " + "]" + "}";
-        PropertyDescriptor barSchema = new PropertyDescriptor.Builder()
-            .name("barSchema")
-            .dynamic(false)
+            .expressionLanguageSupported(ExpressionLanguageScope.NONE)
             .build();
 
-        AvroSchemaRegistry delegate = new AvroSchemaRegistry();
-        delegate.onPropertyModified(fooSchema, null, fooSchemaText);
-        delegate.onPropertyModified(barSchema, null, "");
+    private static final String NON_PERIOD_NAMESPACE_SEPARATOR = """
+                                {"namespace": "example-avro", "type": 
"record", "name": "User",
+                                "fields": [ {"name": "name", "type": 
["string", "null"]},
+                                {"name": "favorite_number",  "type": ["int", 
"null"]},
+                                {"name": "foo",  "type": ["int", "null"]},
+                                {"name": "favorite_color", "type": ["string", 
"null"]} ]}""";
 
-        SchemaIdentifier schemaIdentifier = 
SchemaIdentifier.builder().name(schemaName).build();
-        RecordSchema locatedSchema = delegate.retrieveSchema(schemaIdentifier);
-        assertEquals(fooSchemaText, locatedSchema.getSchemaText().get());
-        assertThrows(SchemaNotFoundException.class, () -> 
delegate.retrieveSchema(SchemaIdentifier.builder().name("barSchema").build()));
+    private static final String ILLEGAL_CHARACTER_IN_RECORD_NAME = """
+                                {"namespace": "example.avro", "type": 
"record", "name": "$User",
+                                "fields": [ {"name": "name", "type": 
["string", "null"]},
+                                {"name": "favorite_number",  "type": ["int", 
"null"]},
+                                {"name": "foo",  "type": ["int", "null"]},
+                                {"name": "favorite_color", "type": ["string", 
"null"]} ]}""";
+
+    private static final String ILLEGAL_CHARACTER_IN_FIELD_NAME = """
+                                {"namespace": "example.avro", "type": 
"record", "name": "User",
+                                "fields": [ {"name": "@name", "type": 
["string", "null"]},
+                                {"name": "favorite_number",  "type": ["int", 
"null"]},
+                                {"name": "foo",  "type": ["int", "null"]},
+                                {"name": "favorite_color", "type": ["string", 
"null"]} ]}""";
+
+    private static final String NON_MATCHING_DEFAULT_TYPE = """
+                                {"namespace": "example.avro", "type": 
"record", "name": "User",
+                                "fields": [ {"name": "name", "type": 
["string", "null"]},
+                                {"name": "favorite_number",  "type": ["int", 
"null"]},
+                                {"name": "foo",  "type": "int", "default": 
"NAN"},
+                                {"name": "favorite_color", "type": ["string", 
"null"]} ]}""";
+
+    private static final String NON_MATCHING_UNION_DEFAULT_TYPE = """
+                                {"namespace": "example.avro", "type": 
"record", "name": "User",
+                                "fields": [ {"name": "name", "type": 
["string", "null"]},
+                                {"name": "favorite_number",  "type": ["int", 
"null"]},
+                                {"name": "foo",  "type": ["int", "null"], 
"default": "NAN"},
+                                {"name": "favorite_color", "type": ["string", 
"null"]} ]}""";
+
+    private TestRunner runner;
+    private AvroSchemaRegistry avroSchemaRegistry;
+
+    @BeforeEach
+    void setup() throws Exception {
+        runner = TestRunners.newTestRunner(NoOpProcessor.class);
+        avroSchemaRegistry = new AvroSchemaRegistry();
+        runner.addControllerService("avroSchemaRegistry", avroSchemaRegistry);
     }
 
     @Test
-    public void 
validateStrictAndNonStrictSchemaRegistrationFromDynamicProperties() {
+    public void testRetrievalOfNonExistentSchema() {
+        runner.assertValid(avroSchemaRegistry);
+        runner.enableControllerService(avroSchemaRegistry);
+        final SchemaIdentifier nonExistentSchemaIdentifier = 
SchemaIdentifier.builder().name("barSchema").build();
+
+        assertThrows(SchemaNotFoundException.class, () -> 
avroSchemaRegistry.retrieveSchema(nonExistentSchemaIdentifier));
+    }
+
+    @Test
+    public void validateSchemaRegistration() throws Exception {
         String schemaName = "fooSchema";
-        ConfigurationContext configContext = mock(ConfigurationContext.class);
-        Map<PropertyDescriptor, String> properties = new HashMap<>();
-        PropertyDescriptor fooSchema = new PropertyDescriptor.Builder()
-                .name(schemaName)
-                .dynamic(true)
-                .build();
-        // NOTE: name of record and name of first field are not 
Avro-compliant, verified below
-        String fooSchemaText = "{\"namespace\": \"example.avro\", " + 
"\"type\": \"record\", " + "\"name\": \"$User\", "
-                + "\"fields\": [ " + "{\"name\": \"@name\", \"type\": 
[\"string\", \"null\"]}, "
-                + "{\"name\": \"favorite_number\",  \"type\": [\"int\", 
\"null\"]}, "
-                + "{\"name\": \"foo\",  \"type\": [\"int\", \"null\"]}, "
-                + "{\"name\": \"favorite_color\", \"type\": [\"string\", 
\"null\"]} " + "]" + "}";
-        PropertyDescriptor barSchema = new PropertyDescriptor.Builder()
-                .name("barSchema")
-                .dynamic(false)
-                .build();
-        properties.put(fooSchema, fooSchemaText);
-        properties.put(barSchema, "");
-        AvroSchemaRegistry delegate = new AvroSchemaRegistry();
-        delegate.getSupportedPropertyDescriptors().forEach(prop -> 
properties.put(prop, prop.getDisplayName()));
-        when(configContext.getProperties()).thenReturn(properties);
-
-        ValidationContext validationContext = mock(ValidationContext.class);
-        when(validationContext.getProperties()).thenReturn(properties);
-        PropertyValue propertyValue = mock(PropertyValue.class);
-        
when(validationContext.getProperty(AvroSchemaRegistry.VALIDATE_FIELD_NAMES)).thenReturn(propertyValue);
-
-        // Strict parsing
-        when(propertyValue.asBoolean()).thenReturn(true);
-        Collection<ValidationResult> results = 
delegate.customValidate(validationContext);
-        assertTrue(results.stream().anyMatch(result -> !result.isValid()));
-
-        // Non-strict parsing
-        when(propertyValue.asBoolean()).thenReturn(false);
-        results = delegate.customValidate(validationContext);
-        results.forEach(result -> assertTrue(result.isValid()));
+        String fooSchemaText = """
+                {"namespace": "example.avro", "type": "record", "name": "User",
+                "fields": [ {"name": "name", "type": ["string", "null"]},
+                {"name": "favorite_number",  "type": ["int", "null"]},
+                {"name": "foo",  "type": ["int", "null"]},
+                {"name": "favorite_color", "type": ["string", "null"]} ]}""";
+
+        runner.setProperty(avroSchemaRegistry, 
SUPPORTED_DYNAMIC_PROPERTY_DESCRIPTOR, fooSchemaText);
+        runner.assertValid(avroSchemaRegistry);
+        runner.enableControllerService(avroSchemaRegistry);
+
+        final SchemaIdentifier schemaIdentifier = 
SchemaIdentifier.builder().name(schemaName).build();
+        final RecordSchema locatedSchema = 
avroSchemaRegistry.retrieveSchema(schemaIdentifier);
+        assertTrue(locatedSchema.getSchemaText().isPresent());
+        assertEquals(fooSchemaText, locatedSchema.getSchemaText().get());
+    }
+
+    @ParameterizedTest
+    @MethodSource("invalidSchemas")
+    public void testWhereSchemasValidated(String schema) {
+        runner.setProperty(avroSchemaRegistry, 
SUPPORTED_DYNAMIC_PROPERTY_DESCRIPTOR, schema);
+        runner.setProperty(avroSchemaRegistry, 
AvroSchemaRegistry.VALIDATION_STRATEGY, ValidationStrategy.VALIDATE.getValue());
+
+        runner.assertNotValid(avroSchemaRegistry);
+    }
+
+    @ParameterizedTest
+    @MethodSource("invalidSchemas")
+    public void testWhereSchemasNotValidated(String schema) {
+        runner.setProperty(avroSchemaRegistry, 
SUPPORTED_DYNAMIC_PROPERTY_DESCRIPTOR, schema);
+        runner.setProperty(avroSchemaRegistry, 
AvroSchemaRegistry.VALIDATION_STRATEGY, ValidationStrategy.NONE.getValue());
+
+        runner.assertValid(avroSchemaRegistry);
+    }
+
+    @ParameterizedTest
+    @EnumSource(ValidationStrategy.class)
+    public void 
testDuplicateFieldsInvalidRegardlessOfValidation(ValidationStrategy 
validationStrategy) {
+        final String schema = """
+                {"namespace": "example.avro", "type": "record", "name": "User",
+                "fields": [ {"name": "name", "type": ["string", "null"]},
+                {"name": "favorite_number",  "type": ["int", "null"]},
+                {"name": "foo",  "type": ["int", "null"]},
+                {"name": "foo",  "type": ["int", "null"]},
+                {"name": "favorite_color", "type": ["string", "null"]} ]}""";
+
+        runner.setProperty(avroSchemaRegistry, 
SUPPORTED_DYNAMIC_PROPERTY_DESCRIPTOR, schema);
+        runner.setProperty(avroSchemaRegistry, 
AvroSchemaRegistry.VALIDATION_STRATEGY, validationStrategy.getValue());
+
+        runner.assertNotValid(avroSchemaRegistry);
+    }
+
+    @ParameterizedTest
+    @MethodSource("migrationConfigurations")
+    void testMigrateProperties(MockPropertyConfiguration configuration) {
+        final Set<String> expectedRemoved = new 
HashSet<>(AvroSchemaRegistry.OBSOLETE_VALIDATE_FIELD_NAMES);
+        final Set<String> expectedUpdated = 
Set.of(AvroSchemaRegistry.VALIDATION_STRATEGY.getName());
+
+        final AvroSchemaRegistry service = new AvroSchemaRegistry();
+        service.migrateProperties(configuration);
+
+        final PropertyMigrationResult result = 
configuration.toPropertyMigrationResult();
+        final Set<String> propertiesRemoved = result.getPropertiesRemoved();
+        assertEquals(expectedRemoved, propertiesRemoved);

Review Comment:
   This expects both obsolete names in the removed set, but production 
StandardPropertyConfiguration.removeProperty records nothing for an absent 
property while the mock records it unconditionally. Should the test assert only 
the obsolete name that was actually present, so it matches production behavior?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to