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