csharptest | 71f662c | 2011-05-20 15:15:34 -0500 | [diff] [blame^] | 1 | #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 |
|
| 37 | using System.IO;
|
| 38 | using Google.ProtocolBuffers.Descriptors;
|
| 39 | using Google.ProtocolBuffers.TestProtos;
|
| 40 | using NUnit.Framework;
|
| 41 |
|
| 42 | namespace 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 | } |