1 | #region Copyright notice and license
|
---|
2 | // 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:
|
---|
6 | // http://code.google.com/p/protobuf/
|
---|
7 | //
|
---|
8 | // Redistribution and use in source and binary forms, with or without
|
---|
9 | // modification, are permitted provided that the following conditions are
|
---|
10 | // met:
|
---|
11 | //
|
---|
12 | // * 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.
|
---|
21 | //
|
---|
22 | // 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.
|
---|
33 | #endregion
|
---|
34 |
|
---|
35 | using System.IO;
|
---|
36 | using Google.ProtocolBuffers.Descriptors;
|
---|
37 | using Google.ProtocolBuffers.TestProtos;
|
---|
38 | using NUnit.Framework;
|
---|
39 |
|
---|
40 | namespace Google.ProtocolBuffers {
|
---|
41 | /// <summary>
|
---|
42 | /// Miscellaneous tests for message operations that apply to both
|
---|
43 | /// generated and dynamic messages.
|
---|
44 | /// </summary>
|
---|
45 | [TestFixture]
|
---|
46 | public class MessageTest {
|
---|
47 | // =================================================================
|
---|
48 | // Message-merging tests.
|
---|
49 |
|
---|
50 | private static readonly TestAllTypes MergeSource = new TestAllTypes.Builder {
|
---|
51 | OptionalInt32 = 1,
|
---|
52 | OptionalString = "foo",
|
---|
53 | OptionalForeignMessage = ForeignMessage.DefaultInstance,
|
---|
54 | }.AddRepeatedString("bar").Build();
|
---|
55 |
|
---|
56 | private static readonly TestAllTypes MergeDest = new TestAllTypes.Builder {
|
---|
57 | OptionalInt64 = 2,
|
---|
58 | OptionalString = "baz",
|
---|
59 | OptionalForeignMessage = new ForeignMessage.Builder { C=3 }.Build(),
|
---|
60 | }.AddRepeatedString("qux").Build();
|
---|
61 |
|
---|
62 | private const string MergeResultText =
|
---|
63 | "optional_int32: 1\n" +
|
---|
64 | "optional_int64: 2\n" +
|
---|
65 | "optional_string: \"foo\"\n" +
|
---|
66 | "optional_foreign_message {\n" +
|
---|
67 | " c: 3\n" +
|
---|
68 | "}\n" +
|
---|
69 | "repeated_string: \"qux\"\n" +
|
---|
70 | "repeated_string: \"bar\"\n";
|
---|
71 |
|
---|
72 | [Test]
|
---|
73 | public void MergeFrom() {
|
---|
74 | TestAllTypes result = TestAllTypes.CreateBuilder(MergeDest).MergeFrom(MergeSource).Build();
|
---|
75 |
|
---|
76 | Assert.AreEqual(MergeResultText, result.ToString());
|
---|
77 | }
|
---|
78 |
|
---|
79 | /// <summary>
|
---|
80 | /// Test merging a DynamicMessage into a GeneratedMessage.
|
---|
81 | /// As long as they have the same descriptor, this should work, but it is an
|
---|
82 | /// entirely different code path.
|
---|
83 | /// </summary>
|
---|
84 | [Test]
|
---|
85 | public void MergeFromDynamic() {
|
---|
86 | TestAllTypes result = (TestAllTypes) TestAllTypes.CreateBuilder(MergeDest)
|
---|
87 | .MergeFrom(DynamicMessage.CreateBuilder(MergeSource).Build())
|
---|
88 | .Build();
|
---|
89 |
|
---|
90 | Assert.AreEqual(MergeResultText, result.ToString());
|
---|
91 | }
|
---|
92 |
|
---|
93 | /// <summary>
|
---|
94 | /// Test merging two DynamicMessages.
|
---|
95 | /// </summary>
|
---|
96 | [Test]
|
---|
97 | public void DynamicMergeFrom() {
|
---|
98 | DynamicMessage result = (DynamicMessage) DynamicMessage.CreateBuilder(MergeDest)
|
---|
99 | .MergeFrom((DynamicMessage) DynamicMessage.CreateBuilder(MergeSource).Build())
|
---|
100 | .Build();
|
---|
101 |
|
---|
102 | Assert.AreEqual(MergeResultText, result.ToString());
|
---|
103 | }
|
---|
104 |
|
---|
105 | // =================================================================
|
---|
106 | // Required-field-related tests.
|
---|
107 |
|
---|
108 | private static readonly TestRequired TestRequiredUninitialized = TestRequired.DefaultInstance;
|
---|
109 | private static readonly TestRequired TestRequiredInitialized = new TestRequired.Builder {
|
---|
110 | A = 1, B = 2, C = 3
|
---|
111 | }.Build();
|
---|
112 |
|
---|
113 | [Test]
|
---|
114 | public void Initialization() {
|
---|
115 | TestRequired.Builder builder = TestRequired.CreateBuilder();
|
---|
116 |
|
---|
117 | Assert.IsFalse(builder.IsInitialized);
|
---|
118 | builder.A = 1;
|
---|
119 | Assert.IsFalse(builder.IsInitialized);
|
---|
120 | builder.B = 1;
|
---|
121 | Assert.IsFalse(builder.IsInitialized);
|
---|
122 | builder.C = 1;
|
---|
123 | Assert.IsTrue(builder.IsInitialized);
|
---|
124 | }
|
---|
125 |
|
---|
126 | [Test]
|
---|
127 | public void RequiredForeign() {
|
---|
128 | TestRequiredForeign.Builder builder = TestRequiredForeign.CreateBuilder();
|
---|
129 |
|
---|
130 | Assert.IsTrue(builder.IsInitialized);
|
---|
131 |
|
---|
132 | builder.SetOptionalMessage(TestRequiredUninitialized);
|
---|
133 | Assert.IsFalse(builder.IsInitialized);
|
---|
134 |
|
---|
135 | builder.SetOptionalMessage(TestRequiredInitialized);
|
---|
136 | Assert.IsTrue(builder.IsInitialized);
|
---|
137 |
|
---|
138 | builder.AddRepeatedMessage(TestRequiredUninitialized);
|
---|
139 | Assert.IsFalse(builder.IsInitialized);
|
---|
140 |
|
---|
141 | builder.SetRepeatedMessage(0, TestRequiredInitialized);
|
---|
142 | Assert.IsTrue(builder.IsInitialized);
|
---|
143 | }
|
---|
144 |
|
---|
145 | [Test]
|
---|
146 | public void RequiredExtension() {
|
---|
147 | TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder();
|
---|
148 |
|
---|
149 | Assert.IsTrue(builder.IsInitialized);
|
---|
150 |
|
---|
151 | builder.SetExtension(TestRequired.Single, TestRequiredUninitialized);
|
---|
152 | Assert.IsFalse(builder.IsInitialized);
|
---|
153 |
|
---|
154 | builder.SetExtension(TestRequired.Single, TestRequiredInitialized);
|
---|
155 | Assert.IsTrue(builder.IsInitialized);
|
---|
156 |
|
---|
157 | builder.AddExtension(TestRequired.Multi, TestRequiredUninitialized);
|
---|
158 | Assert.IsFalse(builder.IsInitialized);
|
---|
159 |
|
---|
160 | builder.SetExtension(TestRequired.Multi, 0, TestRequiredInitialized);
|
---|
161 | Assert.IsTrue(builder.IsInitialized);
|
---|
162 | }
|
---|
163 |
|
---|
164 | [Test]
|
---|
165 | public void RequiredDynamic() {
|
---|
166 | MessageDescriptor descriptor = TestRequired.Descriptor;
|
---|
167 | DynamicMessage.Builder builder = DynamicMessage.CreateBuilder(descriptor);
|
---|
168 |
|
---|
169 | Assert.IsFalse(builder.IsInitialized);
|
---|
170 | builder[descriptor.FindDescriptor<FieldDescriptor>("a")] = 1;
|
---|
171 | Assert.IsFalse(builder.IsInitialized);
|
---|
172 | builder[descriptor.FindDescriptor<FieldDescriptor>("b")] = 1;
|
---|
173 | Assert.IsFalse(builder.IsInitialized);
|
---|
174 | builder[descriptor.FindDescriptor<FieldDescriptor>("c")] = 1;
|
---|
175 | Assert.IsTrue(builder.IsInitialized);
|
---|
176 | }
|
---|
177 |
|
---|
178 | [Test]
|
---|
179 | public void RequiredDynamicForeign() {
|
---|
180 | MessageDescriptor descriptor = TestRequiredForeign.Descriptor;
|
---|
181 | DynamicMessage.Builder builder = DynamicMessage.CreateBuilder(descriptor);
|
---|
182 |
|
---|
183 | Assert.IsTrue(builder.IsInitialized);
|
---|
184 |
|
---|
185 | builder[descriptor.FindDescriptor<FieldDescriptor>("optional_message")] = TestRequiredUninitialized;
|
---|
186 | Assert.IsFalse(builder.IsInitialized);
|
---|
187 |
|
---|
188 | builder[descriptor.FindDescriptor<FieldDescriptor>("optional_message")] = TestRequiredInitialized;
|
---|
189 | Assert.IsTrue(builder.IsInitialized);
|
---|
190 |
|
---|
191 | builder.AddRepeatedField(descriptor.FindDescriptor<FieldDescriptor>("repeated_message"), TestRequiredUninitialized);
|
---|
192 | Assert.IsFalse(builder.IsInitialized);
|
---|
193 |
|
---|
194 | builder.SetRepeatedField(descriptor.FindDescriptor<FieldDescriptor>("repeated_message"), 0, TestRequiredInitialized);
|
---|
195 | Assert.IsTrue(builder.IsInitialized);
|
---|
196 | }
|
---|
197 |
|
---|
198 | [Test]
|
---|
199 | public void UninitializedException() {
|
---|
200 | try {
|
---|
201 | TestRequired.CreateBuilder().Build();
|
---|
202 | Assert.Fail("Should have thrown an exception.");
|
---|
203 | } catch (UninitializedMessageException e) {
|
---|
204 | Assert.AreEqual("Message missing required fields: a, b, c", e.Message);
|
---|
205 | }
|
---|
206 | }
|
---|
207 |
|
---|
208 | [Test]
|
---|
209 | public void BuildPartial() {
|
---|
210 | // We're mostly testing that no exception is thrown.
|
---|
211 | TestRequired message = TestRequired.CreateBuilder().BuildPartial();
|
---|
212 | Assert.IsFalse(message.IsInitialized);
|
---|
213 | }
|
---|
214 |
|
---|
215 | [Test]
|
---|
216 | public void NestedUninitializedException() {
|
---|
217 | try {
|
---|
218 | TestRequiredForeign.CreateBuilder()
|
---|
219 | .SetOptionalMessage(TestRequiredUninitialized)
|
---|
220 | .AddRepeatedMessage(TestRequiredUninitialized)
|
---|
221 | .AddRepeatedMessage(TestRequiredUninitialized)
|
---|
222 | .Build();
|
---|
223 | Assert.Fail("Should have thrown an exception.");
|
---|
224 | } catch (UninitializedMessageException e) {
|
---|
225 | Assert.AreEqual(
|
---|
226 | "Message missing required fields: " +
|
---|
227 | "optional_message.a, " +
|
---|
228 | "optional_message.b, " +
|
---|
229 | "optional_message.c, " +
|
---|
230 | "repeated_message[0].a, " +
|
---|
231 | "repeated_message[0].b, " +
|
---|
232 | "repeated_message[0].c, " +
|
---|
233 | "repeated_message[1].a, " +
|
---|
234 | "repeated_message[1].b, " +
|
---|
235 | "repeated_message[1].c",
|
---|
236 | e.Message);
|
---|
237 | }
|
---|
238 | }
|
---|
239 |
|
---|
240 | [Test]
|
---|
241 | public void BuildNestedPartial() {
|
---|
242 | // We're mostly testing that no exception is thrown.
|
---|
243 | TestRequiredForeign message =
|
---|
244 | TestRequiredForeign.CreateBuilder()
|
---|
245 | .SetOptionalMessage(TestRequiredUninitialized)
|
---|
246 | .AddRepeatedMessage(TestRequiredUninitialized)
|
---|
247 | .AddRepeatedMessage(TestRequiredUninitialized)
|
---|
248 | .BuildPartial();
|
---|
249 | Assert.IsFalse(message.IsInitialized);
|
---|
250 | }
|
---|
251 |
|
---|
252 | [Test]
|
---|
253 | public void ParseUnititialized() {
|
---|
254 | try {
|
---|
255 | TestRequired.ParseFrom(ByteString.Empty);
|
---|
256 | Assert.Fail("Should have thrown an exception.");
|
---|
257 | } catch (InvalidProtocolBufferException e) {
|
---|
258 | Assert.AreEqual("Message missing required fields: a, b, c", e.Message);
|
---|
259 | }
|
---|
260 | }
|
---|
261 |
|
---|
262 | [Test]
|
---|
263 | public void ParseNestedUnititialized() {
|
---|
264 | ByteString data =
|
---|
265 | TestRequiredForeign.CreateBuilder()
|
---|
266 | .SetOptionalMessage(TestRequiredUninitialized)
|
---|
267 | .AddRepeatedMessage(TestRequiredUninitialized)
|
---|
268 | .AddRepeatedMessage(TestRequiredUninitialized)
|
---|
269 | .BuildPartial().ToByteString();
|
---|
270 |
|
---|
271 | try {
|
---|
272 | TestRequiredForeign.ParseFrom(data);
|
---|
273 | Assert.Fail("Should have thrown an exception.");
|
---|
274 | } catch (InvalidProtocolBufferException e) {
|
---|
275 | Assert.AreEqual(
|
---|
276 | "Message missing required fields: " +
|
---|
277 | "optional_message.a, " +
|
---|
278 | "optional_message.b, " +
|
---|
279 | "optional_message.c, " +
|
---|
280 | "repeated_message[0].a, " +
|
---|
281 | "repeated_message[0].b, " +
|
---|
282 | "repeated_message[0].c, " +
|
---|
283 | "repeated_message[1].a, " +
|
---|
284 | "repeated_message[1].b, " +
|
---|
285 | "repeated_message[1].c",
|
---|
286 | e.Message);
|
---|
287 | }
|
---|
288 | }
|
---|
289 |
|
---|
290 | [Test]
|
---|
291 | public void DynamicUninitializedException() {
|
---|
292 | try {
|
---|
293 | DynamicMessage.CreateBuilder(TestRequired.Descriptor).Build();
|
---|
294 | Assert.Fail("Should have thrown an exception.");
|
---|
295 | } catch (UninitializedMessageException e) {
|
---|
296 | Assert.AreEqual("Message missing required fields: a, b, c", e.Message);
|
---|
297 | }
|
---|
298 | }
|
---|
299 |
|
---|
300 | [Test]
|
---|
301 | public void DynamicBuildPartial() {
|
---|
302 | // We're mostly testing that no exception is thrown.
|
---|
303 | DynamicMessage message = DynamicMessage.CreateBuilder(TestRequired.Descriptor).BuildPartial();
|
---|
304 | Assert.IsFalse(message.Initialized);
|
---|
305 | }
|
---|
306 |
|
---|
307 | [Test]
|
---|
308 | public void DynamicParseUnititialized() {
|
---|
309 | try {
|
---|
310 | MessageDescriptor descriptor = TestRequired.Descriptor;
|
---|
311 | DynamicMessage.ParseFrom(descriptor, ByteString.Empty);
|
---|
312 | Assert.Fail("Should have thrown an exception.");
|
---|
313 | } catch (InvalidProtocolBufferException e) {
|
---|
314 | Assert.AreEqual("Message missing required fields: a, b, c", e.Message);
|
---|
315 | }
|
---|
316 | }
|
---|
317 |
|
---|
318 | [Test]
|
---|
319 | public void PackedTypesWrittenDirectlyToStream() {
|
---|
320 | TestPackedTypes message = new TestPackedTypes.Builder {PackedInt32List = {0, 1, 2}}.Build();
|
---|
321 | MemoryStream stream = new MemoryStream();
|
---|
322 | message.WriteTo(stream);
|
---|
323 | stream.Position = 0;
|
---|
324 | TestPackedTypes readMessage = TestPackedTypes.ParseFrom(stream);
|
---|
325 | Assert.AreEqual(message, readMessage);
|
---|
326 | }
|
---|
327 | }
|
---|
328 |
|
---|
329 | }
|
---|