diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ConfigurePDXCommand.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ConfigurePDXCommand.java
index 0c11448f40b4..43719f94ca87 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ConfigurePDXCommand.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ConfigurePDXCommand.java
@@ -28,6 +28,8 @@
import org.apache.geode.internal.cache.xmlcache.CacheXmlGenerator;
import org.apache.geode.management.cli.CliMetaData;
import org.apache.geode.management.cli.Result;
+import org.apache.geode.management.internal.cli.AbstractCliAroundInterceptor;
+import org.apache.geode.management.internal.cli.GfshParseResult;
import org.apache.geode.management.internal.cli.i18n.CliStrings;
import org.apache.geode.management.internal.cli.result.InfoResultData;
import org.apache.geode.management.internal.cli.result.ResultBuilder;
@@ -37,8 +39,42 @@
import org.apache.geode.security.ResourcePermission;
public class ConfigurePDXCommand extends GfshCommand {
+
+ /**
+ *
+ * @param checkPortability
+ * @param patterns
+ */
+ protected ReflectionBasedAutoSerializer createReflectionBasedAutoSerializer(
+ boolean checkPortability, String[] patterns) {
+ return new ReflectionBasedAutoSerializer(checkPortability, patterns);
+ }
+
+ /**
+ * @param forParsing if true then this creation is used for parsing xml; if false then it is used
+ * for generating xml.
+ * @since GemFire 5.7
+ */
+ protected CacheCreation getCacheCreation(boolean forParsing) {
+ return new CacheCreation(forParsing);
+ }
+
+ /**
+ * Creates the XmlEntity associated to the PDX configuration.
+ */
+ protected XmlEntity createXmlEntity(CacheCreation cache) {
+ final StringWriter stringWriter = new StringWriter();
+ final PrintWriter printWriter = new PrintWriter(stringWriter);
+ CacheXmlGenerator.generate(cache, printWriter, true, false, false);
+ printWriter.close();
+ String xmlDefinition = stringWriter.toString();
+
+ return XmlEntity.builder().withType(CacheXml.PDX).withConfig(xmlDefinition).build();
+ }
+
@CliCommand(value = CliStrings.CONFIGURE_PDX, help = CliStrings.CONFIGURE_PDX__HELP)
- @CliMetaData(relatedTopic = CliStrings.TOPIC_GEODE_REGION)
+ @CliMetaData(relatedTopic = CliStrings.TOPIC_GEODE_REGION,
+ interceptor = "org.apache.geode.management.internal.cli.commands.ConfigurePDXCommand$Interceptor")
@ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
operation = ResourcePermission.Operation.MANAGE)
public Result configurePDX(
@@ -49,26 +85,26 @@ public Result configurePDX(
@CliOption(key = CliStrings.CONFIGURE_PDX__DISKSTORE, specifiedDefaultValue = "",
help = CliStrings.CONFIGURE_PDX__DISKSTORE__HELP) String diskStore,
@CliOption(key = CliStrings.CONFIGURE_PDX__AUTO__SERIALIZER__CLASSES,
- help = CliStrings.CONFIGURE_PDX__AUTO__SERIALIZER__CLASSES__HELP) String[] patterns,
+ help = CliStrings.CONFIGURE_PDX__AUTO__SERIALIZER__CLASSES__HELP) String[] nonPortableClassesPatterns,
@CliOption(key = CliStrings.CONFIGURE_PDX__PORTABLE__AUTO__SERIALIZER__CLASSES,
- help = CliStrings.CONFIGURE_PDX__PORTABLE__AUTO__SERIALIZER__CLASSES__HELP) String[] portablePatterns) {
+ help = CliStrings.CONFIGURE_PDX__PORTABLE__AUTO__SERIALIZER__CLASSES__HELP) String[] portableClassesPatterns) {
+
Result result;
try {
+ ReflectionBasedAutoSerializer autoSerializer;
+ CacheCreation cache = getCacheCreation(true);
InfoResultData ird = ResultBuilder.createInfoResultData();
- CacheCreation cache = new CacheCreation(true);
- if ((portablePatterns != null && portablePatterns.length > 0)
- && (patterns != null && patterns.length > 0)) {
- return ResultBuilder.createUserErrorResult(CliStrings.CONFIGURE_PDX__ERROR__MESSAGE);
- }
if (!getAllNormalMembers().isEmpty()) {
ird.addLine(CliStrings.CONFIGURE_PDX__NORMAL__MEMBERS__WARNING);
}
+
// Set persistent and the disk-store
if (diskStore != null) {
cache.setPdxPersistent(true);
ird.addLine(CliStrings.CONFIGURE_PDX__PERSISTENT + " = " + cache.getPdxPersistent());
+
if (!diskStore.equals("")) {
cache.setPdxDiskStore(diskStore);
ird.addLine(CliStrings.CONFIGURE_PDX__DISKSTORE + " = " + cache.getPdxDiskStore());
@@ -86,52 +122,65 @@ public Result configurePDX(
} else {
cache.setPdxReadSerialized(CacheConfig.DEFAULT_PDX_READ_SERIALIZED);
}
+
ird.addLine(
CliStrings.CONFIGURE_PDX__READ__SERIALIZED + " = " + cache.getPdxReadSerialized());
-
// Set ignoreUnreadFields
if (ignoreUnreadFields != null) {
cache.setPdxIgnoreUnreadFields(ignoreUnreadFields);
} else {
cache.setPdxIgnoreUnreadFields(CacheConfig.DEFAULT_PDX_IGNORE_UNREAD_FIELDS);
}
+
ird.addLine(CliStrings.CONFIGURE_PDX__IGNORE__UNREAD_FIELDS + " = "
+ cache.getPdxIgnoreUnreadFields());
-
- if (portablePatterns != null) {
- ReflectionBasedAutoSerializer autoSerializer =
- new ReflectionBasedAutoSerializer(portablePatterns);
+ // Auto Serializer Configuration
+ if (portableClassesPatterns != null) {
+ autoSerializer = createReflectionBasedAutoSerializer(true, portableClassesPatterns);
cache.setPdxSerializer(autoSerializer);
- ird.addLine("PDX Serializer " + cache.getPdxSerializer().getClass().getName());
- ird.addLine("Portable classes " + Arrays.toString(portablePatterns));
+ ird.addLine("PDX Serializer = " + cache.getPdxSerializer().getClass().getName());
+ ird.addLine("Portable Classes = " + Arrays.toString(portableClassesPatterns));
}
- if (patterns != null) {
- ReflectionBasedAutoSerializer nonPortableAutoSerializer =
- new ReflectionBasedAutoSerializer(true, patterns);
- cache.setPdxSerializer(nonPortableAutoSerializer);
- ird.addLine("PDX Serializer : " + cache.getPdxSerializer().getClass().getName());
- ird.addLine("Non portable classes :" + Arrays.toString(patterns));
+ if (nonPortableClassesPatterns != null) {
+ autoSerializer = createReflectionBasedAutoSerializer(false, nonPortableClassesPatterns);
+ cache.setPdxSerializer(autoSerializer);
+ ird.addLine("PDX Serializer = " + cache.getPdxSerializer().getClass().getName());
+ ird.addLine("Non Portable Classes = " + Arrays.toString(nonPortableClassesPatterns));
}
- final StringWriter stringWriter = new StringWriter();
- final PrintWriter printWriter = new PrintWriter(stringWriter);
- CacheXmlGenerator.generate(cache, printWriter, true, false, false);
- printWriter.close();
- String xmlDefinition = stringWriter.toString();
- // TODO jbarrett - shouldn't this use the same loadXmlDefinition that other constructors use?
- XmlEntity xmlEntity =
- XmlEntity.builder().withType(CacheXml.PDX).withConfig(xmlDefinition).build();
-
+ XmlEntity xmlEntity = createXmlEntity(cache);
result = ResultBuilder.buildResult(ird);
persistClusterConfiguration(result,
() -> getSharedConfiguration().addXmlEntity(xmlEntity, null));
-
} catch (Exception e) {
return ResultBuilder.createGemFireErrorResult(e.getMessage());
}
+
return result;
}
+
+ /**
+ * Interceptor to validate command parameters.
+ */
+ public static class Interceptor extends AbstractCliAroundInterceptor {
+
+ @Override
+ public Result preExecution(GfshParseResult parseResult) {
+ Object portableClassesPatterns =
+ parseResult.getParamValue(CliStrings.CONFIGURE_PDX__PORTABLE__AUTO__SERIALIZER__CLASSES);
+ Object nonPortableClassesPatterns =
+ parseResult.getParamValue(CliStrings.CONFIGURE_PDX__AUTO__SERIALIZER__CLASSES);
+
+ if ((nonPortableClassesPatterns != null && ((String[]) nonPortableClassesPatterns).length > 0)
+ && (portableClassesPatterns != null && ((String[]) portableClassesPatterns).length > 0)) {
+
+ return ResultBuilder.createUserErrorResult(CliStrings.CONFIGURE_PDX__ERROR__MESSAGE);
+ }
+
+ return ResultBuilder.createInfoResult("");
+ }
+ }
}
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/i18n/CliStrings.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/i18n/CliStrings.java
index fe8650c02125..98f4920d07a3 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/i18n/CliStrings.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/i18n/CliStrings.java
@@ -3114,11 +3114,12 @@ public class CliStrings {
public static final String CONFIGURE_PDX__PORTABLE__AUTO__SERIALIZER__CLASSES =
"portable-auto-serializable-classes";
public static final String CONFIGURE_PDX__PORTABLE__AUTO__SERIALIZER__CLASSES__HELP =
- "the patterns which are matched against domain class names to determine whether they should be serialized";
+ "The patterns that are matched against domain class names to determine whether they should be serialized. Serialization done by the auto-serializer will throw an exception if the object of these classes are not portable to non-java languages (check-portability=true).";
public static final String CONFIGURE_PDX__AUTO__SERIALIZER__CLASSES = "auto-serializable-classes";
public static final String CONFIGURE_PDX__AUTO__SERIALIZER__CLASSES__HELP =
- "the patterns which are matched against domain class names to determine whether they should be serialized, serialization done by the auto-serializer will throw an exception if the object of these classes are not portable to non-java languages";
+ "The patterns that are matched against domain class names to determine whether they should be auto-serialized. Serialization done by the auto-serializer will not throw an exception if the object of these classes are not portable to non-java languages (check-portability=false).";
+
public static final String CONFIGURE_PDX__NORMAL__MEMBERS__WARNING =
"The command would only take effect on new data members joining the distributed system. It won't affect the existing data members";
public static final String CONFIGURE_PDX__ERROR__MESSAGE =
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ConfigurePDXCommandIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ConfigurePDXCommandIntegrationTest.java
new file mode 100644
index 000000000000..b1288b0c60e2
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ConfigurePDXCommandIntegrationTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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.geode.management.internal.cli.commands;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.test.junit.categories.IntegrationTest;
+import org.apache.geode.test.junit.rules.GfshCommandRule;
+import org.apache.geode.test.junit.rules.LocatorStarterRule;
+
+@Category(IntegrationTest.class)
+public class ConfigurePDXCommandIntegrationTest {
+ private static final String BASE_COMMAND_STRING = "configure pdx ";
+
+ @Rule
+ public GfshCommandRule gfsh = new GfshCommandRule().withTimeout(1);
+
+ @Rule
+ public LocatorStarterRule locator = new LocatorStarterRule().withAutoStart().withJMXManager();
+
+ @Before
+ public void before() throws Exception {
+ gfsh.connectAndVerify(locator);
+ }
+
+ @Test
+ @Ignore("See https://issues.apache.org/jira/browse/GEODE-4794")
+ public void commandShouldSucceedWhenUsingDefaults() {
+ gfsh.executeAndAssertThat(BASE_COMMAND_STRING).statusIsSuccess().hasNoFailToPersistError();
+ }
+
+ @Test
+ public void commandShouldFailWhenNotConnected() throws Exception {
+ gfsh.disconnect();
+ gfsh.executeAndAssertThat(BASE_COMMAND_STRING).statusIsError().containsOutput("Command",
+ "was found but is not currently available");
+ }
+
+ @Test
+ public void commandShouldSucceedWhenConfiguringAutoSerializableClassesWithPersistence() {
+ gfsh.executeAndAssertThat(BASE_COMMAND_STRING
+ + "--read-serialized=true --disk-store=myDiskStore --ignore-unread-fields=true --auto-serializable-classes=com.company.DomainObject.*#identity=id")
+ .statusIsSuccess().hasNoFailToPersistError();
+
+ String sharedConfigXml = locator.getLocator().getSharedConfiguration()
+ .getConfiguration("cluster").getCacheXmlContent();
+ assertThat(sharedConfigXml).contains(
+ "");
+ assertThat(sharedConfigXml).contains("",
+ "org.apache.geode.pdx.ReflectionBasedAutoSerializer",
+ "",
+ "com.company.DomainObject.*, com.company.DomainObject.*#identity=id",
+ "", "");
+ assertThat(sharedConfigXml).contains("");
+ }
+
+ @Test
+ public void commandShouldSucceedWhenConfiguringAutoSerializableClassesWithoutPersistence() {
+ gfsh.executeAndAssertThat(BASE_COMMAND_STRING
+ + "--read-serialized=false --ignore-unread-fields=false --auto-serializable-classes=com.company.DomainObject.*#identity=id")
+ .statusIsSuccess().hasNoFailToPersistError();
+
+ String sharedConfigXml = locator.getLocator().getSharedConfiguration()
+ .getConfiguration("cluster").getCacheXmlContent();
+ assertThat(sharedConfigXml).contains("");
+ assertThat(sharedConfigXml).contains("",
+ "org.apache.geode.pdx.ReflectionBasedAutoSerializer",
+ "",
+ "com.company.DomainObject.*, com.company.DomainObject.*#identity=id",
+ "", "");
+ assertThat(sharedConfigXml).contains("");
+ }
+
+ @Test
+ public void commandShouldSucceedWhenConfiguringPortableAutoSerializableClassesWithPersistence() {
+ gfsh.executeAndAssertThat(BASE_COMMAND_STRING
+ + "--read-serialized=true --disk-store=myDiskStore --ignore-unread-fields=true --portable-auto-serializable-classes=com.company.DomainObject.*#identity=id")
+ .statusIsSuccess().hasNoFailToPersistError();
+
+ String sharedConfigXml = locator.getLocator().getSharedConfiguration()
+ .getConfiguration("cluster").getCacheXmlContent();
+ assertThat(sharedConfigXml).contains(
+ "");
+ assertThat(sharedConfigXml).contains("")
+ .contains("true").contains("");
+ assertThat(sharedConfigXml).contains("",
+ "org.apache.geode.pdx.ReflectionBasedAutoSerializer",
+ "",
+ "com.company.DomainObject.*, com.company.DomainObject.*#identity=id",
+ "", "");
+ assertThat(sharedConfigXml).contains("");
+ }
+
+ @Test
+ public void commandShouldSucceedWhenConfiguringPortableAutoSerializableClassesWithoutPersistence() {
+ gfsh.executeAndAssertThat(BASE_COMMAND_STRING
+ + "--read-serialized=false --ignore-unread-fields=false --portable-auto-serializable-classes=com.company.DomainObject.*#identity=id")
+ .statusIsSuccess().hasNoFailToPersistError();
+
+ String sharedConfigXml = locator.getLocator().getSharedConfiguration()
+ .getConfiguration("cluster").getCacheXmlContent();
+ assertThat(sharedConfigXml).contains("");
+ assertThat(sharedConfigXml).contains("")
+ .contains("true").contains("");
+ assertThat(sharedConfigXml).contains("",
+ "org.apache.geode.pdx.ReflectionBasedAutoSerializer",
+ "",
+ "com.company.DomainObject.*, com.company.DomainObject.*#identity=id",
+ "", "");
+ assertThat(sharedConfigXml).contains("");
+ }
+}
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ConfigurePDXCommandTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ConfigurePDXCommandTest.java
new file mode 100644
index 000000000000..bfd5a61716c0
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/ConfigurePDXCommandTest.java
@@ -0,0 +1,379 @@
+/*
+ * 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.geode.management.internal.cli.commands;
+
+import static org.apache.geode.internal.cache.CacheConfig.DEFAULT_PDX_IGNORE_UNREAD_FIELDS;
+import static org.apache.geode.internal.cache.CacheConfig.DEFAULT_PDX_PERSISTENT;
+import static org.apache.geode.internal.cache.CacheConfig.DEFAULT_PDX_READ_SERIALIZED;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.distributed.internal.ClusterConfigurationService;
+import org.apache.geode.internal.cache.CacheConfig;
+import org.apache.geode.internal.cache.InternalCache;
+import org.apache.geode.internal.cache.xmlcache.CacheCreation;
+import org.apache.geode.management.internal.cli.result.CommandResult;
+import org.apache.geode.management.internal.configuration.domain.XmlEntity;
+import org.apache.geode.test.junit.assertions.CommandResultAssert;
+import org.apache.geode.test.junit.categories.UnitTest;
+import org.apache.geode.test.junit.rules.GfshParserRule;
+
+@Category(UnitTest.class)
+public class ConfigurePDXCommandTest {
+ private static final String BASE_COMMAND_STRING = "configure pdx ";
+
+ @ClassRule
+ public static CustomGfshParserRule gfshParserRule = new CustomGfshParserRule();
+
+ private InternalCache cache;
+ private XmlEntity xmlEntity;
+ private CacheCreation cacheCreation;
+ private ConfigurePDXCommand command;
+ private ClusterConfigurationService clusterConfigurationService;
+
+ @Before
+ public void setUp() throws Exception {
+ cache = mock(InternalCache.class);
+ xmlEntity = mock(XmlEntity.class);
+ command = spy(ConfigurePDXCommand.class);
+ cacheCreation = spy(CacheCreation.class);
+ clusterConfigurationService = mock(ClusterConfigurationService.class);
+
+ doReturn(cache).when(command).getCache();
+ doReturn(xmlEntity).when(command).createXmlEntity(any());
+ doReturn(cacheCreation).when(command).getCacheCreation(anyBoolean());
+ doReturn(Collections.emptySet()).when(command).getAllNormalMembers();
+ doReturn(clusterConfigurationService).when(command).getSharedConfiguration();
+ }
+
+ @Test
+ public void parsingShouldSucceedWithoutArguments() {
+ assertThat(gfshParserRule.parse(BASE_COMMAND_STRING)).isNotNull();
+ }
+
+ @Test
+ public void parsingAutoCompleteShouldSucceed() throws Exception {
+ GfshParserRule.CommandCandidate candidate = gfshParserRule.complete(BASE_COMMAND_STRING);
+
+ assertThat(candidate).isNotNull();
+ assertThat(candidate.getCandidates()).isNotNull();
+ assertThat(candidate.getCandidates().size()).isEqualTo(5);
+ }
+
+ @Test
+ public void executionShouldHandleInternalFailures() {
+ doThrow(new RuntimeException("Can't create CacheCreation.")).when(command)
+ .getCacheCreation(anyBoolean());
+ gfshParserRule.executeAndAssertThat(command, BASE_COMMAND_STRING).statusIsError()
+ .containsOutput("Could not process command due to error. Can't create CacheCreation.");
+ doReturn(cacheCreation).when(command).getCacheCreation(anyBoolean());
+
+ doThrow(new RuntimeException("Can't find members.")).when(command).getAllNormalMembers();
+ gfshParserRule.executeAndAssertThat(command, BASE_COMMAND_STRING).statusIsError()
+ .containsOutput("Could not process command due to error. Can't find members.");
+ doReturn(Collections.emptySet()).when(command).getAllNormalMembers();
+
+ doThrow(new RuntimeException("Can't create XmlEntity.")).when(command).createXmlEntity(any());
+ gfshParserRule.executeAndAssertThat(command, BASE_COMMAND_STRING).statusIsError()
+ .containsOutput("Could not process command due to error. Can't create XmlEntity.");
+ doReturn(xmlEntity).when(command).createXmlEntity(any());
+
+ doThrow(new RuntimeException("Can't create ReflectionBasedAutoSerializer.")).when(command)
+ .createReflectionBasedAutoSerializer(anyBoolean(), any());
+ gfshParserRule
+ .executeAndAssertThat(command,
+ BASE_COMMAND_STRING + "--auto-serializable-classes=" + new String[] {})
+ .statusIsError().containsOutput(
+ "Could not process command due to error. Can't create ReflectionBasedAutoSerializer.");
+ gfshParserRule
+ .executeAndAssertThat(command,
+ BASE_COMMAND_STRING + "--portable-auto-serializable-classes=" + new String[] {})
+ .statusIsError().containsOutput(
+ "Could not process command due to error. Can't create ReflectionBasedAutoSerializer.");
+
+ verify(command, times(0)).persistClusterConfiguration(any(), any());
+ }
+
+ @Test
+ public void executionShouldFailIfBothPortableAndNonPortableClassesParametersAreSpecifiedAtTheSameTime() {
+ gfshParserRule
+ .executeAndAssertThat(command,
+ BASE_COMMAND_STRING
+ + "--auto-serializable-classes=org.apache.geode --portable-auto-serializable-classes=org.apache.geode")
+ .statusIsError().containsOutput(
+ "The autoserializer cannot support both portable and non-portable classes at the same time.");
+
+ verify(command, times(0)).persistClusterConfiguration(any(), any());
+ }
+
+ @Test
+ public void executionShouldIncludeWarningMessageWhenThereAreMembersAlreadyRunning() {
+ Set members = new HashSet<>();
+ DistributedMember mockMember = mock(DistributedMember.class);
+ when(mockMember.getId()).thenReturn("member0");
+ members.add(mockMember);
+ doReturn(xmlEntity).when(command).createXmlEntity(any());
+ doReturn(members).when(command).getAllNormalMembers();
+
+ gfshParserRule.executeAndAssertThat(command, BASE_COMMAND_STRING).statusIsSuccess()
+ .hasDefaultsConfigured(command, cacheCreation).containsOutput(
+ "The command would only take effect on new data members joining the distributed system. It won't affect the existing data members");
+ }
+
+ @Test
+ public void executionShouldWorkCorrectlyWhenDefaultsAreUsed() {
+ // Factory Default
+ gfshParserRule.executeAndAssertThat(command, BASE_COMMAND_STRING).statusIsSuccess()
+ .hasNoFailToPersistError().hasDefaultsConfigured(command, cacheCreation);
+ }
+
+ @Test
+ public void executionShouldCorrectlyConfigurePersistenceWhenDefaultDiskStoreIsUsed() {
+ // Default Disk Store
+ gfshParserRule.executeAndAssertThat(command, BASE_COMMAND_STRING + "--disk-store")
+ .statusIsSuccess().hasNoFailToPersistError()
+ .hasReadSerializedConfigured(DEFAULT_PDX_READ_SERIALIZED, cacheCreation)
+ .hasIgnoreUnreadFieldsConfigured(DEFAULT_PDX_IGNORE_UNREAD_FIELDS, cacheCreation)
+ .hasPersistenseConfigured(true, "DEFAULT", cacheCreation);
+
+ verify(cacheCreation, times(0)).setPdxSerializer(any());
+ verify(command, times(1)).persistClusterConfiguration(any(), any());
+ verify(command, times(0)).createReflectionBasedAutoSerializer(anyBoolean(), any());
+ }
+
+ @Test
+ public void executionShouldCorrectlyConfigurePersistenceWhenCustomDiskStoreIsUsed() {
+ // Custom Disk Store
+ gfshParserRule.executeAndAssertThat(command, BASE_COMMAND_STRING + "--disk-store=myDiskStore")
+ .statusIsSuccess().hasNoFailToPersistError()
+ .hasReadSerializedConfigured(DEFAULT_PDX_READ_SERIALIZED, cacheCreation)
+ .hasIgnoreUnreadFieldsConfigured(DEFAULT_PDX_IGNORE_UNREAD_FIELDS, cacheCreation)
+ .hasPersistenseConfigured(true, "myDiskStore", cacheCreation);
+
+ verify(cacheCreation, times(0)).setPdxSerializer(any());
+ verify(command, times(1)).persistClusterConfiguration(any(), any());
+ verify(command, times(0)).createReflectionBasedAutoSerializer(anyBoolean(), any());
+ }
+
+ @Test
+ public void executionShouldCorrectlyConfigureReadSerializedWhenFlagIsSetAsTrue() {
+ // Custom Configuration as True
+ gfshParserRule.executeAndAssertThat(command, BASE_COMMAND_STRING + "--read-serialized=true")
+ .statusIsSuccess().hasNoFailToPersistError()
+ .hasReadSerializedConfigured(true, cacheCreation)
+ .hasIgnoreUnreadFieldsConfigured(DEFAULT_PDX_IGNORE_UNREAD_FIELDS, cacheCreation)
+ .hasPersistenseConfigured(DEFAULT_PDX_PERSISTENT, null, cacheCreation);
+
+ verify(cacheCreation, times(0)).setPdxSerializer(any());
+ verify(command, times(1)).persistClusterConfiguration(any(), any());
+ verify(command, times(0)).createReflectionBasedAutoSerializer(anyBoolean(), any());
+ }
+
+ @Test
+ public void executionShouldCorrectlyConfigureReadSerializedWhenFlagIsSetAsFalse() {
+ // Custom Configuration as False
+ gfshParserRule.executeAndAssertThat(command, BASE_COMMAND_STRING + "--read-serialized=false")
+ .statusIsSuccess().hasNoFailToPersistError()
+ .hasReadSerializedConfigured(false, cacheCreation)
+ .hasIgnoreUnreadFieldsConfigured(DEFAULT_PDX_IGNORE_UNREAD_FIELDS, cacheCreation)
+ .hasPersistenseConfigured(DEFAULT_PDX_PERSISTENT, null, cacheCreation);
+
+ verify(cacheCreation, times(0)).setPdxSerializer(any());
+ verify(command, times(1)).persistClusterConfiguration(any(), any());
+ verify(command, times(0)).createReflectionBasedAutoSerializer(anyBoolean(), any());
+ }
+
+ @Test
+ public void executionShouldCorrectlyConfigureIgnoreUnreadFieldsWhenFlagIsSetAsTrue() {
+ // Custom Configuration as True
+ gfshParserRule
+ .executeAndAssertThat(command, BASE_COMMAND_STRING + "--ignore-unread-fields=true")
+ .statusIsSuccess().hasNoFailToPersistError()
+ .hasReadSerializedConfigured(DEFAULT_PDX_READ_SERIALIZED, cacheCreation)
+ .hasIgnoreUnreadFieldsConfigured(true, cacheCreation)
+ .hasPersistenseConfigured(DEFAULT_PDX_PERSISTENT, null, cacheCreation);
+
+ verify(cacheCreation, times(0)).setPdxSerializer(any());
+ verify(command, times(1)).persistClusterConfiguration(any(), any());
+ verify(command, times(0)).createReflectionBasedAutoSerializer(anyBoolean(), any());
+ }
+
+ @Test
+ public void executionShouldCorrectlyConfigureIgnoreUnreadFieldsWhenFlagIsSetAsFalse() {
+ // Custom Configuration as False
+ gfshParserRule
+ .executeAndAssertThat(command, BASE_COMMAND_STRING + "--ignore-unread-fields=false")
+ .statusIsSuccess().hasNoFailToPersistError()
+ .hasReadSerializedConfigured(DEFAULT_PDX_READ_SERIALIZED, cacheCreation)
+ .hasIgnoreUnreadFieldsConfigured(false, cacheCreation)
+ .hasPersistenseConfigured(DEFAULT_PDX_PERSISTENT, null, cacheCreation);
+
+ verify(cacheCreation, times(0)).setPdxSerializer(any());
+ verify(command, times(1)).persistClusterConfiguration(any(), any());
+ verify(command, times(0)).createReflectionBasedAutoSerializer(anyBoolean(), any());
+ }
+
+ @Test
+ public void executionShouldCorrectlyConfigurePortableAutoSerializableClassesWhenUsingCustomPattern() {
+ String[] patterns = new String[] {"com.company.DomainObject.*#identity=id"};
+
+ // Custom Settings
+ gfshParserRule
+ .executeAndAssertThat(command,
+ BASE_COMMAND_STRING + "--portable-auto-serializable-classes=" + patterns[0])
+ .statusIsSuccess().hasNoFailToPersistError()
+ .hasReadSerializedConfigured(DEFAULT_PDX_READ_SERIALIZED, cacheCreation)
+ .hasIgnoreUnreadFieldsConfigured(DEFAULT_PDX_IGNORE_UNREAD_FIELDS, cacheCreation)
+ .hasPersistenseConfigured(DEFAULT_PDX_PERSISTENT, null, cacheCreation)
+ .containsOutput("Portable Classes = [com.company.DomainObject.*#identity=id]")
+ .containsOutput("PDX Serializer = org.apache.geode.pdx.ReflectionBasedAutoSerializer");
+
+ verify(cacheCreation, times(1)).setPdxSerializer(any());
+ verify(command, times(1)).persistClusterConfiguration(any(), any());
+ verify(command, times(1)).createReflectionBasedAutoSerializer(true, patterns);
+ }
+
+ @Test
+ public void executionShouldCorrectlyConfigureAutoSerializableClassesWhenUsingCustomPattern() {
+ String[] patterns = new String[] {"com.company.DomainObject.*#identity=id"};
+
+ // Custom Settings
+ gfshParserRule
+ .executeAndAssertThat(command,
+ BASE_COMMAND_STRING + "--auto-serializable-classes=" + patterns[0])
+ .statusIsSuccess().hasNoFailToPersistError()
+ .hasReadSerializedConfigured(CacheConfig.DEFAULT_PDX_READ_SERIALIZED, cacheCreation)
+ .hasIgnoreUnreadFieldsConfigured(CacheConfig.DEFAULT_PDX_IGNORE_UNREAD_FIELDS,
+ cacheCreation)
+ .hasPersistenseConfigured(CacheConfig.DEFAULT_PDX_PERSISTENT, null, cacheCreation)
+ .containsOutput("Non Portable Classes = [com.company.DomainObject.*#identity=id]")
+ .containsOutput("PDX Serializer = org.apache.geode.pdx.ReflectionBasedAutoSerializer");
+
+ verify(cacheCreation, times(1)).setPdxSerializer(any());
+ verify(command, times(1)).persistClusterConfiguration(any(), any());
+ verify(command, times(1)).createReflectionBasedAutoSerializer(false, patterns);
+ }
+
+ static class CustomGfshParserRule extends GfshParserRule {
+ @Override
+ public CustomResultAssert executeAndAssertThat(T instance, String command) {
+ CommandResultAssert resultAssert = super.executeAndAssertThat(instance, command);;
+
+ return new CustomResultAssert(resultAssert.getCommandResult());
+ }
+ }
+
+ static class CustomResultAssert extends CommandResultAssert {
+ public CustomResultAssert(CommandResult commandResult) {
+ super(commandResult);
+ }
+
+ @Override
+ public CustomResultAssert statusIsError() {
+ super.statusIsError();
+
+ return this;
+ }
+
+ @Override
+ public CustomResultAssert statusIsSuccess() {
+ super.statusIsSuccess();
+
+ return this;
+ }
+
+ @Override
+ public CustomResultAssert containsOutput(String... expectedOutputs) {
+ super.containsOutput(expectedOutputs);
+
+ return this;
+ }
+
+ @Override
+ public CustomResultAssert hasNoFailToPersistError() {
+ super.hasNoFailToPersistError();
+
+ return this;
+ }
+
+ public CustomResultAssert hasPersistenseConfigured(boolean persistenceEnabled,
+ String diskStoreName, CacheCreation cache) {
+ assertThat(actual.getOutput()).contains("persistent = " + persistenceEnabled);
+
+ if (StringUtils.isNotEmpty(diskStoreName)) {
+ assertThat(actual.getOutput()).contains("disk-store = " + diskStoreName);
+ }
+
+ if (persistenceEnabled) {
+ verify(cache, times(1)).setPdxPersistent(true);
+ } else {
+ verify(cache, times(0)).setPdxPersistent(true);
+ }
+
+ return this;
+ }
+
+
+ public CustomResultAssert hasReadSerializedConfigured(boolean readSerializedEnabled,
+ CacheCreation cache) {
+ assertThat(actual.getOutput()).contains("read-serialized = " + readSerializedEnabled);
+ verify(cache, times(1)).setPdxReadSerialized(readSerializedEnabled);
+
+ return this;
+ }
+
+ public CustomResultAssert hasIgnoreUnreadFieldsConfigured(boolean ignoreUnreadFieldsEnabled,
+ CacheCreation cache) {
+ assertThat(actual.getOutput())
+ .contains("ignore-unread-fields = " + ignoreUnreadFieldsEnabled);
+ verify(cache, times(1)).setPdxIgnoreUnreadFields(ignoreUnreadFieldsEnabled);
+
+ return this;
+ }
+
+ public CustomResultAssert hasDefaultsConfigured(ConfigurePDXCommand command,
+ CacheCreation cacheCreation) {
+ hasNoFailToPersistError();
+ hasReadSerializedConfigured(DEFAULT_PDX_READ_SERIALIZED, cacheCreation);
+ hasIgnoreUnreadFieldsConfigured(DEFAULT_PDX_IGNORE_UNREAD_FIELDS, cacheCreation);
+ hasPersistenseConfigured(DEFAULT_PDX_PERSISTENT, null, cacheCreation);
+
+ verify(cacheCreation, times(0)).setPdxSerializer(any());
+ verify(command, times(1)).persistClusterConfiguration(any(), any());
+ verify(command, times(0)).createReflectionBasedAutoSerializer(anyBoolean(), any());
+
+ return this;
+ }
+ }
+}