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