1 #region Copyright notice and license 2 // Protocol Buffers - Google's data interchange format 3 // Copyright 2015 Google Inc. All rights reserved. 4 // 5 // Use of this source code is governed by a BSD-style 6 // license that can be found in the LICENSE file or at 7 // https://developers.google.com/open-source/licenses/bsd 8 #endregion 9 10 using System; 11 using System.Collections; 12 using Google.Protobuf.TestProtos.Proto2; 13 using NUnit.Framework; 14 15 using static Google.Protobuf.TestProtos.Proto2.UnittestExtensions; 16 17 namespace Google.Protobuf 18 { 19 public class ExtensionSetTest 20 { 21 [Test] EmptyExtensionSet()22 public void EmptyExtensionSet() 23 { 24 ExtensionSet<TestAllExtensions> extensions = new ExtensionSet<TestAllExtensions>(); 25 Assert.AreEqual(0, extensions.CalculateSize()); 26 } 27 28 [Test] MergeExtensionSet()29 public void MergeExtensionSet() 30 { 31 ExtensionSet<TestAllExtensions> extensions = null; 32 ExtensionSet.Set(ref extensions, OptionalBoolExtension, true); 33 34 ExtensionSet<TestAllExtensions> other = null; 35 36 Assert.IsFalse(ExtensionSet.Has(ref other, OptionalBoolExtension)); 37 ExtensionSet.MergeFrom(ref other, extensions); 38 Assert.IsTrue(ExtensionSet.Has(ref other, OptionalBoolExtension)); 39 } 40 41 [Test] TestMergeCodedInput()42 public void TestMergeCodedInput() 43 { 44 var message = new TestAllExtensions(); 45 message.SetExtension(OptionalBoolExtension, true); 46 var serialized = message.ToByteArray(); 47 48 MessageParsingHelpers.AssertWritingMessage(message); 49 50 MessageParsingHelpers.AssertReadingMessage( 51 TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { OptionalBoolExtension }), 52 serialized, 53 other => 54 { 55 Assert.AreEqual(message, other); 56 Assert.AreEqual(message.CalculateSize(), other.CalculateSize()); 57 }); 58 } 59 60 [Test] TestMergeMessage()61 public void TestMergeMessage() 62 { 63 var message = new TestAllExtensions(); 64 message.SetExtension(OptionalBoolExtension, true); 65 66 var other = new TestAllExtensions(); 67 68 Assert.AreNotEqual(message, other); 69 Assert.AreNotEqual(message.CalculateSize(), other.CalculateSize()); 70 71 other.MergeFrom(message); 72 73 Assert.AreEqual(message, other); 74 Assert.AreEqual(message.CalculateSize(), other.CalculateSize()); 75 } 76 77 [Test] TryMergeFieldFrom_CodedInputStream()78 public void TryMergeFieldFrom_CodedInputStream() 79 { 80 var message = new TestAllExtensions(); 81 message.SetExtension(OptionalStringExtension, "abcd"); 82 83 var input = new CodedInputStream(message.ToByteArray()); 84 input.ExtensionRegistry = new ExtensionRegistry { OptionalStringExtension }; 85 input.ReadTag(); // TryMergeFieldFrom expects that a tag was just read and will inspect the LastTag value 86 87 ExtensionSet<TestAllExtensions> extensionSet = null; 88 // test the legacy overload of TryMergeFieldFrom that takes a CodedInputStream 89 Assert.IsTrue(ExtensionSet.TryMergeFieldFrom(ref extensionSet, input)); 90 Assert.AreEqual("abcd", ExtensionSet.Get(ref extensionSet, OptionalStringExtension)); 91 } 92 93 [Test] GetSingle()94 public void GetSingle() 95 { 96 var extensionValue = new TestAllTypes.Types.NestedMessage() { Bb = 42 }; 97 var untypedExtension = new Extension<TestAllExtensions, object>(OptionalNestedMessageExtension.FieldNumber, codec: null); 98 var wrongTypedExtension = new Extension<TestAllExtensions, TestAllTypes>(OptionalNestedMessageExtension.FieldNumber, codec: null); 99 100 var message = new TestAllExtensions(); 101 102 var value1 = message.GetExtension(untypedExtension); 103 Assert.IsNull(value1); 104 105 message.SetExtension(OptionalNestedMessageExtension, extensionValue); 106 var value2 = message.GetExtension(untypedExtension); 107 Assert.IsNotNull(value2); 108 109 var valueBytes = ((IMessage)value2).ToByteArray(); 110 var parsedValue = TestProtos.Proto2.TestAllTypes.Types.NestedMessage.Parser.ParseFrom(valueBytes); 111 Assert.AreEqual(extensionValue, parsedValue); 112 113 var ex = Assert.Throws<InvalidOperationException>(() => message.GetExtension(wrongTypedExtension)); 114 115 var fullAssemblyName = typeof(TestAllTypes).Assembly.FullName; 116 var expectedMessage = $"The stored extension value has a type of 'Google.Protobuf.TestProtos.Proto2.TestAllTypes+Types+NestedMessage, {fullAssemblyName}'. " + 117 $"This a different from the requested type of 'Google.Protobuf.TestProtos.Proto2.TestAllTypes, {fullAssemblyName}'."; 118 Assert.AreEqual(expectedMessage, ex.Message); 119 } 120 121 [Test] GetRepeated()122 public void GetRepeated() 123 { 124 var extensionValue = new TestAllTypes.Types.NestedMessage() { Bb = 42 }; 125 var untypedExtension = new Extension<TestAllExtensions, IList>(RepeatedNestedMessageExtension.FieldNumber, codec: null); 126 var wrongTypedExtension = new RepeatedExtension<TestAllExtensions, TestAllTypes>(RepeatedNestedMessageExtension.FieldNumber, codec: null); 127 128 var message = new TestAllExtensions(); 129 130 var value1 = message.GetExtension(untypedExtension); 131 Assert.IsNull(value1); 132 133 var repeatedField = message.GetOrInitializeExtension<TestAllTypes.Types.NestedMessage>(RepeatedNestedMessageExtension); 134 repeatedField.Add(extensionValue); 135 136 var value2 = message.GetExtension(untypedExtension); 137 Assert.IsNotNull(value2); 138 Assert.AreEqual(1, value2.Count); 139 140 var valueBytes = ((IMessage)value2[0]).ToByteArray(); 141 var parsedValue = TestProtos.Proto2.TestAllTypes.Types.NestedMessage.Parser.ParseFrom(valueBytes); 142 Assert.AreEqual(extensionValue, parsedValue); 143 144 var ex = Assert.Throws<InvalidOperationException>(() => message.GetExtension(wrongTypedExtension)); 145 146 var fullAssemblyName = typeof(TestAllTypes).Assembly.FullName; 147 var expectedMessage = $"The stored extension value has a type of 'Google.Protobuf.TestProtos.Proto2.TestAllTypes+Types+NestedMessage, {fullAssemblyName}'. " + 148 $"This a different from the requested type of 'Google.Protobuf.TestProtos.Proto2.TestAllTypes, {fullAssemblyName}'."; 149 Assert.AreEqual(expectedMessage, ex.Message); 150 } 151 152 [Test] TestEquals()153 public void TestEquals() 154 { 155 var message = new TestAllExtensions(); 156 message.SetExtension(OptionalBoolExtension, true); 157 158 var other = new TestAllExtensions(); 159 160 Assert.AreNotEqual(message, other); 161 Assert.AreNotEqual(message.CalculateSize(), other.CalculateSize()); 162 163 other.SetExtension(OptionalBoolExtension, true); 164 165 Assert.AreEqual(message, other); 166 Assert.AreEqual(message.CalculateSize(), other.CalculateSize()); 167 } 168 169 [Test] TestHashCode()170 public void TestHashCode() 171 { 172 var message = new TestAllExtensions(); 173 var hashCode = message.GetHashCode(); 174 175 message.SetExtension(OptionalBoolExtension, true); 176 177 Assert.AreNotEqual(hashCode, message.GetHashCode()); 178 } 179 180 [Test] TestClone()181 public void TestClone() 182 { 183 var message = new TestAllExtensions(); 184 message.SetExtension(OptionalBoolExtension, true); 185 186 var other = message.Clone(); 187 188 Assert.AreEqual(message, other); 189 Assert.AreEqual(message.CalculateSize(), other.CalculateSize()); 190 } 191 192 [Test] TestDefaultValueRoundTrip()193 public void TestDefaultValueRoundTrip() 194 { 195 var message = new TestAllExtensions(); 196 message.SetExtension(OptionalBoolExtension, false); 197 Assert.IsFalse(message.GetExtension(OptionalBoolExtension)); 198 Assert.IsTrue(message.HasExtension(OptionalBoolExtension)); 199 200 var bytes = message.ToByteArray(); 201 var registry = new ExtensionRegistry { OptionalBoolExtension }; 202 var parsed = TestAllExtensions.Parser.WithExtensionRegistry(registry).ParseFrom(bytes); 203 Assert.IsFalse(parsed.GetExtension(OptionalBoolExtension)); 204 Assert.IsTrue(parsed.HasExtension(OptionalBoolExtension)); 205 } 206 } 207 } 208