1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 package org.apache.thrift;
20 
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.jupiter.api.Assertions.assertFalse;
23 import static org.junit.jupiter.api.Assertions.assertNotSame;
24 import static org.junit.jupiter.api.Assertions.assertNull;
25 import static org.junit.jupiter.api.Assertions.assertThrows;
26 import static org.junit.jupiter.api.Assertions.assertTrue;
27 
28 import java.io.ByteArrayInputStream;
29 import java.io.ByteArrayOutputStream;
30 import java.io.ObjectInputStream;
31 import java.io.ObjectOutputStream;
32 import java.nio.ByteBuffer;
33 import java.util.ArrayList;
34 import java.util.Collections;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.Map;
38 import java.util.Set;
39 import org.apache.thrift.protocol.TBinaryProtocol;
40 import org.apache.thrift.protocol.TProtocol;
41 import org.apache.thrift.protocol.TTupleProtocol;
42 import org.apache.thrift.transport.TMemoryBuffer;
43 import org.junit.jupiter.api.Test;
44 import thrift.test.ComparableUnion;
45 import thrift.test.Empty;
46 import thrift.test.RandomStuff;
47 import thrift.test.SomeEnum;
48 import thrift.test.StructWithAUnion;
49 import thrift.test.TestUnion;
50 import thrift.test.TestUnionMinusStringField;
51 
52 public class TestTUnion {
53 
54   @Test
testBasic()55   public void testBasic() throws Exception {
56     {
57       TestUnion union = new TestUnion();
58       assertFalse(union.isSet());
59       assertFalse(union.isSetI32_field());
60       assertNull(union.getFieldValue());
61     }
62     {
63       TestUnion union = new TestUnion(TestUnion._Fields.I32_FIELD, 25);
64       assertEquals(25, union.getFieldValue());
65       assertEquals(25, union.getFieldValue(TestUnion._Fields.I32_FIELD));
66       assertTrue(union.isSetI32_field());
67       assertThrows(
68           IllegalArgumentException.class,
69           () -> union.getFieldValue(TestUnion._Fields.STRING_FIELD));
70     }
71     {
72       TestUnion union = new TestUnion();
73       // should not throw an exception here
74       union.hashCode();
75       union.setI32_field(1);
76       assertEquals(1, union.getI32_field());
77       union.hashCode();
78       assertFalse(union.isSetString_field());
79 
80       assertThrows(Exception.class, union::getString_field);
81     }
82     {
83       TestUnion union = TestUnion.i32_field(1);
84       assertFalse(union.equals(null));
85     }
86     {
87       TestUnion union = TestUnion.enum_field(SomeEnum.ONE);
88       union.hashCode();
89     }
90     {
91       TestUnion union = new TestUnion();
92       // should not throw an exception
93       union.toString();
94     }
95   }
96 
97   @Test
testCompareTo()98   public void testCompareTo() throws Exception {
99     ComparableUnion cu = ComparableUnion.string_field("a");
100     ComparableUnion cu2 = ComparableUnion.string_field("b");
101 
102     assertEquals(0, cu.compareTo(cu));
103     assertEquals(0, cu2.compareTo(cu2));
104 
105     assertTrue(cu.compareTo(cu2) < 0);
106     assertTrue(cu2.compareTo(cu) > 0);
107 
108     cu2 = ComparableUnion.binary_field(ByteBuffer.wrap(new byte[] {2}));
109 
110     assertTrue(cu.compareTo(cu2) < 0);
111     assertTrue(cu2.compareTo(cu) > 0);
112 
113     cu = ComparableUnion.binary_field(ByteBuffer.wrap(new byte[] {1}));
114 
115     assertTrue(cu.compareTo(cu2) < 0);
116     assertTrue(cu2.compareTo(cu) > 0);
117 
118     TestUnion union1 = new TestUnion(TestUnion._Fields.STRUCT_LIST, new ArrayList<RandomStuff>());
119     TestUnion union2 = new TestUnion(TestUnion._Fields.STRUCT_LIST, new ArrayList<RandomStuff>());
120     assertEquals(0, union1.compareTo(union2));
121 
122     TestUnion union3 = new TestUnion(TestUnion._Fields.I32_SET, new HashSet<Integer>());
123     Set<Integer> i32_set = new HashSet<Integer>();
124     i32_set.add(1);
125     TestUnion union4 = new TestUnion(TestUnion._Fields.I32_SET, i32_set);
126     assertTrue(union3.compareTo(union4) < 0);
127 
128     Map<Integer, Integer> i32_map = new HashMap<Integer, Integer>();
129     i32_map.put(1, 1);
130     TestUnion union5 = new TestUnion(TestUnion._Fields.I32_MAP, i32_map);
131     TestUnion union6 = new TestUnion(TestUnion._Fields.I32_MAP, new HashMap<Integer, Integer>());
132     assertTrue(union5.compareTo(union6) > 0);
133   }
134 
135   @Test
testEquality()136   public void testEquality() throws Exception {
137     TestUnion union = new TestUnion(TestUnion._Fields.I32_FIELD, 25);
138 
139     TestUnion otherUnion = new TestUnion(TestUnion._Fields.STRING_FIELD, "blah!!!");
140 
141     assertFalse(union.equals(otherUnion));
142 
143     otherUnion = new TestUnion(TestUnion._Fields.I32_FIELD, 400);
144 
145     assertFalse(union.equals(otherUnion));
146 
147     otherUnion = new TestUnion(TestUnion._Fields.OTHER_I32_FIELD, 25);
148 
149     assertFalse(union.equals(otherUnion));
150   }
151 
152   @Test
testSerialization()153   public void testSerialization() throws Exception {
154     TestUnion union = new TestUnion(TestUnion._Fields.I32_FIELD, 25);
155     union.setI32_set(Collections.singleton(42));
156 
157     TMemoryBuffer buf = new TMemoryBuffer(0);
158     TProtocol proto = new TBinaryProtocol(buf);
159 
160     union.write(proto);
161 
162     TestUnion u2 = new TestUnion();
163 
164     u2.read(proto);
165 
166     assertEquals(u2, union);
167 
168     StructWithAUnion swau = new StructWithAUnion(u2);
169 
170     buf = new TMemoryBuffer(0);
171     proto = new TBinaryProtocol(buf);
172 
173     swau.write(proto);
174 
175     StructWithAUnion swau2 = new StructWithAUnion();
176     assertFalse(swau2.equals(swau));
177     swau2.read(proto);
178     assertEquals(swau2, swau);
179 
180     // this should NOT throw an exception.
181     buf = new TMemoryBuffer(0);
182     proto = new TBinaryProtocol(buf);
183 
184     swau.write(proto);
185     new Empty().read(proto);
186   }
187 
188   @Test
testTupleProtocolSerialization()189   public void testTupleProtocolSerialization() throws Exception {
190     TestUnion union = new TestUnion(TestUnion._Fields.I32_FIELD, 25);
191     union.setI32_set(Collections.singleton(42));
192 
193     TMemoryBuffer buf = new TMemoryBuffer(0);
194     TProtocol proto = new TTupleProtocol(buf);
195 
196     union.write(proto);
197 
198     TestUnion u2 = new TestUnion();
199 
200     u2.read(proto);
201 
202     assertEquals(u2, union);
203 
204     StructWithAUnion swau = new StructWithAUnion(u2);
205 
206     buf = new TMemoryBuffer(0);
207     proto = new TBinaryProtocol(buf);
208 
209     swau.write(proto);
210 
211     StructWithAUnion swau2 = new StructWithAUnion();
212     assertFalse(swau2.equals(swau));
213     swau2.read(proto);
214     assertEquals(swau2, swau);
215 
216     // this should NOT throw an exception.
217     buf = new TMemoryBuffer(0);
218     proto = new TTupleProtocol(buf);
219 
220     swau.write(proto);
221     new Empty().read(proto);
222   }
223 
224   @Test
testSkip()225   public void testSkip() throws Exception {
226     TestUnion tu = TestUnion.string_field("string");
227     byte[] tuSerialized = new TSerializer().serialize(tu);
228     TestUnionMinusStringField tums = new TestUnionMinusStringField();
229     new TDeserializer().deserialize(tums, tuSerialized);
230     assertNull(tums.getSetField());
231     assertNull(tums.getFieldValue());
232   }
233 
234   @Test
testDeepCopy()235   public void testDeepCopy() throws Exception {
236     byte[] bytes = {1, 2, 3};
237     ByteBuffer value = ByteBuffer.wrap(bytes);
238     ComparableUnion cu = ComparableUnion.binary_field(value);
239     ComparableUnion copy = cu.deepCopy();
240     assertEquals(cu, copy);
241     assertNotSame(cu.bufferForBinary_field().array(), copy.bufferForBinary_field().array());
242   }
243 
244   @Test
testToString()245   public void testToString() throws Exception {
246     byte[] bytes = {1, 2, 3};
247     ByteBuffer value = ByteBuffer.wrap(bytes);
248     ComparableUnion cu = ComparableUnion.binary_field(value);
249     String expectedString = "<ComparableUnion binary_field:01 02 03>";
250     assertEquals(expectedString, cu.toString());
251   }
252 
253   @Test
testJavaSerializable()254   public void testJavaSerializable() throws Exception {
255     ByteArrayOutputStream baos = new ByteArrayOutputStream();
256     ObjectOutputStream oos = new ObjectOutputStream(baos);
257 
258     TestUnion tu = TestUnion.string_field("string");
259 
260     // Serialize tu the Java way...
261     oos.writeObject(tu);
262     byte[] serialized = baos.toByteArray();
263 
264     // Attempt to deserialize it
265     ByteArrayInputStream bais = new ByteArrayInputStream(serialized);
266     ObjectInputStream ois = new ObjectInputStream(bais);
267     TestUnion tu2 = (TestUnion) ois.readObject();
268 
269     assertEquals(tu, tu2);
270   }
271 }
272