diff --git a/Makefile.am b/Makefile.am index 62e8a782dd..4550ce8e95 100644 --- a/Makefile.am +++ b/Makefile.am @@ -66,6 +66,8 @@ csharp_EXTRA_DIST= \ csharp/keys/README.md \ csharp/protos/README.md \ csharp/protos/map_unittest_proto3.proto \ + csharp/protos/old_extensions1.proto \ + csharp/protos/old_extensions2.proto \ csharp/protos/unittest_custom_options_proto3.proto \ csharp/protos/unittest_import_public_proto3.proto \ csharp/protos/unittest_import_public.proto \ diff --git a/csharp/generate_protos.sh b/csharp/generate_protos.sh index 06daa4e81c..3829d05e64 100755 --- a/csharp/generate_protos.sh +++ b/csharp/generate_protos.sh @@ -41,6 +41,9 @@ $PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf \ src/google/protobuf/wrappers.proto # Test protos +# Note that this deliberately does *not* include old_extensions1.proto +# and old_extensions2.proto, which are generated with an older version +# of protoc. $PROTOC -Isrc -Icsharp/protos \ --csharp_out=csharp/src/Google.Protobuf.Test/TestProtos \ --descriptor_set_out=csharp/src/Google.Protobuf.Test/testprotos.pb \ diff --git a/csharp/protos/old_extensions1.proto b/csharp/protos/old_extensions1.proto new file mode 100644 index 0000000000..58f6eb580c --- /dev/null +++ b/csharp/protos/old_extensions1.proto @@ -0,0 +1,52 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file we will use for unit testing. +// +// LINT: ALLOW_GROUPS, LEGACY_NAMES + +// This file is part of the unit test for issue #6822. It is +// generated with protoc from version 3.10.1. + +syntax = "proto3"; + +// Import the proto file containing the extension. We don't use it, +// but the import is what caused the issue. +import "old_extensions2.proto"; + +option csharp_namespace = "Google.Protobuf.TestProtos.OldGenerator"; + +// We don't use this message other than to get its descriptor. +message TestMessage { +} diff --git a/csharp/protos/old_extensions2.proto b/csharp/protos/old_extensions2.proto new file mode 100644 index 0000000000..78f732a8ad --- /dev/null +++ b/csharp/protos/old_extensions2.proto @@ -0,0 +1,50 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file we will use for unit testing. +// +// LINT: ALLOW_GROUPS, LEGACY_NAMES + +// This file is part of the unit test for issue #6822. It is +// generated with protoc from version 3.10.1. + +syntax = "proto3"; + +import "google/protobuf/descriptor.proto"; + +option csharp_namespace = "Google.Protobuf.TestProtos.OldGenerator"; + +extend google.protobuf.MethodOptions { + string method_ext = 1234567; +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs index 264cbbe037..482db535e2 100644 --- a/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs +++ b/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs @@ -365,5 +365,23 @@ namespace Google.Protobuf.Reflection var descriptor = Google.Protobuf.Reflection.FileDescriptor.DescriptorProtoFileDescriptor; Assert.AreEqual("google/protobuf/descriptor.proto", descriptor.Name); } + + [Test] + public void DescriptorImportingExtensionsFromOldCodeGen() + { + // The extension collection includes a null extension. There's not a lot we can do about that + // in itself, as the old generator didn't provide us the extension information. + var extensions = TestProtos.OldGenerator.OldExtensions2Reflection.Descriptor.Extensions; + Assert.AreEqual(1, extensions.UnorderedExtensions.Count); + // Note: this assertion is present so that it will fail if OldExtensions2 is regenerated + // with a new generator. + Assert.Null(extensions.UnorderedExtensions[0].Extension); + + // ... but we can make sure we at least don't cause a failure when retrieving descriptors. + // In particular, old_extensions1.proto imports old_extensions2.proto, and this used to cause + // an execution-time failure. + var importingDescriptor = TestProtos.OldGenerator.OldExtensions1Reflection.Descriptor; + Assert.NotNull(importingDescriptor); + } } } diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/OldExtensions1.cs b/csharp/src/Google.Protobuf.Test/TestProtos/OldExtensions1.cs new file mode 100644 index 0000000000..3824f4c6ea --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/TestProtos/OldExtensions1.cs @@ -0,0 +1,148 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: old_extensions1.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Google.Protobuf.TestProtos.OldGenerator { + + /// Holder for reflection information generated from old_extensions1.proto + public static partial class OldExtensions1Reflection { + + #region Descriptor + /// File descriptor for old_extensions1.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static OldExtensions1Reflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "ChVvbGRfZXh0ZW5zaW9uczEucHJvdG8aFW9sZF9leHRlbnNpb25zMi5wcm90", + "byINCgtUZXN0TWVzc2FnZUIqqgInR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90", + "b3MuT2xkR2VuZXJhdG9yYgZwcm90bzM=")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.OldGenerator.OldExtensions2Reflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.OldGenerator.TestMessage), global::Google.Protobuf.TestProtos.OldGenerator.TestMessage.Parser, null, null, null, null) + })); + } + #endregion + + } + #region Messages + /// + /// We don't use this message other than to get its descriptor. + /// + public sealed partial class TestMessage : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Protobuf.TestProtos.OldGenerator.OldExtensions1Reflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMessage(TestMessage other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMessage Clone() { + return new TestMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestMessage other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + } + } + } + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/OldExtensions2.cs b/csharp/src/Google.Protobuf.Test/TestProtos/OldExtensions2.cs new file mode 100644 index 0000000000..265dd3ba58 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/TestProtos/OldExtensions2.cs @@ -0,0 +1,40 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: old_extensions2.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Google.Protobuf.TestProtos.OldGenerator { + + /// Holder for reflection information generated from old_extensions2.proto + public static partial class OldExtensions2Reflection { + + #region Descriptor + /// File descriptor for old_extensions2.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static OldExtensions2Reflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "ChVvbGRfZXh0ZW5zaW9uczIucHJvdG8aIGdvb2dsZS9wcm90b2J1Zi9kZXNj", + "cmlwdG9yLnByb3RvOjQKCm1ldGhvZF9leHQSHi5nb29nbGUucHJvdG9idWYu", + "TWV0aG9kT3B0aW9ucxiHrUsgASgJQiqqAidHb29nbGUuUHJvdG9idWYuVGVz", + "dFByb3Rvcy5PbGRHZW5lcmF0b3JiBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { pbr::FileDescriptor.DescriptorProtoFileDescriptor, }, + new pbr::GeneratedClrTypeInfo(null, null)); + } + #endregion + + } +} + +#endregion Designer generated code