Skip to content

Commit

Permalink
GEODE-5038: Improve human-readable formatting of arrays in PdxInstanc…
Browse files Browse the repository at this point in the history
…e.toString(). (apache#1793)

* GEODE-5038: Improve human-readable formatting of arrays.

* GEODE-5038: Explicitly handling primitive arrays.
  • Loading branch information
PivotalSarge authored Apr 19, 2018
1 parent 8ec0c53 commit 36204d1
Show file tree
Hide file tree
Showing 3 changed files with 235 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import org.apache.geode.internal.tcp.ByteBufferInputStream;
import org.apache.geode.internal.tcp.ByteBufferInputStream.ByteSource;
import org.apache.geode.internal.tcp.ByteBufferInputStream.ByteSourceFactory;
import org.apache.geode.internal.util.Hex;
import org.apache.geode.pdx.JSONFormatter;
import org.apache.geode.pdx.PdxSerializationException;
import org.apache.geode.pdx.WritablePdxInstance;
Expand Down Expand Up @@ -464,8 +465,30 @@ public String toString() {
result.append(fieldType.getFieldName());
result.append("=");
try {
// TODO check to see if getField returned an array and if it did use Arrays.deepToString
result.append(ur.readField(fieldType.getFieldName()));
final Object value = ur.readField(fieldType.getFieldName());
if (value instanceof byte[]) {
result.append(Hex.toHex((byte[]) value));
} else if (value.getClass().isArray()) {
if (value instanceof short[]) {
result.append(Arrays.toString((short[]) value));
} else if (value instanceof int[]) {
result.append(Arrays.toString((int[]) value));
} else if (value instanceof long[]) {
result.append(Arrays.toString((long[]) value));
} else if (value instanceof char[]) {
result.append(Arrays.toString((char[]) value));
} else if (value instanceof float[]) {
result.append(Arrays.toString((float[]) value));
} else if (value instanceof double[]) {
result.append(Arrays.toString((double[]) value));
} else if (value instanceof boolean[]) {
result.append(Arrays.toString((boolean[]) value));
} else {
result.append(Arrays.deepToString((Object[]) value));
}
} else {
result.append(value);
}
} catch (RuntimeException e) {
result.append(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ public WritablePdxInstanceImpl(PdxReaderImpl original) {
}

private synchronized void dirtyField(PdxField f, Object value) {
if (this.dirtyFields == null) {
this.dirtyFields = new Object[getPdxType().getFieldCount()];
if (dirtyFields == null) {
dirtyFields = new Object[getPdxType().getFieldCount()];
}
if (value == null) {
value = NULL_TOKEN;
}
this.dirtyFields[f.getFieldIndex()] = value;
dirtyFields[f.getFieldIndex()] = value;
clearCachedState();
}

Expand All @@ -49,10 +49,10 @@ private synchronized void dirtyField(PdxField f, Object value) {
*/
@Override
protected synchronized PdxReaderImpl getUnmodifiableReader(String fieldName) {
if (this.dirtyFields != null) {
if (dirtyFields != null) {
PdxField f = getPdxType().getPdxField(fieldName);
if (f != null) {
if (this.dirtyFields[f.getFieldIndex()] != null) {
if (dirtyFields[f.getFieldIndex()] != null) {
return getUnmodifiableReader();
}
}
Expand All @@ -75,7 +75,7 @@ public synchronized int hashCode() {
*/
@Override
protected synchronized PdxReaderImpl getUnmodifiableReader() {
if (this.dirtyFields != null) {
if (dirtyFields != null) {
PdxOutputStream os = new PdxOutputStream(basicSize() + PdxWriterImpl.HEADER_SIZE);
PdxWriterImpl writer;
if (getPdxType().getHasDeletedField()) {
Expand All @@ -92,7 +92,7 @@ protected synchronized PdxReaderImpl getUnmodifiableReader() {
if (f.isDeleted()) {
continue;
}
Object dv = this.dirtyFields[f.getFieldIndex()];
Object dv = dirtyFields[f.getFieldIndex()];
if (dv != null) {
if (dv == NULL_TOKEN) {
dv = null;
Expand All @@ -106,7 +106,7 @@ protected synchronized PdxReaderImpl getUnmodifiableReader() {
ByteBuffer bb = os.toByteBuffer();
bb.position(PdxWriterImpl.HEADER_SIZE);
basicSetBuffer(bb.slice());
this.dirtyFields = null;
dirtyFields = null;
}
return new PdxReaderImpl(this);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
/*
* 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.internal;

import static org.apache.commons.lang.StringUtils.substringAfter;
import static org.apache.geode.distributed.ConfigurationProperties.DISTRIBUTED_SYSTEM_ID;
import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
import static org.junit.Assert.assertEquals;

import java.io.Serializable;

import org.apache.commons.lang.StringUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import org.apache.geode.cache.CacheFactory;
import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.apache.geode.pdx.PdxInstance;
import org.apache.geode.test.junit.categories.IntegrationTest;
import org.apache.geode.test.junit.categories.SerializationTest;

@Category({IntegrationTest.class, SerializationTest.class})
public class PdxInstanceImplTest {
private GemFireCacheImpl cache;

@Before
public void setUp() {
cache = (GemFireCacheImpl) new CacheFactory().set(MCAST_PORT, "0")
.set(DISTRIBUTED_SYSTEM_ID, "255").setPdxReadSerialized(true).create();
}

@After
public void tearDown() {
cache.close();
}

@Test
public void testToStringForEmpty() {
PdxInstance instance =
PdxInstanceFactoryImpl.newCreator("testToStringForEmpty", false, cache).create();
assertEquals("testToStringForEmpty]{}", substringAfter(instance.toString(), ","));
}

@Test
public void testToStringForInteger() {
PdxInstance instance = PdxInstanceFactoryImpl.newCreator("testToStringForInteger", false, cache)
.writeInt("intField", 37).create();
assertEquals("testToStringForInteger]{intField=37}", substringAfter(instance.toString(), ","));
}

@Test
public void testToStringForString() {
PdxInstance instance = PdxInstanceFactoryImpl.newCreator("testToStringForString", false, cache)
.writeString("stringField", "MOOF!").create();
assertEquals("testToStringForString]{stringField=MOOF!}",
substringAfter(instance.toString(), ","));
}

@Test
public void testToStringForBooleanLongDoubleAndString() {
PdxInstance instance =
PdxInstanceFactoryImpl.newCreator("testToStringForBooleanLongDoubleAndString", false, cache)
.writeBoolean("booleanField", Boolean.TRUE).writeLong("longField", 37L)
.writeDouble("doubleField", 3.1415).writeString("stringField", "MOOF!").create();
assertEquals(
"testToStringForBooleanLongDoubleAndString]{booleanField=true, doubleField=3.1415, longField=37, stringField=MOOF!}",
substringAfter(instance.toString(), ","));
}

@Test
public void testToStringForObject() {
PdxInstance instance = PdxInstanceFactoryImpl.newCreator("testToStringForObject", false, cache)
.writeObject("objectField", new SerializableObject("Dave")).create();
assertEquals("testToStringForObject]{objectField=Dave}",
substringAfter(instance.toString(), ","));
}

@Test
public void testToStringForByteArray() {
PdxInstance instance = PdxInstanceFactoryImpl
.newCreator("testToStringForByteArray", false, cache).writeByteArray("byteArrayField",
new byte[] {(byte) 0xDE, (byte) 0xAD, (byte) 0xBE, (byte) 0xEF})
.create();
assertEquals("testToStringForByteArray]{byteArrayField=DEADBEEF}",
substringAfter(instance.toString(), ","));
}

@Test
public void testToStringForObjectArray() {
PdxInstance instance =
PdxInstanceFactoryImpl.newCreator("testToStringForObjectArray", false, cache)
.writeObjectArray("objectArrayField",
new Object[] {new SerializableObject("Dave"), new SerializableObject("Stewart")})
.create();
assertEquals("testToStringForObjectArray]{objectArrayField=[Dave, Stewart]}",
substringAfter(instance.toString(), ","));
}

@Test
public void testToStringForIntegerArray() {
PdxInstance instance =
PdxInstanceFactoryImpl.newCreator("testToStringForIntegerArray", false, cache)
.writeObjectArray("integerArrayField", new Integer[] {new Integer(37), new Integer(42)})
.create();
assertEquals("testToStringForIntegerArray]{integerArrayField=[37, 42]}",
substringAfter(instance.toString(), ","));
}

@Test
public void testToStringForShortArray() {
PdxInstance instance =
PdxInstanceFactoryImpl.newCreator("testToStringForShortArray", false, cache)
.writeShortArray("shortArrayField", new short[] {37, 42}).create();
assertEquals("testToStringForShortArray]{shortArrayField=[37, 42]}",
substringAfter(instance.toString(), ","));
}

@Test
public void testToStringForIntArray() {
PdxInstance instance =
PdxInstanceFactoryImpl.newCreator("testToStringForIntArray", false, cache)
.writeIntArray("intArrayField", new int[] {37, 42}).create();
assertEquals("testToStringForIntArray]{intArrayField=[37, 42]}",
substringAfter(instance.toString(), ","));
}

@Test
public void testToStringForLongArray() {
PdxInstance instance =
PdxInstanceFactoryImpl.newCreator("testToStringForLongArray", false, cache)
.writeLongArray("longArrayField", new long[] {37L, 42L}).create();
assertEquals("testToStringForLongArray]{longArrayField=[37, 42]}",
substringAfter(instance.toString(), ","));
}

@Test
public void testToStringForCharArray() {
PdxInstance instance =
PdxInstanceFactoryImpl.newCreator("testToStringForCharArray", false, cache)
.writeCharArray("charArrayField", new char[] {'o', 'k'}).create();
assertEquals("testToStringForCharArray]{charArrayField=[o, k]}",
substringAfter(instance.toString(), ","));
}

@Test
public void testToStringForFloatArray() {
PdxInstance instance =
PdxInstanceFactoryImpl.newCreator("testToStringForFloatArray", false, cache)
.writeFloatArray("floatArrayField", new float[] {3.14159F, 2.71828F}).create();
assertEquals("testToStringForFloatArray]{floatArrayField=[3.14159, 2.71828]}",
substringAfter(instance.toString(), ","));
}

@Test
public void testToStringForDoubleArray() {
PdxInstance instance =
PdxInstanceFactoryImpl.newCreator("testToStringForDoubleArray", false, cache)
.writeDoubleArray("doubleArrayField", new double[] {3.14159, 2.71828}).create();
assertEquals("testToStringForDoubleArray]{doubleArrayField=[3.14159, 2.71828]}",
substringAfter(instance.toString(), ","));
}

@Test
public void testToStringForBooleanArray() {
PdxInstance instance =
PdxInstanceFactoryImpl.newCreator("testToStringForBooleanArray", false, cache)
.writeBooleanArray("booleanArrayField", new boolean[] {false, true}).create();
assertEquals("testToStringForBooleanArray]{booleanArrayField=[false, true]}",
substringAfter(instance.toString(), ","));
}

static class SerializableObject implements Serializable {
String name;

public SerializableObject() {
// Do nothing.
}

public SerializableObject(String name) {
this.name = name;
}

@Override
public String toString() {
return StringUtils.trimToEmpty(name);
}
}
}

0 comments on commit 36204d1

Please sign in to comment.