http://git-wip-us.apache.org/repos/asf/geode/blob/be8db8b7/geode-core/src/test/java/org/apache/geode/internal/cache/rollingupgrade/RollingUpgradeDUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/rollingupgrade/RollingUpgradeDUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/rollingupgrade/RollingUpgradeDUnitTest.java new file mode 100644 index 0000000..369bc3b --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/internal/cache/rollingupgrade/RollingUpgradeDUnitTest.java @@ -0,0 +1,1051 @@ +/* + * 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.internal.cache.rollingupgrade; + +import org.apache.geode.cache.RegionShortcut; +import org.apache.geode.cache30.CacheSerializableRunnable; +import org.apache.geode.distributed.internal.DistributionConfig; +import org.apache.geode.internal.AvailablePortHelper; +import org.apache.geode.internal.FileUtil; +import org.apache.geode.internal.Version; +import org.apache.geode.test.dunit.DistributedTestUtils; +import org.apache.geode.test.dunit.Host; +import org.apache.geode.test.dunit.IgnoredException; +import org.apache.geode.test.dunit.Invoke; +import org.apache.geode.test.dunit.LogWriterUtils; +import org.apache.geode.test.dunit.NetworkUtils; +import org.apache.geode.test.dunit.VM; +import org.apache.geode.test.dunit.internal.JUnit4DistributedTestCase; +import org.apache.geode.test.dunit.standalone.DUnitLauncher; +import org.apache.geode.test.dunit.standalone.VersionManager; +import org.apache.geode.test.junit.categories.BackwardCompatibilityTest; +import org.apache.geode.test.junit.categories.DistributedTest; +import org.apache.geode.test.junit.runners.CategoryWithParameterizedRunnerFactory; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.net.InetAddress; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Properties; + +/** + * RollingUpgrade dunit tests are distributed among subclasses of RollingUpgradeDUnitTest to avoid + * spurious "hangs" being declared by Hydra. + * + * This test will not run properly in eclipse at this point due to having to bounce vms Currently, + * bouncing vms is necessary because we are starting gemfire with different class loaders and the + * class loaders are lingering (possibly due to daemon threads - the vm itself is still running) + * + * Note: to run in eclipse, I had to copy over the jg-magic-map.txt file into my GEMFIRE_OUTPUT + * location, in the same directory as #MagicNumberReader otherwise the two systems were unable to + * talk to one another due to one using a magic number and the other not. Also turnOffBounce will + * need to be set to true so that bouncing a vm doesn't lead to a NPE. + * + * @author jhuynh + */ + +@Category({DistributedTest.class, BackwardCompatibilityTest.class}) +@RunWith(Parameterized.class) [email protected](CategoryWithParameterizedRunnerFactory.class) +public class RollingUpgradeDUnitTest extends JUnit4DistributedTestCase { + + @Parameterized.Parameters + public static Collection<String> data() { + return VersionManager.getInstance().getVersionsWithoutCurrent(); + } + + private File[] testingDirs = new File[3]; + + private static String diskDir = "RollingUpgradeDUnitTest"; + + // Each vm will have a cache object + private static Object cache; + + // the old version of Geode we're testing against + private String oldVersion; + + private void deleteVMFiles() throws Exception { + System.out.println("deleting files in vm" + VM.getCurrentVMNum()); + File pwd = new File("."); + for (File entry : pwd.listFiles()) { + try { + FileUtil.delete(entry); + } catch (Exception e) { + System.out.println("Could not delete " + entry + ": " + e.getMessage()); + } + } + } + + private void deleteWorkingDirFiles() throws Exception { + Invoke.invokeInEveryVM("delete files", () -> deleteVMFiles()); + } + + @Override + public void postSetUp() throws Exception { + deleteWorkingDirFiles(); + IgnoredException.addIgnoredException( + "cluster configuration service not available|ConflictingPersistentDataException"); + } + + public RollingUpgradeDUnitTest(String version) { + oldVersion = version; + } + + @Test + public void testRollServersOnReplicatedRegion_dataserializable() throws Exception { + doTestRollAll("replicate", "dataserializable", oldVersion); + } + + @Test + public void testRollServersOnPartitionedRegion_dataserializable() throws Exception { + doTestRollAll("partitionedRedundant", "dataserializable", oldVersion); + } + + @Test + public void testRollServersOnPersistentRegion_dataserializable() throws Exception { + doTestRollAll("persistentReplicate", "dataserializable", oldVersion); + } + + + // We start an "old" locator and old servers + // We roll the locator + // Now we roll all the servers from old to new + public void doTestRollAll(String regionType, String objectType, String startingVersion) + throws Exception { + final Host host = Host.getHost(0); + VM server1 = host.getVM(startingVersion, 0); + VM server2 = host.getVM(startingVersion, 1); + VM server3 = host.getVM(startingVersion, 2); + VM locator = host.getVM(startingVersion, 3); + + + String regionName = "aRegion"; + String shortcutName = RegionShortcut.REPLICATE.name(); + if (regionType.equals("replicate")) { + shortcutName = RegionShortcut.REPLICATE.name(); + } else if ((regionType.equals("partitionedRedundant"))) { + shortcutName = RegionShortcut.PARTITION_REDUNDANT.name(); + } else if ((regionType.equals("persistentReplicate"))) { + shortcutName = RegionShortcut.PARTITION_PERSISTENT.name(); + for (int i = 0; i < testingDirs.length; i++) { + testingDirs[i] = new File(diskDir, "diskStoreVM_" + String.valueOf(host.getVM(i).getPid())) + .getAbsoluteFile(); + if (!testingDirs[i].exists()) { + System.out.println(" Creating diskdir for server: " + i); + testingDirs[i].mkdirs(); + } + } + } + + int[] locatorPorts = AvailablePortHelper.getRandomAvailableTCPPorts(1); + String hostName = NetworkUtils.getServerHostName(host); + String locatorString = getLocatorString(locatorPorts); + final Properties locatorProps = new Properties(); + // configure all class loaders for each vm + + try { + locator.invoke(invokeStartLocator(hostName, locatorPorts[0], getTestMethodName(), + locatorString, locatorProps)); + invokeRunnableInVMs(invokeCreateCache(getSystemProperties(locatorPorts)), server1, server2, + server3); + + // create region + if ((regionType.equals("persistentReplicate"))) { + for (int i = 0; i < testingDirs.length; i++) { + CacheSerializableRunnable runnable = + invokeCreatePersistentReplicateRegion(regionName, testingDirs[i]); + invokeRunnableInVMs(runnable, host.getVM(i)); + } + } else { + invokeRunnableInVMs(invokeCreateRegion(regionName, shortcutName), server1, server2, + server3); + } + + putAndVerify(objectType, server1, regionName, 0, 10, server2, server3); + locator = rollLocatorToCurrent(locator, hostName, locatorPorts[0], getTestMethodName(), + locatorString); + + server1 = rollServerToCurrentAndCreateRegion(server1, regionType, testingDirs[0], + shortcutName, regionName, locatorPorts); + verifyValues(objectType, regionName, 0, 10, server1); + putAndVerify(objectType, server1, regionName, 5, 15, server2, server3); + putAndVerify(objectType, server2, regionName, 10, 20, server1, server3); + + server2 = rollServerToCurrentAndCreateRegion(server2, regionType, testingDirs[1], + shortcutName, regionName, locatorPorts); + verifyValues(objectType, regionName, 0, 10, server2); + putAndVerify(objectType, server2, regionName, 15, 25, server1, server3); + putAndVerify(objectType, server3, regionName, 20, 30, server2, server3); + + server3 = rollServerToCurrentAndCreateRegion(server3, regionType, testingDirs[2], + shortcutName, regionName, locatorPorts); + verifyValues(objectType, regionName, 0, 10, server3); + putAndVerify(objectType, server3, regionName, 15, 25, server1, server2); + putAndVerify(objectType, server1, regionName, 20, 30, server1, server2, server3); + + + } finally { + invokeRunnableInVMs(true, invokeStopLocator(), locator); + invokeRunnableInVMs(true, invokeCloseCache(), server1, server2, server3); + if ((regionType.equals("persistentReplicate"))) { + deleteDiskStores(); + } + } + } + + // ******** TEST HELPER METHODS ********/ + private void putAndVerify(String objectType, VM putter, String regionName, int start, int end, + VM check1, VM check2, VM check3) throws Exception { + if (objectType.equals("strings")) { + putStringsAndVerify(putter, regionName, start, end, check1, check2, check3); + } else if (objectType.equals("serializable")) { + putSerializableAndVerify(putter, regionName, start, end, check1, check2, check3); + } else if (objectType.equals("dataserializable")) { + putDataSerializableAndVerify(putter, regionName, start, end, check1, check2, check3); + } else { + throw new Error("Not a valid test object type"); + } + } + + // ******** TEST HELPER METHODS ********/ + private void putAndVerify(String objectType, VM putter, String regionName, int start, int end, + VM check1, VM check2) throws Exception { + if (objectType.equals("strings")) { + putStringsAndVerify(putter, regionName, start, end, check1, check2); + } else if (objectType.equals("serializable")) { + putSerializableAndVerify(putter, regionName, start, end, check1, check2); + } else if (objectType.equals("dataserializable")) { + putDataSerializableAndVerify(putter, regionName, start, end, check1, check2); + } else { + throw new Error("Not a valid test object type"); + } + } + + private void putStringsAndVerify(VM putter, final String regionName, final int start, + final int end, VM... vms) { + for (int i = start; i < end; i++) { + putter.invoke(invokePut(regionName, "" + i, "VALUE(" + i + ")")); + } + + threadSleep(); + + // verify present in others + for (VM vm : vms) { + vm.invoke(invokeAssertEntriesEqual(regionName, start, end)); + } + } + + private void putSerializableAndVerify(VM putter, String regionName, int start, int end, + VM... vms) { + for (int i = start; i < end; i++) { + putter.invoke(invokePut(regionName, "" + i, new Properties())); + } + + threadSleep(); + + // verify present in others + for (VM vm : vms) { + vm.invoke(invokeAssertEntriesExist(regionName, start, end)); + } + } + + private void putDataSerializableAndVerify(VM putter, String regionName, int start, int end, + VM... vms) throws Exception { + for (int i = start; i < end; i++) { + Class aClass = Thread.currentThread().getContextClassLoader() + .loadClass("org.apache.geode.cache.ExpirationAttributes"); + Constructor constructor = aClass.getConstructor(int.class); + Object testDataSerializable = constructor.newInstance(i); + putter.invoke(invokePut(regionName, "" + i, testDataSerializable)); + } + + threadSleep(); + + // verify present in others + for (VM vm : vms) { + vm.invoke(invokeAssertEntriesExist(regionName, start, end)); + } + } + + private void verifyValues(String objectType, String regionName, int start, int end, VM... vms) { + threadSleep(); + if (objectType.equals("strings")) { + for (VM vm : vms) { + vm.invoke(invokeAssertEntriesEqual(regionName, start, end)); + } + } else if (objectType.equals("serializable")) { + for (VM vm : vms) { + vm.invoke(invokeAssertEntriesExist(regionName, start, end)); + } + } else if (objectType.equals("dataserializable")) { + for (VM vm : vms) { + vm.invoke(invokeAssertEntriesExist(regionName, start, end)); + } + } + } + + // Oddly the puts will return and for some reason the other vms have yet to recieve or process the + // put? + private void threadSleep() { + try { + Thread.sleep(250); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + private void query(String queryString, int numExpectedResults, VM... vms) { + for (VM vm : vms) { + vm.invoke(invokeAssertQueryResults(queryString, numExpectedResults)); + } + } + + private void invokeRunnableInVMs(CacheSerializableRunnable runnable, VM... vms) throws Exception { + for (VM vm : vms) { + vm.invoke(runnable); + } + } + + // Used to close cache and make sure we attempt on all vms even if some do not have a cache + private void invokeRunnableInVMs(boolean catchErrors, CacheSerializableRunnable runnable, + VM... vms) throws Exception { + for (VM vm : vms) { + try { + vm.invoke(runnable); + } catch (Exception e) { + if (!catchErrors) { + throw e; + } + } + } + } + + private VM rollServerToCurrent(VM oldServer, int[] locatorPorts) throws Exception { + // Roll the server + oldServer.invoke(invokeCloseCache()); + VM rollServer = Host.getHost(0).getVM(oldServer.getPid()); // gets a vm with the current version + rollServer.invoke(invokeCreateCache(locatorPorts == null ? getSystemPropertiesPost71() + : getSystemPropertiesPost71(locatorPorts))); + rollServer.invoke(invokeAssertVersion(Version.CURRENT_ORDINAL)); + return rollServer; + } + + /* + * @param rollServer + * + * @param createRegionMethod + * + * @param regionName + * + * @param locatorPorts if null, uses dunit locator + * + * @throws Exception + */ + private void rollServerToCurrentAndCreateRegion(VM rollServer, String shortcutName, + String regionName, int[] locatorPorts) throws Exception { + rollServerToCurrent(rollServer, locatorPorts); + // recreate region on "rolled" server + invokeRunnableInVMs(invokeCreateRegion(regionName, shortcutName), rollServer); + rollServer.invoke(invokeRebalance()); + } + + private VM rollServerToCurrentAndCreateRegion(VM oldServer, String regionType, File diskdir, + String shortcutName, String regionName, int[] locatorPorts) throws Exception { + VM rollServer = rollServerToCurrent(oldServer, locatorPorts); + // recreate region on "rolled" server + if ((regionType.equals("persistentReplicate"))) { + CacheSerializableRunnable runnable = + invokeCreatePersistentReplicateRegion(regionName, diskdir); + invokeRunnableInVMs(runnable, rollServer); + } else { + invokeRunnableInVMs(invokeCreateRegion(regionName, shortcutName), rollServer); + } + rollServer.invoke(invokeRebalance()); + return rollServer; + } + + private VM rollLocatorToCurrent(VM oldLocator, final String serverHostName, final int port, + final String testName, final String locatorString) throws Exception { + // Roll the locator + oldLocator.invoke(invokeStopLocator()); + VM rollLocator = Host.getHost(0).getVM(oldLocator.getPid()); // gets a VM with current version + final Properties props = new Properties(); + props.setProperty(DistributionConfig.ENABLE_CLUSTER_CONFIGURATION_NAME, "false"); + rollLocator.invoke(invokeStartLocator(serverHostName, port, testName, locatorString, props)); + return rollLocator; + } + + // Due to licensing changes + public Properties getSystemPropertiesPost71() { + Properties props = getSystemProperties(); + return props; + } + + // Due to licensing changes + public Properties getSystemPropertiesPost71(int[] locatorPorts) { + Properties props = getSystemProperties(locatorPorts); + return props; + } + + public Properties getSystemProperties() { + Properties props = DistributedTestUtils.getAllDistributedSystemProperties(new Properties()); + props.remove("disable-auto-reconnect"); + props.remove(DistributionConfig.OFF_HEAP_MEMORY_SIZE_NAME); + props.remove(DistributionConfig.LOCK_MEMORY_NAME); + return props; + } + + public Properties getSystemProperties(int[] locatorPorts) { + Properties p = new Properties(); + String locatorString = getLocatorString(locatorPorts); + p.setProperty("locators", locatorString); + p.setProperty("mcast-port", "0"); + return p; + } + + public Properties getClientSystemProperties() { + Properties p = new Properties(); + p.setProperty("mcast-port", "0"); + return p; + } + + public static String getLocatorString(int locatorPort) { + String locatorString = getDUnitLocatorAddress() + "[" + locatorPort + "]"; + return locatorString; + } + + public static String getLocatorString(int[] locatorPorts) { + String locatorString = ""; + int numLocators = locatorPorts.length; + for (int i = 0; i < numLocators; i++) { + locatorString += getLocatorString(locatorPorts[i]); + if (i + 1 < numLocators) { + locatorString += ","; + } + } + return locatorString; + } + + + private List<URL> addFile(File file) throws MalformedURLException { + ArrayList<URL> urls = new ArrayList<URL>(); + if (file.isDirectory()) { + // Do not want to start cache with sample code xml + if (file.getName().contains("SampleCode")) { + return urls; + } else { + File[] files = file.listFiles(); + for (File afile : files) { + urls.addAll(addFile(afile)); + } + } + } else { + URL url = file.toURI().toURL(); + urls.add(url); + } + return urls; + } + + + + private CacheSerializableRunnable invokeStartLocator(final String serverHostName, final int port, + final String testName, final String locatorsString, final Properties props) { + return new CacheSerializableRunnable("execute: startLocator") { + public void run2() { + try { + startLocator(serverHostName, port, testName, locatorsString, props); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + + private CacheSerializableRunnable invokeStartLocatorAndServer(final String serverHostName, + final int port, final String testName, final Properties systemProperties) { + return new CacheSerializableRunnable("execute: startLocator") { + public void run2() { + try { + systemProperties.put(DistributionConfig.START_LOCATOR_NAME, + "" + serverHostName + "[" + port + "]"); + RollingUpgradeDUnitTest.cache = createCache(systemProperties); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + + private CacheSerializableRunnable invokeCreateCache(final Properties systemProperties) { + return new CacheSerializableRunnable("execute: createCache") { + public void run2() { + try { + RollingUpgradeDUnitTest.cache = createCache(systemProperties); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + + private CacheSerializableRunnable invokeCreateClientCache(final Properties systemProperties, + final String[] hosts, final int[] ports) { + return new CacheSerializableRunnable("execute: createClientCache") { + public void run2() { + try { + RollingUpgradeDUnitTest.cache = createClientCache(systemProperties, hosts, ports); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + + private CacheSerializableRunnable invokeStartCacheServer(final int port) { + return new CacheSerializableRunnable("execute: startCacheServer") { + public void run2() { + try { + startCacheServer(RollingUpgradeDUnitTest.cache, port); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + + private CacheSerializableRunnable invokeAssertVersion(final short version) { + return new CacheSerializableRunnable("execute: assertVersion") { + public void run2() { + try { + assertVersion(RollingUpgradeDUnitTest.cache, version); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + + private CacheSerializableRunnable invokeCreateRegion(final String regionName, + final String shortcutName) { + return new CacheSerializableRunnable("execute: createRegion") { + public void run2() { + try { + createRegion(RollingUpgradeDUnitTest.cache, regionName, shortcutName); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + + private CacheSerializableRunnable invokeCreatePersistentReplicateRegion(final String regionName, + final File diskstore) { + return new CacheSerializableRunnable("execute: createPersistentReplicateRegion") { + public void run2() { + try { + createPersistentReplicateRegion(RollingUpgradeDUnitTest.cache, regionName, diskstore); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + + private CacheSerializableRunnable invokeCreateClientRegion(final String regionName, + final String shortcutName) { + return new CacheSerializableRunnable("execute: createClientRegion") { + public void run2() { + try { + createClientRegion(RollingUpgradeDUnitTest.cache, regionName, shortcutName); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + + private CacheSerializableRunnable invokePut(final String regionName, final Object key, + final Object value) { + return new CacheSerializableRunnable("execute: put") { + public void run2() { + try { + put(RollingUpgradeDUnitTest.cache, regionName, key, value); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + + private CacheSerializableRunnable invokeAssertEntriesEqual(final String regionName, + final int start, final int end) { + return new CacheSerializableRunnable("execute: assertEntriesEqual") { + public void run2() { + try { + for (int i = start; i < end; i++) { + assertEntryEquals(RollingUpgradeDUnitTest.cache, regionName, "" + i, + "VALUE(" + i + ")"); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + + private CacheSerializableRunnable invokeAssertEntriesExist(final String regionName, + final int start, final int end) { + return new CacheSerializableRunnable("execute: assertEntryExists") { + public void run2() { + try { + for (int i = start; i < end; i++) { + assertEntryExists(RollingUpgradeDUnitTest.cache, regionName, "" + i); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + + private CacheSerializableRunnable invokeStopLocator() { + return new CacheSerializableRunnable("execute: stopLocator") { + public void run2() { + try { + stopLocator(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + + private CacheSerializableRunnable invokeCloseCache() { + return new CacheSerializableRunnable("execute: closeCache") { + public void run2() { + try { + closeCache(RollingUpgradeDUnitTest.cache); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + + private CacheSerializableRunnable invokeRebalance() { + return new CacheSerializableRunnable("execute: rebalance") { + public void run2() { + try { + rebalance(RollingUpgradeDUnitTest.cache); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + + private CacheSerializableRunnable invokeAssertQueryResults(final String queryString, + final int numExpected) { + return new CacheSerializableRunnable("execute: assertQueryResults") { + public void run2() { + try { + assertQueryResults(RollingUpgradeDUnitTest.cache, queryString, numExpected); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + + public void deleteDiskStores() throws Exception { + try { + FileUtil.delete(new File(diskDir).getAbsoluteFile()); + } catch (IOException e) { + throw new Error("Error deleting files", e); + } + } + + public static Object createCache(Properties systemProperties) throws Exception { + + // systemProperties.put(DistributionConfig.LOG_FILE_NAME, + // "rollingUpgradeCacheVM" + VM.getCurrentVMNum() + ".log"); + + Class distConfigClass = Thread.currentThread().getContextClassLoader() + .loadClass("org.apache.geode.distributed.internal.DistributionConfigImpl"); + boolean disableConfig = true; + try { + distConfigClass.getDeclaredField("useSharedConfiguration"); + } catch (NoSuchFieldException e) { + disableConfig = false; + } + if (disableConfig) { + systemProperties.put(DistributionConfig.USE_CLUSTER_CONFIGURATION_NAME, "false"); + } + + Class cacheFactoryClass = Thread.currentThread().getContextClassLoader() + .loadClass("org.apache.geode.cache.CacheFactory"); + Constructor constructor = cacheFactoryClass.getConstructor(Properties.class); + constructor.setAccessible(true); + Object cacheFactory = constructor.newInstance(systemProperties); + + Method createMethod = cacheFactoryClass.getMethod("create"); + createMethod.setAccessible(true); + Object cache = null; + cache = createMethod.invoke(cacheFactory); + return cache; + } + + public static void startCacheServer(Object cache, int port) throws Exception { + Method addCacheServerMethod = cache.getClass().getMethod("addCacheServer"); + addCacheServerMethod.setAccessible(true); + Object cacheServer = addCacheServerMethod.invoke(cache); + + Method setPortMethod = cacheServer.getClass().getMethod("setPort", int.class); + setPortMethod.setAccessible(true); + setPortMethod.invoke(cacheServer, port); + + Method startMethod = cacheServer.getClass().getMethod("start"); + startMethod.setAccessible(true); + startMethod.invoke(cacheServer); + } + + public static Object createClientCache(Properties systemProperties, String[] hosts, int[] ports) + throws Exception { + Class aClass = Thread.currentThread().getContextClassLoader() + .loadClass("org.apache.geode.cache.client.ClientCacheFactory"); + Constructor constructor = aClass.getConstructor(Properties.class); + constructor.setAccessible(true); + + Object ccf = constructor.newInstance(systemProperties); + Method addPoolLocatorMethod = aClass.getMethod("addPoolLocator", String.class, int.class); + addPoolLocatorMethod.setAccessible(true); + int hostsLength = hosts.length; + for (int i = 0; i < hostsLength; i++) { + addPoolLocatorMethod.invoke(ccf, hosts[i], ports[i]); + } + + Method createMethod = aClass.getMethod("create"); + createMethod.setAccessible(true); + Object cache = createMethod.invoke(ccf); + + return cache; + } + + public static boolean assertRegionExists(Object cache, String regionName) throws Exception { + Object region = cache.getClass().getMethod("getRegion", String.class).invoke(cache, regionName); + if (region == null) { + throw new Error("Region: " + regionName + " does not exist"); + } + return true; + } + + public static Object getRegion(Object cache, String regionName) throws Exception { + return cache.getClass().getMethod("getRegion", String.class).invoke(cache, regionName); + } + + public static boolean assertEntryEquals(Object cache, String regionName, Object key, Object value) + throws Exception { + assertRegionExists(cache, regionName); + Object region = getRegion(cache, regionName); + Object regionValue = region.getClass().getMethod("get", Object.class).invoke(region, key); + if (regionValue == null) { + System.out.println("region value does not exist for key: " + key); + throw new Error("Region value does not exist for key:" + key); + } + if (!regionValue.equals(value)) { + System.out.println("Entry for key:" + key + " does not equal value: " + value); + throw new Error("Entry for key:" + key + " does not equal value: " + value); + } + return true; + } + + public static boolean assertEntryExists(Object cache, String regionName, Object key) + throws Exception { + assertRegionExists(cache, regionName); + Object region = getRegion(cache, regionName); + Object regionValue = region.getClass().getMethod("get", Object.class).invoke(region, key); + if (regionValue == null) { + System.out.println("Entry for key:" + key + " does not exist"); + throw new Error("Entry for key:" + key + " does not exist"); + } + return true; + } + + public static Object put(Object cache, String regionName, Object key, Object value) + throws Exception { + Object region = getRegion(cache, regionName); + return region.getClass().getMethod("put", Object.class, Object.class).invoke(region, key, + value); + } + + public static void createRegion(Object cache, String regionName, String shortcutName) + throws Exception { + Class aClass = Thread.currentThread().getContextClassLoader() + .loadClass("org.apache.geode.cache.RegionShortcut"); + Object[] enumConstants = aClass.getEnumConstants(); + Object shortcut = null; + int length = enumConstants.length; + for (int i = 0; i < length; i++) { + Object constant = enumConstants[i]; + if (((Enum) constant).name().equals(shortcutName)) { + shortcut = constant; + break; + } + } + + Method createRegionFactoryMethod = cache.getClass().getMethod("createRegionFactory", aClass); + createRegionFactoryMethod.setAccessible(true); + Object regionFactory = createRegionFactoryMethod.invoke(cache, shortcut); + Method createMethod = regionFactory.getClass().getMethod("create", String.class); + createMethod.setAccessible(true); + createMethod.invoke(regionFactory, regionName); + } + + public static void createPartitionedRegion(Object cache, String regionName) throws Exception { + createRegion(cache, regionName, RegionShortcut.PARTITION.name()); + } + + public static void createPartitionedRedundantRegion(Object cache, String regionName) + throws Exception { + createRegion(cache, regionName, RegionShortcut.PARTITION_REDUNDANT.name()); + } + + public static void createReplicatedRegion(Object cache, String regionName) throws Exception { + createRegion(cache, regionName, RegionShortcut.REPLICATE.name()); + } + + // Assumes a client cache is passed + public static void createClientRegion(Object cache, String regionName, String shortcutName) + throws Exception { + Class aClass = Thread.currentThread().getContextClassLoader() + .loadClass("org.apache.geode.cache.client.ClientRegionShortcut"); + Object[] enumConstants = aClass.getEnumConstants(); + Object shortcut = null; + int length = enumConstants.length; + for (int i = 0; i < length; i++) { + Object constant = enumConstants[i]; + if (((Enum) constant).name().equals(shortcutName)) { + shortcut = constant; + break; + } + } + Object clientRegionFactory = cache.getClass() + .getMethod("createClientRegionFactory", shortcut.getClass()).invoke(cache, shortcut); + clientRegionFactory.getClass().getMethod("create", String.class).invoke(clientRegionFactory, + regionName); + } + + public static void createRegion(String regionName, Object regionFactory) throws Exception { + regionFactory.getClass().getMethod("create", String.class).invoke(regionFactory, regionName); + } + + public static void createPersistentReplicateRegion(Object cache, String regionName, + File diskStore) throws Exception { + Object store = cache.getClass().getMethod("findDiskStore", String.class).invoke(cache, "store"); + Class dataPolicyObject = Thread.currentThread().getContextClassLoader() + .loadClass("org.apache.geode.cache.DataPolicy"); + Object dataPolicy = dataPolicyObject.getField("PERSISTENT_REPLICATE").get(null); + if (store == null) { + Object dsf = cache.getClass().getMethod("createDiskStoreFactory").invoke(cache); + dsf.getClass().getMethod("setMaxOplogSize", long.class).invoke(dsf, 1L); + dsf.getClass().getMethod("setDiskDirs", File[].class).invoke(dsf, + new Object[] {new File[] {diskStore.getAbsoluteFile()}}); + dsf.getClass().getMethod("create", String.class).invoke(dsf, "store"); + } + Object rf = cache.getClass().getMethod("createRegionFactory").invoke(cache); + rf.getClass().getMethod("setDiskStoreName", String.class).invoke(rf, "store"); + rf.getClass().getMethod("setDataPolicy", dataPolicy.getClass()).invoke(rf, dataPolicy); + rf.getClass().getMethod("create", String.class).invoke(rf, regionName); + } + + public static void assertVersion(Object cache, short ordinal) throws Exception { + Class idmClass = Thread.currentThread().getContextClassLoader() + .loadClass("org.apache.geode.distributed.internal.membership.InternalDistributedMember"); + Method getDSMethod = cache.getClass().getMethod("getDistributedSystem"); + getDSMethod.setAccessible(true); + Object ds = getDSMethod.invoke(cache); + + Method getDistributedMemberMethod = ds.getClass().getMethod("getDistributedMember"); + getDistributedMemberMethod.setAccessible(true); + Object member = getDistributedMemberMethod.invoke(ds); + Method getVersionObjectMethod = member.getClass().getMethod("getVersionObject"); + getVersionObjectMethod.setAccessible(true); + Object thisVersion = getVersionObjectMethod.invoke(member); + Method getOrdinalMethod = thisVersion.getClass().getMethod("ordinal"); + getOrdinalMethod.setAccessible(true); + short thisOrdinal = (Short) getOrdinalMethod.invoke(thisVersion); + if (ordinal != thisOrdinal) { + throw new Error( + "Version ordinal:" + thisOrdinal + " was not the expected ordinal of:" + ordinal); + } + } + + public static void assertQueryResults(Object cache, String queryString, int numExpectedResults) { + try { + Method getQSMethod = cache.getClass().getMethod("getQueryService"); + getQSMethod.setAccessible(true); + Object qs = getQSMethod.invoke(cache); + Method newQueryMethod = qs.getClass().getMethod("newQuery", String.class); + newQueryMethod.setAccessible(true); + Object query = newQueryMethod.invoke(qs, queryString); + Method executeMethod = query.getClass().getMethod("execute"); + executeMethod.setAccessible(true); + Object results = executeMethod.invoke(query); + + Method sizeMethod = results.getClass().getMethod("size"); + sizeMethod.setAccessible(true); + int numResults = (Integer) sizeMethod.invoke(results); + + if (numResults != numExpectedResults) { + System.out.println("Num Results was:" + numResults); + throw new Error("Num results:" + numResults + " != num expected:" + numExpectedResults); + } + } catch (Exception e) { + throw new Error("Query Exception", e); + } + } + + public static void stopCacheServers(Object cache) throws Exception { + Method getCacheServersMethod = cache.getClass().getMethod("getCacheServers"); + getCacheServersMethod.setAccessible(true); + List cacheServers = (List) getCacheServersMethod.invoke(cache); + Method stopMethod = null; + for (Object cs : cacheServers) { + if (stopMethod == null) { + stopMethod = cs.getClass().getMethod("stop"); + } + stopMethod.setAccessible(true); + stopMethod.invoke(cs); + } + } + + public static void closeCache(Object cache) throws Exception { + if (cache == null) { + return; + } + Method isClosedMethod = cache.getClass().getMethod("isClosed"); + isClosedMethod.setAccessible(true); + boolean cacheClosed = (Boolean) isClosedMethod.invoke(cache); + if (cache != null && !cacheClosed) { + stopCacheServers(cache); + Method method = cache.getClass().getMethod("close"); + method.setAccessible(true); + method.invoke(cache); + long startTime = System.currentTimeMillis(); + while (!cacheClosed && System.currentTimeMillis() - startTime < 30000) { + try { + Thread.sleep(1000); + Method cacheClosedMethod = cache.getClass().getMethod("isClosed"); + cacheClosedMethod.setAccessible(true); + cacheClosed = (Boolean) cacheClosedMethod.invoke(cache); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + cache = null; + } + + public static void rebalance(Object cache) throws Exception { + Method getRMMethod = cache.getClass().getMethod("getResourceManager"); + getRMMethod.setAccessible(true); + Object manager = getRMMethod.invoke(cache); + + Method createRebalanceFactoryMethod = manager.getClass().getMethod("createRebalanceFactory"); + createRebalanceFactoryMethod.setAccessible(true); + Object rebalanceFactory = createRebalanceFactoryMethod.invoke(manager); + Object op = null; + Method m = rebalanceFactory.getClass().getMethod("start"); + m.setAccessible(true); + op = m.invoke(rebalanceFactory); + + // Wait until the rebalance is completex + try { + Method getResultsMethod = op.getClass().getMethod("getResults"); + getResultsMethod.setAccessible(true); + Object results = getResultsMethod.invoke(op); + Method getTotalTimeMethod = results.getClass().getMethod("getTotalTime"); + getTotalTimeMethod.setAccessible(true); + System.out.println("Took " + getTotalTimeMethod.invoke(results) + " milliseconds\n"); + Method getTotalBucketsMethod = results.getClass().getMethod("getTotalBucketTransferBytes"); + getTotalBucketsMethod.setAccessible(true); + System.out.println("Transfered " + getTotalBucketsMethod.invoke(results) + "bytes\n"); + } catch (Exception e) { + Thread.currentThread().interrupt(); + throw e; + } + } + + /** + * Starts a locator with given configuration. + * + * @param props TODO + */ + public static void startLocator(final String serverHostName, final int port, + final String testName, final String locatorsString, final Properties props) throws Exception { + props.setProperty(DistributionConfig.MCAST_PORT_NAME, "0"); + props.setProperty(DistributionConfig.LOCATORS_NAME, locatorsString); + props.setProperty(DistributionConfig.LOG_LEVEL_NAME, LogWriterUtils.getDUnitLogLevel()); + + InetAddress bindAddr = null; + try { + bindAddr = InetAddress.getByName(serverHostName);// getServerHostName(vm.getHost())); + } catch (UnknownHostException uhe) { + throw new Error("While resolving bind address ", uhe); + } + + File logFile = new File(testName + "-locator" + port + ".log"); + Class locatorClass = Thread.currentThread().getContextClassLoader() + .loadClass("org.apache.geode.distributed.Locator"); + Method startLocatorAndDSMethod = + locatorClass.getMethod("startLocatorAndDS", int.class, File.class, InetAddress.class, + Properties.class, boolean.class, boolean.class, String.class); + startLocatorAndDSMethod.setAccessible(true); + startLocatorAndDSMethod.invoke(null, port, logFile, bindAddr, props, true, true, null); + } + + public static void stopLocator() throws Exception { + Class internalLocatorClass = Thread.currentThread().getContextClassLoader() + .loadClass("org.apache.geode.distributed.internal.InternalLocator"); + Method locatorMethod = internalLocatorClass.getMethod("getLocator"); + locatorMethod.setAccessible(true); + Object locator = locatorMethod.invoke(null); + Method stopLocatorMethod = locator.getClass().getMethod("stop"); + stopLocatorMethod.setAccessible(true); + stopLocatorMethod.invoke(locator); + } + + /** + * Get the port that the standard dunit locator is listening on. + * + * @return + */ + public static String getDUnitLocatorAddress() { + return Host.getHost(0).getHostName(); + } + +} +
http://git-wip-us.apache.org/repos/asf/geode/blob/be8db8b7/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscBCDUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscBCDUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscBCDUnitTest.java new file mode 100755 index 0000000..54367fd --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscBCDUnitTest.java @@ -0,0 +1,42 @@ +/* + * 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.internal.cache.tier.sockets; + +import org.apache.geode.test.dunit.standalone.VersionManager; +import org.apache.geode.test.junit.categories.BackwardCompatibilityTest; +import org.apache.geode.test.junit.categories.ClientServerTest; +import org.apache.geode.test.junit.categories.DistributedTest; +import org.apache.geode.test.junit.runners.CategoryWithParameterizedRunnerFactory; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.Collection; + +@Category({DistributedTest.class, ClientServerTest.class, BackwardCompatibilityTest.class}) +@RunWith(Parameterized.class) [email protected](CategoryWithParameterizedRunnerFactory.class) +public class ClientServerMiscBCDUnitTest extends ClientServerMiscDUnitTest { + @Parameterized.Parameters + public static Collection<String> data() { + return VersionManager.getInstance().getVersionsWithoutCurrent(); + } + + public ClientServerMiscBCDUnitTest(String version) { + super(); + testVersion = version; + } + +} http://git-wip-us.apache.org/repos/asf/geode/blob/be8db8b7/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscDUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscDUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscDUnitTest.java index 391653c..b4f3185 100755 --- a/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscDUnitTest.java +++ b/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscDUnitTest.java @@ -14,21 +14,16 @@ */ package org.apache.geode.internal.cache.tier.sockets; -import static org.apache.geode.distributed.ConfigurationProperties.*; -import static org.junit.Assert.*; - -import java.util.Iterator; -import java.util.Properties; -import java.util.Set; +import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS; +import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import org.apache.geode.GemFireConfigException; -import org.apache.geode.cache.client.ClientCache; -import org.apache.geode.cache.client.ClientCacheFactory; -import org.apache.geode.test.dunit.DistributedTestUtils; -import org.apache.geode.test.junit.categories.ClientServerTest; -import org.junit.Test; -import org.junit.experimental.categories.Category; - import org.apache.geode.GemFireIOException; import org.apache.geode.cache.AttributesFactory; import org.apache.geode.cache.Cache; @@ -38,6 +33,7 @@ import org.apache.geode.cache.DataPolicy; import org.apache.geode.cache.Region; import org.apache.geode.cache.RegionAttributes; import org.apache.geode.cache.Scope; +import org.apache.geode.cache.client.ClientCacheFactory; import org.apache.geode.cache.client.NoAvailableServersException; import org.apache.geode.cache.client.Pool; import org.apache.geode.cache.client.PoolManager; @@ -54,6 +50,7 @@ import org.apache.geode.internal.cache.CacheServerImpl; import org.apache.geode.internal.cache.GemFireCacheImpl; import org.apache.geode.internal.cache.LocalRegion; import org.apache.geode.test.dunit.Assert; +import org.apache.geode.test.dunit.DistributedTestUtils; import org.apache.geode.test.dunit.Host; import org.apache.geode.test.dunit.IgnoredException; import org.apache.geode.test.dunit.LogWriterUtils; @@ -62,7 +59,19 @@ import org.apache.geode.test.dunit.VM; import org.apache.geode.test.dunit.Wait; import org.apache.geode.test.dunit.WaitCriterion; import org.apache.geode.test.dunit.cache.internal.JUnit4CacheTestCase; +import org.apache.geode.test.dunit.standalone.VersionManager; +import org.apache.geode.test.junit.categories.ClientServerTest; import org.apache.geode.test.junit.categories.DistributedTest; +import org.apache.geode.test.junit.runners.CategoryWithParameterizedRunnerFactory; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Properties; +import java.util.Set; /** * Tests client server corner cases between Region and Pool @@ -115,11 +124,18 @@ public class ClientServerMiscDUnitTest extends JUnit4CacheTestCase { final int removeRange_2Start = 7; final int removeRange_2End = 9; + protected String testVersion; // version for client caches for backward-compatibility + // testing + + public ClientServerMiscDUnitTest() { + testVersion = VersionManager.CURRENT_VERSION; + } + @Override public final void postSetUp() throws Exception { host = Host.getHost(0); - server1 = host.getVM(0); - server2 = host.getVM(1); + server1 = host.getVM(2); + server2 = host.getVM(3); } private int initServerCache(boolean notifyBySub) { @@ -140,16 +156,16 @@ public class ClientServerMiscDUnitTest extends JUnit4CacheTestCase { int port1 = initServerCache(true); // vm0 int port2 = initServerCache2(true); // vm1 String serverName = NetworkUtils.getServerHostName(Host.getHost(0)); - host.getVM(2).invoke(() -> this.createClientCacheV(serverName, port1)); - host.getVM(3).invoke(() -> this.createClientCacheV(serverName, port2)); + host.getVM(testVersion, 0).invoke(() -> this.createClientCacheV(serverName, port1)); + host.getVM(testVersion, 1).invoke(() -> this.createClientCacheV(serverName, port2)); LogWriterUtils.getLogWriter() .info("Testing concurrent map operations from a client with a distributed region"); - concurrentMapTest(host.getVM(2), "/" + REGION_NAME1); - // TODO add verification in vm3 + concurrentMapTest(host.getVM(testVersion, 0), "/" + REGION_NAME1); + // TODO add verification in vm1 LogWriterUtils.getLogWriter() .info("Testing concurrent map operations from a client with a partitioned region"); - concurrentMapTest(host.getVM(2), "/" + PR_REGION_NAME); - // TODO add verification in vm3 + concurrentMapTest(host.getVM(testVersion, 0), "/" + PR_REGION_NAME); + // TODO add verification in vm1 } @Test @@ -157,16 +173,16 @@ public class ClientServerMiscDUnitTest extends JUnit4CacheTestCase { int port1 = initServerCache(true); // vm0 int port2 = initServerCache2(true); // vm1 String serverName = NetworkUtils.getServerHostName(Host.getHost(0)); - host.getVM(2).invoke(() -> this.createEmptyClientCache(serverName, port1)); - host.getVM(3).invoke(() -> this.createClientCacheV(serverName, port2)); + host.getVM(testVersion, 0).invoke(() -> this.createEmptyClientCache(serverName, port1)); + host.getVM(testVersion, 1).invoke(() -> this.createClientCacheV(serverName, port2)); LogWriterUtils.getLogWriter() .info("Testing concurrent map operations from a client with a distributed region"); - concurrentMapTest(host.getVM(2), "/" + REGION_NAME1); - // TODO add verification in vm3 + concurrentMapTest(host.getVM(testVersion, 0), "/" + REGION_NAME1); + // TODO add verification in vm1 LogWriterUtils.getLogWriter() .info("Testing concurrent map operations from a client with a partitioned region"); - concurrentMapTest(host.getVM(2), "/" + PR_REGION_NAME); - // TODO add verification in vm3 + concurrentMapTest(host.getVM(testVersion, 0), "/" + PR_REGION_NAME); + // TODO add verification in vm1 } /** http://git-wip-us.apache.org/repos/asf/geode/blob/be8db8b7/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscSelectorDUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscSelectorDUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscSelectorDUnitTest.java index e177b79..6ea9c67 100644 --- a/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscSelectorDUnitTest.java +++ b/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscSelectorDUnitTest.java @@ -15,23 +15,16 @@ package org.apache.geode.internal.cache.tier.sockets; import org.apache.geode.test.junit.categories.ClientServerTest; -import org.junit.experimental.categories.Category; -import org.junit.Test; - -import static org.junit.Assert.*; - -import org.apache.geode.test.dunit.cache.internal.JUnit4CacheTestCase; -import org.apache.geode.test.dunit.internal.JUnit4DistributedTestCase; import org.apache.geode.test.junit.categories.DistributedTest; +import org.junit.experimental.categories.Category; /** * Just like parent but enables server thread pool (ie. selector) - * - * */ @Category({DistributedTest.class, ClientServerTest.class}) public class ClientServerMiscSelectorDUnitTest extends ClientServerMiscDUnitTest { + public ClientServerMiscSelectorDUnitTest() { super(); } http://git-wip-us.apache.org/repos/asf/geode/blob/be8db8b7/geode-core/src/test/java/org/apache/geode/test/dunit/DUnitEnv.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/test/dunit/DUnitEnv.java b/geode-core/src/test/java/org/apache/geode/test/dunit/DUnitEnv.java index efc196f..42ccf38 100644 --- a/geode-core/src/test/java/org/apache/geode/test/dunit/DUnitEnv.java +++ b/geode-core/src/test/java/org/apache/geode/test/dunit/DUnitEnv.java @@ -66,8 +66,10 @@ public abstract class DUnitEnv { public abstract int getVMID(); - public abstract BounceResult bounce(int pid) throws RemoteException; + public abstract BounceResult bounce(String version, int pid) throws RemoteException; public abstract File getWorkingDirectory(int pid); + public abstract File getWorkingDirectory(String version, int pid); + } http://git-wip-us.apache.org/repos/asf/geode/blob/be8db8b7/geode-core/src/test/java/org/apache/geode/test/dunit/Host.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/test/dunit/Host.java b/geode-core/src/test/java/org/apache/geode/test/dunit/Host.java old mode 100644 new mode 100755 index 43cbccf..277c803 --- a/geode-core/src/test/java/org/apache/geode/test/dunit/Host.java +++ b/geode-core/src/test/java/org/apache/geode/test/dunit/Host.java @@ -17,9 +17,12 @@ package org.apache.geode.test.dunit; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.apache.geode.test.dunit.standalone.RemoteDUnitVMIF; +import org.apache.geode.test.dunit.standalone.VersionManager; /** * <P> @@ -93,6 +96,22 @@ public abstract class Host implements Serializable { } } + /** + * Reset all VMs to be using the current version of Geode. Some backward-compatibility tests will + * set a VM to a different version. This will ensure that all are using the current build. + */ + public static void setAllVMsToCurrentVersion() { + int numHosts = getHostCount(); + for (int hostIndex = 0; hostIndex < numHosts; hostIndex++) { + Host host = Host.getHost(hostIndex); + int numVMs = host.getVMCount(); + for (int i = 0; i < numVMs; i++) { + host.getVM(VersionManager.CURRENT_VERSION, i); + } + } + + } + ///////////////////// Constructors ////////////////////// /** @@ -145,6 +164,25 @@ public abstract class Host implements Serializable { } /** + * return a collection of all VMs + */ + public Set<VM> getAllVMs() { + return new HashSet<>(vms); + } + + /** + * Returns the nth VM of the given version. Optional operation currently supported only in + * distributedTests. + * + * @param version + * @param n + * @return the requested VM + */ + public VM getVM(String version, int n) { + throw new UnsupportedOperationException("Not supported in this implementation of Host"); + } + + /** * Adds a VM to this <code>Host</code> with the given process id and client record. */ protected void addVM(int pid, RemoteDUnitVMIF client) { http://git-wip-us.apache.org/repos/asf/geode/blob/be8db8b7/geode-core/src/test/java/org/apache/geode/test/dunit/Invoke.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/test/dunit/Invoke.java b/geode-core/src/test/java/org/apache/geode/test/dunit/Invoke.java index a09f5ff..002abd4 100755 --- a/geode-core/src/test/java/org/apache/geode/test/dunit/Invoke.java +++ b/geode-core/src/test/java/org/apache/geode/test/dunit/Invoke.java @@ -52,8 +52,7 @@ public class Invoke { for (int hostIndex = 0; hostIndex < Host.getHostCount(); hostIndex++) { Host host = Host.getHost(hostIndex); - for (int vmIndex = 0; vmIndex < host.getVMCount(); vmIndex++) { - VM vm = host.getVM(vmIndex); + for (VM vm : host.getAllVMs()) { if (name != null) vm.invoke(name, runnable); else @@ -74,8 +73,7 @@ public class Invoke { for (int hostIndex = 0; hostIndex < Host.getHostCount(); hostIndex++) { Host host = Host.getHost(hostIndex); - for (int vmIndex = 0; vmIndex < host.getVMCount(); vmIndex++) { - VM vm = host.getVM(vmIndex); + for (VM vm : host.getAllVMs()) { vm.invoke(targetClass, targetMethod); } } @@ -93,8 +91,7 @@ public class Invoke { for (int hostIndex = 0; hostIndex < Host.getHostCount(); hostIndex++) { Host host = Host.getHost(hostIndex); - for (int vmIndex = 0; vmIndex < host.getVMCount(); vmIndex++) { - VM vm = host.getVM(vmIndex); + for (VM vm : host.getAllVMs()) { vm.invoke(targetClass, targetMethod, methodArgs); } } @@ -116,8 +113,7 @@ public class Invoke { Map<VM, T> ret = new HashMap<VM, T>(); for (int h = 0; h < Host.getHostCount(); h++) { Host host = Host.getHost(h); - for (int v = 0; v < host.getVMCount(); v++) { - VM vm = host.getVM(v); + for (VM vm : host.getAllVMs()) { if (name != null) ret.put(vm, vm.invoke(name, callable)); else http://git-wip-us.apache.org/repos/asf/geode/blob/be8db8b7/geode-core/src/test/java/org/apache/geode/test/dunit/VM.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/test/dunit/VM.java b/geode-core/src/test/java/org/apache/geode/test/dunit/VM.java index 04d2951..6055f8b 100644 --- a/geode-core/src/test/java/org/apache/geode/test/dunit/VM.java +++ b/geode-core/src/test/java/org/apache/geode/test/dunit/VM.java @@ -28,6 +28,7 @@ import org.apache.geode.internal.process.ProcessUtils; import org.apache.geode.test.dunit.standalone.BounceResult; import org.apache.geode.test.dunit.standalone.RemoteDUnitVMIF; import org.apache.geode.test.dunit.standalone.StandAloneDUnitEnv; +import org.apache.geode.test.dunit.standalone.VersionManager; /** * This class represents a Java Virtual Machine that runs on a host. @@ -41,6 +42,9 @@ public class VM implements Serializable { /** The process id of this VM */ private int pid; + /** The version of Geode used in this VM */ + private String version; + /** The hydra client for this VM */ private RemoteDUnitVMIF client; @@ -69,13 +73,32 @@ public class VM implements Serializable { } /** + * Returns the name of a VM for use in the RMI naming service or working directory on disk + */ + public static String getVMName(String version, int pid) { + if (pid == -2) { + return "locator"; + } + if (pid < 0 || VersionManager.isCurrentVersion(version)) { + return "vm" + pid; + } else { + return "vm" + pid + "_v" + version; + } + } + + /** * Creates a new {@code VM} that runs on a given host with a given process id. * * TODO: change pid to reflect value from {@link ProcessUtils#identifyPid()} */ public VM(final Host host, final int pid, final RemoteDUnitVMIF client) { + this(host, VersionManager.CURRENT_VERSION, pid, client); + } + + public VM(final Host host, final String version, final int pid, final RemoteDUnitVMIF client) { this.host = host; this.pid = pid; + this.version = version; this.client = client; this.available = true; } @@ -88,6 +111,16 @@ public class VM implements Serializable { } /** + * Returns the version of Geode used in this VM. + * + * @see VersionManager#CURRENT_VERSION + * @see Host#getVM(String, int) + */ + public String getVersion() { + return this.version; + } + + /** * Returns the process id of this {@code VM}. */ public int getPid() { @@ -359,6 +392,10 @@ public class VM implements Serializable { * {@code hydra.Prms#maxClientStartupWaitSec}. */ public synchronized void bounce() { + bounce(this.version); + } + + public synchronized void bounce(String targetVersion) { if (!this.available) { throw new RMIException(this, getClass().getName(), "bounceVM", new IllegalStateException("VM not available: " + this)); @@ -367,9 +404,10 @@ public class VM implements Serializable { this.available = false; try { - BounceResult result = DUnitEnv.get().bounce(this.pid); + BounceResult result = DUnitEnv.get().bounce(targetVersion, this.pid); this.pid = result.getNewPid(); this.client = result.getNewClient(); + this.version = targetVersion; this.available = true; } catch (UnsupportedOperationException e) { @@ -386,11 +424,12 @@ public class VM implements Serializable { } public String toString() { - return "VM " + getPid() + " running on " + getHost(); + return "VM " + getPid() + " running on " + getHost() + + (VersionManager.isCurrentVersion(version) ? "" : (" with version " + version)); } public File getWorkingDirectory() { - return DUnitEnv.get().getWorkingDirectory(getPid()); + return DUnitEnv.get().getWorkingDirectory(getVersion(), getPid()); } private MethExecutorResult execute(final Class targetClass, final String methodName, http://git-wip-us.apache.org/repos/asf/geode/blob/be8db8b7/geode-core/src/test/java/org/apache/geode/test/dunit/standalone/ChildVM.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/test/dunit/standalone/ChildVM.java b/geode-core/src/test/java/org/apache/geode/test/dunit/standalone/ChildVM.java index b85d0b5..634e09f 100644 --- a/geode-core/src/test/java/org/apache/geode/test/dunit/standalone/ChildVM.java +++ b/geode-core/src/test/java/org/apache/geode/test/dunit/standalone/ChildVM.java @@ -18,6 +18,7 @@ import java.rmi.Naming; import org.apache.geode.internal.OSProcess; import org.apache.geode.internal.logging.LogService; +import org.apache.geode.test.dunit.VM; import org.apache.geode.test.dunit.internal.JUnit4DistributedTestCase; import org.apache.geode.test.dunit.standalone.DUnitLauncher.MasterRemote; @@ -43,14 +44,19 @@ public class ChildVM { try { int namingPort = Integer.getInteger(DUnitLauncher.RMI_PORT_PARAM); int vmNum = Integer.getInteger(DUnitLauncher.VM_NUM_PARAM); + String geodeVersion = System.getProperty(DUnitLauncher.VM_VERSION_PARAM); int pid = OSProcess.getId(); logger.info("VM" + vmNum + " is launching" + (pid > 0 ? " with PID " + pid : "")); + if (!VersionManager.isCurrentVersion(geodeVersion)) { + logger.info("This VM is using Geode version {}", geodeVersion); + } MasterRemote holder = (MasterRemote) Naming .lookup("//localhost:" + namingPort + "/" + DUnitLauncher.MASTER_PARAM); DUnitLauncher.init(holder); DUnitLauncher.locatorPort = holder.getLocatorPort(); final RemoteDUnitVM dunitVM = new RemoteDUnitVM(); - Naming.rebind("//localhost:" + namingPort + "/vm" + vmNum, dunitVM); + final String name = "//localhost:" + namingPort + "/vm" + vmNum; + Naming.rebind(name, dunitVM); JUnit4DistributedTestCase.initializeBlackboard(); holder.signalVMReady(); // This loop is here so this VM will die even if the master is mean killed. http://git-wip-us.apache.org/repos/asf/geode/blob/be8db8b7/geode-core/src/test/java/org/apache/geode/test/dunit/standalone/DUnitLauncher.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/test/dunit/standalone/DUnitLauncher.java b/geode-core/src/test/java/org/apache/geode/test/dunit/standalone/DUnitLauncher.java index 8587ea5..abbfea9 100644 --- a/geode-core/src/test/java/org/apache/geode/test/dunit/standalone/DUnitLauncher.java +++ b/geode-core/src/test/java/org/apache/geode/test/dunit/standalone/DUnitLauncher.java @@ -14,8 +14,15 @@ */ package org.apache.geode.test.dunit.standalone; -import batterytest.greplogs.ExpectedStrings; -import batterytest.greplogs.LogConsumer; +import static org.apache.geode.distributed.ConfigurationProperties.DISABLE_AUTO_RECONNECT; +import static org.apache.geode.distributed.ConfigurationProperties.ENABLE_CLUSTER_CONFIGURATION; +import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER; +import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS; +import static org.apache.geode.distributed.ConfigurationProperties.LOG_LEVEL; +import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT; +import static org.apache.geode.distributed.ConfigurationProperties.USE_CLUSTER_CONFIGURATION; +import static org.apache.geode.distributed.internal.DistributionConfig.GEMFIRE_PREFIX; + import org.apache.geode.distributed.Locator; import org.apache.geode.distributed.internal.DistributionConfig; import org.apache.geode.distributed.internal.InternalLocator; @@ -26,8 +33,6 @@ import org.apache.geode.test.dunit.DUnitEnv; import org.apache.geode.test.dunit.Host; import org.apache.geode.test.dunit.SerializableCallable; import org.apache.geode.test.dunit.VM; -import hydra.MethExecutorResult; - import org.apache.geode.test.dunit.internal.JUnit4DistributedTestCase; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; @@ -37,37 +42,55 @@ import org.apache.logging.log4j.core.config.LoggerConfig; import org.apache.logging.log4j.core.layout.PatternLayout; import org.junit.Assert; -import java.io.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; import java.lang.reflect.Method; import java.net.InetAddress; import java.net.URISyntaxException; import java.nio.channels.FileChannel; import java.nio.charset.Charset; -import java.rmi.*; +import java.rmi.AccessException; +import java.rmi.AlreadyBoundException; +import java.rmi.NotBoundException; +import java.rmi.Remote; +import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject; import java.util.List; import java.util.Properties; - -import static org.apache.geode.distributed.ConfigurationProperties.*; +import batterytest.greplogs.ExpectedStrings; +import batterytest.greplogs.LogConsumer; +import hydra.MethExecutorResult; /** * A class to build a fake test configuration and launch some DUnit VMS. - * + * * For use within eclipse. This class completely skips hydra and just starts some vms directly, * creating a fake test configuration - * + * * Also, it's a good idea to set your working directory, because the test code a lot of files that * it leaves around. */ public class DUnitLauncher { - /** change this to use a different log level in unit tests */ + /** + * change this to use a different log level in unit tests + */ public static final String logLevel = System.getProperty("logLevel", "info"); public static final String LOG4J = System.getProperty("log4j.configurationFile"); + /** + * change this to have dunit/vmX directories deleted and recreated when processes are launched + */ + public static final boolean MAKE_NEW_WORKING_DIRS = + Boolean.getBoolean("makeNewWorkingDirsOnBounce"); + static int locatorPort; private static final int NUM_VMS = 4; @@ -83,12 +106,12 @@ public class DUnitLauncher { public static final boolean LOCATOR_LOG_TO_DISK = Boolean.getBoolean("locatorLogToDisk"); static final String MASTER_PARAM = "DUNIT_MASTER"; - public static final String RMI_PORT_PARAM = - DistributionConfig.GEMFIRE_PREFIX + "DUnitLauncher.RMI_PORT"; - static final String VM_NUM_PARAM = DistributionConfig.GEMFIRE_PREFIX + "DUnitLauncher.VM_NUM"; - private static final String LAUNCHED_PROPERTY = - DistributionConfig.GEMFIRE_PREFIX + "DUnitLauncher.LAUNCHED"; + public static final String RMI_PORT_PARAM = GEMFIRE_PREFIX + "DUnitLauncher.RMI_PORT"; + static final String VM_NUM_PARAM = GEMFIRE_PREFIX + "DUnitLauncher.VM_NUM"; + static final String VM_VERSION_PARAM = GEMFIRE_PREFIX + "DUnitLauncher.VM_VERSION"; + + private static final String LAUNCHED_PROPERTY = GEMFIRE_PREFIX + "DUnitLauncher.LAUNCHED"; private static Master master; @@ -123,6 +146,8 @@ public class DUnitLauncher { throw new RuntimeException("Unable to launch dunit VMS", e); } } + + Host.setAllVMsToCurrentVersion(); } /** @@ -189,7 +214,6 @@ public class DUnitLauncher { } }); - // Create a VM for the locator processManager.launchVM(LOCATOR_VM_NUM); @@ -202,7 +226,6 @@ public class DUnitLauncher { init(master); - // Launch an initial set of VMs for (int i = 0; i < NUM_VMS; i++) { processManager.launchVM(i); @@ -305,7 +328,7 @@ public class DUnitLauncher { addSuspectFileAppender(workspaceDir); // Free off heap memory when disconnecting from the distributed system - System.setProperty(DistributionConfig.GEMFIRE_PREFIX + "free-off-heap-memory", "true"); + System.setProperty(GEMFIRE_PREFIX + "free-off-heap-memory", "true"); // indicate that this CM is controlled by the eclipse dunit. System.setProperty(LAUNCHED_PROPERTY, "true"); @@ -368,6 +391,7 @@ public class DUnitLauncher { } } + public interface MasterRemote extends Remote { public int getLocatorPort() throws RemoteException; @@ -376,6 +400,8 @@ public class DUnitLauncher { public void ping() throws RemoteException; public BounceResult bounce(int pid) throws RemoteException; + + public BounceResult bounce(String version, int pid) throws RemoteException; } public static class Master extends UnicastRemoteObject implements MasterRemote { @@ -404,13 +430,19 @@ public class DUnitLauncher { @Override public BounceResult bounce(int pid) { - processManager.bounce(pid); + return bounce(VersionManager.CURRENT_VERSION, pid); + } + + @Override + public BounceResult bounce(String version, int pid) { + processManager.bounce(version, pid); try { if (!processManager.waitForVMs(STARTUP_TIMEOUT)) { throw new RuntimeException("VMs did not start up with 30 seconds"); } - RemoteDUnitVMIF remote = (RemoteDUnitVMIF) registry.lookup("vm" + pid); + RemoteDUnitVMIF remote = + (RemoteDUnitVMIF) registry.lookup(VM.getVMName(VersionManager.CURRENT_VERSION, pid)); return new BounceResult(pid, remote); } catch (RemoteException | NotBoundException e) { throw new RuntimeException("could not lookup name", e); @@ -447,25 +479,45 @@ public class DUnitLauncher { @Override public VM getVM(int n) { + return getVM(VersionManager.CURRENT_VERSION, n); + } + @Override + public VM getVM(String version, int n) { if (n == DEBUGGING_VM_NUM) { // for ease of debugging, pass -1 to get the local VM return debuggingVM; } + if (n < getVMCount()) { + VM current = super.getVM(n); + if (!current.getVersion().equals(version)) { + System.out.println( + "Bouncing VM" + n + " from version " + current.getVersion() + " to " + version); + current.bounce(version); + } + return current; + } + int oldVMCount = getVMCount(); if (n >= oldVMCount) { // If we don't have a VM with that number, dynamically create it. try { - for (int i = oldVMCount; i <= n; i++) { + // first fill in any gaps, to keep the superclass, Host, happy + for (int i = oldVMCount; i < n; i++) { processManager.launchVM(i); } processManager.waitForVMs(STARTUP_TIMEOUT); - for (int i = oldVMCount; i <= n; i++) { + for (int i = oldVMCount; i < n; i++) { addVM(i, processManager.getStub(i)); } + // now create the one we really want + processManager.launchVM(version, n, false); + processManager.waitForVMs(STARTUP_TIMEOUT); + addVM(n, processManager.getStub(n)); + } catch (IOException | InterruptedException | NotBoundException e) { throw new RuntimeException("Could not dynamically launch vm + " + n, e); } http://git-wip-us.apache.org/repos/asf/geode/blob/be8db8b7/geode-core/src/test/java/org/apache/geode/test/dunit/standalone/ProcessManager.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/test/dunit/standalone/ProcessManager.java b/geode-core/src/test/java/org/apache/geode/test/dunit/standalone/ProcessManager.java index c3c33d0..dce4353 100644 --- a/geode-core/src/test/java/org/apache/geode/test/dunit/standalone/ProcessManager.java +++ b/geode-core/src/test/java/org/apache/geode/test/dunit/standalone/ProcessManager.java @@ -38,41 +38,54 @@ import org.apache.commons.io.FileUtils; import org.apache.geode.distributed.internal.DistributionConfig; import org.apache.geode.distributed.internal.InternalLocator; import org.apache.geode.internal.FileUtil; +import org.apache.geode.test.dunit.VM; /** * */ public class ProcessManager { private int namingPort; - private Map<Integer, ProcessHolder> processes = new HashMap<Integer, ProcessHolder>(); + private Map<Integer, ProcessHolder> processes = new HashMap<>(); private File log4jConfig; private int pendingVMs; private Registry registry; private int debugPort = Integer.getInteger("dunit.debug.basePort", 0); private int suspendVM = Integer.getInteger("dunit.debug.suspendVM", -100); + private VersionManager versionManager; public ProcessManager(int namingPort, Registry registry) { + this.versionManager = VersionManager.getInstance(); this.namingPort = namingPort; this.registry = registry; } public synchronized void launchVM(int vmNum) throws IOException { - if (processes.containsKey(vmNum)) { - throw new IllegalStateException("VM " + vmNum + " is already running."); + launchVM(VersionManager.CURRENT_VERSION, vmNum, false); + } + + public synchronized void launchVM(String version, int vmNum, boolean bouncedVM) + throws IOException { + if (processes.containsKey(version)) { + throw new IllegalStateException( + "For version " + version + ", VM " + vmNum + " is already running."); } - String[] cmd = buildJavaCommand(vmNum, namingPort); + String[] cmd = buildJavaCommand(vmNum, namingPort, version); System.out.println("Executing " + Arrays.toString(cmd)); - File workingDir = getVMDir(vmNum); - try { - FileUtil.delete(workingDir); - } catch (IOException e) { - // This delete is occasionally failing on some platforms, maybe due to a lingering - // process. Allow the process to be launched anyway. - System.err.println("Unable to delete " + workingDir + ". Currently contains " - + Arrays.asList(workingDir.list())); + File workingDir = getVMDir(version, vmNum); + if (!workingDir.exists()) { + workingDir.mkdirs(); + } else if (!bouncedVM || DUnitLauncher.MAKE_NEW_WORKING_DIRS) { + try { + FileUtil.delete(workingDir); + } catch (IOException e) { + // This delete is occasionally failing on some platforms, maybe due to a lingering + // process. Allow the process to be launched anyway. + System.err.println("Unable to delete " + workingDir + ". Currently contains " + + Arrays.asList(workingDir.list())); + } + workingDir.mkdirs(); } - workingDir.mkdirs(); if (log4jConfig != null) { FileUtils.copyFileToDirectory(log4jConfig, workingDir); } @@ -82,12 +95,18 @@ public class ProcessManager { pendingVMs++; ProcessHolder holder = new ProcessHolder(process); processes.put(vmNum, holder); - linkStreams(vmNum, holder, process.getErrorStream(), System.err); - linkStreams(vmNum, holder, process.getInputStream(), System.out); + linkStreams(version, vmNum, holder, process.getErrorStream(), System.err); + linkStreams(version, vmNum, holder, process.getInputStream(), System.out); } - public static File getVMDir(int vmNum) { - return new File(DUnitLauncher.DUNIT_DIR, "vm" + vmNum); + public void validateVersion(String version) { + if (!versionManager.isValidVersion(version)) { + throw new IllegalArgumentException("Version " + version + " is not configured for use"); + } + } + + public static File getVMDir(String version, int vmNum) { + return new File(DUnitLauncher.DUNIT_DIR, VM.getVMName(VersionManager.CURRENT_VERSION, vmNum)); } public synchronized void killVMs() { @@ -107,7 +126,7 @@ public class ProcessManager { return false; } - public synchronized void bounce(int vmNum) { + public synchronized void bounce(String version, int vmNum) { if (!processes.containsKey(vmNum)) { throw new IllegalStateException("No such process " + vmNum); } @@ -115,18 +134,18 @@ public class ProcessManager { ProcessHolder holder = processes.remove(vmNum); holder.kill(); holder.getProcess().waitFor(); - launchVM(vmNum); + launchVM(version, vmNum, true); } catch (InterruptedException | IOException e) { throw new RuntimeException("Unable to restart VM " + vmNum, e); } } - private void linkStreams(final int vmNum, final ProcessHolder holder, final InputStream in, - final PrintStream out) { + private void linkStreams(final String version, final int vmNum, final ProcessHolder holder, + final InputStream in, final PrintStream out) { Thread ioTransport = new Thread() { public void run() { BufferedReader reader = new BufferedReader(new InputStreamReader(in)); - String vmName = (vmNum == -2) ? "[locator]" : "[vm_" + vmNum + "]"; + String vmName = "[" + VM.getVMName(version, vmNum) + "] "; try { String line = reader.readLine(); while (line != null) { @@ -151,9 +170,16 @@ public class ProcessManager { ioTransport.start(); } - private String[] buildJavaCommand(int vmNum, int namingPort) { + private String[] buildJavaCommand(int vmNum, int namingPort, String version) { String cmd = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java"; - String classPath = System.getProperty("java.class.path"); + String dunitClasspath = System.getProperty("java.class.path"); + String classPath; + if (!VersionManager.isCurrentVersion(version)) { + classPath = versionManager.getClasspath(version) + File.pathSeparator + dunitClasspath; + } else { + classPath = dunitClasspath; + } + // String tmpDir = System.getProperty("java.io.tmpdir"); String agent = getAgentString(); @@ -163,7 +189,7 @@ public class ProcessManager { debugPort++; } - String jdkSuspend = vmNum == suspendVM ? "y" : "n"; + String jdkSuspend = vmNum == suspendVM ? "y" : "n"; // ignore version ArrayList<String> cmds = new ArrayList<String>(); cmds.add(cmd); cmds.add("-classpath"); @@ -171,9 +197,12 @@ public class ProcessManager { cmds.add(classPath); cmds.add("-D" + DUnitLauncher.RMI_PORT_PARAM + "=" + namingPort); cmds.add("-D" + DUnitLauncher.VM_NUM_PARAM + "=" + vmNum); + cmds.add("-D" + DUnitLauncher.VM_VERSION_PARAM + "=" + version); cmds.add("-D" + DUnitLauncher.WORKSPACE_DIR_PARAM + "=" + new File(".").getAbsolutePath()); if (vmNum >= 0) { // let the locator print a banner - cmds.add("-D" + InternalLocator.INHIBIT_DM_BANNER + "=true"); + if (version.equals(VersionManager.CURRENT_VERSION)) { // enable the banner for older versions + cmds.add("-D" + InternalLocator.INHIBIT_DM_BANNER + "=true"); + } } else { // most distributed unit tests were written under the assumption that network partition // detection is disabled, so we turn it off in the locator. Tests for network partition @@ -293,7 +322,46 @@ public class ProcessManager { public RemoteDUnitVMIF getStub(int i) throws AccessException, RemoteException, NotBoundException, InterruptedException { + return getStub(VersionManager.CURRENT_VERSION, i); + } + + public RemoteDUnitVMIF getStub(String version, int i) + throws AccessException, RemoteException, NotBoundException, InterruptedException { waitForVMs(DUnitLauncher.STARTUP_TIMEOUT); return (RemoteDUnitVMIF) registry.lookup("vm" + i); } + + private static class VersionedVMNumber { + String version; + int number; + + VersionedVMNumber(String version, int number) { + this.version = version; + this.number = number; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + VersionedVMNumber that = (VersionedVMNumber) o; + + if (number != that.number) { + return false; + } + return version.equals(that.version); + } + + @Override + public int hashCode() { + int result = version.hashCode(); + result = 31 * result + number; + return result; + } + } } http://git-wip-us.apache.org/repos/asf/geode/blob/be8db8b7/geode-core/src/test/java/org/apache/geode/test/dunit/standalone/StandAloneDUnitEnv.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/test/dunit/standalone/StandAloneDUnitEnv.java b/geode-core/src/test/java/org/apache/geode/test/dunit/standalone/StandAloneDUnitEnv.java index 3d554ed..1dac10c 100644 --- a/geode-core/src/test/java/org/apache/geode/test/dunit/standalone/StandAloneDUnitEnv.java +++ b/geode-core/src/test/java/org/apache/geode/test/dunit/standalone/StandAloneDUnitEnv.java @@ -60,13 +60,18 @@ public class StandAloneDUnitEnv extends DUnitEnv { } @Override - public BounceResult bounce(int pid) throws RemoteException { - return master.bounce(pid); + public BounceResult bounce(String version, int pid) throws RemoteException { + return master.bounce(version, pid); } @Override public File getWorkingDirectory(int pid) { - return ProcessManager.getVMDir(pid); + return getWorkingDirectory(VersionManager.CURRENT_VERSION, pid); + } + + @Override + public File getWorkingDirectory(String version, int pid) { + return ProcessManager.getVMDir(version, pid); } }
