1 #region Copyright notice and license 2 // Protocol Buffers - Google's data interchange format 3 // Copyright 2008 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 System; 34 using System.IO; 35 using Google.Protobuf.TestProtos; 36 using Proto2 = Google.Protobuf.TestProtos.Proto2; 37 using NUnit.Framework; 38 39 namespace Google.Protobuf 40 { 41 public class UnknownFieldSetTest 42 { 43 public class Data 44 { 45 public static System.Collections.IEnumerable Messages 46 { 47 get 48 { 49 yield return SampleMessages.CreateFullTestAllTypesProto2(); 50 yield return SampleMessages.CreateFullTestAllTypes(); 51 } 52 } 53 } 54 55 [Test] EmptyUnknownFieldSet()56 public void EmptyUnknownFieldSet() 57 { 58 UnknownFieldSet unknownFields = new UnknownFieldSet(); 59 Assert.AreEqual(0, unknownFields.CalculateSize()); 60 } 61 62 [Test] MergeUnknownFieldSet()63 public void MergeUnknownFieldSet() 64 { 65 UnknownFieldSet unknownFields = new UnknownFieldSet(); 66 UnknownField field = new UnknownField(); 67 field.AddFixed32(123); 68 unknownFields.AddOrReplaceField(1, field); 69 UnknownFieldSet otherUnknownFields = new UnknownFieldSet(); 70 Assert.IsFalse(otherUnknownFields.HasField(1)); 71 UnknownFieldSet.MergeFrom(otherUnknownFields, unknownFields); 72 Assert.IsTrue(otherUnknownFields.HasField(1)); 73 } 74 75 [Test] 76 [TestCaseSource(typeof(Data), "Messages")] TestMergeCodedInput(IMessage message)77 public void TestMergeCodedInput(IMessage message) 78 { 79 var emptyMessage = new TestEmptyMessage(); 80 emptyMessage.MergeFrom(message.ToByteArray()); 81 Assert.AreEqual(message.CalculateSize(), emptyMessage.CalculateSize()); 82 Assert.AreEqual(message.ToByteArray(), emptyMessage.ToByteArray()); 83 84 var newMessage = message.Descriptor.Parser.ParseFrom(emptyMessage.ToByteArray()); 85 Assert.AreEqual(message, newMessage); 86 Assert.AreEqual(message.CalculateSize(), newMessage.CalculateSize()); 87 } 88 89 [Test] 90 [TestCaseSource(typeof(Data), "Messages")] TestMergeMessage(IMessage message)91 public void TestMergeMessage(IMessage message) 92 { 93 var emptyMessage = new TestEmptyMessage(); 94 var otherEmptyMessage = new TestEmptyMessage(); 95 emptyMessage.MergeFrom(message.ToByteArray()); 96 otherEmptyMessage.MergeFrom(emptyMessage); 97 98 Assert.AreEqual(message.CalculateSize(), otherEmptyMessage.CalculateSize()); 99 Assert.AreEqual(message.ToByteArray(), otherEmptyMessage.ToByteArray()); 100 } 101 102 [Test] 103 [TestCaseSource(typeof(Data), "Messages")] TestEquals(IMessage message)104 public void TestEquals(IMessage message) 105 { 106 var emptyMessage = new TestEmptyMessage(); 107 var otherEmptyMessage = new TestEmptyMessage(); 108 Assert.AreEqual(emptyMessage, otherEmptyMessage); 109 emptyMessage.MergeFrom(message.ToByteArray()); 110 Assert.AreNotEqual(emptyMessage.CalculateSize(), 111 otherEmptyMessage.CalculateSize()); 112 Assert.AreNotEqual(emptyMessage, otherEmptyMessage); 113 } 114 115 [Test] 116 [TestCaseSource(typeof(Data), "Messages")] TestHashCode(IMessage message)117 public void TestHashCode(IMessage message) 118 { 119 var emptyMessage = new TestEmptyMessage(); 120 int hashCode = emptyMessage.GetHashCode(); 121 emptyMessage.MergeFrom(message.ToByteArray()); 122 Assert.AreNotEqual(hashCode, emptyMessage.GetHashCode()); 123 } 124 125 [Test] 126 [TestCaseSource(typeof(Data), "Messages")] TestClone(IMessage message)127 public void TestClone(IMessage message) 128 { 129 var emptyMessage = new TestEmptyMessage(); 130 var otherEmptyMessage = new TestEmptyMessage(); 131 otherEmptyMessage = emptyMessage.Clone(); 132 Assert.AreEqual(emptyMessage.CalculateSize(), otherEmptyMessage.CalculateSize()); 133 Assert.AreEqual(emptyMessage.ToByteArray(), otherEmptyMessage.ToByteArray()); 134 135 emptyMessage.MergeFrom(message.ToByteArray()); 136 otherEmptyMessage = emptyMessage.Clone(); 137 Assert.AreEqual(message.CalculateSize(), otherEmptyMessage.CalculateSize()); 138 Assert.AreEqual(message.ToByteArray(), otherEmptyMessage.ToByteArray()); 139 } 140 141 [Test] TestClone_LengthDelimited()142 public void TestClone_LengthDelimited() 143 { 144 var unknownVarintField = new UnknownField(); 145 unknownVarintField.AddVarint(99); 146 147 var unknownLengthDelimitedField1 = new UnknownField(); 148 unknownLengthDelimitedField1.AddLengthDelimited(ByteString.CopyFromUtf8("some data")); 149 150 var unknownLengthDelimitedField2 = new UnknownField(); 151 unknownLengthDelimitedField2.AddLengthDelimited(ByteString.CopyFromUtf8("some more data")); 152 153 var destUnknownFieldSet = new UnknownFieldSet(); 154 destUnknownFieldSet.AddOrReplaceField(997, unknownVarintField); 155 destUnknownFieldSet.AddOrReplaceField(999, unknownLengthDelimitedField1); 156 destUnknownFieldSet.AddOrReplaceField(999, unknownLengthDelimitedField2); 157 158 var clone = UnknownFieldSet.Clone(destUnknownFieldSet); 159 160 Assert.IsTrue(clone.HasField(997)); 161 Assert.IsTrue(clone.HasField(999)); 162 } 163 164 [Test] 165 [TestCaseSource(typeof(Data), "Messages")] TestDiscardUnknownFields(IMessage message)166 public void TestDiscardUnknownFields(IMessage message) 167 { 168 var goldenEmptyMessage = new TestEmptyMessage(); 169 byte[] data = message.ToByteArray(); 170 int fullSize = message.CalculateSize(); 171 172 Action<IMessage> assertEmpty = msg => 173 { 174 Assert.AreEqual(0, msg.CalculateSize()); 175 Assert.AreEqual(goldenEmptyMessage, msg); 176 }; 177 178 Action<IMessage> assertFull = msg => Assert.AreEqual(fullSize, msg.CalculateSize()); 179 180 // Test the behavior of the parsers with and without discarding, both generic and non-generic. 181 MessageParser<TestEmptyMessage> retainingParser1 = TestEmptyMessage.Parser; 182 MessageParser retainingParser2 = retainingParser1; 183 MessageParser<TestEmptyMessage> discardingParser1 = retainingParser1.WithDiscardUnknownFields(true); 184 MessageParser discardingParser2 = retainingParser2.WithDiscardUnknownFields(true); 185 186 // Test parse from byte[] 187 MessageParsingHelpers.AssertReadingMessage(retainingParser1, data, m => assertFull(m)); 188 MessageParsingHelpers.AssertReadingMessage(retainingParser2, data, m => assertFull(m)); 189 MessageParsingHelpers.AssertReadingMessage(discardingParser1, data, m => assertEmpty(m)); 190 MessageParsingHelpers.AssertReadingMessage(discardingParser2, data, m => assertEmpty(m)); 191 192 // Test parse from byte[] with offset 193 assertFull(retainingParser1.ParseFrom(data, 0, data.Length)); 194 assertFull(retainingParser2.ParseFrom(data, 0, data.Length)); 195 assertEmpty(discardingParser1.ParseFrom(data, 0, data.Length)); 196 assertEmpty(discardingParser2.ParseFrom(data, 0, data.Length)); 197 198 // Test parse from CodedInputStream 199 assertFull(retainingParser1.ParseFrom(new CodedInputStream(data))); 200 assertFull(retainingParser2.ParseFrom(new CodedInputStream(data))); 201 assertEmpty(discardingParser1.ParseFrom(new CodedInputStream(data))); 202 assertEmpty(discardingParser2.ParseFrom(new CodedInputStream(data))); 203 204 // Test parse from Stream 205 assertFull(retainingParser1.ParseFrom(new MemoryStream(data))); 206 assertFull(retainingParser2.ParseFrom(new MemoryStream(data))); 207 assertEmpty(discardingParser1.ParseFrom(new MemoryStream(data))); 208 assertEmpty(discardingParser2.ParseFrom(new MemoryStream(data))); 209 } 210 211 [Test] TestReadInvalidWireTypeThrowsInvalidProtocolBufferException()212 public void TestReadInvalidWireTypeThrowsInvalidProtocolBufferException() 213 { 214 MemoryStream ms = new MemoryStream(); 215 CodedOutputStream output = new CodedOutputStream(ms); 216 217 uint tag = WireFormat.MakeTag(1, (WireFormat.WireType)6); 218 output.WriteRawVarint32(tag); 219 output.WriteLength(-1); 220 output.Flush(); 221 ms.Position = 0; 222 223 CodedInputStream input = new CodedInputStream(ms); 224 Assert.AreEqual(tag, input.ReadTag()); 225 226 Assert.Throws<InvalidProtocolBufferException>(() => UnknownFieldSet.MergeFieldFrom(null, input)); 227 } 228 } 229 } 230