blob: 5c2a052b6eb14f84c9ee347f4f206bb6a357320a [file] [log] [blame]
Jon Skeetee835a32015-06-30 17:22:26 +01001#region Copyright notice and license
2// Protocol Buffers - Google's data interchange format
3// Copyright 2015 Google Inc. All rights reserved.
4// https://developers.google.com/protocol-buffers/
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met:
9//
10// * Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer.
12// * Redistributions in binary form must reproduce the above
13// copyright notice, this list of conditions and the following disclaimer
14// in the documentation and/or other materials provided with the
15// distribution.
16// * Neither the name of Google Inc. nor the names of its
17// contributors may be used to endorse or promote products derived from
18// this software without specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31#endregion
Jon Skeet78ea98f2015-07-01 14:47:03 +010032
Jon Skeetee835a32015-06-30 17:22:26 +010033using System;
Jon Skeet0d684d32015-06-24 17:21:55 +010034using System.IO;
Jon Skeetbfee2df2015-06-23 16:09:27 +010035using Google.Protobuf.TestProtos;
Jon Skeet90c89322015-05-12 09:47:19 +010036using NUnit.Framework;
Jon Skeet78ea98f2015-07-01 14:47:03 +010037using System.Collections;
38using System.Collections.Generic;
Jon Skeet9df2def2015-08-04 11:26:48 +010039using System.Linq;
40using Google.Protobuf.WellKnownTypes;
csharptest71f662c2011-05-20 15:15:34 -050041
Jon Skeete38294a2015-06-09 19:30:44 +010042namespace Google.Protobuf
csharptest71f662c2011-05-20 15:15:34 -050043{
Jon Skeete38294a2015-06-09 19:30:44 +010044 /// <summary>
45 /// Tests around the generated TestAllTypes message.
46 /// </summary>
csharptest71f662c2011-05-20 15:15:34 -050047 public class GeneratedMessageTest
48 {
Jon Skeete38294a2015-06-09 19:30:44 +010049 [Test]
Jon Skeetdf44ae42015-06-25 12:08:18 +010050 public void EmptyMessageFieldDistinctFromMissingMessageField()
51 {
52 // This demonstrates what we're really interested in...
53 var message1 = new TestAllTypes { SingleForeignMessage = new ForeignMessage() };
54 var message2 = new TestAllTypes(); // SingleForeignMessage is null
55 EqualityTester.AssertInequality(message1, message2);
56 }
57
58 [Test]
Jon Skeete38294a2015-06-09 19:30:44 +010059 public void DefaultValues()
csharptest71f662c2011-05-20 15:15:34 -050060 {
Jon Skeete38294a2015-06-09 19:30:44 +010061 // Single fields
62 var message = new TestAllTypes();
63 Assert.AreEqual(false, message.SingleBool);
64 Assert.AreEqual(ByteString.Empty, message.SingleBytes);
65 Assert.AreEqual(0.0, message.SingleDouble);
66 Assert.AreEqual(0, message.SingleFixed32);
67 Assert.AreEqual(0L, message.SingleFixed64);
68 Assert.AreEqual(0.0f, message.SingleFloat);
69 Assert.AreEqual(ForeignEnum.FOREIGN_UNSPECIFIED, message.SingleForeignEnum);
70 Assert.IsNull(message.SingleForeignMessage);
71 Assert.AreEqual(ImportEnum.IMPORT_ENUM_UNSPECIFIED, message.SingleImportEnum);
72 Assert.IsNull(message.SingleImportMessage);
73 Assert.AreEqual(0, message.SingleInt32);
74 Assert.AreEqual(0L, message.SingleInt64);
75 Assert.AreEqual(TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIED, message.SingleNestedEnum);
76 Assert.IsNull(message.SingleNestedMessage);
77 Assert.IsNull(message.SinglePublicImportMessage);
78 Assert.AreEqual(0, message.SingleSfixed32);
79 Assert.AreEqual(0L, message.SingleSfixed64);
80 Assert.AreEqual(0, message.SingleSint32);
81 Assert.AreEqual(0L, message.SingleSint64);
82 Assert.AreEqual("", message.SingleString);
83 Assert.AreEqual(0U, message.SingleUint32);
84 Assert.AreEqual(0UL, message.SingleUint64);
85
86 // Repeated fields
87 Assert.AreEqual(0, message.RepeatedBool.Count);
88 Assert.AreEqual(0, message.RepeatedBytes.Count);
89 Assert.AreEqual(0, message.RepeatedDouble.Count);
90 Assert.AreEqual(0, message.RepeatedFixed32.Count);
91 Assert.AreEqual(0, message.RepeatedFixed64.Count);
92 Assert.AreEqual(0, message.RepeatedFloat.Count);
93 Assert.AreEqual(0, message.RepeatedForeignEnum.Count);
94 Assert.AreEqual(0, message.RepeatedForeignMessage.Count);
95 Assert.AreEqual(0, message.RepeatedImportEnum.Count);
96 Assert.AreEqual(0, message.RepeatedImportMessage.Count);
97 Assert.AreEqual(0, message.RepeatedNestedEnum.Count);
98 Assert.AreEqual(0, message.RepeatedNestedMessage.Count);
99 Assert.AreEqual(0, message.RepeatedPublicImportMessage.Count);
100 Assert.AreEqual(0, message.RepeatedSfixed32.Count);
101 Assert.AreEqual(0, message.RepeatedSfixed64.Count);
102 Assert.AreEqual(0, message.RepeatedSint32.Count);
103 Assert.AreEqual(0, message.RepeatedSint64.Count);
104 Assert.AreEqual(0, message.RepeatedString.Count);
105 Assert.AreEqual(0, message.RepeatedUint32.Count);
106 Assert.AreEqual(0, message.RepeatedUint64.Count);
107
108 // Oneof fields
109 Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
110 Assert.AreEqual(0, message.OneofUint32);
111 Assert.AreEqual("", message.OneofString);
112 Assert.AreEqual(ByteString.Empty, message.OneofBytes);
113 Assert.IsNull(message.OneofNestedMessage);
csharptest71f662c2011-05-20 15:15:34 -0500114 }
115
Jon Skeet90c89322015-05-12 09:47:19 +0100116 [Test]
Jon Skeet3980cf92015-07-30 13:35:42 +0100117 public void NullStringAndBytesRejected()
118 {
119 var message = new TestAllTypes();
120 Assert.Throws<ArgumentNullException>(() => message.SingleString = null);
121 Assert.Throws<ArgumentNullException>(() => message.OneofString = null);
122 Assert.Throws<ArgumentNullException>(() => message.SingleBytes = null);
123 Assert.Throws<ArgumentNullException>(() => message.OneofBytes = null);
124 }
125
126 [Test]
Jon Skeete38294a2015-06-09 19:30:44 +0100127 public void RoundTrip_Empty()
csharptest71f662c2011-05-20 15:15:34 -0500128 {
Jon Skeete38294a2015-06-09 19:30:44 +0100129 var message = new TestAllTypes();
130 // Without setting any values, there's nothing to write.
131 byte[] bytes = message.ToByteArray();
132 Assert.AreEqual(0, bytes.Length);
133 TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes);
134 Assert.AreEqual(message, parsed);
csharptest71f662c2011-05-20 15:15:34 -0500135 }
136
Jon Skeet90c89322015-05-12 09:47:19 +0100137 [Test]
Jon Skeete38294a2015-06-09 19:30:44 +0100138 public void RoundTrip_SingleValues()
csharptest71f662c2011-05-20 15:15:34 -0500139 {
Jon Skeete38294a2015-06-09 19:30:44 +0100140 var message = new TestAllTypes
141 {
142 SingleBool = true,
Jon Skeet6c1fe6e2015-06-23 11:54:19 +0100143 SingleBytes = ByteString.CopyFrom(1, 2, 3, 4),
Jon Skeete38294a2015-06-09 19:30:44 +0100144 SingleDouble = 23.5,
145 SingleFixed32 = 23,
146 SingleFixed64 = 1234567890123,
147 SingleFloat = 12.25f,
148 SingleForeignEnum = ForeignEnum.FOREIGN_BAR,
149 SingleForeignMessage = new ForeignMessage { C = 10 },
150 SingleImportEnum = ImportEnum.IMPORT_BAZ,
151 SingleImportMessage = new ImportMessage { D = 20 },
152 SingleInt32 = 100,
153 SingleInt64 = 3210987654321,
154 SingleNestedEnum = TestAllTypes.Types.NestedEnum.FOO,
155 SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 35 },
156 SinglePublicImportMessage = new PublicImportMessage { E = 54 },
157 SingleSfixed32 = -123,
158 SingleSfixed64 = -12345678901234,
159 SingleSint32 = -456,
160 SingleSint64 = -12345678901235,
161 SingleString = "test",
162 SingleUint32 = uint.MaxValue,
163 SingleUint64 = ulong.MaxValue
164 };
csharptest71f662c2011-05-20 15:15:34 -0500165
Jon Skeete38294a2015-06-09 19:30:44 +0100166 byte[] bytes = message.ToByteArray();
167 TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes);
168 Assert.AreEqual(message, parsed);
csharptest71f662c2011-05-20 15:15:34 -0500169 }
170
Jon Skeet90c89322015-05-12 09:47:19 +0100171 [Test]
Jon Skeete38294a2015-06-09 19:30:44 +0100172 public void RoundTrip_RepeatedValues()
csharptest71f662c2011-05-20 15:15:34 -0500173 {
Jon Skeete38294a2015-06-09 19:30:44 +0100174 var message = new TestAllTypes
175 {
176 RepeatedBool = { true, false },
Jon Skeet6c1fe6e2015-06-23 11:54:19 +0100177 RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6) },
Jon Skeete38294a2015-06-09 19:30:44 +0100178 RepeatedDouble = { -12.25, 23.5 },
179 RepeatedFixed32 = { uint.MaxValue, 23 },
180 RepeatedFixed64 = { ulong.MaxValue, 1234567890123 },
181 RepeatedFloat = { 100f, 12.25f },
182 RepeatedForeignEnum = { ForeignEnum.FOREIGN_FOO, ForeignEnum.FOREIGN_BAR },
183 RepeatedForeignMessage = { new ForeignMessage(), new ForeignMessage { C = 10 } },
184 RepeatedImportEnum = { ImportEnum.IMPORT_BAZ, ImportEnum.IMPORT_ENUM_UNSPECIFIED },
185 RepeatedImportMessage = { new ImportMessage { D = 20 }, new ImportMessage { D = 25 } },
186 RepeatedInt32 = { 100, 200 },
187 RepeatedInt64 = { 3210987654321, long.MaxValue },
188 RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.FOO, TestAllTypes.Types.NestedEnum.NEG },
189 RepeatedNestedMessage = { new TestAllTypes.Types.NestedMessage { Bb = 35 }, new TestAllTypes.Types.NestedMessage { Bb = 10 } },
190 RepeatedPublicImportMessage = { new PublicImportMessage { E = 54 }, new PublicImportMessage { E = -1 } },
191 RepeatedSfixed32 = { -123, 123 },
192 RepeatedSfixed64 = { -12345678901234, 12345678901234 },
193 RepeatedSint32 = { -456, 100 },
194 RepeatedSint64 = { -12345678901235, 123 },
195 RepeatedString = { "foo", "bar" },
196 RepeatedUint32 = { uint.MaxValue, uint.MinValue },
197 RepeatedUint64 = { ulong.MaxValue, uint.MinValue }
198 };
csharptest71f662c2011-05-20 15:15:34 -0500199
Jon Skeete38294a2015-06-09 19:30:44 +0100200 byte[] bytes = message.ToByteArray();
201 TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes);
202 Assert.AreEqual(message, parsed);
Jie Luof7b417d2015-05-29 12:48:25 -0700203 }
Jon Skeet6c1fe6e2015-06-23 11:54:19 +0100204
Jon Skeetc1283312015-06-26 10:32:23 +0100205 // Note that not every map within map_unittest_proto3 is used. They all go through very
206 // similar code paths. The fact that all maps are present is validation that we have codecs
207 // for every type.
Jon Skeet6c1fe6e2015-06-23 11:54:19 +0100208 [Test]
Jon Skeet0d684d32015-06-24 17:21:55 +0100209 public void RoundTrip_Maps()
210 {
Jon Skeetc1283312015-06-26 10:32:23 +0100211 var message = new TestMap
Jon Skeet0d684d32015-06-24 17:21:55 +0100212 {
Jon Skeetc1283312015-06-26 10:32:23 +0100213 MapBoolBool = {
214 { false, true },
215 { true, false }
Jon Skeet0d684d32015-06-24 17:21:55 +0100216 },
Jon Skeetc1283312015-06-26 10:32:23 +0100217 MapInt32Bytes = {
Jon Skeet0d684d32015-06-24 17:21:55 +0100218 { 5, ByteString.CopyFrom(6, 7, 8) },
219 { 25, ByteString.CopyFrom(1, 2, 3, 4, 5) },
220 { 10, ByteString.Empty }
221 },
Jon Skeetc1283312015-06-26 10:32:23 +0100222 MapInt32ForeignMessage = {
223 { 0, new ForeignMessage { C = 10 } },
Jon Skeet9e4f3542016-01-04 14:03:01 +0000224 { 5, new ForeignMessage() },
Jon Skeetc1283312015-06-26 10:32:23 +0100225 },
226 MapInt32Enum = {
227 { 1, MapEnum.MAP_ENUM_BAR },
228 { 2000, MapEnum.MAP_ENUM_FOO }
Jon Skeet0d684d32015-06-24 17:21:55 +0100229 }
230 };
231
232 byte[] bytes = message.ToByteArray();
Jon Skeetc1283312015-06-26 10:32:23 +0100233 TestMap parsed = TestMap.Parser.ParseFrom(bytes);
Jon Skeet0d684d32015-06-24 17:21:55 +0100234 Assert.AreEqual(message, parsed);
235 }
236
237 [Test]
238 public void MapWithEmptyEntry()
239 {
Jon Skeetc1283312015-06-26 10:32:23 +0100240 var message = new TestMap
Jon Skeet0d684d32015-06-24 17:21:55 +0100241 {
Jon Skeetc1283312015-06-26 10:32:23 +0100242 MapInt32Bytes = { { 0, ByteString.Empty } }
Jon Skeet0d684d32015-06-24 17:21:55 +0100243 };
244
245 byte[] bytes = message.ToByteArray();
Jon Skeetc1283312015-06-26 10:32:23 +0100246 Assert.AreEqual(2, bytes.Length); // Tag for field entry (1 byte), length of entry (0; 1 byte)
Jon Skeet0d684d32015-06-24 17:21:55 +0100247
Jon Skeetc1283312015-06-26 10:32:23 +0100248 var parsed = TestMap.Parser.ParseFrom(bytes);
249 Assert.AreEqual(1, parsed.MapInt32Bytes.Count);
250 Assert.AreEqual(ByteString.Empty, parsed.MapInt32Bytes[0]);
Jon Skeet0d684d32015-06-24 17:21:55 +0100251 }
Jon Skeetc1283312015-06-26 10:32:23 +0100252
Jon Skeet0d684d32015-06-24 17:21:55 +0100253 [Test]
254 public void MapWithOnlyValue()
255 {
256 // Hand-craft the stream to contain a single entry with just a value.
257 var memoryStream = new MemoryStream();
Jon Skeet0e0e0c92015-08-03 11:08:53 +0100258 var output = new CodedOutputStream(memoryStream);
Jon Skeetc1283312015-06-26 10:32:23 +0100259 output.WriteTag(TestMap.MapInt32ForeignMessageFieldNumber, WireFormat.WireType.LengthDelimited);
260 var nestedMessage = new ForeignMessage { C = 20 };
Jon Skeet0d684d32015-06-24 17:21:55 +0100261 // Size of the entry (tag, size written by WriteMessage, data written by WriteMessage)
Jon Skeet15bf55e2015-08-04 12:38:53 +0100262 output.WriteLength(2 + nestedMessage.CalculateSize());
Jon Skeet0d684d32015-06-24 17:21:55 +0100263 output.WriteTag(2, WireFormat.WireType.LengthDelimited);
264 output.WriteMessage(nestedMessage);
265 output.Flush();
266
Jon Skeetc1283312015-06-26 10:32:23 +0100267 var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
268 Assert.AreEqual(nestedMessage, parsed.MapInt32ForeignMessage[0]);
269 }
270
271 [Test]
Jon Skeet9e4f3542016-01-04 14:03:01 +0000272 public void MapWithOnlyKey_PrimitiveValue()
273 {
274 // Hand-craft the stream to contain a single entry with just a key.
275 var memoryStream = new MemoryStream();
276 var output = new CodedOutputStream(memoryStream);
277 output.WriteTag(TestMap.MapInt32DoubleFieldNumber, WireFormat.WireType.LengthDelimited);
278 int key = 10;
279 output.WriteLength(1 + CodedOutputStream.ComputeInt32Size(key));
280 output.WriteTag(1, WireFormat.WireType.Varint);
281 output.WriteInt32(key);
282 output.Flush();
283
284 var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
285 Assert.AreEqual(0.0, parsed.MapInt32Double[key]);
286 }
287
288 [Test]
289 public void MapWithOnlyKey_MessageValue()
290 {
291 // Hand-craft the stream to contain a single entry with just a key.
292 var memoryStream = new MemoryStream();
293 var output = new CodedOutputStream(memoryStream);
294 output.WriteTag(TestMap.MapInt32ForeignMessageFieldNumber, WireFormat.WireType.LengthDelimited);
295 int key = 10;
296 output.WriteLength(1 + CodedOutputStream.ComputeInt32Size(key));
297 output.WriteTag(1, WireFormat.WireType.Varint);
298 output.WriteInt32(key);
299 output.Flush();
300
301 var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
302 Assert.AreEqual(new ForeignMessage(), parsed.MapInt32ForeignMessage[key]);
303 }
304
305 [Test]
Jon Skeetc1283312015-06-26 10:32:23 +0100306 public void MapIgnoresExtraFieldsWithinEntryMessages()
307 {
308 // Hand-craft the stream to contain a single entry with three fields
309 var memoryStream = new MemoryStream();
Jon Skeet0e0e0c92015-08-03 11:08:53 +0100310 var output = new CodedOutputStream(memoryStream);
Jon Skeetc1283312015-06-26 10:32:23 +0100311
312 output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
313
314 var key = 10; // Field 1
315 var value = 20; // Field 2
316 var extra = 30; // Field 3
317
318 // Each field can be represented in a single byte, with a single byte tag.
319 // Total message size: 6 bytes.
Jon Skeet15bf55e2015-08-04 12:38:53 +0100320 output.WriteLength(6);
Jon Skeetc1283312015-06-26 10:32:23 +0100321 output.WriteTag(1, WireFormat.WireType.Varint);
322 output.WriteInt32(key);
323 output.WriteTag(2, WireFormat.WireType.Varint);
324 output.WriteInt32(value);
325 output.WriteTag(3, WireFormat.WireType.Varint);
326 output.WriteInt32(extra);
327 output.Flush();
328
329 var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
330 Assert.AreEqual(value, parsed.MapInt32Int32[key]);
331 }
332
333 [Test]
334 public void MapFieldOrderIsIrrelevant()
335 {
336 var memoryStream = new MemoryStream();
Jon Skeet0e0e0c92015-08-03 11:08:53 +0100337 var output = new CodedOutputStream(memoryStream);
Jon Skeetc1283312015-06-26 10:32:23 +0100338
339 output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
340
341 var key = 10;
342 var value = 20;
343
344 // Each field can be represented in a single byte, with a single byte tag.
345 // Total message size: 4 bytes.
Jon Skeet15bf55e2015-08-04 12:38:53 +0100346 output.WriteLength(4);
Jon Skeetc1283312015-06-26 10:32:23 +0100347 output.WriteTag(2, WireFormat.WireType.Varint);
348 output.WriteInt32(value);
349 output.WriteTag(1, WireFormat.WireType.Varint);
350 output.WriteInt32(key);
351 output.Flush();
352
353 var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
354 Assert.AreEqual(value, parsed.MapInt32Int32[key]);
355 }
356
357 [Test]
358 public void MapNonContiguousEntries()
359 {
360 var memoryStream = new MemoryStream();
Jon Skeet0e0e0c92015-08-03 11:08:53 +0100361 var output = new CodedOutputStream(memoryStream);
Jon Skeetc1283312015-06-26 10:32:23 +0100362
363 // Message structure:
364 // Entry for MapInt32Int32
365 // Entry for MapStringString
366 // Entry for MapInt32Int32
367
368 // First entry
369 var key1 = 10;
370 var value1 = 20;
371 output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
Jon Skeet15bf55e2015-08-04 12:38:53 +0100372 output.WriteLength(4);
Jon Skeetc1283312015-06-26 10:32:23 +0100373 output.WriteTag(1, WireFormat.WireType.Varint);
374 output.WriteInt32(key1);
375 output.WriteTag(2, WireFormat.WireType.Varint);
376 output.WriteInt32(value1);
377
378 // Second entry
379 var key2 = "a";
380 var value2 = "b";
381 output.WriteTag(TestMap.MapStringStringFieldNumber, WireFormat.WireType.LengthDelimited);
Jon Skeet15bf55e2015-08-04 12:38:53 +0100382 output.WriteLength(6); // 3 bytes per entry: tag, size, character
Jon Skeetc1283312015-06-26 10:32:23 +0100383 output.WriteTag(1, WireFormat.WireType.LengthDelimited);
384 output.WriteString(key2);
385 output.WriteTag(2, WireFormat.WireType.LengthDelimited);
386 output.WriteString(value2);
387
388 // Third entry
389 var key3 = 15;
390 var value3 = 25;
391 output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
Jon Skeet15bf55e2015-08-04 12:38:53 +0100392 output.WriteLength(4);
Jon Skeetc1283312015-06-26 10:32:23 +0100393 output.WriteTag(1, WireFormat.WireType.Varint);
394 output.WriteInt32(key3);
395 output.WriteTag(2, WireFormat.WireType.Varint);
396 output.WriteInt32(value3);
397
398 output.Flush();
399 var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
400 var expected = new TestMap
401 {
402 MapInt32Int32 = { { key1, value1 }, { key3, value3 } },
403 MapStringString = { { key2, value2 } }
404 };
405 Assert.AreEqual(expected, parsed);
406 }
407
408 [Test]
409 public void DuplicateKeys_LastEntryWins()
410 {
411 var memoryStream = new MemoryStream();
Jon Skeet0e0e0c92015-08-03 11:08:53 +0100412 var output = new CodedOutputStream(memoryStream);
Jon Skeetc1283312015-06-26 10:32:23 +0100413
414 var key = 10;
415 var value1 = 20;
416 var value2 = 30;
417
418 // First entry
419 output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
Jon Skeet15bf55e2015-08-04 12:38:53 +0100420 output.WriteLength(4);
Jon Skeetc1283312015-06-26 10:32:23 +0100421 output.WriteTag(1, WireFormat.WireType.Varint);
422 output.WriteInt32(key);
423 output.WriteTag(2, WireFormat.WireType.Varint);
424 output.WriteInt32(value1);
425
426 // Second entry - same key, different value
427 output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
Jon Skeet15bf55e2015-08-04 12:38:53 +0100428 output.WriteLength(4);
Jon Skeetc1283312015-06-26 10:32:23 +0100429 output.WriteTag(1, WireFormat.WireType.Varint);
430 output.WriteInt32(key);
431 output.WriteTag(2, WireFormat.WireType.Varint);
432 output.WriteInt32(value2);
433 output.Flush();
434
435 var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
436 Assert.AreEqual(value2, parsed.MapInt32Int32[key]);
Jon Skeet0d684d32015-06-24 17:21:55 +0100437 }
438
439 [Test]
Jon Skeet6c1fe6e2015-06-23 11:54:19 +0100440 public void CloneSingleNonMessageValues()
441 {
442 var original = new TestAllTypes
443 {
444 SingleBool = true,
445 SingleBytes = ByteString.CopyFrom(1, 2, 3, 4),
446 SingleDouble = 23.5,
447 SingleFixed32 = 23,
448 SingleFixed64 = 1234567890123,
449 SingleFloat = 12.25f,
450 SingleInt32 = 100,
451 SingleInt64 = 3210987654321,
452 SingleNestedEnum = TestAllTypes.Types.NestedEnum.FOO,
453 SingleSfixed32 = -123,
454 SingleSfixed64 = -12345678901234,
455 SingleSint32 = -456,
456 SingleSint64 = -12345678901235,
457 SingleString = "test",
458 SingleUint32 = uint.MaxValue,
459 SingleUint64 = ulong.MaxValue
460 };
461 var clone = original.Clone();
462 Assert.AreNotSame(original, clone);
463 Assert.AreEqual(original, clone);
464 // Just as a single example
465 clone.SingleInt32 = 150;
466 Assert.AreNotEqual(original, clone);
467 }
468
469 [Test]
470 public void CloneRepeatedNonMessageValues()
471 {
472 var original = new TestAllTypes
473 {
474 RepeatedBool = { true, false },
475 RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6) },
476 RepeatedDouble = { -12.25, 23.5 },
477 RepeatedFixed32 = { uint.MaxValue, 23 },
478 RepeatedFixed64 = { ulong.MaxValue, 1234567890123 },
479 RepeatedFloat = { 100f, 12.25f },
480 RepeatedInt32 = { 100, 200 },
481 RepeatedInt64 = { 3210987654321, long.MaxValue },
482 RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.FOO, TestAllTypes.Types.NestedEnum.NEG },
483 RepeatedSfixed32 = { -123, 123 },
484 RepeatedSfixed64 = { -12345678901234, 12345678901234 },
485 RepeatedSint32 = { -456, 100 },
486 RepeatedSint64 = { -12345678901235, 123 },
487 RepeatedString = { "foo", "bar" },
488 RepeatedUint32 = { uint.MaxValue, uint.MinValue },
489 RepeatedUint64 = { ulong.MaxValue, uint.MinValue }
490 };
491
492 var clone = original.Clone();
493 Assert.AreNotSame(original, clone);
494 Assert.AreEqual(original, clone);
495 // Just as a single example
496 clone.RepeatedDouble.Add(25.5);
497 Assert.AreNotEqual(original, clone);
498 }
499
500 [Test]
501 public void CloneSingleMessageField()
502 {
503 var original = new TestAllTypes
504 {
505 SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 }
506 };
507
508 var clone = original.Clone();
509 Assert.AreNotSame(original, clone);
510 Assert.AreNotSame(original.SingleNestedMessage, clone.SingleNestedMessage);
511 Assert.AreEqual(original, clone);
512
513 clone.SingleNestedMessage.Bb = 30;
514 Assert.AreNotEqual(original, clone);
515 }
516
517 [Test]
518 public void CloneRepeatedMessageField()
519 {
520 var original = new TestAllTypes
521 {
522 RepeatedNestedMessage = { new TestAllTypes.Types.NestedMessage { Bb = 20 } }
523 };
524
525 var clone = original.Clone();
526 Assert.AreNotSame(original, clone);
527 Assert.AreNotSame(original.RepeatedNestedMessage, clone.RepeatedNestedMessage);
528 Assert.AreNotSame(original.RepeatedNestedMessage[0], clone.RepeatedNestedMessage[0]);
529 Assert.AreEqual(original, clone);
530
531 clone.RepeatedNestedMessage[0].Bb = 30;
532 Assert.AreNotEqual(original, clone);
533 }
534
535 [Test]
536 public void CloneOneofField()
537 {
538 var original = new TestAllTypes
539 {
540 OneofNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 }
541 };
542
543 var clone = original.Clone();
544 Assert.AreNotSame(original, clone);
545 Assert.AreEqual(original, clone);
546
547 // We should have cloned the message
548 original.OneofNestedMessage.Bb = 30;
549 Assert.AreNotEqual(original, clone);
550 }
Jon Skeetbfee2df2015-06-23 16:09:27 +0100551
552 [Test]
Jon Skeetf34d37a2015-06-30 13:16:20 +0100553 public void OneofProperties()
554 {
555 // Switch the oneof case between each of the different options, and check everything behaves
556 // as expected in each case.
557 var message = new TestAllTypes();
558 Assert.AreEqual("", message.OneofString);
559 Assert.AreEqual(0, message.OneofUint32);
560 Assert.AreEqual(ByteString.Empty, message.OneofBytes);
561 Assert.IsNull(message.OneofNestedMessage);
562 Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
563
564 message.OneofString = "sample";
565 Assert.AreEqual("sample", message.OneofString);
566 Assert.AreEqual(0, message.OneofUint32);
567 Assert.AreEqual(ByteString.Empty, message.OneofBytes);
568 Assert.IsNull(message.OneofNestedMessage);
569 Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase);
570
571 var bytes = ByteString.CopyFrom(1, 2, 3);
572 message.OneofBytes = bytes;
573 Assert.AreEqual("", message.OneofString);
574 Assert.AreEqual(0, message.OneofUint32);
575 Assert.AreEqual(bytes, message.OneofBytes);
576 Assert.IsNull(message.OneofNestedMessage);
577 Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofBytes, message.OneofFieldCase);
578
579 message.OneofUint32 = 20;
580 Assert.AreEqual("", message.OneofString);
581 Assert.AreEqual(20, message.OneofUint32);
582 Assert.AreEqual(ByteString.Empty, message.OneofBytes);
583 Assert.IsNull(message.OneofNestedMessage);
584 Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message.OneofFieldCase);
585
586 var nestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 25 };
587 message.OneofNestedMessage = nestedMessage;
588 Assert.AreEqual("", message.OneofString);
589 Assert.AreEqual(0, message.OneofUint32);
590 Assert.AreEqual(ByteString.Empty, message.OneofBytes);
591 Assert.AreEqual(nestedMessage, message.OneofNestedMessage);
592 Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofNestedMessage, message.OneofFieldCase);
593
594 message.ClearOneofField();
595 Assert.AreEqual("", message.OneofString);
596 Assert.AreEqual(0, message.OneofUint32);
597 Assert.AreEqual(ByteString.Empty, message.OneofBytes);
598 Assert.IsNull(message.OneofNestedMessage);
599 Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
600 }
601
602 [Test]
Jon Skeet964627e2015-10-24 06:45:20 +0100603 public void Oneof_DefaultValuesNotEqual()
604 {
605 var message1 = new TestAllTypes { OneofString = "" };
606 var message2 = new TestAllTypes { OneofUint32 = 0 };
607 Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofString, message1.OneofFieldCase);
608 Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase);
609 Assert.AreNotEqual(message1, message2);
610 }
611
612 [Test]
Jon Skeetf34d37a2015-06-30 13:16:20 +0100613 public void OneofSerialization_NonDefaultValue()
614 {
615 var message = new TestAllTypes();
616 message.OneofString = "this would take a bit of space";
617 message.OneofUint32 = 10;
618 var bytes = message.ToByteArray();
619 Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - no string!
620
621 var message2 = TestAllTypes.Parser.ParseFrom(bytes);
622 Assert.AreEqual(message, message2);
623 Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase);
624 }
625
626 [Test]
627 public void OneofSerialization_DefaultValue()
628 {
629 var message = new TestAllTypes();
630 message.OneofString = "this would take a bit of space";
631 message.OneofUint32 = 0; // This is the default value for UInt32; normally wouldn't be serialized
632 var bytes = message.ToByteArray();
633 Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - it's still serialized
634
635 var message2 = TestAllTypes.Parser.ParseFrom(bytes);
636 Assert.AreEqual(message, message2);
637 Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase);
638 }
Jon Skeet9df2def2015-08-04 11:26:48 +0100639
640 [Test]
641 public void IgnoreUnknownFields_RealDataStillRead()
642 {
643 var message = SampleMessages.CreateFullTestAllTypes();
644 var stream = new MemoryStream();
645 var output = new CodedOutputStream(stream);
646 var unusedFieldNumber = 23456;
647 Assert.IsFalse(TestAllTypes.Descriptor.Fields.InDeclarationOrder().Select(x => x.FieldNumber).Contains(unusedFieldNumber));
648 output.WriteTag(unusedFieldNumber, WireFormat.WireType.LengthDelimited);
649 output.WriteString("ignore me");
650 message.WriteTo(output);
651 output.Flush();
652
653 stream.Position = 0;
654 var parsed = TestAllTypes.Parser.ParseFrom(stream);
655 Assert.AreEqual(message, parsed);
656 }
657
658 [Test]
659 public void IgnoreUnknownFields_AllTypes()
660 {
661 // Simple way of ensuring we can skip all kinds of fields.
662 var data = SampleMessages.CreateFullTestAllTypes().ToByteArray();
663 var empty = Empty.Parser.ParseFrom(data);
664 Assert.AreEqual(new Empty(), empty);
665 }
Jon Skeet15bf55e2015-08-04 12:38:53 +0100666
667 // This was originally seen as a conformance test failure.
668 [Test]
669 public void TruncatedMessageFieldThrows()
670 {
671 // 130, 3 is the message tag
672 // 1 is the data length - but there's no data.
673 var data = new byte[] { 130, 3, 1 };
674 Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseFrom(data));
675 }
Jon Skeet6e160372015-08-08 07:24:28 +0100676
677 /// <summary>
678 /// Demonstrates current behaviour with an extraneous end group tag - see issue 688
679 /// for details; we may want to change this.
680 /// </summary>
681 [Test]
Jon Skeet9bdc8482016-02-15 11:58:01 +0000682 public void ExtraEndGroupThrows()
Jon Skeet6e160372015-08-08 07:24:28 +0100683 {
684 var message = SampleMessages.CreateFullTestAllTypes();
685 var stream = new MemoryStream();
686 var output = new CodedOutputStream(stream);
687
Jon Skeet6e160372015-08-08 07:24:28 +0100688 output.WriteTag(TestAllTypes.SingleFixed32FieldNumber, WireFormat.WireType.Fixed32);
689 output.WriteFixed32(123);
Jon Skeet9bdc8482016-02-15 11:58:01 +0000690 output.WriteTag(100, WireFormat.WireType.EndGroup);
Jon Skeet6e160372015-08-08 07:24:28 +0100691
692 output.Flush();
693
694 stream.Position = 0;
Jon Skeet9bdc8482016-02-15 11:58:01 +0000695 Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseFrom(stream));
Jon Skeet6e160372015-08-08 07:24:28 +0100696 }
Jon Skeet5dba7d72016-01-06 11:12:56 +0000697
698 [Test]
699 public void CustomDiagnosticMessage_DirectToStringCall()
700 {
701 var message = new ForeignMessage { C = 31 };
702 Assert.AreEqual("{ \"c\": 31, \"@cInHex\": \"1f\" }", message.ToString());
703 Assert.AreEqual("{ \"c\": 31 }", JsonFormatter.Default.Format(message));
704 }
705
706 [Test]
707 public void CustomDiagnosticMessage_Nested()
708 {
709 var message = new TestAllTypes { SingleForeignMessage = new ForeignMessage { C = 16 } };
710 Assert.AreEqual("{ \"singleForeignMessage\": { \"c\": 16, \"@cInHex\": \"10\" } }", message.ToString());
711 Assert.AreEqual("{ \"singleForeignMessage\": { \"c\": 16 } }", JsonFormatter.Default.Format(message));
712 }
avgwebad2d7752016-03-06 17:50:02 -0800713
714 [Test]
715 public void CustomDiagnosticMessage_DirectToTextWriterCall()
716 {
717 var message = new ForeignMessage { C = 31 };
718 var writer = new StringWriter();
719 JsonFormatter.Default.Format(message, writer);
720 Assert.AreEqual("{ \"c\": 31 }", writer.ToString());
721 }
csharptest71f662c2011-05-20 15:15:34 -0500722 }
Jon Skeete38294a2015-06-09 19:30:44 +0100723}