1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package org.apache.harmony.tests.java.io;
19
20import java.io.ByteArrayInputStream;
21import java.io.ByteArrayOutputStream;
22import java.io.Externalizable;
23import java.io.File;
24import java.io.FileInputStream;
25import java.io.FileOutputStream;
26import java.io.IOException;
27import java.io.NotActiveException;
28import java.io.NotSerializableException;
29import java.io.ObjectInput;
30import java.io.ObjectInputStream;
31import java.io.ObjectOutput;
32import java.io.ObjectOutputStream;
33import java.io.ObjectStreamClass;
34import java.io.ObjectStreamConstants;
35import java.io.ObjectStreamException;
36import java.io.ObjectStreamField;
37import java.io.OutputStream;
38import java.io.Serializable;
39import java.io.SerializablePermission;
40import java.io.WriteAbortedException;
41import java.security.Permission;
42import java.util.Arrays;
43
44import junit.framework.TestCase;
45
46@SuppressWarnings({ "unused", "serial" })
47public class ObjectOutputStreamTest extends TestCase implements Serializable {
48
49    File f;
50
51    public class SerializableTestHelper implements Serializable {
52        public String aField1;
53
54        public String aField2;
55
56        SerializableTestHelper() {
57            aField1 = null;
58            aField2 = null;
59        }
60
61        SerializableTestHelper(String s, String t) {
62            aField1 = s;
63            aField2 = t;
64        }
65
66        private void readObject(ObjectInputStream ois) throws IOException {
67            // note aField2 is not read
68            try {
69                ObjectInputStream.GetField fields = ois.readFields();
70                aField1 = (String) fields.get("aField1", "Zap");
71            } catch (Exception e) {
72            }
73        }
74
75        private void writeObject(ObjectOutputStream oos) throws IOException {
76            // note aField2 is not written
77            ObjectOutputStream.PutField fields = oos.putFields();
78            fields.put("aField1", aField1);
79            oos.writeFields();
80        }
81
82        public String getText1() {
83            return aField1;
84        }
85
86        public void setText1(String s) {
87            aField1 = s;
88        }
89
90        public String getText2() {
91            return aField2;
92        }
93
94        public void setText2(String s) {
95            aField2 = s;
96        }
97    }
98
99    private static class SerializationTest implements java.io.Serializable {
100        int anInt = INIT_INT_VALUE;
101
102        public SerializationTest() {
103            super();
104        }
105    }
106
107    private static class SerializationTestSubclass1 extends SerializationTest
108            implements Serializable {
109        String aString = INIT_STR_VALUE;
110
111        public SerializationTestSubclass1() {
112            super();
113            // Just to change default superclass init value
114            anInt = INIT_INT_VALUE / 2;
115        }
116    }
117
118    private static class SpecTestSuperClass implements Runnable, Serializable {
119        protected java.lang.String instVar;
120
121        public void run() {
122        }
123    }
124
125    private static class SpecTest extends SpecTestSuperClass implements
126            Cloneable, Serializable {
127        public java.lang.String instVar1;
128
129        public static java.lang.String staticVar1;
130
131        public static java.lang.String staticVar2;
132
133        {
134            instVar1 = "NonStaticInitialValue";
135        }
136
137        static {
138            staticVar1 = "StaticInitialValue";
139            staticVar1 = new String(staticVar1);
140        }
141
142        public Object method(Object objParam, Object objParam2) {
143            return new Object();
144        }
145
146        public boolean method(boolean bParam, Object objParam) {
147            return true;
148        }
149
150        public boolean method(boolean bParam, Object objParam, Object objParam2) {
151            return true;
152        }
153
154    }
155
156    private static class SpecTestSubclass extends SpecTest implements
157            Serializable {
158        public transient java.lang.String transientInstVar = "transientValue";
159    }
160
161    private static class ReadWriteObject implements java.io.Serializable {
162        public boolean calledWriteObject = false;
163
164        public boolean calledReadObject = false;
165
166        public ReadWriteObject() {
167            super();
168        }
169
170        private void readObject(java.io.ObjectInputStream in)
171                throws java.io.IOException, ClassNotFoundException {
172            calledReadObject = true;
173            in.readObject();
174        }
175
176        private void writeObject(java.io.ObjectOutputStream out)
177                throws java.io.IOException {
178            calledWriteObject = true;
179            out.writeObject(FOO);
180        }
181    }
182
183    private static class PublicReadWriteObject implements java.io.Serializable {
184        public boolean calledWriteObject = false;
185
186        public boolean calledReadObject = false;
187
188        public PublicReadWriteObject() {
189            super();
190        }
191
192        public void readObject(java.io.ObjectInputStream in)
193                throws java.io.IOException, ClassNotFoundException {
194            calledReadObject = true;
195            in.readObject();
196        }
197
198        public void writeObject(java.io.ObjectOutputStream out)
199                throws java.io.IOException {
200            calledWriteObject = true;
201            out.writeObject(FOO);
202        }
203    }
204
205    private static class FieldOrder implements Serializable {
206        String aaa1NonPrimitive = "aaa1";
207
208        int bbb1PrimitiveInt = 5;
209
210        boolean aaa2PrimitiveBoolean = true;
211
212        String bbb2NonPrimitive = "bbb2";
213    }
214
215    private static class JustReadObject implements java.io.Serializable {
216        public boolean calledReadObject = false;
217
218        public JustReadObject() {
219            super();
220        }
221
222        private void readObject(java.io.ObjectInputStream in)
223                throws java.io.IOException, ClassNotFoundException {
224            calledReadObject = true;
225            in.defaultReadObject();
226        }
227    }
228
229    private static class JustWriteObject implements java.io.Serializable {
230        public boolean calledWriteObject = false;
231
232        public JustWriteObject() {
233            super();
234        }
235
236        private void writeObject(java.io.ObjectOutputStream out)
237                throws java.io.IOException, ClassNotFoundException {
238            calledWriteObject = true;
239            out.defaultWriteObject();
240        }
241    }
242
243    private static class ClassBasedReplacementWhenDumping implements
244            java.io.Serializable {
245        public boolean calledReplacement = false;
246
247        public ClassBasedReplacementWhenDumping() {
248            super();
249        }
250
251        private Object writeReplace() {
252            calledReplacement = true;
253            return FOO; // Replacement is a String
254        }
255    }
256
257    private static class MultipleClassBasedReplacementWhenDumping implements
258            java.io.Serializable {
259        private static class C1 implements java.io.Serializable {
260            private Object writeReplace() {
261                return new C2();
262            }
263        }
264
265        private static class C2 implements java.io.Serializable {
266            private Object writeReplace() {
267                return new C3();
268            }
269        }
270
271        private static class C3 implements java.io.Serializable {
272            private Object writeReplace() {
273                return FOO;
274            }
275        }
276
277        public MultipleClassBasedReplacementWhenDumping() {
278            super();
279        }
280
281        private Object writeReplace() {
282            return new C1();
283        }
284    }
285
286    private static class ClassBasedReplacementWhenLoading implements
287            java.io.Serializable {
288        public ClassBasedReplacementWhenLoading() {
289            super();
290        }
291
292        private Object readResolve() {
293            return FOO; // Replacement is a String
294        }
295    }
296
297    private static class ClassBasedReplacementWhenLoadingViolatesFieldType
298            implements java.io.Serializable {
299        public ClassBasedReplacementWhenLoading classBasedReplacementWhenLoading = new ClassBasedReplacementWhenLoading();
300
301        public ClassBasedReplacementWhenLoadingViolatesFieldType() {
302            super();
303        }
304    }
305
306    private static class MyExceptionWhenDumping implements java.io.Serializable {
307        private static class MyException extends java.io.IOException {
308        }
309
310        ;
311
312        public boolean anInstanceVar = false;
313
314        public MyExceptionWhenDumping() {
315            super();
316        }
317
318        private void readObject(java.io.ObjectInputStream in)
319                throws java.io.IOException, ClassNotFoundException {
320            in.defaultReadObject();
321        }
322
323        private void writeObject(java.io.ObjectOutputStream out)
324                throws java.io.IOException, ClassNotFoundException {
325            throw new MyException();
326        }
327    }
328
329    private static class NonSerializableExceptionWhenDumping implements
330            java.io.Serializable {
331        public Object anInstanceVar = new Object();
332
333        public NonSerializableExceptionWhenDumping() {
334            super();
335        }
336    }
337
338    private static class MyUnserializableExceptionWhenDumping implements
339            java.io.Serializable {
340        private static class MyException extends java.io.IOException {
341            private Object notSerializable = new Object();
342        }
343
344        ;
345
346        public boolean anInstanceVar = false;
347
348        public MyUnserializableExceptionWhenDumping() {
349            super();
350        }
351
352        private void readObject(java.io.ObjectInputStream in)
353                throws java.io.IOException, ClassNotFoundException {
354            in.defaultReadObject();
355        }
356
357        private void writeObject(java.io.ObjectOutputStream out)
358                throws java.io.IOException, ClassNotFoundException {
359            throw new MyException();
360        }
361    }
362
363    private static class WithUnmatchingSerialPersistentFields implements
364            java.io.Serializable {
365        private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField(
366                "value", String.class) };
367
368        public int anInstanceVar = 5;
369
370        public WithUnmatchingSerialPersistentFields() {
371            super();
372        }
373    }
374
375    private static class WithMatchingSerialPersistentFields implements
376            java.io.Serializable {
377        private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField(
378                "anInstanceVar", String.class) };
379
380        public String anInstanceVar = FOO + FOO;
381
382        public WithMatchingSerialPersistentFields() {
383            super();
384        }
385    }
386
387    private static class SerialPersistentFields implements java.io.Serializable {
388        private static final String SIMULATED_FIELD_NAME = "text";
389
390        private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField(
391                SIMULATED_FIELD_NAME, String.class) };
392
393        public int anInstanceVar = 5;
394
395        public SerialPersistentFields() {
396            super();
397        }
398
399        private void readObject(java.io.ObjectInputStream in)
400                throws java.io.IOException, ClassNotFoundException {
401            ObjectInputStream.GetField fields = in.readFields();
402            anInstanceVar = Integer.parseInt((String) fields.get(
403                    SIMULATED_FIELD_NAME, "-5"));
404        }
405
406        private void writeObject(java.io.ObjectOutputStream out)
407                throws java.io.IOException, ClassNotFoundException {
408            ObjectOutputStream.PutField fields = out.putFields();
409            fields.put(SIMULATED_FIELD_NAME, Integer.toString(anInstanceVar));
410            out.writeFields();
411        }
412    }
413
414    private static class WriteFieldsWithoutFetchingPutFields implements
415            java.io.Serializable {
416        private static final String SIMULATED_FIELD_NAME = "text";
417
418        private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField(
419                SIMULATED_FIELD_NAME, String.class) };
420
421        public int anInstanceVar = 5;
422
423        public WriteFieldsWithoutFetchingPutFields() {
424            super();
425        }
426
427        private void readObject(java.io.ObjectInputStream in)
428                throws java.io.IOException, ClassNotFoundException {
429            in.readFields();
430        }
431
432        private void writeObject(java.io.ObjectOutputStream out)
433                throws java.io.IOException, ClassNotFoundException {
434            out.writeFields();
435        }
436    }
437
438    private static class SerialPersistentFieldsWithoutField implements
439            java.io.Serializable {
440        public int anInstanceVar = 5;
441
442        public SerialPersistentFieldsWithoutField() {
443            super();
444        }
445
446        private void readObject(java.io.ObjectInputStream in)
447                throws java.io.IOException, ClassNotFoundException {
448            in.readFields();
449        }
450
451        private void writeObject(java.io.ObjectOutputStream out)
452                throws java.io.IOException, ClassNotFoundException {
453            out.putFields();
454            out.writeFields();
455        }
456    }
457
458    private static class NotSerializable {
459        private int foo;
460
461        public NotSerializable() {
462        }
463
464        protected Object writeReplace() throws ObjectStreamException {
465            return new Integer(42);
466        }
467    }
468
469    private static class WriteReplaceObject implements Serializable {
470        private Object replaceObject;
471
472        private static enum Color {
473            red, blue, green
474        }
475
476        ;
477
478        public WriteReplaceObject(Object o) {
479            replaceObject = o;
480        }
481
482        protected Object writeReplace() throws ObjectStreamException {
483            return replaceObject;
484        }
485    }
486
487    private static class ExternalizableWithReplace implements Externalizable {
488        private int foo;
489
490        public ExternalizableWithReplace() {
491        }
492
493        protected Object writeReplace() throws ObjectStreamException {
494            return new Integer(42);
495        }
496
497        public void writeExternal(ObjectOutput out) {
498        }
499
500        public void readExternal(ObjectInput in) {
501        }
502    }
503
504    private static class ObjectOutputStreamWithReplace extends
505            ObjectOutputStream {
506        public ObjectOutputStreamWithReplace(OutputStream out)
507                throws IOException {
508            super(out);
509            enableReplaceObject(true);
510        }
511
512        protected Object replaceObject(Object obj) throws IOException {
513            if (obj instanceof NotSerializable) {
514                return new Long(10);
515            }
516            if (obj instanceof Integer) {
517                return new Long(((Integer) obj).longValue());
518            }
519            return super.replaceObject(obj);
520        }
521    }
522
523    private static class ObjectOutputStreamWithReplace2 extends
524            ObjectOutputStream {
525        public ObjectOutputStreamWithReplace2(OutputStream out)
526                throws IOException {
527            super(out);
528            enableReplaceObject(true);
529        }
530
531        protected Object replaceObject(Object obj) throws IOException {
532            return new Long(10);
533        }
534    }
535
536    private static class ObjectOutputStreamWriteOverride extends
537            ObjectOutputStream {
538        String test = "test";
539
540        protected ObjectOutputStreamWriteOverride() throws IOException,
541                SecurityException {
542            super();
543        }
544
545        @Override
546        protected void writeObjectOverride(Object object) throws IOException {
547            test = null;
548            super.writeObjectOverride(object);
549        }
550    }
551
552    protected static final String MODE_XLOAD = "xload";
553
554    protected static final String MODE_XDUMP = "xdump";
555
556    static final String FOO = "foo";
557
558    static final String MSG_WITE_FAILED = "Failed to write: ";
559
560    private static final boolean DEBUG = false;
561
562    protected static boolean xload = false;
563
564    protected static boolean xdump = false;
565
566    protected static String xFileName = null;
567
568    protected ObjectInputStream ois;
569
570    protected ObjectOutputStream oos;
571
572    protected ByteArrayOutputStream bao;
573
574    static final int INIT_INT_VALUE = 7;
575
576    static final String INIT_STR_VALUE = "a string that is blortz";
577
578    /**
579     * java.io.ObjectOutputStream#ObjectOutputStream(java.io.OutputStream)
580     */
581    public void test_ConstructorLjava_io_OutputStream() throws IOException {
582        // Test for method java.io.ObjectOutputStream(java.io.OutputStream)
583        oos.close();
584        oos = new ObjectOutputStream(new ByteArrayOutputStream());
585        oos.close();
586    }
587
588    /**
589     * java.io.ObjectOutputStream#close()
590     */
591    public void test_close() {
592        // Test for method void java.io.ObjectOutputStream.close()
593    }
594
595    /**
596     * java.io.ObjectOutputStream#defaultWriteObject()
597     */
598    public void test_defaultWriteObject() throws IOException {
599        // Test for method void java.io.ObjectOutputStream.defaultWriteObject()
600        try {
601            oos.defaultWriteObject();
602            fail("Failed to throw NotActiveException");
603        } catch (NotActiveException e) {
604            // Correct
605        }
606    }
607
608    /**
609     * java.io.ObjectOutputStream#flush()
610     */
611    public void test_flush() throws Exception {
612        // Test for method void java.io.ObjectOutputStream.flush()
613        int size = bao.size();
614        oos.writeByte(127);
615        assertTrue("Data flushed already", bao.size() == size);
616        oos.flush();
617        assertTrue("Failed to flush data", bao.size() > size);
618        // we don't know how many bytes are actually written for 1
619        // byte, so we test > <before>
620        oos.close();
621        oos = null;
622    }
623
624    /**
625     * java.io.ObjectOutputStream#putFields()
626     */
627    public void test_putFields() throws Exception {
628        // Test for method java.io.ObjectOutputStream$PutField
629        // java.io.ObjectOutputStream.putFields()
630
631        SerializableTestHelper sth;
632
633        /*
634         * "SerializableTestHelper" is an object created for these tests with
635         * two fields (Strings) and simple implementations of readObject and
636         * writeObject which simply read and write the first field but not the
637         * second
638         */
639
640        oos.writeObject(new SerializableTestHelper("Gabba", "Jabba"));
641        oos.flush();
642        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
643        sth = (SerializableTestHelper) (ois.readObject());
644        assertEquals("readFields / writeFields failed--first field not set",
645                "Gabba", sth.getText1());
646        assertNull(
647                "readFields / writeFields failed--second field should not have been set",
648                sth.getText2());
649    }
650
651    /**
652     * java.io.ObjectOutputStream#reset()
653     */
654    public void test_reset() throws Exception {
655        // Test for method void java.io.ObjectOutputStream.reset()
656        String o = "HelloWorld";
657        oos.writeObject(o);
658        oos.writeObject(o);
659        oos.reset();
660        oos.writeObject(o);
661        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
662        ois.close();
663    }
664
665    private static class ExternalTest implements Externalizable {
666        public String value;
667
668        public ExternalTest() {
669        }
670
671        public void setValue(String val) {
672            value = val;
673        }
674
675        public String getValue() {
676            return value;
677        }
678
679        public void writeExternal(ObjectOutput output) {
680            try {
681                output.writeUTF(value);
682            } catch (IOException e) {
683                e.printStackTrace();
684            }
685        }
686
687        public void readExternal(ObjectInput input) {
688            try {
689                value = input.readUTF();
690            } catch (IOException e) {
691                e.printStackTrace();
692            }
693        }
694    }
695
696    /**
697     * java.io.ObjectOutputStream#useProtocolVersion(int)
698     */
699    public void test_useProtocolVersionI() throws Exception {
700        // Test for method void
701        // java.io.ObjectOutputStream.useProtocolVersion(int)
702        oos.useProtocolVersion(ObjectOutputStream.PROTOCOL_VERSION_1);
703        ExternalTest t1 = new ExternalTest();
704        t1.setValue("hello1");
705        oos.writeObject(t1);
706        oos.close();
707        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
708        ExternalTest t2 = (ExternalTest) ois.readObject();
709        ois.close();
710        assertTrue(
711                "Cannot read/write PROTOCAL_VERSION_1 Externalizable objects: "
712                        + t2.getValue(), t1.getValue().equals(t2.getValue()));
713
714        // Cannot set protocol version when stream in-flight
715        ObjectOutputStream out = new ObjectOutputStream(
716                new ByteArrayOutputStream());
717        out.writeObject("hello world");
718        try {
719            out.useProtocolVersion(ObjectStreamConstants.PROTOCOL_VERSION_1);
720            fail("Expected IllegalStateException");
721        } catch (IllegalStateException e) {
722            // Expected
723        }
724    }
725
726    /**
727     * java.io.ObjectOutputStream#write(byte[])
728     */
729    public void test_write$B() throws Exception {
730        // Test for method void java.io.ObjectOutputStream.write(byte [])
731        byte[] buf = new byte[10];
732        oos.write("HelloWorld".getBytes());
733        oos.close();
734        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
735        ois.read(buf, 0, 10);
736        ois.close();
737        assertEquals("Read incorrect bytes", "HelloWorld", new String(buf, 0,
738                10));
739    }
740
741    /**
742     * java.io.ObjectOutputStream#write(byte[], int, int)
743     */
744    public void test_write$BII() throws Exception {
745        // Test for method void java.io.ObjectOutputStream.write(byte [], int,
746        // int)
747        byte[] buf = new byte[10];
748        oos.write("HelloWorld".getBytes(), 0, 10);
749        oos.close();
750        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
751        ois.read(buf, 0, 10);
752        ois.close();
753        assertEquals("Read incorrect bytes", "HelloWorld", new String(buf, 0,
754                10));
755    }
756
757    /**
758     * java.io.ObjectOutputStream#write(int)
759     */
760    public void test_writeI() throws Exception {
761        // Test for method void java.io.ObjectOutputStream.write(int)
762        oos.write('T');
763        oos.close();
764        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
765        assertEquals("Read incorrect byte", 'T', ois.read());
766        ois.close();
767    }
768
769    /**
770     * java.io.ObjectOutputStream#writeBoolean(boolean)
771     */
772    public void test_writeBooleanZ() throws Exception {
773        // Test for method void java.io.ObjectOutputStream.writeBoolean(boolean)
774        oos.writeBoolean(true);
775        oos.close();
776        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
777        assertTrue("Wrote incorrect byte value", ois.readBoolean());
778    }
779
780    /**
781     * java.io.ObjectOutputStream#writeByte(int)
782     */
783    public void test_writeByteI() throws Exception {
784        // Test for method void java.io.ObjectOutputStream.writeByte(int)
785        oos.writeByte(127);
786        oos.close();
787        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
788        assertEquals("Wrote incorrect byte value", 127, ois.readByte());
789    }
790
791    /**
792     * java.io.ObjectOutputStream#writeBytes(java.lang.String)
793     */
794    public void test_writeBytesLjava_lang_String() throws Exception {
795        // Test for method void
796        // java.io.ObjectOutputStream.writeBytes(java.lang.String)
797        byte[] buf = new byte[10];
798        oos.writeBytes("HelloWorld");
799        oos.close();
800        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
801        ois.readFully(buf);
802        ois.close();
803        assertEquals("Wrote incorrect bytes value", "HelloWorld", new String(
804                buf, 0, 10, "UTF-8"));
805    }
806
807    /**
808     * java.io.ObjectOutputStream#writeChar(int)
809     */
810    public void test_writeCharI() throws Exception {
811        // Test for method void java.io.ObjectOutputStream.writeChar(int)
812        oos.writeChar('T');
813        oos.close();
814        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
815        assertEquals("Wrote incorrect char value", 'T', ois.readChar());
816    }
817
818    /**
819     * java.io.ObjectOutputStream#writeChars(java.lang.String)
820     */
821    public void test_writeCharsLjava_lang_String() throws Exception {
822        // Test for method void
823        // java.io.ObjectOutputStream.writeChars(java.lang.String)
824        int avail = 0;
825        char[] buf = new char[10];
826        oos.writeChars("HelloWorld");
827        oos.close();
828        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
829        // Number of prim data bytes in stream / 2 to give char index
830        avail = ois.available() / 2;
831        for (int i = 0; i < avail; ++i)
832            buf[i] = ois.readChar();
833        ois.close();
834        assertEquals("Wrote incorrect chars", "HelloWorld", new String(buf, 0,
835                10));
836    }
837
838    /**
839     * java.io.ObjectOutputStream#writeDouble(double)
840     */
841    public void test_writeDoubleD() throws Exception {
842        // Test for method void java.io.ObjectOutputStream.writeDouble(double)
843        oos.writeDouble(Double.MAX_VALUE);
844        oos.close();
845        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
846        assertTrue("Wrote incorrect double value",
847                ois.readDouble() == Double.MAX_VALUE);
848    }
849
850    /**
851     * java.io.ObjectOutputStream#writeFields()
852     */
853    public void test_writeFields() {
854        // Test for method void java.io.ObjectOutputStream.writeFields()
855        assertTrue("Used to test", true);
856    }
857
858    /**
859     * java.io.ObjectOutputStream#writeFloat(float)
860     */
861    public void test_writeFloatF() throws Exception {
862        // Test for method void java.io.ObjectOutputStream.writeFloat(float)
863        oos.writeFloat(Float.MAX_VALUE);
864        oos.close();
865        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
866        assertTrue("Wrote incorrect double value",
867                ois.readFloat() == Float.MAX_VALUE);
868        ois.close();
869        ois = null;
870    }
871
872    /**
873     * java.io.ObjectOutputStream#writeInt(int)
874     */
875    public void test_writeIntI() throws Exception {
876        // Test for method void java.io.ObjectOutputStream.writeInt(int)
877        oos.writeInt(Integer.MAX_VALUE);
878        oos.close();
879        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
880        assertTrue("Wrote incorrect double value",
881                ois.readInt() == Integer.MAX_VALUE);
882        ois.close();
883    }
884
885    /**
886     * java.io.ObjectOutputStream#writeLong(long)
887     */
888    public void test_writeLongJ() throws Exception {
889        // Test for method void java.io.ObjectOutputStream.writeLong(long)
890        oos.writeLong(Long.MAX_VALUE);
891        oos.close();
892        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
893        assertTrue("Wrote incorrect double value",
894                ois.readLong() == Long.MAX_VALUE);
895    }
896
897    /**
898     * java.io.ObjectOutputStream#writeObject(java.lang.Object)
899     */
900    public void test_writeObjectLjava_lang_Object() throws Exception {
901        // Test for method void
902        // java.io.ObjectOutputStream.writeObject(java.lang.Object)
903
904        Object objToSave = null;
905        Object objLoaded;
906
907        SerialPersistentFieldsWithoutField spf = new SerialPersistentFieldsWithoutField();
908        final int CONST = -500;
909        spf.anInstanceVar = CONST;
910        objToSave = spf;
911        if (DEBUG)
912            System.out.println("Obj = " + objToSave);
913        objLoaded = dumpAndReload(objToSave);
914        assertTrue(
915                "serialPersistentFields do not work properly in this implementation",
916                ((SerialPersistentFieldsWithoutField) objLoaded).anInstanceVar != CONST);
917
918    }
919
920    /**
921     * java.io.ObjectOutputStream#writeObject(java.lang.Object)
922     */
923    public void test_writeObject_NotSerializable() throws Exception {
924        ObjectOutput out = null;
925        try {
926            out = new ObjectOutputStream(new ByteArrayOutputStream());
927            out.writeObject(new NotSerializable());
928            fail("Expected NotSerializableException");
929        } catch (NotSerializableException e) {
930        }
931        out.writeObject(new ExternalizableWithReplace());
932    }
933
934    /**
935     * {@link java.io.ObjectOutputStream#writeObjectOverride(Object)}
936     */
937    public void test_writeObject_WriteOverride() throws Exception {
938        ObjectOutputStreamWriteOverride mockOut = new ObjectOutputStreamWriteOverride();
939        mockOut.writeObject(new Object());
940        assertNull(mockOut.test);
941    }
942
943    /**
944     * java.io.ObjectOutputStream#writeShort(int)
945     */
946    public void test_writeShortI() throws Exception {
947        // Test for method void java.io.ObjectOutputStream.writeShort(int)
948        oos.writeShort(127);
949        oos.close();
950        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
951        assertEquals("Wrote incorrect short value", 127, ois.readShort());
952    }
953
954    /**
955     * java.io.ObjectOutputStream#writeUTF(java.lang.String)
956     */
957    public void test_writeUTFLjava_lang_String() throws Exception {
958        // Test for method void
959        // java.io.ObjectOutputStream.writeUTF(java.lang.String)
960        oos.writeUTF("HelloWorld");
961        oos.close();
962        ois = new ObjectInputStream(new ByteArrayInputStream(bao.toByteArray()));
963        assertEquals("Wrote incorrect UTF value", "HelloWorld", ois.readUTF());
964    }
965
966    /**
967     * java.io.ObjectOutputStream#writeObject(java.lang.Object)
968     */
969    public void test_writeObject_Exception() throws ClassNotFoundException,
970            IOException {
971        ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
972        ObjectOutputStream oos = new ObjectOutputStream(baos);
973
974        try {
975            oos.writeObject(new Object());
976            fail("should throw ObjectStreamException");
977        } catch (ObjectStreamException e) {
978            // expected
979        } finally {
980            oos.close();
981            baos.close();
982        }
983
984        byte[] bytes = baos.toByteArray();
985        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(
986                bytes));
987        try {
988            ois.readObject();
989            fail("should throw WriteAbortedException");
990        } catch (WriteAbortedException e) {
991            // expected
992        } finally {
993            ois.close();
994        }
995    }
996
997    /**
998     * {@link java.io.ObjectOutputStream#annotateProxyClass(java.lang.Class<T>)}
999     */
1000    public void test_annotateProxyClass() throws SecurityException, IOException {
1001        MockObjectOutputStream mockObjectOutputStream = new MockObjectOutputStream();
1002        mockObjectOutputStream.annotateProxyClass(this.getClass());
1003        assertEquals("The default implementation is doing nothing.",
1004                mockObjectOutputStream, mockObjectOutputStream);
1005
1006    }
1007
1008    class MockObjectOutputStream extends ObjectOutputStream {
1009
1010        protected MockObjectOutputStream() throws IOException,
1011                SecurityException {
1012            super();
1013        }
1014
1015        @Override
1016        public void annotateProxyClass(Class<?> aClass) throws IOException {
1017            super.annotateProxyClass(aClass);
1018        }
1019
1020    }
1021
1022    /**
1023     * Sets up the fixture, for example, open a network connection. This method
1024     * is called before a test is executed.
1025     */
1026    protected void setUp() throws Exception {
1027        super.setUp();
1028        oos = new ObjectOutputStream(bao = new ByteArrayOutputStream());
1029    }
1030
1031    /**
1032     * Tears down the fixture, for example, close a network connection. This
1033     * method is called after a test is executed.
1034     */
1035    protected void tearDown() throws Exception {
1036        super.tearDown();
1037        if (oos != null) {
1038            try {
1039                oos.close();
1040            } catch (Exception e) {
1041            }
1042        }
1043        if (f != null && f.exists()) {
1044            if (!f.delete()) {
1045                fail("Error cleaning up files during teardown");
1046            }
1047        }
1048    }
1049
1050    protected Object reload() throws IOException, ClassNotFoundException {
1051
1052        // Choose the load stream
1053        if (xload || xdump) {
1054            // Load from pre-existing file
1055            ois = new ObjectInputStream(new FileInputStream(xFileName + "-"
1056                    + getName() + ".ser"));
1057        } else {
1058            // Just load from memory, we dumped to memory
1059            ois = new ObjectInputStream(new ByteArrayInputStream(bao
1060                    .toByteArray()));
1061        }
1062
1063        try {
1064            return ois.readObject();
1065        } finally {
1066            ois.close();
1067        }
1068    }
1069
1070    protected void dump(Object o) throws IOException, ClassNotFoundException {
1071
1072        // Choose the dump stream
1073        if (xdump) {
1074            oos = new ObjectOutputStream(new FileOutputStream(
1075                    f = new java.io.File(xFileName + "-" + getName() + ".ser")));
1076        } else {
1077            oos = new ObjectOutputStream(bao = new ByteArrayOutputStream());
1078        }
1079
1080        // Dump the object
1081        try {
1082            oos.writeObject(o);
1083        } finally {
1084            oos.close();
1085        }
1086    }
1087
1088    /**
1089     * java.io.ObjectOutputStream#writeInt(int)
1090     * java.io.ObjectOutputStream#writeObject(java.lang.Object)
1091     * java.io.ObjectOutputStream#writeUTF(java.lang.String)
1092     */
1093
1094    public void testMixPrimitivesAndObjects() throws Exception {
1095        int i = 7;
1096        String s1 = "string 1";
1097        String s2 = "string 2";
1098        byte[] bytes = { 1, 2, 3 };
1099        try {
1100            oos = new ObjectOutputStream(bao = new ByteArrayOutputStream());
1101            oos.writeInt(i);
1102            oos.writeObject(s1);
1103            oos.writeUTF(s2);
1104            oos.writeObject(bytes);
1105            oos.close();
1106
1107            ois = new ObjectInputStream(new ByteArrayInputStream(bao
1108                    .toByteArray()));
1109
1110            int j = ois.readInt();
1111            assertTrue("Wrong int :" + j, i == j);
1112
1113            String l1 = (String) ois.readObject();
1114            assertTrue("Wrong obj String :" + l1, s1.equals(l1));
1115
1116            String l2 = ois.readUTF();
1117            assertTrue("Wrong UTF String :" + l2, s2.equals(l2));
1118
1119            byte[] bytes2 = (byte[]) ois.readObject();
1120            assertTrue("Wrong byte[]", Arrays.equals(bytes, bytes2));
1121        } finally {
1122            try {
1123                if (oos != null)
1124                    oos.close();
1125                if (ois != null)
1126                    ois.close();
1127            } catch (IOException e) {
1128            }
1129        }
1130    }
1131
1132    /**
1133     * java.io.ObjectOutputStream#writeUnshared(java.lang.Object)
1134     */
1135    public void test_writeUnshared() throws Exception {
1136        // Regression for HARMONY-187
1137        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1138        ObjectOutputStream oos = new ObjectOutputStream(baos);
1139
1140        Object o = "foobar";
1141        oos.writeObject(o);
1142        oos.writeUnshared(o);
1143        oos.writeObject(o);
1144        oos.flush();
1145
1146        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(
1147                baos.toByteArray()));
1148
1149        Object[] oa = new Object[3];
1150        for (int i = 0; i < oa.length; i++) {
1151            oa[i] = ois.readObject();
1152        }
1153
1154        oos.close();
1155        ois.close();
1156
1157        // All three conditions must be met
1158        assertNotSame("oa[0] != oa[1]", oa[0], oa[1]);
1159        assertNotSame("oa[1] != oa[2]", oa[1], oa[2]);
1160        assertSame("oa[0] == oa[2]", oa[0], oa[2]);
1161    }
1162
1163    /**
1164     * java.io.ObjectOutputStream#writeUnshared(java.lang.Object)
1165     */
1166    public void test_writeUnshared2() throws Exception {
1167        // Regression for HARMONY-187
1168        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1169        ObjectOutputStream oos = new ObjectOutputStream(baos);
1170
1171        Object o = new Object[1];
1172        oos.writeObject(o);
1173        oos.writeUnshared(o);
1174        oos.writeObject(o);
1175        oos.flush();
1176
1177        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(
1178                baos.toByteArray()));
1179
1180        Object[] oa = new Object[3];
1181        for (int i = 0; i < oa.length; i++) {
1182            oa[i] = ois.readObject();
1183        }
1184
1185        oos.close();
1186        ois.close();
1187
1188        // All three conditions must be met
1189        assertNotSame("oa[0] != oa[1]", oa[0], oa[1]);
1190        assertNotSame("oa[1] != oa[2]", oa[1], oa[2]);
1191        assertSame("oa[0] == oa[2]", oa[0], oa[2]);
1192    }
1193
1194    protected Object dumpAndReload(Object o) throws IOException,
1195            ClassNotFoundException {
1196        dump(o);
1197        return reload();
1198    }
1199
1200    /**
1201     * java.io.ObjectOutputStream#useProtocolVersion(int)
1202     */
1203    public void test_useProtocolVersionI_2() throws Exception {
1204        ObjectOutputStream oos = new ObjectOutputStream(
1205                new ByteArrayOutputStream());
1206
1207        oos.useProtocolVersion(ObjectOutputStream.PROTOCOL_VERSION_1);
1208        oos.useProtocolVersion(ObjectOutputStream.PROTOCOL_VERSION_2);
1209        try {
1210            oos.useProtocolVersion(3);
1211            fail("Protocol 3 should not be accepted");
1212        } catch (IllegalArgumentException e) {
1213            // expected
1214        } finally {
1215            oos.close();
1216        }
1217    }
1218
1219    /**
1220     * java.io.ObjectOutputStream#replaceObject(java.lang.Object)
1221     */
1222    public void test_replaceObject() throws Exception {
1223        // Regression for HARMONY-1429
1224        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1225        ObjectOutputStreamWithReplace oos = new ObjectOutputStreamWithReplace(
1226                baos);
1227
1228        oos.writeObject(new NotSerializable());
1229        oos.flush();
1230        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(
1231                baos.toByteArray()));
1232        Object obj = ois.readObject();
1233        oos.close();
1234        ois.close();
1235        assertTrue("replaceObject has not been called", (obj instanceof Long));
1236
1237        // Regression for HARMONY-2239
1238        Object replaceObject = int.class;
1239        baos = new ByteArrayOutputStream();
1240        ObjectOutputStreamWithReplace2 oos2 = new ObjectOutputStreamWithReplace2(
1241                baos);
1242        oos2.writeObject(new WriteReplaceObject(replaceObject));
1243        oos2.flush();
1244        ois = new ObjectInputStream(
1245                new ByteArrayInputStream(baos.toByteArray()));
1246        obj = ois.readObject();
1247        oos.close();
1248        ois.close();
1249        assertTrue("replaceObject has not been called", (obj instanceof Long));
1250
1251        replaceObject = ObjectStreamClass.lookup(Integer.class);
1252        baos = new ByteArrayOutputStream();
1253        oos2 = new ObjectOutputStreamWithReplace2(baos);
1254        oos2.writeObject(new WriteReplaceObject(replaceObject));
1255        oos2.flush();
1256        ois = new ObjectInputStream(
1257                new ByteArrayInputStream(baos.toByteArray()));
1258        obj = ois.readObject();
1259        oos.close();
1260        ois.close();
1261        assertTrue("replaceObject has not been called", (obj instanceof Long));
1262
1263        replaceObject = WriteReplaceObject.Color.red;
1264        baos = new ByteArrayOutputStream();
1265        oos2 = new ObjectOutputStreamWithReplace2(baos);
1266        oos2.writeObject(new WriteReplaceObject(replaceObject));
1267        oos2.flush();
1268        ois = new ObjectInputStream(
1269                new ByteArrayInputStream(baos.toByteArray()));
1270        obj = ois.readObject();
1271        oos.close();
1272        ois.close();
1273        assertTrue("replaceObject has not been called", (obj instanceof Long));
1274
1275        // Regression for HARMONY-3158
1276        Object obj1;
1277        Object obj2;
1278        Object obj3;
1279
1280        baos = new ByteArrayOutputStream();
1281        oos = new ObjectOutputStreamWithReplace(baos);
1282
1283        oos.writeObject(new Integer(99));
1284        oos.writeObject(Integer.class);
1285        oos.writeObject(ObjectStreamClass.lookup(Integer.class));
1286        oos.flush();
1287
1288        ois = new ObjectInputStream(
1289                new ByteArrayInputStream(baos.toByteArray()));
1290        obj1 = ois.readObject();
1291        obj2 = ois.readObject();
1292        obj3 = ois.readObject();
1293        oos.close();
1294        ois.close();
1295
1296        assertTrue("1st replaceObject worked incorrectly", obj1 instanceof Long);
1297        assertEquals("1st replaceObject worked incorrectly", 99, ((Long) obj1)
1298                .longValue());
1299        assertEquals("2nd replaceObject worked incorrectly", Integer.class,
1300                obj2);
1301        assertEquals("3rd replaceObject worked incorrectly",
1302                ObjectStreamClass.class, obj3.getClass());
1303    }
1304
1305    public void test_putFieldWrite() throws Exception {
1306        // Regression test for HARMONY-6483
1307        ObjectOutputStream oos = new ObjectOutputStream(new ByteArrayOutputStream());
1308        try {
1309            oos.writeObject(new OutputObject());
1310            fail("Should throw an IllegalArgumentException");
1311        } catch (IllegalArgumentException iae) {
1312            // Expected
1313        }
1314    }
1315
1316    private static class OutputObject implements Serializable {
1317        private void writeObject(ObjectOutputStream oos) throws IOException {
1318            ObjectOutputStream oos2 = new ObjectOutputStream(new ByteArrayOutputStream());
1319            ObjectOutputStream.PutField putField = oos.putFields();
1320            putField.write(oos2);
1321        }
1322    }
1323}
1324