FieldCodecTest.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #region Copyright notice and license
  2. // Protocol Buffers - Google's data interchange format
  3. // Copyright 2015 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. using System.Collections.Generic;
  33. using System.IO;
  34. using System.Reflection;
  35. using Google.Protobuf.TestProtos;
  36. using NUnit.Framework;
  37. namespace Google.Protobuf
  38. {
  39. public class FieldCodecTest
  40. {
  41. #pragma warning disable 0414 // Used by tests via reflection - do not remove!
  42. private static readonly List<ICodecTestData> Codecs = new List<ICodecTestData>
  43. {
  44. new FieldCodecTestData<bool>(FieldCodec.ForBool(100), true, "Bool"),
  45. new FieldCodecTestData<string>(FieldCodec.ForString(100), "sample", "String"),
  46. new FieldCodecTestData<ByteString>(FieldCodec.ForBytes(100), ByteString.CopyFrom(1, 2, 3), "Bytes"),
  47. new FieldCodecTestData<int>(FieldCodec.ForInt32(100), -1000, "Int32"),
  48. new FieldCodecTestData<int>(FieldCodec.ForSInt32(100), -1000, "SInt32"),
  49. new FieldCodecTestData<int>(FieldCodec.ForSFixed32(100), -1000, "SFixed32"),
  50. new FieldCodecTestData<uint>(FieldCodec.ForUInt32(100), 1234, "UInt32"),
  51. new FieldCodecTestData<uint>(FieldCodec.ForFixed32(100), 1234, "Fixed32"),
  52. new FieldCodecTestData<long>(FieldCodec.ForInt64(100), -1000, "Int64"),
  53. new FieldCodecTestData<long>(FieldCodec.ForSInt64(100), -1000, "SInt64"),
  54. new FieldCodecTestData<long>(FieldCodec.ForSFixed64(100), -1000, "SFixed64"),
  55. new FieldCodecTestData<ulong>(FieldCodec.ForUInt64(100), 1234, "UInt64"),
  56. new FieldCodecTestData<ulong>(FieldCodec.ForFixed64(100), 1234, "Fixed64"),
  57. new FieldCodecTestData<float>(FieldCodec.ForFloat(100), 1234.5f, "Float"),
  58. new FieldCodecTestData<double>(FieldCodec.ForDouble(100), 1234567890.5d, "Double"),
  59. new FieldCodecTestData<ForeignEnum>(
  60. FieldCodec.ForEnum(100, t => (int) t, t => (ForeignEnum) t), ForeignEnum.ForeignBaz, "Enum"),
  61. new FieldCodecTestData<ForeignMessage>(
  62. FieldCodec.ForMessage(100, ForeignMessage.Parser), new ForeignMessage { C = 10 }, "Message"),
  63. };
  64. #pragma warning restore 0414
  65. [Test, TestCaseSource("Codecs")]
  66. public void RoundTripWithTag(ICodecTestData codec)
  67. {
  68. codec.TestRoundTripWithTag();
  69. }
  70. [Test, TestCaseSource("Codecs")]
  71. public void RoundTripRaw(ICodecTestData codec)
  72. {
  73. codec.TestRoundTripRaw();
  74. }
  75. [Test, TestCaseSource("Codecs")]
  76. public void CalculateSize(ICodecTestData codec)
  77. {
  78. codec.TestCalculateSizeWithTag();
  79. }
  80. [Test, TestCaseSource("Codecs")]
  81. public void DefaultValue(ICodecTestData codec)
  82. {
  83. codec.TestDefaultValue();
  84. }
  85. [Test, TestCaseSource("Codecs")]
  86. public void FixedSize(ICodecTestData codec)
  87. {
  88. codec.TestFixedSize();
  89. }
  90. // This is ugly, but it means we can have a non-generic interface.
  91. // It feels like NUnit should support this better, but I don't know
  92. // of any better ways right now.
  93. public interface ICodecTestData
  94. {
  95. void TestRoundTripRaw();
  96. void TestRoundTripWithTag();
  97. void TestCalculateSizeWithTag();
  98. void TestDefaultValue();
  99. void TestFixedSize();
  100. }
  101. public class FieldCodecTestData<T> : ICodecTestData
  102. {
  103. private readonly FieldCodec<T> codec;
  104. private readonly T sampleValue;
  105. private readonly string name;
  106. public FieldCodecTestData(FieldCodec<T> codec, T sampleValue, string name)
  107. {
  108. this.codec = codec;
  109. this.sampleValue = sampleValue;
  110. this.name = name;
  111. }
  112. public void TestRoundTripRaw()
  113. {
  114. var stream = new MemoryStream();
  115. var codedOutput = new CodedOutputStream(stream);
  116. codec.ValueWriter(codedOutput, sampleValue);
  117. codedOutput.Flush();
  118. stream.Position = 0;
  119. var codedInput = new CodedInputStream(stream);
  120. Assert.AreEqual(sampleValue, codec.ValueReader(codedInput));
  121. Assert.IsTrue(codedInput.IsAtEnd);
  122. }
  123. public void TestRoundTripWithTag()
  124. {
  125. var stream = new MemoryStream();
  126. var codedOutput = new CodedOutputStream(stream);
  127. codec.WriteTagAndValue(codedOutput, sampleValue);
  128. codedOutput.Flush();
  129. stream.Position = 0;
  130. var codedInput = new CodedInputStream(stream);
  131. codedInput.AssertNextTag(codec.Tag);
  132. Assert.AreEqual(sampleValue, codec.Read(codedInput));
  133. Assert.IsTrue(codedInput.IsAtEnd);
  134. }
  135. public void TestCalculateSizeWithTag()
  136. {
  137. var stream = new MemoryStream();
  138. var codedOutput = new CodedOutputStream(stream);
  139. codec.WriteTagAndValue(codedOutput, sampleValue);
  140. codedOutput.Flush();
  141. Assert.AreEqual(stream.Position, codec.CalculateSizeWithTag(sampleValue));
  142. }
  143. public void TestDefaultValue()
  144. {
  145. // WriteTagAndValue ignores default values
  146. var stream = new MemoryStream();
  147. var codedOutput = new CodedOutputStream(stream);
  148. codec.WriteTagAndValue(codedOutput, codec.DefaultValue);
  149. codedOutput.Flush();
  150. Assert.AreEqual(0, stream.Position);
  151. Assert.AreEqual(0, codec.CalculateSizeWithTag(codec.DefaultValue));
  152. if (typeof(T).GetTypeInfo().IsValueType)
  153. {
  154. Assert.AreEqual(default(T), codec.DefaultValue);
  155. }
  156. // The plain ValueWriter/ValueReader delegates don't.
  157. if (codec.DefaultValue != null) // This part isn't appropriate for message types.
  158. {
  159. codedOutput = new CodedOutputStream(stream);
  160. codec.ValueWriter(codedOutput, codec.DefaultValue);
  161. codedOutput.Flush();
  162. Assert.AreNotEqual(0, stream.Position);
  163. Assert.AreEqual(stream.Position, codec.ValueSizeCalculator(codec.DefaultValue));
  164. stream.Position = 0;
  165. var codedInput = new CodedInputStream(stream);
  166. Assert.AreEqual(codec.DefaultValue, codec.ValueReader(codedInput));
  167. }
  168. }
  169. public void TestFixedSize()
  170. {
  171. Assert.AreEqual(name.Contains("Fixed"), codec.FixedSize != 0);
  172. }
  173. public override string ToString()
  174. {
  175. return name;
  176. }
  177. }
  178. }
  179. }