diff --git a/modules/client-handler/src/integrationTest/java/org/apache/ignite/client/handler/ItClientHandlerTest.java b/modules/client-handler/src/integrationTest/java/org/apache/ignite/client/handler/ItClientHandlerTest.java index 943ceb20877f..1d8a197991c6 100644 --- a/modules/client-handler/src/integrationTest/java/org/apache/ignite/client/handler/ItClientHandlerTest.java +++ b/modules/client-handler/src/integrationTest/java/org/apache/ignite/client/handler/ItClientHandlerTest.java @@ -19,6 +19,7 @@ import static org.apache.ignite.client.handler.ItClientHandlerTestUtils.MAGIC; import static org.apache.ignite.configuration.annotation.ConfigurationType.DISTRIBUTED; +import static org.apache.ignite.internal.security.authentication.SecurityConfigurationModule.DEFAULT_PROVIDER_NAME; import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully; import static org.apache.ignite.lang.ErrorGroups.Authentication.INVALID_CREDENTIALS_ERR; import static org.apache.ignite.lang.ErrorGroups.Authentication.UNSUPPORTED_AUTHENTICATION_TYPE_ERR; @@ -592,7 +593,7 @@ private static void writeAndFlushLoop(Socket socket) throws Exception { private void setupAuthentication(String username, String password) { securityConfiguration.change(change -> { change.changeEnabled(true); - change.changeAuthentication().changeProviders().create("basic", authenticationProviderChange -> { + change.changeAuthentication().changeProviders().update(DEFAULT_PROVIDER_NAME, authenticationProviderChange -> { authenticationProviderChange.convert(BasicAuthenticationProviderChange.class) .changeUsers(users -> users.create(username, user -> user.changePassword(password))); }); diff --git a/modules/client/src/test/java/org/apache/ignite/client/ClientAuthenticationTest.java b/modules/client/src/test/java/org/apache/ignite/client/ClientAuthenticationTest.java index cca0f44ae488..96704bffb467 100644 --- a/modules/client/src/test/java/org/apache/ignite/client/ClientAuthenticationTest.java +++ b/modules/client/src/test/java/org/apache/ignite/client/ClientAuthenticationTest.java @@ -18,14 +18,17 @@ package org.apache.ignite.client; import static org.apache.ignite.configuration.annotation.ConfigurationType.DISTRIBUTED; +import static org.apache.ignite.internal.security.authentication.SecurityConfigurationModule.DEFAULT_PASSWORD; +import static org.apache.ignite.internal.security.authentication.SecurityConfigurationModule.DEFAULT_USERNAME; +import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully; import static org.apache.ignite.internal.util.IgniteUtils.closeAll; +import static org.hamcrest.MatcherAssert.assertThat; import java.util.UUID; import org.apache.ignite.client.fakes.FakeIgnite; import org.apache.ignite.internal.configuration.ClusterConfiguration; import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension; import org.apache.ignite.internal.configuration.testframework.InjectConfiguration; -import org.apache.ignite.internal.security.authentication.basic.BasicAuthenticationProviderChange; import org.apache.ignite.internal.security.configuration.SecurityConfiguration; import org.apache.ignite.internal.security.configuration.SecurityExtensionConfiguration; import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest; @@ -85,9 +88,9 @@ public void testAuthnOnServerBadAuthnOnClient() { @Test public void testAuthnOnClientAuthnOnServer() { - server = startServer(false); + server = startServer(true); - client = startClient(BasicAuthenticator.builder().username("usr").password("pwd").build()); + client = startClient(BasicAuthenticator.builder().username(DEFAULT_USERNAME).password(DEFAULT_PASSWORD).build()); } private IgniteClient startClient(@Nullable IgniteClientAuthenticator authenticator) { @@ -111,15 +114,7 @@ private TestServer startServer(boolean basicAuthn) { null); if (basicAuthn) { - securityConfiguration.change(securityChange -> { - securityChange.changeEnabled(true); - securityChange.changeAuthentication().changeProviders().create("basic", change -> - change.convert(BasicAuthenticationProviderChange.class) - .changeUsers(users -> users.create("usr", user -> - user.changePassword("pwd")) - ) - ); - }).join(); + assertThat(securityConfiguration.change(securityChange -> securityChange.changeEnabled(true)), willCompleteSuccessfully()); } return server; diff --git a/modules/configuration/build.gradle b/modules/configuration/build.gradle index f0f77c6676cb..f4e10cd6a730 100644 --- a/modules/configuration/build.gradle +++ b/modules/configuration/build.gradle @@ -34,9 +34,17 @@ dependencies { testAnnotationProcessor project(':ignite-configuration-annotation-processor') testImplementation project(':ignite-core') testImplementation testFixtures(project(':ignite-core')) + testImplementation libs.junit.testkit testFixturesAnnotationProcessor project(':ignite-configuration-annotation-processor') testFixturesImplementation project(':ignite-core') testFixturesImplementation testFixtures(project(':ignite-core')) testFixturesImplementation libs.typesafe.config } + +// Exclude tests from inner static classes that use JUnit Platform Test Kit. +test { + filter { + excludeTestsMatching "*ConfigurationExtensionTest\$*" + } +} diff --git a/modules/runner/src/main/java/org/apache/ignite/internal/configuration/CompoundModule.java b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/CompoundModule.java similarity index 100% rename from modules/runner/src/main/java/org/apache/ignite/internal/configuration/CompoundModule.java rename to modules/configuration/src/main/java/org/apache/ignite/internal/configuration/CompoundModule.java diff --git a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/testframework/ConfigurationExtensionTest.java b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/testframework/ConfigurationExtensionTest.java index 48c4a323d5a6..71f66ee669e3 100644 --- a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/testframework/ConfigurationExtensionTest.java +++ b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/testframework/ConfigurationExtensionTest.java @@ -17,21 +17,30 @@ package org.apache.ignite.internal.configuration.testframework; -import static java.util.concurrent.TimeUnit.SECONDS; +import static org.apache.ignite.internal.testframework.JunitExtensionTestUtils.assertExecutesWithFailure; +import static org.apache.ignite.internal.testframework.matchers.CompletableFutureExceptionMatcher.willThrowFast; import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully; import static org.apache.ignite.internal.util.CompletableFutures.nullCompletedFuture; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasSize; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import org.apache.ignite.configuration.validation.ConfigurationValidationException; import org.apache.ignite.internal.configuration.sample.DiscoveryConfiguration; import org.apache.ignite.internal.configuration.sample.ExtendedDiscoveryConfiguration; import org.apache.ignite.internal.configuration.sample.ExtendedDiscoveryConfigurationSchema; import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest; +import org.apache.ignite.internal.testframework.JunitExtensionTestUtils; +import org.apache.ignite.internal.util.ExceptionUtils; +import org.assertj.core.api.Condition; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -56,25 +65,23 @@ static void staticParameterInjection( /** Test that contains injected parameter. */ @Test - public void injectConfiguration( - @InjectConfiguration("mock.joinTimeout=100") DiscoveryConfiguration paramCfg - ) throws Exception { + void injectConfiguration(@InjectConfiguration("mock.joinTimeout=100") DiscoveryConfiguration paramCfg) { assertEquals(5000, fieldCfg.joinTimeout().value()); assertEquals(100, paramCfg.joinTimeout().value()); - paramCfg.change(d -> d.changeJoinTimeout(200)).get(1, SECONDS); + assertThat(paramCfg.change(d -> d.changeJoinTimeout(200)), willCompleteSuccessfully()); assertEquals(200, paramCfg.joinTimeout().value()); - paramCfg.joinTimeout().update(300).get(1, SECONDS); + assertThat(paramCfg.joinTimeout().update(300), willCompleteSuccessfully()); assertEquals(300, paramCfg.joinTimeout().value()); } /** Tests that notifications work on injected configuration instance. */ @Test - public void notifications() throws Exception { + void notifications() { List log = new ArrayList<>(); fieldCfg.listen(ctx -> { @@ -95,35 +102,33 @@ public void notifications() throws Exception { return nullCompletedFuture(); }); - fieldCfg.change(change -> change.changeJoinTimeout(1000_000)).get(1, SECONDS); + assertThat(fieldCfg.change(change -> change.changeJoinTimeout(1000_000)), willCompleteSuccessfully()); assertEquals(List.of("update", "join"), log); log.clear(); - fieldCfg.failureDetectionTimeout().update(2000_000).get(1, SECONDS); + assertThat(fieldCfg.failureDetectionTimeout().update(2000_000), willCompleteSuccessfully()); assertEquals(List.of("update", "failure"), log); } /** Tests that internal configuration extensions work properly on injected configuration instance. */ @Test - public void internalConfiguration( - @InjectConfiguration(extensions = {ExtendedConfigurationSchema.class}) BasicConfiguration cfg - ) throws Exception { + void internalConfiguration(@InjectConfiguration(extensions = ExtendedConfigurationSchema.class) BasicConfiguration cfg) { assertThat(cfg, is(instanceOf(ExtendedConfiguration.class))); assertEquals(1, cfg.visible().value()); assertEquals(2, ((ExtendedConfiguration) cfg).invisible().value()); - cfg.change(change -> { + assertThat(cfg.change(change -> { assertThat(change, is(instanceOf(ExtendedChange.class))); change.changeVisible(3); ((ExtendedChange) change).changeInvisible(4); - }).get(1, SECONDS); + }), willCompleteSuccessfully()); assertEquals(3, cfg.visible().value()); @@ -132,7 +137,7 @@ public void internalConfiguration( /** Test UUID generation in mocks. */ @Test - public void testInjectInternalId( + void testInjectInternalId( @InjectConfiguration( extensions = ExtendedDiscoveryConfigurationSchema.class, name = "test" @@ -140,4 +145,125 @@ public void testInjectInternalId( ) { assertNotNull(((ExtendedDiscoveryConfiguration) discoveryConfig).id().value()); } + + /** Tests that changing a value to one within the valid range succeeds. */ + @Test + void rangeValidationAcceptsValidChange(@InjectConfiguration ValidatedConfiguration cfg) { + assertThat(cfg.change(c -> c.changeRangeValue(80)), willCompleteSuccessfully()); + + assertEquals(80, cfg.rangeValue().value()); + } + + /** Tests that changing a value to one outside the valid range throws {@link ConfigurationValidationException}. */ + @Test + void rangeValidationRejectsInvalidChange(@InjectConfiguration ValidatedConfiguration cfg) { + assertThat(cfg.change(c -> c.changeRangeValue(0)), willThrowFast(ConfigurationValidationException.class)); + } + + /** Tests that changing an {@code @Immutable} field throws {@link ConfigurationValidationException}. */ + @Test + void immutableValidationRejectsChange(@InjectConfiguration ValidatedConfiguration cfg) { + assertThat(cfg.change(c -> c.changeConstValue("changed")), willThrowFast(ConfigurationValidationException.class)); + } + + /** Tests that a failed validation does not mutate the configuration value. */ + @Test + void failedValidationLeavesValueUnchanged(@InjectConfiguration ValidatedConfiguration cfg) { + assertThat(cfg.change(c -> c.changeRangeValue(0)), willThrowFast(ConfigurationValidationException.class)); + + assertEquals(50, cfg.rangeValue().value()); + } + + /** Tests that all violated constraints are collected and reported together. */ + @Test + void multipleValidationIssuesAreReported(@InjectConfiguration ValidatedConfiguration cfg) { + CompletableFuture future = cfg.change(c -> c.changeRangeValue(0).changeConstValue("changed")); + + assertThat(future, willThrowFast(ConfigurationValidationException.class)); + + ExecutionException ex = assertThrows(ExecutionException.class, future::get); + + assertThat(((ConfigurationValidationException) ex.getCause()).getIssues(), hasSize(2)); + } + + /** + * Tests that {@code @Value(hasDefault = true)} schema defaults are applied when no explicit HOCON values + * are provided. + */ + @Test + void defaultValuesAreApplied(@InjectConfiguration ValidatedConfiguration cfg) { + assertEquals(50, cfg.rangeValue().value()); + assertEquals("constant", cfg.constValue().value()); + } + + /** + * Tests that initial configuration values are validated at injection time, and that a value + * violating a constraint causes {@link ConfigurationValidationException} to be thrown. + */ + @Test + void initialValidationRejectsInvalidValue() { + assertInjectionFails(InvalidInitialValueTest.class); + } + + @Test + void missingDefaultValueIsRejectedByValidation() { + assertInjectionFails(MissingDefaultValueTest.class); + } + + @Test + void invalidDefaultValueIsRejectedByValidation() { + assertInjectionFails(InvalidDefaultValueTest.class); + } + + private static void assertInjectionFails(Class testClass) { + assertExecutesWithFailure( + testClass, + new Condition<>( + t -> ExceptionUtils.hasCause(t, ConfigurationValidationException.class), + "ConfigurationValidationException" + ) + ); + } + + /** + * A test class whose {@code @Value(hasDefault = true)} is not initialized. + * It is not a normal test and is only executed programmatically via {@link JunitExtensionTestUtils}. + */ + @ExtendWith(ConfigurationExtension.class) + static class MissingDefaultValueTest extends BaseIgniteAbstractTest { + @SuppressWarnings("unused") + @InjectConfiguration + InvalidDefaultConfiguration cfg; + + @Test + void test() {} + } + + /** + * A test class whose field injection intentionally violates {@code @Range(min=1)}. + * It is not a normal test and is only executed programmatically via {@link JunitExtensionTestUtils}. + */ + @ExtendWith(ConfigurationExtension.class) + static class InvalidInitialValueTest extends BaseIgniteAbstractTest { + @SuppressWarnings("unused") + @InjectConfiguration("mock.rangeValue=0") + ValidatedConfiguration cfg; + + @Test + void test() {} + } + + /** + * A test class whose {@code @Value(hasDefault = true)} is inialized with an invalid value. + * It is not a normal test and is only executed programmatically via {@link JunitExtensionTestUtils}. + */ + @ExtendWith(ConfigurationExtension.class) + static class InvalidDefaultValueTest extends BaseIgniteAbstractTest { + @SuppressWarnings("unused") + @InjectConfiguration + InvalidDefaultConfiguration cfg; + + @Test + void test() {} + } } diff --git a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/testframework/InvalidDefaultConfigurationSchema.java b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/testframework/InvalidDefaultConfigurationSchema.java new file mode 100644 index 000000000000..223e1bc86ce6 --- /dev/null +++ b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/testframework/InvalidDefaultConfigurationSchema.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package org.apache.ignite.internal.configuration.testframework; + +import org.apache.ignite.configuration.annotation.Config; +import org.apache.ignite.configuration.annotation.Value; +import org.apache.ignite.configuration.validation.Range; + +/** + * Configuration schema whose {@code @Value(hasDefault = true)} field is initialized with an invalid value. + */ +@Config +public class InvalidDefaultConfigurationSchema { + @Value(hasDefault = true) + @Range(min = 1, max = 100) + public int invalidDefaultValue = -1; +} diff --git a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/testframework/MissingDefaultConfigurationSchema.java b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/testframework/MissingDefaultConfigurationSchema.java new file mode 100644 index 000000000000..7ddf0e501632 --- /dev/null +++ b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/testframework/MissingDefaultConfigurationSchema.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package org.apache.ignite.internal.configuration.testframework; + +import org.apache.ignite.configuration.annotation.Config; +import org.apache.ignite.configuration.annotation.Value; + +/** + * Configuration schema whose {@code @Value(hasDefault = true)} field is not initialized. + * Used by {@link ConfigurationExtensionTest} to verify that schema defaults are subject to validation. + */ +@Config +public class MissingDefaultConfigurationSchema { + @Value(hasDefault = true) + public String defaultValue; +} diff --git a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/testframework/ValidatedConfigurationSchema.java b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/testframework/ValidatedConfigurationSchema.java new file mode 100644 index 000000000000..8d34afc6e043 --- /dev/null +++ b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/testframework/ValidatedConfigurationSchema.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package org.apache.ignite.internal.configuration.testframework; + +import org.apache.ignite.configuration.annotation.Config; +import org.apache.ignite.configuration.annotation.Value; +import org.apache.ignite.configuration.validation.Immutable; +import org.apache.ignite.configuration.validation.Range; + +/** + * Configuration schema with validation annotations, used by {@link ConfigurationExtensionTest}. + */ +@Config +public class ValidatedConfigurationSchema { + @Range(min = 1, max = 100) + @Value(hasDefault = true) + public int rangeValue = 50; + + @Immutable + @Value(hasDefault = true) + public String constValue = "constant"; +} diff --git a/modules/configuration/src/testFixtures/java/org/apache/ignite/internal/configuration/testframework/BasicConfigurationSchema.java b/modules/configuration/src/testFixtures/java/org/apache/ignite/internal/configuration/testframework/BasicConfigurationSchema.java index 78f8a7dd7ec6..b3fb2b6ab1ea 100644 --- a/modules/configuration/src/testFixtures/java/org/apache/ignite/internal/configuration/testframework/BasicConfigurationSchema.java +++ b/modules/configuration/src/testFixtures/java/org/apache/ignite/internal/configuration/testframework/BasicConfigurationSchema.java @@ -17,13 +17,13 @@ package org.apache.ignite.internal.configuration.testframework; -import org.apache.ignite.configuration.annotation.Config; +import org.apache.ignite.configuration.annotation.ConfigurationRoot; import org.apache.ignite.configuration.annotation.Value; /** * Configuration schema for {@link ConfigurationExtensionTest#notifications()}. */ -@Config +@ConfigurationRoot(rootName = "basic") public class BasicConfigurationSchema { @Value(hasDefault = true) public int visible = 1; diff --git a/modules/configuration/src/testFixtures/java/org/apache/ignite/internal/configuration/testframework/ConfigurationExtension.java b/modules/configuration/src/testFixtures/java/org/apache/ignite/internal/configuration/testframework/ConfigurationExtension.java index 3f13dbfb754b..4dc605807f84 100644 --- a/modules/configuration/src/testFixtures/java/org/apache/ignite/internal/configuration/testframework/ConfigurationExtension.java +++ b/modules/configuration/src/testFixtures/java/org/apache/ignite/internal/configuration/testframework/ConfigurationExtension.java @@ -20,21 +20,27 @@ import static java.lang.reflect.Modifier.isStatic; import static java.util.concurrent.CompletableFuture.allOf; import static java.util.concurrent.Executors.newSingleThreadExecutor; +import static org.apache.ignite.configuration.annotation.ConfigurationType.DISTRIBUTED; import static org.apache.ignite.configuration.annotation.ConfigurationType.LOCAL; import static org.apache.ignite.internal.configuration.notifications.ConfigurationNotifier.notifyListeners; +import static org.apache.ignite.internal.configuration.testframework.InjectConfiguration.MOCK_ROOT_NAME; import static org.apache.ignite.internal.configuration.util.ConfigurationUtil.findEx; import static org.apache.ignite.internal.configuration.util.ConfigurationUtil.polymorphicSchemaExtensions; import static org.apache.ignite.internal.configuration.util.ConfigurationUtil.schemaExtensions; import static org.apache.ignite.internal.configuration.util.ConfigurationUtil.touch; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import com.typesafe.config.ConfigFactory; import com.typesafe.config.ConfigObject; import java.lang.reflect.Field; import java.lang.reflect.Parameter; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.NoSuchElementException; import java.util.ServiceLoader; +import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; @@ -45,7 +51,11 @@ import org.apache.ignite.configuration.RootKey; import org.apache.ignite.configuration.SuperRootChange; import org.apache.ignite.configuration.annotation.ConfigurationType; -import org.apache.ignite.configuration.annotation.PolymorphicConfigInstance; +import org.apache.ignite.configuration.validation.ConfigurationValidationException; +import org.apache.ignite.configuration.validation.ValidationIssue; +import org.apache.ignite.configuration.validation.Validator; +import org.apache.ignite.internal.configuration.CompoundModule; +import org.apache.ignite.internal.configuration.ConfigurationTreeGenerator; import org.apache.ignite.internal.configuration.DynamicConfiguration; import org.apache.ignite.internal.configuration.DynamicConfigurationChanger; import org.apache.ignite.internal.configuration.RootInnerNode; @@ -57,6 +67,9 @@ import org.apache.ignite.internal.configuration.tree.ConfigurationSource; import org.apache.ignite.internal.configuration.tree.InnerNode; import org.apache.ignite.internal.configuration.util.ConfigurationUtil; +import org.apache.ignite.internal.configuration.validation.ConfigurationValidator; +import org.apache.ignite.internal.configuration.validation.ConfigurationValidatorImpl; +import org.jetbrains.annotations.Nullable; import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.AfterEachCallback; import org.junit.jupiter.api.extension.BeforeAllCallback; @@ -86,35 +99,28 @@ public class ConfigurationExtension implements BeforeEachCallback, AfterEachCall /** Key to store {@link ExecutorService} in {@link ExtensionContext.Store}. */ private static final Object POOL_KEY = new Object(); - private static final List LOCAL_MODULES = new ArrayList<>(); - private static final List DISTRIBUTED_MODULES = new ArrayList<>(); + private static final ConfigurationModule LOCAL_MODULE; - /** All {@link ConfigurationExtension} classes in classpath. */ - private static final List> EXTENSIONS; - - /** All {@link PolymorphicConfigInstance} classes in classpath. */ - private static final List> POLYMORPHIC_EXTENSIONS; + private static final ConfigurationModule DISTRIBUTED_MODULE; static { // Automatically find all @InternalConfiguration and @PolymorphicConfigInstance classes // to avoid configuring extensions manually in every test. ServiceLoader modules = ServiceLoader.load(ConfigurationModule.class); - List> extensions = new ArrayList<>(); - List> polymorphicExtensions = new ArrayList<>(); + List localModules = new ArrayList<>(); + List distributedModules = new ArrayList<>(); modules.forEach(configurationModule -> { - extensions.addAll(configurationModule.schemaExtensions()); - polymorphicExtensions.addAll(configurationModule.polymorphicSchemaExtensions()); if (configurationModule.type() == LOCAL) { - LOCAL_MODULES.add(configurationModule); + localModules.add(configurationModule); } else { - DISTRIBUTED_MODULES.add(configurationModule); + distributedModules.add(configurationModule); } }); - EXTENSIONS = List.copyOf(extensions); - POLYMORPHIC_EXTENSIONS = List.copyOf(polymorphicExtensions); + LOCAL_MODULE = new CompoundModule(LOCAL, localModules); + DISTRIBUTED_MODULE = new CompoundModule(DISTRIBUTED, distributedModules); } @Override @@ -220,14 +226,15 @@ private static Object cfgValue( // classes, extension is designed to mock actual configurations from public API to configure Ignite components. Class schemaClass = Class.forName(type.getCanonicalName() + "Schema"); - List> extensions = EXTENSIONS; - List> polymorphicExtensions = POLYMORPHIC_EXTENSIONS; + Collection> extensions = configurationModule(annotation.type()).schemaExtensions(); if (annotation.extensions().length > 0) { extensions = new ArrayList<>(extensions); extensions.addAll(List.of(annotation.extensions())); } + Collection> polymorphicExtensions = configurationModule(annotation.type()).polymorphicSchemaExtensions(); + if (annotation.polymorphicExtensions().length > 0) { polymorphicExtensions = new ArrayList<>(polymorphicExtensions); polymorphicExtensions.addAll(List.of(annotation.polymorphicExtensions())); @@ -240,22 +247,14 @@ private static Object cfgValue( ); // RootKey must be mocked, there's no way to instantiate it using a public constructor. - RootKey rootKey = new RootKey<>( - annotation.rootName().isBlank() ? "mock" : annotation.rootName(), - LOCAL, - schemaClass, - false - ); + RootKey rootKey = new RootKey<>(rootName(annotation), annotation.type(), schemaClass, false); - // Accept both "mock" (HOCON convention per @InjectConfiguration docs) and rootKey.key() - // (for patchConfigurationWithDynamicDefaults which uses the real root key). - SuperRoot superRoot = new SuperRoot(s -> - s.equals(rootKey.key()) || s.equals("mock") - ? new RootInnerNode(rootKey, cgen.instantiateNode(schemaClass)) - : null - ); + SuperRoot superRoot = createSuperRoot(rootKey, schemaClass, cgen); + + // Use empty object as default. + String hoconStr = annotation.value().isBlank() ? rootKey.key() + " : {}" : annotation.value(); - ConfigObject hoconCfg = ConfigFactory.parseString(annotation.value()).root(); + ConfigObject hoconCfg = ConfigFactory.parseString(hoconStr).root(); HoconConverter.hoconSource(hoconCfg).descend(superRoot); @@ -265,7 +264,7 @@ private static Object cfgValue( ConfigurationUtil.addDefaults(superRoot); - if (!annotation.name().isEmpty()) { + if (!annotation.name().isBlank()) { InnerNode root = superRoot.getRoot(rootKey); root.internalId(UUID.randomUUID()); @@ -274,6 +273,10 @@ private static Object cfgValue( superRoot.makeImmutable(); + ConfigurationValidator validator = configurationValidator(annotation, rootKey, schemaClass, cgen); + + validateConfiguration(validator, superRoot); + // Reference to the super root is required to make DynamicConfigurationChanger#change method atomic. var superRootRef = new AtomicReference<>(superRoot); @@ -296,19 +299,19 @@ public CompletableFuture change(ConfigurationSource change) { ConfigurationUtil.dropNulls(copy); + validateConfiguration(validator, sr, copy); + if (superRootRef.compareAndSet(sr, copy)) { long storageRevision = storageRevisionCounter.incrementAndGet(); long notificationNumber = notificationListenerCounter.incrementAndGet(); - List> futures = new ArrayList<>(); - - futures.addAll(notifyListeners( + Collection> futures = notifyListeners( sr.getRoot(rootKey), copy.getRoot(rootKey), (DynamicConfiguration) cfgRef.get(), storageRevision, notificationNumber - )); + ); return allOf(futures.toArray(CompletableFuture[]::new)); } @@ -353,8 +356,8 @@ private static boolean supportsAsConfigurationType(Class type) { private static void patchWithDynamicDefault(ConfigurationType type, SuperRoot superRoot) { SuperRootChangeImpl rootChange = new SuperRootChangeImpl(superRoot); - List modules = type == LOCAL ? LOCAL_MODULES : DISTRIBUTED_MODULES; - modules.forEach(module -> patchIfRootExists(module, rootChange)); + + patchIfRootExists(configurationModule(type), rootChange); } /** @@ -369,4 +372,74 @@ private static void patchIfRootExists(ConfigurationModule module, SuperRootChang // Module tried to access a root that doesn't exist in this SuperRoot - skip } } + + private static void validateConfiguration(@Nullable ConfigurationValidator validator, SuperRoot configuration) { + if (validator == null) { + return; + } + + List validationIssues = validator.validate(configuration); + + if (!validationIssues.isEmpty()) { + throw new ConfigurationValidationException(validationIssues); + } + } + + private static void validateConfiguration(@Nullable ConfigurationValidator validator, SuperRoot curRoots, SuperRoot changes) { + if (validator == null) { + return; + } + + List validationIssues = validator.validate(curRoots, changes); + + if (!validationIssues.isEmpty()) { + throw new ConfigurationValidationException(validationIssues); + } + } + + @Nullable + private static ConfigurationValidator configurationValidator( + InjectConfiguration annotation, + RootKey rootKey, + Class schemaClass, + ConfigurationAsmGenerator cgen + ) { + if (!annotation.validate()) { + return null; + } + + ConfigurationTreeGenerator mockGenerator = mockConfigurationTreeGenerator(rootKey, schemaClass, cgen); + + Set> validators = configurationModule(annotation.type()).validators(); + + return ConfigurationValidatorImpl.withDefaultValidators(mockGenerator, validators); + } + + private static SuperRoot createSuperRoot(RootKey rootKey, Class schemaClass, ConfigurationAsmGenerator cgen) { + // Accept both "mock" (HOCON convention per @InjectConfiguration docs) and rootKey.key() + // (for patchConfigurationWithDynamicDefaults which uses the real root key). + return new SuperRoot(s -> + s.equals(rootKey.key()) || s.equals(MOCK_ROOT_NAME) + ? new RootInnerNode(rootKey, cgen.instantiateNode(schemaClass)) + : null + ); + } + + private static ConfigurationTreeGenerator mockConfigurationTreeGenerator( + RootKey rootKey, Class schemaClass, ConfigurationAsmGenerator cgen + ) { + ConfigurationTreeGenerator generator = mock(ConfigurationTreeGenerator.class); + + when(generator.createSuperRoot()).thenAnswer(invocation -> createSuperRoot(rootKey, schemaClass, cgen)); + + return generator; + } + + private static ConfigurationModule configurationModule(ConfigurationType type) { + return type == LOCAL ? LOCAL_MODULE : DISTRIBUTED_MODULE; + } + + private static String rootName(InjectConfiguration annotation) { + return annotation.rootName().isBlank() ? MOCK_ROOT_NAME : annotation.rootName(); + } } diff --git a/modules/configuration/src/testFixtures/java/org/apache/ignite/internal/configuration/testframework/InjectConfiguration.java b/modules/configuration/src/testFixtures/java/org/apache/ignite/internal/configuration/testframework/InjectConfiguration.java index 9ee019512e95..e2aca6dd1e72 100644 --- a/modules/configuration/src/testFixtures/java/org/apache/ignite/internal/configuration/testframework/InjectConfiguration.java +++ b/modules/configuration/src/testFixtures/java/org/apache/ignite/internal/configuration/testframework/InjectConfiguration.java @@ -34,13 +34,13 @@ /** * Annotation for injecting configuration instances into tests. - *

- * This annotation should be used on either fields or method parameters of the {@code *Configuration} type. - *

- * Injected instance is initialized with values passed in {@link #value()}, with schema defaults where explicit initial values are not + * + *

This annotation should be used on either fields or method parameters of the {@code *Configuration} type. + * + *

Injected instance is initialized with values passed in {@link #value()}, with schema defaults where explicit initial values are not * found. - *

- * Although configuration instance is mutable, there's no {@link ConfigurationRegistry} and {@link ConfigurationChanger} underneath. Main + * + *

Although configuration instance is mutable, there's no {@link ConfigurationRegistry} and {@link ConfigurationChanger} underneath. Main * point of the extension is to provide mocks. * * @see ConfigurationExtension @@ -48,21 +48,23 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.PARAMETER}) public @interface InjectConfiguration { + String MOCK_ROOT_NAME = "mock"; + /** - * Configuration values to initialize the instance. Has HOCON syntax. Must have a root value {@code mock}. - *

- * Examples: + * Configuration values to initialize the instance. Has HOCON syntax. Must have a root value {@link #MOCK_ROOT_NAME}. + * + *

Examples: *

    *
  • {@code mock.timeout=1000}
  • *
  • {@code mock{cfg1=50, cfg2=90}}
  • *
- *

- * Uses only default values by default. + * + *

Uses only default values by default. * * @return Initial configuration values in HOCON format. */ @Language("HOCON") - String value() default "mock : {}"; + String value() default ""; /** * Name value to imitate named list elements. Default empty string value is treated like the absence of the name. @@ -96,4 +98,12 @@ * @return Array of configuration schema extensions. */ Class[] polymorphicExtensions() default {}; + + /** + * Flag indicating whether the provided configuration should be validated. + * + *

It may be useful to disable validation in tests if the developer needs to break the configuration contract on purpose, + * for example to set a smaller value than allowed by the corresponding schema. + */ + boolean validate() default true; } diff --git a/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/JunitExtensionTestUtils.java b/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/JunitExtensionTestUtils.java index f7e43846b78f..723a5da3f097 100644 --- a/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/JunitExtensionTestUtils.java +++ b/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/JunitExtensionTestUtils.java @@ -32,7 +32,7 @@ * * @see JUnit Platform Test Kit */ -class JunitExtensionTestUtils { +public class JunitExtensionTestUtils { /** * Executes the given test class on the Jupiter test engine. */ @@ -45,7 +45,7 @@ private static EngineExecutionResults execute(Class testClass) { /** * Executes the given test class and checks that it has run all its tests successfully. */ - static void assertExecutesSuccessfully(Class testClass) { + public static void assertExecutesSuccessfully(Class testClass) { execute(testClass) .allEvents() .assertThatEvents() @@ -58,7 +58,7 @@ static void assertExecutesSuccessfully(Class testClass) { * Executes the given test class and checks that it fails with matching error conditions. */ @SafeVarargs - static void assertExecutesWithFailure(Class testClass, Condition... conditions) { + public static void assertExecutesWithFailure(Class testClass, Condition... conditions) { execute(testClass) .allEvents() .assertThatEvents() diff --git a/modules/eventlog/src/integrationTest/java/org/apache/ignite/internal/eventlog/impl/ItEventLogConfigurationTest.java b/modules/eventlog/src/integrationTest/java/org/apache/ignite/internal/eventlog/impl/ItEventLogConfigurationTest.java index e94929047f48..a7ad204b0bb2 100644 --- a/modules/eventlog/src/integrationTest/java/org/apache/ignite/internal/eventlog/impl/ItEventLogConfigurationTest.java +++ b/modules/eventlog/src/integrationTest/java/org/apache/ignite/internal/eventlog/impl/ItEventLogConfigurationTest.java @@ -17,6 +17,7 @@ package org.apache.ignite.internal.eventlog.impl; +import static org.apache.ignite.configuration.annotation.ConfigurationType.DISTRIBUTED; import static org.apache.ignite.internal.eventlog.impl.TestEventTypes.TEST_EVENT_TYPE_1; import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully; import static org.hamcrest.MatcherAssert.assertThat; @@ -44,7 +45,7 @@ class ItEventLogConfigurationTest extends BaseIgniteAbstractTest { private static final String IN_MEMORY_SINK_TYPE = "inMemory"; private static final String TEST_SINK_NAME = "testSink"; - @InjectConfiguration(polymorphicExtensions = InMemoryCollectionSinkConfigurationSchema.class) + @InjectConfiguration(polymorphicExtensions = InMemoryCollectionSinkConfigurationSchema.class, type = DISTRIBUTED) private EventLogConfiguration eventLogConfiguration; private EventLogImpl eventLog; diff --git a/modules/eventlog/src/test/java/org/apache/ignite/internal/eventlog/impl/ConfigurationBasedChannelRegistryTest.java b/modules/eventlog/src/test/java/org/apache/ignite/internal/eventlog/impl/ConfigurationBasedChannelRegistryTest.java index 2a50c401d267..19d5ff4db83f 100644 --- a/modules/eventlog/src/test/java/org/apache/ignite/internal/eventlog/impl/ConfigurationBasedChannelRegistryTest.java +++ b/modules/eventlog/src/test/java/org/apache/ignite/internal/eventlog/impl/ConfigurationBasedChannelRegistryTest.java @@ -17,6 +17,7 @@ package org.apache.ignite.internal.eventlog.impl; +import static org.apache.ignite.configuration.annotation.ConfigurationType.DISTRIBUTED; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasSize; @@ -41,7 +42,7 @@ class ConfigurationBasedChannelRegistryTest extends BaseIgniteAbstractTest { private static final String TEST_CHANNEL = "testChannel"; - @InjectConfiguration + @InjectConfiguration(type = DISTRIBUTED) private EventLogConfiguration cfg; private ConfigurationBasedChannelRegistry registry; diff --git a/modules/eventlog/src/test/java/org/apache/ignite/internal/eventlog/impl/ConfigurationBasedSinkRegistryTest.java b/modules/eventlog/src/test/java/org/apache/ignite/internal/eventlog/impl/ConfigurationBasedSinkRegistryTest.java index c3a5f56b4b97..9e6c3799405d 100644 --- a/modules/eventlog/src/test/java/org/apache/ignite/internal/eventlog/impl/ConfigurationBasedSinkRegistryTest.java +++ b/modules/eventlog/src/test/java/org/apache/ignite/internal/eventlog/impl/ConfigurationBasedSinkRegistryTest.java @@ -17,6 +17,7 @@ package org.apache.ignite.internal.eventlog.impl; +import static org.apache.ignite.configuration.annotation.ConfigurationType.DISTRIBUTED; import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.nullValue; @@ -41,7 +42,7 @@ class ConfigurationBasedSinkRegistryTest extends BaseIgniteAbstractTest { private static final String TEST_CHANNEL = "testChannel"; private static final String TEST_SINK = "testSink"; - @InjectConfiguration(polymorphicExtensions = InMemoryCollectionSinkConfigurationSchema.class) + @InjectConfiguration(polymorphicExtensions = InMemoryCollectionSinkConfigurationSchema.class, type = DISTRIBUTED) private EventLogConfiguration cfg; private InMemoryCollectionSink inMemoryCollectionSink; diff --git a/modules/eventlog/src/test/java/org/apache/ignite/internal/eventlog/impl/LogSinkTest.java b/modules/eventlog/src/test/java/org/apache/ignite/internal/eventlog/impl/LogSinkTest.java index 468abd8b73ba..72e247548290 100644 --- a/modules/eventlog/src/test/java/org/apache/ignite/internal/eventlog/impl/LogSinkTest.java +++ b/modules/eventlog/src/test/java/org/apache/ignite/internal/eventlog/impl/LogSinkTest.java @@ -17,6 +17,7 @@ package org.apache.ignite.internal.eventlog.impl; +import static org.apache.ignite.configuration.annotation.ConfigurationType.DISTRIBUTED; import static org.awaitility.Awaitility.await; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasItem; @@ -44,7 +45,7 @@ @ExtendWith(ConfigurationExtension.class) class LogSinkTest extends BaseIgniteAbstractTest { - @InjectConfiguration + @InjectConfiguration(type = DISTRIBUTED) private EventLogConfiguration cfg; private static Path eventlogPath; diff --git a/modules/eventlog/src/test/java/org/apache/ignite/internal/eventlog/impl/WebhookSinkTest.java b/modules/eventlog/src/test/java/org/apache/ignite/internal/eventlog/impl/WebhookSinkTest.java index c541cb8d8b55..a8af06144e90 100644 --- a/modules/eventlog/src/test/java/org/apache/ignite/internal/eventlog/impl/WebhookSinkTest.java +++ b/modules/eventlog/src/test/java/org/apache/ignite/internal/eventlog/impl/WebhookSinkTest.java @@ -28,6 +28,7 @@ import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; import static com.github.tomakehurst.wiremock.client.WireMock.verify; +import static org.apache.ignite.configuration.annotation.ConfigurationType.DISTRIBUTED; import static org.apache.ignite.internal.rest.constants.MediaType.APPLICATION_JSON; import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully; import static org.awaitility.Awaitility.await; @@ -62,7 +63,10 @@ class WebhookSinkTest extends BaseIgniteAbstractTest { private static final UUID CLUSTER_ID = UUID.randomUUID(); - @InjectConfiguration("mock{sinks.webhookSink{type=webhook,endpoint=\"http://localhost\"}}") + @InjectConfiguration( + value = "mock{sinks.webhookSink{type=webhook,endpoint=\"http://localhost\"}}", + type = DISTRIBUTED + ) private EventLogConfiguration cfg; private WebhookSink sink; diff --git a/modules/low-watermark/src/test/java/org/apache/ignite/internal/lowwatermark/LowWatermarkImplTest.java b/modules/low-watermark/src/test/java/org/apache/ignite/internal/lowwatermark/LowWatermarkImplTest.java index 2869a298f698..3d7a53852567 100644 --- a/modules/low-watermark/src/test/java/org/apache/ignite/internal/lowwatermark/LowWatermarkImplTest.java +++ b/modules/low-watermark/src/test/java/org/apache/ignite/internal/lowwatermark/LowWatermarkImplTest.java @@ -86,7 +86,7 @@ /** For {@link LowWatermarkImpl} testing. */ @ExtendWith(ConfigurationExtension.class) public class LowWatermarkImplTest extends BaseIgniteAbstractTest { - @InjectConfiguration + @InjectConfiguration(validate = false) private LowWatermarkConfiguration lowWatermarkConfig; private final ClockService clockService = spy(new TestClockService(new HybridClockImpl())); diff --git a/modules/metrics-exporter-otlp/src/test/java/org/apache/ignite/internal/metrics/exporters/otlp/OtlpPushMetricExporterTest.java b/modules/metrics-exporter-otlp/src/test/java/org/apache/ignite/internal/metrics/exporters/otlp/OtlpPushMetricExporterTest.java index db807fdc7e76..6ce1464cabbd 100644 --- a/modules/metrics-exporter-otlp/src/test/java/org/apache/ignite/internal/metrics/exporters/otlp/OtlpPushMetricExporterTest.java +++ b/modules/metrics-exporter-otlp/src/test/java/org/apache/ignite/internal/metrics/exporters/otlp/OtlpPushMetricExporterTest.java @@ -18,6 +18,7 @@ package org.apache.ignite.internal.metrics.exporters.otlp; import static io.opentelemetry.api.common.AttributeType.STRING; +import static org.apache.ignite.configuration.annotation.ConfigurationType.DISTRIBUTED; import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertArrayEquals; @@ -79,7 +80,10 @@ @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.LENIENT) class OtlpPushMetricExporterTest extends BaseIgniteAbstractTest { - @InjectConfiguration("mock.exporters = {otlp = {exporterName = otlp, periodMillis = 300, endpoint = \"http://localhost:4317\"}}") + @InjectConfiguration( + value = "mock.exporters = {otlp = {exporterName = otlp, periodMillis = 300, endpoint = \"http://localhost:4317\"}}", + type = DISTRIBUTED + ) private MetricConfiguration metricConfiguration; private static final UUID CLUSTER_ID = UUID.randomUUID(); diff --git a/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/MetricManagerTest.java b/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/MetricManagerTest.java index 97b4fa8e49da..3e2e894003a1 100644 --- a/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/MetricManagerTest.java +++ b/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/MetricManagerTest.java @@ -17,6 +17,7 @@ package org.apache.ignite.internal.metrics; +import static org.apache.ignite.configuration.annotation.ConfigurationType.DISTRIBUTED; import static org.apache.ignite.internal.metrics.exporters.jmx.JmxExporter.JMX_EXPORTER_NAME; import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willSucceedFast; import static org.apache.ignite.internal.util.IgniteUtils.makeMbeanName; @@ -45,7 +46,10 @@ public class MetricManagerTest extends BaseIgniteAbstractTest { private static final UUID NODE_ID = UUID.randomUUID(); - @InjectConfiguration("mock.exporters = {" + JMX_EXPORTER_NAME + " = {exporterName = " + JMX_EXPORTER_NAME + "}}") + @InjectConfiguration( + value = "mock.exporters = {" + JMX_EXPORTER_NAME + " = {exporterName = " + JMX_EXPORTER_NAME + "}}", + type = DISTRIBUTED + ) private MetricConfiguration jmxMetricConfiguration; @Test diff --git a/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/exporters/jmx/JmxExporterTest.java b/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/exporters/jmx/JmxExporterTest.java index f1c0252864c2..f322aa52284e 100644 --- a/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/exporters/jmx/JmxExporterTest.java +++ b/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/exporters/jmx/JmxExporterTest.java @@ -18,6 +18,7 @@ package org.apache.ignite.internal.metrics.exporters.jmx; import static java.util.stream.Collectors.toMap; +import static org.apache.ignite.configuration.annotation.ConfigurationType.DISTRIBUTED; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -81,7 +82,7 @@ */ @ExtendWith({ConfigurationExtension.class}) public class JmxExporterTest extends BaseIgniteAbstractTest { - @InjectConfiguration(value = "mock.exporters = {jmx = {exporterName = jmx}}") + @InjectConfiguration(value = "mock.exporters = {jmx = {exporterName = jmx}}", type = DISTRIBUTED) private MetricConfiguration metricConfiguration; private JmxExporterView jmxExporterConf; diff --git a/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/exporters/log/LogPushExporterTest.java b/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/exporters/log/LogPushExporterTest.java index d1abfcf37d50..ebbced059a74 100644 --- a/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/exporters/log/LogPushExporterTest.java +++ b/modules/metrics/src/test/java/org/apache/ignite/internal/metrics/exporters/log/LogPushExporterTest.java @@ -17,6 +17,7 @@ package org.apache.ignite.internal.metrics.exporters.log; +import static org.apache.ignite.configuration.annotation.ConfigurationType.DISTRIBUTED; import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; @@ -72,7 +73,7 @@ */ @ExtendWith({ConfigurationExtension.class}) public class LogPushExporterTest extends BaseIgniteAbstractTest { - @InjectConfiguration("mock.exporters {log {" + @InjectConfiguration(value = "mock.exporters {log {" + "exporterName = logPush, " + "periodMillis = 300, " + "oneLinePerMetricSource = false," @@ -85,7 +86,7 @@ public class LogPushExporterTest extends BaseIgniteAbstractTest { + " \"similar.name.*\", " + " \"ignored\"" + "]" - + "}}") + + "}}", type = DISTRIBUTED) private MetricConfiguration metricConfiguration; private static final UUID CLUSTER_ID = UUID.randomUUID(); diff --git a/modules/placement-driver/src/integrationTest/java/org/apache/ignite/internal/placementdriver/PlacementDriverManagerTest.java b/modules/placement-driver/src/integrationTest/java/org/apache/ignite/internal/placementdriver/PlacementDriverManagerTest.java index d78d82bc7426..a89a9ef59605 100644 --- a/modules/placement-driver/src/integrationTest/java/org/apache/ignite/internal/placementdriver/PlacementDriverManagerTest.java +++ b/modules/placement-driver/src/integrationTest/java/org/apache/ignite/internal/placementdriver/PlacementDriverManagerTest.java @@ -153,7 +153,7 @@ public class PlacementDriverManagerTest extends BasePlacementDriverTest { @InjectConfiguration private SystemDistributedConfiguration systemDistributedConfiguration; - @InjectConfiguration + @InjectConfiguration(validate = false) private ReplicationConfiguration replicationConfiguration; private MetaStorageManagerImpl metaStorageManager; diff --git a/modules/placement-driver/src/test/java/org/apache/ignite/internal/placementdriver/LeaseNegotiationTest.java b/modules/placement-driver/src/test/java/org/apache/ignite/internal/placementdriver/LeaseNegotiationTest.java index 8c445c7a91c4..581337823fd5 100644 --- a/modules/placement-driver/src/test/java/org/apache/ignite/internal/placementdriver/LeaseNegotiationTest.java +++ b/modules/placement-driver/src/test/java/org/apache/ignite/internal/placementdriver/LeaseNegotiationTest.java @@ -125,7 +125,7 @@ public class LeaseNegotiationTest extends BaseIgniteAbstractTest { private final long assignmentsTimestamp = new HybridTimestamp(0, 1).longValue(); - @InjectConfiguration("mock.leaseAgreementAcceptanceTimeLimitMillis = 2000") + @InjectConfiguration(value = "mock.leaseAgreementAcceptanceTimeLimitMillis = 2000", validate = false) private ReplicationConfiguration replicationConfiguration; private static ZonePartitionId replicationGroupId(int objectId, int partId) { diff --git a/modules/placement-driver/src/test/java/org/apache/ignite/internal/placementdriver/LeaseUpdaterTest.java b/modules/placement-driver/src/test/java/org/apache/ignite/internal/placementdriver/LeaseUpdaterTest.java index 3a8e71fc845f..e23632ddef1a 100644 --- a/modules/placement-driver/src/test/java/org/apache/ignite/internal/placementdriver/LeaseUpdaterTest.java +++ b/modules/placement-driver/src/test/java/org/apache/ignite/internal/placementdriver/LeaseUpdaterTest.java @@ -110,7 +110,7 @@ public class LeaseUpdaterTest extends BaseIgniteAbstractTest { private final LogicalNode stableNode = new LogicalNode(randomUUID(), "test-node-stable", NetworkAddress.from("127.0.0.1:10000")); private final LogicalNode pendingNode = new LogicalNode(randomUUID(), "test-node-pending", NetworkAddress.from("127.0.0.1:10001")); - @InjectConfiguration("mock.leaseExpirationIntervalMillis = " + TEST_LEASE_INTERVAL_MILLIS) + @InjectConfiguration(value = "mock.leaseExpirationIntervalMillis = " + TEST_LEASE_INTERVAL_MILLIS, validate = false) private ReplicationConfiguration replicationConfiguration; @Mock diff --git a/modules/raft/src/test/java/org/apache/ignite/internal/raft/storage/segstore/RaftLogGarbageCollectorTest.java b/modules/raft/src/test/java/org/apache/ignite/internal/raft/storage/segstore/RaftLogGarbageCollectorTest.java index 69b6e0c9f958..d17429bbb100 100644 --- a/modules/raft/src/test/java/org/apache/ignite/internal/raft/storage/segstore/RaftLogGarbageCollectorTest.java +++ b/modules/raft/src/test/java/org/apache/ignite/internal/raft/storage/segstore/RaftLogGarbageCollectorTest.java @@ -80,7 +80,7 @@ class RaftLogGarbageCollectorTest extends IgniteAbstractTest { @InjectConfiguration private RaftConfiguration raftConfiguration; - @InjectConfiguration("mock.segmentFileSizeBytes=" + FILE_SIZE) + @InjectConfiguration(value = "mock.segmentFileSizeBytes=" + FILE_SIZE, validate = false) private LogStorageConfiguration storageConfiguration; private SegmentFileManager fileManager; diff --git a/modules/raft/src/test/java/org/apache/ignite/internal/raft/storage/segstore/SegmentFileManagerGetEntryTest.java b/modules/raft/src/test/java/org/apache/ignite/internal/raft/storage/segstore/SegmentFileManagerGetEntryTest.java index 27b182a71247..6828daf5e4de 100644 --- a/modules/raft/src/test/java/org/apache/ignite/internal/raft/storage/segstore/SegmentFileManagerGetEntryTest.java +++ b/modules/raft/src/test/java/org/apache/ignite/internal/raft/storage/segstore/SegmentFileManagerGetEntryTest.java @@ -79,7 +79,7 @@ class SegmentFileManagerGetEntryTest extends IgniteAbstractTest { @BeforeEach void setUp( @InjectConfiguration RaftConfiguration raftConfiguration, - @InjectConfiguration("mock.segmentFileSizeBytes=" + FILE_SIZE) + @InjectConfiguration(value = "mock.segmentFileSizeBytes=" + FILE_SIZE, validate = false) LogStorageConfiguration storageConfiguration ) throws IOException { fileManager = new SegmentFileManager( diff --git a/modules/raft/src/test/java/org/apache/ignite/internal/raft/storage/segstore/SegmentFileManagerTest.java b/modules/raft/src/test/java/org/apache/ignite/internal/raft/storage/segstore/SegmentFileManagerTest.java index a11a96588db7..6ff0d7c94602 100644 --- a/modules/raft/src/test/java/org/apache/ignite/internal/raft/storage/segstore/SegmentFileManagerTest.java +++ b/modules/raft/src/test/java/org/apache/ignite/internal/raft/storage/segstore/SegmentFileManagerTest.java @@ -101,7 +101,7 @@ class SegmentFileManagerTest extends IgniteAbstractTest { @InjectConfiguration private RaftConfiguration raftConfiguration; - @InjectConfiguration("mock.segmentFileSizeBytes=" + FILE_SIZE) + @InjectConfiguration(value = "mock.segmentFileSizeBytes=" + FILE_SIZE, validate = false) private LogStorageConfiguration storageConfiguration; private SegmentFileManager fileManager; diff --git a/modules/raft/src/test/java/org/apache/ignite/internal/raft/storage/segstore/SegstoreLogStorageConcurrencyTest.java b/modules/raft/src/test/java/org/apache/ignite/internal/raft/storage/segstore/SegstoreLogStorageConcurrencyTest.java index ca7ce4c605de..b6237aa569c1 100644 --- a/modules/raft/src/test/java/org/apache/ignite/internal/raft/storage/segstore/SegstoreLogStorageConcurrencyTest.java +++ b/modules/raft/src/test/java/org/apache/ignite/internal/raft/storage/segstore/SegstoreLogStorageConcurrencyTest.java @@ -53,7 +53,7 @@ class SegstoreLogStorageConcurrencyTest extends IgniteAbstractTest { @BeforeEach void setUp( @InjectConfiguration RaftConfiguration raftConfiguration, - @InjectConfiguration("mock.segmentFileSizeBytes=" + SEGMENT_SIZE) + @InjectConfiguration(value = "mock.segmentFileSizeBytes=" + SEGMENT_SIZE, validate = false) LogStorageConfiguration storageConfiguration ) throws IOException { segmentFileManager = new SegmentFileManager( diff --git a/modules/rest/src/test/java/org/apache/ignite/internal/rest/RestComponentTest.java b/modules/rest/src/test/java/org/apache/ignite/internal/rest/RestComponentTest.java index 1071664048ec..47f7a7102a08 100644 --- a/modules/rest/src/test/java/org/apache/ignite/internal/rest/RestComponentTest.java +++ b/modules/rest/src/test/java/org/apache/ignite/internal/rest/RestComponentTest.java @@ -20,6 +20,7 @@ import static io.micronaut.http.HttpStatus.CONFLICT; import static io.micronaut.http.HttpStatus.NOT_FOUND; import static io.micronaut.http.HttpStatus.OK; +import static org.apache.ignite.configuration.annotation.ConfigurationType.DISTRIBUTED; import static org.apache.ignite.configuration.annotation.ConfigurationType.LOCAL; import static org.apache.ignite.internal.rest.RestState.INITIALIZATION; import static org.apache.ignite.internal.rest.RestState.INITIALIZED; @@ -82,7 +83,7 @@ public class RestComponentTest extends BaseIgniteAbstractTest { private HttpClient client; - @InjectConfiguration + @InjectConfiguration(type = DISTRIBUTED, validate = false) private SecurityConfiguration securityConfiguration; @BeforeEach diff --git a/modules/security/src/main/java/org/apache/ignite/internal/security/authentication/SecurityConfigurationModule.java b/modules/security/src/main/java/org/apache/ignite/internal/security/authentication/SecurityConfigurationModule.java index 0fa05a6edc0b..a75b9fabefd5 100644 --- a/modules/security/src/main/java/org/apache/ignite/internal/security/authentication/SecurityConfigurationModule.java +++ b/modules/security/src/main/java/org/apache/ignite/internal/security/authentication/SecurityConfigurationModule.java @@ -38,11 +38,11 @@ */ @AutoService(ConfigurationModule.class) public class SecurityConfigurationModule implements ConfigurationModule { - static final String DEFAULT_PROVIDER_NAME = "default"; + public static final String DEFAULT_PROVIDER_NAME = "default"; - static final String DEFAULT_USERNAME = "ignite"; + public static final String DEFAULT_USERNAME = "ignite"; - static final String DEFAULT_PASSWORD = "ignite"; + public static final String DEFAULT_PASSWORD = "ignite"; @Override public ConfigurationType type() { diff --git a/modules/security/src/test/java/org/apache/ignite/internal/security/authentication/AuthenticationProvidersValidatorImplTest.java b/modules/security/src/test/java/org/apache/ignite/internal/security/authentication/AuthenticationProvidersValidatorImplTest.java index 6735611d1fda..ce945539f34a 100644 --- a/modules/security/src/test/java/org/apache/ignite/internal/security/authentication/AuthenticationProvidersValidatorImplTest.java +++ b/modules/security/src/test/java/org/apache/ignite/internal/security/authentication/AuthenticationProvidersValidatorImplTest.java @@ -23,6 +23,7 @@ import java.util.function.Consumer; import org.apache.ignite.configuration.NamedListView; +import org.apache.ignite.configuration.annotation.ConfigurationType; import org.apache.ignite.configuration.validation.ValidationContext; import org.apache.ignite.internal.configuration.ClusterConfiguration; import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension; @@ -44,7 +45,11 @@ @ExtendWith(ConfigurationExtension.class) class AuthenticationProvidersValidatorImplTest extends BaseIgniteAbstractTest { - @InjectConfiguration(polymorphicExtensions = CustomAuthenticationProviderConfigurationSchema.class) + @InjectConfiguration( + polymorphicExtensions = CustomAuthenticationProviderConfigurationSchema.class, + type = ConfigurationType.DISTRIBUTED, + validate = false + ) private SecurityConfiguration securityConfiguration; @Test