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
10 * http://www.apache.org/licenses/LICENSE-2.0
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
19 package org
.apache
.thrift
;
21 import java
.io
.ByteArrayInputStream
;
22 import java
.io
.ByteArrayOutputStream
;
23 import java
.io
.ObjectInputStream
;
24 import java
.io
.ObjectOutputStream
;
25 import java
.nio
.ByteBuffer
;
26 import java
.util
.HashMap
;
29 import junit
.framework
.TestCase
;
31 import org
.apache
.thrift
.meta_data
.FieldMetaData
;
32 import org
.apache
.thrift
.meta_data
.ListMetaData
;
33 import org
.apache
.thrift
.meta_data
.MapMetaData
;
34 import org
.apache
.thrift
.meta_data
.SetMetaData
;
35 import org
.apache
.thrift
.meta_data
.StructMetaData
;
36 import org
.apache
.thrift
.protocol
.TBinaryProtocol
;
37 import org
.apache
.thrift
.protocol
.TType
;
39 import thrift
.test
.Bonk
;
40 import thrift
.test
.CrazyNesting
;
41 import thrift
.test
.HolyMoley
;
42 import thrift
.test
.Insanity
;
43 import thrift
.test
.JavaTestHelper
;
44 import thrift
.test
.Nesting
;
45 import thrift
.test
.Numberz
;
46 import thrift
.test
.OneOfEach
;
47 import thrift
.test
.StructA
;
48 import thrift
.test
.StructB
;
49 import thrift
.test
.Xtruct
;
51 public class TestStruct
extends TestCase
{
52 public void testIdentity() throws Exception
{
53 TSerializer binarySerializer
= new TSerializer(new TBinaryProtocol
.Factory());
54 TDeserializer binaryDeserializer
= new TDeserializer(new TBinaryProtocol
.Factory());
56 OneOfEach ooe
= Fixtures
.oneOfEach
;
58 Nesting n
= new Nesting();
60 n
.my_ooe
.integer16
= 16;
61 n
.my_ooe
.integer32
= 32;
62 n
.my_ooe
.integer64
= 64;
63 n
.my_ooe
.double_precision
= (Math
.sqrt(5)+1)/2;
64 n
.my_ooe
.some_characters
= ":R (me going \"rrrr\")";
65 n
.my_ooe
.zomg_unicode
= "\u04c0\u216e\u039d\u0020\u041d\u03bf\u217f"+
66 "\u043e\u0261\u0433\u0430\u03c1\u210e\u0020"+
67 "\u0391\u0074\u0074\u03b1\u217d\u03ba\u01c3"+
69 n
.my_bonk
= Fixtures
.nesting
.my_bonk
;
71 HolyMoley hm
= Fixtures
.holyMoley
;
73 OneOfEach ooe2
= new OneOfEach();
74 binaryDeserializer
.deserialize(
76 binarySerializer
.serialize(ooe
));
78 assertEquals(ooe
, ooe2
);
79 assertEquals(ooe
.hashCode(), ooe2
.hashCode());
82 Nesting n2
= new Nesting();
83 binaryDeserializer
.deserialize(
85 binarySerializer
.serialize(n
));
88 assertEquals(n
.hashCode(), n2
.hashCode());
90 HolyMoley hm2
= new HolyMoley();
91 binaryDeserializer
.deserialize(
93 binarySerializer
.serialize(hm
));
95 assertEquals(hm
, hm2
);
96 assertEquals(hm
.hashCode(), hm2
.hashCode());
99 public void testDeepCopy() throws Exception
{
100 TSerializer binarySerializer
= new TSerializer(new TBinaryProtocol
.Factory());
101 TDeserializer binaryDeserializer
= new TDeserializer(new TBinaryProtocol
.Factory());
103 HolyMoley hm
= Fixtures
.holyMoley
;
105 byte[] binaryCopy
= binarySerializer
.serialize(hm
);
106 HolyMoley hmCopy
= new HolyMoley();
107 binaryDeserializer
.deserialize(hmCopy
, binaryCopy
);
108 HolyMoley hmCopy2
= new HolyMoley(hm
);
110 assertEquals(hm
, hmCopy
);
111 assertEquals(hmCopy
, hmCopy2
);
113 // change binary value in original object
114 hm
.big
.get(0).base64
.array()[0]++;
115 // make sure the change didn't propagate to the copied object
116 assertFalse(hm
.equals(hmCopy2
));
117 hm
.big
.get(0).base64
.array()[0]--; // undo change
119 hmCopy2
.bonks
.get("two").get(1).message
= "What else?";
121 assertFalse(hm
.equals(hmCopy2
));
124 public void testCompareTo() throws Exception
{
125 Bonk bonk1
= new Bonk();
126 Bonk bonk2
= new Bonk();
128 // Compare empty thrift objects.
129 assertEquals(0, bonk1
.compareTo(bonk2
));
131 bonk1
.setMessage("m");
133 // Compare one thrift object with a filled in field and another without it.
134 assertTrue(bonk1
.compareTo(bonk2
) > 0);
135 assertTrue(bonk2
.compareTo(bonk1
) < 0);
137 // Compare both have filled-in fields.
138 bonk2
.setMessage("z");
139 assertTrue(bonk1
.compareTo(bonk2
) < 0);
140 assertTrue(bonk2
.compareTo(bonk1
) > 0);
142 // Compare bonk1 has a field filled in that bonk2 doesn't.
144 assertTrue(bonk1
.compareTo(bonk2
) > 0);
145 assertTrue(bonk2
.compareTo(bonk1
) < 0);
147 // Compare bonk1 and bonk2 equal.
149 bonk2
.setMessage("m");
150 assertEquals(0, bonk1
.compareTo(bonk2
));
153 public void testCompareToWithDataStructures() {
154 Insanity insanity1
= new Insanity();
155 Insanity insanity2
= new Insanity();
158 expectEquals(insanity1
, insanity2
);
160 insanity1
.setUserMap(new HashMap
<Numberz
, Long
>());
161 // insanity1.map = {}, insanity2.map = null
162 expectGreaterThan(insanity1
, insanity2
);
164 // insanity1.map = {2:1}, insanity2.map = null
165 insanity1
.getUserMap().put(Numberz
.TWO
, 1l);
166 expectGreaterThan(insanity1
, insanity2
);
168 // insanity1.map = {2:1}, insanity2.map = {}
169 insanity2
.setUserMap(new HashMap
<Numberz
, Long
>());
170 expectGreaterThan(insanity1
, insanity2
);
172 // insanity1.map = {2:1}, insanity2.map = {2:2}
173 insanity2
.getUserMap().put(Numberz
.TWO
, 2l);
174 expectLessThan(insanity1
, insanity2
);
176 // insanity1.map = {2:1, 3:5}, insanity2.map = {2:2}
177 insanity1
.getUserMap().put(Numberz
.THREE
, 5l);
178 expectGreaterThan(insanity1
, insanity2
);
180 // insanity1.map = {2:1, 3:5}, insanity2.map = {2:1, 4:5}
181 insanity2
.getUserMap().put(Numberz
.TWO
, 1l);
182 insanity2
.getUserMap().put(Numberz
.FIVE
, 5l);
183 expectLessThan(insanity1
, insanity2
);
186 private void expectLessThan(Insanity insanity1
, Insanity insanity2
) {
187 int compareTo
= insanity1
.compareTo(insanity2
);
188 assertTrue(insanity1
+ " should be less than " + insanity2
+ ", but is: " + compareTo
, compareTo
< 0);
191 private void expectGreaterThan(Insanity insanity1
, Insanity insanity2
) {
192 int compareTo
= insanity1
.compareTo(insanity2
);
193 assertTrue(insanity1
+ " should be greater than " + insanity2
+ ", but is: " + compareTo
, compareTo
> 0);
196 private void expectEquals(Insanity insanity1
, Insanity insanity2
) {
197 int compareTo
= insanity1
.compareTo(insanity2
);
198 assertEquals(insanity1
+ " should be equal to " + insanity2
+ ", but is: " + compareTo
, 0, compareTo
);
201 public void testMetaData() throws Exception
{
202 Map
<CrazyNesting
._Fields
, FieldMetaData
> mdMap
= CrazyNesting
.metaDataMap
;
204 // Check for struct fields existence
205 assertEquals(4, mdMap
.size());
206 assertTrue(mdMap
.containsKey(CrazyNesting
._Fields
.SET_FIELD
));
207 assertTrue(mdMap
.containsKey(CrazyNesting
._Fields
.LIST_FIELD
));
208 assertTrue(mdMap
.containsKey(CrazyNesting
._Fields
.STRING_FIELD
));
209 assertTrue(mdMap
.containsKey(CrazyNesting
._Fields
.BINARY_FIELD
));
211 // Check for struct fields contents
212 assertEquals("string_field", mdMap
.get(CrazyNesting
._Fields
.STRING_FIELD
).fieldName
);
213 assertEquals("list_field", mdMap
.get(CrazyNesting
._Fields
.LIST_FIELD
).fieldName
);
214 assertEquals("set_field", mdMap
.get(CrazyNesting
._Fields
.SET_FIELD
).fieldName
);
215 assertEquals("binary_field", mdMap
.get(CrazyNesting
._Fields
.BINARY_FIELD
).fieldName
);
217 assertEquals(TFieldRequirementType
.DEFAULT
, mdMap
.get(CrazyNesting
._Fields
.STRING_FIELD
).requirementType
);
218 assertEquals(TFieldRequirementType
.REQUIRED
, mdMap
.get(CrazyNesting
._Fields
.LIST_FIELD
).requirementType
);
219 assertEquals(TFieldRequirementType
.OPTIONAL
, mdMap
.get(CrazyNesting
._Fields
.SET_FIELD
).requirementType
);
221 assertEquals(TType
.STRING
, mdMap
.get(CrazyNesting
._Fields
.STRING_FIELD
).valueMetaData
.type
);
222 assertFalse(mdMap
.get(CrazyNesting
._Fields
.STRING_FIELD
).valueMetaData
.isBinary());
223 assertEquals(TType
.LIST
, mdMap
.get(CrazyNesting
._Fields
.LIST_FIELD
).valueMetaData
.type
);
224 assertEquals(TType
.SET
, mdMap
.get(CrazyNesting
._Fields
.SET_FIELD
).valueMetaData
.type
);
225 assertEquals(TType
.STRING
, mdMap
.get(CrazyNesting
._Fields
.BINARY_FIELD
).valueMetaData
.type
);
226 assertTrue(mdMap
.get(CrazyNesting
._Fields
.BINARY_FIELD
).valueMetaData
.isBinary());
228 // Check nested structures
229 assertTrue(mdMap
.get(CrazyNesting
._Fields
.LIST_FIELD
).valueMetaData
.isContainer());
231 assertFalse(mdMap
.get(CrazyNesting
._Fields
.LIST_FIELD
).valueMetaData
.isStruct());
233 assertEquals(TType
.STRUCT
, ((MapMetaData
)((ListMetaData
)((SetMetaData
)((MapMetaData
)((MapMetaData
)((ListMetaData
)mdMap
.get(CrazyNesting
._Fields
.LIST_FIELD
).valueMetaData
).elemMetaData
).valueMetaData
).valueMetaData
).elemMetaData
).elemMetaData
).keyMetaData
.type
);
235 assertEquals(Insanity
.class, ((StructMetaData
)((MapMetaData
)((ListMetaData
)((SetMetaData
)((MapMetaData
)((MapMetaData
)((ListMetaData
)mdMap
.get(CrazyNesting
._Fields
.LIST_FIELD
).valueMetaData
).elemMetaData
).valueMetaData
).valueMetaData
).elemMetaData
).elemMetaData
).keyMetaData
).structClass
);
237 // Check that FieldMetaData contains a map with metadata for all generated struct classes
238 assertNotNull(FieldMetaData
.getStructMetaDataMap(CrazyNesting
.class));
239 assertNotNull(FieldMetaData
.getStructMetaDataMap(Insanity
.class));
240 assertNotNull(FieldMetaData
.getStructMetaDataMap(Xtruct
.class));
242 assertEquals(CrazyNesting
.metaDataMap
, FieldMetaData
.getStructMetaDataMap(CrazyNesting
.class));
243 assertEquals(Insanity
.metaDataMap
, FieldMetaData
.getStructMetaDataMap(Insanity
.class));
245 for (Map
.Entry
<?
extends TFieldIdEnum
, FieldMetaData
> mdEntry
: mdMap
.entrySet()) {
246 assertEquals(mdEntry
.getKey(), CrazyNesting
._Fields
.findByName(mdEntry
.getValue().fieldName
));
249 MapMetaData vmd
= (MapMetaData
)Insanity
.metaDataMap
.get(Insanity
._Fields
.USER_MAP
).valueMetaData
;
250 assertTrue(vmd
.valueMetaData
.isTypedef());
251 assertFalse(vmd
.keyMetaData
.isTypedef());
254 public void testToString() throws Exception
{
255 JavaTestHelper object
= new JavaTestHelper();
259 object
.req_bin
= ByteBuffer
.wrap(new byte[] {
260 0, -1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12, -13, 14, -15,
261 16, -17, 18, -19, 20, -21, 22, -23, 24, -25, 26, -27, 28, -29,
262 30, -31, 32, -33, 34, -35, 36, -37, 38, -39, 40, -41, 42, -43, 44,
263 -45, 46, -47, 48, -49, 50, -51, 52, -53, 54, -55, 56, -57, 58, -59,
264 60, -61, 62, -63, 64, -65, 66, -67, 68, -69, 70, -71, 72, -73, 74,
265 -75, 76, -77, 78, -79, 80, -81, 82, -83, 84, -85, 86, -87, 88, -89,
266 90, -91, 92, -93, 94, -95, 96, -97, 98, -99, 100, -101, 102, -103,
267 104, -105, 106, -107, 108, -109, 110, -111, 112, -113, 114, -115,
268 116, -117, 118, -119, 120, -121, 122, -123, 124, -125, 126, -127,
271 assertEquals("JavaTestHelper(req_int:0, req_obj:, req_bin:"+
272 "00 FF 02 FD 04 FB 06 F9 08 F7 0A F5 0C F3 0E F1 10 EF 12 ED 14 "+
273 "EB 16 E9 18 E7 1A E5 1C E3 1E E1 20 DF 22 DD 24 DB 26 D9 28 D7 "+
274 "2A D5 2C D3 2E D1 30 CF 32 CD 34 CB 36 C9 38 C7 3A C5 3C C3 3E "+
275 "C1 40 BF 42 BD 44 BB 46 B9 48 B7 4A B5 4C B3 4E B1 50 AF 52 AD "+
276 "54 AB 56 A9 58 A7 5A A5 5C A3 5E A1 60 9F 62 9D 64 9B 66 99 68 "+
277 "97 6A 95 6C 93 6E 91 70 8F 72 8D 74 8B 76 89 78 87 7A 85 7C 83 "+
281 object
.req_bin
= ByteBuffer
.wrap(new byte[] {
282 0, -1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12, -13, 14, -15,
283 16, -17, 18, -19, 20, -21, 22, -23, 24, -25, 26, -27, 28, -29,
284 30, -31, 32, -33, 34, -35, 36, -37, 38, -39, 40, -41, 42, -43, 44,
285 -45, 46, -47, 48, -49, 50, -51, 52, -53, 54, -55, 56, -57, 58, -59,
286 60, -61, 62, -63, 64, -65, 66, -67, 68, -69, 70, -71, 72, -73, 74,
287 -75, 76, -77, 78, -79, 80, -81, 82, -83, 84, -85, 86, -87, 88, -89,
288 90, -91, 92, -93, 94, -95, 96, -97, 98, -99, 100, -101, 102, -103,
289 104, -105, 106, -107, 108, -109, 110, -111, 112, -113, 114, -115,
290 116, -117, 118, -119, 120, -121, 122, -123, 124, -125, 126, -127,
294 assertEquals("JavaTestHelper(req_int:0, req_obj:, req_bin:"+
295 "00 FF 02 FD 04 FB 06 F9 08 F7 0A F5 0C F3 0E F1 10 EF 12 ED 14 "+
296 "EB 16 E9 18 E7 1A E5 1C E3 1E E1 20 DF 22 DD 24 DB 26 D9 28 D7 "+
297 "2A D5 2C D3 2E D1 30 CF 32 CD 34 CB 36 C9 38 C7 3A C5 3C C3 3E "+
298 "C1 40 BF 42 BD 44 BB 46 B9 48 B7 4A B5 4C B3 4E B1 50 AF 52 AD "+
299 "54 AB 56 A9 58 A7 5A A5 5C A3 5E A1 60 9F 62 9D 64 9B 66 99 68 "+
300 "97 6A 95 6C 93 6E 91 70 8F 72 8D 74 8B 76 89 78 87 7A 85 7C 83 "+
304 object
.req_bin
= ByteBuffer
.wrap(new byte[] {});
305 object
.setOpt_binIsSet(true);
307 assertEquals("JavaTestHelper(req_int:0, req_obj:, req_bin:)",
311 private static void assertArrayEquals(byte[] expected
, byte[] actual
) {
312 if (!java
.util
.Arrays
.equals(expected
, actual
)) {
313 fail("Expected byte array did not match actual.");
317 public void testBytesBufferFeatures() throws Exception
{
319 final String testString
= "testBytesBufferFeatures";
320 final JavaTestHelper o
= new JavaTestHelper();
322 o
.setReq_bin((ByteBuffer
)null);
323 assertNull(o
.getReq_bin());
325 o
.setReq_bin(ByteBuffer
.wrap(testString
.getBytes()));
326 assertArrayEquals(testString
.getBytes(), o
.getReq_bin());
328 o
.setReq_bin((byte[])null);
329 assertNull(o
.getReq_bin());
331 o
.setReq_bin(testString
.getBytes());
332 assertArrayEquals(testString
.getBytes(), o
.getReq_bin());
334 o
.setFieldValue(JavaTestHelper
._Fields
.REQ_BIN
, null);
335 assertNull(o
.getReq_bin());
337 o
.setFieldValue(JavaTestHelper
._Fields
.REQ_BIN
, testString
.getBytes());
338 assertArrayEquals(testString
.getBytes(), o
.getReq_bin());
340 o
.setFieldValue(JavaTestHelper
._Fields
.REQ_BIN
, null);
341 assertNull(o
.getReq_bin());
343 o
.setFieldValue(JavaTestHelper
._Fields
.REQ_BIN
, ByteBuffer
.wrap(testString
.getBytes()));
344 assertArrayEquals(testString
.getBytes(), o
.getReq_bin());
347 public void testJavaSerializable() throws Exception
{
348 ByteArrayOutputStream baos
= new ByteArrayOutputStream();
349 ObjectOutputStream oos
= new ObjectOutputStream(baos
);
351 OneOfEach ooe
= Fixtures
.oneOfEach
;
353 // Serialize ooe the Java way...
354 oos
.writeObject(ooe
);
355 byte[] serialized
= baos
.toByteArray();
357 // Attempt to deserialize it
358 ByteArrayInputStream bais
= new ByteArrayInputStream(serialized
);
359 ObjectInputStream ois
= new ObjectInputStream(bais
);
360 OneOfEach ooe2
= (OneOfEach
) ois
.readObject();
362 assertEquals(ooe
, ooe2
);
365 public void testSubStructValidation() throws Exception
{
366 StructA valid
= new StructA("valid");
367 StructA invalid
= new StructA();
369 StructB b
= new StructB();
373 } catch (TException e
) {
377 b
= new StructB().setAb(valid
);
380 b
= new StructB().setAb(invalid
);
384 } catch (TException e
) {
388 b
= new StructB().setAb(valid
).setAa(invalid
);
392 } catch (TException e
) {