blob: c36acf726a36b99db8765c0080b596c37ce0ee86 [file] [log] [blame]
#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2018 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#endregion
using Google.Protobuf.Reflection;
using NUnit.Framework;
using System.Linq;
using System.Reflection;
namespace Google.Protobuf.Test.Reflection
{
// In reality this isn't a test for DescriptorDeclaration so much as the way they're loaded.
public class DescriptorDeclarationTest
{
static readonly FileDescriptor unitTestProto3Descriptor = LoadProtos();
// Note: we don't expose a declaration for FileDescriptor as it doesn't have comments
// at the moment and the locations aren't terribly useful.
// The tests for most elements are quite basic: we don't test every aspect of every element.
// The code within the library falls into two categories:
// - Exposing the properties for *any* declaration
// - Finding the right declaration for an element from the descriptor data
// We have a per-element check to make sure we *are* finding the right declaration, and we
// check every property of declarations in at least one test, but we don't have a cross-product.
// That would effectively be testing protoc, which seems redundant here.
[Test]
public void ServiceComments()
{
var service = unitTestProto3Descriptor.FindTypeByName<ServiceDescriptor>("TestService");
Assert.NotNull(service.Declaration);
Assert.AreEqual(" This is a test service\n", service.Declaration.LeadingComments);
}
[Test]
public void MethodComments()
{
var service = unitTestProto3Descriptor.FindTypeByName<ServiceDescriptor>("TestService");
var method = service.FindMethodByName("Foo");
Assert.NotNull(method.Declaration);
Assert.AreEqual(" This is a test method\n", method.Declaration.LeadingComments);
}
[Test]
public void MessageComments()
{
var message = unitTestProto3Descriptor.FindTypeByName<MessageDescriptor>("CommentMessage");
Assert.NotNull(message.Declaration);
Assert.AreEqual(" This is a leading comment\n", message.Declaration.LeadingComments);
Assert.AreEqual(new[] { " This is leading detached comment 1\n", " This is leading detached comment 2\n" },
message.Declaration.LeadingDetachedComments);
}
[Test]
public void MessageLocations()
{
var message = unitTestProto3Descriptor.FindTypeByName<MessageDescriptor>("CommentMessage");
Assert.NotNull(message.Declaration);
Assert.AreEqual(1, message.Declaration.StartColumn);
Assert.AreEqual(2, message.Declaration.EndColumn);
// This is slightly brittle, but allows a reasonable amount of change.
var diff = message.Declaration.EndLine - message.Declaration.StartLine;
Assert.That(diff, Is.GreaterThanOrEqualTo(10));
Assert.That(diff, Is.LessThanOrEqualTo(50));
}
[Test]
public void EnumComments()
{
var descriptor = unitTestProto3Descriptor.FindTypeByName<EnumDescriptor>("CommentEnum");
Assert.NotNull(descriptor.Declaration);
Assert.AreEqual(" Leading enum comment\n", descriptor.Declaration.LeadingComments);
}
[Test]
public void NestedMessageComments()
{
var outer = unitTestProto3Descriptor.FindTypeByName<MessageDescriptor>("CommentMessage");
var nested = outer.FindDescriptor<MessageDescriptor>("NestedCommentMessage");
Assert.NotNull(nested.Declaration);
Assert.AreEqual(" Leading nested message comment\n", nested.Declaration.LeadingComments);
}
[Test]
public void NestedEnumComments()
{
var outer = unitTestProto3Descriptor.FindTypeByName<MessageDescriptor>("CommentMessage");
var nested = outer.FindDescriptor<EnumDescriptor>("NestedCommentEnum");
Assert.NotNull(nested.Declaration);
Assert.AreEqual(" Leading nested enum comment\n", nested.Declaration.LeadingComments);
}
[Test]
public void FieldComments()
{
var message = unitTestProto3Descriptor.FindTypeByName<MessageDescriptor>("CommentMessage");
var field = message.FindFieldByName("text");
Assert.NotNull(field.Declaration);
Assert.AreEqual(" Leading field comment\n", field.Declaration.LeadingComments);
Assert.AreEqual(" Trailing field comment\n", field.Declaration.TrailingComments);
}
[Test]
public void NestedMessageFieldComments()
{
var outer = unitTestProto3Descriptor.FindTypeByName<MessageDescriptor>("CommentMessage");
var nested = outer.FindDescriptor<MessageDescriptor>("NestedCommentMessage");
var field = nested.FindFieldByName("nested_text");
Assert.NotNull(field.Declaration);
Assert.AreEqual(" Leading nested message field comment\n", field.Declaration.LeadingComments);
}
[Test]
public void EnumValueComments()
{
var enumDescriptor = unitTestProto3Descriptor.FindTypeByName<EnumDescriptor>("CommentEnum");
var value = enumDescriptor.FindValueByName("ZERO_VALUE");
Assert.NotNull(value.Declaration);
Assert.AreEqual(" Zero value comment\n", value.Declaration.LeadingComments);
}
[Test]
public void NestedEnumValueComments()
{
var outer = unitTestProto3Descriptor.FindTypeByName<MessageDescriptor>("CommentMessage");
var nested = outer.FindDescriptor<EnumDescriptor>("NestedCommentEnum");
var value = nested.FindValueByName("ZERO_VALUE");
Assert.NotNull(value.Declaration);
Assert.AreEqual(" Zero value comment\n", value.Declaration.LeadingComments);
}
[Test]
public void OneofComments()
{
// CommentMessage doesn't have an enum, but we can use TestAllTypes.
var message = unitTestProto3Descriptor.FindTypeByName<MessageDescriptor>("TestAllTypes");
var oneof = message.Oneofs.Single(o => o.Name == "oneof_field");
Assert.NotNull(oneof.Declaration);
Assert.AreEqual(" For oneof test\n", oneof.Declaration.LeadingComments);
}
private static FileDescriptor LoadProtos()
{
var type = typeof(DescriptorDeclarationTest);
// TODO: Make this simpler :)
FileDescriptorSet descriptorSet;
using (var stream = type.GetTypeInfo().Assembly.GetManifestResourceStream($"Google.Protobuf.Test.testprotos.pb"))
{
descriptorSet = FileDescriptorSet.Parser.ParseFrom(stream);
}
var byteStrings = descriptorSet.File.Select(f => f.ToByteString()).ToList();
var descriptors = FileDescriptor.BuildFromByteStrings(byteStrings);
return descriptors.Single(d => d.Name == "csharp/protos/unittest_proto3.proto");
}
}
}