1 #region Copyright notice and license 2 // Protocol Buffers - Google's data interchange format 3 // Copyright 2017 Google Inc. All rights reserved. 4 // https://developers.google.com/protocol-buffers/ 5 // 6 // Redistribution and use in source and binary forms, with or without 7 // modification, are permitted provided that the following conditions are 8 // met: 9 // 10 // * Redistributions of source code must retain the above copyright 11 // notice, this list of conditions and the following disclaimer. 12 // * Redistributions in binary form must reproduce the above 13 // copyright notice, this list of conditions and the following disclaimer 14 // in the documentation and/or other materials provided with the 15 // distribution. 16 // * Neither the name of Google Inc. nor the names of its 17 // contributors may be used to endorse or promote products derived from 18 // this software without specific prior written permission. 19 // 20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 #endregion 32 33 using Google.Protobuf.Reflection; 34 using Google.Protobuf.WellKnownTypes; 35 using NUnit.Framework; 36 using System.IO; 37 using System.Linq; 38 using UnitTest.Issues.TestProtos; 39 using static Google.Protobuf.WireFormat; 40 using static UnitTest.Issues.TestProtos.ComplexOptionType2.Types; 41 using static UnitTest.Issues.TestProtos.DummyMessageContainingEnum.Types; 42 using static Google.Protobuf.Test.Reflection.CustomOptionNumber; 43 44 namespace Google.Protobuf.Test.Reflection 45 { 46 // Internal enum to allow us to use "using static" for convenience. 47 // These are the options defined in unittest_custom_options_proto3.proto 48 internal enum CustomOptionNumber 49 { 50 FileOpt1 = 7736974, 51 MessageOpt1 = 7739036, 52 FieldOpt1 = 7740936, 53 OneofOpt1 = 7740111, 54 EnumOpt1 = 7753576, 55 EnumValueOpt1 = 1560678, 56 ServiceOpt1 = 7887650, 57 MethodOpt1 = 7890860, 58 59 // All message options... 60 BoolOpt = 7706090, 61 Int32Opt = 7705709, 62 Int64Opt = 7705542, 63 UInt32Opt = 7704880, 64 UInt64Opt = 7702367, 65 SInt32Opt = 7701568, 66 SInt64Opt = 7700863, 67 Fixed32Opt = 7700307, 68 Fixed64Opt = 7700194, 69 SFixed32Opt = 7698645, 70 SFixed64Opt = 7685475, 71 FloatOpt = 7675390, 72 DoubleOpt = 7673293, 73 StringOpt = 7673285, 74 BytesOpt = 7673238, 75 EnumOpt = 7673233, 76 MessageTypeOpt = 7665967, 77 78 // Miscellaneous 79 ComplexOpt4 = 7633546, 80 ComplexOpt1 = 7646756, 81 ComplexOpt2 = 7636949, 82 ComplexOpt3 = 7636463, 83 84 // Aggregates 85 AggregateFileOpt = 15478479, 86 AggregateMsgOpt = 15480088, 87 AggregateFieldOpt = 15481374, 88 AggregateEnumOpt = 15483218, 89 AggregateEnumValueOpt = 15486921, 90 AggregateServiceOpt = 15497145, 91 AggregateMethodOpt = 15512713, 92 } 93 94 /// <summary> 95 /// The majority of the testing here is done via parsed descriptors. That's simpler to 96 /// achieve (and more important) than constructing a CodedInputStream manually. 97 /// </summary> 98 public class CustomOptionsTest 99 { OptionFetcher(int field, out T value)100 delegate bool OptionFetcher<T>(int field, out T value); 101 102 [Test] ScalarOptions()103 public void ScalarOptions() 104 { 105 var options = CustomOptionOtherValues.Descriptor.CustomOptions; 106 AssertOption(-100, options.TryGetInt32, Int32Opt); 107 AssertOption(12.3456789f, options.TryGetFloat, FloatOpt); 108 AssertOption(1.234567890123456789d, options.TryGetDouble, DoubleOpt); 109 AssertOption("Hello, \"World\"", options.TryGetString, StringOpt); 110 AssertOption(ByteString.CopyFromUtf8("Hello\0World"), options.TryGetBytes, BytesOpt); 111 AssertOption((int)TestEnumType.TestOptionEnumType2, options.TryGetInt32, EnumOpt); 112 } 113 114 [Test] MessageOptions()115 public void MessageOptions() 116 { 117 var options = VariousComplexOptions.Descriptor.CustomOptions; 118 AssertOption(new ComplexOptionType1 { Foo = 42, Foo4 = { 99, 88 } }, options.TryGetMessage, ComplexOpt1); 119 AssertOption(new ComplexOptionType2 120 { 121 Baz = 987, 122 Bar = new ComplexOptionType1 { Foo = 743 }, 123 Fred = new ComplexOptionType4 { Waldo = 321 }, 124 Barney = { new ComplexOptionType4 { Waldo = 101 }, new ComplexOptionType4 { Waldo = 212 } } 125 }, 126 options.TryGetMessage, ComplexOpt2); 127 AssertOption(new ComplexOptionType3 { Qux = 9 }, options.TryGetMessage, ComplexOpt3); 128 } 129 130 [Test] OptionLocations()131 public void OptionLocations() 132 { 133 var fileOptions = UnittestCustomOptionsProto3Reflection.Descriptor.CustomOptions; 134 AssertOption(9876543210UL, fileOptions.TryGetUInt64, FileOpt1); 135 136 var messageOptions = TestMessageWithCustomOptions.Descriptor.CustomOptions; 137 AssertOption(-56, messageOptions.TryGetInt32, MessageOpt1); 138 139 var fieldOptions = TestMessageWithCustomOptions.Descriptor.Fields["field1"].CustomOptions; 140 AssertOption(8765432109UL, fieldOptions.TryGetFixed64, FieldOpt1); 141 142 var oneofOptions = TestMessageWithCustomOptions.Descriptor.Oneofs[0].CustomOptions; 143 AssertOption(-99, oneofOptions.TryGetInt32, OneofOpt1); 144 145 var enumOptions = TestMessageWithCustomOptions.Descriptor.EnumTypes[0].CustomOptions; 146 AssertOption(-789, enumOptions.TryGetSFixed32, EnumOpt1); 147 148 var enumValueOptions = TestMessageWithCustomOptions.Descriptor.EnumTypes[0].FindValueByNumber(2).CustomOptions; 149 AssertOption(123, enumValueOptions.TryGetInt32, EnumValueOpt1); 150 151 var service = UnittestCustomOptionsProto3Reflection.Descriptor.Services 152 .Single(s => s.Name == "TestServiceWithCustomOptions"); 153 var serviceOptions = service.CustomOptions; 154 AssertOption(-9876543210, serviceOptions.TryGetSInt64, ServiceOpt1); 155 156 var methodOptions = service.Methods[0].CustomOptions; 157 AssertOption((int)UnitTest.Issues.TestProtos.MethodOpt1.Val2, methodOptions.TryGetInt32, CustomOptionNumber.MethodOpt1); 158 } 159 160 [Test] MinValues()161 public void MinValues() 162 { 163 var options = CustomOptionMinIntegerValues.Descriptor.CustomOptions; 164 AssertOption(false, options.TryGetBool, BoolOpt); 165 AssertOption(int.MinValue, options.TryGetInt32, Int32Opt); 166 AssertOption(long.MinValue, options.TryGetInt64, Int64Opt); 167 AssertOption(uint.MinValue, options.TryGetUInt32, UInt32Opt); 168 AssertOption(ulong.MinValue, options.TryGetUInt64, UInt64Opt); 169 AssertOption(int.MinValue, options.TryGetSInt32, SInt32Opt); 170 AssertOption(long.MinValue, options.TryGetSInt64, SInt64Opt); 171 AssertOption(uint.MinValue, options.TryGetUInt32, Fixed32Opt); 172 AssertOption(ulong.MinValue, options.TryGetUInt64, Fixed64Opt); 173 AssertOption(int.MinValue, options.TryGetInt32, SFixed32Opt); 174 AssertOption(long.MinValue, options.TryGetInt64, SFixed64Opt); 175 } 176 177 [Test] MaxValues()178 public void MaxValues() 179 { 180 var options = CustomOptionMaxIntegerValues.Descriptor.CustomOptions; 181 AssertOption(true, options.TryGetBool, BoolOpt); 182 AssertOption(int.MaxValue, options.TryGetInt32, Int32Opt); 183 AssertOption(long.MaxValue, options.TryGetInt64, Int64Opt); 184 AssertOption(uint.MaxValue, options.TryGetUInt32, UInt32Opt); 185 AssertOption(ulong.MaxValue, options.TryGetUInt64, UInt64Opt); 186 AssertOption(int.MaxValue, options.TryGetSInt32, SInt32Opt); 187 AssertOption(long.MaxValue, options.TryGetSInt64, SInt64Opt); 188 AssertOption(uint.MaxValue, options.TryGetFixed32, Fixed32Opt); 189 AssertOption(ulong.MaxValue, options.TryGetFixed64, Fixed64Opt); 190 AssertOption(int.MaxValue, options.TryGetSFixed32, SFixed32Opt); 191 AssertOption(long.MaxValue, options.TryGetSFixed64, SFixed64Opt); 192 } 193 194 [Test] AggregateOptions()195 public void AggregateOptions() 196 { 197 // Just two examples 198 var messageOptions = AggregateMessage.Descriptor.CustomOptions; 199 AssertOption(new Aggregate { I = 101, S = "MessageAnnotation" }, messageOptions.TryGetMessage, AggregateMsgOpt); 200 201 var fieldOptions = AggregateMessage.Descriptor.Fields["fieldname"].CustomOptions; 202 AssertOption(new Aggregate { S = "FieldAnnotation" }, fieldOptions.TryGetMessage, AggregateFieldOpt); 203 } 204 AssertOption(T expected, OptionFetcher<T> fetcher, CustomOptionNumber field)205 private void AssertOption<T>(T expected, OptionFetcher<T> fetcher, CustomOptionNumber field) 206 { 207 T actual; 208 Assert.IsTrue(fetcher((int)field, out actual)); 209 Assert.AreEqual(expected, actual); 210 } 211 } 212 } 213