/* * 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 static org.apache.geode.distributed.ConfigurationProperties.*; import static org.junit.Assert.*; import java.util.Properties; import org.apache.geode.test.junit.categories.ClientServerTest; import org.junit.Test; import org.junit.experimental.categories.Category; import org.apache.geode.cache.AttributesFactory; import org.apache.geode.cache.Cache; import org.apache.geode.cache.CacheFactory; 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.PoolManager; import org.apache.geode.cache.client.internal.ConnectionFactoryImpl; import org.apache.geode.cache.client.internal.PoolImpl; import org.apache.geode.cache.server.CacheServer; import org.apache.geode.distributed.DistributedSystem; import org.apache.geode.internal.AvailablePort; import org.apache.geode.internal.cache.tier.ConnectionProxy; import org.apache.geode.test.dunit.Assert; import org.apache.geode.test.dunit.Host; 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.junit.categories.DistributedTest; /** * Test to verify that server responds to a higher versioned client. */ @Category({DistributedTest.class, ClientServerTest.class}) public class BackwardCompatibilityHigherVersionClientDUnitTest extends JUnit4DistributedTestCase { /** the cache */ private static Cache cache = null; private VM server1 = null; private static VM client1 = null; /** name of the test region */ private static final String REGION_NAME = "BackwardCompatibilityHigherVersionClientDUnitTest_Region"; static int CLIENT_ACK_INTERVAL = 5000; private static final String k1 = "k1"; private static final String k2 = "k2"; private static final String client_k1 = "client-k1"; private static final String client_k2 = "client-k2"; private static short currentClientVersion = ConnectionProxy.VERSION.ordinal(); @Override public final void postSetUp() throws Exception { final Host host = Host.getHost(0); server1 = host.getVM(0); client1 = host.getVM(1); } private void createCache(Properties props) throws Exception { DistributedSystem ds = getSystem(props); ds.disconnect(); ds = getSystem(props); assertNotNull(ds); cache = CacheFactory.create(ds); assertNotNull(cache); addExceptions(); } public static void createClientCache(String host, Integer port1) throws Exception { new BackwardCompatibilityHigherVersionClientDUnitTest(); Properties props = new Properties(); props.setProperty(MCAST_PORT, "0"); props.setProperty(LOCATORS, ""); new BackwardCompatibilityHigherVersionClientDUnitTest().createCache(props); PoolImpl p = (PoolImpl) PoolManager.createFactory().addServer(host, port1.intValue()) .setSubscriptionEnabled(true).setSubscriptionRedundancy(1).setThreadLocalConnections(true) .setMinConnections(1).setFreeConnectionTimeout(200000).setReadTimeout(200000) .setPingInterval(10000).setRetryAttempts(1).setSubscriptionAckInterval(CLIENT_ACK_INTERVAL) .create("BackwardCompatibilityHigherVersionClientDUnitTest"); AttributesFactory factory = new AttributesFactory(); factory.setScope(Scope.DISTRIBUTED_ACK); factory.setPoolName(p.getName()); RegionAttributes attrs = factory.create(); cache.createRegion(REGION_NAME, attrs); } public static Integer createServerCache() throws Exception { new BackwardCompatibilityHigherVersionClientDUnitTest().createCache(new Properties()); AttributesFactory factory = new AttributesFactory(); factory.setScope(Scope.DISTRIBUTED_ACK); factory.setDataPolicy(DataPolicy.REPLICATE); RegionAttributes attrs = factory.create(); cache.createRegion(REGION_NAME, attrs); int port = AvailablePort.getRandomAvailablePort(AvailablePort.SOCKET); CacheServer server1 = cache.addCacheServer(); server1.setPort(port); server1.setNotifyBySubscription(true); server1.start(); return new Integer(server1.getPort()); } @Override public final void postTearDown() throws Exception { client1.invoke( () -> BackwardCompatibilityHigherVersionClientDUnitTest.unsetHandshakeVersionForTesting()); client1.invoke( () -> BackwardCompatibilityHigherVersionClientDUnitTest.unsetConnectionToServerFailed()); // close the clients first client1.invoke(() -> BackwardCompatibilityHigherVersionClientDUnitTest.closeCache()); // then close the servers server1.invoke(() -> BackwardCompatibilityHigherVersionClientDUnitTest.closeCache()); } public static void closeCache() { if (cache != null && !cache.isClosed()) { removeExceptions(); cache.close(); cache.getDistributedSystem().disconnect(); } } /** * Verify that server responds to a higher versioned client. */ @Test public void testHigherVersionedClient() { Integer port1 = ((Integer) server1 .invoke(() -> BackwardCompatibilityHigherVersionClientDUnitTest.createServerCache())); client1.invoke( () -> BackwardCompatibilityHigherVersionClientDUnitTest.setHandshakeVersionForTesting()); client1.invoke(() -> BackwardCompatibilityHigherVersionClientDUnitTest .createClientCache(NetworkUtils.getServerHostName(server1.getHost()), port1)); client1.invoke( () -> BackwardCompatibilityHigherVersionClientDUnitTest.verifyConnectionToServerFailed()); } /* * Prepare to write invalid version ordinal byte (current+1) from client to server during * handshake. */ public static void setHandshakeVersionForTesting() throws Exception { HandShake.setVersionForTesting((short) (currentClientVersion + 1)); } public static void addExceptions() throws Exception { if (cache != null && !cache.isClosed()) { cache.getLogger().info("<ExpectedException action=add>" + "UnsupportedVersionException" + "</ExpectedException>"); cache.getLogger().info("<ExpectedException action=add>" + "ServerRefusedConnectionException" + "</ExpectedException>"); cache.getLogger() .info("<ExpectedException action=add>" + "SocketException" + "</ExpectedException>"); cache.getLogger().info("<ExpectedException action=add>" + "Could not initialize a primary queue" + "</ExpectedException>"); } } public static void removeExceptions() { if (cache != null && !cache.isClosed()) { cache.getLogger().info("<ExpectedException action=remove>" + "UnsupportedVersionException" + "</ExpectedException>"); cache.getLogger().info("<ExpectedException action=remove>" + "ServerRefusedConnectionException" + "</ExpectedException>"); cache.getLogger() .info("<ExpectedException action=remove>" + "SocketException" + "</ExpectedException>"); cache.getLogger().info("<ExpectedException action=remove>" + "Could not initialize a primary queue" + "</ExpectedException>"); } } /* * Verify that Client failed when connecting to Server */ public static void verifyConnectionToServerFailed() throws Exception { assertTrue("Higher version Client connected successfully to Server", ConnectionFactoryImpl.testFailedConnectionToServer == true); } /* * Prepare to revert back to writing valid version ordinal byte from client to server during * handshake. */ public static void unsetHandshakeVersionForTesting() throws Exception { HandShake.setVersionForTesting(currentClientVersion); } /* * Restore ConnectionFactoryImpl.testFailedConnectionToServer to its default value. */ public static void unsetConnectionToServerFailed() throws Exception { ConnectionFactoryImpl.testFailedConnectionToServer = false; } public static void destroyRegion() { try { Region r = cache.getRegion("/" + REGION_NAME); assertNotNull(r); r.destroyRegion(); } catch (Exception ex) { Assert.fail("failed while destroy region ", ex); } } }