blob: 2fbf452226b7324680696af9d6f47f874032929c [file] [log] [blame]
/*
* 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;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import org.junit.Assert;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.apache.geode.cache.Cache;
import org.apache.geode.distributed.ConfigurationProperties;
import org.apache.geode.distributed.internal.DistributedSystemService;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.distributed.internal.DistributionConfigImpl;
import org.apache.geode.internal.ByteArrayDataInput;
import org.apache.geode.internal.HeapDataOutputStream;
import org.apache.geode.internal.InternalDataSerializer;
import org.apache.geode.internal.Version;
import org.apache.geode.internal.VersionedDataInputStream;
import org.apache.geode.internal.VersionedDataOutputStream;
import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.internal.cache.tier.sockets.OldClientSupportService;
import org.apache.geode.test.dunit.cache.internal.JUnit4CacheTestCase;
import org.apache.geode.test.junit.categories.SerializationTest;
import com.gemstone.gemfire.OldClientSupportProvider;
@Category({SerializationTest.class})
@SuppressWarnings("deprecation")
public class OldClientSupportDUnitTest extends JUnit4CacheTestCase {
private static final List<String> allGeodeThrowableClasses =
Arrays.asList(new String[] {"org.apache.geode.cache.execute.EmptyRegionFunctionException",});
private static final List<String> newArrayClassNames = Arrays.asList(new String[] {
"[Lorg.apache.geode.class1", "[[Lorg.apache.geode.class1", "[[[Lorg.apache.geode.class1"});
private static final List<String> oldArrayClassNames =
Arrays.asList(new String[] {"[Lcom.gemstone.gemfire.class1", "[[Lcom.gemstone.gemfire.class1",
"[[[Lcom.gemstone.gemfire.class1"});
private static final List<String> allNonconformingArrayClassNames = Arrays.asList(
new String[] {"[Lmypackage.org.apache.geode.class2", "[[Lmypackage.org.apache.geode.class2"});
private Cache myCache;
@Override
public void postSetUp() throws Exception {
super.postSetUp();
myCache = getCache();
}
@Test
public void cacheInstallsOldClientSupportServiceProvider() throws Exception {
Assert.assertNotNull(((InternalCache) myCache).getService(OldClientSupportService.class));
}
/**
* This test can be vastly simplified if clients have the ability to translate org.apache.geode
* package prefixes to com.gemstone.gemfire. In that case we will only need to test translation of
* EmtpyRegionFunctionException.
*/
@Test
public void testConversionOfThrowablesForOldClients() throws Exception {
List<Throwable> problems = new LinkedList<>();
for (String geodeClassName : allGeodeThrowableClasses) {
try {
convertThrowable(geodeClassName);
} catch (Exception e) {
System.out.println("-- failed");
Exception failure =
new Exception("Failed processing " + geodeClassName + ": " + e.toString());
failure.initCause(e);
problems.add(failure);
}
}
if (!problems.isEmpty()) {
Assert.fail(problems.toString());
}
}
@Test
public void testConversionOfArrayTypes() throws Exception {
OldClientSupportService oldClientSupport = OldClientSupportProvider.getService(myCache);
Version oldClientVersion = Version.GFE_82;
VersionedDataOutputStream dout = new VersionedDataOutputStream(
new HeapDataOutputStream(10, oldClientVersion), oldClientVersion);
for (String geodeClassName : newArrayClassNames) {
String newName = oldClientSupport.processOutgoingClassName(geodeClassName, dout);
Assert.assertNotEquals(geodeClassName, newName);
}
for (String className : allNonconformingArrayClassNames) {
String newName = oldClientSupport.processOutgoingClassName(className, dout);
Assert.assertEquals(className, newName);
}
VersionedDataInputStream din = new VersionedDataInputStream(
new DataInputStream(new ByteArrayInputStream(new byte[10])), oldClientVersion);
for (String oldClassName : oldArrayClassNames) {
String newName = oldClientSupport.processIncomingClassName(oldClassName, din);
Assert.assertNotEquals(oldClassName, newName);
}
}
private void convertThrowable(String geodeClassName) throws Exception {
Version oldClientVersion = Version.GFE_82;
final String comGemstoneGemFire = "com.gemstone.gemfire";
final int comGemstoneGemFireLength = comGemstoneGemFire.length();
OldClientSupportService oldClientSupport = OldClientSupportProvider.getService(myCache);
System.out.println("checking " + geodeClassName);
Class geodeClass = Class.forName(geodeClassName);
Object geodeObject = instantiate(geodeClass);
if (geodeObject instanceof Throwable) {
Throwable geodeThrowable = (Throwable) instantiate(geodeClass);
Throwable gemfireThrowable = oldClientSupport.getThrowable(geodeThrowable, oldClientVersion);
Assert.assertEquals(
"Failed to convert " + geodeClassName + ". Throwable class is "
+ gemfireThrowable.getClass().getName(),
comGemstoneGemFire,
gemfireThrowable.getClass().getName().substring(0, comGemstoneGemFireLength));
}
}
private Object instantiate(Class<?> aClass) throws Exception {
Constructor<?> c = null;
try {
c = aClass.getConstructor();
return c.newInstance();
} catch (NoSuchMethodException e1) {
try {
c = aClass.getConstructor(String.class);
return c.newInstance("test instance");
} catch (NoSuchMethodException e2) {
try {
c = aClass.getConstructor(String.class, Throwable.class);
return c.newInstance("test instance", null);
} catch (NoSuchMethodException e3) {
throw new RuntimeException("unable to find an instantiator for " + aClass.getName());
}
}
}
}
/**
* com.gemstone.gemfire objects received from a client should translate to org.apache.geode
* objects. Here we perform a simple unit test on a com.gemstone.gemfire object to ensure that
* this is happening correctly for Java-serialized objects
*/
@Test
public void oldClientObjectTranslatesToGeodeObject_javaSerialization() throws Exception {
Properties properties = new Properties();
properties.put(ConfigurationProperties.SERIALIZABLE_OBJECT_FILTER,
"org.apache.geode.ClientSerializableObjec");
DistributionConfig config = new DistributionConfigImpl(properties);
InternalDataSerializer.initialize(config, new ArrayList<DistributedSystemService>());
com.gemstone.gemfire.ClientSerializableObject gemfireObject =
new com.gemstone.gemfire.ClientSerializableObject();
com.gemstone.gemfire.ClientSerializableObject subObject =
new com.gemstone.gemfire.ClientSerializableObject();
gemfireObject.setSubObject(subObject);
ByteArrayOutputStream byteStream = new ByteArrayOutputStream(500);
DataOutputStream dataOut = new DataOutputStream(byteStream);
DataSerializer.writeObject(gemfireObject, dataOut);
dataOut.flush();
byte[] serializedForm = byteStream.toByteArray();
ByteArrayDataInput byteDataInput = new ByteArrayDataInput();
byteDataInput.initialize(serializedForm, Version.GFE_82);
ClientSerializableObject result = DataSerializer.readObject(byteDataInput);
Assert.assertEquals("Expected an org.apache.geode exception but found " + result,
result.getClass().getName().substring(0, "org.apache.geode".length()), "org.apache.geode");
ClientSerializableObject newSubObject = result.getSubObject();
Assert.assertNotNull(newSubObject);
}
/**
* com.gemstone.gemfire objects received from a client should translate to org.apache.geode
* objects. Here we perform a simple unit test on a com.gemstone.gemfire object to ensure that
* this is happening correctly for data-serialized objects
*/
@Test
public void oldClientObjectTranslatesToGeodeObject_dataSerialization() throws Exception {
com.gemstone.gemfire.ClientDataSerializableObject gemfireObject =
new com.gemstone.gemfire.ClientDataSerializableObject();
ByteArrayOutputStream byteStream = new ByteArrayOutputStream(500);
DataOutputStream dataOut = new DataOutputStream(byteStream);
// use an internal API to ensure that java serialization isn't used
InternalDataSerializer.writeObject(gemfireObject, dataOut, false);
dataOut.flush();
byte[] serializedForm = byteStream.toByteArray();
ByteArrayDataInput byteDataInput = new ByteArrayDataInput();
byteDataInput.initialize(serializedForm, Version.GFE_82);
Object result = DataSerializer.readObject(byteDataInput);
Assert.assertEquals("Expected an org.apache.geode object but found " + result,
result.getClass().getName().substring(0, "org.apache.geode".length()), "org.apache.geode");
}
/**
* com.gemstone.gemfire objects received from a client should translate to org.apache.geode
* objects. Here we perform a simple unit test on a com.gemstone.gemfire object to ensure that
* this is happening correctly for PDX-serialized objects
*/
@Test
public void oldClientObjectTranslatesToGeodeObject_pdxSerialization() throws Exception {
com.gemstone.gemfire.ClientPDXSerializableObject gemfireObject =
new com.gemstone.gemfire.ClientPDXSerializableObject();
ByteArrayOutputStream byteStream = new ByteArrayOutputStream(500);
DataOutputStream dataOut = new DataOutputStream(byteStream);
// use an internal API to ensure that java serialization isn't used
InternalDataSerializer.writeObject(gemfireObject, dataOut, false);
dataOut.flush();
byte[] serializedForm = byteStream.toByteArray();
ByteArrayDataInput byteDataInput = new ByteArrayDataInput();
byteDataInput.initialize(serializedForm, Version.GFE_82);
Object result = DataSerializer.readObject(byteDataInput);
Assert.assertEquals("Expected an org.apache.geode object but found " + result,
result.getClass().getName().substring(0, "org.apache.geode".length()), "org.apache.geode");
}
}