This is an automated email from the ASF dual-hosted git repository. asf-gitbox-commits pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-jcs.git
commit ea261720153ff13c9483e2f94ada39aaf9cc2994 Author: Thomas Vandahl <[email protected]> AuthorDate: Sun Oct 18 23:08:20 2026 +0200 Rework serialization tests --- .../remote/AbstractRemoteAuxiliaryCache.java | 11 +- .../remote/AbstractRemoteCacheListener.java | 4 +- .../jcs4/engine/behavior/IElementSerializer.java | 59 ++++ .../serialization/SerializationConversionUtil.java | 127 -------- .../utils/serialization/StandardSerializer.java | 5 + .../jcs4/auxiliary/remote/RemoteCacheUnitTest.java | 11 +- .../CompressingSerializerUnitTest.java | 59 ---- .../EncryptingSerializerUnitTest.java | 56 ---- .../SerializationConversionUtilUnitTest.java | 200 ------------ .../utils/serialization/SerializerUnitTest.java | 339 ++++++++++++++++++--- .../serialization/StandardSerializerUnitTest.java | 75 +---- 11 files changed, 380 insertions(+), 566 deletions(-) diff --git a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/remote/AbstractRemoteAuxiliaryCache.java b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/remote/AbstractRemoteAuxiliaryCache.java index 387acec5..443a7f1d 100644 --- a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/remote/AbstractRemoteAuxiliaryCache.java +++ b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/remote/AbstractRemoteAuxiliaryCache.java @@ -46,7 +46,6 @@ import org.apache.commons.jcs4.engine.logging.behavior.ICacheEventLogger.CacheEv import org.apache.commons.jcs4.engine.stats.Stats; import org.apache.commons.jcs4.engine.stats.behavior.IStats; import org.apache.commons.jcs4.log.Log; -import org.apache.commons.jcs4.utils.serialization.SerializationConversionUtil; import org.apache.commons.jcs4.utils.threadpool.ThreadPoolManager; /** Abstract base for remote caches. I'm trying to break out and reuse common functionality. */ @@ -406,8 +405,7 @@ public abstract class AbstractRemoteAuxiliaryCache<K, V> if (retVal instanceof ICacheElementSerialized<K, V> serialized && this.getAuxiliaryCacheAttributes().getRemoteType() != RemoteType.CLUSTER) { - retVal = SerializationConversionUtil.getDeSerializedCacheElement(serialized, - super.getElementSerializer() ); + retVal = super.getElementSerializer().getDeSerializedCacheElement(serialized); } } catch ( final IOException | ClassNotFoundException ex ) @@ -446,9 +444,7 @@ public abstract class AbstractRemoteAuxiliaryCache<K, V> // to have no ability to deserialize the objects. if ( this.getAuxiliaryCacheAttributes().getRemoteType() != RemoteType.CLUSTER ) { - unwrappedResult = SerializationConversionUtil - .getDeSerializedCacheElement(serialized, - super.getElementSerializer() ); + unwrappedResult = super.getElementSerializer().getDeSerializedCacheElement(serialized); } } else @@ -538,7 +534,8 @@ public abstract class AbstractRemoteAuxiliaryCache<K, V> // convert so we don't have to know about the object on the // other end. - final ICacheElementSerialized<K, V> serialized = SerializationConversionUtil.getSerializedCacheElement( ce, super.getElementSerializer() ); + final ICacheElementSerialized<K, V> serialized = + super.getElementSerializer().getSerializedCacheElement(ce); remoteCacheService.update( serialized, getListenerId() ); } diff --git a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/remote/AbstractRemoteCacheListener.java b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/remote/AbstractRemoteCacheListener.java index 7d305f55..aca7be9f 100644 --- a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/remote/AbstractRemoteCacheListener.java +++ b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/remote/AbstractRemoteCacheListener.java @@ -31,7 +31,6 @@ import org.apache.commons.jcs4.engine.behavior.ICompositeCacheManager; import org.apache.commons.jcs4.engine.behavior.IElementSerializer; import org.apache.commons.jcs4.log.Log; import org.apache.commons.jcs4.utils.net.HostNameUtil; -import org.apache.commons.jcs4.utils.serialization.SerializationConversionUtil; /** Shared listener base. */ public abstract class AbstractRemoteCacheListener<K, V> @@ -183,8 +182,7 @@ public abstract class AbstractRemoteCacheListener<K, V> log.debug( "Object needs to be deserialized." ); try { - cb = SerializationConversionUtil.getDeSerializedCacheElement( - serialized, this.elementSerializer ); + cb = this.elementSerializer.getDeSerializedCacheElement(serialized); log.debug( "Deserialized result = {0}", cb ); } catch ( final IOException e ) diff --git a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/behavior/IElementSerializer.java b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/behavior/IElementSerializer.java index 3f41122a..1129df5b 100644 --- a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/behavior/IElementSerializer.java +++ b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/behavior/IElementSerializer.java @@ -33,6 +33,9 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import org.apache.commons.jcs4.engine.CacheElement; +import org.apache.commons.jcs4.engine.CacheElementSerialized; + /** * Defines the behavior for cache element serializers. This layer of abstraction allows us to plug * in different serialization mechanisms, such as a compressing standard serializer. @@ -284,4 +287,60 @@ public interface IElementSerializer } return count; } + + /** + * This returns a wrapper that has a de-serialized version of the value + * instead of the serialized value. + * + * @param serialized + * @return null for null; + * @throws IOException + * @throws ClassNotFoundException + */ + default <K, V> ICacheElement<K, V> getDeSerializedCacheElement( final ICacheElementSerialized<K, V> serialized) + throws IOException, ClassNotFoundException + { + if ( serialized == null ) + { + return null; + } + + V deSerializedValue = deSerialize(serialized.serializedValue(), null); + final ICacheElement<K, V> deSerialized = new CacheElement<>(serialized.cacheName(), + serialized.key(), deSerializedValue, serialized.elementAttributes()); + + return deSerialized; + } + + /** + * This returns a wrapper that has a serialized version of the value instead + * of the value. + * + * @param element + * @return null for null; + * @throws IOException + */ + default <K, V> ICacheElementSerialized<K, V> getSerializedCacheElement( final ICacheElement<K, V> element) + throws IOException + { + if ( element == null ) + { + return null; + } + + byte[] serializedValue = null; + + // if it has already been serialized, don't do it again. + if (element instanceof ICacheElementSerialized<K, V> serialized) + { + serializedValue = serialized.serializedValue(); + } + else + { + serializedValue = serialize(element.value()); + } + + return new CacheElementSerialized<>( + element.cacheName(), element.key(), serializedValue, element.elementAttributes() ); + } } diff --git a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/utils/serialization/SerializationConversionUtil.java b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/utils/serialization/SerializationConversionUtil.java deleted file mode 100644 index 5c13c8d7..00000000 --- a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/utils/serialization/SerializationConversionUtil.java +++ /dev/null @@ -1,127 +0,0 @@ -package org.apache.commons.jcs4.utils.serialization; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import java.io.IOException; - -import org.apache.commons.jcs4.engine.CacheElement; -import org.apache.commons.jcs4.engine.CacheElementSerialized; -import org.apache.commons.jcs4.engine.behavior.ICacheElement; -import org.apache.commons.jcs4.engine.behavior.ICacheElementSerialized; -import org.apache.commons.jcs4.engine.behavior.IElementSerializer; -import org.apache.commons.jcs4.log.Log; - -/** - * This uses a supplied Serializer to convert to and from cache elements. - */ -public class SerializationConversionUtil -{ - /** The logger */ - private static final Log log = Log.getLog( SerializationConversionUtil.class ); - - /** - * This returns a wrapper that has a de-serialized version of the value - * instead of the serialized value. - * - * @param serialized - * @param elementSerializer - * the serializer to be used. - * @return null for null; - * @throws IOException - * @throws ClassNotFoundException - */ - public static <K, V> ICacheElement<K, V> getDeSerializedCacheElement( final ICacheElementSerialized<K, V> serialized, - final IElementSerializer elementSerializer ) - throws IOException, ClassNotFoundException - { - if ( serialized == null ) - { - return null; - } - - V deSerializedValue = null; - - if ( elementSerializer == null ) { - // we could just use the default. - throw new IOException( "Could not de-serialize object. The ElementSerializer is null." ); - } - try - { - deSerializedValue = elementSerializer.deSerialize( serialized.serializedValue(), null ); - } - catch ( final ClassNotFoundException | IOException e ) - { - log.error( "Problem de-serializing object.", e ); - throw e; - } - final ICacheElement<K, V> deSerialized = new CacheElement<>(serialized.cacheName(), - serialized.key(), deSerializedValue, serialized.elementAttributes()); - - return deSerialized; - } - - /** - * This returns a wrapper that has a serialized version of the value instead - * of the value. - * - * @param element - * @param elementSerializer - * the serializer to be used. - * @return null for null; - * @throws IOException - */ - public static <K, V> ICacheElementSerialized<K, V> getSerializedCacheElement( final ICacheElement<K, V> element, - final IElementSerializer elementSerializer ) - throws IOException - { - if ( element == null ) - { - return null; - } - - byte[] serializedValue = null; - - // if it has already been serialized, don't do it again. - if (element instanceof ICacheElementSerialized<K, V> serialized) - { - serializedValue = serialized.serializedValue(); - } - else - { - if ( elementSerializer == null ) - { - // we could just use the default. - throw new IOException( "Could not serialize object. The ElementSerializer is null." ); - } - try - { - serializedValue = elementSerializer.serialize(element.value()); - } - catch ( final IOException e ) - { - log.error( "Problem serializing object.", e ); - throw e; - } - } - - return new CacheElementSerialized<>( - element.cacheName(), element.key(), serializedValue, element.elementAttributes() ); - } -} diff --git a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/utils/serialization/StandardSerializer.java b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/utils/serialization/StandardSerializer.java index 152f225d..9fd1b33b 100644 --- a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/utils/serialization/StandardSerializer.java +++ b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/utils/serialization/StandardSerializer.java @@ -48,6 +48,11 @@ public class StandardSerializer public <T> T deSerialize(final byte[] data, final ClassLoader loader) throws IOException, ClassNotFoundException { + if (data == null) + { + return null; + } + try (ByteArrayInputStream bais = new ByteArrayInputStream(data); ObjectInputStream ois = new ObjectInputStreamClassLoaderAware(bais, loader)) { diff --git a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/auxiliary/remote/RemoteCacheUnitTest.java b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/auxiliary/remote/RemoteCacheUnitTest.java index 16e80f22..0aeed4ec 100644 --- a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/auxiliary/remote/RemoteCacheUnitTest.java +++ b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/auxiliary/remote/RemoteCacheUnitTest.java @@ -32,7 +32,6 @@ import org.apache.commons.jcs4.engine.CacheElement; import org.apache.commons.jcs4.engine.ZombieCacheServiceNonLocal; import org.apache.commons.jcs4.engine.behavior.ICacheElement; import org.apache.commons.jcs4.engine.behavior.ICacheElementSerialized; -import org.apache.commons.jcs4.utils.serialization.SerializationConversionUtil; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -240,9 +239,8 @@ class RemoteCacheUnitTest // VERIFY assertInstanceOf( ICacheElementSerialized.class, service.lastUpdate, "The element should be in the serialized wrapper." ); - final ICacheElement<String, String> result = SerializationConversionUtil - .getDeSerializedCacheElement( (ICacheElementSerialized<String, String>) service.lastUpdate, remoteCache - .getElementSerializer() ); + final ICacheElement<String, String> result = remoteCache.getElementSerializer() + .getDeSerializedCacheElement((ICacheElementSerialized<String, String>) service.lastUpdate); assertEquals( element.value(), result.value(), "Wrong element updated." ); assertEquals( Long.valueOf( listenerId ), service.updateRequestIdList.get( 0 ), "Wrong listener id." ); } @@ -297,9 +295,8 @@ class RemoteCacheUnitTest // VERIFY assertInstanceOf( ICacheElementSerialized.class, service.lastUpdate, "The element should be in the serialized warapper." ); - final ICacheElement<String, String> result = SerializationConversionUtil - .getDeSerializedCacheElement( (ICacheElementSerialized<String, String>) service.lastUpdate, remoteCache - .getElementSerializer() ); + final ICacheElement<String, String> result = remoteCache.getElementSerializer() + .getDeSerializedCacheElement( (ICacheElementSerialized<String, String>) service.lastUpdate); assertEquals( element.value(), result.value(), "Wrong element updated." ); } } diff --git a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/utils/serialization/CompressingSerializerUnitTest.java b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/utils/serialization/CompressingSerializerUnitTest.java index e64a5761..9de78c84 100644 --- a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/utils/serialization/CompressingSerializerUnitTest.java +++ b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/utils/serialization/CompressingSerializerUnitTest.java @@ -19,12 +19,8 @@ package org.apache.commons.jcs4.utils.serialization; * under the License. */ -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; -import java.io.IOException; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -42,23 +38,6 @@ class CompressingSerializerUnitTest this.serializer = new CompressingSerializer(); } - /** - * Verify that we don't get any erorrs for null input. - * - * @throws ClassNotFoundException - * @throws IOException - */ - @Test - void testDeserialize_NullInput() - throws IOException, ClassNotFoundException - { - // DO WORK - final Object result = serializer.deSerialize( null, null ); - - // VERIFY - assertNull( result, "Should have nothing." ); - } - /** * Verify that the compressed is smaller. * @@ -85,42 +64,4 @@ class CompressingSerializerUnitTest "Compressed should be smaller. compressed size = " + compressed.length + "nonCompressed size = " + nonCompressed.length ); } - - /** - * Test serialization with a null object. Verify that we don't get an error. - * - * @throws Exception on error - */ - @Test - void testSerialize_NullInput() - throws Exception - { - final String before = null; - - // DO WORK - final byte[] serialized = serializer.serialize( before ); - final String after = (String) serializer.deSerialize( serialized, null ); - - // VERIFY - assertNull( after, "Should have nothing. after =" + after ); - } - - /** - * Test simple back and forth with a string. - * <p> - * ))<=>(( - * - * @throws Exception on error - */ - @Test - void testSimpleBackAndForth() - throws Exception - { - // DO WORK - final String before = "adsfdsafdsafdsafdsafdsafdsafdsagfdsafdsafdsfdsafdsafsa333 31231"; - final String after = (String) serializer.deSerialize( serializer.serialize( before ), null ); - - // VERIFY - assertEquals( before, after, "Before and after should be the same." ); - } } diff --git a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/utils/serialization/EncryptingSerializerUnitTest.java b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/utils/serialization/EncryptingSerializerUnitTest.java index 0f1892bd..817550c3 100644 --- a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/utils/serialization/EncryptingSerializerUnitTest.java +++ b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/utils/serialization/EncryptingSerializerUnitTest.java @@ -20,7 +20,6 @@ package org.apache.commons.jcs4.utils.serialization; */ import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; @@ -43,23 +42,6 @@ class EncryptingSerializerUnitTest this.serializer.setPreSharedKey("my_secret_key"); } - /** - * Verify that we don't get any errors for null input. - * - * @throws ClassNotFoundException - * @throws IOException - */ - @Test - void testDeserialize_NullInput() - throws IOException, ClassNotFoundException - { - // DO WORK - final Object result = serializer.deSerialize( null, null ); - - // VERIFY - assertNull( result, "Should have nothing." ); - } - /** * Test different key. * @@ -97,42 +79,4 @@ class EncryptingSerializerUnitTest // VERIFY assertEquals( before, after, "Before and after should be the same." ); } - - /** - * Test serialization with a null object. Verify that we don't get an error. - * - * @throws Exception on error - */ - @Test - void testSerialize_NullInput() - throws Exception - { - final String before = null; - - // DO WORK - final byte[] serialized = serializer.serialize( before ); - final String after = (String) serializer.deSerialize( serialized, null ); - - // VERIFY - assertNull( after, "Should have nothing. after =" + after ); - } - - /** - * Test simple back and forth with a string. - * <p> - * ))<=>(( - * - * @throws Exception on error - */ - @Test - void testSimpleBackAndForth() - throws Exception - { - // DO WORK - final String before = "adsfdsafdsafdsafdsafdsafdsafdsagfdsafdsafdsfdsafdsafsa333 31231"; - final String after = serializer.deSerialize( serializer.serialize( before ), null ); - - // VERIFY - assertEquals( before, after, "Before and after should be the same." ); - } } diff --git a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/utils/serialization/SerializationConversionUtilUnitTest.java b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/utils/serialization/SerializationConversionUtilUnitTest.java deleted file mode 100644 index 84070d2d..00000000 --- a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/utils/serialization/SerializationConversionUtilUnitTest.java +++ /dev/null @@ -1,200 +0,0 @@ -package org.apache.commons.jcs4.utils.serialization; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.fail; - -import java.io.IOException; -import java.time.Duration; - -import org.apache.commons.jcs4.engine.CacheElement; -import org.apache.commons.jcs4.engine.ElementAttributes; -import org.apache.commons.jcs4.engine.TestElementAttributes; -import org.apache.commons.jcs4.engine.behavior.ICacheElement; -import org.apache.commons.jcs4.engine.behavior.ICacheElementSerialized; -import org.apache.commons.jcs4.engine.behavior.IElementSerializer; -import org.junit.jupiter.api.Test; - -/** - * Tests the serialization conversion util. - */ -class SerializationConversionUtilUnitTest -{ - /** - * Verify that we can go back and forth with the simplest of objects. - * - * @throws Exception - */ - @Test - void testAccidentalDoubleConversion() - throws Exception - { - // SETUP - final String cacheName = "testName"; - final String key = "key"; - final String value = "value fdsadf dsafdsa fdsaf dsafdsaf dsafdsaf dsaf dsaf dsaf dsafa dsaf dsaf dsafdsaf"; - - final IElementSerializer elementSerializer = new StandardSerializer(); - final ElementAttributes attr = TestElementAttributes - .withEternalFalseAndMaxLife(Duration.ofSeconds(34)); - - final ICacheElement<String, String> before = new CacheElement<>(cacheName, key, - value, attr); - - // DO WORK - final ICacheElementSerialized<String, String> alreadySerialized = - SerializationConversionUtil.getSerializedCacheElement( before, elementSerializer ); - final ICacheElementSerialized<String, String> serialized = - SerializationConversionUtil.getSerializedCacheElement( alreadySerialized, elementSerializer ); - - // VERIFY - assertNotNull( serialized, "Should have a serialized object." ); - - // DO WORK - final ICacheElement<String, String> after = - SerializationConversionUtil.getDeSerializedCacheElement( serialized, elementSerializer ); - - // VERIFY - assertNotNull( after, "Should have a deserialized object." ); - assertEquals( before.value(), after.value(), "Values should be the same." ); - assertEquals( before.elementAttributes().MaxLife(), after - .elementAttributes().MaxLife(), "Attributes should be the same." ); - assertEquals( before.key(), after.key(), "Keys should be the same." ); - assertEquals( before.cacheName(), after.cacheName(), "Cache name should be the same." ); - } - - /** - * Verify null for null. - * - * @throws Exception - */ - @Test - void testgGetDeSerializedCacheElement_null() - throws Exception - { - // SETUP - final IElementSerializer elementSerializer = new StandardSerializer(); - final ICacheElementSerialized<String, String> before = null; - - // DO WORK - final ICacheElement<String, String> result = - SerializationConversionUtil.getDeSerializedCacheElement( before, elementSerializer ); - - // VERIFY - assertNull( result, "Should get null for null" ); - } - - /** - * Verify null for null. - * - * @throws IOException - */ - @Test - void testgGetSerializedCacheElement_null() - throws IOException - { - // SETUP - final IElementSerializer elementSerializer = new StandardSerializer(); - final ICacheElement<String, String> before = null; - - // DO WORK - final ICacheElementSerialized<String, String> result = - SerializationConversionUtil.getSerializedCacheElement( before, elementSerializer ); - - // VERIFY - assertNull( result, "Should get null for null" ); - } - - /** - * Verify that we get an IOException for a null serializer. - */ - @Test - void testNullSerializerConversion() - { - // SETUP - final String cacheName = "testName"; - final String key = "key"; - final String value = "value fdsadf dsafdsa fdsaf dsafdsaf dsafdsaf dsaf dsaf dsaf dsafa dsaf dsaf dsafdsaf"; - - final IElementSerializer elementSerializer = null; // new StandardSerializer(); - final ElementAttributes attr = TestElementAttributes - .withEternalFalseAndMaxLife(Duration.ofSeconds(34)); - - final ICacheElement<String, String> before = new CacheElement<>(cacheName, key, - value, attr); - - // DO WORK - try - { - SerializationConversionUtil.getSerializedCacheElement( before, elementSerializer ); - - // VERIFY - fail( "We should have received an IOException." ); - } - catch ( final IOException e ) - { - // expected - } - } - - /** - * Verify that we can go back and forth with the simplest of objects. - * - * @throws Exception - */ - @Test - void testSimpleConversion() - throws Exception - { - // SETUP - final String cacheName = "testName"; - final String key = "key"; - final String value = "value fdsadf dsafdsa fdsaf dsafdsaf dsafdsaf dsaf dsaf dsaf dsafa dsaf dsaf dsafdsaf"; - - final IElementSerializer elementSerializer = new StandardSerializer(); - final ElementAttributes attr = TestElementAttributes - .withEternalFalseAndMaxLife(Duration.ofSeconds(34)); - - final ICacheElement<String, String> before = new CacheElement<>(cacheName, key, - value, attr); - - // DO WORK - final ICacheElementSerialized<String, String> serialized = - SerializationConversionUtil.getSerializedCacheElement( before, elementSerializer ); - - // VERIFY - assertNotNull( serialized, "Should have a serialized object." ); - - // DO WORK - final ICacheElement<String, String> after = - SerializationConversionUtil.getDeSerializedCacheElement( serialized, elementSerializer ); - - // VERIFY - assertNotNull( after, "Should have a deserialized object." ); - assertEquals( before.value(), after.value(), "Values should be the same." ); - assertEquals( before.elementAttributes().MaxLife(), after - .elementAttributes().MaxLife(), "Attributes should be the same." ); - assertEquals( before.key(), after.key(), "Keys should be the same." ); - assertEquals( before.cacheName(), after.cacheName(), "Cache name should be the same." ); - } -} diff --git a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/utils/serialization/SerializerUnitTest.java b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/utils/serialization/SerializerUnitTest.java index ba32b2a5..e349b941 100644 --- a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/utils/serialization/SerializerUnitTest.java +++ b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/utils/serialization/SerializerUnitTest.java @@ -1,5 +1,7 @@ package org.apache.commons.jcs4.utils.serialization; +import static org.junit.jupiter.api.Assertions.assertEquals; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -20,12 +22,31 @@ package org.apache.commons.jcs4.utils.serialization; */ import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.io.IOException; +import java.io.Serializable; +import java.time.Duration; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.stream.Stream; import org.apache.commons.jcs4.JCS; import org.apache.commons.jcs4.access.CacheAccess; +import org.apache.commons.jcs4.engine.CacheElement; +import org.apache.commons.jcs4.engine.ElementAttributes; +import org.apache.commons.jcs4.engine.TestElementAttributes; +import org.apache.commons.jcs4.engine.behavior.ICacheElement; +import org.apache.commons.jcs4.engine.behavior.ICacheElementSerialized; +import org.apache.commons.jcs4.engine.behavior.IElementSerializer; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; /** * Verify that serializer functionality works. @@ -52,81 +73,327 @@ class SerializerUnitTest } /** - * Verify that object reading and writing with CompressingSerializer works + * Verify that object reading and writing with different IElementSerializer implementations works * * @throws Exception */ - @Test - public void testReadWriteCompressingSerializer() + @ParameterizedTest + @ValueSource(strings = {"blockRegion1", "blockRegion2", "blockRegion3"}) + public void testReadWriteSerializer(String cacheRegion) throws Exception { - // CompressingSerializer - final CacheAccess<String, String> jcs = JCS.getInstance( "blockRegion1" ); + final CacheAccess<String, String> jcs = JCS.getInstance(cacheRegion); + final int count = 500; // 100 fit in memory + + for ( int i = 0; i < count; i++ ) + { + jcs.put( "key:" + i, "data" + i ); + } + + for ( int i = 0; i < count; i++ ) + { + final String res = jcs.get( "key:" + i ); + assertNotNull( res, "[key:" + i + "] should not be null, " + jcs.getStatistics() ); + } - testReadWrite(jcs); + Thread.sleep(500); // Give some time to empty the write queue + JCS.shutdown(); + + // Re-init + final CacheAccess<String, String> jcs2 = JCS.getInstance(cacheRegion); + + for ( int i = 0; i < count; i++ ) + { + final String res = jcs2.get( "key:" + i ); + assertNotNull( res, "[key:" + i + "] should not be null, " + jcs2.getStatistics() ); + } + } + + private static Stream<Arguments> provideSerializer() { + + StandardSerializer stdSerializer = new StandardSerializer(); + CompressingSerializer compressingSerializer = new CompressingSerializer(); + EncryptingSerializer encryptingSerializer = new EncryptingSerializer(); + encryptingSerializer.setPreSharedKey("my_secret_key"); + JSONSerializer jsonSerializer = new JSONSerializer(); + + return Stream.of( + Arguments.of(stdSerializer), + Arguments.of(compressingSerializer), + Arguments.of(encryptingSerializer), + Arguments.of(jsonSerializer) + ); } /** - * Verify that object reading and writing with EncryptingSerializer works + * Test serialization with a null object. Verify that we don't get an error. * + * @param serializer the serializer object * @throws Exception */ - @Test - public void testReadWriteEncryptingSerializer() + @ParameterizedTest + @MethodSource("provideSerializer") + void testNullInput(IElementSerializer serializer) throws Exception { - // EncryptingSerializer - final CacheAccess<String, String> jcs1 = JCS.getInstance( "blockRegion2" ); + final String before = null; - testReadWrite(jcs1); + // DO WORK + final byte[] serialized = serializer.serialize( before ); + //System.out.println( "testNullInput " + serialized ); - JCS.shutdown(); + final String after = serializer.deSerialize( serialized, null ); + //System.out.println( "testNullInput " + after ); - // Re-init - // EncryptingSerializer - final CacheAccess<String, String> jcs2 = JCS.getInstance( "blockRegion2" ); + // VERIFY + assertNull( after, "Should have nothing." ); + } + + /** + * Verify that we don't get any errors for null input. + * + * @param serializer the serializer object + * @throws ClassNotFoundException + * @throws IOException + */ + @ParameterizedTest + @MethodSource("provideSerializer") + void testDeserialize_NullInput(IElementSerializer serializer) + throws IOException, ClassNotFoundException + { + // DO WORK + final Object result = serializer.deSerialize( null, null ); + + // VERIFY + assertNull( result, "Should have nothing." ); + } + + /** + * Test simple back and forth with a string. + * <p> + * ))<=>(( + * + * @param serializer the serializer object + * @throws Exception on error + */ + @ParameterizedTest + @MethodSource("provideSerializer") + void testSimpleBackAndForth(IElementSerializer serializer) + throws Exception + { + // DO WORK + final String before = "adsfdsafdsafdsafdsafdsafdsafdsagfdsafdsafdsfdsafdsafsa333 31231"; + final String after = (String) serializer.deSerialize( serializer.serialize( before ), null ); - for ( int i = 0; i < 500; i++ ) + // VERIFY + assertEquals( before, after, "Before and after should be the same." ); + } + + /** + * Test simple back and forth with a string. + * + * @param serializer the serializer object + * @throws Exception + */ + @ParameterizedTest + @MethodSource("provideSerializer") + void testBigStringBackAndForth(IElementSerializer serializer) + throws Exception + { + final String string = "This is my big string ABCDEFGH"; + final StringBuilder sb = new StringBuilder(); + sb.append( string ); + for ( int i = 0; i < 4; i++ ) { - final String res = jcs2.get( "key:" + i ); - assertNotNull( res, "[key:" + i + "] should not be null, " + jcs2.getStatistics() ); + sb.append( " " + i + sb.toString() ); // big string } + final String before = sb.toString(); + + // DO WORK + final String after = (String) serializer.deSerialize( serializer.serialize( before ), null ); + + // VERIFY + assertEquals( before, after, "Before and after should be the same." ); } + public static record Person(String name, int age, Date birthdate) implements Serializable {} + /** - * Verify that object reading and writing with JSONSerializer works + * Test simple back and forth with an object. + * + * @param serializer the serializer object + * @throws Exception + */ + @ParameterizedTest + @MethodSource("provideSerializer") + void testObjectBackAndForth(IElementSerializer serializer) + throws Exception + { + Date date = new GregorianCalendar(1977, Calendar.DECEMBER, 15).getTime(); + final Person before = new Person("joe", 21, date); + + // DO WORK + byte[] serialized = serializer.serialize(before); + // System.out.println(new String(serialized, StandardCharsets.UTF_8)); + final Person after = serializer.deSerialize(serialized, null); + + // VERIFY + assertEquals(before.name(), after.name(), "Before and after should be the same."); + assertEquals(before.age(), after.age(), "Before and after should be the same."); + assertEquals(before.birthdate(), after.birthdate(), "Before and after should be the same."); + } + + /** + * Test CacheElement back and forth. + * + * @param serializer the serializer object + * @throws Exception + */ + @ParameterizedTest + @MethodSource("provideSerializer") + void testCacheElementBackAndForth(IElementSerializer serializer) + throws Exception + { + final CacheElement<Integer, Person> before = new CacheElement<>("testCache", Integer.valueOf(4), + new Person("joe", 21, new GregorianCalendar(1977, Calendar.DECEMBER, 15).getTime()), + new ElementAttributes(false, true, false, true, Duration.ofMinutes(2), Duration.ofSeconds(65))); + + // DO WORK + byte[] serialized = serializer.serialize(before); + final CacheElement<Integer, Person> after = serializer.deSerialize(serialized, null); + + // VERIFY + assertEquals(before.cacheName(), after.cacheName(), "Before and after should be the same."); + assertEquals(before.key(), after.key(), "Before and after should be the same."); + assertEquals(before.value(), after.value(), "Before and after should be the same."); + assertEquals(before.elementAttributes().IsSpool(), after.elementAttributes().IsSpool(), "Before and after should be the same."); + assertEquals(before.elementAttributes().IsLateral(), after.elementAttributes().IsLateral(), "Before and after should be the same."); + assertEquals(before.elementAttributes().IsRemote(), after.elementAttributes().IsRemote(), "Before and after should be the same."); + assertEquals(before.elementAttributes().IsEternal(), after.elementAttributes().IsEternal(), "Before and after should be the same."); + assertEquals(before.elementAttributes().MaxLife(), after.elementAttributes().MaxLife(), "Before and after should be the same."); + assertEquals(before.elementAttributes().MaxIdleTime(), after.elementAttributes().MaxIdleTime(), "Before and after should be the same."); + } + + /** + * Verify that we can go back and forth with the simplest of objects. * * @throws Exception */ @Test - public void testReadWriteJSONSerializer() + void testAccidentalDoubleConversion() throws Exception { - // JSONSerializer - final CacheAccess<String, String> jcs = JCS.getInstance( "blockRegion3" ); + // SETUP + final String cacheName = "testName"; + final String key = "key"; + final String value = "value fdsadf dsafdsa fdsaf dsafdsaf dsafdsaf dsaf dsaf dsaf dsafa dsaf dsaf dsafdsaf"; + + final IElementSerializer elementSerializer = new StandardSerializer(); + final ElementAttributes attr = TestElementAttributes + .withEternalFalseAndMaxLife(Duration.ofSeconds(34)); + + final ICacheElement<String, String> before = new CacheElement<>(cacheName, key, + value, attr); + + // DO WORK + final ICacheElementSerialized<String, String> alreadySerialized = + elementSerializer.getSerializedCacheElement(before); + final ICacheElementSerialized<String, String> serialized = + elementSerializer.getSerializedCacheElement(alreadySerialized); + + // VERIFY + assertNotNull(serialized, "Should have a serialized object."); - testReadWrite(jcs); + // DO WORK + final ICacheElement<String, String> after = elementSerializer.getDeSerializedCacheElement(serialized); + + // VERIFY + assertNotNull( after, "Should have a deserialized object." ); + assertEquals( before.value(), after.value(), "Values should be the same." ); + assertEquals( before.elementAttributes().MaxLife(), after + .elementAttributes().MaxLife(), "Attributes should be the same." ); + assertEquals( before.key(), after.key(), "Keys should be the same." ); + assertEquals( before.cacheName(), after.cacheName(), "Cache name should be the same." ); } /** - * Verify that object reading and writing works + * Verify null for null. * * @throws Exception */ - private void testReadWrite(CacheAccess<String, String> jcs) + @Test + void testGetDeSerializedCacheElement_null() throws Exception { - final int count = 500; // 100 fit in memory + // SETUP + final IElementSerializer elementSerializer = new StandardSerializer(); + final ICacheElementSerialized<String, String> before = null; - for ( int i = 0; i < count; i++ ) - { - jcs.put( "key:" + i, "data" + i ); - } + // DO WORK + final ICacheElement<String, String> result = elementSerializer.getDeSerializedCacheElement(before); - for ( int i = 0; i < count; i++ ) - { - final String res = jcs.get( "key:" + i ); - assertNotNull( res, "[key:" + i + "] should not be null, " + jcs.getStatistics() ); - } + // VERIFY + assertNull( result, "Should get null for null" ); + } + + /** + * Verify null for null. + * + * @throws IOException + */ + @Test + void testgGetSerializedCacheElement_null() + throws IOException + { + // SETUP + final IElementSerializer elementSerializer = new StandardSerializer(); + final ICacheElement<String, String> before = null; + + // DO WORK + final ICacheElementSerialized<String, String> result = elementSerializer.getSerializedCacheElement(before); + + // VERIFY + assertNull( result, "Should get null for null" ); + } + + /** + * Verify that we can go back and forth with the simplest of objects. + * + * @throws Exception + */ + @Test + void testSimpleConversion() + throws Exception + { + // SETUP + final String cacheName = "testName"; + final String key = "key"; + final String value = "value fdsadf dsafdsa fdsaf dsafdsaf dsafdsaf dsaf dsaf dsaf dsafa dsaf dsaf dsafdsaf"; + + final IElementSerializer elementSerializer = new StandardSerializer(); + final ElementAttributes attr = TestElementAttributes + .withEternalFalseAndMaxLife(Duration.ofSeconds(34)); + + final ICacheElement<String, String> before = new CacheElement<>(cacheName, key, + value, attr); + + // DO WORK + final ICacheElementSerialized<String, String> serialized = + elementSerializer.getSerializedCacheElement(before); + + // VERIFY + assertNotNull( serialized, "Should have a serialized object." ); + + // DO WORK + final ICacheElement<String, String> after = + elementSerializer.getDeSerializedCacheElement(serialized); + + // VERIFY + assertNotNull( after, "Should have a deserialized object." ); + assertEquals( before.value(), after.value(), "Values should be the same." ); + assertEquals( before.elementAttributes().MaxLife(), after + .elementAttributes().MaxLife(), "Attributes should be the same." ); + assertEquals( before.key(), after.key(), "Keys should be the same." ); + assertEquals( before.cacheName(), after.cacheName(), "Cache name should be the same." ); } } diff --git a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/utils/serialization/StandardSerializerUnitTest.java b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/utils/serialization/StandardSerializerUnitTest.java index 8b5aa00f..07252997 100644 --- a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/utils/serialization/StandardSerializerUnitTest.java +++ b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/utils/serialization/StandardSerializerUnitTest.java @@ -19,8 +19,6 @@ package org.apache.commons.jcs4.utils.serialization; * under the License. */ -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.ByteArrayInputStream; @@ -29,7 +27,7 @@ import java.io.InvalidClassException; import java.io.StreamCorruptedException; import java.nio.ByteBuffer; -import org.apache.commons.collections4.bag.HashBag; +import org.apache.commons.collections4.multiset.HashMultiSet; import org.apache.commons.jcs4.io.ObjectInputStreamClassLoaderAware; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -50,77 +48,12 @@ class StandardSerializerUnitTest void setUp() throws Exception { - // Override filter expression for ObjectInputFilter + // Override filter expression for ObjectInputFilter System.setProperty(ObjectInputStreamClassLoaderAware.SYSTEM_PROPERTY_SERIALIZATION_FILTER, "!org.apache.commons.collections4.**"); this.serializer = new StandardSerializer(); } - /** - * Test simple back and forth with a string. - * - * @throws Exception - */ - @Test - void testBigStringBackAndForth() - throws Exception - { - final String string = "This is my big string ABCDEFGH"; - final StringBuilder sb = new StringBuilder(); - sb.append( string ); - for ( int i = 0; i < 4; i++ ) - { - sb.append( " " + i + sb.toString() ); // big string - } - final String before = sb.toString(); - - // DO WORK - final String after = (String) serializer.deSerialize( serializer.serialize( before ), null ); - - // VERIFY - assertEquals( before, after, "Before and after should be the same." ); - } - - /** - * Test serialization with a null object. Verify that we don't get an error. - * - * @throws Exception - */ - @Test - void testNullInput() - throws Exception - { - final String before = null; - - // DO WORK - final byte[] serialized = serializer.serialize( before ); - //System.out.println( "testNullInput " + serialized ); - - final String after = (String) serializer.deSerialize( serialized, null ); - //System.out.println( "testNullInput " + after ); - - // VERIFY - assertNull( after, "Should have nothing." ); - } - - /** - * Test simple back and forth with a string. - * - * @throws Exception - */ - @Test - void testSimpleBackAndForth() - throws Exception - { - final String before = "adsfdsafdsafdsafdsafdsafdsafdsagfdsafdsafdsfdsafdsafsa333 31231"; - - // DO WORK - final String after = (String) serializer.deSerialize( serializer.serialize( before ), null ); - - // VERIFY - assertEquals( before, after, "Before and after should be the same." ); - } - /** * Verify that we can filter classes to be deserialized * @@ -131,9 +64,9 @@ class StandardSerializerUnitTest throws IOException { // DO WORK - final byte[] serialized = serializer.serialize( new HashBag<String>() ); // forbidden class + final byte[] serialized = serializer.serialize(new HashMultiSet<String>()); // forbidden class - assertThrows(InvalidClassException.class, () -> serializer.deSerialize( serialized, null )); + assertThrows(InvalidClassException.class, () -> serializer.deSerialize(serialized, null)); } /**
