pull/288/head
Jon Skeet 13 years ago
commit 57e5746a39
  1. 7
      protos/extest/unittest_issues.proto
  2. 59
      src/ProtocolBuffers.Test/IssuesTest.cs
  3. 1
      src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
  4. 290
      src/ProtocolBuffers.Test/TestProtos/UnitTestExtrasIssuesProtoFile.cs
  5. 5
      src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs
  6. 18
      src/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs
  7. 2
      src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs
  8. 16
      src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs

@ -129,4 +129,9 @@ message DeprecatedFieldsMessage {
optional DeprecatedEnum EnumValue = 5 [deprecated = true];
repeated DeprecatedEnum EnumArray = 6 [deprecated = true];
}
}
// Issue 45: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=45
message ItemField {
optional int32 item = 1;
}

@ -0,0 +1,59 @@
#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 Google.ProtocolBuffers.Descriptors;
using NUnit.Framework;
using UnitTest.Issues.TestProtos;
namespace Google.ProtocolBuffers
{
/// <summary>
/// Tests for issues which aren't easily compartmentalized into other unit tests.
/// </summary>
[TestFixture]
public class IssuesTest
{
// Issue 45
[Test]
public void FieldCalledItem()
{
ItemField message = new ItemField.Builder { Item = 3 }.Build();
FieldDescriptor field = ItemField.Descriptor.FindFieldByName("item");
Assert.IsNotNull(field);
Assert.AreEqual(3, message[field]);
}
}
}

@ -94,6 +94,7 @@
<Compile Include="ExtendableMessageTest.cs" />
<Compile Include="GeneratedBuilderTest.cs" />
<Compile Include="GeneratedMessageTest.cs" />
<Compile Include="IssuesTest.cs" />
<Compile Include="MessageStreamIteratorTest.cs" />
<Compile Include="MessageStreamWriterTest.cs" />
<Compile Include="MessageTest.cs" />

@ -36,6 +36,8 @@ namespace UnitTest.Issues.TestProtos {
internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.DeprecatedChild, global::UnitTest.Issues.TestProtos.DeprecatedChild.Builder> internal__static_unittest_issues_DeprecatedChild__FieldAccessorTable;
internal static pbd::MessageDescriptor internal__static_unittest_issues_DeprecatedFieldsMessage__Descriptor;
internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage, global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.Builder> internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable;
internal static pbd::MessageDescriptor internal__static_unittest_issues_ItemField__Descriptor;
internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.ItemField, global::UnitTest.Issues.TestProtos.ItemField.Builder> internal__static_unittest_issues_ItemField__FieldAccessorTable;
#endregion
#region Descriptor
public static pbd::FileDescriptor Descriptor {
@ -63,11 +65,11 @@ namespace UnitTest.Issues.TestProtos {
"eRgEIAMoCzIgLnVuaXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkQ2hpbGRCAhgB" +
"EjYKCUVudW1WYWx1ZRgFIAEoDjIfLnVuaXR0ZXN0X2lzc3Vlcy5EZXByZWNh" +
"dGVkRW51bUICGAESNgoJRW51bUFycmF5GAYgAygOMh8udW5pdHRlc3RfaXNz" +
"dWVzLkRlcHJlY2F0ZWRFbnVtQgIYASpHCgxOZWdhdGl2ZUVudW0SFgoJRml2" +
"ZUJlbG93EPv//////////wESFQoITWludXNPbmUQ////////////ARIICgRa" +
"ZXJvEAAqGQoORGVwcmVjYXRlZEVudW0SBwoDb25lEAFCQEgBwj47ChpVbml0" +
"VGVzdC5Jc3N1ZXMuVGVzdFByb3RvcxIdVW5pdFRlc3RFeHRyYXNJc3N1ZXNQ" +
"cm90b0ZpbGU=");
"dWVzLkRlcHJlY2F0ZWRFbnVtQgIYASIZCglJdGVtRmllbGQSDAoEaXRlbRgB" +
"IAEoBSpHCgxOZWdhdGl2ZUVudW0SFgoJRml2ZUJlbG93EPv//////////wES" +
"FQoITWludXNPbmUQ////////////ARIICgRaZXJvEAAqGQoORGVwcmVjYXRl" +
"ZEVudW0SBwoDb25lEAFCQEgBwj47ChpVbml0VGVzdC5Jc3N1ZXMuVGVzdFBy" +
"b3RvcxIdVW5pdFRlc3RFeHRyYXNJc3N1ZXNQcm90b0ZpbGU=");
pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
descriptor = root;
internal__static_unittest_issues_A__Descriptor = Descriptor.MessageTypes[0];
@ -106,6 +108,10 @@ namespace UnitTest.Issues.TestProtos {
internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable =
new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage, global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.Builder>(internal__static_unittest_issues_DeprecatedFieldsMessage__Descriptor,
new string[] { "PrimitiveValue", "PrimitiveArray", "MessageValue", "MessageArray", "EnumValue", "EnumArray", });
internal__static_unittest_issues_ItemField__Descriptor = Descriptor.MessageTypes[9];
internal__static_unittest_issues_ItemField__FieldAccessorTable =
new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.ItemField, global::UnitTest.Issues.TestProtos.ItemField.Builder>(internal__static_unittest_issues_ItemField__Descriptor,
new string[] { "Item", });
pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();
RegisterAllExtensions(registry);
global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.RegisterAllExtensions(registry);
@ -3151,6 +3157,280 @@ namespace UnitTest.Issues.TestProtos {
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.4.1.473")]
public sealed partial class ItemField : pb::GeneratedMessage<ItemField, ItemField.Builder> {
private ItemField() { }
private static readonly ItemField defaultInstance = new ItemField().MakeReadOnly();
private static readonly string[] _itemFieldFieldNames = new string[] { "item" };
private static readonly uint[] _itemFieldFieldTags = new uint[] { 8 };
public static ItemField DefaultInstance {
get { return defaultInstance; }
}
public override ItemField DefaultInstanceForType {
get { return DefaultInstance; }
}
protected override ItemField ThisMessage {
get { return this; }
}
public static pbd::MessageDescriptor Descriptor {
get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_ItemField__Descriptor; }
}
protected override pb::FieldAccess.FieldAccessorTable<ItemField, ItemField.Builder> InternalFieldAccessors {
get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_ItemField__FieldAccessorTable; }
}
public const int ItemFieldNumber = 1;
private bool hasItem;
private int item_;
public bool HasItem {
get { return hasItem; }
}
public int Item {
get { return item_; }
}
public override bool IsInitialized {
get {
return true;
}
}
public override void WriteTo(pb::ICodedOutputStream output) {
int size = SerializedSize;
string[] field_names = _itemFieldFieldNames;
if (hasItem) {
output.WriteInt32(1, field_names[0], Item);
}
UnknownFields.WriteTo(output);
}
private int memoizedSerializedSize = -1;
public override int SerializedSize {
get {
int size = memoizedSerializedSize;
if (size != -1) return size;
size = 0;
if (hasItem) {
size += pb::CodedOutputStream.ComputeInt32Size(1, Item);
}
size += UnknownFields.SerializedSize;
memoizedSerializedSize = size;
return size;
}
}
public static ItemField ParseFrom(pb::ByteString data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
public static ItemField ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
}
public static ItemField ParseFrom(byte[] data) {
return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
}
public static ItemField ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
}
public static ItemField ParseFrom(global::System.IO.Stream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
public static ItemField ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static ItemField ParseDelimitedFrom(global::System.IO.Stream input) {
return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
}
public static ItemField ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
}
public static ItemField ParseFrom(pb::ICodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
public static ItemField ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
private ItemField MakeReadOnly() {
return this;
}
public static Builder CreateBuilder() { return new Builder(); }
public override Builder ToBuilder() { return CreateBuilder(this); }
public override Builder CreateBuilderForType() { return new Builder(); }
public static Builder CreateBuilder(ItemField prototype) {
return new Builder(prototype);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.4.1.473")]
public sealed partial class Builder : pb::GeneratedBuilder<ItemField, Builder> {
protected override Builder ThisBuilder {
get { return this; }
}
public Builder() {
result = DefaultInstance;
resultIsReadOnly = true;
}
internal Builder(ItemField cloneFrom) {
result = cloneFrom;
resultIsReadOnly = true;
}
private bool resultIsReadOnly;
private ItemField result;
private ItemField PrepareBuilder() {
if (resultIsReadOnly) {
ItemField original = result;
result = new ItemField();
resultIsReadOnly = false;
MergeFrom(original);
}
return result;
}
public override bool IsInitialized {
get { return result.IsInitialized; }
}
protected override ItemField MessageBeingBuilt {
get { return PrepareBuilder(); }
}
public override Builder Clear() {
result = DefaultInstance;
resultIsReadOnly = true;
return this;
}
public override Builder Clone() {
if (resultIsReadOnly) {
return new Builder(result);
} else {
return new Builder().MergeFrom(result);
}
}
public override pbd::MessageDescriptor DescriptorForType {
get { return global::UnitTest.Issues.TestProtos.ItemField.Descriptor; }
}
public override ItemField DefaultInstanceForType {
get { return global::UnitTest.Issues.TestProtos.ItemField.DefaultInstance; }
}
public override ItemField BuildPartial() {
if (resultIsReadOnly) {
return result;
}
resultIsReadOnly = true;
return result.MakeReadOnly();
}
public override Builder MergeFrom(pb::IMessage other) {
if (other is ItemField) {
return MergeFrom((ItemField) other);
} else {
base.MergeFrom(other);
return this;
}
}
public override Builder MergeFrom(ItemField other) {
if (other == global::UnitTest.Issues.TestProtos.ItemField.DefaultInstance) return this;
PrepareBuilder();
if (other.HasItem) {
Item = other.Item;
}
this.MergeUnknownFields(other.UnknownFields);
return this;
}
public override Builder MergeFrom(pb::ICodedInputStream input) {
return MergeFrom(input, pb::ExtensionRegistry.Empty);
}
public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
PrepareBuilder();
pb::UnknownFieldSet.Builder unknownFields = null;
uint tag;
string field_name;
while (input.ReadTag(out tag, out field_name)) {
if(tag == 0 && field_name != null) {
int field_ordinal = global::System.Array.BinarySearch(_itemFieldFieldNames, field_name, global::System.StringComparer.Ordinal);
if(field_ordinal >= 0)
tag = _itemFieldFieldTags[field_ordinal];
else {
if (unknownFields == null) {
unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
}
ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
continue;
}
}
switch (tag) {
case 0: {
throw pb::InvalidProtocolBufferException.InvalidTag();
}
default: {
if (pb::WireFormat.IsEndGroupTag(tag)) {
if (unknownFields != null) {
this.UnknownFields = unknownFields.Build();
}
return this;
}
if (unknownFields == null) {
unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
}
ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
break;
}
case 8: {
result.hasItem = input.ReadInt32(ref result.item_);
break;
}
}
}
if (unknownFields != null) {
this.UnknownFields = unknownFields.Build();
}
return this;
}
public bool HasItem {
get { return result.hasItem; }
}
public int Item {
get { return result.Item; }
set { SetItem(value); }
}
public Builder SetItem(int value) {
PrepareBuilder();
result.hasItem = true;
result.item_ = value;
return this;
}
public Builder ClearItem() {
PrepareBuilder();
result.hasItem = false;
result.item_ = 0;
return this;
}
}
static ItemField() {
object.ReferenceEquals(global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.Descriptor, null);
}
}
#endregion
}

@ -44,6 +44,11 @@ namespace Google.ProtocolBuffers.FieldAccess
/// </summary>
internal static class ReflectionUtil
{
/// <summary>
/// Empty Type[] used when calling GetProperty to force property instead of indexer fetching.
/// </summary>
internal static readonly Type[] EmptyTypes = new Type[0];
/// <summary>
/// Creates a delegate which will execute the given method and then return
/// the result as an object.

@ -66,14 +66,14 @@ namespace Google.ProtocolBuffers.FieldAccess
internal RepeatedPrimitiveAccessor(string name)
{
PropertyInfo messageProperty = typeof (TMessage).GetProperty(name + "List");
PropertyInfo builderProperty = typeof (TBuilder).GetProperty(name + "List");
PropertyInfo countProperty = typeof (TMessage).GetProperty(name + "Count");
MethodInfo clearMethod = typeof (TBuilder).GetMethod("Clear" + name, EmptyTypes);
getElementMethod = typeof (TMessage).GetMethod("Get" + name, new Type[] {typeof (int)});
PropertyInfo messageProperty = typeof(TMessage).GetProperty(name + "List", ReflectionUtil.EmptyTypes);
PropertyInfo builderProperty = typeof(TBuilder).GetProperty(name + "List", ReflectionUtil.EmptyTypes);
PropertyInfo countProperty = typeof(TMessage).GetProperty(name + "Count", ReflectionUtil.EmptyTypes);
MethodInfo clearMethod = typeof(TBuilder).GetMethod("Clear" + name, EmptyTypes);
getElementMethod = typeof(TMessage).GetMethod("Get" + name, new Type[] {typeof(int)});
clrType = getElementMethod.ReturnType;
MethodInfo addMethod = typeof (TBuilder).GetMethod("Add" + name, new Type[] {ClrType});
setElementMethod = typeof (TBuilder).GetMethod("Set" + name, new Type[] {typeof (int), ClrType});
MethodInfo addMethod = typeof(TBuilder).GetMethod("Add" + name, new Type[] {ClrType});
setElementMethod = typeof(TBuilder).GetMethod("Set" + name, new Type[] {typeof(int), ClrType});
if (messageProperty == null
|| builderProperty == null
|| countProperty == null
@ -85,9 +85,9 @@ namespace Google.ProtocolBuffers.FieldAccess
throw new ArgumentException("Not all required properties/methods available");
}
clearDelegate =
(Func<TBuilder, IBuilder>) Delegate.CreateDelegate(typeof (Func<TBuilder, IBuilder>), null, clearMethod);
(Func<TBuilder, IBuilder>) Delegate.CreateDelegate(typeof(Func<TBuilder, IBuilder>), null, clearMethod);
countDelegate = (Func<TMessage, int>) Delegate.CreateDelegate
(typeof (Func<TMessage, int>), null, countProperty.GetGetMethod());
(typeof(Func<TMessage, int>), null, countProperty.GetGetMethod());
getValueDelegate = ReflectionUtil.CreateUpcastDelegate<TMessage>(messageProperty.GetGetMethod());
addValueDelegate = ReflectionUtil.CreateDowncastDelegateIgnoringReturn<TBuilder>(addMethod);
getRepeatedWrapperDelegate = ReflectionUtil.CreateUpcastDelegate<TBuilder>(builderProperty.GetGetMethod());

@ -50,7 +50,7 @@ namespace Google.ProtocolBuffers.FieldAccess
internal SingleMessageAccessor(string name) : base(name)
{
MethodInfo createBuilderMethod = ClrType.GetMethod("CreateBuilder", EmptyTypes);
MethodInfo createBuilderMethod = ClrType.GetMethod("CreateBuilder", ReflectionUtil.EmptyTypes);
if (createBuilderMethod == null)
{
throw new ArgumentException("No public static CreateBuilder method declared in " + ClrType.Name);

@ -47,8 +47,6 @@ namespace Google.ProtocolBuffers.FieldAccess
private readonly Func<TMessage, bool> hasDelegate;
private readonly Func<TBuilder, IBuilder> clearDelegate;
internal static readonly Type[] EmptyTypes = new Type[0];
/// <summary>
/// The CLR type of the field (int, the enum type, ByteString, the message etc).
/// As declared by the property.
@ -60,14 +58,14 @@ namespace Google.ProtocolBuffers.FieldAccess
internal SinglePrimitiveAccessor(string name)
{
PropertyInfo messageProperty = typeof (TMessage).GetProperty(name);
PropertyInfo builderProperty = typeof (TBuilder).GetProperty(name);
PropertyInfo messageProperty = typeof(TMessage).GetProperty(name, ReflectionUtil.EmptyTypes);
PropertyInfo builderProperty = typeof(TBuilder).GetProperty(name, ReflectionUtil.EmptyTypes);
if (builderProperty == null)
{
builderProperty = typeof (TBuilder).GetProperty(name);
builderProperty = typeof(TBuilder).GetProperty(name, ReflectionUtil.EmptyTypes);
}
PropertyInfo hasProperty = typeof (TMessage).GetProperty("Has" + name);
MethodInfo clearMethod = typeof (TBuilder).GetMethod("Clear" + name, EmptyTypes);
PropertyInfo hasProperty = typeof(TMessage).GetProperty("Has" + name, ReflectionUtil.EmptyTypes);
MethodInfo clearMethod = typeof(TBuilder).GetMethod("Clear" + name, ReflectionUtil.EmptyTypes);
if (messageProperty == null || builderProperty == null || hasProperty == null || clearMethod == null)
{
throw new ArgumentException("Not all required properties/methods available");
@ -75,9 +73,9 @@ namespace Google.ProtocolBuffers.FieldAccess
clrType = messageProperty.PropertyType;
hasDelegate =
(Func<TMessage, bool>)
Delegate.CreateDelegate(typeof (Func<TMessage, bool>), null, hasProperty.GetGetMethod());
Delegate.CreateDelegate(typeof(Func<TMessage, bool>), null, hasProperty.GetGetMethod());
clearDelegate =
(Func<TBuilder, IBuilder>) Delegate.CreateDelegate(typeof (Func<TBuilder, IBuilder>), null, clearMethod);
(Func<TBuilder, IBuilder>) Delegate.CreateDelegate(typeof(Func<TBuilder, IBuilder>), null, clearMethod);
getValueDelegate = ReflectionUtil.CreateUpcastDelegate<TMessage>(messageProperty.GetGetMethod());
setValueDelegate = ReflectionUtil.CreateDowncastDelegate<TBuilder>(builderProperty.GetSetMethod());
}

Loading…
Cancel
Save