1 /* 2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* @test 25 * @bug 8026344 26 * @summary Exercise classes in j.u.c.atomic that use serialization proxies 27 */ 28 29 import java.util.concurrent.atomic.DoubleAdder; 30 import java.util.concurrent.atomic.DoubleAccumulator; 31 import java.util.concurrent.atomic.LongAdder; 32 import java.util.concurrent.atomic.LongAccumulator; 33 import java.util.function.DoubleBinaryOperator; 34 import java.util.function.LongBinaryOperator; 35 import java.io.ByteArrayOutputStream; 36 import java.io.ByteArrayInputStream; 37 import java.io.DataInputStream; 38 import java.io.Serializable; 39 import java.io.ObjectInputStream; 40 import java.io.ObjectOutputStream; 41 import java.io.IOException; 42 43 /** 44 * Basic test to exercise the j.u.c.atomic classes that use serialization 45 * proxies. 46 */ 47 public class Serial { 48 main(String[] args)49 public static void main(String[] args) { 50 testDoubleAdder(); 51 testDoubleAccumulator(); 52 testLongAdder(); 53 testLongAccumulator(); 54 } 55 testDoubleAdder()56 static void testDoubleAdder() { 57 DoubleAdder a = new DoubleAdder(); 58 a.add(20.1d); 59 DoubleAdder result = echo(a); 60 if (result.doubleValue() != a.doubleValue()) 61 throw new RuntimeException("Unexpected doubleValue"); 62 63 checkSerialClassName(a, "java.util.concurrent.atomic.DoubleAdder$SerializationProxy"); 64 } 65 testDoubleAccumulator()66 static void testDoubleAccumulator() { 67 DoubleBinaryOperator plus = (DoubleBinaryOperator & Serializable) (x, y) -> x + y; 68 DoubleAccumulator a = new DoubleAccumulator(plus, 13.9d); 69 a.accumulate(17.5d); 70 DoubleAccumulator result = echo(a); 71 if (result.get() != a.get()) 72 throw new RuntimeException("Unexpected value"); 73 a.reset(); 74 result.reset(); 75 if (result.get() != a.get()) 76 throw new RuntimeException("Unexpected value after reset"); 77 78 checkSerialClassName(a, "java.util.concurrent.atomic.DoubleAccumulator$SerializationProxy"); 79 } 80 testLongAdder()81 static void testLongAdder() { 82 LongAdder a = new LongAdder(); 83 a.add(45); 84 LongAdder result = echo(a); 85 if (result.longValue() != a.longValue()) 86 throw new RuntimeException("Unexpected longValue"); 87 88 checkSerialClassName(a, "java.util.concurrent.atomic.LongAdder$SerializationProxy"); 89 } 90 testLongAccumulator()91 static void testLongAccumulator() { 92 LongBinaryOperator plus = (LongBinaryOperator & Serializable) (x, y) -> x + y; 93 LongAccumulator a = new LongAccumulator(plus, -2); 94 a.accumulate(34); 95 LongAccumulator result = echo(a); 96 if (result.get() != a.get()) 97 throw new RuntimeException("Unexpected value"); 98 a.reset(); 99 result.reset(); 100 if (result.get() != a.get()) 101 throw new RuntimeException("Unexpected value after reset"); 102 103 checkSerialClassName(a, "java.util.concurrent.atomic.LongAccumulator$SerializationProxy"); 104 } 105 106 /** 107 * Serialize the given object, returning the reconstituted object. 108 */ 109 @SuppressWarnings("unchecked") echo(T obj)110 static <T extends Serializable> T echo(T obj) { 111 ByteArrayOutputStream out = new ByteArrayOutputStream(); 112 try (ObjectOutputStream oos = new ObjectOutputStream(out)) { 113 oos.writeObject(obj); 114 } catch (IOException e) { 115 throw new RuntimeException("Serialization failed: " + e); 116 } 117 ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); 118 try (ObjectInputStream ois = new ObjectInputStream(in)) { 119 return (T) ois.readObject(); 120 } catch (IOException | ClassNotFoundException e) { 121 throw new RuntimeException("Deserialization failed: " + e); 122 } 123 } 124 125 /** 126 * Checks that the given object serializes to the expected class. 127 */ checkSerialClassName(Serializable obj, String expected)128 static void checkSerialClassName(Serializable obj, String expected) { 129 String cn = serialClassName(obj); 130 if (!cn.equals(expected)) 131 throw new RuntimeException(obj.getClass() + " serialized as " + cn 132 + ", expected " + expected); 133 } 134 135 /** 136 * Returns the class name that the given object serializes as. 137 */ serialClassName(Serializable obj)138 static String serialClassName(Serializable obj) { 139 ByteArrayOutputStream out = new ByteArrayOutputStream(); 140 try (ObjectOutputStream oos = new ObjectOutputStream(out)) { 141 oos.writeObject(obj); 142 } catch (IOException e) { 143 throw new RuntimeException("Serialization failed: " + e); 144 } 145 ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); 146 try (DataInputStream dis = new DataInputStream(in)) { 147 dis.readShort(); // STREAM_MAGIC 148 dis.readShort(); // STREAM_VERSION 149 dis.readByte(); // TC_OBJECT 150 dis.readByte(); // TC_CLASSDESC 151 return dis.readUTF(); // className 152 } catch (IOException e) { 153 throw new RuntimeException(e); 154 } 155 } 156 } 157