blob: 0f2d1c9a76215aff229210f1120ab6d631e15cc6 [file] [log] [blame]
csharptest71f662c2011-05-20 15:15:34 -05001#region Copyright notice and license
2
3// Protocol Buffers - Google's data interchange format
4// Copyright 2008 Google Inc. All rights reserved.
5// http://github.com/jskeet/dotnet-protobufs/
6// Original C++/Java/Python code:
7// http://code.google.com/p/protobuf/
8//
9// Redistribution and use in source and binary forms, with or without
10// modification, are permitted provided that the following conditions are
11// met:
12//
13// * Redistributions of source code must retain the above copyright
14// notice, this list of conditions and the following disclaimer.
15// * Redistributions in binary form must reproduce the above
16// copyright notice, this list of conditions and the following disclaimer
17// in the documentation and/or other materials provided with the
18// distribution.
19// * Neither the name of Google Inc. nor the names of its
20// contributors may be used to endorse or promote products derived from
21// this software without specific prior written permission.
22//
23// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35#endregion
36
37using System.IO;
38using Google.ProtocolBuffers.Descriptors;
39using Google.ProtocolBuffers.TestProtos;
40using NUnit.Framework;
41
42namespace Google.ProtocolBuffers
43{
44 /// <summary>
45 /// Miscellaneous tests for message operations that apply to both
46 /// generated and dynamic messages.
47 /// </summary>
48 [TestFixture]
49 public class MessageTest
50 {
51 // =================================================================
52 // Message-merging tests.
53
54 private static readonly TestAllTypes MergeSource = new TestAllTypes.Builder
55 {
56 OptionalInt32 = 1,
57 OptionalString = "foo",
58 OptionalForeignMessage =
59 ForeignMessage.DefaultInstance,
60 }.AddRepeatedString("bar").Build();
61
62 private static readonly TestAllTypes MergeDest = new TestAllTypes.Builder
63 {
64 OptionalInt64 = 2,
65 OptionalString = "baz",
66 OptionalForeignMessage =
67 new ForeignMessage.Builder {C = 3}.Build(),
68 }.AddRepeatedString("qux").Build();
69
70 private const string MergeResultText =
71 "optional_int32: 1\n" +
72 "optional_int64: 2\n" +
73 "optional_string: \"foo\"\n" +
74 "optional_foreign_message {\n" +
75 " c: 3\n" +
76 "}\n" +
77 "repeated_string: \"qux\"\n" +
78 "repeated_string: \"bar\"\n";
79
80 [Test]
81 public void MergeFrom()
82 {
83 TestAllTypes result = TestAllTypes.CreateBuilder(MergeDest).MergeFrom(MergeSource).Build();
84
85 Assert.AreEqual(MergeResultText, result.ToString());
86 }
87
88 /// <summary>
89 /// Test merging a DynamicMessage into a GeneratedMessage.
90 /// As long as they have the same descriptor, this should work, but it is an
91 /// entirely different code path.
92 /// </summary>
93 [Test]
94 public void MergeFromDynamic()
95 {
96 TestAllTypes result = (TestAllTypes) TestAllTypes.CreateBuilder(MergeDest)
97 .MergeFrom(DynamicMessage.CreateBuilder(MergeSource).Build())
98 .Build();
99
100 Assert.AreEqual(MergeResultText, result.ToString());
101 }
102
103 /// <summary>
104 /// Test merging two DynamicMessages.
105 /// </summary>
106 [Test]
107 public void DynamicMergeFrom()
108 {
109 DynamicMessage result = (DynamicMessage) DynamicMessage.CreateBuilder(MergeDest)
110 .MergeFrom(
111 (DynamicMessage)
112 DynamicMessage.CreateBuilder(MergeSource).Build())
113 .Build();
114
115 Assert.AreEqual(MergeResultText, result.ToString());
116 }
117
118 // =================================================================
119 // Required-field-related tests.
120
121 private static readonly TestRequired TestRequiredUninitialized = TestRequired.DefaultInstance;
122
123 private static readonly TestRequired TestRequiredInitialized = new TestRequired.Builder
124 {
125 A = 1,
126 B = 2,
127 C = 3
128 }.Build();
129
130 [Test]
131 public void Initialization()
132 {
133 TestRequired.Builder builder = TestRequired.CreateBuilder();
134
135 Assert.IsFalse(builder.IsInitialized);
136 builder.A = 1;
137 Assert.IsFalse(builder.IsInitialized);
138 builder.B = 1;
139 Assert.IsFalse(builder.IsInitialized);
140 builder.C = 1;
141 Assert.IsTrue(builder.IsInitialized);
142 }
143
144 [Test]
145 public void RequiredForeign()
146 {
147 TestRequiredForeign.Builder builder = TestRequiredForeign.CreateBuilder();
148
149 Assert.IsTrue(builder.IsInitialized);
150
151 builder.SetOptionalMessage(TestRequiredUninitialized);
152 Assert.IsFalse(builder.IsInitialized);
153
154 builder.SetOptionalMessage(TestRequiredInitialized);
155 Assert.IsTrue(builder.IsInitialized);
156
157 builder.AddRepeatedMessage(TestRequiredUninitialized);
158 Assert.IsFalse(builder.IsInitialized);
159
160 builder.SetRepeatedMessage(0, TestRequiredInitialized);
161 Assert.IsTrue(builder.IsInitialized);
162 }
163
164 [Test]
165 public void RequiredExtension()
166 {
167 TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder();
168
169 Assert.IsTrue(builder.IsInitialized);
170
171 builder.SetExtension(TestRequired.Single, TestRequiredUninitialized);
172 Assert.IsFalse(builder.IsInitialized);
173
174 builder.SetExtension(TestRequired.Single, TestRequiredInitialized);
175 Assert.IsTrue(builder.IsInitialized);
176
177 builder.AddExtension(TestRequired.Multi, TestRequiredUninitialized);
178 Assert.IsFalse(builder.IsInitialized);
179
180 builder.SetExtension(TestRequired.Multi, 0, TestRequiredInitialized);
181 Assert.IsTrue(builder.IsInitialized);
182 }
183
184 [Test]
185 public void RequiredDynamic()
186 {
187 MessageDescriptor descriptor = TestRequired.Descriptor;
188 DynamicMessage.Builder builder = DynamicMessage.CreateBuilder(descriptor);
189
190 Assert.IsFalse(builder.IsInitialized);
191 builder[descriptor.FindDescriptor<FieldDescriptor>("a")] = 1;
192 Assert.IsFalse(builder.IsInitialized);
193 builder[descriptor.FindDescriptor<FieldDescriptor>("b")] = 1;
194 Assert.IsFalse(builder.IsInitialized);
195 builder[descriptor.FindDescriptor<FieldDescriptor>("c")] = 1;
196 Assert.IsTrue(builder.IsInitialized);
197 }
198
199 [Test]
200 public void RequiredDynamicForeign()
201 {
202 MessageDescriptor descriptor = TestRequiredForeign.Descriptor;
203 DynamicMessage.Builder builder = DynamicMessage.CreateBuilder(descriptor);
204
205 Assert.IsTrue(builder.IsInitialized);
206
207 builder[descriptor.FindDescriptor<FieldDescriptor>("optional_message")] = TestRequiredUninitialized;
208 Assert.IsFalse(builder.IsInitialized);
209
210 builder[descriptor.FindDescriptor<FieldDescriptor>("optional_message")] = TestRequiredInitialized;
211 Assert.IsTrue(builder.IsInitialized);
212
213 builder.AddRepeatedField(descriptor.FindDescriptor<FieldDescriptor>("repeated_message"),
214 TestRequiredUninitialized);
215 Assert.IsFalse(builder.IsInitialized);
216
217 builder.SetRepeatedField(descriptor.FindDescriptor<FieldDescriptor>("repeated_message"), 0,
218 TestRequiredInitialized);
219 Assert.IsTrue(builder.IsInitialized);
220 }
221
222 [Test]
223 public void UninitializedException()
224 {
225 try
226 {
227 TestRequired.CreateBuilder().Build();
228 Assert.Fail("Should have thrown an exception.");
229 }
230 catch (UninitializedMessageException e)
231 {
232 Assert.AreEqual("Message missing required fields: a, b, c", e.Message);
233 }
234 }
235
236 [Test]
237 public void BuildPartial()
238 {
239 // We're mostly testing that no exception is thrown.
240 TestRequired message = TestRequired.CreateBuilder().BuildPartial();
241 Assert.IsFalse(message.IsInitialized);
242 }
243
244 [Test]
245 public void NestedUninitializedException()
246 {
247 try
248 {
249 TestRequiredForeign.CreateBuilder()
250 .SetOptionalMessage(TestRequiredUninitialized)
251 .AddRepeatedMessage(TestRequiredUninitialized)
252 .AddRepeatedMessage(TestRequiredUninitialized)
253 .Build();
254 Assert.Fail("Should have thrown an exception.");
255 }
256 catch (UninitializedMessageException e)
257 {
258 Assert.AreEqual(
259 "Message missing required fields: " +
260 "optional_message.a, " +
261 "optional_message.b, " +
262 "optional_message.c, " +
263 "repeated_message[0].a, " +
264 "repeated_message[0].b, " +
265 "repeated_message[0].c, " +
266 "repeated_message[1].a, " +
267 "repeated_message[1].b, " +
268 "repeated_message[1].c",
269 e.Message);
270 }
271 }
272
273 [Test]
274 public void BuildNestedPartial()
275 {
276 // We're mostly testing that no exception is thrown.
277 TestRequiredForeign message =
278 TestRequiredForeign.CreateBuilder()
279 .SetOptionalMessage(TestRequiredUninitialized)
280 .AddRepeatedMessage(TestRequiredUninitialized)
281 .AddRepeatedMessage(TestRequiredUninitialized)
282 .BuildPartial();
283 Assert.IsFalse(message.IsInitialized);
284 }
285
286 [Test]
287 public void ParseUnititialized()
288 {
289 try
290 {
291 TestRequired.ParseFrom(ByteString.Empty);
292 Assert.Fail("Should have thrown an exception.");
293 }
294 catch (InvalidProtocolBufferException e)
295 {
296 Assert.AreEqual("Message missing required fields: a, b, c", e.Message);
297 }
298 }
299
300 [Test]
301 public void ParseNestedUnititialized()
302 {
303 ByteString data =
304 TestRequiredForeign.CreateBuilder()
305 .SetOptionalMessage(TestRequiredUninitialized)
306 .AddRepeatedMessage(TestRequiredUninitialized)
307 .AddRepeatedMessage(TestRequiredUninitialized)
308 .BuildPartial().ToByteString();
309
310 try
311 {
312 TestRequiredForeign.ParseFrom(data);
313 Assert.Fail("Should have thrown an exception.");
314 }
315 catch (InvalidProtocolBufferException e)
316 {
317 Assert.AreEqual(
318 "Message missing required fields: " +
319 "optional_message.a, " +
320 "optional_message.b, " +
321 "optional_message.c, " +
322 "repeated_message[0].a, " +
323 "repeated_message[0].b, " +
324 "repeated_message[0].c, " +
325 "repeated_message[1].a, " +
326 "repeated_message[1].b, " +
327 "repeated_message[1].c",
328 e.Message);
329 }
330 }
331
332 [Test]
333 public void DynamicUninitializedException()
334 {
335 try
336 {
337 DynamicMessage.CreateBuilder(TestRequired.Descriptor).Build();
338 Assert.Fail("Should have thrown an exception.");
339 }
340 catch (UninitializedMessageException e)
341 {
342 Assert.AreEqual("Message missing required fields: a, b, c", e.Message);
343 }
344 }
345
346 [Test]
347 public void DynamicBuildPartial()
348 {
349 // We're mostly testing that no exception is thrown.
350 DynamicMessage message = DynamicMessage.CreateBuilder(TestRequired.Descriptor).BuildPartial();
351 Assert.IsFalse(message.Initialized);
352 }
353
354 [Test]
355 public void DynamicParseUnititialized()
356 {
357 try
358 {
359 MessageDescriptor descriptor = TestRequired.Descriptor;
360 DynamicMessage.ParseFrom(descriptor, ByteString.Empty);
361 Assert.Fail("Should have thrown an exception.");
362 }
363 catch (InvalidProtocolBufferException e)
364 {
365 Assert.AreEqual("Message missing required fields: a, b, c", e.Message);
366 }
367 }
368
369 [Test]
370 public void PackedTypesWrittenDirectlyToStream()
371 {
372 TestPackedTypes message = new TestPackedTypes.Builder {PackedInt32List = {0, 1, 2}}.Build();
373 MemoryStream stream = new MemoryStream();
374 message.WriteTo(stream);
375 stream.Position = 0;
376 TestPackedTypes readMessage = TestPackedTypes.ParseFrom(stream);
377 Assert.AreEqual(message, readMessage);
378 }
379 }
380}