PageRenderTime 25ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/Examples/DictionaryTests.cs

https://gitlab.com/meermalik/protobuf-net
C# | 353 lines | 317 code | 36 blank | 0 comment | 4 complexity | 74dd945c651e80536a09fb9764943820 MD5 | raw file
  1. using System.Linq;
  2. using NUnit.Framework;
  3. using System.Collections.Generic;
  4. using ProtoBuf;
  5. using System;
  6. using ProtoBuf.Meta;
  7. using System.IO;
  8. using System.Diagnostics;
  9. using System.Text;
  10. namespace Examples.Dictionary
  11. {
  12. [ProtoContract]
  13. class DataWithDictionary<T>
  14. {
  15. public DataWithDictionary()
  16. {
  17. Data = new Dictionary<int, T>();
  18. }
  19. [ProtoMember(1)]
  20. public IDictionary<int, T> Data { get; private set; }
  21. }
  22. [ProtoContract]
  23. class SimpleData : IEquatable<SimpleData>
  24. {
  25. private SimpleData() {}
  26. public SimpleData(int value) {
  27. Value = value;}
  28. [ProtoMember(1)]
  29. public int Value { get; set; }
  30. public bool Equals(SimpleData other)
  31. {
  32. return Value == other.Value;
  33. }
  34. public override int GetHashCode()
  35. {
  36. return Value.GetHashCode();
  37. }
  38. public override bool Equals(object other)
  39. {
  40. return Equals(other as SimpleData);
  41. }
  42. }
  43. [TestFixture]
  44. public class DictionaryTests
  45. {
  46. [Test]
  47. public void TestNestedDictionaryWithStrings()
  48. {
  49. var obj = new DataWithDictionary<string>();
  50. obj.Data[0] = "abc";
  51. obj.Data[4] = "def";
  52. obj.Data[7] = "abc";
  53. var clone = Serializer.DeepClone(obj);
  54. Assert.AreNotSame(obj,clone);
  55. AssertEqual(obj.Data, clone.Data);
  56. }
  57. [Test]
  58. public void TestNestedDictionaryWithSimpleData()
  59. {
  60. var obj = new DataWithDictionary<SimpleData>();
  61. obj.Data[0] = new SimpleData(5);
  62. obj.Data[4] = new SimpleData(72);
  63. obj.Data[7] = new SimpleData(72);
  64. var clone = Serializer.DeepClone(obj);
  65. Assert.AreNotSame(obj, clone);
  66. AssertEqual(obj.Data, clone.Data);
  67. }
  68. [Test]
  69. public void RoundtripDictionary()
  70. {
  71. var lookup = new Dictionary<int,string>();
  72. lookup[0] = "abc";
  73. lookup[4] = "def";
  74. lookup[7] = "abc";
  75. var clone = Serializer.DeepClone(lookup);
  76. AssertEqual(lookup, clone);
  77. }
  78. static void AssertEqual<TKey, TValue>(
  79. IDictionary<TKey, TValue> expected,
  80. IDictionary<TKey, TValue> actual)
  81. {
  82. Assert.AreNotSame(expected, actual, "Instance");
  83. Assert.AreEqual(expected.Count, actual.Count, "Count");
  84. foreach (var pair in expected)
  85. {
  86. TValue value;
  87. Assert.IsTrue(actual.TryGetValue(pair.Key, out value), "Missing: " + pair.Key);
  88. Assert.AreEqual(pair.Value, value, "Value: " + pair.Key);
  89. }
  90. }
  91. }
  92. [TestFixture]
  93. public class EmptyDictionaryTests
  94. {
  95. [Test]
  96. public void EmptyDictionaryShouldDeserializeAsNonNull()
  97. {
  98. using (var ms = new MemoryStream())
  99. {
  100. var data = new Dictionary<string, int>();
  101. Serializer.Serialize(ms, data);
  102. ms.Position = 0;
  103. var clone = Serializer.Deserialize<Dictionary<string, int>>(ms);
  104. Assert.IsNotNull(clone);
  105. Assert.AreEqual(0, clone.Count);
  106. }
  107. }
  108. [Test]
  109. public void NonEmptyDictionaryShouldDeserialize()
  110. {
  111. using (var ms = new MemoryStream())
  112. {
  113. var data = new Dictionary<string, int> { { "abc", 123 } };
  114. Serializer.Serialize(ms, data);
  115. ms.Position = 0;
  116. var clone = Serializer.Deserialize<Dictionary<string, int>>(ms);
  117. Assert.IsNotNull(clone);
  118. Assert.AreEqual(1, clone.Count);
  119. Assert.AreEqual(123, clone["abc"]);
  120. }
  121. }
  122. [Test]
  123. public void EmptyDictionaryShouldDeserializeAsNonNullViaInterface()
  124. {
  125. using (var ms = new MemoryStream())
  126. {
  127. var data = new Dictionary<string, int>();
  128. Serializer.Serialize(ms, data);
  129. ms.Position = 0;
  130. var clone = Serializer.Deserialize<IDictionary<string, int>>(ms);
  131. Assert.IsNotNull(clone);
  132. Assert.AreEqual(0, clone.Count);
  133. }
  134. }
  135. [Test]
  136. public void NonEmptyDictionaryShouldDeserializeViaInterface()
  137. {
  138. using (var ms = new MemoryStream())
  139. {
  140. var data = new Dictionary<string, int> { { "abc", 123 } };
  141. Serializer.Serialize(ms, data);
  142. ms.Position = 0;
  143. var clone = Serializer.Deserialize<IDictionary<string, int>>(ms);
  144. Assert.IsNotNull(clone);
  145. Assert.AreEqual(1, clone.Count);
  146. Assert.AreEqual(123, clone["abc"]);
  147. }
  148. }
  149. }
  150. [TestFixture]
  151. public class NestedDictionaryTests {
  152. [Test]
  153. public void TestNestedConcreteConcreteDictionary()
  154. {
  155. Dictionary<string, Dictionary<string, String>> data = new Dictionary<string, Dictionary<string, string>>
  156. {
  157. { "abc", new Dictionary<string,string> {{"def","ghi"}}},
  158. { "jkl", new Dictionary<string,string> {{"mno","pqr"},{"stu","vwx"}}}
  159. };
  160. CheckNested(data, "original");
  161. var clone = Serializer.DeepClone(data);
  162. CheckNested(clone, "clone");
  163. }
  164. [Test]
  165. public void TestNestedInterfaceInterfaceDictionary()
  166. {
  167. IDictionary<string, IDictionary<string, String>> data = new Dictionary<string, IDictionary<string, string>>
  168. {
  169. { "abc", new Dictionary<string,string> {{"def","ghi"}}},
  170. { "jkl", new Dictionary<string,string> {{"mno","pqr"},{"stu","vwx"}}}
  171. };
  172. CheckNested(data, "original");
  173. var clone = Serializer.DeepClone(data);
  174. CheckNested(clone, "clone");
  175. }
  176. [Test]
  177. public void TestNestedInterfaceConcreteDictionary()
  178. {
  179. IDictionary<string, Dictionary<string, String>> data = new Dictionary<string, Dictionary<string, string>>
  180. {
  181. { "abc", new Dictionary<string,string> {{"def","ghi"}}},
  182. { "jkl", new Dictionary<string,string> {{"mno","pqr"},{"stu","vwx"}}}
  183. };
  184. CheckNested(data, "original");
  185. var clone = Serializer.DeepClone(data);
  186. CheckNested(clone, "clone");
  187. }
  188. [Test]
  189. public void TestNestedConcreteInterfaceDictionary()
  190. {
  191. Dictionary<string, IDictionary<string, String>> data = new Dictionary<string, IDictionary<string, string>>
  192. {
  193. { "abc", new Dictionary<string,string> {{"def","ghi"}}},
  194. { "jkl", new Dictionary<string,string> {{"mno","pqr"},{"stu","vwx"}}}
  195. };
  196. CheckNested(data, "original");
  197. var clone = Serializer.DeepClone(data);
  198. CheckNested(clone, "clone");
  199. }
  200. static void CheckNested<TInner>(IDictionary<string, TInner> data, string message)
  201. where TInner : IDictionary<string, string>
  202. {
  203. Assert.IsNotNull(data, message);
  204. Assert.AreEqual(2, data.Keys.Count, message);
  205. var inner = data["abc"];
  206. Assert.AreEqual(1, inner.Keys.Count, message);
  207. Assert.AreEqual(inner["def"], "ghi", message);
  208. inner = data["jkl"];
  209. Assert.AreEqual(2, inner.Keys.Count, message);
  210. Assert.AreEqual(inner["mno"], "pqr", message);
  211. Assert.AreEqual(inner["stu"], "vwx", message);
  212. }
  213. [Test]
  214. public void CheckPerformanceNotInsanelyBad()
  215. {
  216. var model = TypeModel.Create();
  217. model.Add(typeof (PropsViaDictionaryDefault), true);
  218. model.Add(typeof (PropsViaDictionaryGrouped), true);
  219. model.Add(typeof (PropsViaProperties), true);
  220. model.CompileInPlace();
  221. var o1 = new PropsViaProperties { Field1 = 123, Field2 = 456, Field3 = 789 };
  222. var o2 = new PropsViaDictionaryDefault()
  223. {
  224. Values = new List<KeyValuePair> {
  225. new KeyValuePair {Key = "Field1", Value =123 },
  226. new KeyValuePair {Key = "Field2", Value =456 },
  227. new KeyValuePair {Key = "Field2", Value =789 },
  228. }
  229. };
  230. var o3 = new PropsViaDictionaryGrouped()
  231. {
  232. Values = new List<KeyValuePair> {
  233. new KeyValuePair {Key = "Field1", Value =123 },
  234. new KeyValuePair {Key = "Field2", Value =456 },
  235. new KeyValuePair {Key = "Field2", Value =789 },
  236. }
  237. };
  238. int s1, s2, s3, d1, d2, d3;
  239. int l1 = BulkTest(model, o1, out s1, out d1);
  240. int l2 = BulkTest(model, o2, out s2, out d2);
  241. int l3 = BulkTest(model, o2, out s3, out d3);
  242. Console.WriteLine("Bytes (props)\t" + l1);
  243. Console.WriteLine("Ser (props)\t" + s1);
  244. Console.WriteLine("Deser (props)\t" + d1);
  245. Console.WriteLine("Bytes (kv-default)\t" + l2);
  246. Console.WriteLine("Ser (kv-default)\t" + s2);
  247. Console.WriteLine("Deser (kv-default)\t" + d2);
  248. Console.WriteLine("Bytes (kv-grouped)\t" + l3);
  249. Console.WriteLine("Ser (kv-grouped)\t" + s3);
  250. Console.WriteLine("Deser (kv-grouped)\t" + d3);
  251. var pw = new ProtoWriter(Stream.Null, null, null);
  252. Stopwatch watch = Stopwatch.StartNew();
  253. for (int i = 0; i < LOOP; i++ ) {
  254. ProtoWriter.WriteFieldHeader(1, WireType.String, pw);
  255. ProtoWriter.WriteString("Field1", pw);
  256. ProtoWriter.WriteFieldHeader(1, WireType.String, pw);
  257. ProtoWriter.WriteString("Field2", pw);
  258. ProtoWriter.WriteFieldHeader(1, WireType.String, pw);
  259. ProtoWriter.WriteString("Field3", pw);
  260. }
  261. watch.Stop();
  262. pw.Close();
  263. Console.WriteLine("Encoding: " + watch.ElapsedMilliseconds);
  264. }
  265. const int LOOP = 500000;
  266. static int BulkTest<T>(TypeModel model, T obj, out int serialize, out int deserialize) where T: class
  267. {
  268. using(MemoryStream ms = new MemoryStream())
  269. {
  270. Stopwatch watch = Stopwatch.StartNew();
  271. for (int i = 0; i < LOOP; i++)
  272. {
  273. ms.Position = 0;
  274. ms.SetLength(0);
  275. model.Serialize(ms, obj);
  276. }
  277. watch.Stop();
  278. serialize = (int)watch.ElapsedMilliseconds;
  279. watch.Reset();
  280. Type type = typeof (T);
  281. watch.Start();
  282. for (int i = 0; i < LOOP; i++)
  283. {
  284. ms.Position = 0;
  285. model.Deserialize(ms, null, type);
  286. }
  287. watch.Stop();
  288. deserialize = (int)watch.ElapsedMilliseconds;
  289. return (int)ms.Length;
  290. }
  291. }
  292. [ProtoContract]
  293. public class PropsViaDictionaryDefault
  294. {
  295. [ProtoMember(1, DataFormat = DataFormat.Default)] public List<KeyValuePair> Values { get; set;}
  296. }
  297. [ProtoContract]
  298. public class PropsViaDictionaryGrouped
  299. {
  300. [ProtoMember(1, DataFormat = DataFormat.Group)]
  301. public List<KeyValuePair> Values { get; set; }
  302. }
  303. [ProtoContract]
  304. public class KeyValuePair
  305. {
  306. [ProtoMember(1)] public string Key { get; set;}
  307. [ProtoMember(2)] public int Value { get; set;}
  308. }
  309. [ProtoContract]
  310. class PropsViaProperties
  311. {
  312. [ProtoMember(1)] public int Field1 { get; set;}
  313. [ProtoMember(2)] public int Field2 { get; set;}
  314. [ProtoMember(3)] public int Field3 { get; set;}
  315. }
  316. }
  317. }