This is an automated email from the ASF dual-hosted git repository.
chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fury.git
The following commit(s) were added to refs/heads/main by this push:
new 9a39cb3f feat(java): Support copy capabilities for some classes
without no-argument constructors (#1794)
9a39cb3f is described below
commit 9a39cb3fc7a92e2c9546b094d60af62fc6d2e603
Author: zhaommmmomo <[email protected]>
AuthorDate: Tue Aug 13 14:07:08 2024 +0800
feat(java): Support copy capabilities for some classes without no-argument
constructors (#1794)
## What does this PR do?
Some classes with no-argument constructors will report an error when
calling `copy()`.
This pr:
- implement the copy method for the no-argument constructor serializer
- add test case
## Related issues
https://github.com/apache/fury/issues/1777
https://github.com/apache/fury/issues/1679
## Does this PR introduce any user-facing change?
<!--
If any user-facing interface changes, please [open an
issue](https://github.com/apache/fury/issues/new/choose) describing the
need to do so and update the document if necessary.
-->
- [ ] Does this PR introduce any public API change?
- [ ] Does this PR introduce any binary protocol compatibility change?
## Benchmark
<!--
When the PR has an impact on performance (if you don't know whether the
PR will have an impact on performance, you can submit the PR first, and
if it will have impact on performance, the code reviewer will explain
it), be sure to attach a benchmark data here.
-->
---------
Co-authored-by: Shawn Yang <[email protected]>
---
.../apache/fury/serializer/BufferSerializers.java | 8 +
.../fury/serializer/ExternalizableSerializer.java | 3 +-
.../apache/fury/serializer/ForwardSerializer.java | 13 ++
.../org/apache/fury/serializer/JavaSerializer.java | 2 +-
.../apache/fury/serializer/JdkProxySerializer.java | 14 ++
.../apache/fury/serializer/LambdaSerializer.java | 11 +
.../apache/fury/serializer/ObjectSerializer.java | 4 +-
.../fury/serializer/ObjectStreamSerializer.java | 5 +-
.../fury/serializer/ReplaceResolveSerializer.java | 2 +-
.../org/apache/fury/serializer/URLSerializer.java | 2 +-
.../collection/AbstractCollectionSerializer.java | 29 +++
.../collection/AbstractMapSerializer.java | 24 +++
.../collection/ChildContainerSerializers.java | 19 +-
.../collection/CollectionSerializer.java | 16 --
.../collection/CollectionSerializers.java | 11 -
.../collection/GuavaCollectionSerializers.java | 54 +++--
.../test/java/org/apache/fury/FuryTestBase.java | 33 +++
.../fury/serializer/ArraySerializersTest.java | 79 +++++++
.../fury/serializer/BufferSerializersTest.java | 12 ++
.../CodegenCompatibleSerializerTest.java | 47 +++++
.../fury/serializer/CodegenSerializerTest.java | 31 +++
.../fury/serializer/CompatibleSerializerTest.java | 10 +
.../apache/fury/serializer/EnumSerializerTest.java | 13 ++
.../serializer/ExternalizableSerializerTest.java | 9 +-
.../fury/serializer/ForwardSerializerTest.java | 42 ++++
.../apache/fury/serializer/JavaSerializerTest.java | 9 +
.../fury/serializer/JdkProxySerializerTest.java | 27 +++
.../fury/serializer/LambdaSerializerTest.java | 20 ++
.../fury/serializer/LocaleSerializerTest.java | 11 +
.../fury/serializer/ObjectSerializerTest.java | 51 ++++-
.../serializer/ObjectStreamSerializerTest.java | 104 +++++++++
.../fury/serializer/OptionalSerializersTest.java | 15 ++
.../fury/serializer/PrimitiveSerializersTest.java | 22 ++
.../serializer/ReplaceResolveSerializerTest.java | 86 ++++++++
.../fury/serializer/StringSerializerTest.java | 13 ++
.../fury/serializer/TimeSerializersTest.java | 125 +++++++++++
.../apache/fury/serializer/URLSerializerTest.java | 11 +
.../collection/ChildContainerSerializersTest.java | 71 +++++++
.../collection/CollectionSerializersTest.java | 235 +++++++++++++++++++++
.../collection/GuavaCollectionSerializersTest.java | 61 ++++++
.../serializer/collection/MapSerializersTest.java | 140 ++++++++++++
.../collection/SynchronizedSerializersTest.java | 7 +
.../collection/UnmodifiableSerializersTest.java | 13 ++
43 files changed, 1460 insertions(+), 54 deletions(-)
diff --git
a/java/fury-core/src/main/java/org/apache/fury/serializer/BufferSerializers.java
b/java/fury-core/src/main/java/org/apache/fury/serializer/BufferSerializers.java
index c7ea6ee7..17ca6c36 100644
---
a/java/fury-core/src/main/java/org/apache/fury/serializer/BufferSerializers.java
+++
b/java/fury-core/src/main/java/org/apache/fury/serializer/BufferSerializers.java
@@ -44,6 +44,14 @@ public class BufferSerializers {
fury.writeBufferObject(buffer, new
BufferObject.ByteBufferBufferObject(value));
}
+ @Override
+ public ByteBuffer copy(ByteBuffer value) {
+ ByteBuffer dst = ByteBuffer.allocate(value.remaining());
+ dst.put(value.duplicate());
+ dst.rewind();
+ return dst;
+ }
+
@Override
public ByteBuffer read(MemoryBuffer buffer) {
MemoryBuffer newBuffer = fury.readBufferObject(buffer);
diff --git
a/java/fury-core/src/main/java/org/apache/fury/serializer/ExternalizableSerializer.java
b/java/fury-core/src/main/java/org/apache/fury/serializer/ExternalizableSerializer.java
index c16778c5..8753f74a 100644
---
a/java/fury-core/src/main/java/org/apache/fury/serializer/ExternalizableSerializer.java
+++
b/java/fury-core/src/main/java/org/apache/fury/serializer/ExternalizableSerializer.java
@@ -30,7 +30,8 @@ import org.apache.fury.memory.Platform;
import org.apache.fury.reflect.ReflectionUtils;
/** Serializer for class implements {@link Externalizable}. */
-public class ExternalizableSerializer<T extends Externalizable> extends
Serializer<T> {
+public class ExternalizableSerializer<T extends Externalizable>
+ extends AbstractObjectSerializer<T> {
private final MethodHandle constructor;
private final MemoryBufferObjectInput objectInput;
private final MemoryBufferObjectOutput objectOutput;
diff --git
a/java/fury-core/src/main/java/org/apache/fury/serializer/ForwardSerializer.java
b/java/fury-core/src/main/java/org/apache/fury/serializer/ForwardSerializer.java
index 6e65e28b..d9c1597b 100644
---
a/java/fury-core/src/main/java/org/apache/fury/serializer/ForwardSerializer.java
+++
b/java/fury-core/src/main/java/org/apache/fury/serializer/ForwardSerializer.java
@@ -96,6 +96,10 @@ public class ForwardSerializer {
byte[] bytes = buffer.getRemainingBytes();
return deserialize(serializer, bytes);
}
+
+ protected Object copy(T serializer, Object obj) {
+ throw new UnsupportedOperationException();
+ }
}
public static class DefaultFuryProxy extends SerializerProxy<LoaderBinding> {
@@ -174,6 +178,11 @@ public class ForwardSerializer {
protected Object deserialize(LoaderBinding serializer, MemoryBuffer
buffer) {
return serializer.get().deserialize(buffer);
}
+
+ @Override
+ protected Object copy(LoaderBinding serializer, Object obj) {
+ return serializer.get().copy(obj);
+ }
}
private final SerializerProxy proxy;
@@ -264,4 +273,8 @@ public class ForwardSerializer {
public <T> T deserialize(MemoryBuffer buffer) {
return (T) proxy.deserialize(serializerLocal.get(), buffer);
}
+
+ public <T> T copy(T obj) {
+ return (T) proxy.copy(serializerLocal.get(), obj);
+ }
}
diff --git
a/java/fury-core/src/main/java/org/apache/fury/serializer/JavaSerializer.java
b/java/fury-core/src/main/java/org/apache/fury/serializer/JavaSerializer.java
index 199a5eba..858ea86c 100644
---
a/java/fury-core/src/main/java/org/apache/fury/serializer/JavaSerializer.java
+++
b/java/fury-core/src/main/java/org/apache/fury/serializer/JavaSerializer.java
@@ -48,7 +48,7 @@ import org.apache.fury.resolver.ClassResolver;
* true, this serializer will be used.
*/
@SuppressWarnings({"rawtypes", "unchecked"})
-public class JavaSerializer extends Serializer {
+public class JavaSerializer extends AbstractObjectSerializer {
private static final Logger LOG =
LoggerFactory.getLogger(JavaSerializer.class);
private final MemoryBufferObjectInput objectInput;
private final MemoryBufferObjectOutput objectOutput;
diff --git
a/java/fury-core/src/main/java/org/apache/fury/serializer/JdkProxySerializer.java
b/java/fury-core/src/main/java/org/apache/fury/serializer/JdkProxySerializer.java
index 2e52b2a3..9ab89651 100644
---
a/java/fury-core/src/main/java/org/apache/fury/serializer/JdkProxySerializer.java
+++
b/java/fury-core/src/main/java/org/apache/fury/serializer/JdkProxySerializer.java
@@ -60,6 +60,20 @@ public class JdkProxySerializer extends Serializer {
fury.writeRef(buffer, Proxy.getInvocationHandler(value));
}
+ @Override
+ public Object copy(Object value) {
+ Class<?>[] interfaces = value.getClass().getInterfaces();
+ InvocationHandler invocationHandler = Proxy.getInvocationHandler(value);
+ Preconditions.checkNotNull(interfaces);
+ Preconditions.checkNotNull(invocationHandler);
+ Object proxy = Proxy.newProxyInstance(fury.getClassLoader(), interfaces,
STUB_HANDLER);
+ if (needToCopyRef) {
+ fury.reference(value, proxy);
+ }
+ Platform.putObject(proxy, PROXY_HANDLER_FIELD_OFFSET,
fury.copyObject(invocationHandler));
+ return proxy;
+ }
+
@Override
public Object read(MemoryBuffer buffer) {
final RefResolver resolver = fury.getRefResolver();
diff --git
a/java/fury-core/src/main/java/org/apache/fury/serializer/LambdaSerializer.java
b/java/fury-core/src/main/java/org/apache/fury/serializer/LambdaSerializer.java
index e8c82212..f6b54341 100644
---
a/java/fury-core/src/main/java/org/apache/fury/serializer/LambdaSerializer.java
+++
b/java/fury-core/src/main/java/org/apache/fury/serializer/LambdaSerializer.java
@@ -80,6 +80,17 @@ public class LambdaSerializer extends Serializer {
}
}
+ @Override
+ public Object copy(Object value) {
+ try {
+ Object replacement = writeReplaceMethod.invoke(value);
+ Object newReplacement = getDataSerializer().copy(replacement);
+ return READ_RESOLVE_METHOD.invoke(newReplacement);
+ } catch (Exception e) {
+ throw new RuntimeException("Can't copy lambda " + value, e);
+ }
+ }
+
@Override
public Object read(MemoryBuffer buffer) {
try {
diff --git
a/java/fury-core/src/main/java/org/apache/fury/serializer/ObjectSerializer.java
b/java/fury-core/src/main/java/org/apache/fury/serializer/ObjectSerializer.java
index 374b5be9..c6faf3e7 100644
---
a/java/fury-core/src/main/java/org/apache/fury/serializer/ObjectSerializer.java
+++
b/java/fury-core/src/main/java/org/apache/fury/serializer/ObjectSerializer.java
@@ -83,7 +83,9 @@ public final class ObjectSerializer<T> extends
AbstractObjectSerializer<T> {
// avoid recursive building serializers.
// Use `setSerializerIfAbsent` to avoid overwriting existing serializer
for class when used
// as data serializer.
- classResolver.setSerializerIfAbsent(cls, this);
+ if (resolveParent) {
+ classResolver.setSerializerIfAbsent(cls, this);
+ }
Collection<Descriptor> descriptors;
boolean shareMeta = fury.getConfig().isMetaShareEnabled();
if (shareMeta) {
diff --git
a/java/fury-core/src/main/java/org/apache/fury/serializer/ObjectStreamSerializer.java
b/java/fury-core/src/main/java/org/apache/fury/serializer/ObjectStreamSerializer.java
index 8ec1b59f..c8afee22 100644
---
a/java/fury-core/src/main/java/org/apache/fury/serializer/ObjectStreamSerializer.java
+++
b/java/fury-core/src/main/java/org/apache/fury/serializer/ObjectStreamSerializer.java
@@ -58,7 +58,6 @@ import org.apache.fury.memory.MemoryBuffer;
import org.apache.fury.memory.Platform;
import org.apache.fury.reflect.ReflectionUtils;
import org.apache.fury.resolver.ClassInfo;
-import org.apache.fury.resolver.ClassResolver;
import org.apache.fury.resolver.FieldResolver;
import org.apache.fury.resolver.FieldResolver.ClassField;
import org.apache.fury.util.ExceptionUtils;
@@ -78,11 +77,10 @@ import org.apache.fury.util.unsafe._JDKAccess;
* <p>`ObjectInputStream#setObjectInputFilter` will be ignored by this
serializer.
*/
@SuppressWarnings({"unchecked", "rawtypes"})
-public class ObjectStreamSerializer extends Serializer {
+public class ObjectStreamSerializer extends AbstractObjectSerializer {
private static final Logger LOG =
LoggerFactory.getLogger(ObjectStreamSerializer.class);
private final Constructor constructor;
- private final ClassResolver classResolver;
private final SlotsInfo[] slotsInfos;
public ObjectStreamSerializer(Fury fury, Class<?> type) {
@@ -109,7 +107,6 @@ public class ObjectStreamSerializer extends Serializer {
constructor =
(Constructor)
ReflectionUtils.getObjectFieldValue(ObjectStreamClass.lookup(type), "cons");
}
- this.classResolver = fury.getClassResolver();
this.constructor = constructor;
List<SlotsInfo> slotsInfoList = new ArrayList<>();
Class<?> end = type;
diff --git
a/java/fury-core/src/main/java/org/apache/fury/serializer/ReplaceResolveSerializer.java
b/java/fury-core/src/main/java/org/apache/fury/serializer/ReplaceResolveSerializer.java
index e8e10ac7..dfac24d8 100644
---
a/java/fury-core/src/main/java/org/apache/fury/serializer/ReplaceResolveSerializer.java
+++
b/java/fury-core/src/main/java/org/apache/fury/serializer/ReplaceResolveSerializer.java
@@ -44,7 +44,7 @@ import org.apache.fury.util.unsafe._JDKAccess;
* will skip classname writing if object returned by `writeReplace` is
different from current class.
*/
@SuppressWarnings({"unchecked", "rawtypes"})
-public class ReplaceResolveSerializer extends Serializer {
+public class ReplaceResolveSerializer extends AbstractObjectSerializer {
private static final Logger LOG =
LoggerFactory.getLogger(ReplaceResolveSerializer.class);
/**
diff --git
a/java/fury-core/src/main/java/org/apache/fury/serializer/URLSerializer.java
b/java/fury-core/src/main/java/org/apache/fury/serializer/URLSerializer.java
index df269558..4c935de0 100644
--- a/java/fury-core/src/main/java/org/apache/fury/serializer/URLSerializer.java
+++ b/java/fury-core/src/main/java/org/apache/fury/serializer/URLSerializer.java
@@ -27,7 +27,7 @@ import org.apache.fury.memory.Platform;
/** Serializer for {@link URL}. */
// TODO(chaokunyang) ensure security to avoid dnslog detection.
-public final class URLSerializer extends ImmutableSerializer<URL> {
+public final class URLSerializer extends AbstractObjectSerializer<URL> {
public URLSerializer(Fury fury, Class<URL> type) {
super(fury, type);
diff --git
a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/AbstractCollectionSerializer.java
b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/AbstractCollectionSerializer.java
index 8ade17b4..e6e97969 100644
---
a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/AbstractCollectionSerializer.java
+++
b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/AbstractCollectionSerializer.java
@@ -542,6 +542,35 @@ public abstract class AbstractCollectionSerializer<T>
extends Serializer<T> {
}
}
+ public void copyElements(Collection originCollection, Collection
newCollection) {
+ ClassResolver classResolver = fury.getClassResolver();
+ for (Object element : originCollection) {
+ if (element != null) {
+ ClassInfo classInfo =
+ classResolver.getClassInfo(element.getClass(),
elementClassInfoHolder);
+ if (!classInfo.getSerializer().isImmutable()) {
+ element = fury.copyObject(element, classInfo.getClassId());
+ }
+ }
+ newCollection.add(element);
+ }
+ }
+
+ public void copyElements(Collection originCollection, Object[] elements) {
+ int index = 0;
+ ClassResolver classResolver = fury.getClassResolver();
+ for (Object element : originCollection) {
+ if (element != null) {
+ ClassInfo classInfo =
+ classResolver.getClassInfo(element.getClass(),
elementClassInfoHolder);
+ if (!classInfo.getSerializer().isImmutable()) {
+ element = fury.copyObject(element, classInfo.getSerializer());
+ }
+ }
+ elements[index++] = element;
+ }
+ }
+
private RuntimeException buildException(Throwable e) {
return new IllegalArgumentException(
"Please provide public no arguments constructor for class " + type, e);
diff --git
a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/AbstractMapSerializer.java
b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/AbstractMapSerializer.java
index 620f1426..89049441 100644
---
a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/AbstractMapSerializer.java
+++
b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/AbstractMapSerializer.java
@@ -21,8 +21,10 @@ package org.apache.fury.serializer.collection;
import static org.apache.fury.type.TypeUtils.MAP_TYPE;
+import com.google.common.collect.ImmutableMap.Builder;
import java.lang.invoke.MethodHandle;
import java.util.Map;
+import java.util.Map.Entry;
import org.apache.fury.Fury;
import org.apache.fury.collection.IdentityMap;
import org.apache.fury.collection.Tuple2;
@@ -439,6 +441,28 @@ public abstract class AbstractMapSerializer<T> extends
Serializer<T> {
}
}
+ protected <K, V> void copyEntry(Map<K, V> originMap, Builder<K, V> builder) {
+ ClassResolver classResolver = fury.getClassResolver();
+ for (Entry<K, V> entry : originMap.entrySet()) {
+ K key = entry.getKey();
+ if (key != null) {
+ ClassInfo classInfo = classResolver.getClassInfo(key.getClass(),
keyClassInfoWriteCache);
+ if (!classInfo.getSerializer().isImmutable()) {
+ key = fury.copyObject(key, classInfo.getClassId());
+ }
+ }
+ V value = entry.getValue();
+ if (value != null) {
+ ClassInfo classInfo =
+ classResolver.getClassInfo(value.getClass(),
valueClassInfoWriteCache);
+ if (!classInfo.getSerializer().isImmutable()) {
+ value = fury.copyObject(value, classInfo.getClassId());
+ }
+ }
+ builder.put(key, value);
+ }
+ }
+
@SuppressWarnings("unchecked")
protected final void readElements(MemoryBuffer buffer, int size, Map map) {
Serializer keySerializer = this.keySerializer;
diff --git
a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/ChildContainerSerializers.java
b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/ChildContainerSerializers.java
index fdb8c18f..57e76bb2 100644
---
a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/ChildContainerSerializers.java
+++
b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/ChildContainerSerializers.java
@@ -127,7 +127,7 @@ public class ChildContainerSerializers {
ArrayList.class, LinkedList.class, ArrayDeque.class, Vector.class,
HashSet.class
// PriorityQueue/TreeSet/ConcurrentSkipListSet need comparator as
constructor argument
);
-
+ protected Serializer<T> objectSerializer;
protected final Serializer[] slotsSerializers;
public ChildCollectionSerializer(Fury fury, Class<T> cls) {
@@ -149,6 +149,14 @@ public class ChildContainerSerializers {
readAndSetFields(buffer, collection, slotsSerializers);
return collection;
}
+
+ @Override
+ public T copy(T originCollection) {
+ if (objectSerializer == null) {
+ objectSerializer = new ObjectSerializer<>(fury, type, false);
+ }
+ return fury.copyObject(originCollection, objectSerializer);
+ }
}
public static final class ChildArrayListSerializer<T extends ArrayList>
@@ -177,6 +185,7 @@ public class ChildContainerSerializers {
HashMap.class, LinkedHashMap.class, ConcurrentHashMap.class
// TreeMap/ConcurrentSkipListMap need comparator as constructor
argument
);
+ private Serializer<T> objectSerializer;
private final Serializer[] slotsSerializers;
public ChildMapSerializer(Fury fury, Class<T> cls) {
@@ -199,6 +208,14 @@ public class ChildContainerSerializers {
readAndSetFields(buffer, map, slotsSerializers);
return map;
}
+
+ @Override
+ public T copy(T originMap) {
+ if (objectSerializer == null) {
+ objectSerializer = new ObjectSerializer<>(fury, type, false);
+ }
+ return fury.copyObject(originMap, objectSerializer);
+ }
}
private static <T> Serializer[] buildSlotsSerializers(
diff --git
a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/CollectionSerializer.java
b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/CollectionSerializer.java
index 4a507b69..85cc8569 100644
---
a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/CollectionSerializer.java
+++
b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/CollectionSerializer.java
@@ -22,8 +22,6 @@ package org.apache.fury.serializer.collection;
import java.util.Collection;
import org.apache.fury.Fury;
import org.apache.fury.memory.MemoryBuffer;
-import org.apache.fury.resolver.ClassInfo;
-import org.apache.fury.resolver.ClassResolver;
/** Base serializer for all java collections. */
@SuppressWarnings({"unchecked", "rawtypes"})
@@ -65,20 +63,6 @@ public class CollectionSerializer<T extends Collection>
extends AbstractCollecti
return (T) newCollection;
}
- public void copyElements(T originCollection, Collection newCollection) {
- ClassResolver classResolver = fury.getClassResolver();
- for (Object element : originCollection) {
- if (element != null) {
- ClassInfo classInfo =
- classResolver.getClassInfo(element.getClass(),
elementClassInfoHolder);
- if (!classInfo.getSerializer().isImmutable()) {
- element = fury.copyObject(element, classInfo.getClassId());
- }
- }
- newCollection.add(element);
- }
- }
-
@Override
public T read(MemoryBuffer buffer) {
Collection collection = newCollection(buffer);
diff --git
a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/CollectionSerializers.java
b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/CollectionSerializers.java
index 96a8b6b4..990711d6 100644
---
a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/CollectionSerializers.java
+++
b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/CollectionSerializers.java
@@ -107,23 +107,12 @@ public class CollectionSerializers {
Object[] elements = new Object[originCollection.size()];
List<?> newCollection = Arrays.asList(elements);
if (needToCopyRef) {
- List<?> copyObject = (List<?>) fury.getCopyObject(originCollection);
- if (copyObject != null) {
- return copyObject;
- }
fury.reference(originCollection, newCollection);
}
copyElements(originCollection, elements);
return newCollection;
}
- private void copyElements(List<?> originCollection, Object[] elements) {
- int size = originCollection.size();
- for (int i = 0; i < size; i++) {
- elements[i] = fury.copyObject(originCollection.get(i));
- }
- }
-
@Override
public short getXtypeId() {
return (short) -Type.LIST.getId();
diff --git
a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/GuavaCollectionSerializers.java
b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/GuavaCollectionSerializers.java
index 59a9e832..fe94b435 100644
---
a/java/fury-core/src/main/java/org/apache/fury/serializer/collection/GuavaCollectionSerializers.java
+++
b/java/fury-core/src/main/java/org/apache/fury/serializer/collection/GuavaCollectionSerializers.java
@@ -22,6 +22,7 @@ package org.apache.fury.serializer.collection;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.ImmutableSortedSet;
@@ -91,6 +92,13 @@ public class GuavaCollectionSerializers {
public T xnewInstance(Collection collection) {
return (T) ImmutableList.copyOf(collection);
}
+
+ @Override
+ public T copy(T originCollection) {
+ Object[] elements = new Object[originCollection.size()];
+ copyElements(originCollection, elements);
+ return (T) ImmutableList.copyOf(elements);
+ }
}
private static final String pkg = "com.google.common.collect";
@@ -133,6 +141,13 @@ public class GuavaCollectionSerializers {
return (T) function.apply(elements);
}
+ @Override
+ public T copy(T originCollection) {
+ Object[] elements = new Object[originCollection.size()];
+ copyElements(originCollection, elements);
+ return (T) function.apply(elements);
+ }
+
@Override
public short getXtypeId() {
return (short) -Type.LIST.getId();
@@ -173,6 +188,13 @@ public class GuavaCollectionSerializers {
protected T xnewInstance(Collection collection) {
return (T) ImmutableSet.copyOf(collection);
}
+
+ @Override
+ public T copy(T originCollection) {
+ Object[] elements = new Object[originCollection.size()];
+ copyElements(originCollection, elements);
+ return (T) ImmutableSet.copyOf(elements);
+ }
}
public static final class ImmutableSortedSetSerializer<T extends
ImmutableSortedSet>
@@ -203,6 +225,14 @@ public class GuavaCollectionSerializers {
Object[] elements = data.elements;
return (T) new
ImmutableSortedSet.Builder<>(data.comparator).add(elements).build();
}
+
+ @Override
+ public T copy(T originCollection) {
+ Comparator comparator = fury.copyObject(originCollection.comparator());
+ Object[] elements = new Object[originCollection.size()];
+ copyElements(originCollection, elements);
+ return (T) new
ImmutableSortedSet.Builder<>(comparator).add(elements).build();
+ }
}
abstract static class GuavaMapSerializer<T extends Map> extends
MapSerializer<T> {
@@ -222,13 +252,10 @@ public class GuavaCollectionSerializers {
}
@Override
- public Map newMap(Map map) {
- return new MapContainer(map.size());
- }
-
- @Override
- public T onMapCopy(Map map) {
- return onMapRead(map);
+ public T copy(T originMap) {
+ Builder builder = makeBuilder(originMap.size());
+ copyEntry(originMap, builder);
+ return (T) builder.build();
}
@Override
@@ -352,14 +379,11 @@ public class GuavaCollectionSerializers {
}
@Override
- public Map newMap(Map map) {
- Comparator comparator = fury.copyObject(((ImmutableSortedMap)
map).comparator());
- return new SortedMapContainer<>(comparator, map.size());
- }
-
- @Override
- public T onMapCopy(Map map) {
- return onMapRead(map);
+ public T copy(T originMap) {
+ Comparator comparator = fury.copyObject(originMap.comparator());
+ ImmutableSortedMap.Builder builder = new
ImmutableSortedMap.Builder(comparator);
+ copyEntry(originMap, builder);
+ return (T) builder.build();
}
@Override
diff --git a/java/fury-core/src/test/java/org/apache/fury/FuryTestBase.java
b/java/fury-core/src/test/java/org/apache/fury/FuryTestBase.java
index 3f4cb6c1..aa1a5f2c 100644
--- a/java/fury-core/src/test/java/org/apache/fury/FuryTestBase.java
+++ b/java/fury-core/src/test/java/org/apache/fury/FuryTestBase.java
@@ -59,6 +59,28 @@ public abstract class FuryTestBase {
return
Fury.builder().withLanguage(Language.JAVA).requireClassRegistration(false);
}
+ @DataProvider
+ public static Object[] furyCopyConfig() {
+ return new Object[][] {
+ {
+ builder()
+ .withRefCopy(true)
+ .withLanguage(Language.JAVA)
+ .withJdkClassSerializableCheck(false)
+ .withCodegen(false)
+ .build()
+ },
+ {
+ builder()
+ .withRefCopy(true)
+ .withLanguage(Language.JAVA)
+ .withJdkClassSerializableCheck(false)
+ .withCodegen(true)
+ .build()
+ },
+ };
+ }
+
@DataProvider
public static Object[][] referenceTrackingConfig() {
return new Object[][] {{false}, {true}};
@@ -264,6 +286,17 @@ public abstract class FuryTestBase {
return newObj;
}
+ public static void copyCheck(Fury fury, Object obj) {
+ Object copy = fury.copy(obj);
+ Assert.assertEquals(obj, copy);
+ Assert.assertNotSame(obj, copy);
+ }
+
+ public static void copyCheckWithoutSame(Fury fury, Object obj) {
+ Object copy = fury.copy(obj);
+ Assert.assertEquals(obj, copy);
+ }
+
public static void roundCheck(Fury fury1, Fury fury2, Object o) {
roundCheck(fury1, fury2, o, Function.identity());
}
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/ArraySerializersTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/ArraySerializersTest.java
index 918259c7..b4db601d 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/ArraySerializersTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/ArraySerializersTest.java
@@ -74,6 +74,29 @@ public class ArraySerializersTest extends FuryTestBase {
serDeCheck(fury1, fury2, new Object[] {"str", 1});
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testObjectArrayCopy(Fury fury) {
+ copyCheck(fury, new Object[] {false, true});
+ copyCheck(fury, new Object[] {(byte) 1, (byte) 1});
+ copyCheck(fury, new Object[] {(short) 1, (short) 1});
+ copyCheck(fury, new Object[] {(char) 1, (char) 1});
+ copyCheck(fury, new Object[] {1, 1});
+ copyCheck(fury, new Object[] {(float) 1.0, (float) 1.1});
+ copyCheck(fury, new Object[] {1.0, 1.1});
+ copyCheck(fury, new Object[] {1L, 2L});
+ copyCheck(fury, new Boolean[] {false, true});
+ copyCheck(fury, new Byte[] {(byte) 1, (byte) 1});
+ copyCheck(fury, new Short[] {(short) 1, (short) 1});
+ copyCheck(fury, new Character[] {(char) 1, (char) 1});
+ copyCheck(fury, new Integer[] {1, 1});
+ copyCheck(fury, new Float[] {(float) 1.0, (float) 1.1});
+ copyCheck(fury, new Double[] {1.0, 1.1});
+ copyCheck(fury, new Long[] {1L, 2L});
+ copyCheck(fury, new Object[] {false, true, (byte) 1, (byte) 1, (float)
1.0, (float) 1.1});
+ copyCheck(fury, new String[] {"str", "str"});
+ copyCheck(fury, new Object[] {"str", 1});
+ }
+
@Test(dataProvider = "crossLanguageReferenceTrackingConfig")
public void testMultiArraySerialization(boolean referenceTracking, Language
language) {
FuryBuilder builder =
@@ -94,6 +117,18 @@ public class ArraySerializersTest extends FuryTestBase {
serDeCheck(fury1, fury2, new Integer[][] {{1, 2}, {1, 2}});
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testMultiArraySerialization(Fury fury) {
+ copyCheck(fury, new Object[][] {{false, true}, {false, true}});
+ copyCheck(
+ fury,
+ new Object[][] {
+ {false, true, (byte) 1, (byte) 1, (float) 1.0, (float) 1.1},
+ {false, true, (byte) 1, (byte) 1, (float) 1.0, (float) 1.1}
+ });
+ copyCheck(fury, new Integer[][] {{1, 2}, {1, 2}});
+ }
+
@Test(dataProvider = "crossLanguageReferenceTrackingConfig")
public void testPrimitiveArray(boolean referenceTracking, Language language)
{
Supplier<FuryBuilder> builder =
@@ -107,6 +142,18 @@ public class ArraySerializersTest extends FuryTestBase {
testPrimitiveArray(fury1, fury2);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testPrimitiveArray(Fury fury) {
+ copyCheck(fury, new boolean[] {false, true});
+ copyCheck(fury, new byte[] {1, 1});
+ copyCheck(fury, new short[] {1, 1});
+ copyCheck(fury, new int[] {1, 1});
+ copyCheck(fury, new long[] {1, 1});
+ copyCheck(fury, new float[] {1.f, 1.f});
+ copyCheck(fury, new double[] {1.0, 1.0});
+ copyCheck(fury, new char[] {'a', ' '});
+ }
+
public static void testPrimitiveArray(Fury fury1, Fury fury2) {
assertTrue(
Arrays.equals(
@@ -160,6 +207,14 @@ public class ArraySerializersTest extends FuryTestBase {
}
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testArrayStructZeroCopy(Fury fury) {
+ for (int i = 0; i < 4; i++) {
+ ArraysData arraysData = new ArraysData(7 * i);
+ copyCheck(fury, arraysData);
+ }
+ }
+
@EqualsAndHashCode
static class A {
final int f1;
@@ -221,4 +276,28 @@ public class ArraySerializersTest extends FuryTestBase {
deserialized.array[1] = "World";
Assert.assertEquals(deserialized.array, new String[] {"Hello", "World"});
}
+
+ @SuppressWarnings("unchecked")
+ @Test(dataProvider = "furyCopyConfig")
+ public void testArrayPolyMorphic(Fury fury) {
+ Object[] arr = new String[] {"a", "b"};
+ copyCheck(fury, arr);
+
+ A[] arr1 = new B[] {new B(1, "a"), new B(2, "b")};
+ copyCheck(fury, arr1);
+
+ Struct struct1 = new Struct(arr1);
+ copyCheck(fury, struct1);
+ A[] arr2 = new A[] {new A(1), new B(2, "b")};
+ Struct struct2 = new Struct(arr2);
+ copyCheck(fury, struct2);
+
+ final GenericArrayWrapper<String> wrapper = new
GenericArrayWrapper<>(String.class, 2);
+ wrapper.array[0] = "Hello";
+ wrapper.array[1] = "World";
+ GenericArrayWrapper<String> copy = fury.copy(wrapper);
+ Assert.assertEquals(copy.array, wrapper.array);
+ Assert.assertNotSame(copy.array, wrapper.array);
+ Assert.assertNotSame(copy, wrapper);
+ }
}
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/BufferSerializersTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/BufferSerializersTest.java
index b4f9301c..d499322a 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/BufferSerializersTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/BufferSerializersTest.java
@@ -39,4 +39,16 @@ public class BufferSerializersTest extends FuryTestBase {
ByteBufferUtil.rewind(buffer2);
serDeCheck(fury, buffer2);
}
+
+ @Test(dataProvider = "furyCopyConfig")
+ public void testByteBuffer(Fury fury) {
+ ByteBuffer buffer1 = ByteBuffer.allocate(32);
+ buffer1.putLong(1000L);
+ ByteBufferUtil.rewind(buffer1);
+ copyCheck(fury, buffer1);
+ ByteBuffer buffer2 = ByteBuffer.allocateDirect(32);
+ buffer2.putDouble(1.0 / 3);
+ ByteBufferUtil.rewind(buffer2);
+ copyCheck(fury, buffer2);
+ }
}
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/CodegenCompatibleSerializerTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/CodegenCompatibleSerializerTest.java
index f29c211a..e9cbf399 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/CodegenCompatibleSerializerTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/CodegenCompatibleSerializerTest.java
@@ -75,6 +75,20 @@ public class CodegenCompatibleSerializerTest extends
FuryTestBase {
serDeCheck(fury, BeanA.createBeanA(2));
}
+ @Test(dataProvider = "config")
+ public void testCopy(boolean referenceTracking, boolean scopedMetaShare,
boolean enableCodegen) {
+ Fury fury =
+ furyBuilder()
+ .withRefCopy(referenceTracking)
+ .withCodegen(enableCodegen)
+ .withScopedMetaShare(scopedMetaShare)
+ .withCompatibleMode(CompatibleMode.COMPATIBLE)
+ .build();
+ copyCheck(fury, Foo.create());
+ copyCheck(fury, BeanB.createBeanB(2));
+ copyCheck(fury, BeanA.createBeanA(2));
+ }
+
@Test(dataProvider = "config")
public void testWriteCompatibleBasic(
boolean referenceTracking, boolean scopedMetaShare, boolean
enableCodegen) throws Exception {
@@ -124,6 +138,39 @@ public class CodegenCompatibleSerializerTest extends
FuryTestBase {
}
}
+ @Test(dataProvider = "config")
+ public void testWriteCompatibleBasicCopy(
+ boolean referenceTracking, boolean scopedMetaShare, boolean
enableCodegen) throws Exception {
+ Supplier<FuryBuilder> builder =
+ () ->
+ Fury.builder()
+ .withLanguage(Language.JAVA)
+ .withRefCopy(referenceTracking)
+ .withCodegen(enableCodegen)
+ .withCompatibleMode(CompatibleMode.COMPATIBLE)
+ .withScopedMetaShare(scopedMetaShare)
+ .requireClassRegistration(false);
+ Fury fury = builder.get().build();
+ Object foo = Foo.create();
+ for (Class<?> fooClass :
+ new Class<?>[] {
+ Foo.createCompatibleClass1(), Foo.createCompatibleClass2(),
Foo.createCompatibleClass3(),
+ }) {
+ Object newFoo = fooClass.newInstance();
+ ReflectionUtils.unsafeCopy(foo, newFoo);
+ Fury newFury =
builder.get().withClassLoader(fooClass.getClassLoader()).build();
+ {
+ Object copy = fury.copy(newFoo);
+ Assert.assertEquals(copy.getClass().getName(), Foo.class.getName());
+ Assert.assertTrue(ReflectionUtils.objectCommonFieldsEquals(copy,
newFoo));
+ }
+ {
+ Object o3 = newFury.copy(foo);
+ Assert.assertTrue(ReflectionUtils.objectFieldsEquals(o3, foo));
+ }
+ }
+ }
+
@Test(dataProvider = "config")
public void testWriteCompatibleCollectionBasic(
boolean referenceTracking, boolean scopedMetaShare, boolean
enableCodegen) throws Exception {
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/CodegenSerializerTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/CodegenSerializerTest.java
index 594a9855..862cb434 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/CodegenSerializerTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/CodegenSerializerTest.java
@@ -20,6 +20,7 @@
package org.apache.fury.serializer;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotSame;
import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue;
@@ -64,6 +65,15 @@ public class CodegenSerializerTest extends FuryTestBase {
serDe(fury, b);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testSimpleBean(Fury fury) {
+ B b = new B();
+ b.f1 = "str1";
+ b.f2 = 1;
+ b.f3 = "str3";
+ copyCheck(fury, b);
+ }
+
@Test
public void testSupport() {
assertTrue(CodegenSerializer.supportCodegenForJavaSerialization(Cyclic.class));
@@ -93,6 +103,11 @@ public class CodegenSerializerTest extends FuryTestBase {
assertEquals(cyclic1, cyclic);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testCopyCircularReference(Fury fury) {
+ copyCheck(fury, Cyclic.create(true));
+ }
+
private static final class Circular1 {
public int f1;
public Circular1 circular1;
@@ -125,6 +140,22 @@ public class CodegenSerializerTest extends FuryTestBase {
serDe(fury, circular2);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testComplexCircular(Fury fury) {
+ Circular1 circular1 = new Circular1();
+ Circular2 circular2 = new Circular2();
+ circular1.circular1 = circular1;
+ circular1.circular2 = circular2;
+ circular2.circular1 = circular1;
+ circular2.circular2 = circular2;
+ Circular1 copy1 = fury.copy(circular1);
+ Circular2 copy2 = fury.copy(circular2);
+ assertSame(copy1.circular1, copy1);
+ assertNotSame(copy1.circular2, copy2);
+ assertNotSame(copy2.circular1, copy1);
+ assertSame(copy2.circular2, copy2);
+ }
+
@Data
public static class NonFinalPublic {}
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/CompatibleSerializerTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/CompatibleSerializerTest.java
index 3b6222d2..a2467022 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/CompatibleSerializerTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/CompatibleSerializerTest.java
@@ -61,6 +61,16 @@ public class CompatibleSerializerTest extends FuryTestBase {
serDeCheck(fury, BeanA.createBeanA(2));
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testCopy(Fury fury) {
+ fury.registerSerializer(Foo.class, new CompatibleSerializer<>(fury,
Foo.class));
+ fury.registerSerializer(BeanA.class, new CompatibleSerializer<>(fury,
BeanA.class));
+ fury.registerSerializer(BeanB.class, new CompatibleSerializer<>(fury,
BeanB.class));
+ copyCheck(fury, Foo.create());
+ copyCheck(fury, BeanB.createBeanB(2));
+ copyCheck(fury, BeanA.createBeanA(2));
+ }
+
@Test(dataProvider = "referenceTrackingConfig")
public void testWriteCompatibleBasic(boolean referenceTrackingConfig) throws
Exception {
Fury fury =
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/EnumSerializerTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/EnumSerializerTest.java
index ae03bb4f..8cdbc061 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/EnumSerializerTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/EnumSerializerTest.java
@@ -69,6 +69,14 @@ public class EnumSerializerTest extends FuryTestBase {
assertEquals(EnumSubClass.B, serDe(fury1, fury2, EnumSubClass.B));
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testEnumSerializer(Fury fury) {
+ copyCheckWithoutSame(fury, EnumFoo.A);
+ copyCheckWithoutSame(fury, EnumFoo.B);
+ copyCheckWithoutSame(fury, EnumSubClass.A);
+ copyCheckWithoutSame(fury, EnumSubClass.B);
+ }
+
@Test
public void testEnumSerializationUnexistentEnumValueAsNull() {
String enumCode2 = "enum TestEnum2 {" + " A;" + "}";
@@ -107,6 +115,11 @@ public class EnumSerializerTest extends FuryTestBase {
builder().withCodegen(enableCodegen).build(), new
EnumSubclassFieldTest(EnumSubClass.B));
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testEnumSubclassField(Fury fury) {
+ copyCheck(fury, new EnumSubclassFieldTest(EnumSubClass.B));
+ }
+
@Test(dataProvider = "scopedMetaShare")
public void testEnumSubclassFieldCompatible(boolean scopedMetaShare) {
serDeCheck(
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/ExternalizableSerializerTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/ExternalizableSerializerTest.java
index a3c1ba59..d3e25d57 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/ExternalizableSerializerTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/ExternalizableSerializerTest.java
@@ -23,11 +23,12 @@ import static org.testng.Assert.assertEquals;
import java.io.Externalizable;
import org.apache.fury.Fury;
+import org.apache.fury.FuryTestBase;
import org.apache.fury.config.Language;
import org.apache.fury.serializer.test.Factory;
import org.testng.annotations.Test;
-public class ExternalizableSerializerTest {
+public class ExternalizableSerializerTest extends FuryTestBase {
@Test
public void testInaccessibleExternalizable() {
@@ -41,4 +42,10 @@ public class ExternalizableSerializerTest {
.build();
assertEquals(e, fury.deserialize(fury.serialize(e)));
}
+
+ @Test(dataProvider = "furyCopyConfig")
+ public void testInaccessibleExternalizable(Fury fury) {
+ Externalizable e = Factory.newInstance(1, 1, "bytes".getBytes());
+ copyCheck(fury, e);
+ }
}
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/ForwardSerializerTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/ForwardSerializerTest.java
index 07768e5a..2e695a22 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/ForwardSerializerTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/ForwardSerializerTest.java
@@ -84,6 +84,11 @@ public class ForwardSerializerTest {
Input input = new Input(bytes);
return serializer.readClassAndObject(input);
}
+
+ @Override
+ protected Object copy(Kryo serializer, Object obj) {
+ return serializer.copy(obj);
+ }
});
default:
throw new UnsupportedOperationException("Unsupported serializer type "
+ serializerType);
@@ -99,6 +104,15 @@ public class ForwardSerializerTest {
assertEquals(fury.deserialize(fury.serialize(beanA)), beanA);
}
+ @Test
+ public void testCopy() {
+ BeanA beanA = BeanA.createBeanA(3);
+ ForwardSerializer kryo = createSerializer("Kryo");
+ assertEquals(kryo.copy(beanA), beanA);
+ ForwardSerializer fury = createSerializer("Fury");
+ assertEquals(fury.copy(beanA), beanA);
+ }
+
private volatile boolean hasException;
@Test
@@ -129,6 +143,34 @@ public class ForwardSerializerTest {
}
}
+ @Test
+ public void testConcurrentCopy() throws InterruptedException {
+ BeanA beanA = BeanA.createBeanA(3);
+ for (String type : new String[] {"Kryo", "Fury"}) {
+ ForwardSerializer serializer = createSerializer(type);
+ serializer.register(BeanA.class);
+ assertEquals(serializer.copy(beanA), beanA);
+ ExecutorService executorService = Executors.newFixedThreadPool(12);
+ for (int i = 0; i < 1000; i++) {
+ executorService.execute(
+ () -> {
+ for (int j = 0; j < 10; j++) {
+ try {
+ assertEquals(serializer.copy(beanA), beanA);
+ } catch (Exception e) {
+ hasException = true;
+ e.printStackTrace();
+ throw e;
+ }
+ }
+ });
+ }
+ executorService.shutdown();
+ assertTrue(executorService.awaitTermination(30, TimeUnit.SECONDS));
+ assertFalse(hasException);
+ }
+ }
+
@Test
public void testClassLoader() throws Exception {
ForwardSerializer serializer = createSerializer("Fury");
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/JavaSerializerTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/JavaSerializerTest.java
index 608526a0..e1adc9a0 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/JavaSerializerTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/JavaSerializerTest.java
@@ -24,6 +24,8 @@ import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamConstants;
import java.io.Serializable;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.nio.ByteBuffer;
import lombok.Data;
import org.apache.fury.Fury;
@@ -77,4 +79,11 @@ public class JavaSerializerTest extends FuryTestBase {
bytes = fury.serialize(1.1);
Assert.assertFalse(JavaSerializer.serializedByJDK(bytes));
}
+
+ @Test(dataProvider = "furyCopyConfig")
+ public void testJdkSerializationCopy(Fury fury) throws MalformedURLException
{
+ URL url = new URL("http://localhost:80");
+ fury.registerSerializer(URL.class, JavaSerializer.class);
+ copyCheck(fury, url);
+ }
}
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/JdkProxySerializerTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/JdkProxySerializerTest.java
index 00cc440a..0f892fb1 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/JdkProxySerializerTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/JdkProxySerializerTest.java
@@ -20,6 +20,7 @@
package org.apache.fury.serializer;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotSame;
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
@@ -58,6 +59,17 @@ public class JdkProxySerializerTest extends FuryTestBase {
assertEquals(deserializedFunction.apply(null), 1);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testJdkProxy(Fury fury) {
+ Function function =
+ (Function)
+ Proxy.newProxyInstance(
+ fury.getClassLoader(), new Class[] {Function.class}, new
TestInvocationHandler());
+ Function copy = fury.copy(function);
+ assertNotSame(copy, function);
+ assertEquals(copy.apply(null), 1);
+ }
+
private static class RefTestInvocationHandler implements InvocationHandler,
Serializable {
private Function proxy;
@@ -102,4 +114,19 @@ public class JdkProxySerializerTest extends FuryTestBase {
(RefTestInvocationHandler)
Proxy.getInvocationHandler(deserializedFunction);
assertEquals(deserializedHandler.getProxy(), deserializedFunction);
}
+
+ @Test(dataProvider = "furyCopyConfig")
+ public void testJdkProxyRef(Fury fury) {
+ RefTestInvocationHandler hdlr = new RefTestInvocationHandler();
+ Function function =
+ (Function)
+ Proxy.newProxyInstance(fury.getClassLoader(), new Class[]
{Function.class}, hdlr);
+ hdlr.setProxy(function);
+ assertEquals(hdlr.getProxy(), function);
+
+ Function copy = fury.copy(function);
+ RefTestInvocationHandler copyHandler =
+ (RefTestInvocationHandler) Proxy.getInvocationHandler(copy);
+ assertEquals(copyHandler.getProxy(), copy);
+ }
}
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/LambdaSerializerTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/LambdaSerializerTest.java
index a65a3b37..c159c7dd 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/LambdaSerializerTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/LambdaSerializerTest.java
@@ -57,6 +57,26 @@ public class LambdaSerializerTest extends FuryTestBase {
fury.getClassResolver().getSerializerClass(Class.class),
Serializers.ClassSerializer.class);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testLambdaCopy(Fury fury) {
+ {
+ BiFunction<Fury, Object, byte[]> function =
+ (Serializable & BiFunction<Fury, Object, byte[]>) Fury::serialize;
+ fury.copy(function);
+ }
+ {
+ Function<Integer, Integer> function =
+ (Serializable & Function<Integer, Integer>) (x) -> x + x;
+ Function<Integer, Integer> newFunc = fury.copy(function);
+ assertEquals(newFunc.apply(10), Integer.valueOf(20));
+ List<Function<Integer, Integer>> list =
fury.copy(Arrays.asList(function, function));
+ assertSame(list.get(0), list.get(1));
+ assertEquals(list.get(0).apply(20), Integer.valueOf(40));
+ }
+ assertSame(
+ fury.getClassResolver().getSerializerClass(Class.class),
Serializers.ClassSerializer.class);
+ }
+
@Test
public void testLambdaUnserializableMsg() {
Fury fury = Fury.builder().requireClassRegistration(false).build();
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/LocaleSerializerTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/LocaleSerializerTest.java
index 03347aaf..dfa0f504 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/LocaleSerializerTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/LocaleSerializerTest.java
@@ -38,4 +38,15 @@ public class LocaleSerializerTest extends FuryTestBase {
serDeCheckSerializerAndEqual(fury, Locale.TAIWAN, "LocaleSerializer");
serDeCheckSerializerAndEqual(fury, Locale.getDefault(),
"LocaleSerializer");
}
+
+ @Test(dataProvider = "furyCopyConfig")
+ public void testWrite(Fury fury) {
+ copyCheckWithoutSame(fury, Locale.US);
+ copyCheckWithoutSame(fury, Locale.CHINESE);
+ copyCheckWithoutSame(fury, Locale.ENGLISH);
+ copyCheckWithoutSame(fury, Locale.TRADITIONAL_CHINESE);
+ copyCheckWithoutSame(fury, Locale.CHINA);
+ copyCheckWithoutSame(fury, Locale.TAIWAN);
+ copyCheckWithoutSame(fury, Locale.getDefault());
+ }
}
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/ObjectSerializerTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/ObjectSerializerTest.java
index b47c1afa..0512fc48 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/ObjectSerializerTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/ObjectSerializerTest.java
@@ -20,18 +20,21 @@
package org.apache.fury.serializer;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotSame;
import lombok.Data;
import org.apache.fury.Fury;
+import org.apache.fury.FuryTestBase;
import org.apache.fury.config.Language;
import org.apache.fury.memory.MemoryBuffer;
import org.apache.fury.memory.MemoryUtils;
import org.apache.fury.test.bean.Cyclic;
import org.apache.fury.util.Preconditions;
+import org.testng.Assert;
import org.testng.annotations.Test;
@SuppressWarnings("unchecked")
-public class ObjectSerializerTest {
+public class ObjectSerializerTest extends FuryTestBase {
@Test
public void testLocalClass() {
@@ -55,6 +58,21 @@ public class ObjectSerializerTest {
assertEquals(foo.foo("str"), ((Foo) obj).foo("str"));
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testLocalClass(Fury fury) {
+ String str = "str";
+ class Foo {
+ public String foo(String s) {
+ return str + s;
+ }
+ }
+ ObjectSerializer serializer = new ObjectSerializer(fury, Foo.class);
+ Foo foo = new Foo();
+ Object obj = serializer.copy(foo);
+ assertEquals(foo.foo("str"), ((Foo) obj).foo("str"));
+ Assert.assertNotSame(foo, obj);
+ }
+
@Test
public void testAnonymousClass() {
String str = "str";
@@ -83,6 +101,27 @@ public class ObjectSerializerTest {
assertEquals(foo.foo("str"), ((Foo) obj).foo("str"));
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testAnonymousClass(Fury fury) {
+ String str = "str";
+ class Foo {
+ public String foo(String s) {
+ return str + s;
+ }
+ }
+ Foo foo =
+ new Foo() {
+ @Override
+ public String foo(String s) {
+ return "Anonymous " + s;
+ }
+ };
+ ObjectSerializer serializer = new ObjectSerializer(fury, foo.getClass());
+ Object obj = serializer.copy(foo);
+ assertEquals(foo.foo("str"), ((Foo) obj).foo("str"));
+ assertNotSame(foo, obj);
+ }
+
@Test
public void testSerializeCircularReference() {
Cyclic cyclic = Cyclic.create(true);
@@ -105,6 +144,15 @@ public class ObjectSerializerTest {
assertEquals(cyclic1, cyclic);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testCopyCircularReference(Fury fury) {
+ Cyclic cyclic = Cyclic.create(true);
+ ObjectSerializer<Cyclic> serializer = new ObjectSerializer<>(fury,
Cyclic.class);
+ Cyclic cyclic1 = serializer.copy(cyclic);
+ assertEquals(cyclic1, cyclic);
+ assertNotSame(cyclic1, cyclic);
+ }
+
@Data
public static class A {
Integer f1;
@@ -129,5 +177,6 @@ public class ObjectSerializerTest {
A a = new A();
serializer.write(buffer, a);
assertEquals(a, serializer.read(buffer));
+ assertEquals(a, serializer.copy(a));
}
}
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/ObjectStreamSerializerTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/ObjectStreamSerializerTest.java
index 4ab26324..91e07de2 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/ObjectStreamSerializerTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/ObjectStreamSerializerTest.java
@@ -90,6 +90,14 @@ public class ObjectStreamSerializerTest extends FuryTestBase
{
assertEquals(buf.toString(), "abc");
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testJDKCompatibleCommonCopy(Fury fury) {
+ fury.registerSerializer(
+ StringBuilder.class, new ObjectStreamSerializer(fury,
StringBuilder.class));
+ StringBuilder sb = fury.copy(new StringBuilder("abc"));
+ assertEquals(sb.toString(), "abc");
+ }
+
@Test(dataProvider = "javaFury")
public void testDispatch(Fury fury) {
WriteObjectTestClass o = new WriteObjectTestClass(new char[] {'a', 'b'});
@@ -174,6 +182,31 @@ public class ObjectStreamSerializerTest extends
FuryTestBase {
serDeCheck(fury, testClassObj3);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testJDKCompatiblePutFieldsCopy(Fury fury) {
+ fury.registerSerializer(
+ StringBuffer.class, new ObjectStreamSerializer(fury,
StringBuffer.class));
+ StringBuffer newStringBuffer = fury.copy(new StringBuffer("abc"));
+ assertEquals(newStringBuffer.toString(), "abc");
+ BigInteger bigInteger = BigInteger.valueOf(1000);
+ fury.registerSerializer(BigInteger.class, new ObjectStreamSerializer(fury,
BigInteger.class));
+ copyCheck(fury, bigInteger);
+ fury.registerSerializer(InetAddress.class, new
ObjectStreamSerializer(fury, InetAddress.class));
+ fury.registerSerializer(
+ Inet4Address.class, new ObjectStreamSerializer(fury,
Inet4Address.class));
+ InetAddress inetAddress = InetAddress.getLoopbackAddress();
+ copyCheck(fury, inetAddress);
+ WriteObjectTestClass2 testClassObj2 = new WriteObjectTestClass2(new char[]
{'a', 'b'}, "abc");
+ fury.registerSerializer(
+ WriteObjectTestClass2.class, new ObjectStreamSerializer(fury,
WriteObjectTestClass2.class));
+ copyCheck(fury, testClassObj2);
+ // test defaultReadObject compatible with putFields.
+ WriteObjectTestClass3 testClassObj3 = new WriteObjectTestClass3(new char[]
{'a', 'b'}, "abc");
+ fury.registerSerializer(
+ WriteObjectTestClass3.class, new ObjectStreamSerializer(fury,
WriteObjectTestClass3.class));
+ copyCheck(fury, testClassObj3);
+ }
+
@Test(dataProvider = "javaFury")
public void testJDKCompatibleMap(Fury fury) {
ImmutableMap<String, Integer> mapData = ImmutableMap.of("k1", 1, "k2", 2);
@@ -207,6 +240,27 @@ public class ObjectStreamSerializerTest extends
FuryTestBase {
}
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testJDKCompatibleMapCopy(Fury fury) {
+ ImmutableMap<String, Integer> mapData = ImmutableMap.of("k1", 1, "k2", 2);
+ {
+ ObjectStreamSerializer serializer = new ObjectStreamSerializer(fury,
ConcurrentHashMap.class);
+ ConcurrentHashMap<String, Integer> map = new
ConcurrentHashMap<>(mapData);
+ Object copy = serializer.copy(map);
+ assertEquals(copy, map);
+ }
+ {
+ fury.registerSerializer(
+ ConcurrentHashMap.class, new ObjectStreamSerializer(fury,
ConcurrentHashMap.class));
+ copyCheck(fury, new ConcurrentHashMap<>(mapData));
+ }
+ {
+ Map<String, Integer> map = new HashMap<>(mapData);
+ fury.registerSerializer(map.getClass(), new ObjectStreamSerializer(fury,
map.getClass()));
+ copyCheck(fury, map);
+ }
+ }
+
@Test(dataProvider = "javaFury")
public void testJDKCompatibleList(Fury fury) {
fury.registerSerializer(ArrayList.class, new ObjectStreamSerializer(fury,
ArrayList.class));
@@ -218,6 +272,17 @@ public class ObjectStreamSerializerTest extends
FuryTestBase {
serDeCheck(fury, new Vector<>(list));
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testJDKCompatibleListCopy(Fury fury) {
+ fury.registerSerializer(ArrayList.class, new ObjectStreamSerializer(fury,
ArrayList.class));
+ List<String> list = new ArrayList<>(ImmutableList.of("a", "b", "c", "d"));
+ copyCheck(fury, list);
+ fury.registerSerializer(LinkedList.class, new ObjectStreamSerializer(fury,
LinkedList.class));
+ copyCheck(fury, new LinkedList<>(list));
+ fury.registerSerializer(Vector.class, new ObjectStreamSerializer(fury,
Vector.class));
+ copyCheck(fury, new Vector<>(list));
+ }
+
@Test(dataProvider = "enableCodegen")
public void testJDKCompatibleCircularReference(boolean enableCodegen) {
Fury fury =
@@ -248,6 +313,24 @@ public class ObjectStreamSerializerTest extends
FuryTestBase {
}
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testJDKCompatibleCircularReference(Fury fury) {
+ {
+ ObjectStreamSerializer serializer = new ObjectStreamSerializer(fury,
ConcurrentHashMap.class);
+ ConcurrentHashMap<String, Object> map =
+ new ConcurrentHashMap<>(
+ ImmutableMap.of(
+ "k1", 1,
+ "k2", 2));
+ map.put("k3", map);
+ @SuppressWarnings("unchecked")
+ ConcurrentHashMap<String, Object> newMap =
+ (ConcurrentHashMap<String, Object>) serializer.copy(map);
+ assertSame(newMap.get("k3"), newMap);
+ assertEquals(newMap.get("k2"), map.get("k2"));
+ }
+ }
+
public abstract static class ValidationTestClass1 implements Serializable {
transient int state;
String str;
@@ -303,6 +386,18 @@ public class ObjectStreamSerializerTest extends
FuryTestBase {
assertEquals(obj2.state, realState);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testObjectInputValidationCopy(Fury fury) {
+ fury.registerSerializer(
+ ValidationTestClass2.class, new ObjectStreamSerializer(fury,
ValidationTestClass2.class));
+ int realState = 100;
+ String str = "abc";
+ ValidationTestClass2 obj = new ValidationTestClass2(str, realState);
+ ValidationTestClass2 obj2 = fury.copy(obj);
+ assertEquals(obj2.realState, realState);
+ assertEquals(obj2.str, str);
+ }
+
@EqualsAndHashCode(callSuper = true)
public static class WriteObjectTestClass4 extends WriteObjectTestClass {
@@ -330,6 +425,15 @@ public class ObjectStreamSerializerTest extends
FuryTestBase {
serDeCheckSerializer(fury, testClassObj4, "ObjectStreamSerializer");
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testWriteObjectReplaceCopy(Fury fury) throws
MalformedURLException {
+ copyCheck(fury, new URL("http://test"));
+ WriteObjectTestClass4 testClassObj4 = new WriteObjectTestClass4(new char[]
{'a', 'b'});
+ fury.registerSerializer(
+ WriteObjectTestClass4.class, new ObjectStreamSerializer(fury,
WriteObjectTestClass4.class));
+ copyCheck(fury, testClassObj4);
+ }
+
// TODO(chaokunyang) add `readObjectNoData` test for class inheritance
change.
// @Test
public void testReadObjectNoData() {}
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/OptionalSerializersTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/OptionalSerializersTest.java
index 0ef9be30..8e8ea72d 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/OptionalSerializersTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/OptionalSerializersTest.java
@@ -45,4 +45,19 @@ public class OptionalSerializersTest extends FuryTestBase {
serDeCheckSerializerAndEqual(fury, OptionalDouble.of(Double.MIN_VALUE),
"Optional");
serDeCheckSerializerAndEqual(fury, OptionalDouble.of(Double.MAX_VALUE),
"Optional");
}
+
+ @Test(dataProvider = "furyCopyConfig")
+ void testOptionals(Fury fury) {
+ copyCheckWithoutSame(fury, Optional.empty());
+ copyCheck(fury, Optional.of("abc"));
+ copyCheckWithoutSame(fury, OptionalInt.empty());
+ copyCheckWithoutSame(fury, OptionalInt.of(Integer.MIN_VALUE));
+ copyCheckWithoutSame(fury, OptionalInt.of(Integer.MAX_VALUE));
+ copyCheckWithoutSame(fury, OptionalLong.empty());
+ copyCheckWithoutSame(fury, OptionalLong.of(Long.MIN_VALUE));
+ copyCheckWithoutSame(fury, OptionalLong.of(Long.MAX_VALUE));
+ copyCheckWithoutSame(fury, OptionalDouble.empty());
+ copyCheckWithoutSame(fury, OptionalDouble.of(Double.MIN_VALUE));
+ copyCheckWithoutSame(fury, OptionalDouble.of(Double.MAX_VALUE));
+ }
}
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/PrimitiveSerializersTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/PrimitiveSerializersTest.java
index 2f1ff206..bcc965b0 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/PrimitiveSerializersTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/PrimitiveSerializersTest.java
@@ -119,4 +119,26 @@ public class PrimitiveSerializersTest extends FuryTestBase
{
serDeCheck(fury, struct);
}
}
+
+ @Test(dataProvider = "furyCopyConfig")
+ public void testPrimitiveStruct(Fury fury) {
+ PrimitiveStruct struct =
+ new PrimitiveStruct(
+ Byte.MIN_VALUE,
+ Byte.MIN_VALUE,
+ Character.MIN_VALUE,
+ Character.MIN_VALUE,
+ Short.MIN_VALUE,
+ Short.MIN_VALUE,
+ Integer.MIN_VALUE,
+ Integer.MIN_VALUE,
+ Long.MIN_VALUE,
+ Long.MIN_VALUE,
+ -3763915443215605988L, // test Long.reverseBytes in
_readVarInt64OnBE
+ Float.MIN_VALUE,
+ Float.MIN_VALUE,
+ Double.MIN_VALUE,
+ Double.MIN_VALUE);
+ copyCheck(fury, struct);
+ }
}
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/ReplaceResolveSerializerTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/ReplaceResolveSerializerTest.java
index 955639e7..c0d2f782 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/ReplaceResolveSerializerTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/ReplaceResolveSerializerTest.java
@@ -20,6 +20,7 @@
package org.apache.fury.serializer;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotSame;
import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertThrows;
import static org.testng.Assert.assertTrue;
@@ -99,6 +100,22 @@ public class ReplaceResolveSerializerTest extends
FuryTestBase {
fury.getClassResolver().getSerializer(map1.getClass()) instanceof
ReplaceResolveSerializer);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testCommonReplace(Fury fury) {
+ CustomReplaceClass1 o1 = new CustomReplaceClass1("abc");
+ fury.registerSerializer(CustomReplaceClass1.class,
ReplaceResolveSerializer.class);
+ fury.registerSerializer(CustomReplaceClass1.Replaced.class,
ReplaceResolveSerializer.class);
+ copyCheck(fury, o1);
+
+ ImmutableList<Integer> list1 = ImmutableList.of(1, 2, 3, 4);
+ fury.registerSerializer(list1.getClass(), new
ReplaceResolveSerializer(fury, list1.getClass()));
+ copyCheck(fury, list1);
+
+ ImmutableMap<String, Integer> map1 = ImmutableMap.of("k1", 1, "k2", 2);
+ fury.registerSerializer(map1.getClass(), new
ReplaceResolveSerializer(fury, map1.getClass()));
+ copyCheck(fury, map1);
+ }
+
@Data
public static class CustomReplaceClass2 implements Serializable {
public boolean copy;
@@ -156,6 +173,20 @@ public class ReplaceResolveSerializerTest extends
FuryTestBase {
instanceof ReplaceResolveSerializer);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testCopyReplaceCircularClass(Fury fury) {
+ fury.registerSerializer(CustomReplaceClass2.class,
ReplaceResolveSerializer.class);
+ for (Object o :
+ new Object[] {
+ new CustomReplaceClass2(false, 2), new CustomReplaceClass2(true, 2),
+ }) {
+ fury.registerSerializer(o.getClass(), ReplaceResolveSerializer.class);
+ copyCheck(fury, o);
+ }
+ CustomReplaceClass2 o = new CustomReplaceClass2(false, 6);
+ copyCheck(fury, o);
+ }
+
public static class CustomReplaceClass3 implements Serializable {
public Object ref;
@@ -207,6 +238,27 @@ public class ReplaceResolveSerializerTest extends
FuryTestBase {
}
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testWriteReplaceSameClassCircularRef(Fury fury) {
+ fury.registerSerializer(CustomReplaceClass3.class,
ReplaceResolveSerializer.class);
+ {
+ CustomReplaceClass3 o1 = new CustomReplaceClass3();
+ o1.ref = o1;
+ CustomReplaceClass3 copy = fury.copy(o1);
+ assertSame(copy, copy.ref);
+ }
+ {
+ CustomReplaceClass3 o1 = new CustomReplaceClass3();
+ CustomReplaceClass3 o2 = new CustomReplaceClass3();
+ o1.ref = o2;
+ o2.ref = o1;
+ {
+ CustomReplaceClass3 newObj1 = fury.copy(o1);
+ assertNotSame(newObj1.ref, o2);
+ }
+ }
+ }
+
public static class CustomReplaceClass4 implements Serializable {
public Object ref;
@@ -300,6 +352,19 @@ public class ReplaceResolveSerializerTest extends
FuryTestBase {
fury.getClassResolver().getSerializer(Subclass1.class) instanceof
ReplaceResolveSerializer);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testWriteReplaceSubClass(Fury fury) {
+ fury.registerSerializer(CustomReplaceClass2.class,
ReplaceResolveSerializer.class);
+ fury.registerSerializer(Subclass1.class, ReplaceResolveSerializer.class);
+ for (Object o :
+ new Object[] {
+ new Subclass1(false, 2, 10), new Subclass1(true, 2, 11),
+ }) {
+ fury.registerSerializer(o.getClass(), ReplaceResolveSerializer.class);
+ copyCheck(fury, o);
+ }
+ }
+
public static class Subclass2 extends CustomReplaceClass2 {
int state;
@@ -417,6 +482,20 @@ public class ReplaceResolveSerializerTest extends
FuryTestBase {
fury1, fury2, new SimpleCollectionTest(ImmutableList.of(1, 2),
ImmutableList.of("a", "b")));
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testImmutable(Fury fury) {
+ fury.registerSerializer(ImmutableList.of(1, 2).getClass(),
ReplaceResolveSerializer.class);
+ fury.registerSerializer(SimpleCollectionTest.class,
ReplaceResolveSerializer.class);
+ fury.registerSerializer(ImmutableMap.of("1", 2).getClass(),
ReplaceResolveSerializer.class);
+ fury.registerSerializer(SimpleMapTest.class,
ReplaceResolveSerializer.class);
+ copyCheck(fury, ImmutableList.of(1, 2));
+ copyCheck(fury, ImmutableList.of("a", "b"));
+ copyCheck(fury, new SimpleCollectionTest(ImmutableList.of(1, 2),
ImmutableList.of("a", "b")));
+ copyCheck(fury, ImmutableMap.of("1", 2));
+ copyCheck(fury, ImmutableMap.of(1, 2));
+ copyCheck(fury, new SimpleMapTest(ImmutableMap.of("k", 2),
ImmutableMap.of(1, 2)));
+ }
+
@Data
@AllArgsConstructor
public static class SimpleMapTest {
@@ -491,6 +570,13 @@ public class ReplaceResolveSerializerTest extends
FuryTestBase {
assertEquals(o.f1, 10);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testInheritance(Fury fury) {
+ fury.registerSerializer(InheritanceTestClass.class,
ReplaceResolveSerializer.class);
+ InheritanceTestClass o = fury.copy(new InheritanceTestClass((byte) 10));
+ assertEquals(o.f1, 10);
+ }
+
static class WriteReplaceExternalizable implements Externalizable {
private transient int f1;
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/StringSerializerTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/StringSerializerTest.java
index 84cc69ed..fc891ac5 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/StringSerializerTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/StringSerializerTest.java
@@ -70,6 +70,19 @@ public class StringSerializerTest extends FuryTestBase {
}
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testJavaStringCopy(Fury fury) {
+ for (int i = 0; i < 32; i++) {
+ for (int j = 0; j < 32; j++) {
+ String str = StringUtils.random(j);
+ if (j % 2 == 0) {
+ str += "你好"; // utf16
+ }
+ copyCheckWithoutSame(fury, str);
+ }
+ }
+ }
+
private static String readJavaStringZeroCopy(MemoryBuffer buffer) {
try {
Field valueIsBytesField =
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/TimeSerializersTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/TimeSerializersTest.java
index 6688cf4c..1cbaf55e 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/TimeSerializersTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/TimeSerializersTest.java
@@ -68,6 +68,23 @@ public class TimeSerializersTest extends FuryTestBase {
serDeCheckSerializerAndEqual(fury, Period.of(100, 11, 20), "Time");
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testBasicTime(Fury fury) {
+ copyCheckWithoutSame(fury, new Date());
+ copyCheckWithoutSame(fury, new java.sql.Date(100));
+ copyCheckWithoutSame(fury, new java.sql.Time(200));
+ copyCheckWithoutSame(fury, new Timestamp(300));
+ copyCheckWithoutSame(fury, new java.sql.Date(-100));
+ copyCheckWithoutSame(fury, new java.sql.Time(-200));
+ copyCheckWithoutSame(fury, new Timestamp(-300));
+ copyCheckWithoutSame(fury, LocalDate.now());
+ copyCheckWithoutSame(fury, LocalTime.now());
+ copyCheckWithoutSame(fury, LocalDateTime.now());
+ copyCheckWithoutSame(fury,
DateTimeUtils.truncateInstantToMicros(Instant.now()));
+ copyCheckWithoutSame(fury, Duration.between((Instant.now()),
Instant.ofEpochSecond(-1)));
+ copyCheckWithoutSame(fury, Period.of(100, 11, 20));
+ }
+
@Test
public void testCalendar() {
Fury fury =
Fury.builder().withLanguage(Language.JAVA).requireClassRegistration(false).build();
@@ -75,6 +92,12 @@ public class TimeSerializersTest extends FuryTestBase {
serDeCheckSerializerAndEqual(fury, Calendar.getInstance(), "Calendar");
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testCalendar(Fury fury) {
+ copyCheckWithoutSame(fury, GregorianCalendar.getInstance());
+ copyCheckWithoutSame(fury, Calendar.getInstance());
+ }
+
@Test
public void testZone() {
Fury fury =
Fury.builder().withLanguage(Language.JAVA).requireClassRegistration(false).build();
@@ -122,6 +145,43 @@ public class TimeSerializersTest extends FuryTestBase {
"OffsetDateTimeSerializer");
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testZone(Fury fury) {
+ copyCheckWithoutSame(
+ fury,
+ ZonedDateTime.of(Year.MIN_VALUE, Month.JANUARY.getValue(), 1, 0, 0, 0,
0, ZoneOffset.UTC));
+ copyCheckWithoutSame(
+ fury,
+ ZonedDateTime.of(
+ Year.MIN_VALUE, Month.JANUARY.getValue(), 1, 0, 0, 0, 0,
ZoneId.of("Europe/Berlin")));
+ copyCheckWithoutSame(
+ fury,
+ ZonedDateTime.of(
+ Year.MAX_VALUE,
+ Month.DECEMBER.getValue(),
+ 31,
+ 23,
+ 59,
+ 59,
+ 999999999,
+ ZoneId.of("Europe/Berlin")));
+ copyCheckWithoutSame(fury, Year.of(Year.MIN_VALUE));
+ copyCheckWithoutSame(fury, Year.of(Year.MAX_VALUE));
+ copyCheckWithoutSame(fury, YearMonth.of(Year.MIN_VALUE, Month.APRIL));
+ copyCheckWithoutSame(fury, YearMonth.of(Year.MAX_VALUE, Month.APRIL));
+ copyCheckWithoutSame(fury, MonthDay.of(Month.JANUARY, 11));
+ copyCheckWithoutSame(fury, MonthDay.of(Month.DECEMBER, 11));
+ copyCheckWithoutSame(fury, OffsetTime.of(1, 1, 1, 1, ZoneOffset.UTC));
+ copyCheckWithoutSame(fury, OffsetTime.of(23, 59, 59, 999999999,
ZoneOffset.UTC));
+ copyCheckWithoutSame(
+ fury,
+ OffsetDateTime.of(Year.MIN_VALUE, Month.JANUARY.getValue(), 1, 0, 0,
0, 0, ZoneOffset.UTC));
+ copyCheckWithoutSame(
+ fury,
+ OffsetDateTime.of(
+ Year.MAX_VALUE, Month.DECEMBER.getValue(), 31, 23, 59, 59,
999999999, ZoneOffset.UTC));
+ }
+
@Data
public static class TimeStruct {
Date date;
@@ -162,6 +222,21 @@ public class TimeSerializersTest extends FuryTestBase {
}
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testTimeStruct(Fury fury) {
+ TimeStruct struct = new TimeStruct();
+ struct.date = new Date();
+ struct.sqlDate = new java.sql.Date(100);
+ struct.time = new java.sql.Time(200);
+ struct.timestamp = new Timestamp(300);
+ struct.localDate = LocalDate.now();
+ struct.localTime = LocalTime.now();
+ struct.localDateTime = LocalDateTime.now();
+ struct.instant = DateTimeUtils.truncateInstantToMicros(Instant.now());
+ struct.duration = Duration.between(Instant.now(),
Instant.ofEpochSecond(-1));
+ copyCheck(fury, struct);
+ }
+
@Data
public static class TimeStructRef {
Date date1;
@@ -266,4 +341,54 @@ public class TimeSerializersTest extends FuryTestBase {
}
}
}
+
+ @Test(dataProvider = "furyCopyConfig")
+ public void testTimeStructRef(Fury fury) {
+ {
+ fury.registerSerializer(
+ TimeStructRef.class, CodegenSerializer.loadCodegenSerializer(fury,
TimeStructRef.class));
+ TimeStructRef struct = createTimeStructRef(new TimeStructRef());
+ TimeStructRef struct1 = fury.copy(struct);
+ Assert.assertSame(struct1.date1, struct1.date2);
+ Assert.assertSame(struct1.sqlDate1, struct1.sqlDate2);
+ Assert.assertSame(struct1.time1, struct1.time2);
+ Assert.assertSame(struct1.instant1, struct1.instant2);
+ Assert.assertSame(struct1.duration1, struct1.duration2);
+ }
+ {
+ fury.registerSerializer(
+ TimeStruct.class, CodegenSerializer.loadCodegenSerializer(fury,
TimeStruct.class));
+ fury.registerSerializer(
+ TimeStructRef1.class,
+ CodegenSerializer.loadCodegenSerializer(fury, TimeStructRef1.class));
+ TimeStructRef1 struct = (TimeStructRef1) createTimeStructRef(new
TimeStructRef1());
+ TimeStructRef1 struct1 = fury.copy(struct);
+ Assert.assertSame(struct1.date1, struct1.date2);
+ Assert.assertSame(struct1.sqlDate1, struct1.sqlDate2);
+ Assert.assertSame(struct1.time1, struct1.time2);
+ Assert.assertSame(struct1.instant1, struct1.instant2);
+ Assert.assertSame(struct1.duration1, struct1.duration2);
+ }
+ {
+ fury.registerSerializer(Date.class, new
TimeSerializers.DateSerializer(fury, true));
+ fury.registerSerializer(
+ java.sql.Date.class, new TimeSerializers.SqlDateSerializer(fury,
true));
+ fury.registerSerializer(Instant.class, new
TimeSerializers.InstantSerializer(fury, true));
+ {
+ TimeStructRef struct = createTimeStructRef(new TimeStructRef());
+ TimeStructRef struct2 = fury.copy(struct);
+ // TimeStructRef serializer already generated, enable ref tracking
doesn't take effect.
+ Assert.assertSame(struct2.date1, struct2.date2);
+ }
+ {
+ TimeStructRef struct = createTimeStructRef(new TimeStructRef2());
+ TimeStructRef struct2 = fury.copy(struct);
+ Assert.assertSame(struct2.date1, struct2.date2);
+ Assert.assertSame(struct2.sqlDate1, struct2.sqlDate2);
+ Assert.assertSame(struct2.instant1, struct2.instant2);
+ Assert.assertSame(struct2.time1, struct2.time2);
+ Assert.assertSame(struct2.duration1, struct2.duration2);
+ }
+ }
+ }
}
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/URLSerializerTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/URLSerializerTest.java
index 570ce6d3..35e296aa 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/URLSerializerTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/URLSerializerTest.java
@@ -35,6 +35,11 @@ public class URLSerializerTest extends FuryTestBase {
new URL("http://test"));
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testDefaultCopy(Fury fury) throws MalformedURLException {
+ copyCheck(fury, new URL("http://test"));
+ }
+
@Test
public void testURLSerializer() throws MalformedURLException {
Fury fury = Fury.builder().build();
@@ -43,4 +48,10 @@ public class URLSerializerTest extends FuryTestBase {
serDeCheckSerializer(fury, new URL("http://test"), "URLSerializer"),
new URL("http://test"));
}
+
+ @Test(dataProvider = "furyCopyConfig")
+ public void testURLSerializer(Fury fury) throws MalformedURLException {
+ fury.registerSerializer(URL.class, URLSerializer.class);
+ copyCheck(fury, new URL("http://test"));
+ }
}
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/collection/ChildContainerSerializersTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/collection/ChildContainerSerializersTest.java
index 4d118442..f7def9be 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/collection/ChildContainerSerializersTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/collection/ChildContainerSerializersTest.java
@@ -35,6 +35,7 @@ import lombok.Data;
import org.apache.fury.Fury;
import org.apache.fury.FuryTestBase;
import org.apache.fury.config.CompatibleMode;
+import org.apache.fury.test.bean.Cyclic;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@@ -131,6 +132,52 @@ public class ChildContainerSerializersTest extends
FuryTestBase {
}
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testChildCollectionCopy(Fury fury) {
+ List<Object> data = ImmutableList.of(1, true, "test", Cyclic.create(true));
+ {
+ ChildArrayList<Object> list = new ChildArrayList<>();
+ list.addAll(data);
+ list.state = 3;
+ ChildArrayList<Object> newList = fury.copy(list);
+ Assert.assertEquals(newList, list);
+ Assert.assertEquals(newList.state, 3);
+ Assert.assertEquals(
+ fury.getClassResolver().getSerializer(newList.getClass()).getClass(),
+ ChildContainerSerializers.ChildArrayListSerializer.class);
+ ArrayList<Object> innerList =
+ new ArrayList<Object>() {
+ {
+ add(Cyclic.create(true));
+ }
+ };
+ copyCheck(fury, innerList);
+ Assert.assertEquals(
+
fury.getClassResolver().getSerializer(innerList.getClass()).getClass(),
+ CollectionSerializers.JDKCompatibleCollectionSerializer.class);
+ }
+ {
+ ChildLinkedList<Object> list = new ChildLinkedList<>();
+ list.addAll(data);
+ copyCheck(fury, list);
+ }
+ {
+ ChildArrayDeque<Object> list = new ChildArrayDeque<>();
+ list.addAll(data);
+ Assert.assertEquals(ImmutableList.copyOf(fury.copy(list)), data);
+ }
+ {
+ ChildVector<Object> list = new ChildVector<>();
+ list.addAll(data);
+ copyCheck(fury, list);
+ }
+ {
+ ChildHashSet<Object> list = new ChildHashSet<>();
+ list.addAll(data);
+ copyCheck(fury, list);
+ }
+ }
+
public static class ChildHashMap<K, V> extends HashMap<K, V> {
private int state;
}
@@ -165,6 +212,30 @@ public class ChildContainerSerializersTest extends
FuryTestBase {
}
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testChildMapCopy(Fury fury) {
+ Map<String, Object> data = ImmutableMap.of("k1", 1, "k2", 2, "k3",
Cyclic.create(true));
+ {
+ ChildHashMap<String, Object> map = new ChildHashMap<>();
+ map.putAll(data);
+ map.state = 3;
+ ChildHashMap<String, Object> copy = fury.copy(map);
+ Assert.assertEquals(map, copy);
+ Assert.assertEquals(map.state, copy.state);
+ Assert.assertNotSame(map, copy);
+ }
+ {
+ ChildLinkedHashMap<String, Object> map = new ChildLinkedHashMap<>();
+ map.putAll(data);
+ copyCheck(fury, map);
+ }
+ {
+ ChildConcurrentHashMap<String, Object> map = new
ChildConcurrentHashMap<>();
+ map.putAll(data);
+ copyCheck(fury, map);
+ }
+ }
+
private static class CustomMap extends HashMap<String, String> {}
@Data
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/collection/CollectionSerializersTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/collection/CollectionSerializersTest.java
index 72b0850f..328d2a05 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/collection/CollectionSerializersTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/collection/CollectionSerializersTest.java
@@ -55,6 +55,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.LongStream;
import lombok.AllArgsConstructor;
import lombok.Data;
@@ -65,6 +66,7 @@ import org.apache.fury.memory.MemoryBuffer;
import org.apache.fury.memory.MemoryUtils;
import org.apache.fury.reflect.TypeRef;
import
org.apache.fury.serializer.collection.CollectionSerializers.JDKCompatibleCollectionSerializer;
+import org.apache.fury.test.bean.Cyclic;
import org.apache.fury.type.GenericType;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -87,6 +89,15 @@ public class CollectionSerializersTest extends FuryTestBase {
serDeCheckSerializer(fury, new LinkedHashSet<>(data), "LinkedHashSet");
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testBasicList(Fury fury) {
+ List<Object> data = Arrays.asList(1, true, "test", Cyclic.create(true));
+ copyCheck(fury, new ArrayList<>(data));
+ copyCheck(fury, data);
+ copyCheck(fury, new HashSet<>(data));
+ copyCheck(fury, new LinkedHashSet<>(data));
+ }
+
@Test(dataProvider = "referenceTrackingConfig")
public void testBasicListNested(boolean referenceTrackingConfig) {
Fury fury =
@@ -181,6 +192,52 @@ public class CollectionSerializersTest extends
FuryTestBase {
Assert.assertThrows(RuntimeException.class, () ->
fury.deserialize(bytes2));
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testSortedSet(Fury fury) {
+ AtomicInteger i = new AtomicInteger(1);
+ TreeSet<String> set = new TreeSet<>(new TestComparator(i));
+
+ TreeSet<String> copy = fury.copy(set);
+
+ Comparator<? super String> comparator1 = set.comparator();
+ Comparator<? super String> comparator2 = copy.comparator();
+ Assert.assertEquals(comparator1, comparator2);
+ set.add("str11");
+ copy.add("str11");
+ Assert.assertEquals(copy, set);
+ Assert.assertNotSame(copy, set);
+ i.set(-1);
+ Assert.assertNotEquals(comparator1, comparator2);
+ set.add("str2");
+ copy.add("str2");
+ Assert.assertNotEquals(Arrays.toString(copy.toArray()),
Arrays.toString(set.toArray()));
+ copy.add("str");
+ Assert.assertEquals(Arrays.toString(copy.toArray()), "[str, str2, str11]");
+ }
+
+ private class TestComparator implements Comparator<String> {
+ AtomicInteger i;
+
+ public TestComparator(AtomicInteger i) {
+ this.i = i;
+ }
+
+ @Override
+ public int compare(String s1, String s2) {
+ int delta = s1.length() - s2.length();
+ if (delta == i.get()) {
+ return s1.compareTo(s2);
+ } else {
+ return delta;
+ }
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return ((TestComparator) obj).i.get() == this.i.get();
+ }
+ }
+
@Test
public void testEmptyCollection() {
serDeCheckSerializer(getJavaFury(), Collections.EMPTY_LIST,
"EmptyListSerializer");
@@ -188,12 +245,25 @@ public class CollectionSerializersTest extends
FuryTestBase {
serDeCheckSerializer(getJavaFury(), Collections.EMPTY_SET,
"EmptySetSerializer");
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testEmptyCollection(Fury fury) {
+ copyCheckWithoutSame(fury, Collections.EMPTY_LIST);
+ copyCheckWithoutSame(fury, Collections.emptySortedSet());
+ copyCheckWithoutSame(fury, Collections.EMPTY_SET);
+ }
+
@Test
public void testSingleCollection() {
serDeCheckSerializer(getJavaFury(), Collections.singletonList(1),
"SingletonList");
serDeCheckSerializer(getJavaFury(), Collections.singleton(1),
"SingletonSet");
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testSingleCollection(Fury fury) {
+ copyCheck(fury, Collections.singletonList(Cyclic.create(true)));
+ copyCheck(fury, Collections.singleton(Cyclic.create(true)));
+ }
+
@Test
public void tesSkipList() {
serDeCheckSerializer(
@@ -202,18 +272,37 @@ public class CollectionSerializersTest extends
FuryTestBase {
"ConcurrentSkipListSet");
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void tesSkipList(Fury fury) {
+ copyCheck(fury, new ConcurrentSkipListSet<>(Arrays.asList("a", "b", "c")));
+ }
+
@Test
public void tesVectorSerializer() {
serDeCheckSerializer(
getJavaFury(), new Vector<>(Arrays.asList("a", "b", "c")),
"VectorSerializer");
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void tesVectorSerializer(Fury fury) {
+ copyCheck(fury, new Vector<>(Arrays.asList("a", 1, Cyclic.create(true))));
+ }
+
@Test
public void tesArrayDequeSerializer() {
serDeCheckSerializer(
getJavaFury(), new ArrayDeque<>(Arrays.asList("a", "b", "c")),
"ArrayDeque");
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void tesArrayDequeSerializer(Fury fury) {
+ ImmutableList<Object> list = ImmutableList.of("a", 1, Cyclic.create(true));
+ ArrayDeque<Object> deque = new ArrayDeque<>(list);
+ ArrayDeque<Object> copy = fury.copy(deque);
+ Assert.assertEquals(ImmutableList.copyOf(copy), list);
+ Assert.assertNotSame(deque, copy);
+ }
+
public enum TestEnum {
A,
B,
@@ -242,6 +331,13 @@ public class CollectionSerializersTest extends
FuryTestBase {
// TODO test enum which has enums exceed 128.
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void tesEnumSetSerializer(Fury fury) {
+ copyCheck(fury, EnumSet.allOf(TestEnum.class));
+ copyCheck(fury, EnumSet.of(TestEnum.A));
+ copyCheck(fury, EnumSet.of(TestEnum.A, TestEnum.B));
+ }
+
@Test
public void tesBitSetSerializer() {
serDe(getJavaFury(), BitSet.valueOf(LongStream.range(0, 2).toArray()));
@@ -258,6 +354,12 @@ public class CollectionSerializersTest extends
FuryTestBase {
CollectionSerializers.BitSetSerializer.class);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void tesBitSetSerializer(Fury fury) {
+ copyCheck(fury, BitSet.valueOf(LongStream.range(0, 2).toArray()));
+ copyCheck(fury, BitSet.valueOf(LongStream.range(0, 128).toArray()));
+ }
+
@Test
public void tesPriorityQueueSerializer() {
serDe(getJavaFury(), new PriorityQueue<>(Arrays.asList("a", "b", "c")));
@@ -266,6 +368,13 @@ public class CollectionSerializersTest extends
FuryTestBase {
CollectionSerializers.PriorityQueueSerializer.class);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void tesPriorityQueueSerializer(Fury fury) {
+ ImmutableList<String> list = ImmutableList.of("a", "b", "c");
+ PriorityQueue<String> copy = fury.copy(new PriorityQueue<>(list));
+ Assert.assertEquals(ImmutableList.copyOf(copy), list);
+ }
+
@Test
public void testCopyOnWriteArrayList() {
final CopyOnWriteArrayList<String> list =
@@ -276,6 +385,13 @@ public class CollectionSerializersTest extends
FuryTestBase {
CollectionSerializers.CopyOnWriteArrayListSerializer.class);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testCopyOnWriteArrayList(Fury fury) {
+ final CopyOnWriteArrayList<Object> list =
+ new CopyOnWriteArrayList<>(new Object[] {"a", "b",
Cyclic.create(true)});
+ copyCheck(fury, list);
+ }
+
@Test(dataProvider = "enableCodegen")
public void testSetFromMap(boolean enableCodegen) {
final Fury fury =
@@ -294,6 +410,15 @@ public class CollectionSerializersTest extends
FuryTestBase {
CollectionSerializers.SetFromMapSerializer.class);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testSetFromMap(Fury fury) {
+ final Set<Object> set = Collections.newSetFromMap(Maps.newConcurrentMap());
+ set.add("a");
+ set.add("b");
+ set.add(Cyclic.create(true));
+ copyCheck(fury, set);
+ }
+
@Test
public void testConcurrentMapKeySetViewMap() {
final ConcurrentHashMap.KeySetView<Object, Boolean> set =
ConcurrentHashMap.newKeySet();
@@ -306,6 +431,15 @@ public class CollectionSerializersTest extends
FuryTestBase {
CollectionSerializers.ConcurrentHashMapKeySetView.class);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testConcurrentMapKeySetViewMap(Fury fury) {
+ final ConcurrentHashMap.KeySetView<Object, Boolean> set =
ConcurrentHashMap.newKeySet();
+ set.add("a");
+ set.add("b");
+ set.add(Cyclic.create(true));
+ copyCheck(fury, set);
+ }
+
@Test
public void testSerializeJavaBlockingQueue() {
Fury fury =
@@ -334,6 +468,29 @@ public class CollectionSerializersTest extends
FuryTestBase {
}
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testSerializeJavaBlockingQueue(Fury fury) {
+ {
+ ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
+ queue.add(1);
+ queue.add(2);
+ queue.add(3);
+ ArrayBlockingQueue<Integer> copy = fury.copy(queue);
+ Assert.assertEquals(Arrays.toString(copy.toArray()), "[1, 2, 3]");
+ }
+ {
+ // If reference tracking is off, deserialization will throw
+ // `java.lang.IllegalMonitorStateException`
+ // when using fury `ObjectStreamSerializer`, maybe some internal state
are shared.
+ LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(10);
+ queue.add(1);
+ queue.add(2);
+ queue.add(3);
+ LinkedBlockingQueue<Integer> copy = fury.copy(queue);
+ Assert.assertEquals(Arrays.toString(copy.toArray()), "[1, 2, 3]");
+ }
+ }
+
@Test
public void testCollectionNoJIT() {
Fury fury =
Fury.builder().withLanguage(Language.JAVA).withCodegen(false).build();
@@ -363,6 +520,15 @@ public class CollectionSerializersTest extends
FuryTestBase {
}
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testSimpleBeanCollectionFieldsCopy(Fury fury) {
+ SimpleBeanCollectionFields obj = new SimpleBeanCollectionFields();
+ obj.list = new ArrayList<>();
+ obj.list.add("a");
+ obj.list.add("b");
+ Assert.assertEquals(fury.copy(obj).toString(), obj.toString());
+ }
+
@Data
@AllArgsConstructor
public static class NotFinal {
@@ -383,6 +549,14 @@ public class CollectionSerializersTest extends
FuryTestBase {
serDeCheck(fury, container);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testContainerCopy(Fury fury) {
+ Container container = new Container();
+ container.list1 = ofArrayList(new NotFinal(1));
+ container.map1 = ofHashMap("k", new NotFinal(2));
+ copyCheck(fury, container);
+ }
+
@Data
public static class CollectionFieldsClass {
public ArrayList<String> arrayList;
@@ -476,6 +650,12 @@ public class CollectionSerializersTest extends
FuryTestBase {
}
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testCollectionFieldSerializersCopy(Fury fury) {
+ CollectionFieldsClass obj = createCollectionFieldsObject();
+ Assert.assertEquals(fury.copy(obj).toString(), obj.toString());
+ }
+
@Data
@AllArgsConstructor
public static class NestedCollection1 {
@@ -489,6 +669,13 @@ public class CollectionSerializersTest extends
FuryTestBase {
Assert.assertEquals(serDe(fury, o), o);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testNestedCollection1Copy(Fury fury) {
+ ArrayList<Integer> list = ofArrayList(1, 2);
+ NestedCollection1 o = new NestedCollection1(ofArrayList(list));
+ copyCheck(fury, o);
+ }
+
@Data
@AllArgsConstructor
public static class NestedCollection2 {
@@ -502,6 +689,13 @@ public class CollectionSerializersTest extends
FuryTestBase {
Assert.assertEquals(serDe(fury, o), o);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testNestedCollection2Copy(Fury fury) {
+ ArrayList<Integer> list = ofArrayList(1, 2);
+ NestedCollection2 o = new
NestedCollection2(ofArrayList(ofArrayList(list)));
+ copyCheck(fury, o);
+ }
+
public static class TestClassForDefaultCollectionSerializer extends
AbstractCollection<String> {
private final List<String> data = new ArrayList<>();
@@ -547,6 +741,15 @@ public class CollectionSerializersTest extends
FuryTestBase {
CollectionSerializers.DefaultJavaCollectionSerializer.class);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testDefaultCollectionSerializer(Fury fury) {
+ TestClassForDefaultCollectionSerializer collection =
+ new TestClassForDefaultCollectionSerializer();
+ collection.add("a");
+ collection.add("b");
+ copyCheck(fury, collection);
+ }
+
@SuppressWarnings("unchecked")
@Test
public void testJavaSerialization() {
@@ -573,6 +776,17 @@ public class CollectionSerializersTest extends
FuryTestBase {
assertEquals(set, fury.deserialize(fury.serialize(buffer, set)));
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testJavaSerialization(Fury fury) {
+ ImmutableSortedSet<Integer> set = ImmutableSortedSet.of(1, 2, 3);
+ Class<? extends ImmutableSortedSet> setClass = set.getClass();
+ JDKCompatibleCollectionSerializer javaSerializer =
+ new JDKCompatibleCollectionSerializer(fury, setClass);
+ Object copy = javaSerializer.copy(set);
+ assertEquals(set, copy);
+ Assert.assertNotSame(set, copy);
+ }
+
public static class SubListSerializer extends CollectionSerializer {
public SubListSerializer(Fury fury, Class cls) {
@@ -618,6 +832,13 @@ public class CollectionSerializersTest extends
FuryTestBase {
serDeCheck(f, data);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testCollectionNullElements(Fury fury) {
+ List data = new ArrayList<>();
+ data.add(null);
+ copyCheck(fury, data);
+ }
+
@Data
abstract static class Foo {
private int f1;
@@ -644,4 +865,18 @@ public class CollectionSerializersTest extends
FuryTestBase {
serDeCheck(fury, test);
}
}
+
+ @Test(dataProvider = "furyCopyConfig")
+ public void testAbstractCollectionElementsSerialization(Fury fury) {
+ {
+ CollectionAbstractTest test = new CollectionAbstractTest();
+ test.fooList = new ArrayList<>(ImmutableList.of(new Foo1(), new Foo1()));
+ copyCheck(fury, test);
+ }
+ {
+ CollectionAbstractTest test = new CollectionAbstractTest();
+ test.fooList = new ArrayList<>(ofArrayList(new Foo1(), new Foo1()));
+ copyCheck(fury, test);
+ }
+ }
}
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/collection/GuavaCollectionSerializersTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/collection/GuavaCollectionSerializersTest.java
index 56d585c1..62e0ca4f 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/collection/GuavaCollectionSerializersTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/collection/GuavaCollectionSerializersTest.java
@@ -48,6 +48,12 @@ public class GuavaCollectionSerializersTest extends
FuryTestBase {
GuavaCollectionSerializers.RegularImmutableListSerializer.class);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testImmutableListSerializerCopy(Fury fury) {
+ copyCheck(fury, ImmutableList.of(1));
+ copyCheck(fury, ImmutableList.of(1, 2));
+ }
+
@Test(dataProvider = "trackingRefFury")
public void testImmutableSetSerializer(Fury fury) {
serDe(fury, ImmutableSet.of(1));
@@ -60,6 +66,18 @@ public class GuavaCollectionSerializersTest extends
FuryTestBase {
GuavaCollectionSerializers.ImmutableSetSerializer.class);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testImmutableSetSerializerCopy(Fury fury) {
+ copyCheck(fury, ImmutableSet.of(1));
+ Assert.assertEquals(
+
fury.getClassResolver().getSerializerClass(ImmutableSet.of(1).getClass()),
+ GuavaCollectionSerializers.ImmutableSetSerializer.class);
+ copyCheck(fury, ImmutableSet.of(1, 2));
+ Assert.assertEquals(
+ fury.getClassResolver().getSerializerClass(ImmutableSet.of(1,
2).getClass()),
+ GuavaCollectionSerializers.ImmutableSetSerializer.class);
+ }
+
@Test(dataProvider = "trackingRefFury")
public void testImmutableSortedSetSerializer(Fury fury) {
serDe(fury, ImmutableSortedSet.of(1, 2));
@@ -68,6 +86,14 @@ public class GuavaCollectionSerializersTest extends
FuryTestBase {
GuavaCollectionSerializers.ImmutableSortedSetSerializer.class);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testImmutableSortedSetSerializerCopy(Fury fury) {
+ copyCheck(fury, ImmutableSortedSet.of(1, 2));
+ Assert.assertEquals(
+ fury.getClassResolver().getSerializerClass(ImmutableSortedSet.of(1,
2).getClass()),
+ GuavaCollectionSerializers.ImmutableSortedSetSerializer.class);
+ }
+
@Test(dataProvider = "trackingRefFury")
public void testImmutableMapSerializer(Fury fury) {
serDe(fury, ImmutableMap.of("k1", 1, "k2", 2));
@@ -76,6 +102,14 @@ public class GuavaCollectionSerializersTest extends
FuryTestBase {
GuavaCollectionSerializers.ImmutableMapSerializer.class);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testImmutableMapSerializerCopy(Fury fury) {
+ copyCheck(fury, ImmutableMap.of("k1", 1, "k2", 2));
+ Assert.assertEquals(
+ fury.getClassResolver().getSerializerClass(ImmutableMap.of("k1", 1,
"k2", 2).getClass()),
+ GuavaCollectionSerializers.ImmutableMapSerializer.class);
+ }
+
@Test(dataProvider = "trackingRefFury")
public void testImmutableBiMapSerializer(Fury fury) {
serDe(fury, ImmutableBiMap.of("k1", 1));
@@ -88,6 +122,18 @@ public class GuavaCollectionSerializersTest extends
FuryTestBase {
GuavaCollectionSerializers.ImmutableBiMapSerializer.class);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testImmutableBiMapSerializerCopy(Fury fury) {
+ copyCheck(fury, ImmutableBiMap.of("k1", 1));
+ Assert.assertEquals(
+ fury.getClassResolver().getSerializerClass(ImmutableBiMap.of("k1",
1).getClass()),
+ GuavaCollectionSerializers.ImmutableBiMapSerializer.class);
+ copyCheck(fury, ImmutableBiMap.of("k1", 1, "k2", 2));
+ Assert.assertEquals(
+ fury.getClassResolver().getSerializerClass(ImmutableBiMap.of("k1", 1,
"k2", 2).getClass()),
+ GuavaCollectionSerializers.ImmutableBiMapSerializer.class);
+ }
+
@Test(dataProvider = "trackingRefFury")
public void testImmutableSortedMapSerializer(Fury fury) {
serDe(fury, ImmutableSortedMap.of("k1", 1, "k2", 2));
@@ -97,6 +143,15 @@ public class GuavaCollectionSerializersTest extends
FuryTestBase {
GuavaCollectionSerializers.ImmutableSortedMapSerializer.class);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testImmutableSortedMapSerializerCopy(Fury fury) {
+ copyCheck(fury, ImmutableSortedMap.of("k1", 1, "k2", 2));
+ Assert.assertEquals(
+ fury.getClassResolver()
+ .getSerializerClass(ImmutableSortedMap.of("k1", 1, "k2",
2).getClass()),
+ GuavaCollectionSerializers.ImmutableSortedMapSerializer.class);
+ }
+
@Test
public void tesXlangSerialize() {
Fury fury = Fury.builder().withLanguage(Language.XLANG).build();
@@ -126,4 +181,10 @@ public class GuavaCollectionSerializersTest extends
FuryTestBase {
Pojo deserializedPojo = (Pojo) fury.deserialize(bytes);
System.out.println(deserializedPojo);
}
+
+ @Test(dataProvider = "furyCopyConfig")
+ void testNestedRefTrackingCopy(Fury fury) {
+ Pojo pojo = new Pojo(ImmutableList.of(ImmutableList.of(1, 2),
ImmutableList.of(2, 2)));
+ copyCheck(fury, pojo);
+ }
}
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/collection/MapSerializersTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/collection/MapSerializersTest.java
index 6aa5f2cf..760d061b 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/collection/MapSerializersTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/collection/MapSerializersTest.java
@@ -46,10 +46,12 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.fury.Fury;
import org.apache.fury.FuryTestBase;
+import org.apache.fury.collection.LazyMap;
import org.apache.fury.collection.MapEntry;
import org.apache.fury.config.Language;
import org.apache.fury.reflect.TypeRef;
import
org.apache.fury.serializer.collection.CollectionSerializersTest.TestEnum;
+import org.apache.fury.test.bean.Cyclic;
import org.apache.fury.test.bean.MapFields;
import org.apache.fury.type.GenericType;
import org.testng.Assert;
@@ -70,6 +72,25 @@ public class MapSerializersTest extends FuryTestBase {
serDeCheckSerializer(fury, new LinkedHashMap<>(data), "LinkedHashMap");
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testBasicMap(Fury fury) {
+ Map<String, Object> data =
+ new HashMap<>(ImmutableMap.of("a", 1, "b", 2, "c",
Cyclic.create(true)));
+ copyCheck(fury, data);
+ copyCheck(fury, new LinkedHashMap<>(data));
+ copyCheck(fury, new LazyMap<>(new ArrayList<>(data.entrySet())));
+
+ Map<Object, Object> cycMap = new HashMap<>();
+ cycMap.put(cycMap, cycMap);
+ Map<Object, Object> copy = fury.copy(cycMap);
+ copy.forEach(
+ (k, v) -> {
+ Assert.assertSame(k, copy);
+ Assert.assertSame(v, copy);
+ Assert.assertSame(k, v);
+ });
+ }
+
@Test(dataProvider = "referenceTrackingConfig")
public void testBasicMapNested(boolean referenceTrackingConfig) {
Fury fury =
@@ -84,6 +105,14 @@ public class MapSerializersTest extends FuryTestBase {
serDeCheckSerializer(fury, new LinkedHashMap<>(data), "LinkedHashMap");
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testBasicMapNested(Fury fury) {
+ Map<String, Integer> data0 = new HashMap<>(ImmutableMap.of("a", 1, "b",
2));
+ Map<String, Map<String, Integer>> data = ofHashMap("k1", data0, "k2",
data0);
+ copyCheck(fury, data);
+ copyCheck(fury, new LinkedHashMap<>(data));
+ }
+
@Test(dataProvider = "referenceTrackingConfig")
public void testMapGenerics(boolean referenceTrackingConfig) {
Fury fury =
@@ -119,6 +148,12 @@ public class MapSerializersTest extends FuryTestBase {
Assert.assertThrows(RuntimeException.class, () ->
fury.deserialize(bytes2));
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testSortedMap(Fury fury) {
+ Map<String, Integer> data = new TreeMap<>(ImmutableMap.of("a", 1, "b", 2));
+ copyCheck(fury, data);
+ }
+
@Data
public static class BeanForMap {
public Map<String, String> map = new TreeMap<>();
@@ -156,17 +191,48 @@ public class MapSerializersTest extends FuryTestBase {
assertEquals(beanForMap, serDe(fury, beanForMap));
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testTreeMap(Fury fury) {
+ TreeMap<String, String> map =
+ new TreeMap<>(
+ (Comparator<? super String> & Serializable)
+ (s1, s2) -> {
+ int delta = s1.length() - s2.length();
+ if (delta == 0) {
+ return s1.compareTo(s2);
+ } else {
+ return delta;
+ }
+ });
+ map.put("str1", "1");
+ map.put("str2", "1");
+ copyCheck(fury, map);
+ BeanForMap beanForMap = new BeanForMap();
+ copyCheck(fury, beanForMap);
+ }
+
@Test
public void testEmptyMap() {
serDeCheckSerializer(getJavaFury(), Collections.EMPTY_MAP,
"EmptyMapSerializer");
serDeCheckSerializer(getJavaFury(), Collections.emptySortedMap(),
"EmptySortedMap");
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testEmptyMap(Fury fury) {
+ copyCheckWithoutSame(fury, Collections.EMPTY_MAP);
+ copyCheckWithoutSame(fury, Collections.emptySortedMap());
+ }
+
@Test
public void testSingleMap() {
serDeCheckSerializer(getJavaFury(), Collections.singletonMap("k", 1),
"SingletonMap");
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testSingleMap(Fury fury) {
+ copyCheck(fury, Collections.singletonMap("k", 1));
+ }
+
@Test
public void testConcurrentMap() {
Map<String, Integer> data = new TreeMap<>(ImmutableMap.of("a", 1, "b", 2));
@@ -174,6 +240,13 @@ public class MapSerializersTest extends FuryTestBase {
serDeCheckSerializer(getJavaFury(), new ConcurrentSkipListMap<>(data),
"ConcurrentSkipListMap");
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testConcurrentMap(Fury fury) {
+ Map<String, Integer> data = new TreeMap<>(ImmutableMap.of("a", 1, "b", 2));
+ copyCheck(fury, new ConcurrentHashMap<>(data));
+ copyCheck(fury, new ConcurrentSkipListMap<>(data));
+ }
+
@Test
public void testEnumMap() {
EnumMap<TestEnum, Object> enumMap = new EnumMap<>(TestEnum.class);
@@ -185,6 +258,17 @@ public class MapSerializersTest extends FuryTestBase {
MapSerializers.EnumMapSerializer.class);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testEnumMap(Fury fury) {
+ EnumMap<TestEnum, Object> enumMap = new EnumMap<>(TestEnum.class);
+ enumMap.put(TestEnum.A, 1);
+ enumMap.put(TestEnum.B, "str");
+ copyCheck(fury, enumMap);
+ Assert.assertEquals(
+
getJavaFury().getClassResolver().getSerializerClass(enumMap.getClass()),
+ MapSerializers.EnumMapSerializer.class);
+ }
+
private static Map<String, Integer> newInnerMap() {
return new HashMap<String, Integer>() {
{
@@ -202,6 +286,12 @@ public class MapSerializersTest extends FuryTestBase {
serDeCheck(fury, map);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testNoArgConstructor(Fury fury) {
+ Map<String, Integer> map = newInnerMap();
+ copyCheck(fury, map);
+ }
+
@Test
public void testMapNoJIT() {
Fury fury =
Fury.builder().withLanguage(Language.JAVA).withCodegen(false).build();
@@ -216,12 +306,24 @@ public class MapSerializersTest extends FuryTestBase {
Assert.assertEquals(serDe(fury, obj), obj);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testMapFieldSerializersCopy(Fury fury) {
+ MapFields obj = createMapFieldsObject();
+ copyCheck(fury, obj);
+ }
+
@Test(dataProvider = "javaFuryKVCompatible")
public void testMapFieldsKVCompatible(Fury fury) {
MapFields obj = createMapFieldsObject();
Assert.assertEquals(serDe(fury, obj), obj);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testMapFieldsKVCompatibleCopy(Fury fury) {
+ MapFields obj = createMapFieldsObject();
+ copyCheck(fury, obj);
+ }
+
public static MapFields createMapFieldsObject() {
MapFields obj = new MapFields();
Map<String, Integer> map = ImmutableMap.of("k1", 1, "k2", 2);
@@ -308,6 +410,25 @@ public class MapSerializersTest extends FuryTestBase {
serDeCheck(fury, map2);
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testDefaultMapSerializer(Fury fury) {
+ TestClass1ForDefaultMap map = new TestClass1ForDefaultMap();
+ map.put("a", 1);
+ map.put("b", 2);
+ Assert.assertSame(
+
fury.getClassResolver().getSerializerClass(TestClass1ForDefaultMap.class),
+ MapSerializers.DefaultJavaMapSerializer.class);
+ copyCheck(fury, map);
+
+ TestClass2ForDefaultMap map2 = new TestClass2ForDefaultMap();
+ map.put("a", 1);
+ map.put("b", 2);
+ Assert.assertSame(
+
fury.getClassResolver().getSerializerClass(TestClass2ForDefaultMap.class),
+ MapSerializers.DefaultJavaMapSerializer.class);
+ copyCheck(fury, map2);
+ }
+
@Data
@AllArgsConstructor
public static class GenericMapBoundTest {
@@ -363,4 +484,23 @@ public class MapSerializersTest extends FuryTestBase {
serDeCheck(fury, map);
}
}
+
+ @Test(dataProvider = "furyCopyConfig")
+ public void testStringKeyMapSerializer(Fury fury) {
+ fury.registerSerializer(StringKeyMap.class,
MapSerializers.StringKeyMapSerializer.class);
+ {
+ StringKeyMap<List<String>> map = new StringKeyMap<>();
+ map.put("k1", ofArrayList("a", "b"));
+ copyCheck(fury, map);
+ }
+ {
+ // test nested map
+ StringKeyMap<StringKeyMap<String>> map = new StringKeyMap<>();
+ StringKeyMap<String> map2 = new StringKeyMap<>();
+ map2.put("k-k1", "v1");
+ map2.put("k-k2", "v2");
+ map.put("k1", map2);
+ copyCheck(fury, map);
+ }
+ }
}
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/collection/SynchronizedSerializersTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/collection/SynchronizedSerializersTest.java
index 4056023e..d8edfb02 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/collection/SynchronizedSerializersTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/collection/SynchronizedSerializersTest.java
@@ -103,6 +103,13 @@ public class SynchronizedSerializersTest extends
FuryTestBase {
assertEquals(((CollectionFields) (newObj)).toCanEqual(), obj.toCanEqual());
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testCollectionFieldSerializersCopy(Fury fury) {
+ CollectionFields obj = createCollectionFields();
+ Object newObj = fury.copy(obj);
+ assertEquals(((CollectionFields) (newObj)).toCanEqual(), obj.toCanEqual());
+ }
+
public static CollectionFields createCollectionFields() {
CollectionFields obj = new CollectionFields();
Collection<Integer> collection =
Collections.synchronizedCollection(Arrays.asList(1, 2));
diff --git
a/java/fury-core/src/test/java/org/apache/fury/serializer/collection/UnmodifiableSerializersTest.java
b/java/fury-core/src/test/java/org/apache/fury/serializer/collection/UnmodifiableSerializersTest.java
index 62172d3c..46777bd5 100644
---
a/java/fury-core/src/test/java/org/apache/fury/serializer/collection/UnmodifiableSerializersTest.java
+++
b/java/fury-core/src/test/java/org/apache/fury/serializer/collection/UnmodifiableSerializersTest.java
@@ -143,6 +143,13 @@ public class UnmodifiableSerializersTest extends
FuryTestBase {
assertEquals(((CollectionFields) (newObj)).toCanEqual(), obj.toCanEqual());
}
+ @Test(dataProvider = "furyCopyConfig")
+ public void testCollectionFieldSerializersCopy(Fury fury) {
+ CollectionFields obj = createCollectionFields();
+ Object newObj = fury.copy(obj);
+ assertEquals(((CollectionFields) (newObj)).toCanEqual(), obj.toCanEqual());
+ }
+
public static MapFields createMapFields() {
MapFields obj = new MapFields();
Map<String, Integer> map = ImmutableMap.of("k1", 1, "k2", 2);
@@ -179,4 +186,10 @@ public class UnmodifiableSerializersTest extends
FuryTestBase {
MapFields obj = createMapFields();
Assert.assertEquals(serDe(fury, obj), obj);
}
+
+ @Test(dataProvider = "furyCopyConfig")
+ public void testMapFieldSerializersCopy(Fury fury) {
+ MapFields obj = createMapFields();
+ copyCheck(fury, obj);
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]