1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // https://developers.google.com/protocol-buffers/ 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions are 7 // met: 8 // 9 // * Redistributions of source code must retain the above copyright 10 // notice, this list of conditions and the following disclaimer. 11 // * Redistributions in binary form must reproduce the above 12 // copyright notice, this list of conditions and the following disclaimer 13 // in the documentation and/or other materials provided with the 14 // distribution. 15 // * Neither the name of Google Inc. nor the names of its 16 // contributors may be used to endorse or promote products derived from 17 // this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 package com.google.protobuf; 32 33 import com.google.protobuf.UnittestLite.TestAllTypesLite; 34 import com.google.protobuf.UnittestLite.TestPackedExtensionsLite; 35 import com.google.protobuf.UnittestLite.TestParsingMergeLite; 36 import protobuf_unittest.UnittestOptimizeFor; 37 import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize; 38 import protobuf_unittest.UnittestOptimizeFor.TestRequiredOptimizedForSize; 39 import protobuf_unittest.UnittestProto; 40 import protobuf_unittest.UnittestProto.ForeignMessage; 41 import protobuf_unittest.UnittestProto.TestAllTypes; 42 import protobuf_unittest.UnittestProto.TestEmptyMessage; 43 import protobuf_unittest.UnittestProto.TestParsingMerge; 44 import protobuf_unittest.UnittestProto.TestRequired; 45 46 import junit.framework.TestCase; 47 48 import java.io.ByteArrayInputStream; 49 import java.io.ByteArrayOutputStream; 50 import java.io.IOException; 51 import java.io.InputStream; 52 53 /** 54 * Unit test for {@link Parser}. 55 * 56 * @author liujisi@google.com (Pherl Liu) 57 */ 58 public class ParserTest extends TestCase { testGeneratedMessageParserSingleton()59 public void testGeneratedMessageParserSingleton() throws Exception { 60 for (int i = 0; i < 10; i++) { 61 assertEquals(TestAllTypes.parser(), TestUtil.getAllSet().getParserForType()); 62 } 63 } 64 assertRoundTripEquals(MessageLite message, ExtensionRegistryLite registry)65 private void assertRoundTripEquals(MessageLite message, 66 ExtensionRegistryLite registry) 67 throws Exception { 68 final byte[] data = message.toByteArray(); 69 final int offset = 20; 70 final int length = data.length; 71 final int padding = 30; 72 Parser<? extends MessageLite> parser = message.getParserForType(); 73 assertMessageEquals(message, parser.parseFrom(data, registry)); 74 assertMessageEquals(message, parser.parseFrom( 75 generatePaddingArray(data, offset, padding), 76 offset, length, registry)); 77 assertMessageEquals(message, parser.parseFrom( 78 message.toByteString(), registry)); 79 assertMessageEquals(message, parser.parseFrom( 80 new ByteArrayInputStream(data), registry)); 81 assertMessageEquals(message, parser.parseFrom( 82 CodedInputStream.newInstance(data), registry)); 83 } 84 85 @SuppressWarnings("unchecked") assertRoundTripEquals(MessageLite message)86 private void assertRoundTripEquals(MessageLite message) throws Exception { 87 final byte[] data = message.toByteArray(); 88 final int offset = 20; 89 final int length = data.length; 90 final int padding = 30; 91 92 Parser<MessageLite> parser = 93 (Parser<MessageLite>) message.getParserForType(); 94 assertMessageEquals(message, parser.parseFrom(data)); 95 assertMessageEquals(message, parser.parseFrom( 96 generatePaddingArray(data, offset, padding), 97 offset, length)); 98 assertMessageEquals(message, parser.parseFrom(message.toByteString())); 99 assertMessageEquals(message, parser.parseFrom( 100 new ByteArrayInputStream(data))); 101 assertMessageEquals(message, parser.parseFrom( 102 CodedInputStream.newInstance(data))); 103 } 104 assertMessageEquals( MessageLite expected, MessageLite actual)105 private void assertMessageEquals( 106 MessageLite expected, MessageLite actual) 107 throws Exception { 108 if (expected instanceof Message) { 109 assertEquals(expected, actual); 110 } else { 111 assertEquals(expected.toByteString(), actual.toByteString()); 112 } 113 } 114 generatePaddingArray(byte[] data, int offset, int padding)115 private byte[] generatePaddingArray(byte[] data, int offset, int padding) { 116 byte[] result = new byte[offset + data.length + padding]; 117 System.arraycopy(data, 0, result, offset, data.length); 118 return result; 119 } 120 testNormalMessage()121 public void testNormalMessage() throws Exception { 122 assertRoundTripEquals(TestUtil.getAllSet()); 123 } 124 125 testParsePartial()126 public void testParsePartial() throws Exception { 127 assertParsePartial(TestRequired.parser(), TestRequired.newBuilder().setA(1).buildPartial()); 128 } 129 assertParsePartial( Parser<T> parser, T partialMessage)130 private <T extends MessageLite> void assertParsePartial( 131 Parser<T> parser, T partialMessage) throws Exception { 132 final String errorString = 133 "Should throw exceptions when the parsed message isn't initialized."; 134 135 // parsePartialFrom should pass. 136 byte[] data = partialMessage.toByteArray(); 137 assertEquals(partialMessage, parser.parsePartialFrom(data)); 138 assertEquals(partialMessage, parser.parsePartialFrom( 139 partialMessage.toByteString())); 140 assertEquals(partialMessage, parser.parsePartialFrom( 141 new ByteArrayInputStream(data))); 142 assertEquals(partialMessage, parser.parsePartialFrom( 143 CodedInputStream.newInstance(data))); 144 145 // parseFrom(ByteArray) 146 try { 147 parser.parseFrom(partialMessage.toByteArray()); 148 fail(errorString); 149 } catch (InvalidProtocolBufferException e) { 150 // pass. 151 } 152 153 // parseFrom(ByteString) 154 try { 155 parser.parseFrom(partialMessage.toByteString()); 156 fail(errorString); 157 } catch (InvalidProtocolBufferException e) { 158 // pass. 159 } 160 161 // parseFrom(InputStream) 162 try { 163 parser.parseFrom(new ByteArrayInputStream(partialMessage.toByteArray())); 164 fail(errorString); 165 } catch (IOException e) { 166 // pass. 167 } 168 169 // parseFrom(CodedInputStream) 170 try { 171 parser.parseFrom(CodedInputStream.newInstance( 172 partialMessage.toByteArray())); 173 fail(errorString); 174 } catch (IOException e) { 175 // pass. 176 } 177 } 178 testParseExtensions()179 public void testParseExtensions() throws Exception { 180 assertRoundTripEquals(TestUtil.getAllExtensionsSet(), 181 TestUtil.getExtensionRegistry()); 182 assertRoundTripEquals( 183 TestUtilLite.getAllLiteExtensionsSet(), TestUtilLite.getExtensionRegistryLite()); 184 } 185 testParsePacked()186 public void testParsePacked() throws Exception { 187 assertRoundTripEquals(TestUtil.getPackedSet()); 188 assertRoundTripEquals(TestUtil.getPackedExtensionsSet(), 189 TestUtil.getExtensionRegistry()); 190 assertRoundTripEquals( 191 TestUtilLite.getLitePackedExtensionsSet(), TestUtilLite.getExtensionRegistryLite()); 192 } 193 testParseDelimitedTo()194 public void testParseDelimitedTo() throws Exception { 195 // Write normal Message. 196 TestAllTypes normalMessage = TestUtil.getAllSet(); 197 ByteArrayOutputStream output = new ByteArrayOutputStream(); 198 normalMessage.writeDelimitedTo(output); 199 200 // Write MessageLite with packed extension fields. 201 TestPackedExtensionsLite packedMessage = TestUtilLite.getLitePackedExtensionsSet(); 202 packedMessage.writeDelimitedTo(output); 203 204 InputStream input = new ByteArrayInputStream(output.toByteArray()); 205 assertMessageEquals( 206 normalMessage, 207 normalMessage.getParserForType().parseDelimitedFrom(input)); 208 assertMessageEquals( 209 packedMessage, 210 packedMessage 211 .getParserForType() 212 .parseDelimitedFrom(input, TestUtilLite.getExtensionRegistryLite())); 213 } 214 testParseUnknownFields()215 public void testParseUnknownFields() throws Exception { 216 // All fields will be treated as unknown fields in emptyMessage. 217 TestEmptyMessage emptyMessage = 218 TestEmptyMessage.parser().parseFrom(TestUtil.getAllSet().toByteString()); 219 assertEquals( 220 TestUtil.getAllSet().toByteString(), 221 emptyMessage.toByteString()); 222 } 223 224 testOptimizeForSize()225 public void testOptimizeForSize() throws Exception { 226 TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder(); 227 builder.setI(12).setMsg(ForeignMessage.newBuilder().setC(34).build()); 228 builder.setExtension(TestOptimizedForSize.testExtension, 56); 229 builder.setExtension(TestOptimizedForSize.testExtension2, 230 TestRequiredOptimizedForSize.newBuilder().setX(78).build()); 231 232 TestOptimizedForSize message = builder.build(); 233 ExtensionRegistry registry = ExtensionRegistry.newInstance(); 234 UnittestOptimizeFor.registerAllExtensions(registry); 235 236 assertRoundTripEquals(message, registry); 237 } 238 239 /** Helper method for {@link #testParsingMerge()}.*/ assertMessageMerged(TestAllTypes allTypes)240 private void assertMessageMerged(TestAllTypes allTypes) 241 throws Exception { 242 assertEquals(3, allTypes.getOptionalInt32()); 243 assertEquals(2, allTypes.getOptionalInt64()); 244 assertEquals("hello", allTypes.getOptionalString()); 245 } 246 247 /** Helper method for {@link #testParsingMergeLite()}.*/ assertMessageMerged(TestAllTypesLite allTypes)248 private void assertMessageMerged(TestAllTypesLite allTypes) 249 throws Exception { 250 assertEquals(3, allTypes.getOptionalInt32()); 251 assertEquals(2, allTypes.getOptionalInt64()); 252 assertEquals("hello", allTypes.getOptionalString()); 253 } 254 testParsingMerge()255 public void testParsingMerge() throws Exception { 256 // Build messages. 257 TestAllTypes.Builder builder = TestAllTypes.newBuilder(); 258 TestAllTypes msg1 = builder.setOptionalInt32(1).build(); 259 builder.clear(); 260 TestAllTypes msg2 = builder.setOptionalInt64(2).build(); 261 builder.clear(); 262 TestAllTypes msg3 = builder.setOptionalInt32(3) 263 .setOptionalString("hello").build(); 264 265 // Build groups. 266 TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG1 = 267 TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder() 268 .setField1(msg1).build(); 269 TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG2 = 270 TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder() 271 .setField1(msg2).build(); 272 TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG3 = 273 TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder() 274 .setField1(msg3).build(); 275 TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG1 = 276 TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder() 277 .setField1(msg1).build(); 278 TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG2 = 279 TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder() 280 .setField1(msg2).build(); 281 TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG3 = 282 TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder() 283 .setField1(msg3).build(); 284 285 // Assign and serialize RepeatedFieldsGenerator. 286 ByteString data = TestParsingMerge.RepeatedFieldsGenerator.newBuilder() 287 .addField1(msg1).addField1(msg2).addField1(msg3) 288 .addField2(msg1).addField2(msg2).addField2(msg3) 289 .addField3(msg1).addField3(msg2).addField3(msg3) 290 .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3) 291 .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3) 292 .addExt1(msg1).addExt1(msg2).addExt1(msg3) 293 .addExt2(msg1).addExt2(msg2).addExt2(msg3) 294 .build().toByteString(); 295 296 // Parse TestParsingMerge. 297 ExtensionRegistry registry = ExtensionRegistry.newInstance(); 298 UnittestProto.registerAllExtensions(registry); 299 TestParsingMerge parsingMerge = TestParsingMerge.parser().parseFrom(data, registry); 300 301 // Required and optional fields should be merged. 302 assertMessageMerged(parsingMerge.getRequiredAllTypes()); 303 assertMessageMerged(parsingMerge.getOptionalAllTypes()); 304 assertMessageMerged( 305 parsingMerge.getOptionalGroup().getOptionalGroupAllTypes()); 306 assertMessageMerged(parsingMerge.getExtension( 307 TestParsingMerge.optionalExt)); 308 309 // Repeated fields should not be merged. 310 assertEquals(3, parsingMerge.getRepeatedAllTypesCount()); 311 assertEquals(3, parsingMerge.getRepeatedGroupCount()); 312 assertEquals(3, parsingMerge.getExtensionCount( 313 TestParsingMerge.repeatedExt)); 314 } 315 testParsingMergeLite()316 public void testParsingMergeLite() throws Exception { 317 // Build messages. 318 TestAllTypesLite.Builder builder = 319 TestAllTypesLite.newBuilder(); 320 TestAllTypesLite msg1 = builder.setOptionalInt32(1).build(); 321 builder.clear(); 322 TestAllTypesLite msg2 = builder.setOptionalInt64(2).build(); 323 builder.clear(); 324 TestAllTypesLite msg3 = builder.setOptionalInt32(3) 325 .setOptionalString("hello").build(); 326 327 // Build groups. 328 TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG1 = 329 TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder() 330 .setField1(msg1).build(); 331 TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG2 = 332 TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder() 333 .setField1(msg2).build(); 334 TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG3 = 335 TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder() 336 .setField1(msg3).build(); 337 TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG1 = 338 TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder() 339 .setField1(msg1).build(); 340 TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG2 = 341 TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder() 342 .setField1(msg2).build(); 343 TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG3 = 344 TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder() 345 .setField1(msg3).build(); 346 347 // Assign and serialize RepeatedFieldsGenerator. 348 ByteString data = TestParsingMergeLite.RepeatedFieldsGenerator.newBuilder() 349 .addField1(msg1).addField1(msg2).addField1(msg3) 350 .addField2(msg1).addField2(msg2).addField2(msg3) 351 .addField3(msg1).addField3(msg2).addField3(msg3) 352 .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3) 353 .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3) 354 .addExt1(msg1).addExt1(msg2).addExt1(msg3) 355 .addExt2(msg1).addExt2(msg2).addExt2(msg3) 356 .build().toByteString(); 357 358 // Parse TestParsingMergeLite. 359 ExtensionRegistry registry = ExtensionRegistry.newInstance(); 360 UnittestLite.registerAllExtensions(registry); 361 TestParsingMergeLite parsingMerge = TestParsingMergeLite.parser().parseFrom(data, registry); 362 363 // Required and optional fields should be merged. 364 assertMessageMerged(parsingMerge.getRequiredAllTypes()); 365 assertMessageMerged(parsingMerge.getOptionalAllTypes()); 366 assertMessageMerged( 367 parsingMerge.getOptionalGroup().getOptionalGroupAllTypes()); 368 assertMessageMerged(parsingMerge.getExtension( 369 TestParsingMergeLite.optionalExt)); 370 371 // Repeated fields should not be merged. 372 assertEquals(3, parsingMerge.getRepeatedAllTypesCount()); 373 assertEquals(3, parsingMerge.getRepeatedGroupCount()); 374 assertEquals(3, parsingMerge.getExtensionCount( 375 TestParsingMergeLite.repeatedExt)); 376 } 377 } 378