001    /*
002     *  Copyright 2001-2005 Stephen Colebourne
003     *
004     *  Licensed under the Apache License, Version 2.0 (the "License");
005     *  you may not use this file except in compliance with the License.
006     *  You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     *  Unless required by applicable law or agreed to in writing, software
011     *  distributed under the License is distributed on an "AS IS" BASIS,
012     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     *  See the License for the specific language governing permissions and
014     *  limitations under the License.
015     */
016    package org.joda.time;
017    
018    import java.io.ByteArrayInputStream;
019    import java.io.ByteArrayOutputStream;
020    import java.io.FileInputStream;
021    import java.io.FileOutputStream;
022    import java.io.ObjectInputStream;
023    import java.io.ObjectOutputStream;
024    import java.io.Serializable;
025    import java.util.Locale;
026    import java.util.TimeZone;
027    
028    import junit.framework.TestCase;
029    import junit.framework.TestSuite;
030    
031    import org.joda.time.chrono.BuddhistChronology;
032    import org.joda.time.chrono.CopticChronology;
033    import org.joda.time.chrono.GJChronology;
034    import org.joda.time.chrono.GregorianChronology;
035    import org.joda.time.chrono.ISOChronology;
036    import org.joda.time.chrono.JulianChronology;
037    import org.joda.time.field.DelegatedDurationField;
038    import org.joda.time.field.MillisDurationField;
039    import org.joda.time.field.UnsupportedDateTimeField;
040    import org.joda.time.field.UnsupportedDurationField;
041    
042    /**
043     * This class is a Junit unit test for serialization.
044     *
045     * @author Stephen Colebourne
046     */
047    public class TestSerialization extends TestCase {
048        // Test in 2002/03 as time zones are more well known
049        // (before the late 90's they were all over the place)
050    
051        private static final DateTimeZone PARIS = DateTimeZone.forID("Europe/Paris");
052        private static final DateTimeZone LONDON = DateTimeZone.forID("Europe/London");
053        private static final DateTimeZone TOKYO = DateTimeZone.forID("Asia/Tokyo");
054        
055        long y2002days = 365 + 365 + 366 + 365 + 365 + 365 + 366 + 365 + 365 + 365 + 
056                         366 + 365 + 365 + 365 + 366 + 365 + 365 + 365 + 366 + 365 + 
057                         365 + 365 + 366 + 365 + 365 + 365 + 366 + 365 + 365 + 365 +
058                         366 + 365;
059        long y2003days = 365 + 365 + 366 + 365 + 365 + 365 + 366 + 365 + 365 + 365 + 
060                         366 + 365 + 365 + 365 + 366 + 365 + 365 + 365 + 366 + 365 + 
061                         365 + 365 + 366 + 365 + 365 + 365 + 366 + 365 + 365 + 365 +
062                         366 + 365 + 365;
063        
064        // 2002-06-09
065        private long TEST_TIME_NOW =
066                (y2002days + 31L + 28L + 31L + 30L + 31L + 9L -1L) * DateTimeConstants.MILLIS_PER_DAY;
067                
068        // 2002-04-05
069        private long TEST_TIME1 =
070                (y2002days + 31L + 28L + 31L + 5L -1L) * DateTimeConstants.MILLIS_PER_DAY
071                + 12L * DateTimeConstants.MILLIS_PER_HOUR
072                + 24L * DateTimeConstants.MILLIS_PER_MINUTE;
073            
074        // 2003-05-06
075        private long TEST_TIME2 =
076                (y2003days + 31L + 28L + 31L + 30L + 6L -1L) * DateTimeConstants.MILLIS_PER_DAY
077                + 14L * DateTimeConstants.MILLIS_PER_HOUR
078                + 28L * DateTimeConstants.MILLIS_PER_MINUTE;
079    
080        private static class MockDelegatedDurationField extends DelegatedDurationField implements Serializable {
081            private static final long serialVersionUID = 1878496002811998493L;        
082            public MockDelegatedDurationField() {
083                super(MillisDurationField.INSTANCE);
084            }
085        }
086    
087        private DateTimeZone originalDateTimeZone = null;
088        private TimeZone originalTimeZone = null;
089        private Locale originalLocale = null;
090    
091        public static void main(String[] args) {
092            junit.textui.TestRunner.run(suite());
093        }
094    
095        public static TestSuite suite() {
096            return new TestSuite(TestSerialization.class);
097        }
098    
099        public TestSerialization(String name) {
100            super(name);
101        }
102    
103        protected void setUp() throws Exception {
104            DateTimeUtils.setCurrentMillisFixed(TEST_TIME_NOW);
105            originalDateTimeZone = DateTimeZone.getDefault();
106            originalTimeZone = TimeZone.getDefault();
107            originalLocale = Locale.getDefault();
108            DateTimeZone.setDefault(LONDON);
109            TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));
110            Locale.setDefault(Locale.UK);
111        }
112    
113        protected void tearDown() throws Exception {
114            DateTimeUtils.setCurrentMillisSystem();
115            DateTimeZone.setDefault(originalDateTimeZone);
116            TimeZone.setDefault(originalTimeZone);
117            Locale.setDefault(originalLocale);
118            originalDateTimeZone = null;
119            originalTimeZone = null;
120            originalLocale = null;
121        }
122    
123        //-----------------------------------------------------------------------
124        public void testTest() {
125            assertEquals("2002-06-09T00:00:00.000Z", new Instant(TEST_TIME_NOW).toString());
126            assertEquals("2002-04-05T12:24:00.000Z", new Instant(TEST_TIME1).toString());
127            assertEquals("2003-05-06T14:28:00.000Z", new Instant(TEST_TIME2).toString());
128        }
129    
130        //-----------------------------------------------------------------------
131        public void testSerializedInstant() throws Exception {
132            Instant test = new Instant();
133            loadAndCompare(test, "Instant", false);
134            inlineCompare(test, false);
135        }
136    
137        public void testSerializedDateTime() throws Exception {
138            DateTime test = new DateTime();
139            loadAndCompare(test, "DateTime", false);
140            inlineCompare(test, false);
141        }
142    
143        public void testSerializedDateTimeProperty() throws Exception {
144            DateTime.Property test = new DateTime().hourOfDay();
145            loadAndCompare(test, "DateTimeProperty", false);
146            inlineCompare(test, false);
147        }
148    
149        public void testSerializedMutableDateTime() throws Exception {
150            MutableDateTime test = new MutableDateTime();
151            loadAndCompare(test, "MutableDateTime", false);
152            inlineCompare(test, false);
153        }
154    
155        public void testSerializedMutableDateTimeProperty() throws Exception {
156            MutableDateTime.Property test = new MutableDateTime().hourOfDay();
157            loadAndCompare(test, "MutableDateTimeProperty", false);
158            inlineCompare(test, false);
159        }
160    
161        public void testSerializedDateMidnight() throws Exception {
162            DateMidnight test = new DateMidnight();
163            loadAndCompare(test, "DateMidnight", false);
164            inlineCompare(test, false);
165        }
166    
167        public void testSerializedDateMidnightProperty() throws Exception {
168            DateMidnight.Property test = new DateMidnight().monthOfYear();
169            loadAndCompare(test, "DateMidnightProperty", false);
170            inlineCompare(test, false);
171        }
172    
173        public void testSerializedLocalDate() throws Exception {
174            LocalDate test = new LocalDate();
175            loadAndCompare(test, "LocalDate", false);
176            inlineCompare(test, false);
177        }
178    
179        public void testSerializedLocalDateBuddhist() throws Exception {
180            LocalDate test = new LocalDate(BuddhistChronology.getInstanceUTC());
181            loadAndCompare(test, "LocalDateBuddhist", false);
182            inlineCompare(test, false);
183        }
184    
185        public void testSerializedLocalTime() throws Exception {
186            LocalTime test = new LocalTime();
187            loadAndCompare(test, "LocalTime", false);
188            inlineCompare(test, false);
189        }
190    
191        public void testSerializedLocalDateTime() throws Exception {
192            LocalDateTime test = new LocalDateTime();
193            loadAndCompare(test, "LocalDateTime", false);
194            inlineCompare(test, false);
195        }
196    
197        public void testSerializedYearMonthDay() throws Exception {
198            YearMonthDay test = new YearMonthDay();
199            loadAndCompare(test, "YearMonthDay", false);
200            inlineCompare(test, false);
201        }
202    
203        public void testSerializedTimeOfDay() throws Exception {
204            TimeOfDay test = new TimeOfDay();
205            loadAndCompare(test, "TimeOfDay", false);
206            inlineCompare(test, false);
207        }
208    
209        public void testSerializedDateTimeZoneUTC() throws Exception {
210            DateTimeZone test = DateTimeZone.UTC;
211            loadAndCompare(test, "DateTimeZoneUTC", true);
212            inlineCompare(test, true);
213        }
214    
215        public void testSerializedDateTimeZone() throws Exception {
216            // have to re-get the zone, as TestDateTimeZone may have
217            // changed the cache, or a SoftReference may have got cleared
218            DateTimeZone test = DateTimeZone.forID("Europe/Paris");
219            loadAndCompare(test, "DateTimeZone", true);
220            inlineCompare(test, true);
221        }
222    
223        public void testDuration() throws Exception {
224            Duration test = Duration.millis(12345);
225            loadAndCompare(test, "Duration", false);
226            inlineCompare(test, false);
227        }
228    
229        public void testSerializedCopticChronology() throws Exception {
230            CopticChronology test = CopticChronology.getInstance(LONDON);
231            loadAndCompare(test, "CopticChronology", true);
232            inlineCompare(test, true);
233        }
234    
235        public void testSerializedISOChronology() throws Exception {
236            ISOChronology test = ISOChronology.getInstance(PARIS);
237            loadAndCompare(test, "ISOChronology", true);
238            inlineCompare(test, true);
239        }
240    
241        public void testSerializedGJChronology() throws Exception {
242            GJChronology test = GJChronology.getInstance(TOKYO);
243            loadAndCompare(test, "GJChronology", true);
244            inlineCompare(test, true);
245        }
246    
247        public void testSerializedGJChronologyChangedInternals() throws Exception {
248            GJChronology test = GJChronology.getInstance(PARIS, 123L, 2);
249            loadAndCompare(test, "GJChronologyChangedInternals", true);
250            inlineCompare(test, true);
251        }
252    
253        public void testSerializedGregorianChronology() throws Exception {
254            GregorianChronology test = GregorianChronology.getInstance(PARIS);
255            loadAndCompare(test, "GregorianChronology", true);
256            inlineCompare(test, true);
257        }
258    
259        public void testSerializedJulianChronology() throws Exception {
260            JulianChronology test = JulianChronology.getInstance(PARIS);
261            loadAndCompare(test, "JulianChronology", true);
262            inlineCompare(test, true);
263        }
264    
265        public void testSerializedBuddhistChronology() throws Exception {
266            BuddhistChronology test = BuddhistChronology.getInstance(PARIS);
267            loadAndCompare(test, "BuddhistChronology", true);
268            inlineCompare(test, true);
269        }
270    
271        public void testSerializedPeriodType() throws Exception {
272            PeriodType test = PeriodType.dayTime();
273            loadAndCompare(test, "PeriodType", false);
274            inlineCompare(test, false);
275        }
276    
277        public void testSerializedDateTimeFieldType() throws Exception {
278            DateTimeFieldType test = DateTimeFieldType.clockhourOfDay();
279            loadAndCompare(test, "DateTimeFieldType", true);
280            inlineCompare(test, true);
281        }
282    
283        public void testSerializedUnsupportedDateTimeField() throws Exception {
284            UnsupportedDateTimeField test = UnsupportedDateTimeField.getInstance(
285                    DateTimeFieldType.year(),
286                    UnsupportedDurationField.getInstance(DurationFieldType.years()));
287            loadAndCompare(test, "UnsupportedDateTimeField", true);
288            inlineCompare(test, true);
289        }
290    
291        private void loadAndCompare(Serializable test, String filename, boolean same) throws Exception {
292            FileInputStream fis = new FileInputStream("src/test/resources/" + filename + ".dat");
293            ObjectInputStream ois = new ObjectInputStream(fis);
294            Object obj = ois.readObject();
295            ois.close();
296            if (same) {
297                assertSame(test, obj);
298            } else {
299                assertEquals(test, obj);
300            }
301    //        try {
302    //            fis = new FileInputStream("src/test/resources/" + filename + "2.dat");
303    //            ois = new ObjectInputStream(fis);
304    //            obj = ois.readObject();
305    //            ois.close();
306    //            if (same) {
307    //                assertSame(test, obj);
308    //            } else {
309    //                assertEquals(test, obj);
310    //            }
311    //        } catch (FileNotFoundException ex) {
312    //            // ignore
313    //        }
314        }
315    
316        public void inlineCompare(Serializable test, boolean same) throws Exception {
317            ByteArrayOutputStream baos = new ByteArrayOutputStream();
318            ObjectOutputStream oos = new ObjectOutputStream(baos);
319            oos.writeObject(test);
320            oos.close();
321            
322            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
323            ObjectInputStream ois = new ObjectInputStream(bais);
324            Object obj = ois.readObject();
325            ois.close();
326            
327            if (same) {
328                assertSame(test, obj);
329            } else {
330                assertEquals(test, obj);
331            }
332        }
333    
334    //    //-----------------------------------------------------------------------
335    //    public void testStoreSerializedInstant() throws Exception {
336    //        Instant test = new Instant();
337    //        store(test, "Instant.dat");
338    //    }
339    //
340    //    public void testStoreSerializedDateTime() throws Exception {
341    //        DateTime test = new DateTime();
342    //        store(test, "DateTime.dat");
343    //    }
344    //
345    //    public void testStoreSerializedMutableDateTime() throws Exception {
346    //        MutableDateTime test = new MutableDateTime();
347    //        store(test, "MutableDateTime.dat");
348    //    }
349    //
350    //    public void testStoreSerializedDateMidnight() throws Exception {
351    //        DateMidnight test = new DateMidnight();
352    //        store(test, "DateMidnight.dat");
353    //    }
354    //
355    //    public void testStoreSerializedLocalDate() throws Exception {
356    //        LocalDate test = new LocalDate();
357    //        store(test, "LocalDate.dat");
358    //    }
359    //
360    //    public void testStoreSerializedLocalDateBuddhist() throws Exception {
361    //        LocalDate test = new LocalDate(BuddhistChronology.getInstanceUTC());
362    //        store(test, "LocalDateBuddhist.dat");
363    //    }
364    //
365    //    public void testStoreSerializedLocalTime() throws Exception {
366    //        LocalTime test = new LocalTime();
367    //        store(test, "LocalTime.dat");
368    //    }
369    //
370    //    public void testStoreSerializedLocalDateTime() throws Exception {
371    //        LocalDateTime test = new LocalDateTime();
372    //        store(test, "LocalDateTime.dat");
373    //    }
374    //
375    //    public void testStoreSerializedYearMonthDay() throws Exception {
376    //        YearMonthDay test = new YearMonthDay();
377    //        store(test, "YearMonthDay.dat");
378    //    }
379    //
380    //    public void testStoreSerializedYearMonthDayProperty() throws Exception {
381    //        YearMonthDay.Property test = new YearMonthDay().monthOfYear();
382    //        store(test, "YearMonthDayProperty.dat");
383    //    }
384    //
385    //    public void testStoreSerializedTimeOfDay() throws Exception {
386    //        TimeOfDay test = new TimeOfDay();
387    //        store(test, "TimeOfDay.dat");
388    //    }
389    //
390    //    public void testStoreSerializedTimeOfDayProperty() throws Exception {
391    //        TimeOfDay.Property test = new TimeOfDay().hourOfDay();
392    //        store(test, "TimeOfDayProperty.dat");
393    //    }
394    //
395    //    public void testStoreSerializedDateTimeZoneUTC() throws Exception {
396    //        DateTimeZone test = DateTimeZone.UTC;
397    //        store(test, "DateTimeZoneUTC.dat");
398    //    }
399    //
400    //    public void testStoreSerializedDateTimeZone() throws Exception {
401    //        DateTimeZone test = PARIS;
402    //        store(test, "DateTimeZone.dat");
403    //    }
404    //
405    //    public void testStoreSerializedCopticChronology() throws Exception {
406    //        CopticChronology test = CopticChronology.getInstance(LONDON);
407    //        store(test, "CopticChronology.dat");
408    //    }
409    //
410    //    public void testStoreSerializedISOChronology() throws Exception {
411    //        ISOChronology test = ISOChronology.getInstance(PARIS);
412    //        store(test, "ISOChronology.dat");
413    //    }
414    //
415    //    public void testStoreSerializedGJChronology() throws Exception {
416    //        GJChronology test = GJChronology.getInstance(TOKYO);
417    //        store(test, "GJChronology.dat");
418    //    }
419    //
420    //    // Format changed in v1.2 - min days in first week not deserialized in v1.0/1.1
421    //    public void testStoreSerializedGJChronologyChangedInternals() throws Exception {
422    //        GJChronology test = GJChronology.getInstance(PARIS, 123L, 2);
423    //        store(test, "GJChronologyChangedInternals.dat");
424    //    }
425    //
426    //    public void testStoreSerializedGregorianChronology() throws Exception {
427    //        GregorianChronology test = GregorianChronology.getInstance(PARIS);
428    //        store(test, "GregorianChronology.dat");
429    //    }
430    //
431    //    public void testStoreSerializedJulianChronology() throws Exception {
432    //        JulianChronology test = JulianChronology.getInstance(PARIS);
433    //        store(test, "JulianChronology.dat");
434    //    }
435    //
436    //    public void testStoreSerializedBuddhistChronology() throws Exception {
437    //        BuddhistChronology test = BuddhistChronology.getInstance(PARIS);
438    //        store(test, "BuddhistChronology.dat");
439    //    }
440    //
441    //    public void testStoreSerializedPeriodType() throws Exception {
442    //        PeriodType test = PeriodType.dayTime();
443    //        store(test, "PeriodType.dat");
444    //    }
445    //
446    //    public void testStoreSerializedDateTimeFieldType() throws Exception {
447    //        DateTimeFieldType test = DateTimeFieldType.clockhourOfDay();
448    //        store(test, "DateTimeFieldType.dat");
449    //    }
450    //
451    //    public void testStoreSerializedUnsupportedDateTimeField() throws Exception {
452    //        UnsupportedDateTimeField test = UnsupportedDateTimeField.getInstance(
453    //                DateTimeFieldType.year(),
454    //                UnsupportedDurationField.getInstance(DurationFieldType.years()));
455    //        store(test, "UnsupportedDateTimeField.dat");
456    //    }
457    //
458    //    public void testStoreSerializedDurationFieldType() throws Exception {
459    //        DurationFieldType test = DurationFieldType.MINUTES_TYPE;
460    //        store(test, "DurationFieldType.dat");
461    //    }
462    //
463    //    public void testStoreSerializedMillisDurationField() throws Exception {
464    //        MillisDurationField test = (MillisDurationField) MillisDurationField.INSTANCE;
465    //        store(test, "MillisDurationField.dat");
466    //    }
467    //
468    //    public void testStoreSerializedDelegatedDurationField() throws Exception {
469    //        DelegatedDurationField test = new MockDelegatedDurationField();
470    //        store(test, "DelegatedDurationField.dat");
471    //    }
472    //
473    //    public void testStoreSerializedUnsupportedDurationField() throws Exception {
474    //        UnsupportedDurationField test = UnsupportedDurationField.getInstance(DurationFieldType.eras());
475    //        store(test, "UnsupportedDurationField.dat");
476    //    }
477    //
478        // format changed (properly defined) in v1.1
479    //    public void testStoreSerializedDateTimeProperty() throws Exception {
480    //        DateTime.Property test = new DateTime().hourOfDay();
481    //        store(test, "DateTimeProperty.dat");
482    //    }
483    //
484    //    public void testStoreSerializedMutableDateTimeProperty() throws Exception {
485    //        MutableDateTime.Property test = new MutableDateTime().hourOfDay();
486    //        store(test, "MutableDateTimeProperty.dat");
487    //    }
488    //
489    //    public void testStoreSerializedDateMidnightProperty() throws Exception {
490    //        DateMidnight.Property test = new DateMidnight().monthOfYear();
491    //        store(test, "DateMidnightProperty.dat");
492    //    }
493    //
494    //    public void testStoreSerializedDateMidnightProperty() throws Exception {
495    //        Duration test = Duration.millis(12345);
496    //        store(test, "Duration.dat");
497    //    }
498    
499        private void store(Serializable test, String filename) throws Exception {
500            FileOutputStream fos = new FileOutputStream("src/test/resources/" + filename);
501            ObjectOutputStream oos = new ObjectOutputStream(fos);
502            try {
503                oos.writeObject(test);
504            } finally {
505                oos.close();
506            }
507            oos.close();
508        }
509    
510    }