#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 Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Google.ProtocolBuffers
{
/// <summary>
/// Miscellaneous tests for message operations that apply to both
/// generated and dynamic messages.
/// </summary>
[TestClass]
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";
[TestMethod]
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>
[TestMethod]
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>
[TestMethod]
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();
[TestMethod]
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);
}
[TestMethod]
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);
}
[TestMethod]
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);
}
[TestMethod]
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);
}
[TestMethod]
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);
}
[TestMethod]
public void UninitializedException()
{
try
{
TestRequired.CreateBuilder().Build();
Assert.Fail("Should have thrown an exception.");
}
catch (UninitializedMessageException e)
{
Assert.AreEqual("Message missing required fields: a, b, c", e.Message);
}
}
[TestMethod]
public void BuildPartial()
{
// We're mostly testing that no exception is thrown.
TestRequired message = TestRequired.CreateBuilder().BuildPartial();
Assert.IsFalse(message.IsInitialized);
}
[TestMethod]
public void NestedUninitializedException()
{
try
{
TestRequiredForeign.CreateBuilder()
.SetOptionalMessage(TestRequiredUninitialized)
.AddRepeatedMessage(TestRequiredUninitialized)
.AddRepeatedMessage(TestRequiredUninitialized)
.Build();
Assert.Fail("Should have thrown an exception.");
}
catch (UninitializedMessageException e)
{
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);
}
}
[TestMethod]
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);
}
[TestMethod]
public void ParseUnititialized()
{
try
{
TestRequired.ParseFrom(ByteString.Empty);
Assert.Fail("Should have thrown an exception.");
}
catch (InvalidProtocolBufferException e)
{
Assert.AreEqual("Message missing required fields: a, b, c", e.Message);
}
}
[TestMethod]
public void ParseNestedUnititialized()
{
ByteString data =
TestRequiredForeign.CreateBuilder()
.SetOptionalMessage(TestRequiredUninitialized)
.AddRepeatedMessage(TestRequiredUninitialized)
.AddRepeatedMessage(TestRequiredUninitialized)
.BuildPartial().ToByteString();
try
{
TestRequiredForeign.ParseFrom(data);
Assert.Fail("Should have thrown an exception.");
}
catch (InvalidProtocolBufferException e)
{
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);
}
}
[TestMethod]
public void DynamicUninitializedException()
{
try
{
DynamicMessage.CreateBuilder(TestRequired.Descriptor).Build();
Assert.Fail("Should have thrown an exception.");
}
catch (UninitializedMessageException e)
{
Assert.AreEqual("Message missing required fields: a, b, c", e.Message);
}
}
[TestMethod]
public void DynamicBuildPartial()
{
// We're mostly testing that no exception is thrown.
DynamicMessage message = DynamicMessage.CreateBuilder(TestRequired.Descriptor).BuildPartial();
Assert.IsFalse(message.Initialized);
}
[TestMethod]
public void DynamicParseUnititialized()
{
try
{
MessageDescriptor descriptor = TestRequired.Descriptor;
DynamicMessage.ParseFrom(descriptor, ByteString.Empty);
Assert.Fail("Should have thrown an exception.");
}
catch (InvalidProtocolBufferException e)
{
Assert.AreEqual("Message missing required fields: a, b, c", e.Message);
}
}
[TestMethod]
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);
}
}
}