You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by kl...@apache.org on 2019/03/29 16:21:25 UTC

[geode] branch develop updated: GEODE-6558: Add InternalDistributedSystem.Builder (#3354)

This is an automated email from the ASF dual-hosted git repository.

klund pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/develop by this push:
     new d7911d6  GEODE-6558: Add InternalDistributedSystem.Builder (#3354)
d7911d6 is described below

commit d7911d629c387c3d029185fcd64e25136fa08fb0
Author: Kirk Lund <kl...@apache.org>
AuthorDate: Fri Mar 29 09:21:10 2019 -0700

    GEODE-6558: Add InternalDistributedSystem.Builder (#3354)
    
    * Remove all but one constructor.
    * Replace newInstance methods with InternalDistributedSystem.Builder.
    * Replace newInstanceForTesting methods with
    InternalDistributedSystem.BuilderForTesting.
    * Replace public static boolean var ALLOW_MULTIPLE_SYSTEMS with usage
    of Boolean.getBoolean(ALLOW_MULTIPLE_SYSTEMS_PROPERTY) in
    connectInternal.
    
    Most code paths are using DistributedSystem.connect or
    InternalDistributedSystem.connectInternal to construct a system.
    connectInternal now uses InternalDistributedSystem.Builder.
    
    Several tests are using  InternalDistributedSystem.BuilderForTesting.
---
 ...utedSystemBuilderForTestingIntegrationTest.java |  56 ++++++
 ...nalDistributedSystemBuilderIntegrationTest.java |  68 +++++++
 .../InternalDistributedSystemJUnitTest.java        |   3 +-
 .../gms/fd/GMSHealthMonitorJUnitTest.java          |   5 +-
 .../gms/messenger/JGroupsMessengerJUnitTest.java   |   7 +-
 .../gms/mgr/GMSMembershipManagerJUnitTest.java     |   7 +-
 .../geode/pdx/internal/MultipleCacheJUnitTest.java |  18 +-
 .../internal/InternalDistributedSystem.java        | 207 ++++++++++-----------
 .../geode/internal/cache/InternalCacheBuilder.java |  10 +-
 .../InternalDistributedSystemIntegrationTest.java  |  84 +++++++++
 ...rnalDistributedSystemStatisticsManagerTest.java |  13 +-
 .../geode/internal/cache/GemFireCacheImplTest.java |  15 +-
 ...ernalCacheBuilderAllowsMultipleSystemsTest.java |  14 +-
 .../internal/cache/InternalCacheBuilderTest.java   |   2 -
 14 files changed, 360 insertions(+), 149 deletions(-)

diff --git a/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/InternalDistributedSystemBuilderForTestingIntegrationTest.java b/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/InternalDistributedSystemBuilderForTestingIntegrationTest.java
new file mode 100644
index 0000000..7a1ae86
--- /dev/null
+++ b/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/InternalDistributedSystemBuilderForTestingIntegrationTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.distributed.internal;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Properties;
+
+import org.junit.Test;
+
+import org.apache.geode.CancelCriterion;
+import org.apache.geode.internal.statistics.StatisticsManager;
+import org.apache.geode.internal.statistics.StatisticsManagerFactory;
+
+public class InternalDistributedSystemBuilderForTestingIntegrationTest {
+
+  @Test
+  public void builderForTesting() {
+    Properties configProperties = new Properties();
+
+    DistributionManager distributionManager = mock(DistributionManager.class);
+    when(distributionManager.getCancelCriterion()).thenReturn(mock(CancelCriterion.class));
+
+    StatisticsManager statisticsManager = mock(StatisticsManager.class);
+    StatisticsManagerFactory statisticsManagerFactory = mock(StatisticsManagerFactory.class);
+    when(statisticsManagerFactory.create(any(), anyLong(), anyBoolean()))
+        .thenReturn(statisticsManager);
+
+    InternalDistributedSystem system =
+        new InternalDistributedSystem.BuilderForTesting(configProperties)
+            .setDistributionManager(distributionManager)
+            .setStatisticsManagerFactory(statisticsManagerFactory)
+            .build();
+
+    assertThat(system.isConnected()).isTrue();
+    assertThat(system.getDistributionManager()).isSameAs(distributionManager);
+    assertThat(system.getStatisticsManager()).isSameAs(statisticsManager);
+  }
+}
diff --git a/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/InternalDistributedSystemBuilderIntegrationTest.java b/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/InternalDistributedSystemBuilderIntegrationTest.java
new file mode 100644
index 0000000..3cc9590
--- /dev/null
+++ b/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/InternalDistributedSystemBuilderIntegrationTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.distributed.internal;
+
+import static org.apache.geode.distributed.ConfigurationProperties.NAME;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+import java.util.Properties;
+
+import org.junit.After;
+import org.junit.Test;
+
+import org.apache.geode.security.PostProcessor;
+import org.apache.geode.security.SecurityManager;
+
+public class InternalDistributedSystemBuilderIntegrationTest {
+
+  private InternalDistributedSystem system;
+
+  @After
+  public void tearDown() {
+    system.disconnect();
+  }
+
+  @Test
+  public void buildBuildsAndInitializesSystem() {
+    String theName = "theName";
+    Properties configProperties = new Properties();
+    configProperties.setProperty(NAME, theName);
+
+    system = new InternalDistributedSystem.Builder(configProperties)
+        .build();
+
+    assertThat(system.isConnected()).isTrue();
+    assertThat(system.getName()).isEqualTo(theName);
+  }
+
+  @Test
+  public void buildUsesSecurityConfig() {
+    SecurityManager theSecurityManager = mock(SecurityManager.class);
+    PostProcessor thePostProcessor = mock(PostProcessor.class);
+
+    SecurityConfig securityConfig = new SecurityConfig(theSecurityManager, thePostProcessor);
+    Properties configProperties = new Properties();
+
+    system = new InternalDistributedSystem.Builder(configProperties)
+        .setSecurityConfig(securityConfig)
+        .build();
+
+    assertThat(system.getSecurityService().getSecurityManager())
+        .isSameAs(theSecurityManager);
+    assertThat(system.getSecurityService().getPostProcessor())
+        .isSameAs(thePostProcessor);
+  }
+}
diff --git a/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/InternalDistributedSystemJUnitTest.java b/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/InternalDistributedSystemJUnitTest.java
index ef19a68..d310a47 100644
--- a/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/InternalDistributedSystemJUnitTest.java
+++ b/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/InternalDistributedSystemJUnitTest.java
@@ -642,7 +642,8 @@ public class InternalDistributedSystemJUnitTest {
     props.setProperty(MCAST_PORT, "0");
     props.setProperty(LOCATORS, "");
     Config config1 = new DistributionConfigImpl(props, false);
-    InternalDistributedSystem sys = InternalDistributedSystem.newInstance(config1.toProperties());
+    InternalDistributedSystem sys =
+        new InternalDistributedSystem.Builder(config1.toProperties()).build();
     try {
 
       props.put(MCAST_PORT, "1");
diff --git a/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/membership/gms/fd/GMSHealthMonitorJUnitTest.java b/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/membership/gms/fd/GMSHealthMonitorJUnitTest.java
index dbbd332..d80b424 100644
--- a/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/membership/gms/fd/GMSHealthMonitorJUnitTest.java
+++ b/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/membership/gms/fd/GMSHealthMonitorJUnitTest.java
@@ -135,8 +135,9 @@ public class GMSHealthMonitorJUnitTest {
     nonDefault.put(LOCATORS, "localhost[10344]");
     DistributionManager dm = mock(DistributionManager.class);
     SocketCreatorFactory.setDistributionConfig(new DistributionConfigImpl(new Properties()));
-    InternalDistributedSystem system =
-        InternalDistributedSystem.newInstanceForTesting(dm, nonDefault);
+    InternalDistributedSystem system = new InternalDistributedSystem.BuilderForTesting(nonDefault)
+        .setDistributionManager(dm)
+        .build();
 
     when(mockConfig.getDistributionConfig()).thenReturn(mockDistConfig);
     when(mockConfig.getMemberTimeout()).thenReturn(memberTimeout);
diff --git a/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessengerJUnitTest.java b/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessengerJUnitTest.java
index d5239e8..e560312 100755
--- a/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessengerJUnitTest.java
+++ b/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/membership/gms/messenger/JGroupsMessengerJUnitTest.java
@@ -103,6 +103,7 @@ import org.apache.geode.internal.Version;
 import org.apache.geode.internal.admin.remote.RemoteTransportConfig;
 import org.apache.geode.internal.alerting.AlertingAction;
 import org.apache.geode.internal.cache.DistributedCacheOperation;
+import org.apache.geode.internal.statistics.StatisticsRegistry;
 import org.apache.geode.test.junit.categories.MembershipTest;
 
 @Category({MembershipTest.class})
@@ -166,7 +167,11 @@ public class JGroupsMessengerJUnitTest {
 
     DistributionManager dm = mock(DistributionManager.class);
     InternalDistributedSystem system =
-        InternalDistributedSystem.newInstanceForTesting(dm, nonDefault);
+        new InternalDistributedSystem.BuilderForTesting(nonDefault)
+            .setDistributionManager(dm)
+            .setStatisticsManagerFactory(
+                (name, startTime, statsDisabled) -> new StatisticsRegistry(name, startTime))
+            .build();
     when(services.getStatistics()).thenReturn(new DistributionStats(system, statsId));
 
     messenger = new JGroupsMessenger();
diff --git a/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/membership/gms/mgr/GMSMembershipManagerJUnitTest.java b/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/membership/gms/mgr/GMSMembershipManagerJUnitTest.java
index 5aa4b46..9fa2efe 100644
--- a/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/membership/gms/mgr/GMSMembershipManagerJUnitTest.java
+++ b/geode-core/src/integrationTest/java/org/apache/geode/distributed/internal/membership/gms/mgr/GMSMembershipManagerJUnitTest.java
@@ -82,6 +82,7 @@ import org.apache.geode.distributed.internal.membership.gms.interfaces.Messenger
 import org.apache.geode.distributed.internal.membership.gms.mgr.GMSMembershipManager.StartupEvent;
 import org.apache.geode.internal.admin.remote.AlertListenerMessage;
 import org.apache.geode.internal.admin.remote.RemoteTransportConfig;
+import org.apache.geode.internal.statistics.DummyStatisticsRegistry;
 import org.apache.geode.internal.tcp.ConnectExceptions;
 import org.apache.geode.test.junit.categories.MembershipTest;
 
@@ -422,7 +423,11 @@ public class GMSMembershipManagerJUnitTest {
     DMStats stats = mock(DMStats.class);
 
     InternalDistributedSystem system =
-        InternalDistributedSystem.newInstanceForTesting(dm, distProperties);
+        new InternalDistributedSystem.BuilderForTesting(distProperties)
+            .setDistributionManager(dm)
+            .setStatisticsManagerFactory(
+                (name, startTime, statsDisabled) -> new DummyStatisticsRegistry(name, startTime))
+            .build();
 
     when(dm.getStats()).thenReturn(stats);
     when(dm.getSystem()).thenReturn(system);
diff --git a/geode-core/src/integrationTest/java/org/apache/geode/pdx/internal/MultipleCacheJUnitTest.java b/geode-core/src/integrationTest/java/org/apache/geode/pdx/internal/MultipleCacheJUnitTest.java
index 9b970b6..915a969 100644
--- a/geode-core/src/integrationTest/java/org/apache/geode/pdx/internal/MultipleCacheJUnitTest.java
+++ b/geode-core/src/integrationTest/java/org/apache/geode/pdx/internal/MultipleCacheJUnitTest.java
@@ -17,6 +17,7 @@ package org.apache.geode.pdx.internal;
 import static org.apache.geode.cache.RegionShortcut.REPLICATE;
 import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
 import static org.apache.geode.distributed.ConfigurationProperties.NAME;
+import static org.apache.geode.distributed.internal.InternalDistributedSystem.ALLOW_MULTIPLE_SYSTEMS_PROPERTY;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
@@ -32,6 +33,7 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.contrib.java.lang.system.RestoreSystemProperties;
 import org.junit.experimental.categories.Category;
 import org.junit.rules.TemporaryFolder;
 
@@ -51,6 +53,9 @@ import org.apache.geode.test.junit.categories.ClientServerTest;
 public class MultipleCacheJUnitTest {
 
   @Rule
+  public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
+
+  @Rule
   public TemporaryFolder locatorFolder = new TemporaryFolder();
 
   private List<Cache> caches = new ArrayList<>();
@@ -60,7 +65,7 @@ public class MultipleCacheJUnitTest {
 
   @Before
   public void startLocator() throws IOException {
-    InternalDistributedSystem.ALLOW_MULTIPLE_SYSTEMS = true;
+    System.setProperty(ALLOW_MULTIPLE_SYSTEMS_PROPERTY, "true");
 
     connectListener = mock(ConnectListener.class);
     InternalDistributedSystem.addConnectListener(connectListener);
@@ -72,13 +77,9 @@ public class MultipleCacheJUnitTest {
 
   @After
   public void closeSystemsAndLocator() {
-    try {
-      InternalDistributedSystem.removeConnectListener(connectListener);
-      caches.forEach(Cache::close);
-      locator.stop();
-    } finally {
-      InternalDistributedSystem.ALLOW_MULTIPLE_SYSTEMS = false;
-    }
+    InternalDistributedSystem.removeConnectListener(connectListener);
+    caches.forEach(Cache::close);
+    locator.stop();
   }
 
   @Test
@@ -94,7 +95,6 @@ public class MultipleCacheJUnitTest {
     assertThat(cache2).isNotSameAs(cache1);
 
     DistributedMember member1 = cache1.getDistributedSystem().getDistributedMember();
-
     DistributedMember member2 = cache2.getDistributedSystem().getDistributedMember();
 
     assertThat(member2).isNotEqualTo(member1);
diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalDistributedSystem.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalDistributedSystem.java
index dd65470..af5a73e 100644
--- a/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalDistributedSystem.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalDistributedSystem.java
@@ -12,7 +12,6 @@
  * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
-
 package org.apache.geode.distributed.internal;
 
 import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
@@ -58,6 +57,7 @@ import org.apache.geode.StatisticsType;
 import org.apache.geode.SystemConnectException;
 import org.apache.geode.SystemFailure;
 import org.apache.geode.annotations.Immutable;
+import org.apache.geode.annotations.VisibleForTesting;
 import org.apache.geode.annotations.internal.MakeNotStatic;
 import org.apache.geode.annotations.internal.MutableForTesting;
 import org.apache.geode.cache.CacheClosedException;
@@ -146,13 +146,6 @@ public class InternalDistributedSystem extends DistributedSystem
       GEMFIRE_PREFIX + "ALLOW_MULTIPLE_SYSTEMS";
 
   /**
-   * Feature flag to enable multiple caches within a JVM.
-   */
-  @MutableForTesting
-  public static boolean ALLOW_MULTIPLE_SYSTEMS =
-      Boolean.getBoolean(ALLOW_MULTIPLE_SYSTEMS_PROPERTY);
-
-  /**
    * If auto-reconnect is going on this will hold a reference to it
    */
   @MakeNotStatic
@@ -195,6 +188,7 @@ public class InternalDistributedSystem extends DistributedSystem
   /**
    * If the experimental multiple-system feature is enabled, always create a new system.
    *
+   * <p>
    * Otherwise, create a new InternalDistributedSystem with the given properties, or connect to an
    * existing one with the same properties.
    */
@@ -204,8 +198,10 @@ public class InternalDistributedSystem extends DistributedSystem
       config = new Properties();
     }
 
-    if (ALLOW_MULTIPLE_SYSTEMS) {
-      return InternalDistributedSystem.newInstance(config);
+    if (Boolean.getBoolean(ALLOW_MULTIPLE_SYSTEMS_PROPERTY)) {
+      return new Builder(config)
+          .setSecurityConfig(securityConfig)
+          .build();
     }
 
     synchronized (existingSystemsLock) {
@@ -253,8 +249,9 @@ public class InternalDistributedSystem extends DistributedSystem
       }
 
       // Make a new connection to the distributed system
-      InternalDistributedSystem newSystem =
-          InternalDistributedSystem.newInstance(config, securityConfig);
+      InternalDistributedSystem newSystem = new Builder(config)
+          .setSecurityConfig(securityConfig)
+          .build();
       addSystem(newSystem);
       return newSystem;
     }
@@ -417,79 +414,6 @@ public class InternalDistributedSystem extends DistributedSystem
     this.deltaEnabledOnServer = deltaEnabledOnServer;
   }
 
-  ///////////////////// Static Methods /////////////////////
-
-  /**
-   * Creates a new instance of <code>InternalDistributedSystem</code> with the given configuration.
-   */
-  public static InternalDistributedSystem newInstance(Properties config) {
-    return newInstance(config, null);
-  }
-
-  public static InternalDistributedSystem newInstance(Properties config,
-      SecurityConfig securityConfig) {
-    if (securityConfig == null) {
-      return newInstance(config, null, null);
-    } else {
-      return newInstance(config, securityConfig.getSecurityManager(),
-          securityConfig.getPostProcessor());
-    }
-  }
-
-  public static InternalDistributedSystem newInstance(Properties config,
-      SecurityManager securityManager, PostProcessor postProcessor) {
-    boolean success = false;
-    InternalDataSerializer.checkSerializationVersion();
-    try {
-      SystemFailure.startThreads();
-      InternalDistributedSystem newSystem = new InternalDistributedSystem(config);
-      newSystem.initialize(securityManager, postProcessor);
-      reconnectAttemptCounter = 0; // reset reconnect count since we just got a new connection
-      notifyConnectListeners(newSystem);
-      success = true;
-      return newSystem;
-    } finally {
-      if (!success) {
-        SystemFailure.stopThreads();
-      }
-    }
-  }
-
-  /**
-   * Creates a non-functional instance for testing.
-   *
-   * @param distributionManager the distribution manager for the test instance
-   * @param properties properties to configure the test instance
-   */
-  public static InternalDistributedSystem newInstanceForTesting(
-      DistributionManager distributionManager, Properties properties) {
-    StatisticsManagerFactory statisticsManagerFactory = defaultStatisticsManagerFactory();
-
-    return newInstanceForTesting(
-        distributionManager, properties, statisticsManagerFactory);
-  }
-
-  /**
-   * Creates a non-functional instance for testing.
-   *
-   * @param distributionManager the distribution manager for the test instance
-   * @param properties properties to configure the test instance
-   * @param statisticsManagerFactory the statistics manager factory for the test instance
-   */
-  static InternalDistributedSystem newInstanceForTesting(DistributionManager distributionManager,
-      Properties properties, StatisticsManagerFactory statisticsManagerFactory) {
-    ConnectionConfigImpl connectionConfig = new ConnectionConfigImpl(properties);
-
-    InternalDistributedSystem internalDistributedSystem =
-        new InternalDistributedSystem(connectionConfig, statisticsManagerFactory);
-
-    internalDistributedSystem.config = new RuntimeDistributionConfigImpl(internalDistributedSystem);
-    internalDistributedSystem.dm = distributionManager;
-    internalDistributedSystem.isConnected = true;
-
-    return internalDistributedSystem;
-  }
-
   public static boolean removeSystem(InternalDistributedSystem oldSystem) {
     return DistributedSystem.removeSystem(oldSystem);
   }
@@ -595,32 +519,8 @@ public class InternalDistributedSystem extends DistributedSystem
   }
 
   /**
-   * Creates a new {@code InternalDistributedSystem} with the given configuration properties.
-   * Does all of the magic of finding the "default" values of properties.
-   * <p>
-   * See {@link #connect} for a list of exceptions that may be thrown.
-   *
-   * @param configurationProperties properties to configure the connection
-   */
-  private InternalDistributedSystem(Properties configurationProperties) {
-    this(new ConnectionConfigImpl(configurationProperties));
-  }
-
-  /**
    * Creates a new {@code InternalDistributedSystem} with the given configuration.
-   * <p>
-   * See {@link #connect} for a list of exceptions that may be thrown.
    *
-   * @param config the configuration for the connection
-   */
-  private InternalDistributedSystem(ConnectionConfig config) {
-    this(config, defaultStatisticsManagerFactory());
-    isReconnectingDS = config.isReconnecting();
-    quorumChecker = config.quorumChecker();
-  }
-
-  /**
-   * Creates a new {@code InternalDistributedSystem} with the given configuration.
    * <p>
    * See {@link #connect} for a list of exceptions that may be thrown.
    *
@@ -639,6 +539,8 @@ public class InternalDistributedSystem extends DistributedSystem
     DSFIDFactory.registerTypes();
 
     originalConfig = config.distributionConfig();
+    isReconnectingDS = config.isReconnecting();
+    quorumChecker = config.quorumChecker();
 
     ((DistributionConfigImpl) this.originalConfig).checkForDisallowedDefaults(); // throws
                                                                                  // IllegalStateEx
@@ -653,8 +555,6 @@ public class InternalDistributedSystem extends DistributedSystem
         statisticsManagerFactory.create(originalConfig.getName(), startTime, statsDisabled);
   }
 
-
-  //////////////////// Instance Methods ////////////////////
   public SecurityService getSecurityService() {
     return this.securityService;
   }
@@ -912,6 +812,7 @@ public class InternalDistributedSystem extends DistributedSystem
 
     this.reconnected = this.attemptingToReconnect;
     this.attemptingToReconnect = false;
+    reconnectAttemptCounter = 0; // reset reconnect count since we just got a new connection
   }
 
   private void startSampler() {
@@ -3059,4 +2960,88 @@ public class InternalDistributedSystem extends DistributedSystem
       }
     };
   }
+
+  public static class Builder {
+
+    private final Properties configProperties;
+
+    private SecurityConfig securityConfig;
+
+    public Builder(Properties configProperties) {
+      this.configProperties = configProperties;
+    }
+
+    public Builder setSecurityConfig(SecurityConfig securityConfig) {
+      this.securityConfig = securityConfig;
+      return this;
+    }
+
+    /**
+     * Builds and initializes new instance of InternalDistributedSystem.
+     */
+    public InternalDistributedSystem build() {
+      if (securityConfig == null) {
+        securityConfig = new SecurityConfig(null, null);
+      }
+
+      boolean stopThreads = true;
+      InternalDataSerializer.checkSerializationVersion();
+      try {
+        SystemFailure.startThreads();
+        InternalDistributedSystem newSystem =
+            new InternalDistributedSystem(new ConnectionConfigImpl(
+                configProperties), defaultStatisticsManagerFactory());
+        newSystem
+            .initialize(securityConfig.getSecurityManager(), securityConfig.getPostProcessor());
+        notifyConnectListeners(newSystem);
+        stopThreads = false;
+        return newSystem;
+      } finally {
+        if (stopThreads) {
+          SystemFailure.stopThreads();
+        }
+      }
+    }
+  }
+
+  @VisibleForTesting
+  public static class BuilderForTesting {
+
+    private final Properties configProperties;
+
+    private DistributionManager distributionManager;
+    private StatisticsManagerFactory statisticsManagerFactory = defaultStatisticsManagerFactory();
+
+    public BuilderForTesting(Properties configProperties) {
+      this.configProperties = configProperties;
+    }
+
+    public BuilderForTesting setDistributionManager(DistributionManager distributionManager) {
+      this.distributionManager = distributionManager;
+      return this;
+    }
+
+    public BuilderForTesting setStatisticsManagerFactory(
+        StatisticsManagerFactory statisticsManagerFactory) {
+      this.statisticsManagerFactory = statisticsManagerFactory;
+      return this;
+    }
+
+    /**
+     * Builds instance without initializing it for testing.
+     */
+    public InternalDistributedSystem build() {
+      ConnectionConfigImpl connectionConfig = new ConnectionConfigImpl(configProperties);
+
+      InternalDistributedSystem internalDistributedSystem =
+          new InternalDistributedSystem(connectionConfig, statisticsManagerFactory);
+
+      internalDistributedSystem.config =
+          new RuntimeDistributionConfigImpl(internalDistributedSystem);
+      internalDistributedSystem.dm = distributionManager;
+      internalDistributedSystem.isConnected = true;
+
+      return internalDistributedSystem;
+    }
+  }
 }
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/InternalCacheBuilder.java b/geode-core/src/main/java/org/apache/geode/internal/cache/InternalCacheBuilder.java
index 20e549d..fa980e7 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/InternalCacheBuilder.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/InternalCacheBuilder.java
@@ -16,7 +16,7 @@ package org.apache.geode.internal.cache;
 
 import static java.util.Objects.requireNonNull;
 import static org.apache.geode.distributed.internal.DistributionConfig.GEMFIRE_PREFIX;
-import static org.apache.geode.distributed.internal.InternalDistributedSystem.ALLOW_MULTIPLE_SYSTEMS;
+import static org.apache.geode.distributed.internal.InternalDistributedSystem.ALLOW_MULTIPLE_SYSTEMS_PROPERTY;
 
 import java.util.HashSet;
 import java.util.Optional;
@@ -352,7 +352,7 @@ public class InternalCacheBuilder {
 
   private Optional<InternalDistributedSystem> findInternalDistributedSystem() {
     InternalDistributedSystem internalDistributedSystem = null;
-    if (configProperties.isEmpty() && !ALLOW_MULTIPLE_SYSTEMS) {
+    if (configProperties.isEmpty() && !allowMultipleSystems()) {
       // any ds will do
       internalDistributedSystem = singletonSystemSupplier.get();
       validateUsabilityOfSecurityCallbacks(internalDistributedSystem, cacheConfig);
@@ -370,7 +370,7 @@ public class InternalCacheBuilder {
 
   private InternalCache existingCache(Supplier<? extends InternalCache> systemCacheSupplier,
       Supplier<? extends InternalCache> singletonCacheSupplier) {
-    InternalCache cache = ALLOW_MULTIPLE_SYSTEMS
+    InternalCache cache = allowMultipleSystems()
         ? systemCacheSupplier.get()
         : singletonCacheSupplier.get();
 
@@ -422,6 +422,10 @@ public class InternalCacheBuilder {
     }
   }
 
+  private static boolean allowMultipleSystems() {
+    return Boolean.getBoolean(ALLOW_MULTIPLE_SYSTEMS_PROPERTY);
+  }
+
   @VisibleForTesting
   interface InternalCacheConstructor {
     InternalCache construct(boolean isClient, PoolFactory poolFactory,
diff --git a/geode-core/src/test/java/org/apache/geode/distributed/internal/InternalDistributedSystemIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/distributed/internal/InternalDistributedSystemIntegrationTest.java
new file mode 100644
index 0000000..17aa28b
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/distributed/internal/InternalDistributedSystemIntegrationTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.distributed.internal;
+
+import static org.apache.geode.distributed.ConfigurationProperties.NAME;
+import static org.apache.geode.distributed.internal.InternalDistributedSystem.ALLOW_MULTIPLE_SYSTEMS_PROPERTY;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Properties;
+
+import org.junit.After;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.contrib.java.lang.system.RestoreSystemProperties;
+
+import org.apache.geode.distributed.DistributedSystem;
+
+public class InternalDistributedSystemIntegrationTest {
+
+  private InternalDistributedSystem system;
+  private InternalDistributedSystem system2;
+
+  @Rule
+  public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
+
+  @After
+  public void tearDown() {
+    if (system != null) {
+      system.disconnect();
+    }
+    if (system2 != null) {
+      system2.disconnect();
+    }
+  }
+
+  @Test
+  public void connect() {
+    String theName = "theName";
+    Properties configProperties = new Properties();
+    configProperties.setProperty(NAME, theName);
+
+    system = (InternalDistributedSystem) DistributedSystem.connect(configProperties);
+
+    assertThat(system.isConnected()).isTrue();
+    assertThat(system.getName()).isEqualTo(theName);
+  }
+
+  @Test
+  public void connectWithAllowsMultipleSystems() {
+    System.setProperty(ALLOW_MULTIPLE_SYSTEMS_PROPERTY, "true");
+
+    String name1 = "name1";
+    Properties configProperties1 = new Properties();
+    configProperties1.setProperty(NAME, name1);
+
+    system = (InternalDistributedSystem) DistributedSystem.connect(configProperties1);
+
+    String name2 = "name2";
+    Properties configProperties2 = new Properties();
+    configProperties2.setProperty(NAME, name2);
+
+    system2 = (InternalDistributedSystem) DistributedSystem.connect(configProperties2);
+
+    assertThat(system.isConnected()).isTrue();
+    assertThat(system.getName()).isEqualTo(name1);
+
+    assertThat(system2.isConnected()).isTrue();
+    assertThat(system2.getName()).isEqualTo(name2);
+
+    assertThat(system2).isNotSameAs(system);
+  }
+}
diff --git a/geode-core/src/test/java/org/apache/geode/distributed/internal/InternalDistributedSystemStatisticsManagerTest.java b/geode-core/src/test/java/org/apache/geode/distributed/internal/InternalDistributedSystemStatisticsManagerTest.java
index 71f1848..452f94a 100644
--- a/geode-core/src/test/java/org/apache/geode/distributed/internal/InternalDistributedSystemStatisticsManagerTest.java
+++ b/geode-core/src/test/java/org/apache/geode/distributed/internal/InternalDistributedSystemStatisticsManagerTest.java
@@ -67,8 +67,10 @@ public class InternalDistributedSystemStatisticsManagerTest {
     initMocks(this);
     when(statisticsManagerFactory.create(any(), anyLong(), anyBoolean()))
         .thenReturn(statisticsManager);
-    internalDistributedSystem = InternalDistributedSystem.newInstanceForTesting(distributionManager,
-        new Properties(), statisticsManagerFactory);
+    internalDistributedSystem = new InternalDistributedSystem.BuilderForTesting(new Properties())
+        .setDistributionManager(distributionManager)
+        .setStatisticsManagerFactory(statisticsManagerFactory)
+        .build();
   }
 
   @Test
@@ -81,8 +83,11 @@ public class InternalDistributedSystemStatisticsManagerTest {
         .create(any(), anyLong(), eq(false)))
             .thenReturn(statisticsManagerCreatedByFactory);
 
-    InternalDistributedSystem result = InternalDistributedSystem
-        .newInstanceForTesting(distributionManager, new Properties(), statisticsManagerFactory);
+    InternalDistributedSystem result =
+        new InternalDistributedSystem.BuilderForTesting(new Properties())
+            .setDistributionManager(distributionManager)
+            .setStatisticsManagerFactory(statisticsManagerFactory)
+            .build();
 
     assertThat(result.getStatisticsManager())
         .isSameAs(statisticsManagerCreatedByFactory);
diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/GemFireCacheImplTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/GemFireCacheImplTest.java
index 5f97af0..71d982d 100644
--- a/geode-core/src/test/java/org/apache/geode/internal/cache/GemFireCacheImplTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/cache/GemFireCacheImplTest.java
@@ -14,6 +14,7 @@
  */
 package org.apache.geode.internal.cache;
 
+import static org.apache.geode.distributed.internal.InternalDistributedSystem.ALLOW_MULTIPLE_SYSTEMS_PROPERTY;
 import static org.apache.geode.test.awaitility.GeodeAwaitility.await;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -32,7 +33,9 @@ import java.util.concurrent.ThreadPoolExecutor;
 
 import io.micrometer.core.instrument.MeterRegistry;
 import org.junit.After;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.contrib.java.lang.system.RestoreSystemProperties;
 
 import org.apache.geode.SerializationException;
 import org.apache.geode.cache.CacheClosedException;
@@ -51,12 +54,13 @@ import org.apache.geode.test.fake.Fakes;
  */
 public class GemFireCacheImplTest {
 
+  @Rule
+  public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
+
   private GemFireCacheImpl gemFireCacheImpl;
 
   @After
   public void tearDown() {
-    InternalDistributedSystem.ALLOW_MULTIPLE_SYSTEMS = false;
-
     if (gemFireCacheImpl != null) {
       gemFireCacheImpl.close();
     }
@@ -322,9 +326,7 @@ public class GemFireCacheImplTest {
 
   @Test
   public void clientCacheWouldNotRequestClusterConfig() {
-    // we will need to set the value to true so that we can use a mock gemFireCacheImpl
-    boolean oldValue = InternalDistributedSystem.ALLOW_MULTIPLE_SYSTEMS;
-    InternalDistributedSystem.ALLOW_MULTIPLE_SYSTEMS = true;
+    System.setProperty(ALLOW_MULTIPLE_SYSTEMS_PROPERTY, "true");
 
     InternalDistributedSystem internalDistributedSystem = Fakes.distributedSystem();
     gemFireCacheImpl = mock(GemFireCacheImpl.class);
@@ -336,9 +338,6 @@ public class GemFireCacheImplTest {
 
     verify(gemFireCacheImpl, times(0)).requestSharedConfiguration();
     verify(gemFireCacheImpl, times(0)).applyJarAndXmlFromClusterConfig();
-
-    // reset it back to the old value
-    InternalDistributedSystem.ALLOW_MULTIPLE_SYSTEMS = oldValue;
   }
 
   @Test
diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/InternalCacheBuilderAllowsMultipleSystemsTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/InternalCacheBuilderAllowsMultipleSystemsTest.java
index ed0ac66..e229599 100644
--- a/geode-core/src/test/java/org/apache/geode/internal/cache/InternalCacheBuilderAllowsMultipleSystemsTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/cache/InternalCacheBuilderAllowsMultipleSystemsTest.java
@@ -14,6 +14,7 @@
  */
 package org.apache.geode.internal.cache;
 
+import static org.apache.geode.distributed.internal.InternalDistributedSystem.ALLOW_MULTIPLE_SYSTEMS_PROPERTY;
 import static org.apache.geode.internal.cache.InternalCacheBuilderAllowsMultipleSystemsTest.CacheState.CLOSED;
 import static org.apache.geode.internal.cache.InternalCacheBuilderAllowsMultipleSystemsTest.CacheState.OPEN;
 import static org.assertj.core.api.Assertions.assertThat;
@@ -34,9 +35,10 @@ import java.util.function.Supplier;
 
 import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
 import org.assertj.core.api.ThrowableAssert;
-import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.contrib.java.lang.system.RestoreSystemProperties;
 import org.mockito.Mock;
 
 import org.apache.geode.cache.CacheExistsException;
@@ -53,6 +55,9 @@ import org.apache.geode.internal.metrics.CompositeMeterRegistryFactory;
  */
 public class InternalCacheBuilderAllowsMultipleSystemsTest {
 
+  @Rule
+  public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
+
   private static final int ANY_SYSTEM_ID = 12;
   private static final String ANY_MEMBER_NAME = "a-member-name";
   private static final String ANY_HOST_NAME = "a-host-name";
@@ -85,12 +90,7 @@ public class InternalCacheBuilderAllowsMultipleSystemsTest {
   public void setUp() {
     initMocks(this);
 
-    InternalDistributedSystem.ALLOW_MULTIPLE_SYSTEMS = true;
-  }
-
-  @After
-  public void tearDown() {
-    InternalDistributedSystem.ALLOW_MULTIPLE_SYSTEMS = false;
+    System.setProperty(ALLOW_MULTIPLE_SYSTEMS_PROPERTY, "true");
   }
 
   @Test
diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/InternalCacheBuilderTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/InternalCacheBuilderTest.java
index 97fc693..ec43567 100644
--- a/geode-core/src/test/java/org/apache/geode/internal/cache/InternalCacheBuilderTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/cache/InternalCacheBuilderTest.java
@@ -96,8 +96,6 @@ public class InternalCacheBuilderTest {
 
     when(nullSingletonSystemSupplier.get()).thenReturn(null);
     when(nullSingletonCacheSupplier.get()).thenReturn(null);
-
-    InternalDistributedSystem.ALLOW_MULTIPLE_SYSTEMS = false;
   }
 
   @Test