blob: 85a0c5fbb0ae9bbb82794b6f8dea3f89081f151a [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.pdx;
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 java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.apache.geode.CopyHelper;
import org.apache.geode.DataSerializable;
import org.apache.geode.DataSerializer;
import org.apache.geode.DeltaTestImpl;
import org.apache.geode.ToDataException;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.DiskStoreFactory;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.internal.HeapDataOutputStream;
import org.apache.geode.internal.PdxSerializerObject;
import org.apache.geode.internal.SystemAdmin;
import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.apache.geode.internal.serialization.DSCODE;
import org.apache.geode.internal.serialization.Version;
import org.apache.geode.internal.tcp.ByteBufferInputStream.ByteSourceFactory;
import org.apache.geode.internal.util.ArrayUtils;
import org.apache.geode.pdx.internal.DataSize;
import org.apache.geode.pdx.internal.PdxReaderImpl;
import org.apache.geode.pdx.internal.PdxType;
import org.apache.geode.pdx.internal.PdxWriterImpl;
import org.apache.geode.pdx.internal.PeerTypeRegistration;
import org.apache.geode.pdx.internal.TypeRegistry;
import org.apache.geode.test.junit.categories.SerializationTest;
@Category({SerializationTest.class})
public class PdxSerializableJUnitTest {
private GemFireCacheImpl cache;
@Before
public void setUp() {
// make it a loner
this.cache = (GemFireCacheImpl) new CacheFactory().set(MCAST_PORT, "0").create();
}
@After
public void tearDown() {
this.cache.close();
}
private int getPdxTypeIdForClass(Class c) {
// here we are assuming Dsid == 0
return this.cache.getPdxRegistry().getExistingTypeForClass(c).hashCode()
& PeerTypeRegistration.PLACE_HOLDER_FOR_TYPE_ID;
}
private int getNumPdxTypes() {
return this.cache.getPdxRegistry().typeMap().size();
}
@Test
public void testNoDiskStore() throws Exception {
this.cache.close();
this.cache = (GemFireCacheImpl) new CacheFactory().set(MCAST_PORT, "0").setPdxPersistent(true)
.setPdxDiskStore("doesNotExist").create();
HeapDataOutputStream out = new HeapDataOutputStream(Version.CURRENT);
PdxSerializable object = new SimpleClass(1, (byte) 5, null);
try {
DataSerializer.writeObject(object, out);
throw new Exception("expected PdxInitializationException");
} catch (PdxInitializationException expected) {
}
}
// for bugs 44271 and 44914
@Test
public void testPdxPersistentKeys() throws Exception {
this.cache.close();
this.cache = (GemFireCacheImpl) new CacheFactory().set(MCAST_PORT, "0").setPdxPersistent(true)
.setPdxDiskStore("pdxDS").create();
try {
DiskStoreFactory dsf = this.cache.createDiskStoreFactory();
dsf.create("pdxDS");
this.cache.createDiskStoreFactory().create("r2DS");
Region r1 = this.cache.createRegionFactory(RegionShortcut.LOCAL_PERSISTENT).create("r1");
r1.put(new SimpleClass(1, (byte) 1), "1");
r1.put(new SimpleClass(2, (byte) 2), "2");
r1.put(new SimpleClass(1, (byte) 1), "1.2"); // so we have something to compact offline
Region r2 = this.cache.createRegionFactory(RegionShortcut.LOCAL_PERSISTENT)
.setDiskStoreName("r2DS").create("r2");
r2.put(new SimpleClass(1, (byte) 1), new SimpleClass(1, (byte) 1));
r2.put(new SimpleClass(2, (byte) 2), new SimpleClass(2, (byte) 2));
this.cache.close();
this.cache = (GemFireCacheImpl) new CacheFactory().set(MCAST_PORT, "0").setPdxPersistent(true)
.setPdxDiskStore("pdxDS").create();
dsf = this.cache.createDiskStoreFactory();
dsf.create("pdxDS");
this.cache.createDiskStoreFactory().create("r2DS");
r1 = this.cache.createRegionFactory(RegionShortcut.LOCAL_PERSISTENT).create("r1");
r2 = this.cache.createRegionFactory(RegionShortcut.LOCAL_PERSISTENT).setDiskStoreName("r2DS")
.create("r2");
assertEquals(true, r1.containsKey(new SimpleClass(1, (byte) 1)));
assertEquals(true, r1.containsKey(new SimpleClass(2, (byte) 2)));
assertEquals(true, r2.containsKey(new SimpleClass(1, (byte) 1)));
assertEquals(true, r2.containsKey(new SimpleClass(2, (byte) 2)));
assertEquals(new SimpleClass(1, (byte) 1), r2.get(new SimpleClass(1, (byte) 1)));
assertEquals(new SimpleClass(2, (byte) 2), r2.get(new SimpleClass(2, (byte) 2)));
this.cache.close();
// use a cache.xml to recover
this.cache = (GemFireCacheImpl) new CacheFactory().set(MCAST_PORT, "0").create();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintWriter pw = new PrintWriter(new OutputStreamWriter(baos), true);
pw.println("<?xml version=\"1.0\"?>");
pw.println("<!DOCTYPE cache PUBLIC");
pw.println(" \"-//GemStone Systems, Inc.//GemFire Declarative Caching 7.0//EN\"");
pw.println(" \"http://www.gemstone.com/dtd/cache7_0.dtd\">");
pw.println("<cache>");
pw.println(" <disk-store name=\"r2DS\"/>");
pw.println(" <disk-store name=\"pdxDS\"/>");
pw.println(" <pdx persistent=\"true\" disk-store-name=\"pdxDS\"/>");
pw.println(" <region name=\"r1\" refid=\"LOCAL_PERSISTENT\"/>");
pw.println(" <region name=\"r2\" refid=\"LOCAL_PERSISTENT\">");
pw.println(" <region-attributes disk-store-name=\"r2DS\"/>");
pw.println(" </region>");
pw.println("</cache>");
pw.close();
byte[] bytes = baos.toByteArray();
this.cache.loadCacheXml(new ByteArrayInputStream(bytes));
r1 = this.cache.getRegion("/r1");
r2 = this.cache.getRegion("/r2");
assertEquals(true, r1.containsKey(new SimpleClass(1, (byte) 1)));
assertEquals(true, r1.containsKey(new SimpleClass(2, (byte) 2)));
assertEquals(true, r2.containsKey(new SimpleClass(1, (byte) 1)));
assertEquals(true, r2.containsKey(new SimpleClass(2, (byte) 2)));
assertEquals(new SimpleClass(1, (byte) 1), r2.get(new SimpleClass(1, (byte) 1)));
assertEquals(new SimpleClass(2, (byte) 2), r2.get(new SimpleClass(2, (byte) 2)));
this.cache.close();
// make sure offlines tools work with disk store that has pdx keys
SystemAdmin.validateDiskStore("DEFAULT", ".");
SystemAdmin.compactDiskStore("DEFAULT", ".");
SystemAdmin.modifyDiskStore("DEFAULT", ".");
SystemAdmin.validateDiskStore("r2DS", ".");
SystemAdmin.compactDiskStore("r2DS", ".");
SystemAdmin.modifyDiskStore("r2DS", ".");
SystemAdmin.validateDiskStore("pdxDS", ".");
SystemAdmin.compactDiskStore("pdxDS", ".");
SystemAdmin.modifyDiskStore("pdxDS", ".");
} finally {
try {
this.cache.close();
} finally {
Pattern pattern = Pattern.compile("BACKUP(DEFAULT|pdxDS|r2DS).*");
File[] files = new File(".").listFiles((dir1, name) -> pattern.matcher(name).matches());
if (files != null) {
for (File file : files) {
Files.delete(file.toPath());
}
}
}
}
}
@Test
public void testPdxPersistentKeysDefDS() throws Exception {
this.cache.close();
this.cache =
(GemFireCacheImpl) new CacheFactory().set(MCAST_PORT, "0").setPdxPersistent(true).create();
try {
this.cache.createDiskStoreFactory().create("r2DS");
Region r1 = this.cache.createRegionFactory(RegionShortcut.LOCAL_PERSISTENT)
.setDiskStoreName("r2DS").create("r1");
r1.put(new SimpleClass(1, (byte) 1), "1");
r1.put(new SimpleClass(2, (byte) 2), "2");
r1.put(new SimpleClass(1, (byte) 1), "1.2"); // so we have something to compact offline
Region r2 = this.cache.createRegionFactory(RegionShortcut.LOCAL_PERSISTENT)
.setDiskStoreName("r2DS").create("r2");
r2.put(new SimpleClass(1, (byte) 1), new SimpleClass(1, (byte) 1));
r2.put(new SimpleClass(2, (byte) 2), new SimpleClass(2, (byte) 2));
this.cache.close();
this.cache = (GemFireCacheImpl) new CacheFactory().set(MCAST_PORT, "0").setPdxPersistent(true)
.create();
this.cache.createDiskStoreFactory().create("r2DS");
r1 = this.cache.createRegionFactory(RegionShortcut.LOCAL_PERSISTENT).setDiskStoreName("r2DS")
.create("r1");
r2 = this.cache.createRegionFactory(RegionShortcut.LOCAL_PERSISTENT).setDiskStoreName("r2DS")
.create("r2");
assertEquals(true, r1.containsKey(new SimpleClass(1, (byte) 1)));
assertEquals(true, r1.containsKey(new SimpleClass(2, (byte) 2)));
assertEquals(true, r2.containsKey(new SimpleClass(1, (byte) 1)));
assertEquals(true, r2.containsKey(new SimpleClass(2, (byte) 2)));
assertEquals(new SimpleClass(1, (byte) 1), r2.get(new SimpleClass(1, (byte) 1)));
assertEquals(new SimpleClass(2, (byte) 2), r2.get(new SimpleClass(2, (byte) 2)));
this.cache.close();
// use a cache.xml to recover
this.cache = (GemFireCacheImpl) new CacheFactory().set(MCAST_PORT, "0").create();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintWriter pw = new PrintWriter(new OutputStreamWriter(baos), true);
pw.println("<?xml version=\"1.0\"?>");
pw.println("<!DOCTYPE cache PUBLIC");
pw.println(" \"-//GemStone Systems, Inc.//GemFire Declarative Caching 7.0//EN\"");
pw.println(" \"http://www.gemstone.com/dtd/cache7_0.dtd\">");
pw.println("<cache>");
pw.println(" <disk-store name=\"r2DS\"/>");
pw.println(" <pdx persistent=\"true\"/>");
pw.println(" <region name=\"r1\" refid=\"LOCAL_PERSISTENT\">");
pw.println(" <region-attributes disk-store-name=\"r2DS\"/>");
pw.println(" </region>");
pw.println(" <region name=\"r2\" refid=\"LOCAL_PERSISTENT\">");
pw.println(" <region-attributes disk-store-name=\"r2DS\"/>");
pw.println(" </region>");
pw.println("</cache>");
pw.close();
byte[] bytes = baos.toByteArray();
this.cache.loadCacheXml(new ByteArrayInputStream(bytes));
r1 = this.cache.getRegion("/r1");
r2 = this.cache.getRegion("/r2");
assertEquals(true, r1.containsKey(new SimpleClass(1, (byte) 1)));
assertEquals(true, r1.containsKey(new SimpleClass(2, (byte) 2)));
assertEquals(true, r2.containsKey(new SimpleClass(1, (byte) 1)));
assertEquals(true, r2.containsKey(new SimpleClass(2, (byte) 2)));
assertEquals(new SimpleClass(1, (byte) 1), r2.get(new SimpleClass(1, (byte) 1)));
assertEquals(new SimpleClass(2, (byte) 2), r2.get(new SimpleClass(2, (byte) 2)));
this.cache.close();
// make sure offlines tools work with disk store that has pdx keys
SystemAdmin.validateDiskStore("DEFAULT", ".");
SystemAdmin.compactDiskStore("DEFAULT", ".");
SystemAdmin.modifyDiskStore("DEFAULT", ".");
SystemAdmin.validateDiskStore("r2DS", ".");
SystemAdmin.compactDiskStore("r2DS", ".");
SystemAdmin.modifyDiskStore("r2DS", ".");
} finally {
try {
this.cache.close();
} finally {
Pattern pattern = Pattern.compile("BACKUP(DEFAULT|r2DS).*");
File[] files = new File(".").listFiles((dir1, name) -> pattern.matcher(name).matches());
if (files != null) {
for (File file : files) {
Files.delete(file.toPath());
}
}
}
}
}
@Test
public void testByteFormatForSimpleClass() throws Exception {
HeapDataOutputStream out = new HeapDataOutputStream(Version.CURRENT);
PdxSerializable object = new SimpleClass(1, (byte) 5, null);
DataSerializer.writeObject(object, out);
int typeId = getPdxTypeIdForClass(SimpleClass.class);
byte[] actual = out.toByteArray();
byte[] expected = new byte[] {DSCODE.PDX.toByte(), // byte
0, 0, 0, 4 + 1 + 1, // int - length of byte stream = 4(myInt) + 1(myByte) + 1 (myEnum)
(byte) (typeId >> 24), (byte) (typeId >> 16), (byte) (typeId >> 8), (byte) typeId, // int -
// typeId
0, 0, 0, 1, // int - myInt = 1
5, // byte - myByte = 5
DSCODE.NULL.toByte()};
StringBuffer msg = new StringBuffer("Actual output: ");
for (byte val : actual) {
msg.append(val + ", ");
}
msg.append("\nExpected output: ");
for (byte val : expected) {
msg.append(val + ", ");
}
assertTrue("Mismatch in length, actual.length: " + actual.length + " and expected length: "
+ expected.length, actual.length == expected.length);
for (int i = 0; i < actual.length; i++) {
if (actual[i] != expected[i]) {
System.out.println(msg.toString());
}
assertTrue("Mismatch at index " + i, actual[i] == expected[i]);
}
System.out.println("\n");
DataInput in = new DataInputStream(new ByteArrayInputStream(actual));
SimpleClass actualVal = (SimpleClass) DataSerializer.readObject(in);
// System.out.println("actualVal..."+actualVal);
assertTrue(
"Mismatch in write and read value: Value Write..." + object + " Value Read..." + actualVal,
object.equals(actualVal));
}
@Test
public void testByteFormatForStrings() throws Exception {
boolean myFlag = true;
short myShort = 25;
String myString1 = "Class4_myString1";
long myLong = 15654;
String myString2 = "Class4_myString2";
String myString3 = "Class4_myString3";
int myInt = 1420;
float myFloat = 123.023f;
HeapDataOutputStream out = new HeapDataOutputStream(Version.CURRENT);
SimpleClass1 pdx =
new SimpleClass1(myFlag, myShort, myString1, myLong, myString2, myString3, myInt, myFloat);
DataSerializer.writeObject(pdx, out);
int typeId = getPdxTypeIdForClass(SimpleClass1.class);
HeapDataOutputStream hdos1 = new HeapDataOutputStream(Version.CURRENT);
DataSerializer.writeString(myString1, hdos1);
byte[] str1Bytes = hdos1.toByteArray();
HeapDataOutputStream hdos2 = new HeapDataOutputStream(Version.CURRENT);
DataSerializer.writeString(myString2, hdos2);
byte[] str2Bytes = hdos2.toByteArray();
HeapDataOutputStream hdos3 = new HeapDataOutputStream(Version.CURRENT);
DataSerializer.writeString(myString3, hdos3);
byte[] str3Bytes = hdos3.toByteArray();
int length = 1 /* myFlag */ + 2 /* myShort */
+ 8 /* myLong */ + 4 /* myInt */ + 4 /* myFloat */ + str1Bytes.length + str2Bytes.length
+ str3Bytes.length + 2 /* byte offset for 3 strings */;
int offset1 = 1 + 2;
int offset2 = offset1 + 8 + str1Bytes.length;
int offset3 = offset1 + 8 + str1Bytes.length + str2Bytes.length;
byte[] actual = out.toByteArray();
int floatBytes = Float.floatToRawIntBits(myFloat);
Byte[] expected = new Byte[] {DSCODE.PDX.toByte(), // byte
(byte) (length >> 24), (byte) (length >> 16), (byte) (length >> 8), (byte) length, // int -
// length
// of
// byte
// stream
(byte) (typeId >> 24), (byte) (typeId >> 16), (byte) (typeId >> 8), (byte) typeId, // int -
// typeId
1, // boolean - myFlag = true
(byte) (myShort >> 8), (byte) myShort, // short - myShort
(byte) (myLong >> 56), (byte) (myLong >> 48), (byte) (myLong >> 40), (byte) (myLong >> 32),
(byte) (myLong >> 24), (byte) (myLong >> 16), (byte) (myLong >> 8), (byte) myLong, // long -
// myLong
(byte) (myInt >> 24), (byte) (myInt >> 16), (byte) (myInt >> 8), (byte) myInt, // int -
// myInt
(byte) (floatBytes >> 24), (byte) (floatBytes >> 16), (byte) (floatBytes >> 8),
(byte) floatBytes, // float - myFloat
(byte) offset3, // offset of myString3
(byte) offset2, // offset of myString2
};
for (int i = (str1Bytes.length - 1); i >= 0; i--) {
expected =
(Byte[]) ArrayUtils.insert(expected, offset1 + PdxWriterImpl.HEADER_SIZE, str1Bytes[i]); // +
// 5
// for:
// 1
// for
// DSCODE.PDX.toByte()
// and
// 4
// for
// byte
// stream
// length
}
for (int i = (str2Bytes.length - 1); i >= 0; i--) {
expected =
(Byte[]) ArrayUtils.insert(expected, offset2 + PdxWriterImpl.HEADER_SIZE, str2Bytes[i]);
}
for (int i = (str3Bytes.length - 1); i >= 0; i--) {
expected =
(Byte[]) ArrayUtils.insert(expected, offset3 + PdxWriterImpl.HEADER_SIZE, str3Bytes[i]);
}
StringBuffer msg = new StringBuffer("Actual output: ");
for (byte val : actual) {
msg.append(val + ", ");
}
msg.append("\nExpected output: ");
for (byte val : expected) {
msg.append(val + ", ");
}
if (actual.length != expected.length) {
System.out.println(msg.toString());
}
assertTrue("Mismatch in length, actual.length: " + actual.length + " and expected length: "
+ expected.length, actual.length == expected.length);
for (int i = 0; i < actual.length; i++) {
if (actual[i] != expected[i]) {
System.out.println(msg.toString());
}
assertTrue("Mismatch at index " + i, actual[i] == expected[i]);
}
System.out.println("\n");
DataInput in = new DataInputStream(new ByteArrayInputStream(actual));
SimpleClass1 actualVal = (SimpleClass1) DataSerializer.readObject(in);
// System.out.println("actualVal..."+actualVal);
assertTrue(
"Mismatch in write and read value: Value Write..." + pdx + " Value Read..." + actualVal,
pdx.equals(actualVal));
cache.setReadSerializedForTest(true);
try {
in = new DataInputStream(new ByteArrayInputStream(actual));
PdxInstance pi = (PdxInstance) DataSerializer.readObject(in);
actualVal = (SimpleClass1) pi.getObject();
assertTrue(
"Mismatch in write and read value: Value Write..." + pdx + " Value Read..." + actualVal,
pdx.equals(actualVal));
assertTrue(pi.hasField("myFlag"));
assertTrue(pi.hasField("myShort"));
assertTrue(pi.hasField("myString1"));
assertTrue(pi.hasField("myLong"));
assertTrue(pi.hasField("myString2"));
assertTrue(pi.hasField("myString3"));
assertTrue(pi.hasField("myInt"));
assertTrue(pi.hasField("myFloat"));
assertEquals(pdx.isMyFlag(), pi.getField("myFlag"));
assertEquals(pdx.getMyShort(), pi.getField("myShort"));
assertEquals(pdx.getMyString1(), pi.getField("myString1"));
assertEquals(pdx.getMyLong(), pi.getField("myLong"));
assertEquals(pdx.getMyString2(), pi.getField("myString2"));
assertEquals(pdx.getMyString3(), pi.getField("myString3"));
assertEquals(pdx.getMyInt(), pi.getField("myInt"));
assertEquals(pdx.getMyFloat(), pi.getField("myFloat"));
PdxReaderImpl reader = (PdxReaderImpl) pi;
PdxType type = reader.getPdxType();
assertEquals(SimpleClass1.class.getName(), type.getClassName());
assertEquals(8, type.getFieldCount());
assertEquals(2, type.getVariableLengthFieldCount());
assertEquals(0, type.getPdxField("myFlag").getFieldIndex());
assertEquals(1, type.getPdxField("myShort").getFieldIndex());
assertEquals(2, type.getPdxField("myString1").getFieldIndex());
assertEquals(3, type.getPdxField("myLong").getFieldIndex());
assertEquals(4, type.getPdxField("myString2").getFieldIndex());
assertEquals(5, type.getPdxField("myString3").getFieldIndex());
assertEquals(6, type.getPdxField("myInt").getFieldIndex());
assertEquals(7, type.getPdxField("myFloat").getFieldIndex());
assertEquals(FieldType.BOOLEAN, type.getPdxField("myFlag").getFieldType());
assertEquals(FieldType.SHORT, type.getPdxField("myShort").getFieldType());
assertEquals(FieldType.STRING, type.getPdxField("myString1").getFieldType());
assertEquals(FieldType.LONG, type.getPdxField("myLong").getFieldType());
assertEquals(FieldType.STRING, type.getPdxField("myString2").getFieldType());
assertEquals(FieldType.STRING, type.getPdxField("myString3").getFieldType());
assertEquals(FieldType.INT, type.getPdxField("myInt").getFieldType());
assertEquals(FieldType.FLOAT, type.getPdxField("myFloat").getFieldType());
assertEquals("myFlag", type.getPdxField("myFlag").getFieldName());
assertEquals("myShort", type.getPdxField("myShort").getFieldName());
assertEquals("myString1", type.getPdxField("myString1").getFieldName());
assertEquals("myLong", type.getPdxField("myLong").getFieldName());
assertEquals("myString2", type.getPdxField("myString2").getFieldName());
assertEquals("myString3", type.getPdxField("myString3").getFieldName());
assertEquals("myInt", type.getPdxField("myInt").getFieldName());
assertEquals("myFloat", type.getPdxField("myFloat").getFieldName());
assertEquals(0, type.getPdxField("myFlag").getVarLenFieldSeqId());
assertEquals(0, type.getPdxField("myShort").getVarLenFieldSeqId());
assertEquals(0, type.getPdxField("myString1").getVarLenFieldSeqId());
assertEquals(0, type.getPdxField("myLong").getVarLenFieldSeqId());
assertEquals(1, type.getPdxField("myString2").getVarLenFieldSeqId());
assertEquals(2, type.getPdxField("myString3").getVarLenFieldSeqId());
assertEquals(2, type.getPdxField("myInt").getVarLenFieldSeqId());
assertEquals(2, type.getPdxField("myFloat").getVarLenFieldSeqId());
assertEquals(false, type.getPdxField("myFlag").isVariableLengthType());
assertEquals(false, type.getPdxField("myShort").isVariableLengthType());
assertEquals(true, type.getPdxField("myString1").isVariableLengthType());
assertEquals(false, type.getPdxField("myLong").isVariableLengthType());
assertEquals(true, type.getPdxField("myString2").isVariableLengthType());
assertEquals(true, type.getPdxField("myString3").isVariableLengthType());
assertEquals(false, type.getPdxField("myInt").isVariableLengthType());
assertEquals(false, type.getPdxField("myFloat").isVariableLengthType());
assertEquals(ByteSourceFactory.wrap(new byte[] {(byte) (pdx.isMyFlag() ? 1 : 0)}),
reader.getRaw(0));
assertEquals(
ByteSourceFactory
.wrap(new byte[] {(byte) (pdx.getMyShort() >> 8), (byte) pdx.getMyShort()}),
reader.getRaw(1));
assertEquals(ByteSourceFactory.wrap(str1Bytes), reader.getRaw(2));
assertEquals(ByteSourceFactory.wrap(new byte[] {(byte) (pdx.getMyLong() >> 56),
(byte) (pdx.getMyLong() >> 48), (byte) (pdx.getMyLong() >> 40),
(byte) (pdx.getMyLong() >> 32), (byte) (pdx.getMyLong() >> 24),
(byte) (pdx.getMyLong() >> 16), (byte) (pdx.getMyLong() >> 8), (byte) pdx.getMyLong(),}),
reader.getRaw(3));
assertEquals(ByteSourceFactory.wrap(str2Bytes), reader.getRaw(4));
assertEquals(ByteSourceFactory.wrap(str3Bytes), reader.getRaw(5));
assertEquals(
ByteSourceFactory.wrap(new byte[] {(byte) (pdx.getMyInt() >> 24),
(byte) (pdx.getMyInt() >> 16), (byte) (pdx.getMyInt() >> 8), (byte) pdx.getMyInt()}),
reader.getRaw(6));
assertEquals(ByteSourceFactory.wrap(new byte[] {(byte) (floatBytes >> 24),
(byte) (floatBytes >> 16), (byte) (floatBytes >> 8), (byte) floatBytes}),
reader.getRaw(7));
} finally {
cache.setReadSerializedForTest(false);
}
}
@Test
public void testByteFormatForLongStrings() throws Exception {
boolean myFlag = true;
short myShort = 25;
String myString1 =
"A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1."
+ "A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1."
+ "A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1."
+ "A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1."
+ "A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1."
+ "A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1."
+ "A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1."
+ "A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1."
+ "A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1."
+ "A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.A very long string1.";
long myLong = 15654;
String myString2 = "Class4_myString2";
String myString3 =
"Even longer string3. Even longer string3. Even longer string3. Even longer string3. Even longer string3. Even longer string3. "
+ "Even longer string3. Even longer string3. Even longer string3. Even longer string3. Even longer string3. Even longer string3. Even longer string3. "
+ "Even longer string3. Even longer string3. Even longer string3. Even longer string3. Even longer string3. Even longer string3. Even longer string3. "
+ "Even longer string3. Even longer string3. Even longer string3. Even longer string3. Even longer string3. Even longer string3. Even longer string3. "
+ "Even longer string3. Even longer string3. Even longer string3. Even longer string3. Even longer string3. Even longer string3. Even longer string3. "
+ "Even longer string3. Even longer string3. Even longer string3. Even longer string3. Even longer string3. ";
int myInt = 1420;
float myFloat = 123.023f;
HeapDataOutputStream out = new HeapDataOutputStream(Version.CURRENT);
SimpleClass1 pdx =
new SimpleClass1(myFlag, myShort, myString1, myLong, myString2, myString3, myInt, myFloat);
DataSerializer.writeObject(pdx, out);
int typeId = getPdxTypeIdForClass(SimpleClass1.class);
HeapDataOutputStream hdos1 = new HeapDataOutputStream(Version.CURRENT);
DataSerializer.writeString(myString1, hdos1);
byte[] str1Bytes = hdos1.toByteArray();
HeapDataOutputStream hdos2 = new HeapDataOutputStream(Version.CURRENT);
DataSerializer.writeString(myString2, hdos2);
byte[] str2Bytes = hdos2.toByteArray();
HeapDataOutputStream hdos3 = new HeapDataOutputStream(Version.CURRENT);
DataSerializer.writeString(myString3, hdos3);
byte[] str3Bytes = hdos3.toByteArray();
int length = 1 /* myFlag */ + 2 /* myShort */
+ 8 /* myLong */ + 4 /* myInt */ + 4 /* myFloat */ + str1Bytes.length + str2Bytes.length
+ str3Bytes.length + (2 * 2) /* short offset for 3 strings */;
int offset1 = 1 + 2;
int offset2 = offset1 + 8 + str1Bytes.length;
int offset3 = offset1 + 8 + str1Bytes.length + str2Bytes.length;
byte[] actual = out.toByteArray();
int floatBytes = Float.floatToRawIntBits(myFloat);
Byte[] expected = new Byte[] {DSCODE.PDX.toByte(), // byte
(byte) (length >> 24), (byte) (length >> 16), (byte) (length >> 8), (byte) length, // int -
// length
// of
// byte
// stream
(byte) (typeId >> 24), (byte) (typeId >> 16), (byte) (typeId >> 8), (byte) typeId, // int -
// typeId
1, // boolean - myFlag = true
(byte) (myShort >> 8), (byte) myShort, // short - myShort
(byte) (myLong >> 56), (byte) (myLong >> 48), (byte) (myLong >> 40), (byte) (myLong >> 32),
(byte) (myLong >> 24), (byte) (myLong >> 16), (byte) (myLong >> 8), (byte) myLong, // long -
// myLong
(byte) (myInt >> 24), (byte) (myInt >> 16), (byte) (myInt >> 8), (byte) myInt, // int -
// myInt
(byte) (floatBytes >> 24), (byte) (floatBytes >> 16), (byte) (floatBytes >> 8),
(byte) floatBytes, // float - myFloat
(byte) (offset3 >> 8), (byte) offset3, // offset of myString3
(byte) (offset2 >> 8), (byte) offset2, // offset of myString2
};
for (int i = (str1Bytes.length - 1); i >= 0; i--) {
expected =
(Byte[]) ArrayUtils.insert(expected, offset1 + PdxWriterImpl.HEADER_SIZE, str1Bytes[i]); // +
// 5
// for:
// 1
// for
// DSCODE.PDX.toByte()
// and
// 4
// for
// byte
// stream
// length
}
for (int i = (str2Bytes.length - 1); i >= 0; i--) {
expected =
(Byte[]) ArrayUtils.insert(expected, offset2 + PdxWriterImpl.HEADER_SIZE, str2Bytes[i]);
}
for (int i = (str3Bytes.length - 1); i >= 0; i--) {
expected =
(Byte[]) ArrayUtils.insert(expected, offset3 + PdxWriterImpl.HEADER_SIZE, str3Bytes[i]);
}
StringBuffer msg = new StringBuffer("Actual output: ");
for (byte val : actual) {
msg.append(val + ", ");
}
msg.append("\nExpected output: ");
for (byte val : expected) {
msg.append(val + ", ");
}
if (actual.length != expected.length) {
System.out.println(msg.toString());
}
assertTrue("Mismatch in length, actual.length: " + actual.length + " and expected length: "
+ expected.length, actual.length == expected.length);
for (int i = 0; i < actual.length; i++) {
if (actual[i] != expected[i]) {
System.out.println(msg.toString());
}
assertTrue("Mismatch at index " + i, actual[i] == expected[i]);
}
System.out.println("\n");
DataInput in = new DataInputStream(new ByteArrayInputStream(actual));
SimpleClass1 actualVal = (SimpleClass1) DataSerializer.readObject(in);
// System.out.println("actualVal..."+actualVal);
assertTrue(
"Mismatch in write and read value: Value Write..." + pdx + " Value Read..." + actualVal,
pdx.equals(actualVal));
cache.setReadSerializedForTest(true);
try {
in = new DataInputStream(new ByteArrayInputStream(actual));
PdxInstance pi = (PdxInstance) DataSerializer.readObject(in);
actualVal = (SimpleClass1) pi.getObject();
assertTrue(
"Mismatch in write and read value: Value Write..." + pdx + " Value Read..." + actualVal,
pdx.equals(actualVal));
assertTrue(pi.hasField("myFlag"));
assertTrue(pi.hasField("myShort"));
assertTrue(pi.hasField("myString1"));
assertTrue(pi.hasField("myLong"));
assertTrue(pi.hasField("myString2"));
assertTrue(pi.hasField("myString3"));
assertTrue(pi.hasField("myInt"));
assertTrue(pi.hasField("myFloat"));
assertEquals(pdx.isMyFlag(), pi.getField("myFlag"));
assertEquals(pdx.getMyShort(), pi.getField("myShort"));
assertEquals(pdx.getMyString1(), pi.getField("myString1"));
assertEquals(pdx.getMyLong(), pi.getField("myLong"));
assertEquals(pdx.getMyString2(), pi.getField("myString2"));
assertEquals(pdx.getMyString3(), pi.getField("myString3"));
assertEquals(pdx.getMyInt(), pi.getField("myInt"));
assertEquals(pdx.getMyFloat(), pi.getField("myFloat"));
PdxReaderImpl reader = (PdxReaderImpl) pi;
PdxType type = reader.getPdxType();
assertEquals(SimpleClass1.class.getName(), type.getClassName());
assertEquals(8, type.getFieldCount());
assertEquals(2, type.getVariableLengthFieldCount());
assertEquals(0, type.getPdxField("myFlag").getFieldIndex());
assertEquals(1, type.getPdxField("myShort").getFieldIndex());
assertEquals(2, type.getPdxField("myString1").getFieldIndex());
assertEquals(3, type.getPdxField("myLong").getFieldIndex());
assertEquals(4, type.getPdxField("myString2").getFieldIndex());
assertEquals(5, type.getPdxField("myString3").getFieldIndex());
assertEquals(6, type.getPdxField("myInt").getFieldIndex());
assertEquals(7, type.getPdxField("myFloat").getFieldIndex());
assertEquals(FieldType.BOOLEAN, type.getPdxField("myFlag").getFieldType());
assertEquals(FieldType.SHORT, type.getPdxField("myShort").getFieldType());
assertEquals(FieldType.STRING, type.getPdxField("myString1").getFieldType());
assertEquals(FieldType.LONG, type.getPdxField("myLong").getFieldType());
assertEquals(FieldType.STRING, type.getPdxField("myString2").getFieldType());
assertEquals(FieldType.STRING, type.getPdxField("myString3").getFieldType());
assertEquals(FieldType.INT, type.getPdxField("myInt").getFieldType());
assertEquals(FieldType.FLOAT, type.getPdxField("myFloat").getFieldType());
assertEquals("myFlag", type.getPdxField("myFlag").getFieldName());
assertEquals("myShort", type.getPdxField("myShort").getFieldName());
assertEquals("myString1", type.getPdxField("myString1").getFieldName());
assertEquals("myLong", type.getPdxField("myLong").getFieldName());
assertEquals("myString2", type.getPdxField("myString2").getFieldName());
assertEquals("myString3", type.getPdxField("myString3").getFieldName());
assertEquals("myInt", type.getPdxField("myInt").getFieldName());
assertEquals("myFloat", type.getPdxField("myFloat").getFieldName());
assertEquals(0, type.getPdxField("myFlag").getVarLenFieldSeqId());
assertEquals(0, type.getPdxField("myShort").getVarLenFieldSeqId());
assertEquals(0, type.getPdxField("myString1").getVarLenFieldSeqId());
assertEquals(0, type.getPdxField("myLong").getVarLenFieldSeqId());
assertEquals(1, type.getPdxField("myString2").getVarLenFieldSeqId());
assertEquals(2, type.getPdxField("myString3").getVarLenFieldSeqId());
assertEquals(2, type.getPdxField("myInt").getVarLenFieldSeqId());
assertEquals(2, type.getPdxField("myFloat").getVarLenFieldSeqId());
assertEquals(false, type.getPdxField("myFlag").isVariableLengthType());
assertEquals(false, type.getPdxField("myShort").isVariableLengthType());
assertEquals(true, type.getPdxField("myString1").isVariableLengthType());
assertEquals(false, type.getPdxField("myLong").isVariableLengthType());
assertEquals(true, type.getPdxField("myString2").isVariableLengthType());
assertEquals(true, type.getPdxField("myString3").isVariableLengthType());
assertEquals(false, type.getPdxField("myInt").isVariableLengthType());
assertEquals(false, type.getPdxField("myFloat").isVariableLengthType());
assertEquals(ByteSourceFactory.wrap(new byte[] {(byte) (pdx.isMyFlag() ? 1 : 0)}),
reader.getRaw(0));
assertEquals(
ByteSourceFactory
.wrap(new byte[] {(byte) (pdx.getMyShort() >> 8), (byte) pdx.getMyShort()}),
reader.getRaw(1));
assertEquals(ByteSourceFactory.wrap(str1Bytes), reader.getRaw(2));
assertEquals(ByteSourceFactory.wrap(new byte[] {(byte) (pdx.getMyLong() >> 56),
(byte) (pdx.getMyLong() >> 48), (byte) (pdx.getMyLong() >> 40),
(byte) (pdx.getMyLong() >> 32), (byte) (pdx.getMyLong() >> 24),
(byte) (pdx.getMyLong() >> 16), (byte) (pdx.getMyLong() >> 8), (byte) pdx.getMyLong(),}),
reader.getRaw(3));
assertEquals(ByteSourceFactory.wrap(str2Bytes), reader.getRaw(4));
assertEquals(ByteSourceFactory.wrap(str3Bytes), reader.getRaw(5));
assertEquals(
ByteSourceFactory.wrap(new byte[] {(byte) (pdx.getMyInt() >> 24),
(byte) (pdx.getMyInt() >> 16), (byte) (pdx.getMyInt() >> 8), (byte) pdx.getMyInt()}),
reader.getRaw(6));
assertEquals(ByteSourceFactory.wrap(new byte[] {(byte) (floatBytes >> 24),
(byte) (floatBytes >> 16), (byte) (floatBytes >> 8), (byte) floatBytes}),
reader.getRaw(7));
} finally {
cache.setReadSerializedForTest(false);
}
}
@Test
public void testByteFormatForNestedPDX() throws Exception {
String myString1 = "ComplexClass1_myString1";
long myLong = 15654;
HashMap<String, PdxSerializable> myHashMap = new HashMap<String, PdxSerializable>();
String myString2 = "ComplexClass1_myString2";
float myFloat = 123.023f;
for (int i = 0; i < 5; i++) {
myHashMap.put("KEY_" + i, new SimpleClass(i, (byte) 5));
}
HeapDataOutputStream out = new HeapDataOutputStream(Version.CURRENT);
PdxSerializable pdx = new NestedPdx(myString1, myLong, myHashMap, myString2, myFloat);
DataSerializer.writeObject(pdx, out);
int typeId = getPdxTypeIdForClass(NestedPdx.class);
HeapDataOutputStream hdos1 = new HeapDataOutputStream(Version.CURRENT);
DataSerializer.writeString(myString1, hdos1);
byte[] str1Bytes = hdos1.toByteArray();
HeapDataOutputStream hdosForMap = new HeapDataOutputStream(Version.CURRENT);
DataSerializer.writeObject(myHashMap, hdosForMap);
byte[] mapBytes = hdosForMap.toByteArray();
HeapDataOutputStream hdos2 = new HeapDataOutputStream(Version.CURRENT);
DataSerializer.writeString(myString2, hdos2);
byte[] str2Bytes = hdos2.toByteArray();
int length = str1Bytes.length + 8 /* myLong */
+ mapBytes.length + str2Bytes.length + 4 /* myFloat */
+ (2 * 1) /*
* offset for 3 var-length fields
*/;
int offset1 = 0;
int offset2 = offset1 + 8 + str1Bytes.length;
int offset3 = offset1 + 8 + str1Bytes.length + mapBytes.length;
byte[] actual = out.toByteArray();
int floatBytes = Float.floatToRawIntBits(myFloat);
Byte[] expected = new Byte[] {DSCODE.PDX.toByte(), // byte
(byte) (length >> 24), (byte) (length >> 16), (byte) (length >> 8), (byte) length, // int -
// length
// of
// byte
// stream
(byte) (typeId >> 24), (byte) (typeId >> 16), (byte) (typeId >> 8), (byte) typeId, // int -
// typeId
(byte) (myLong >> 56), (byte) (myLong >> 48), (byte) (myLong >> 40), (byte) (myLong >> 32),
(byte) (myLong >> 24), (byte) (myLong >> 16), (byte) (myLong >> 8), (byte) myLong, // long -
// myLong
(byte) (floatBytes >> 24), (byte) (floatBytes >> 16), (byte) (floatBytes >> 8),
(byte) floatBytes, // float - myFloat
(byte) offset3, // offset of myString2
(byte) offset2, // offset of myHashMap
};
for (int i = (str1Bytes.length - 1); i >= 0; i--) {
expected =
(Byte[]) ArrayUtils.insert(expected, offset1 + PdxWriterImpl.HEADER_SIZE, str1Bytes[i]);
}
for (int i = (mapBytes.length - 1); i >= 0; i--) {
expected =
(Byte[]) ArrayUtils.insert(expected, offset2 + PdxWriterImpl.HEADER_SIZE, mapBytes[i]);
}
for (int i = (str2Bytes.length - 1); i >= 0; i--) {
expected =
(Byte[]) ArrayUtils.insert(expected, offset3 + PdxWriterImpl.HEADER_SIZE, str2Bytes[i]);
}
StringBuffer msg = new StringBuffer("Actual output: ");
for (byte val : actual) {
msg.append(val + ", ");
}
msg.append("\nExpected output: ");
for (byte val : expected) {
msg.append(val + ", ");
}
if (actual.length != expected.length) {
System.out.println(msg.toString());
}
assertTrue("Mismatch in length, actual.length: " + actual.length + " and expected length: "
+ expected.length, actual.length == expected.length);
for (int i = 0; i < actual.length; i++) {
if (actual[i] != expected[i]) {
System.out.println(msg.toString());
}
assertTrue("Mismatch at index " + i, actual[i] == expected[i]);
}
System.out.println("\n");
DataInput in = new DataInputStream(new ByteArrayInputStream(actual));
NestedPdx actualVal = (NestedPdx) DataSerializer.readObject(in);
// System.out.println("actualVal..."+actualVal);
assertTrue(
"Mismatch in write and read value: Value Write..." + pdx + " Value Read..." + actualVal,
pdx.equals(actualVal));
System.out.println("\n");
}
@Test
public void testByteFormatForDSInsidePDX() throws Exception {
String myString1 = "ComplexClass1_myString1";
long myLong = 15654;
DataSerializable myDS = new DeltaTestImpl(100, "value");
String myString2 = "ComplexClass1_myString2";
float myFloat = 123.023f;
HeapDataOutputStream out = new HeapDataOutputStream(Version.CURRENT);
PdxSerializable pdx = new DSInsidePdx(myString1, myLong, myDS, myString2, myFloat);
DataSerializer.writeObject(pdx, out);
int typeId = getPdxTypeIdForClass(DSInsidePdx.class);
HeapDataOutputStream hdos1 = new HeapDataOutputStream(Version.CURRENT);
DataSerializer.writeString(myString1, hdos1);
byte[] str1Bytes = hdos1.toByteArray();
System.out.println("Length of string1: " + str1Bytes.length);
HeapDataOutputStream hdos2 = new HeapDataOutputStream(Version.CURRENT);
DataSerializer.writeObject(myDS, hdos2);
byte[] dsBytes = hdos2.toByteArray();
System.out.println("Length of DS: " + dsBytes.length);
HeapDataOutputStream hdos3 = new HeapDataOutputStream(Version.CURRENT);
DataSerializer.writeString(myString2, hdos3);
byte[] str2Bytes = hdos3.toByteArray();
System.out.println("Length of string2: " + str2Bytes.length);
int length = str1Bytes.length + 8 /* myLong */
+ dsBytes.length + str2Bytes.length + 4 /* myFloat */
+ (2 * 2) /*
* offset for 3 car-length fields
*/;
int offset1 = 0;
int offset2 = offset1 + 8 + str1Bytes.length;
int offset3 = offset1 + 8 + str1Bytes.length + dsBytes.length;
byte[] actual = out.toByteArray();
int floatBytes = Float.floatToRawIntBits(myFloat);
Byte[] expected = new Byte[] {DSCODE.PDX.toByte(), // byte
(byte) (length >> 24), (byte) (length >> 16), (byte) (length >> 8), (byte) length, // int -
// length
// of
// byte
// stream
(byte) (typeId >> 24), (byte) (typeId >> 16), (byte) (typeId >> 8), (byte) typeId, // int -
// typeId
(byte) (myLong >> 56), (byte) (myLong >> 48), (byte) (myLong >> 40), (byte) (myLong >> 32),
(byte) (myLong >> 24), (byte) (myLong >> 16), (byte) (myLong >> 8), (byte) myLong, // long -
// myLong
(byte) (floatBytes >> 24), (byte) (floatBytes >> 16), (byte) (floatBytes >> 8),
(byte) floatBytes, // float - myFloat
(byte) (offset3 >> 8), (byte) offset3, // offset of myString2
(byte) (offset2 >> 8), (byte) offset2, // offset of myHashMap
};
for (int i = (str1Bytes.length - 1); i >= 0; i--) {
expected =
(Byte[]) ArrayUtils.insert(expected, offset1 + PdxWriterImpl.HEADER_SIZE, str1Bytes[i]); // +
// 5
// for:
// 1
// for
// DSCODE.PDX.toByte()
// and
// 4
// for
// byte
// stream
// length
}
for (int i = (dsBytes.length - 1); i >= 0; i--) {
expected =
(Byte[]) ArrayUtils.insert(expected, offset2 + PdxWriterImpl.HEADER_SIZE, dsBytes[i]);
}
for (int i = (str2Bytes.length - 1); i >= 0; i--) {
expected =
(Byte[]) ArrayUtils.insert(expected, offset3 + PdxWriterImpl.HEADER_SIZE, str2Bytes[i]);
}
StringBuffer msg = new StringBuffer("Actual output: ");
for (byte val : actual) {
msg.append(val + ", ");
}
msg.append("\nExpected output: ");
for (byte val : expected) {
msg.append(val + ", ");
}
assertTrue("Mismatch in length, actual.length: " + actual.length + " and expected length: "
+ expected.length, actual.length == expected.length);
for (int i = 0; i < actual.length; i++) {
if (actual[i] != expected[i]) {
System.out.println(msg.toString());
}
assertTrue("Mismatch at index " + i, actual[i] == expected[i]);
}
System.out.println("\n");
DataInput in = new DataInputStream(new ByteArrayInputStream(actual));
DSInsidePdx actualVal = (DSInsidePdx) DataSerializer.readObject(in);
// System.out.println("actualVal..."+actualVal);
assertTrue(
"Mismatch in write and read value: Value Write..." + pdx + " Value Read..." + actualVal,
pdx.equals(actualVal));
System.out.println("\n");
}
@Test
public void testByteFormatForPDXInsideDS() throws Exception {
String myString1 = "ComplexClass5_myString1";
long myLong = 15654;
String myString2 = "ComplexClass5_myString2";
float myFloat = 123.023f;
HashMap<String, PdxSerializable> myHashMap = new HashMap<String, PdxSerializable>();
for (int i = 0; i < 2; i++) {
myHashMap.put("KEY_" + i, new SimpleClass(i, (byte) i));
}
PdxSerializable myPDX = new NestedPdx(myString1, myLong, myHashMap, myString2, myFloat);
HeapDataOutputStream out = new HeapDataOutputStream(Version.CURRENT);
DataSerializable ds = new PdxInsideDS(myString1, myLong, myPDX, myString2);
DataSerializer.writeObject(ds, out);
HeapDataOutputStream hdosString1 = new HeapDataOutputStream(Version.CURRENT);
DataSerializer.writeString(myString1, hdosString1);
byte[] str1Bytes = hdosString1.toByteArray();
System.out.println("Length of string1: " + str1Bytes.length);
HeapDataOutputStream hdosMyPDX = new HeapDataOutputStream(Version.CURRENT);
DataSerializer.writeObject(myPDX, hdosMyPDX);
byte[] pdxBytes = hdosMyPDX.toByteArray();
System.out.println("Length of myPDX: " + pdxBytes.length);
HeapDataOutputStream hdosString2 = new HeapDataOutputStream(Version.CURRENT);
DataSerializer.writeString(myString2, hdosString2);
byte[] str2Bytes = hdosString2.toByteArray();
System.out.println("Length of string2: " + str2Bytes.length);
Class classInstance = ds.getClass();
HeapDataOutputStream hdosClass = new HeapDataOutputStream(Version.CURRENT);
DataSerializer.writeClass(classInstance, hdosClass);
byte[] dsInitBytes = hdosClass.toByteArray();
int offsetStr1 = 1 + dsInitBytes.length;
int offsetPDX = 1 + dsInitBytes.length + str1Bytes.length + 8;
int offsetStr2 = 1 + dsInitBytes.length + str1Bytes.length + 8 + pdxBytes.length;
byte[] actual = out.toByteArray();
int floatBytes = Float.floatToRawIntBits(myFloat);
Byte[] expected = new Byte[] {DSCODE.DATA_SERIALIZABLE.toByte(), // byte
(byte) (myLong >> 56), (byte) (myLong >> 48), (byte) (myLong >> 40), (byte) (myLong >> 32),
(byte) (myLong >> 24), (byte) (myLong >> 16), (byte) (myLong >> 8), (byte) myLong, // long -
// myLong
};
for (int i = (dsInitBytes.length - 1); i >= 0; i--) {
expected = (Byte[]) ArrayUtils.insert(expected, 1, dsInitBytes[i]);
}
for (int i = (str1Bytes.length - 1); i >= 0; i--) {
expected = (Byte[]) ArrayUtils.insert(expected, offsetStr1, str1Bytes[i]);
}
for (int i = (pdxBytes.length - 1); i >= 0; i--) {
expected = (Byte[]) ArrayUtils.insert(expected, offsetPDX, pdxBytes[i]);
}
for (int i = (str2Bytes.length - 1); i >= 0; i--) {
expected = (Byte[]) ArrayUtils.insert(expected, offsetStr2, str2Bytes[i]);
}
checkBytes(expected, actual);
DataInput in = new DataInputStream(new ByteArrayInputStream(actual));
PdxInsideDS actualVal = (PdxInsideDS) DataSerializer.readObject(in);
// System.out.println("actualVal..."+actualVal);
assertTrue(
"Mismatch in write and read value: Value Write..." + ds + " Value Read..." + actualVal,
ds.equals(actualVal));
}
private void checkBytes(Byte[] expected, byte[] actual) {
StringBuffer msg = new StringBuffer("Actual output: ");
for (byte val : actual) {
msg.append(val + ", ");
}
msg.append("\nExpected output: ");
for (byte val : expected) {
msg.append(val + ", ");
}
if (actual.length != expected.length) {
System.out.println(msg.toString());
}
assertTrue("Mismatch in length, actual.length: " + actual.length + " and expected length: "
+ expected.length, actual.length == expected.length);
for (int i = 0; i < actual.length; i++) {
if (actual[i] != expected[i]) {
System.out.println(msg.toString());
}
assertTrue("Mismatch at index " + i, actual[i] == expected[i]);
}
}
private void checkBytes(byte[] expected, byte[] actual) {
StringBuffer msg = new StringBuffer("Actual output: ");
for (byte val : actual) {
msg.append(val + ", ");
}
msg.append("\nExpected output: ");
for (byte val : expected) {
msg.append(val + ", ");
}
if (actual.length != expected.length) {
System.out.println(msg.toString());
}
assertTrue("Mismatch in length, actual.length: " + actual.length + " and expected length: "
+ expected.length, actual.length == expected.length);
for (int i = 0; i < actual.length; i++) {
if (actual[i] != expected[i]) {
System.out.println(msg.toString());
}
assertTrue("Mismatch at index " + i, actual[i] == expected[i]);
}
}
@Test
public void testLong() throws IOException, ClassNotFoundException {
LongHolder v = (LongHolder) serializeAndDeserialize(new LongHolder(0x69));
assertEquals(0x69, v.getLong());
}
// this method adds coverage for bug 43236
@Test
public void testObjectPdxInstance() throws IOException, ClassNotFoundException {
Boolean previousPdxReadSerializedFlag = cache.getPdxReadSerializedOverride();
cache.setPdxReadSerializedOverride(true);
PdxReaderImpl.TESTHOOK_TRACKREADS = true;
try {
PdxInstance pi = (PdxInstance) serializeAndDeserialize(new ObjectHolder("hello"));
ObjectHolder v3 = (ObjectHolder) pi.getObject();
WritablePdxInstance wpi = pi.createWriter();
wpi.setField("f1", "goodbye");
assertEquals("goodbye", wpi.getField("f1"));
ObjectHolder v = (ObjectHolder) wpi.getObject();
ObjectHolder v2 = (ObjectHolder) wpi.getObject();
assertEquals("goodbye", v.getObject());
assertEquals("goodbye", v2.getObject());
assertEquals("hello", v3.getObject());
assertEquals("goodbye", wpi.getField("f1"));
} finally {
cache.setPdxReadSerializedOverride(previousPdxReadSerializedFlag);
PdxReaderImpl.TESTHOOK_TRACKREADS = false;
}
}
@Test
public void testObjectArrayPdxInstance() throws IOException, ClassNotFoundException {
Boolean previousPdxReadSerializedFlag = cache.getPdxReadSerializedOverride();
cache.setPdxReadSerializedOverride(true);
PdxReaderImpl.TESTHOOK_TRACKREADS = true;
try {
LongFieldHolder[] v = new LongFieldHolder[] {new LongFieldHolder(1), new LongFieldHolder(2)};
PdxInstance pi = (PdxInstance) serializeAndDeserialize(new ObjectArrayHolder(v));
ObjectArrayHolder oah = (ObjectArrayHolder) pi.getObject();
LongFieldHolder[] nv = (LongFieldHolder[]) oah.getObjectArray();
if (!Arrays.equals(v, nv)) {
throw new RuntimeException(
"expected " + Arrays.toString(v) + " but had " + Arrays.toString(nv));
}
Object[] oa = (Object[]) pi.getField("f1");
assertTrue(oa[0] instanceof PdxInstance);
assertTrue(oa[1] instanceof PdxInstance);
LongFieldHolder[] nv2 = new LongFieldHolder[2];
nv2[0] = (LongFieldHolder) ((PdxInstance) oa[0]).getObject();
nv2[1] = (LongFieldHolder) ((PdxInstance) oa[1]).getObject();
if (!Arrays.equals(v, nv2)) {
throw new RuntimeException(
"expected " + Arrays.toString(v) + " but had " + Arrays.toString(nv2));
}
} finally {
cache.setPdxReadSerializedOverride(previousPdxReadSerializedFlag);
PdxReaderImpl.TESTHOOK_TRACKREADS = false;
}
}
@Test
public void testLongField() throws IOException, ClassNotFoundException {
LongFieldHolder v =
(LongFieldHolder) serializeAndDeserialize(new LongFieldHolder(0x1020304050607080L));
assertEquals(0x1020304050607080L, v.getLong());
}
@Test
public void testAll() throws IOException, ClassNotFoundException {
AllFieldTypes v1 = new AllFieldTypes(0x1020304050607080L, false);
AllFieldTypes v2 = (AllFieldTypes) serializeAndDeserialize(v1);
assertEquals(v1, v2);
}
@Test
public void testBasicAll() throws IOException, ClassNotFoundException {
BasicAllFieldTypes v1 = new BasicAllFieldTypes(0x1020304050607080L, false);
try {
serializeAndDeserialize(v1);
throw new RuntimeException("expected NotSerializableException");
} catch (NotSerializableException expected) {
}
this.cache.setPdxSerializer(new BasicAllFieldTypesPdxSerializer());
try {
BasicAllFieldTypes v2 = (BasicAllFieldTypes) serializeAndDeserialize(v1);
assertEquals(v1, v2);
} finally {
this.cache.setPdxSerializer(null);
}
}
@Test
public void testPdxSerializerFalse() throws IOException, ClassNotFoundException {
this.cache.setPdxSerializer(new BasicAllFieldTypesPdxSerializer());
try {
POS v1 = new POS(3);
POS v2 = (POS) serializeAndDeserialize(v1);
assertEquals(v1, v2);
} finally {
this.cache.setPdxSerializer(null);
}
}
@Test
public void testAllWithNulls() throws IOException, ClassNotFoundException {
AllFieldTypes v1 = new AllFieldTypes(0x102030405060708L, true);
AllFieldTypes v2 = (AllFieldTypes) serializeAndDeserialize(v1);
assertEquals(v1, v2);
}
@Test
public void testBasicAllWithNulls() throws IOException, ClassNotFoundException {
BasicAllFieldTypes v1 = new BasicAllFieldTypes(0x1020304050607080L, true);
try {
serializeAndDeserialize(v1);
throw new RuntimeException("expected NotSerializableException");
} catch (NotSerializableException expected) {
}
this.cache.setPdxSerializer(new BasicAllFieldTypesPdxSerializer());
try {
BasicAllFieldTypes v2 = (BasicAllFieldTypes) serializeAndDeserialize(v1);
assertEquals(v1, v2);
} finally {
this.cache.setPdxSerializer(null);
}
}
@Test
public void testAllRF() throws IOException, ClassNotFoundException {
AllFieldTypesRF v1 = new AllFieldTypesRF(0x1020304050607080L, false);
AllFieldTypesRF v2 = (AllFieldTypesRF) serializeAndDeserialize(v1);
assertEquals(v1, v2);
}
@Test
public void testAllWithNullsRF() throws IOException, ClassNotFoundException {
AllFieldTypesRF v1 = new AllFieldTypesRF(0x102030405060708L, true);
AllFieldTypesRF v2 = (AllFieldTypesRF) serializeAndDeserialize(v1);
assertEquals(v1, v2);
}
@Test
public void testAllWF() throws IOException, ClassNotFoundException {
AllFieldTypesWF v1 = new AllFieldTypesWF(0x1020304050607080L, false);
AllFieldTypesWF v2 = (AllFieldTypesWF) serializeAndDeserialize(v1);
assertEquals(v1, v2);
}
@Test
public void testAllWithNullsWF() throws IOException, ClassNotFoundException {
AllFieldTypesWF v1 = new AllFieldTypesWF(0x102030405060708L, true);
AllFieldTypesWF v2 = (AllFieldTypesWF) serializeAndDeserialize(v1);
assertEquals(v1, v2);
}
private Object serializeAndDeserialize(Object in) throws IOException, ClassNotFoundException {
HeapDataOutputStream hdos = new HeapDataOutputStream(Version.CURRENT);
DataSerializer.writeObject(in, hdos);
byte[] bytes = hdos.toByteArray();
System.out.println("Serialized bytes = " + Arrays.toString(bytes));
return DataSerializer.readObject(new DataInputStream(new ByteArrayInputStream(bytes)));
}
public static class LongHolder implements PdxSerializable {
private long v;
public LongHolder(long v) {
this.v = v;
}
public LongHolder() {
}
public long getLong() {
return this.v;
}
@Override
public void toData(PdxWriter writer) {
writer.writeLong("f1", this.v);
}
@Override
public void fromData(PdxReader reader) {
this.v = reader.readLong("f1");
}
}
public static class ObjectHolder implements PdxSerializable {
private Object v;
public ObjectHolder(Object v) {
this.v = v;
}
public ObjectHolder() {
}
public Object getObject() {
return this.v;
}
@Override
public void toData(PdxWriter writer) {
writer.writeObject("f1", this.v);
}
@Override
public void fromData(PdxReader reader) {
this.v = reader.readObject("f1");
}
}
public static class ObjectArrayHolder implements PdxSerializable {
private Object[] v;
public ObjectArrayHolder(Object[] v) {
this.v = v;
}
public ObjectArrayHolder() {
}
public Object[] getObjectArray() {
return this.v;
}
@Override
public void toData(PdxWriter writer) {
writer.writeObjectArray("f1", this.v);
}
@Override
public void fromData(PdxReader reader) {
this.v = reader.readObjectArray("f1");
}
}
public static class LongFieldHolder implements PdxSerializable {
private long v;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (v ^ (v >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
LongFieldHolder other = (LongFieldHolder) obj;
if (v != other.v)
return false;
return true;
}
public LongFieldHolder(long v) {
this.v = v;
}
public LongFieldHolder() {
}
public long getLong() {
return this.v;
}
@Override
public void toData(PdxWriter writer) {
writer.writeLong("f1", this.v);
}
@Override
public void fromData(PdxReader reader) {
this.v = (Long) reader.readField("f1");
}
}
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
public static class BasicAllFieldTypes implements PdxSerializerObject {
public static String FILE_NAME = "testFile.txt";
// additional fields from tests.util.ValueHolder
public char aChar;
public boolean aBoolean;
public byte aByte;
public short aShort;
public int anInt;
public long aLong;
public float aFloat;
public double aDouble;
public Date aDate;
public String aString;
public Object anObject;
public Map aMap;
public Collection aCollection;
public boolean[] aBooleanArray;
public char[] aCharArray;
public byte[] aByteArray;
public short[] aShortArray;
public int[] anIntArray;
public long[] aLongArray;
public float[] aFloatArray;
public double[] aDoubleArray;
public String[] aStringArray;
public Object[] anObjectArray;
public byte[][] anArrayOfByteArray;
public BasicAllFieldTypes() {}
public BasicAllFieldTypes(long base, boolean nulls) {
fillInBaseValues(base, nulls);
}
/**
* Init fields using base as appropriate, but does not initialize aQueryObject field.
*
* @param base The base value for all fields. Fields are all set to a value using base as
* appropriate.
* @param useNulls If true, fill in nulls for those fields that can be set to null (to test null
* values), if false, then use a valid value (to test non-null values).
*/
public void fillInBaseValues(long base, boolean useNulls) {
final int maxCollectionSize = 100;
aChar = (char) base;
aBoolean = true;
aByte = (byte) base;
aShort = (short) base;
anInt = (int) base;
aLong = base;
aFloat = base;
aDouble = base;
aDate = new Date(base);
aString = "" + base;
if (useNulls) {
aDate = null;
aString = null;
anObject = null;
aMap = null;
aCollection = null;
// aRegion = null;
aBooleanArray = null;
aCharArray = null;
aByteArray = null;
aShortArray = null;
anIntArray = null;
aLongArray = null;
aFloatArray = null;
aDoubleArray = null;
anObjectArray = null;
anArrayOfByteArray = null;
} else {
int desiredCollectionSize = (int) Math.min(base, maxCollectionSize);
anObject = new SimpleClass((int) base, (byte) base);
aMap = new HashMap();
aCollection = new ArrayList();
aBooleanArray = new boolean[desiredCollectionSize];
aCharArray = new char[desiredCollectionSize];
aByteArray = new byte[desiredCollectionSize];
aShortArray = new short[desiredCollectionSize];
anIntArray = new int[desiredCollectionSize];
aLongArray = new long[desiredCollectionSize];
aFloatArray = new float[desiredCollectionSize];
aDoubleArray = new double[desiredCollectionSize];
aStringArray = new String[desiredCollectionSize];
anObjectArray = new Object[desiredCollectionSize];
anArrayOfByteArray = new byte[desiredCollectionSize][desiredCollectionSize];
if (desiredCollectionSize > 0) {
for (int i = 0; i < desiredCollectionSize - 1; i++) {
aMap.put(i, i);
aCollection.add(i);
aBooleanArray[i] = (i % 2) == 0;
aCharArray[i] = (char) (i);
aByteArray[i] = (byte) (i);
aShortArray[i] = (short) i;
anIntArray[i] = i;
aLongArray[i] = i;
aFloatArray[i] = i;
aDoubleArray[i] = i;
aStringArray[i] = "" + i;
anObjectArray[i] = anObject;
anArrayOfByteArray[i] = aByteArray;
}
// now add the last value, using base if possible
aMap.put(base, base);
aCollection.add(base);
aBooleanArray[desiredCollectionSize - 1] = true;
aCharArray[desiredCollectionSize - 1] = (char) base;
aByteArray[desiredCollectionSize - 1] = (byte) base;
aShortArray[desiredCollectionSize - 1] = (short) base;
anIntArray[desiredCollectionSize - 1] = (int) base;
aLongArray[desiredCollectionSize - 1] = base;
aFloatArray[desiredCollectionSize - 1] = base;
aDoubleArray[desiredCollectionSize - 1] = base;
aStringArray[desiredCollectionSize - 1] = "" + base;
anObjectArray[desiredCollectionSize - 1] = anObject;
// aRegion = CacheHelper.getCache().rootRegions().iterator().next();
}
}
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return getClass().getName() + " [aChar=" + this.aChar + ", aBoolean=" + this.aBoolean
+ ", aByte=" + this.aByte + ", aShort=" + this.aShort + ", anInt=" + this.anInt
+ ", aLong=" + this.aLong + ", aFloat=" + this.aFloat + ", aDouble=" + this.aDouble
+ ", aDate=" + this.aDate + ", aString=" + this.aString + ", anObject=" + this.anObject
+ ", aMap=" + this.aMap + ", aCollection=" + this.aCollection + ", aBooleanArray="
+ Arrays.toString(this.aBooleanArray) + ", aCharArray=" + Arrays.toString(this.aCharArray)
+ ", aByteArray=" + Arrays.toString(this.aByteArray) + ", aShortArray="
+ Arrays.toString(this.aShortArray) + ", anIntArray=" + Arrays.toString(this.anIntArray)
+ ", aLongArray=" + Arrays.toString(this.aLongArray) + ", aFloatArray="
+ Arrays.toString(this.aFloatArray) + ", aDoubleArray="
+ Arrays.toString(this.aDoubleArray) + ", aStringArray="
+ Arrays.toString(this.aStringArray) + ", anObjectArray="
+ Arrays.toString(this.anObjectArray) + ", anArrayOfByteArray="
+ Arrays.toString(this.anArrayOfByteArray) + "]";
}
@Override
public int hashCode() {
return 37;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof BasicAllFieldTypes)) {
return false;
}
BasicAllFieldTypes other = (BasicAllFieldTypes) o;
if (this.aChar != other.aChar) {
System.out.println("!= aChar");
return false;
}
if (this.aByte != other.aByte) {
System.out.println("!= aByte");
return false;
}
if (this.aBoolean != other.aBoolean) {
System.out.println("!= aBoolean");
return false;
}
if (this.aShort != other.aShort) {
System.out.println("!= aShort");
return false;
}
if (this.anInt != other.anInt) {
System.out.println("!= anInt");
return false;
}
if (this.aLong != other.aLong) {
System.out.println("!= aLong");
return false;
}
if (this.aFloat != other.aFloat) {
System.out.println("!= aFloat");
return false;
}
if (this.aDouble != other.aDouble) {
System.out.println("!= aDouble");
return false;
}
if (!basicEquals(this.aDate, other.aDate)) {
System.out.println("!= aDate");
return false;
}
if (!basicEquals(this.aString, other.aString)) {
System.out.println("!= aString");
return false;
}
if (!basicEquals(this.anObject, other.anObject)) {
System.out.println("!= nObject");
return false;
}
if (!basicEquals(this.aMap, other.aMap)) {
System.out.println("!= aMap");
return false;
}
if (!basicEquals(this.aCollection, other.aCollection)) {
System.out.println("!= aCollection");
return false;
}
// if (!basicEquals(this.aRegion, other.aRegion)) {
// return false;
// }
if (!Arrays.equals(this.aBooleanArray, other.aBooleanArray)) {
System.out.println("!= boolean[]");
return false;
}
if (!Arrays.equals(this.aCharArray, other.aCharArray)) {
System.out.println("!= char[]");
return false;
}
if (!Arrays.equals(this.aByteArray, other.aByteArray)) {
System.out.println("!= byte[]");
return false;
}
if (!Arrays.equals(this.aShortArray, other.aShortArray)) {
System.out.println("!= short[]");
return false;
}
if (!Arrays.equals(this.anIntArray, other.anIntArray)) {
System.out.println("!= int[]");
return false;
}
if (!Arrays.equals(this.aLongArray, other.aLongArray)) {
System.out.println("!= long[]");
return false;
}
if (!Arrays.equals(this.aFloatArray, other.aFloatArray)) {
System.out.println("!= float[]");
return false;
}
if (!Arrays.equals(this.aDoubleArray, other.aDoubleArray)) {
System.out.println("!= double[]");
return false;
}
if (!Arrays.equals(this.aStringArray, other.aStringArray)) {
System.out.println("!= String[]");
return false;
}
if (!Arrays.equals(this.anObjectArray, other.anObjectArray)) {
System.out.println("!= Object[]");
return false;
}
if (!byteArrayofArraysEqual(this.anArrayOfByteArray, other.anArrayOfByteArray)) {
System.out.println("!= byte[][]");
return false;
}
return true;
}
private boolean byteArrayofArraysEqual(byte[][] o1, byte[][] o2) {
if (o1 == null) {
return o2 == null;
} else if (o2 == null) {
return false;
} else {
if (o1.length != o2.length) {
return false;
}
for (int i = 0; i < o1.length; i++) {
if (!Arrays.equals(o1[i], o2[i])) {
return false;
}
}
}
return true;
}
private boolean basicEquals(Object o1, Object o2) {
if (o1 == null) {
return o2 == null;
} else if (o2 == null) {
return false;
} else {
return o1.equals(o2);
}
}
}
@Test
public void testVariableFields() throws Exception {
HeapDataOutputStream out = new HeapDataOutputStream(Version.CURRENT);
DataSerializer.writeObject(new VariableFields(1), out);
try {
DataSerializer.writeObject(new VariableFields(2), out);
throw new RuntimeException("expected ToDataException");
} catch (ToDataException expected) {
if (!(expected.getCause() instanceof PdxSerializationException)) {
throw new RuntimeException("expected cause to be PdxSerializationException");
}
}
try {
DataSerializer.writeObject(new VariableFields(0), out);
throw new RuntimeException("expected PdxSerializationException");
} catch (PdxSerializationException expected) {
}
try {
DataSerializer.writeObject(new VariableFields(1, Object.class), out);
throw new RuntimeException("expected ToDataException");
} catch (ToDataException expected) {
if (!(expected.getCause() instanceof PdxSerializationException)) {
throw new RuntimeException("expected cause to be PdxSerializationException");
}
}
// TODO also test marking different identity fields.
}
public static class VariableFields implements PdxSerializable {
private Class fieldType = String.class;
private int fieldCount;
public VariableFields(int fieldCount) {
this.fieldCount = fieldCount;
}
public VariableFields(int fieldCount, Class fieldType) {
this.fieldCount = fieldCount;
this.fieldType = fieldType;
}
@Override
public void toData(PdxWriter writer) {
((PdxWriterImpl) writer).setDoExtraValidation(true);
writer.writeInt("fieldCount", this.fieldCount);
for (int i = 0; i < this.fieldCount; i++) {
writer.writeField("f" + i, null, this.fieldType);
}
}
@Override
public void fromData(PdxReader reader) {
throw new IllegalStateException("should never be called");
}
}
public static class AllFieldTypes extends BasicAllFieldTypes implements PdxSerializable {
public AllFieldTypes() {
super();
}
public AllFieldTypes(long base, boolean nulls) {
super(base, nulls);
}
/*
* (non-Javadoc)
*
* @see org.apache.geode.pdx.PdxSerializable#toData(org.apache.geode. pdx.PdxWriter)
*/
@Override
public void toData(PdxWriter out) {
new BasicAllFieldTypesPdxSerializer().toData(this, out);
}
/*
* (non-Javadoc)
*
* @see org.apache.geode.pdx.PdxSerializable#fromData(org.apache.geode .pdx.PdxReader)
*/
@Override
public void fromData(PdxReader in) {
new BasicAllFieldTypesPdxSerializer().fillInData(in, this);
}
}
public static class BasicAllFieldTypesPdxSerializer implements PdxSerializer {
@Override
public boolean toData(Object o, PdxWriter out) {
if (o instanceof BasicAllFieldTypes) {
BasicAllFieldTypes pdx = (BasicAllFieldTypes) o;
// extra fields for this version
out.writeChar("aChar", pdx.aChar);
out.writeBoolean("aBoolean", pdx.aBoolean);
out.writeByte("aByte", pdx.aByte);
out.writeShort("aShort", pdx.aShort);
out.writeInt("anInt", pdx.anInt);
out.writeLong("aLong", pdx.aLong);
out.writeFloat("aFloat", pdx.aFloat);
out.writeDouble("aDouble", pdx.aDouble);
out.writeDate("aDate", pdx.aDate);
out.writeString("aString", pdx.aString);
out.writeObject("anObject", pdx.anObject);
out.writeObject("aMap", pdx.aMap);
out.writeObject("aCollection", pdx.aCollection);
out.writeBooleanArray("aBooleanArray", pdx.aBooleanArray);
out.writeCharArray("aCharArray", pdx.aCharArray);
out.writeByteArray("aByteArray", pdx.aByteArray);
out.writeShortArray("aShortArray", pdx.aShortArray);
out.writeIntArray("anIntArray", pdx.anIntArray);
out.writeLongArray("aLongArray", pdx.aLongArray);
out.writeFloatArray("aFloatArray", pdx.aFloatArray);
out.writeDoubleArray("aDoubleArray", pdx.aDoubleArray);
out.writeStringArray("aStringArray", pdx.aStringArray);
out.writeObjectArray("anObjectArray", pdx.anObjectArray);
out.writeArrayOfByteArrays("anArrayOfByteArray", pdx.anArrayOfByteArray);
return true;
} else {
return false;
}
}
@Override
public Object fromData(Class<?> clazz, PdxReader in) {
if (BasicAllFieldTypes.class.isAssignableFrom(clazz)) {
BasicAllFieldTypes pdx = new BasicAllFieldTypes();
fillInData(in, pdx);
return pdx;
} else {
return null;
}
}
public void fillInData(PdxReader in, BasicAllFieldTypes pdx) {
// extra fields for this version
try {
in.readBoolean("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readByte("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readShort("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readInt("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readLong("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readFloat("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readDouble("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readDate("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readString("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readObject("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readBooleanArray("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readCharArray("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readByteArray("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readShortArray("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readIntArray("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readLongArray("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readFloatArray("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readDoubleArray("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readStringArray("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readObjectArray("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readArrayOfByteArrays("aChar");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
try {
in.readChar("aBoolean");
throw new RuntimeException("expected PdxFieldTypeMismatchException");
} catch (PdxFieldTypeMismatchException expected) {
// expected
}
pdx.aChar = in.readChar("aChar");
pdx.aBoolean = in.readBoolean("aBoolean");
pdx.aByte = in.readByte("aByte");
pdx.aShort = in.readShort("aShort");
pdx.anInt = in.readInt("anInt");
pdx.aLong = in.readLong("aLong");
pdx.aFloat = in.readFloat("aFloat");
pdx.aDouble = in.readDouble("aDouble");
pdx.aDate = in.readDate("aDate");
pdx.aString = in.readString("aString");
pdx.anObject = in.readObject("anObject");
pdx.aMap = (Map) in.readObject("aMap");
pdx.aCollection = (Collection) in.readObject("aCollection");
pdx.aBooleanArray = in.readBooleanArray("aBooleanArray");
pdx.aCharArray = in.readCharArray("aCharArray");
pdx.aByteArray = in.readByteArray("aByteArray");
pdx.aShortArray = in.readShortArray("aShortArray");
pdx.anIntArray = in.readIntArray("anIntArray");
pdx.aLongArray = in.readLongArray("aLongArray");
pdx.aFloatArray = in.readFloatArray("aFloatArray");
pdx.aDoubleArray = in.readDoubleArray("aDoubleArray");
pdx.aStringArray = in.readStringArray("aStringArray");
pdx.anObjectArray = in.readObjectArray("anObjectArray");
pdx.anArrayOfByteArray = in.readArrayOfByteArrays("anArrayOfByteArray");
}
}
public static class AllFieldTypesRF extends AllFieldTypes {
public AllFieldTypesRF(long l, boolean b) {
super(l, b);
}
public AllFieldTypesRF() {
super();
}
@Override
public void fromData(PdxReader in) {
aChar = (Character) in.readField("aChar");
aBoolean = (Boolean) in.readField("aBoolean");
aByte = (Byte) in.readField("aByte");
aShort = (Short) in.readField("aShort");
anInt = (Integer) in.readField("anInt");
aLong = (Long) in.readField("aLong");
aFloat = (Float) in.readField("aFloat");
aDouble = (Double) in.readField("aDouble");
aDate = (Date) in.readField("aDate");
aString = (String) in.readField("aString");
anObject = in.readField("anObject");
aMap = (Map) in.readField("aMap");
aCollection = (Collection) in.readField("aCollection");
aBooleanArray = (boolean[]) in.readField("aBooleanArray");
aCharArray = (char[]) in.readField("aCharArray");
aByteArray = (byte[]) in.readField("aByteArray");
aShortArray = (short[]) in.readField("aShortArray");
anIntArray = (int[]) in.readField("anIntArray");
aLongArray = (long[]) in.readField("aLongArray");
aFloatArray = (float[]) in.readField("aFloatArray");
aDoubleArray = (double[]) in.readField("aDoubleArray");
aStringArray = (String[]) in.readField("aStringArray");
anObjectArray = (Object[]) in.readField("anObjectArray");
anArrayOfByteArray = (byte[][]) in.readField("anArrayOfByteArray");
}
}
public static class AllFieldTypesWF extends AllFieldTypes {
public AllFieldTypesWF(long l, boolean b) {
super(l, b);
}
public AllFieldTypesWF() {
super();
}
@Override
public void toData(PdxWriter out) {
out.writeField("aChar", this.aChar, char.class);
out.writeField("aBoolean", this.aBoolean, boolean.class);
out.writeField("aByte", this.aByte, byte.class);
out.writeField("aShort", this.aShort, short.class);
out.writeField("anInt", this.anInt, int.class);
out.writeField("aLong", this.aLong, long.class);
out.writeField("aFloat", this.aFloat, float.class);
out.writeField("aDouble", this.aDouble, double.class);
out.writeField("aDate", this.aDate, Date.class);
out.writeField("aString", this.aString, String.class);
out.writeField("anObject", this.anObject, Object.class);
out.writeField("aMap", this.aMap, Map.class);
out.writeField("aCollection", this.aCollection, Collection.class);
out.writeField("aBooleanArray", this.aBooleanArray, boolean[].class);
out.writeField("aCharArray", this.aCharArray, char[].class);
out.writeField("aByteArray", this.aByteArray, byte[].class);
out.writeField("aShortArray", this.aShortArray, short[].class);
out.writeField("anIntArray", this.anIntArray, int[].class);
out.writeField("aLongArray", this.aLongArray, long[].class);
out.writeField("aFloatArray", this.aFloatArray, float[].class);
out.writeField("aDoubleArray", this.aDoubleArray, double[].class);
out.writeField("aStringArray", this.aStringArray, String[].class);
out.writeField("anObjectArray", this.anObjectArray, Object[].class);
// TODO test other types of Object[] like SimpleClass[].
out.writeField("anArrayOfByteArray", this.anArrayOfByteArray, byte[][].class);
}
}
private byte[] createBlob(Object o) throws IOException {
HeapDataOutputStream out = new HeapDataOutputStream(Version.CURRENT);
DataSerializer.writeObject(o, out);
return out.toByteArray();
}
private <T> T deblob(byte[] blob) throws IOException, ClassNotFoundException {
return (T) DataSerializer.readObject(new DataInputStream(new ByteArrayInputStream(blob)));
}
/**
* Make sure that if a class adds a field that pdx serialization will preserve the extra field.
*/
@Test
public void testFieldAppend() throws Exception {
MyEvolvablePdx.setVersion(1);
MyEvolvablePdx pdx = new MyEvolvablePdx(7);
assertEquals(7, pdx.f1);
assertEquals(0, pdx.f2);
MyEvolvablePdx.setVersion(2);
pdx = new MyEvolvablePdx(7);
assertEquals(7, pdx.f1);
assertEquals(8, pdx.f2);
byte[] v2actual = createBlob(pdx);
int v2typeId = getBlobPdxTypeId(v2actual);
cache.getPdxRegistry().removeLocal(pdx);
MyEvolvablePdx.setVersion(1);
MyEvolvablePdx pdxv1 = deblob(v2actual);
assertEquals(7, pdxv1.f1);
assertEquals(0, pdxv1.f2);
// now reserialize and make sure f2 is preserved
byte[] v1actual = createBlob(pdxv1);
assertEquals(v2typeId, getBlobPdxTypeId(v1actual));
checkBytes(v2actual, v1actual);
// serialize one more time to make sure internal cache works ok
v1actual = createBlob(pdxv1);
assertEquals(v2typeId, getBlobPdxTypeId(v1actual));
checkBytes(v2actual, v1actual);
// make sure CopyHelper preserves extra fields
MyEvolvablePdx pdxv1copy = CopyHelper.copy(pdxv1);
v1actual = createBlob(pdxv1copy);
assertEquals(v2typeId, getBlobPdxTypeId(v1actual));
checkBytes(v2actual, v1actual);
MyEvolvablePdx.setVersion(2);
cache.getPdxRegistry().removeLocal(pdx);
MyEvolvablePdx pdxv2 = deblob(v1actual);
assertEquals(7, pdxv2.f1);
assertEquals(8, pdxv2.f2);
// make sure we can dserialize a second time with the same results
pdxv2 = deblob(v1actual);
assertEquals(7, pdxv2.f1);
assertEquals(8, pdxv2.f2);
}
@Test
public void testFieldInsert() throws Exception {
MyEvolvablePdx.setVersion(1);
MyEvolvablePdx pdx = new MyEvolvablePdx(7);
assertEquals(7, pdx.f1);
assertEquals(0, pdx.f2);
MyEvolvablePdx.setVersion(3);
pdx = new MyEvolvablePdx(7);
assertEquals(7, pdx.f1);
assertEquals(8, pdx.f2);
byte[] v3actual = createBlob(pdx);
int v3typeId = getBlobPdxTypeId(v3actual);
cache.getPdxRegistry().removeLocal(pdx);
MyEvolvablePdx.setVersion(1);
MyEvolvablePdx pdxv1 = deblob(v3actual);
assertEquals(7, pdxv1.f1);
assertEquals(0, pdxv1.f2);
int numPdxTypes = getNumPdxTypes();
// now reserialize and make sure f2 is preserved
byte[] v1actual = createBlob(pdxv1);
int mergedTypeId = getBlobPdxTypeId(v1actual);
assertEquals(numPdxTypes + 1, getNumPdxTypes());
TypeRegistry tr = cache.getPdxRegistry();
PdxType v3Type = tr.getType(v3typeId);
PdxType mergedType = tr.getType(mergedTypeId);
assertFalse(mergedType.equals(v3Type));
assertTrue(mergedType.compatible(v3Type));
MyEvolvablePdx.setVersion(3);
cache.getPdxRegistry().removeLocal(pdxv1);
MyEvolvablePdx pdxv3 = deblob(v1actual);
assertEquals(7, pdxv3.f1);
assertEquals(8, pdxv3.f2);
}
@Test
public void testFieldRemove() throws Exception {
// this test pretends that version 1 is newer than version2
// so it look like a field was removed.
MyEvolvablePdx.setVersion(1);
MyEvolvablePdx pdx = new MyEvolvablePdx(7);
assertEquals(7, pdx.f1);
assertEquals(0, pdx.f2);
byte[] v1actual = createBlob(pdx);
int v1typeId = getBlobPdxTypeId(v1actual);
cache.getPdxRegistry().removeLocal(pdx);
MyEvolvablePdx.setVersion(2);
MyEvolvablePdx pdxv2 = deblob(v1actual);
assertEquals(7, pdxv2.f1);
assertEquals(0, pdxv2.f2);
pdxv2.f2 = 23;
int numPdxTypes = getNumPdxTypes();
// now reserialize and make sure it is version2 and not version1
byte[] v2actual = createBlob(pdxv2);
int v2typeId = getBlobPdxTypeId(v2actual);
assertEquals(numPdxTypes + 1, getNumPdxTypes());
TypeRegistry tr = cache.getPdxRegistry();
PdxType v2Type = tr.getType(v2typeId);
PdxType v1Type = tr.getType(v1typeId);
assertFalse(v1Type.equals(v2Type));
assertFalse(v1Type.compatible(v2Type));
assertNotNull(v1Type.getPdxField("f1"));
assertNull(v1Type.getPdxField("f2"));
assertNotNull(v2Type.getPdxField("f1"));
assertNotNull(v2Type.getPdxField("f2"));
MyEvolvablePdx.setVersion(1);
cache.getPdxRegistry().removeLocal(pdx);
MyEvolvablePdx pdxv3 = deblob(v2actual);
assertEquals(7, pdxv3.f1);
assertEquals(0, pdxv3.f2);
}
private int getBlobPdxTypeId(byte[] blob) {
ByteBuffer bb = ByteBuffer.wrap(blob);
// skip byte for PDX dscode and integer for pdx length
return bb.getInt(DataSize.BYTE_SIZE + DataSize.INTEGER_SIZE);
}
public static class MyEvolvablePdx implements PdxSerializable {
private static int version = 1;
private static int getVersion() {
return version;
}
private static void setVersion(int v) {
version = v;
}
public int f1;
public int f2;
public MyEvolvablePdx(int base) {
this.f1 = base;
base++;
if (getVersion() >= 2) {
this.f2 = base;
base++;
}
}
public MyEvolvablePdx() {
// need for pdx deserialization
}
@Override
public void toData(PdxWriter writer) {
if (getVersion() == 3) {
writer.writeInt("f2", this.f2);
}
writer.writeInt("f1", this.f1);
if (getVersion() == 2) {
writer.writeInt("f2", this.f2);
}
}
@Override
public void fromData(PdxReader reader) {
if (getVersion() == 3) {
this.f2 = reader.readInt("f2");
}
this.f1 = reader.readInt("f1");
if (getVersion() == 2) {
this.f2 = reader.readInt("f2");
}
}
}
/** PlainOldSerializable */
public static class POS implements java.io.Serializable {
int f;
public POS(int i) {
this.f = i;
}
public int hashCode() {
return f;
}
public boolean equals(Object obj) {
if (obj == null)
return false;
if (!(obj instanceof POS))
return false;
POS other = (POS) obj;
return this.f == other.f;
}
}
}