You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by jo...@apache.org on 2006/01/18 21:39:19 UTC

svn commit: r370252 - in /jakarta/commons/sandbox/id/trunk: ./ src/java/org/apache/commons/id/random/ src/test-serialization/ src/test-serialization/org.apache.commons.id.random.SessionIdGenerator/ src/test-serialization/org.apache.commons.id.serial.Ti...

Author: joehni
Date: Wed Jan 18 12:39:03 2006
New Revision: 370252

URL: http://svn.apache.org/viewcvs?rev=370252&view=rev
Log:
Add serialization test suite.
Add serialization support for SessionIdGenerator and TimeBasedAlphanumericIdGenerator.

Added:
    jakarta/commons/sandbox/id/trunk/src/test-serialization/
    jakarta/commons/sandbox/id/trunk/src/test-serialization/org.apache.commons.id.random.SessionIdGenerator/
    jakarta/commons/sandbox/id/trunk/src/test-serialization/org.apache.commons.id.random.SessionIdGenerator/20060118.ser   (with props)
    jakarta/commons/sandbox/id/trunk/src/test-serialization/org.apache.commons.id.serial.TimeBasedAlphanumericIdentifierGenerator/
    jakarta/commons/sandbox/id/trunk/src/test-serialization/org.apache.commons.id.serial.TimeBasedAlphanumericIdentifierGenerator/20060116.ser   (with props)
    jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/SerializationTestContext.java   (with props)
Modified:
    jakarta/commons/sandbox/id/trunk/project.xml
    jakarta/commons/sandbox/id/trunk/src/java/org/apache/commons/id/random/SessionIdGenerator.java
    jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/random/SessionIdGeneratorTest.java
    jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/serial/TimeBasedAlphanumericIdentifierGeneratorTest.java
    jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/test/AssertSerialization.java

Modified: jakarta/commons/sandbox/id/trunk/project.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/id/trunk/project.xml?rev=370252&r1=370251&r2=370252&view=diff
==============================================================================
--- jakarta/commons/sandbox/id/trunk/project.xml (original)
+++ jakarta/commons/sandbox/id/trunk/project.xml Wed Jan 18 12:39:03 2006
@@ -172,7 +172,7 @@
     <unitTestSourceDirectory>src/test</unitTestSourceDirectory>
     <unitTest>
       <includes>
-        <include>**/*Test*</include>
+        <include>**/*Test.*</include>
       </includes>
       <resources>
         <resource>

Modified: jakarta/commons/sandbox/id/trunk/src/java/org/apache/commons/id/random/SessionIdGenerator.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/id/trunk/src/java/org/apache/commons/id/random/SessionIdGenerator.java?rev=370252&r1=370251&r2=370252&view=diff
==============================================================================
--- jakarta/commons/sandbox/id/trunk/src/java/org/apache/commons/id/random/SessionIdGenerator.java (original)
+++ jakarta/commons/sandbox/id/trunk/src/java/org/apache/commons/id/random/SessionIdGenerator.java Wed Jan 18 12:39:03 2006
@@ -18,6 +18,7 @@
 
 import org.apache.commons.id.AbstractStringIdentifierGenerator;
 
+import java.io.Serializable;
 import java.util.Random;
 
 /**
@@ -34,8 +35,12 @@
  * @author Commons-Id team
  * @version $Id$
  */
-public class SessionIdGenerator extends AbstractStringIdentifierGenerator {
+public class SessionIdGenerator extends AbstractStringIdentifierGenerator implements Serializable {
 
+    /**
+     * <code>serialVersionUID</code> is the serializable UID for the binary version of the class.
+     */
+    private static final long serialVersionUID = 20060118L;
     /**
      * We want to have a random string with a length of 6 characters.
      * Since we encode it base-36, we modulo the random number with

Added: jakarta/commons/sandbox/id/trunk/src/test-serialization/org.apache.commons.id.random.SessionIdGenerator/20060118.ser
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/id/trunk/src/test-serialization/org.apache.commons.id.random.SessionIdGenerator/20060118.ser?rev=370252&view=auto
==============================================================================
Binary file - no diff available.

Propchange: jakarta/commons/sandbox/id/trunk/src/test-serialization/org.apache.commons.id.random.SessionIdGenerator/20060118.ser
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: jakarta/commons/sandbox/id/trunk/src/test-serialization/org.apache.commons.id.serial.TimeBasedAlphanumericIdentifierGenerator/20060116.ser
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/id/trunk/src/test-serialization/org.apache.commons.id.serial.TimeBasedAlphanumericIdentifierGenerator/20060116.ser?rev=370252&view=auto
==============================================================================
Binary file - no diff available.

Propchange: jakarta/commons/sandbox/id/trunk/src/test-serialization/org.apache.commons.id.serial.TimeBasedAlphanumericIdentifierGenerator/20060116.ser
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/SerializationTestContext.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/SerializationTestContext.java?rev=370252&view=auto
==============================================================================
--- jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/SerializationTestContext.java (added)
+++ jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/SerializationTestContext.java Wed Jan 18 12:39:03 2006
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.id;
+
+import org.apache.commons.id.test.AssertSerialization;
+
+import java.io.File;
+
+
+/**
+ * Helper class to provide the context to test serialization compatibility of a type.
+ * 
+ * @author Commons-Id team
+ * @version $Id$
+ */
+public abstract class SerializationTestContext implements AssertSerialization.Context {
+
+    public static final File SERIALIZATION_REFERENCE_DIR = new File("src/test-serialization");
+
+    public File getReferenceBaseDir() {
+        return SERIALIZATION_REFERENCE_DIR;
+    }
+}

Propchange: jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/SerializationTestContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/SerializationTestContext.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Modified: jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/random/SessionIdGeneratorTest.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/random/SessionIdGeneratorTest.java?rev=370252&r1=370251&r2=370252&view=diff
==============================================================================
--- jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/random/SessionIdGeneratorTest.java (original)
+++ jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/random/SessionIdGeneratorTest.java Wed Jan 18 12:39:03 2006
@@ -16,9 +16,13 @@
 package org.apache.commons.id.random;
 
 import junit.framework.TestCase;
+import junit.framework.TestSuite;
 
+import org.apache.commons.id.SerializationTestContext;
 import org.apache.commons.id.StringIdentifierGenerator;
+import org.apache.commons.id.test.AssertSerialization;
 
+import java.io.Serializable;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -41,5 +45,32 @@
             }
         }
         assertEquals(generators.length*generators.length, set.size());
+    }
+    
+    /**
+     * {@link TestSuite} for SessionIdGenerator. Ensures serialization.
+     * 
+     * @return the TestSuite
+     */
+    public static TestSuite suite() {
+        final TestSuite suite = new TestSuite(SessionIdGeneratorTest.class);
+        suite.addTest(AssertSerialization.createSerializationTestSuite(new SerializationTestContext() {
+
+            public void verify(Object serialized, long uid) {
+                SessionIdGenerator test = (SessionIdGenerator)serialized;
+                SessionIdGenerator idGenerator = (SessionIdGenerator)createReference();
+                assertEquals(idGenerator.maxLength(), test.maxLength());
+                assertEquals(idGenerator.minLength(), test.minLength());
+            }
+
+            public Serializable createReference() {
+                return new SessionIdGenerator();
+            }
+
+            public Class getType() {
+                return SessionIdGenerator.class;
+            }
+        }));
+        return suite;
     }
 }

Modified: jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/serial/TimeBasedAlphanumericIdentifierGeneratorTest.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/serial/TimeBasedAlphanumericIdentifierGeneratorTest.java?rev=370252&r1=370251&r2=370252&view=diff
==============================================================================
--- jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/serial/TimeBasedAlphanumericIdentifierGeneratorTest.java (original)
+++ jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/serial/TimeBasedAlphanumericIdentifierGeneratorTest.java Wed Jan 18 12:39:03 2006
@@ -15,6 +15,15 @@
  */
 package org.apache.commons.id.serial;
 
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.commons.id.IdentifierGenerator;
+import org.apache.commons.id.SerializationTestContext;
+import org.apache.commons.id.StringIdentifierGenerator;
+import org.apache.commons.id.test.AssertSerialization;
+
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
@@ -24,12 +33,6 @@
 import java.util.List;
 import java.util.TimeZone;
 
-import org.apache.commons.id.IdentifierGenerator;
-import org.apache.commons.id.StringIdentifierGenerator;
-import org.apache.commons.id.test.AssertSerialization;
-
-import junit.framework.TestCase;
-
 
 /**
  * @author Commons-Uid team
@@ -224,14 +227,29 @@
     }
 
     /**
-     * Test serializability.
-     */
-    public void testSerializable() {
-        TimeBasedAlphanumericIdentifierGenerator idGenerator = new TimeBasedAlphanumericIdentifierGenerator(
-                1);
-        TimeBasedAlphanumericIdentifierGenerator serialized = (TimeBasedAlphanumericIdentifierGenerator)AssertSerialization
-                .assertSerializable(idGenerator);
-        assertEquals(idGenerator.maxLength(), serialized.maxLength());
-        assertEquals(idGenerator.minLength(), serialized.minLength());
+     * {@link TestSuite} for TimeBasedAlphanumericIdentifierGenerator. Ensures serialization.
+     * 
+     * @return the TestSuite
+     */
+    public static TestSuite suite() {
+        final TestSuite suite = new TestSuite(TimeBasedAlphanumericIdentifierGeneratorTest.class);
+        suite.addTest(AssertSerialization.createSerializationTestSuite(new SerializationTestContext() {
+
+            public void verify(Object serialized, long uid) {
+                TimeBasedAlphanumericIdentifierGenerator test = (TimeBasedAlphanumericIdentifierGenerator)serialized;
+                TimeBasedAlphanumericIdentifierGenerator idGenerator = (TimeBasedAlphanumericIdentifierGenerator)createReference();
+                assertEquals(idGenerator.maxLength(), test.maxLength());
+                assertEquals(idGenerator.minLength(), test.minLength());
+            }
+
+            public Serializable createReference() {
+                return new TimeBasedAlphanumericIdentifierGenerator(1);
+            }
+
+            public Class getType() {
+                return TimeBasedAlphanumericIdentifierGenerator.class;
+            }
+        }));
+        return suite;
     }
 }

Modified: jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/test/AssertSerialization.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/test/AssertSerialization.java?rev=370252&r1=370251&r2=370252&view=diff
==============================================================================
--- jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/test/AssertSerialization.java (original)
+++ jakarta/commons/sandbox/id/trunk/src/test/org/apache/commons/id/test/AssertSerialization.java Wed Jan 18 12:39:03 2006
@@ -17,11 +17,21 @@
 
 import junit.framework.Assert;
 import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InvalidClassException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
 import java.io.Serializable;
 
 
@@ -43,7 +53,7 @@
      * @return the serialized object
      * @since 1.0
      */
-    public static Object assertSerializable(final Serializable serializable) {
+    public static Serializable assertSerializable(final Serializable serializable) {
         return assertSerializable(null, serializable);
     }
 
@@ -55,7 +65,8 @@
      * @return the serialized object
      * @since 1.0
      */
-    public static Object assertSerializable(final String message, final Serializable serializable) {
+    public static Serializable assertSerializable(
+            final String message, final Serializable serializable) {
         return assertSerializable(message, serializable, serializable.getClass());
     }
 
@@ -67,7 +78,7 @@
      * @return the serialized object
      * @since 1.0
      */
-    public static Object assertSerializable(
+    public static Serializable assertSerializable(
             final Serializable serializable, final Class expectedType) {
         return assertSerializable(null, serializable, expectedType);
     }
@@ -81,18 +92,35 @@
      * @return the serialized object
      * @since 1.0
      */
-    public static Object assertSerializable(
+    public static Serializable assertSerializable(
             String message, final Serializable serializable, final Class expectedType) {
         message = message != null ? message + ": " : "";
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        return assertSerializable(baos, message, serializable, expectedType);
+    }
+
+    /**
+     * Assert an object to be {@linkplain Serializable}.
+     * 
+     * @param baos the {@link ByteArrayOutputStream} with the serialized reference object
+     * @param message the error message
+     * @param serializable object to serialize
+     * @param expectedType the expected type of the result
+     * @return the serialized object
+     * @since 1.0
+     */
+    private static Serializable assertSerializable(
+            final ByteArrayOutputStream baos, String message, final Serializable serializable,
+            final Class expectedType) {
+        message = message != null ? message + ": " : "";
         try {
-            final ByteArrayOutputStream baos = new ByteArrayOutputStream();
             final ObjectOutputStream oos = new ObjectOutputStream(baos);
             oos.writeObject(serializable);
             oos.close();
 
             final ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
             final ObjectInputStream ois = new ObjectInputStream(bais);
-            final Object serialized = ois.readObject();
+            final Serializable serialized = (Serializable)ois.readObject();
             ois.close();
             Assert.assertNotNull(message + "Serialized object is null", serialized);
             Assert.assertSame(
@@ -102,5 +130,215 @@
         } catch (final Exception e) {
             throw new AssertionFailedError(message + e.getMessage());
         }
+    }
+
+    /**
+     * Interface for the serialization test context.
+     * 
+     * @author J&ouml;rg Schaible
+     * @since 1.0
+     */
+    public static interface Context {
+
+        /**
+         * Verify the (de-)serialized object. Test the object with appropriate assert methods and
+         * try to check all members, especially newly added.
+         * 
+         * @param serialized the object itself
+         * @param uid the <code>serialVersionUID</code> of the deserialized object
+         * @since 1.0
+         */
+        void verify(Object serialized, long uid);
+
+        /**
+         * Create a reference object of the class to serialize.
+         * 
+         * @return the reference object
+         * @since 1.0
+         */
+        Serializable createReference();
+
+        /**
+         * Retrieve the base directory for the serialized object files. Each type has an own
+         * directory that contains files with serialized compatible object of that type, but
+         * different <code>serialVersionUID</code>. This id is used for the filename.
+         * 
+         * @return the base directory
+         * @since 1.0
+         */
+        File getReferenceBaseDir();
+
+        /**
+         * Retrieve the type of the serialized class.
+         * 
+         * @return the type
+         * @since 1.0
+         */
+        Class getType();
+    }
+
+    /**
+     * A test case used to test the serialization capability and the compatibility with previous
+     * versions of the type. Instances of the class are internally generated.
+     * 
+     * @author J&ouml;rg Schaible
+     * @since 1.0
+     */
+    public static class SerializationTest extends TestCase {
+        private final Context context;
+        private final ByteArrayOutputStream baos;
+
+        private SerializationTest(final String name, final Context context) {
+            super(name);
+            this.context = context;
+            this.baos = new ByteArrayOutputStream();
+        }
+
+        /**
+         * Test the serializability of the object.
+         */
+        public void testSerialization() {
+            final Class type = context.getType();
+            final ObjectStreamClass osc = ObjectStreamClass.lookup(type);
+            assertNotNull(type.getName() + " is not serializable", osc);
+            final Serializable reference = context.createReference();
+            assertNotNull("No reference object for " + type.getName() + " retrieved", reference);
+            final Serializable serialized = assertSerializable(baos, "", reference, type);
+            context.verify(serialized, osc.getSerialVersionUID());
+
+            createReferenceFile(osc);
+        }
+
+        private void createReferenceFile(final ObjectStreamClass osc) {
+            final File referenceDir = context.getReferenceBaseDir();
+            final File referenceFile = new File(new File(referenceDir, osc.getName()), Long
+                    .toString(osc.getSerialVersionUID())
+                    + ".ser");
+            if (!referenceFile.isFile()) {
+                if (!referenceDir.isDirectory()) {
+                    throw new AssertionFailedError("Missing serialization reference directory: "
+                            + referenceDir.getAbsolutePath());
+                }
+                if (!referenceFile.getParentFile().isDirectory()) {
+                    referenceFile.getParentFile().mkdir();
+                }
+                try {
+                    try {
+                        final FileOutputStream out = new FileOutputStream(referenceFile);
+                        try {
+                            out.write(baos.toByteArray());
+                        } catch (final IOException e) {
+                            throw new AssertionFailedError("Cannot write missing reference file "
+                                    + referenceFile.getAbsolutePath()
+                                    + ". "
+                                    + e.getMessage());
+                        } finally {
+                            out.close();
+                        }
+                    } catch (final FileNotFoundException e) {
+                        throw new AssertionFailedError("Cannot create missing reference file "
+                                + referenceFile.getAbsolutePath()
+                                + ". "
+                                + e.getMessage());
+                    } catch (final IOException e) {
+                        throw new AssertionFailedError("Cannot close missing reference file "
+                                + referenceFile.getAbsolutePath()
+                                + ". "
+                                + e.getMessage());
+                    }
+
+                } catch (final AssertionFailedError e) {
+                    if (referenceFile.exists()) {
+                        referenceFile.delete();
+                    }
+                    throw e;
+                }
+                throw new AssertionFailedError("Missing reference file "
+                        + referenceFile.getAbsolutePath()
+                        + " created.");
+            }
+        }
+
+        /**
+         * Test the compatibility with a version of the type.
+         * 
+         * @param filename the filename of the file with the serialized object
+         */
+        public void checkCompatibility(final String filename) {
+            final Class type = context.getType();
+            final ObjectStreamClass osc = ObjectStreamClass.lookup(type);
+            assertNotNull(type.getName() + " is not serializable", osc);
+
+            final File referenceDir = new File(context.getReferenceBaseDir(), type.getName());
+            if (referenceDir.isDirectory()) {
+                final File file = new File(referenceDir, filename);
+                try {
+                    final ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
+                    final Serializable serialized = (Serializable)ois.readObject();
+                    context.verify(serialized, osc.getSerialVersionUID());
+                } catch (final FileNotFoundException e) {
+                    throw new AssertionFailedError("Missing reference file "
+                            + file.getAbsolutePath()
+                            + ". "
+                            + e.getMessage());
+                } catch (final InvalidClassException e) {
+                    throw new AssertionFailedError("Cannot load object from reference file "
+                            + file.getAbsolutePath()
+                            + ". Adjust class implementation. "
+                            + e.getMessage());
+                } catch (final IOException e) {
+                    throw new AssertionFailedError("Cannot read from reference file "
+                            + file.getAbsolutePath()
+                            + ". "
+                            + e.getMessage());
+                } catch (final ClassNotFoundException e) {
+                    throw new AssertionFailedError("Class of reference file "
+                            + file.getAbsolutePath()
+                            + " not found. "
+                            + e.getMessage());
+                }
+            }
+        }
+
+        protected void runTest() throws Throwable {
+            final String name = getName();
+            if (name.endsWith(".ser")) {
+                checkCompatibility(name);
+            } else {
+                super.runTest();
+            }
+        }
+    }
+
+    /**
+     * Create a {@link TestSuite} for the serializability of a type. A caller must provide a proper
+     * {@link Context}, that enables the suite to test the serializability of the provided type and
+     * ensures backward compatibility for older versions of the type. For each type version a file
+     * is provided with the <code>serialVersionUID</code> as filename in a directory named like
+     * the type to test. If no reference file is stored in the reference DB, the test fails, but the
+     * file is created automatically, so the next run will succeed.
+     * 
+     * @param context the test Context
+     * @return the TestSuite with the tests
+     * @since 1.0
+     */
+    public static TestSuite createSerializationTestSuite(final Context context) {
+        final TestSuite suite = new TestSuite("Serialization Tests");
+        suite.addTest(new SerializationTest("testSerialization", context));
+
+        final Class type = context.getType();
+        final File referenceDir = new File(context.getReferenceBaseDir(), type.getName());
+        if (referenceDir.isDirectory()) {
+            final File[] files = referenceDir.listFiles(new FilenameFilter() {
+                public boolean accept(final File dir, final String name) {
+                    return name.endsWith(".ser");
+                }
+            });
+            for (int i = 0; i < files.length; i++) {
+                suite.addTest(new SerializationTest(files[i].getName(), context));
+            }
+        }
+
+        return suite;
     }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org