• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 protobuf_unittest.UnittestMset.RawMessageSet;
34 import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
35 import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
36 import protobuf_unittest.UnittestProto;
37 import protobuf_unittest.UnittestProto.TestAllExtensions;
38 import protobuf_unittest.UnittestProto.TestAllTypes;
39 import protobuf_unittest.UnittestProto.TestExtensionInsideTable;
40 import protobuf_unittest.UnittestProto.TestFieldOrderings;
41 import protobuf_unittest.UnittestProto.TestOneof2;
42 import protobuf_unittest.UnittestProto.TestOneofBackwardsCompatible;
43 import protobuf_unittest.UnittestProto.TestPackedExtensions;
44 import protobuf_unittest.UnittestProto.TestPackedTypes;
45 import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet;
46 import java.io.ByteArrayInputStream;
47 import java.io.ByteArrayOutputStream;
48 import java.util.List;
49 import junit.framework.TestCase;
50 
51 /**
52  * Tests related to parsing and serialization.
53  *
54  * @author kenton@google.com (Kenton Varda)
55  */
56 public class WireFormatTest extends TestCase {
57 
58   private static final int TYPE_ID_1 =
59       TestMessageSetExtension1.getDescriptor().getExtensions().get(0).getNumber();
60   private static final int TYPE_ID_2 =
61       TestMessageSetExtension2.getDescriptor().getExtensions().get(0).getNumber();
62   private static final int UNKNOWN_TYPE_ID = 1550055;
63 
testSerialization()64   public void testSerialization() throws Exception {
65     TestAllTypes message = TestUtil.getAllSet();
66 
67     ByteString rawBytes = message.toByteString();
68     assertEquals(rawBytes.size(), message.getSerializedSize());
69 
70     TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
71 
72     TestUtil.assertAllFieldsSet(message2);
73   }
74 
testSerializationPacked()75   public void testSerializationPacked() throws Exception {
76     TestPackedTypes message = TestUtil.getPackedSet();
77 
78     ByteString rawBytes = message.toByteString();
79     assertEquals(rawBytes.size(), message.getSerializedSize());
80 
81     TestPackedTypes message2 = TestPackedTypes.parseFrom(rawBytes);
82 
83     TestUtil.assertPackedFieldsSet(message2);
84   }
85 
testSerializeExtensions()86   public void testSerializeExtensions() throws Exception {
87     // TestAllTypes and TestAllExtensions should have compatible wire formats,
88     // so if we serialize a TestAllExtensions then parse it as TestAllTypes
89     // it should work.
90 
91     TestAllExtensions message = TestUtil.getAllExtensionsSet();
92     ByteString rawBytes = message.toByteString();
93     assertEquals(rawBytes.size(), message.getSerializedSize());
94 
95     TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
96 
97     TestUtil.assertAllFieldsSet(message2);
98   }
99 
testSerializePackedExtensions()100   public void testSerializePackedExtensions() throws Exception {
101     // TestPackedTypes and TestPackedExtensions should have compatible wire
102     // formats; check that they serialize to the same string.
103     TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
104     ByteString rawBytes = message.toByteString();
105 
106     TestPackedTypes message2 = TestUtil.getPackedSet();
107     ByteString rawBytes2 = message2.toByteString();
108 
109     assertEquals(rawBytes, rawBytes2);
110   }
111 
testSerializationPackedWithoutGetSerializedSize()112   public void testSerializationPackedWithoutGetSerializedSize() throws Exception {
113     // Write directly to an OutputStream, without invoking getSerializedSize()
114     // This used to be a bug where the size of a packed field was incorrect,
115     // since getSerializedSize() was never invoked.
116     TestPackedTypes message = TestUtil.getPackedSet();
117 
118     // Directly construct a CodedOutputStream around the actual OutputStream,
119     // in case writeTo(OutputStream output) invokes getSerializedSize();
120     ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
121     CodedOutputStream codedOutput = CodedOutputStream.newInstance(outputStream);
122 
123     message.writeTo(codedOutput);
124 
125     codedOutput.flush();
126 
127     TestPackedTypes message2 = TestPackedTypes.parseFrom(outputStream.toByteArray());
128 
129     TestUtil.assertPackedFieldsSet(message2);
130   }
131 
testParseExtensions()132   public void testParseExtensions() throws Exception {
133     // TestAllTypes and TestAllExtensions should have compatible wire formats,
134     // so if we serialize a TestAllTypes then parse it as TestAllExtensions
135     // it should work.
136 
137     TestAllTypes message = TestUtil.getAllSet();
138     ByteString rawBytes = message.toByteString();
139 
140     ExtensionRegistryLite registry = TestUtil.getExtensionRegistry();
141 
142     TestAllExtensions message2 = TestAllExtensions.parseFrom(rawBytes, registry);
143 
144     TestUtil.assertAllExtensionsSet(message2);
145   }
146 
testParsePackedExtensions()147   public void testParsePackedExtensions() throws Exception {
148     // Ensure that packed extensions can be properly parsed.
149     TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
150     ByteString rawBytes = message.toByteString();
151 
152     ExtensionRegistryLite registry = TestUtil.getExtensionRegistry();
153 
154     TestPackedExtensions message2 = TestPackedExtensions.parseFrom(rawBytes, registry);
155 
156     TestUtil.assertPackedExtensionsSet(message2);
157   }
158 
testSerializeDelimited()159   public void testSerializeDelimited() throws Exception {
160     ByteArrayOutputStream output = new ByteArrayOutputStream();
161     TestUtil.getAllSet().writeDelimitedTo(output);
162     output.write(12);
163     TestUtil.getPackedSet().writeDelimitedTo(output);
164     output.write(34);
165 
166     ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
167 
168     TestUtil.assertAllFieldsSet(TestAllTypes.parseDelimitedFrom(input));
169     assertEquals(12, input.read());
170     TestUtil.assertPackedFieldsSet(TestPackedTypes.parseDelimitedFrom(input));
171     assertEquals(34, input.read());
172     assertEquals(-1, input.read());
173 
174     // We're at EOF, so parsing again should return null.
175     assertTrue(TestAllTypes.parseDelimitedFrom(input) == null);
176   }
177 
assertFieldsInOrder(ByteString data)178   private void assertFieldsInOrder(ByteString data) throws Exception {
179     CodedInputStream input = data.newCodedInput();
180     int previousTag = 0;
181 
182     while (true) {
183       int tag = input.readTag();
184       if (tag == 0) {
185         break;
186       }
187 
188       assertTrue(tag > previousTag);
189       previousTag = tag;
190       input.skipField(tag);
191     }
192   }
193 
testInterleavedFieldsAndExtensions()194   public void testInterleavedFieldsAndExtensions() throws Exception {
195     // Tests that fields are written in order even when extension ranges
196     // are interleaved with field numbers.
197     ByteString data =
198         TestFieldOrderings.newBuilder()
199             .setMyInt(1)
200             .setMyString("foo")
201             .setMyFloat(1.0F)
202             .setExtension(UnittestProto.myExtensionInt, 23)
203             .setExtension(UnittestProto.myExtensionString, "bar")
204             .build()
205             .toByteString();
206     assertFieldsInOrder(data);
207 
208     Descriptors.Descriptor descriptor = TestFieldOrderings.getDescriptor();
209     ByteString dynamicData =
210         DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor())
211             .setField(descriptor.findFieldByName("my_int"), 1L)
212             .setField(descriptor.findFieldByName("my_string"), "foo")
213             .setField(descriptor.findFieldByName("my_float"), 1.0F)
214             .setField(UnittestProto.myExtensionInt.getDescriptor(), 23)
215             .setField(UnittestProto.myExtensionString.getDescriptor(), "bar")
216             .build()
217             .toByteString();
218     assertFieldsInOrder(dynamicData);
219   }
220 
getTestFieldOrderingsRegistry()221   private ExtensionRegistry getTestFieldOrderingsRegistry() {
222     ExtensionRegistry result = ExtensionRegistry.newInstance();
223     result.add(UnittestProto.myExtensionInt);
224     result.add(UnittestProto.myExtensionString);
225     return result;
226   }
227 
testParseMultipleExtensionRanges()228   public void testParseMultipleExtensionRanges() throws Exception {
229     // Make sure we can parse a message that contains multiple extensions
230     // ranges.
231     TestFieldOrderings source =
232         TestFieldOrderings.newBuilder()
233             .setMyInt(1)
234             .setMyString("foo")
235             .setMyFloat(1.0F)
236             .setExtension(UnittestProto.myExtensionInt, 23)
237             .setExtension(UnittestProto.myExtensionString, "bar")
238             .build();
239     TestFieldOrderings dest =
240         TestFieldOrderings.parseFrom(source.toByteString(), getTestFieldOrderingsRegistry());
241     assertEquals(source, dest);
242   }
243 
getTestExtensionInsideTableRegistry()244   private static ExtensionRegistry getTestExtensionInsideTableRegistry() {
245     ExtensionRegistry result = ExtensionRegistry.newInstance();
246     result.add(UnittestProto.testExtensionInsideTableExtension);
247     return result;
248   }
249 
testExtensionInsideTable()250   public void testExtensionInsideTable() throws Exception {
251     // Make sure the extension within the range of table is parsed correctly in experimental
252     // runtime.
253     TestExtensionInsideTable source =
254         TestExtensionInsideTable.newBuilder()
255             .setField1(1)
256             .setExtension(UnittestProto.testExtensionInsideTableExtension, 23)
257             .build();
258     TestExtensionInsideTable dest =
259         TestExtensionInsideTable.parseFrom(
260             source.toByteString(), getTestExtensionInsideTableRegistry());
261     assertEquals(source, dest);
262   }
263 
testParseMultipleExtensionRangesDynamic()264   public void testParseMultipleExtensionRangesDynamic() throws Exception {
265     // Same as above except with DynamicMessage.
266     Descriptors.Descriptor descriptor = TestFieldOrderings.getDescriptor();
267     DynamicMessage source =
268         DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor())
269             .setField(descriptor.findFieldByName("my_int"), 1L)
270             .setField(descriptor.findFieldByName("my_string"), "foo")
271             .setField(descriptor.findFieldByName("my_float"), 1.0F)
272             .setField(UnittestProto.myExtensionInt.getDescriptor(), 23)
273             .setField(UnittestProto.myExtensionString.getDescriptor(), "bar")
274             .build();
275     DynamicMessage dest =
276         DynamicMessage.parseFrom(
277             descriptor, source.toByteString(), getTestFieldOrderingsRegistry());
278     assertEquals(source, dest);
279   }
280 
testSerializeMessageSetEagerly()281   public void testSerializeMessageSetEagerly() throws Exception {
282     testSerializeMessageSetWithFlag(true);
283   }
284 
testSerializeMessageSetNotEagerly()285   public void testSerializeMessageSetNotEagerly() throws Exception {
286     testSerializeMessageSetWithFlag(false);
287   }
288 
testSerializeMessageSetWithFlag(boolean eagerParsing)289   private void testSerializeMessageSetWithFlag(boolean eagerParsing) throws Exception {
290     ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
291     // Set up a TestMessageSet with two known messages and an unknown one.
292     TestMessageSet messageSet =
293         TestMessageSet.newBuilder()
294             .setExtension(
295                 TestMessageSetExtension1.messageSetExtension,
296                 TestMessageSetExtension1.newBuilder().setI(123).build())
297             .setExtension(
298                 TestMessageSetExtension2.messageSetExtension,
299                 TestMessageSetExtension2.newBuilder().setStr("foo").build())
300             .setUnknownFields(
301                 UnknownFieldSet.newBuilder()
302                     .addField(
303                         UNKNOWN_TYPE_ID,
304                         UnknownFieldSet.Field.newBuilder()
305                             .addLengthDelimited(ByteString.copyFromUtf8("bar"))
306                             .build())
307                     .build())
308             .build();
309 
310     ByteString data = messageSet.toByteString();
311 
312     // Parse back using RawMessageSet and check the contents.
313     RawMessageSet raw = RawMessageSet.parseFrom(data);
314 
315     assertTrue(raw.getUnknownFields().asMap().isEmpty());
316 
317     assertEquals(3, raw.getItemCount());
318     assertEquals(TYPE_ID_1, raw.getItem(0).getTypeId());
319     assertEquals(TYPE_ID_2, raw.getItem(1).getTypeId());
320     assertEquals(UNKNOWN_TYPE_ID, raw.getItem(2).getTypeId());
321 
322     TestMessageSetExtension1 message1 =
323         TestMessageSetExtension1.parseFrom(raw.getItem(0).getMessage());
324     assertEquals(123, message1.getI());
325 
326     TestMessageSetExtension2 message2 =
327         TestMessageSetExtension2.parseFrom(raw.getItem(1).getMessage());
328     assertEquals("foo", message2.getStr());
329 
330     assertEquals("bar", raw.getItem(2).getMessage().toStringUtf8());
331   }
332 
testParseMessageSetEagerly()333   public void testParseMessageSetEagerly() throws Exception {
334     testParseMessageSetWithFlag(true);
335   }
336 
testParseMessageSetNotEagerly()337   public void testParseMessageSetNotEagerly() throws Exception {
338     testParseMessageSetWithFlag(false);
339   }
340 
testParseMessageSetWithFlag(boolean eagerParsing)341   private void testParseMessageSetWithFlag(boolean eagerParsing) throws Exception {
342     ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
343     ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
344     extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
345     extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
346 
347     // Set up a RawMessageSet with two known messages and an unknown one.
348     RawMessageSet raw =
349         RawMessageSet.newBuilder()
350             .addItem(
351                 RawMessageSet.Item.newBuilder()
352                     .setTypeId(TYPE_ID_1)
353                     .setMessage(
354                         TestMessageSetExtension1.newBuilder().setI(123).build().toByteString())
355                     .build())
356             .addItem(
357                 RawMessageSet.Item.newBuilder()
358                     .setTypeId(TYPE_ID_2)
359                     .setMessage(
360                         TestMessageSetExtension2.newBuilder().setStr("foo").build().toByteString())
361                     .build())
362             .addItem(
363                 RawMessageSet.Item.newBuilder()
364                     .setTypeId(UNKNOWN_TYPE_ID)
365                     .setMessage(ByteString.copyFromUtf8("bar"))
366                     .build())
367             .build();
368 
369     ByteString data = raw.toByteString();
370 
371     // Parse as a TestMessageSet and check the contents.
372     TestMessageSet messageSet = TestMessageSet.parseFrom(data, extensionRegistry);
373 
374     assertEquals(123, messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI());
375     assertEquals(
376         "foo", messageSet.getExtension(TestMessageSetExtension2.messageSetExtension).getStr());
377 
378     // Check for unknown field with type LENGTH_DELIMITED,
379     //   number UNKNOWN_TYPE_ID, and contents "bar".
380     UnknownFieldSet unknownFields = messageSet.getUnknownFields();
381     assertEquals(1, unknownFields.asMap().size());
382     assertTrue(unknownFields.hasField(UNKNOWN_TYPE_ID));
383 
384     UnknownFieldSet.Field field = unknownFields.getField(UNKNOWN_TYPE_ID);
385     assertEquals(1, field.getLengthDelimitedList().size());
386     assertEquals("bar", field.getLengthDelimitedList().get(0).toStringUtf8());
387   }
388 
testParseMessageSetExtensionEagerly()389   public void testParseMessageSetExtensionEagerly() throws Exception {
390     testParseMessageSetExtensionWithFlag(true);
391   }
392 
testParseMessageSetExtensionNotEagerly()393   public void testParseMessageSetExtensionNotEagerly() throws Exception {
394     testParseMessageSetExtensionWithFlag(false);
395   }
396 
testParseMessageSetExtensionWithFlag(boolean eagerParsing)397   private void testParseMessageSetExtensionWithFlag(boolean eagerParsing) throws Exception {
398     ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
399     ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
400     extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
401 
402     // Set up a RawMessageSet with a known messages.
403     RawMessageSet raw =
404         RawMessageSet.newBuilder()
405             .addItem(
406                 RawMessageSet.Item.newBuilder()
407                     .setTypeId(TYPE_ID_1)
408                     .setMessage(
409                         TestMessageSetExtension1.newBuilder().setI(123).build().toByteString())
410                     .build())
411             .build();
412 
413     ByteString data = raw.toByteString();
414 
415     // Parse as a TestMessageSet and check the contents.
416     TestMessageSet messageSet = TestMessageSet.parseFrom(data, extensionRegistry);
417     assertEquals(123, messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI());
418   }
419 
testMergeLazyMessageSetExtensionEagerly()420   public void testMergeLazyMessageSetExtensionEagerly() throws Exception {
421     testMergeLazyMessageSetExtensionWithFlag(true);
422   }
423 
testMergeLazyMessageSetExtensionNotEagerly()424   public void testMergeLazyMessageSetExtensionNotEagerly() throws Exception {
425     testMergeLazyMessageSetExtensionWithFlag(false);
426   }
427 
testMergeLazyMessageSetExtensionWithFlag(boolean eagerParsing)428   private void testMergeLazyMessageSetExtensionWithFlag(boolean eagerParsing) throws Exception {
429     ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
430     ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
431     extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
432 
433     // Set up a RawMessageSet with a known messages.
434     RawMessageSet raw =
435         RawMessageSet.newBuilder()
436             .addItem(
437                 RawMessageSet.Item.newBuilder()
438                     .setTypeId(TYPE_ID_1)
439                     .setMessage(
440                         TestMessageSetExtension1.newBuilder().setI(123).build().toByteString())
441                     .build())
442             .build();
443 
444     ByteString data = raw.toByteString();
445 
446     // Parse as a TestMessageSet and store value into lazy field
447     TestMessageSet messageSet = TestMessageSet.parseFrom(data, extensionRegistry);
448     // Merge lazy field check the contents.
449     messageSet = messageSet.toBuilder().mergeFrom(data, extensionRegistry).build();
450     assertEquals(123, messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI());
451   }
452 
testMergeMessageSetExtensionEagerly()453   public void testMergeMessageSetExtensionEagerly() throws Exception {
454     testMergeMessageSetExtensionWithFlag(true);
455   }
456 
testMergeMessageSetExtensionNotEagerly()457   public void testMergeMessageSetExtensionNotEagerly() throws Exception {
458     testMergeMessageSetExtensionWithFlag(false);
459   }
460 
testMergeMessageSetExtensionWithFlag(boolean eagerParsing)461   private void testMergeMessageSetExtensionWithFlag(boolean eagerParsing) throws Exception {
462     ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
463     ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
464     extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
465 
466     // Set up a RawMessageSet with a known messages.
467     RawMessageSet raw =
468         RawMessageSet.newBuilder()
469             .addItem(
470                 RawMessageSet.Item.newBuilder()
471                     .setTypeId(TYPE_ID_1)
472                     .setMessage(
473                         TestMessageSetExtension1.newBuilder().setI(123).build().toByteString())
474                     .build())
475             .build();
476 
477     // Serialize RawMessageSet unnormally (message value before type id)
478     ByteString.CodedBuilder out = ByteString.newCodedBuilder(raw.getSerializedSize());
479     CodedOutputStream output = out.getCodedOutput();
480     List<RawMessageSet.Item> items = raw.getItemList();
481     for (int i = 0; i < items.size(); i++) {
482       RawMessageSet.Item item = items.get(i);
483       output.writeTag(1, WireFormat.WIRETYPE_START_GROUP);
484       output.writeBytes(3, item.getMessage());
485       output.writeInt32(2, item.getTypeId());
486       output.writeTag(1, WireFormat.WIRETYPE_END_GROUP);
487     }
488     ByteString data = out.build();
489 
490     // Merge bytes into TestMessageSet and check the contents.
491     TestMessageSet messageSet =
492         TestMessageSet.newBuilder().mergeFrom(data, extensionRegistry).build();
493     assertEquals(123, messageSet.getExtension(TestMessageSetExtension1.messageSetExtension).getI());
494   }
495 
496   // ================================================================
497   // oneof
testOneofWireFormat()498   public void testOneofWireFormat() throws Exception {
499     TestOneof2.Builder builder = TestOneof2.newBuilder();
500     TestUtil.setOneof(builder);
501     TestOneof2 message = builder.build();
502     ByteString rawBytes = message.toByteString();
503 
504     assertEquals(rawBytes.size(), message.getSerializedSize());
505 
506     TestOneof2 message2 = TestOneof2.parseFrom(rawBytes);
507     TestUtil.assertOneofSet(message2);
508   }
509 
testOneofOnlyLastSet()510   public void testOneofOnlyLastSet() throws Exception {
511     TestOneofBackwardsCompatible source =
512         TestOneofBackwardsCompatible.newBuilder().setFooInt(100).setFooString("101").build();
513 
514     ByteString rawBytes = source.toByteString();
515     TestOneof2 message = TestOneof2.parseFrom(rawBytes);
516     assertFalse(message.hasFooInt());
517     assertTrue(message.hasFooString());
518   }
519 }
520