| #region Copyright notice and license | |
| // Protocol Buffers - Google's data interchange format | |
| // Copyright 2008 Google Inc. All rights reserved. | |
| // http://github.com/jskeet/dotnet-protobufs/ | |
| // Original C++/Java/Python code: | |
| // http://code.google.com/p/protobuf/ | |
| // | |
| // Redistribution and use in source and binary forms, with or without | |
| // modification, are permitted provided that the following conditions are | |
| // met: | |
| // | |
| // * Redistributions of source code must retain the above copyright | |
| // notice, this list of conditions and the following disclaimer. | |
| // * Redistributions in binary form must reproduce the above | |
| // copyright notice, this list of conditions and the following disclaimer | |
| // in the documentation and/or other materials provided with the | |
| // distribution. | |
| // * Neither the name of Google Inc. nor the names of its | |
| // contributors may be used to endorse or promote products derived from | |
| // this software without specific prior written permission. | |
| // | |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| #endregion | |
| using System.IO; | |
| using Google.ProtocolBuffers.Descriptors; | |
| using Google.ProtocolBuffers.TestProtos; | |
| using NUnit.Framework; | |
| namespace Google.ProtocolBuffers | |
| { | |
| /// <summary> | |
| /// Miscellaneous tests for message operations that apply to both | |
| /// generated and dynamic messages. | |
| /// </summary> | |
| public class MessageTest | |
| { | |
| // ================================================================= | |
| // Message-merging tests. | |
| private static readonly TestAllTypes MergeSource = new TestAllTypes.Builder | |
| { | |
| OptionalInt32 = 1, | |
| OptionalString = "foo", | |
| OptionalForeignMessage = | |
| ForeignMessage.DefaultInstance, | |
| }.AddRepeatedString("bar").Build(); | |
| private static readonly TestAllTypes MergeDest = new TestAllTypes.Builder | |
| { | |
| OptionalInt64 = 2, | |
| OptionalString = "baz", | |
| OptionalForeignMessage = | |
| new ForeignMessage.Builder {C = 3}.Build(), | |
| }.AddRepeatedString("qux").Build(); | |
| private const string MergeResultText = | |
| "optional_int32: 1\n" + | |
| "optional_int64: 2\n" + | |
| "optional_string: \"foo\"\n" + | |
| "optional_foreign_message {\n" + | |
| " c: 3\n" + | |
| "}\n" + | |
| "repeated_string: \"qux\"\n" + | |
| "repeated_string: \"bar\"\n"; | |
| [Test] | |
| public void MergeFrom() | |
| { | |
| TestAllTypes result = TestAllTypes.CreateBuilder(MergeDest).MergeFrom(MergeSource).Build(); | |
| Assert.AreEqual(MergeResultText, result.ToString()); | |
| } | |
| /// <summary> | |
| /// Test merging a DynamicMessage into a GeneratedMessage. | |
| /// As long as they have the same descriptor, this should work, but it is an | |
| /// entirely different code path. | |
| /// </summary> | |
| [Test] | |
| public void MergeFromDynamic() | |
| { | |
| TestAllTypes result = (TestAllTypes) TestAllTypes.CreateBuilder(MergeDest) | |
| .MergeFrom(DynamicMessage.CreateBuilder(MergeSource).Build()) | |
| .Build(); | |
| Assert.AreEqual(MergeResultText, result.ToString()); | |
| } | |
| /// <summary> | |
| /// Test merging two DynamicMessages. | |
| /// </summary> | |
| [Test] | |
| public void DynamicMergeFrom() | |
| { | |
| DynamicMessage result = (DynamicMessage) DynamicMessage.CreateBuilder(MergeDest) | |
| .MergeFrom( | |
| (DynamicMessage) | |
| DynamicMessage.CreateBuilder(MergeSource).Build()) | |
| .Build(); | |
| Assert.AreEqual(MergeResultText, result.ToString()); | |
| } | |
| // ================================================================= | |
| // Required-field-related tests. | |
| private static readonly TestRequired TestRequiredUninitialized = TestRequired.DefaultInstance; | |
| private static readonly TestRequired TestRequiredInitialized = new TestRequired.Builder | |
| { | |
| A = 1, | |
| B = 2, | |
| C = 3 | |
| }.Build(); | |
| [Test] | |
| public void Initialization() | |
| { | |
| TestRequired.Builder builder = TestRequired.CreateBuilder(); | |
| Assert.IsFalse(builder.IsInitialized); | |
| builder.A = 1; | |
| Assert.IsFalse(builder.IsInitialized); | |
| builder.B = 1; | |
| Assert.IsFalse(builder.IsInitialized); | |
| builder.C = 1; | |
| Assert.IsTrue(builder.IsInitialized); | |
| } | |
| [Test] | |
| public void UninitializedBuilderToString() | |
| { | |
| TestRequired.Builder builder = TestRequired.CreateBuilder().SetA(1); | |
| Assert.AreEqual("a: 1\n", builder.ToString()); | |
| } | |
| [Test] | |
| public void RequiredForeign() | |
| { | |
| TestRequiredForeign.Builder builder = TestRequiredForeign.CreateBuilder(); | |
| Assert.IsTrue(builder.IsInitialized); | |
| builder.SetOptionalMessage(TestRequiredUninitialized); | |
| Assert.IsFalse(builder.IsInitialized); | |
| builder.SetOptionalMessage(TestRequiredInitialized); | |
| Assert.IsTrue(builder.IsInitialized); | |
| builder.AddRepeatedMessage(TestRequiredUninitialized); | |
| Assert.IsFalse(builder.IsInitialized); | |
| builder.SetRepeatedMessage(0, TestRequiredInitialized); | |
| Assert.IsTrue(builder.IsInitialized); | |
| } | |
| [Test] | |
| public void RequiredExtension() | |
| { | |
| TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder(); | |
| Assert.IsTrue(builder.IsInitialized); | |
| builder.SetExtension(TestRequired.Single, TestRequiredUninitialized); | |
| Assert.IsFalse(builder.IsInitialized); | |
| builder.SetExtension(TestRequired.Single, TestRequiredInitialized); | |
| Assert.IsTrue(builder.IsInitialized); | |
| builder.AddExtension(TestRequired.Multi, TestRequiredUninitialized); | |
| Assert.IsFalse(builder.IsInitialized); | |
| builder.SetExtension(TestRequired.Multi, 0, TestRequiredInitialized); | |
| Assert.IsTrue(builder.IsInitialized); | |
| } | |
| [Test] | |
| public void RequiredDynamic() | |
| { | |
| MessageDescriptor descriptor = TestRequired.Descriptor; | |
| DynamicMessage.Builder builder = DynamicMessage.CreateBuilder(descriptor); | |
| Assert.IsFalse(builder.IsInitialized); | |
| builder[descriptor.FindDescriptor<FieldDescriptor>("a")] = 1; | |
| Assert.IsFalse(builder.IsInitialized); | |
| builder[descriptor.FindDescriptor<FieldDescriptor>("b")] = 1; | |
| Assert.IsFalse(builder.IsInitialized); | |
| builder[descriptor.FindDescriptor<FieldDescriptor>("c")] = 1; | |
| Assert.IsTrue(builder.IsInitialized); | |
| } | |
| [Test] | |
| public void RequiredDynamicForeign() | |
| { | |
| MessageDescriptor descriptor = TestRequiredForeign.Descriptor; | |
| DynamicMessage.Builder builder = DynamicMessage.CreateBuilder(descriptor); | |
| Assert.IsTrue(builder.IsInitialized); | |
| builder[descriptor.FindDescriptor<FieldDescriptor>("optional_message")] = TestRequiredUninitialized; | |
| Assert.IsFalse(builder.IsInitialized); | |
| builder[descriptor.FindDescriptor<FieldDescriptor>("optional_message")] = TestRequiredInitialized; | |
| Assert.IsTrue(builder.IsInitialized); | |
| builder.AddRepeatedField(descriptor.FindDescriptor<FieldDescriptor>("repeated_message"), | |
| TestRequiredUninitialized); | |
| Assert.IsFalse(builder.IsInitialized); | |
| builder.SetRepeatedField(descriptor.FindDescriptor<FieldDescriptor>("repeated_message"), 0, | |
| TestRequiredInitialized); | |
| Assert.IsTrue(builder.IsInitialized); | |
| } | |
| [Test] | |
| public void UninitializedException() | |
| { | |
| var e = Assert.Throws<UninitializedMessageException>(() => TestRequired.CreateBuilder().Build()); | |
| Assert.AreEqual("Message missing required fields: a, b, c", e.Message); | |
| } | |
| [Test] | |
| public void BuildPartial() | |
| { | |
| // We're mostly testing that no exception is thrown. | |
| TestRequired message = TestRequired.CreateBuilder().BuildPartial(); | |
| Assert.IsFalse(message.IsInitialized); | |
| } | |
| [Test] | |
| public void NestedUninitializedException() | |
| { | |
| var e = Assert.Throws<UninitializedMessageException>(() => TestRequiredForeign.CreateBuilder() | |
| .SetOptionalMessage(TestRequiredUninitialized) | |
| .AddRepeatedMessage(TestRequiredUninitialized) | |
| .AddRepeatedMessage(TestRequiredUninitialized) | |
| .Build()); | |
| Assert.AreEqual( | |
| "Message missing required fields: " + | |
| "optional_message.a, " + | |
| "optional_message.b, " + | |
| "optional_message.c, " + | |
| "repeated_message[0].a, " + | |
| "repeated_message[0].b, " + | |
| "repeated_message[0].c, " + | |
| "repeated_message[1].a, " + | |
| "repeated_message[1].b, " + | |
| "repeated_message[1].c", | |
| e.Message); | |
| } | |
| [Test] | |
| public void BuildNestedPartial() | |
| { | |
| // We're mostly testing that no exception is thrown. | |
| TestRequiredForeign message = | |
| TestRequiredForeign.CreateBuilder() | |
| .SetOptionalMessage(TestRequiredUninitialized) | |
| .AddRepeatedMessage(TestRequiredUninitialized) | |
| .AddRepeatedMessage(TestRequiredUninitialized) | |
| .BuildPartial(); | |
| Assert.IsFalse(message.IsInitialized); | |
| } | |
| [Test] | |
| public void ParseUninitialized() | |
| { | |
| var e = Assert.Throws<InvalidProtocolBufferException>(() => TestRequired.ParseFrom(ByteString.Empty)); | |
| Assert.AreEqual("Message missing required fields: a, b, c", e.Message); | |
| } | |
| [Test] | |
| public void ParseNestedUnititialized() | |
| { | |
| ByteString data = | |
| TestRequiredForeign.CreateBuilder() | |
| .SetOptionalMessage(TestRequiredUninitialized) | |
| .AddRepeatedMessage(TestRequiredUninitialized) | |
| .AddRepeatedMessage(TestRequiredUninitialized) | |
| .BuildPartial().ToByteString(); | |
| var e = Assert.Throws<InvalidProtocolBufferException>(() => TestRequiredForeign.ParseFrom(data)); | |
| Assert.AreEqual( | |
| "Message missing required fields: " + | |
| "optional_message.a, " + | |
| "optional_message.b, " + | |
| "optional_message.c, " + | |
| "repeated_message[0].a, " + | |
| "repeated_message[0].b, " + | |
| "repeated_message[0].c, " + | |
| "repeated_message[1].a, " + | |
| "repeated_message[1].b, " + | |
| "repeated_message[1].c", | |
| e.Message); | |
| } | |
| [Test] | |
| public void DynamicUninitializedException() | |
| { | |
| var e = Assert.Throws<UninitializedMessageException>(() => DynamicMessage.CreateBuilder(TestRequired.Descriptor).Build()); | |
| Assert.AreEqual("Message missing required fields: a, b, c", e.Message); | |
| } | |
| [Test] | |
| public void DynamicBuildPartial() | |
| { | |
| // We're mostly testing that no exception is thrown. | |
| DynamicMessage message = DynamicMessage.CreateBuilder(TestRequired.Descriptor).BuildPartial(); | |
| Assert.IsFalse(message.Initialized); | |
| } | |
| [Test] | |
| public void DynamicParseUnititialized() | |
| { | |
| MessageDescriptor descriptor = TestRequired.Descriptor; | |
| var e = Assert.Throws<InvalidProtocolBufferException>(() => DynamicMessage.ParseFrom(descriptor, ByteString.Empty)); | |
| Assert.AreEqual("Message missing required fields: a, b, c", e.Message); | |
| } | |
| [Test] | |
| public void PackedTypesWrittenDirectlyToStream() | |
| { | |
| TestPackedTypes message = new TestPackedTypes.Builder {PackedInt32List = {0, 1, 2}}.Build(); | |
| MemoryStream stream = new MemoryStream(); | |
| message.WriteTo(stream); | |
| stream.Position = 0; | |
| TestPackedTypes readMessage = TestPackedTypes.ParseFrom(stream); | |
| Assert.AreEqual(message, readMessage); | |
| } | |
| } | |
| } |