#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 { /// /// Miscellaneous tests for message operations that apply to both /// generated and dynamic messages. /// 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()); } /// /// 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. /// [Test] public void MergeFromDynamic() { TestAllTypes result = (TestAllTypes) TestAllTypes.CreateBuilder(MergeDest) .MergeFrom(DynamicMessage.CreateBuilder(MergeSource).Build()) .Build(); Assert.AreEqual(MergeResultText, result.ToString()); } /// /// Test merging two DynamicMessages. /// [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("a")] = 1; Assert.IsFalse(builder.IsInitialized); builder[descriptor.FindDescriptor("b")] = 1; Assert.IsFalse(builder.IsInitialized); builder[descriptor.FindDescriptor("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("optional_message")] = TestRequiredUninitialized; Assert.IsFalse(builder.IsInitialized); builder[descriptor.FindDescriptor("optional_message")] = TestRequiredInitialized; Assert.IsTrue(builder.IsInitialized); builder.AddRepeatedField(descriptor.FindDescriptor("repeated_message"), TestRequiredUninitialized); Assert.IsFalse(builder.IsInitialized); builder.SetRepeatedField(descriptor.FindDescriptor("repeated_message"), 0, TestRequiredInitialized); Assert.IsTrue(builder.IsInitialized); } [Test] public void UninitializedException() { var e = Assert.Throws(() => 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(() => 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(() => 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(() => 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(() => 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(() => 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); } } }