/src/Compilers/Core/CodeAnalysisTest/ObjectSerializationTests.cs

https://gitlab.com/sharadag/Roslyn · C# · 631 lines · 538 code · 87 blank · 6 comment · 12 complexity · 345468575d999d13f6598ef63dc130ba MD5 · raw file

  1. // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. using Roslyn.Utilities;
  8. using Xunit;
  9. namespace Microsoft.CodeAnalysis.UnitTests
  10. {
  11. public sealed class ObjectSerializationTests
  12. {
  13. [Fact]
  14. public void TestRoundTripPrimitives()
  15. {
  16. var stream = new MemoryStream();
  17. var writer = new ObjectWriter(stream);
  18. writer.WriteBoolean(true);
  19. writer.WriteBoolean(false);
  20. writer.WriteByte(Byte.MaxValue);
  21. writer.WriteSByte(SByte.MaxValue);
  22. writer.WriteInt16(Int16.MaxValue);
  23. writer.WriteInt32(Int32.MaxValue);
  24. writer.WriteInt32(Byte.MaxValue);
  25. writer.WriteInt32(Int16.MaxValue);
  26. writer.WriteInt64(Int64.MaxValue);
  27. writer.WriteUInt16(UInt16.MaxValue);
  28. writer.WriteUInt32(UInt32.MaxValue);
  29. writer.WriteUInt64(UInt64.MaxValue);
  30. writer.WriteDecimal(Decimal.MaxValue);
  31. writer.WriteDouble(Double.MaxValue);
  32. writer.WriteSingle(Single.MaxValue);
  33. writer.WriteChar('X');
  34. writer.WriteString("YYY");
  35. writer.WriteString("\uD800\uDC00"); // valid surrogate pair
  36. writer.WriteString("\uDC00\uD800"); // invalid surrogate pair
  37. writer.WriteString("\uD800"); // incomplete surrogate pair
  38. writer.WriteCompressedUInt(Byte.MaxValue >> 2); // 6 bits
  39. writer.WriteCompressedUInt(UInt16.MaxValue >> 2); // 14 bits
  40. writer.WriteCompressedUInt(UInt32.MaxValue >> 2); // 30 bits
  41. var dt = DateTime.Now;
  42. writer.WriteDateTime(dt);
  43. writer.Dispose();
  44. stream.Position = 0;
  45. var reader = new ObjectReader(stream);
  46. Assert.Equal(true, reader.ReadBoolean());
  47. Assert.Equal(false, reader.ReadBoolean());
  48. Assert.Equal(Byte.MaxValue, reader.ReadByte());
  49. Assert.Equal(SByte.MaxValue, reader.ReadSByte());
  50. Assert.Equal(Int16.MaxValue, reader.ReadInt16());
  51. Assert.Equal(Int32.MaxValue, reader.ReadInt32());
  52. Assert.Equal(Byte.MaxValue, reader.ReadInt32());
  53. Assert.Equal(Int16.MaxValue, reader.ReadInt32());
  54. Assert.Equal(Int64.MaxValue, reader.ReadInt64());
  55. Assert.Equal(UInt16.MaxValue, reader.ReadUInt16());
  56. Assert.Equal(UInt32.MaxValue, reader.ReadUInt32());
  57. Assert.Equal(UInt64.MaxValue, reader.ReadUInt64());
  58. Assert.Equal(Decimal.MaxValue, reader.ReadDecimal());
  59. Assert.Equal(Double.MaxValue, reader.ReadDouble());
  60. Assert.Equal(Single.MaxValue, reader.ReadSingle());
  61. Assert.Equal('X', reader.ReadChar());
  62. Assert.Equal("YYY", reader.ReadString());
  63. Assert.Equal("\uD800\uDC00", reader.ReadString()); // valid surrogate pair
  64. Assert.Equal("\uDC00\uD800", reader.ReadString()); // invalid surrogate pair
  65. Assert.Equal("\uD800", reader.ReadString()); // incomplete surrogate pair
  66. Assert.Equal((UInt32)(Byte.MaxValue >> 2), reader.ReadCompressedUInt());
  67. Assert.Equal((UInt32)(UInt16.MaxValue >> 2), reader.ReadCompressedUInt());
  68. Assert.Equal(UInt32.MaxValue >> 2, reader.ReadCompressedUInt());
  69. Assert.Equal(dt, reader.ReadDateTime());
  70. reader.Dispose();
  71. }
  72. [Fact]
  73. public void TestRoundTripPrimitivesAsValues()
  74. {
  75. var stream = new MemoryStream();
  76. var writer = new ObjectWriter(stream);
  77. writer.WriteValue(true);
  78. writer.WriteValue(false);
  79. writer.WriteValue(Byte.MaxValue);
  80. writer.WriteValue(SByte.MaxValue);
  81. writer.WriteValue(Int16.MaxValue);
  82. writer.WriteValue(Int32.MaxValue);
  83. writer.WriteValue((Int32)Byte.MaxValue);
  84. writer.WriteValue((Int32)Int16.MaxValue);
  85. writer.WriteValue(Int64.MaxValue);
  86. writer.WriteValue(UInt16.MaxValue);
  87. writer.WriteValue(UInt32.MaxValue);
  88. writer.WriteValue(UInt64.MaxValue);
  89. writer.WriteValue(Decimal.MaxValue);
  90. writer.WriteValue(Double.MaxValue);
  91. writer.WriteValue(Single.MaxValue);
  92. writer.WriteValue('X');
  93. writer.WriteValue("YYY");
  94. writer.WriteString("\uD800\uDC00"); // valid surrogate pair
  95. writer.WriteString("\uDC00\uD800"); // invalid surrogate pair
  96. writer.WriteString("\uD800"); // incomplete surrogate pair
  97. writer.WriteValue(null);
  98. writer.WriteValue(ConsoleColor.Cyan);
  99. writer.WriteValue(EByte.Value);
  100. writer.WriteValue(ESByte.Value);
  101. writer.WriteValue(EShort.Value);
  102. writer.WriteValue(EUShort.Value);
  103. writer.WriteValue(EInt.Value);
  104. writer.WriteValue(EUInt.Value);
  105. writer.WriteValue(ELong.Value);
  106. writer.WriteValue(EULong.Value);
  107. writer.WriteValue(typeof(object));
  108. var date = DateTime.Now;
  109. writer.WriteValue(date);
  110. writer.Dispose();
  111. stream.Position = 0;
  112. var reader = new ObjectReader(stream, binder: writer.Binder);
  113. Assert.Equal(true, (bool)reader.ReadValue());
  114. Assert.Equal(false, (bool)reader.ReadValue());
  115. Assert.Equal(Byte.MaxValue, (Byte)reader.ReadValue());
  116. Assert.Equal(SByte.MaxValue, (SByte)reader.ReadValue());
  117. Assert.Equal(Int16.MaxValue, (Int16)reader.ReadValue());
  118. Assert.Equal(Int32.MaxValue, (Int32)reader.ReadValue());
  119. Assert.Equal(Byte.MaxValue, (Int32)reader.ReadValue());
  120. Assert.Equal(Int16.MaxValue, (Int32)reader.ReadValue());
  121. Assert.Equal(Int64.MaxValue, (Int64)reader.ReadValue());
  122. Assert.Equal(UInt16.MaxValue, (UInt16)reader.ReadValue());
  123. Assert.Equal(UInt32.MaxValue, (UInt32)reader.ReadValue());
  124. Assert.Equal(UInt64.MaxValue, (UInt64)reader.ReadValue());
  125. Assert.Equal(Decimal.MaxValue, (Decimal)reader.ReadValue());
  126. Assert.Equal(Double.MaxValue, (Double)reader.ReadValue());
  127. Assert.Equal(Single.MaxValue, (Single)reader.ReadValue());
  128. Assert.Equal('X', (Char)reader.ReadValue());
  129. Assert.Equal("YYY", (String)reader.ReadValue());
  130. Assert.Equal("\uD800\uDC00", (String)reader.ReadValue()); // valid surrogate pair
  131. Assert.Equal("\uDC00\uD800", (String)reader.ReadValue()); // invalid surrogate pair
  132. Assert.Equal("\uD800", (String)reader.ReadValue()); // incomplete surrogate pair
  133. Assert.Equal(null, reader.ReadValue());
  134. Assert.Equal(ConsoleColor.Cyan, reader.ReadValue());
  135. Assert.Equal(EByte.Value, reader.ReadValue());
  136. Assert.Equal(ESByte.Value, reader.ReadValue());
  137. Assert.Equal(EShort.Value, reader.ReadValue());
  138. Assert.Equal(EUShort.Value, reader.ReadValue());
  139. Assert.Equal(EInt.Value, reader.ReadValue());
  140. Assert.Equal(EUInt.Value, reader.ReadValue());
  141. Assert.Equal(ELong.Value, reader.ReadValue());
  142. Assert.Equal(EULong.Value, reader.ReadValue());
  143. Assert.Equal(typeof(object), (Type)reader.ReadValue());
  144. Assert.Equal(date, (DateTime)reader.ReadValue());
  145. reader.Dispose();
  146. }
  147. public enum EByte : byte
  148. {
  149. Value = 1
  150. }
  151. public enum ESByte : sbyte
  152. {
  153. Value = 2
  154. }
  155. public enum EShort : short
  156. {
  157. Value = 3
  158. }
  159. public enum EUShort : ushort
  160. {
  161. Value = 4
  162. }
  163. public enum EInt : int
  164. {
  165. Value = 5
  166. }
  167. public enum EUInt : uint
  168. {
  169. Value = 6
  170. }
  171. public enum ELong : long
  172. {
  173. Value = 7
  174. }
  175. public enum EULong : ulong
  176. {
  177. Value = 8
  178. }
  179. [Fact]
  180. public void TestRoundTripCharacters()
  181. {
  182. // round trip all possible characters as a string
  183. for (int i = ushort.MinValue; i <= ushort.MaxValue; i++)
  184. {
  185. RoundTripCharacter((char)i);
  186. }
  187. }
  188. private void RoundTripCharacter(Char ch)
  189. {
  190. var stream = new MemoryStream();
  191. var writer = new ObjectWriter(stream);
  192. writer.WriteChar(ch);
  193. writer.Dispose();
  194. stream.Position = 0;
  195. var reader = new ObjectReader(stream);
  196. var readch = reader.ReadChar();
  197. reader.Dispose();
  198. Assert.Equal(ch, readch);
  199. }
  200. [Fact]
  201. public void TestRoundTripStringCharacters()
  202. {
  203. // round trip all possible characters as a string
  204. for (int i = ushort.MinValue; i <= ushort.MaxValue; i++)
  205. {
  206. RoundTripStringCharacter((ushort)i);
  207. }
  208. // round trip single string with all possible characters
  209. var sb = new StringBuilder();
  210. for (int i = ushort.MinValue; i <= ushort.MaxValue; i++)
  211. {
  212. sb.Append((char)i);
  213. }
  214. RoundTripString(sb.ToString());
  215. }
  216. private void RoundTripString(string text)
  217. {
  218. var stream = new MemoryStream();
  219. var writer = new ObjectWriter(stream);
  220. writer.WriteString(text);
  221. writer.Dispose();
  222. stream.Position = 0;
  223. var reader = new ObjectReader(stream);
  224. var readText = reader.ReadString();
  225. reader.Dispose();
  226. Assert.Equal(text, readText);
  227. }
  228. private void RoundTripStringCharacter(ushort code)
  229. {
  230. RoundTripString(new String((char)code, 1));
  231. }
  232. [Fact]
  233. public void TestRoundTripArrays()
  234. {
  235. TestRoundTripArray(new object[] { });
  236. TestRoundTripArray(new object[] { "hello" });
  237. TestRoundTripArray(new object[] { "hello", "world" });
  238. TestRoundTripArray(new object[] { "hello", "world", "good" });
  239. TestRoundTripArray(new object[] { "hello", "world", "good", "bye" });
  240. TestRoundTripArray(new object[] { "hello", 123, 45m, 99.9, 'c' });
  241. TestRoundTripArray(new string[] { "hello", null, "world" });
  242. }
  243. private void TestRoundTripArray<T>(T[] values)
  244. {
  245. var stream = new MemoryStream();
  246. var writer = new ObjectWriter(stream);
  247. writer.WriteValue(values);
  248. writer.Dispose();
  249. stream.Position = 0;
  250. var reader = new ObjectReader(stream, binder: writer.Binder);
  251. var readValues = (T[])reader.ReadValue();
  252. reader.Dispose();
  253. Assert.Equal(true, values.SequenceEqual(readValues));
  254. }
  255. [Fact]
  256. public void TestRoundTripWritableObject()
  257. {
  258. var instance = new WritableClass(123, "456");
  259. var stream = new MemoryStream();
  260. var writer = new ObjectWriter(stream);
  261. writer.WriteValue(instance);
  262. writer.Dispose();
  263. stream.Position = 0;
  264. var reader = new ObjectReader(stream, binder: writer.Binder);
  265. var instance2 = (WritableClass)reader.ReadValue();
  266. reader.Dispose();
  267. Assert.NotNull(instance2);
  268. Assert.Equal(instance.X, instance2.X);
  269. Assert.Equal(instance.Y, instance2.Y);
  270. }
  271. [Fact]
  272. public void TestObjectMapLimits()
  273. {
  274. using (var stream = new MemoryStream())
  275. {
  276. var instances = new List<WritableClass>();
  277. // We need enough items to exercise all sizes of ObjectRef
  278. for (int i = 0; i < ushort.MaxValue + 1; i++)
  279. {
  280. instances.Add(new WritableClass(i, i.ToString()));
  281. }
  282. var writer = new ObjectWriter(stream);
  283. // Write each instance twice. The second time around, they'll become ObjectRefs
  284. for (int pass = 0; pass < 2; pass++)
  285. {
  286. foreach (var instance in instances)
  287. {
  288. writer.WriteValue(instance);
  289. }
  290. }
  291. var binder = writer.Binder;
  292. writer.Dispose();
  293. stream.Position = 0;
  294. using (var reader = new ObjectReader(stream, binder: binder))
  295. {
  296. for (int pass = 0; pass < 2; pass++)
  297. {
  298. foreach (var instance in instances)
  299. {
  300. var obj = (WritableClass)reader.ReadValue();
  301. Assert.NotNull(obj);
  302. Assert.Equal(obj.X, instance.X);
  303. Assert.Equal(obj.Y, instance.Y);
  304. }
  305. }
  306. }
  307. }
  308. }
  309. private class WritableClass : IObjectWritable, IObjectReadable
  310. {
  311. internal readonly int X;
  312. internal readonly string Y;
  313. public WritableClass(int x, string y)
  314. {
  315. this.X = x;
  316. this.Y = y;
  317. }
  318. private WritableClass(ObjectReader reader)
  319. {
  320. this.X = reader.ReadInt32();
  321. this.Y = reader.ReadString();
  322. }
  323. public void WriteTo(ObjectWriter writer)
  324. {
  325. writer.WriteInt32(this.X);
  326. writer.WriteString(this.Y);
  327. }
  328. Func<ObjectReader, object> IObjectReadable.GetReader()
  329. {
  330. return (r) => new WritableClass(r);
  331. }
  332. }
  333. #if false
  334. [Fact]
  335. public void TestRoundTripSerializableObject()
  336. {
  337. var instance = new SerializableClass(123, "456");
  338. var stream = new MemoryStream();
  339. var writer = new ObjectWriter(stream);
  340. writer.WriteValue(instance);
  341. writer.Dispose();
  342. stream.Position = 0;
  343. var reader = new ObjectReader(stream);
  344. var instance2 = (SerializableClass)reader.ReadValue();
  345. reader.Dispose();
  346. Assert.NotNull(instance2);
  347. Assert.Equal(instance.X, instance2.X);
  348. Assert.Equal(instance.Y, instance2.Y);
  349. }
  350. private class SerializableClass : ISerializable
  351. {
  352. internal readonly int X;
  353. internal readonly string Y;
  354. public SerializableClass(int x, string y)
  355. {
  356. this.X = x;
  357. this.Y = y;
  358. }
  359. private SerializableClass(SerializationInfo info, StreamingContext context)
  360. {
  361. this.X = info.GetInt32("x");
  362. this.Y = info.GetString("y");
  363. }
  364. public void GetObjectData(SerializationInfo info, StreamingContext context)
  365. {
  366. info.AddValue("x", this.X);
  367. info.AddValue("y", this.Y);
  368. }
  369. }
  370. [Fact]
  371. public void TestRoundTripLocation()
  372. {
  373. var instance = new SpecialLocation();
  374. var stream = new MemoryStream();
  375. var writer = new ObjectWriter(stream);
  376. writer.WriteValue(instance);
  377. writer.Dispose();
  378. stream.Position = 0;
  379. var reader = new ObjectReader(stream);
  380. var instance2 = (Location)reader.ReadValue();
  381. reader.Dispose();
  382. Assert.NotNull(instance2);
  383. Assert.Equal(instance2.GetType(), typeof(SerializedLocation));
  384. Assert.Equal(instance.Kind, instance2.Kind);
  385. Assert.Equal(instance.IsInSource, instance2.IsInSource);
  386. Assert.Equal(instance.SourceSpan, instance2.SourceSpan);
  387. Assert.Equal(instance.Kind, instance2.Kind);
  388. }
  389. private class SpecialLocation : Location
  390. {
  391. private TextSpan textSpan = new TextSpan(10, 20);
  392. public override LocationKind Kind
  393. {
  394. get
  395. {
  396. return LocationKind.None;
  397. }
  398. }
  399. public override TextSpan SourceSpan
  400. {
  401. get
  402. {
  403. return textSpan;
  404. }
  405. }
  406. public override bool Equals(object obj)
  407. {
  408. throw new NotImplementedException();
  409. }
  410. public override int GetHashCode()
  411. {
  412. return 1;
  413. }
  414. }
  415. [Fact]
  416. public void TestRoundTripRawSerializableObject()
  417. {
  418. var instance = new RawSerializableClass(123, "456");
  419. var stream = new MemoryStream();
  420. var writer = new ObjectWriter(stream);
  421. writer.WriteValue(instance);
  422. writer.Dispose();
  423. stream.Position = 0;
  424. var reader = new ObjectReader(stream);
  425. var instance2 = (RawSerializableClass)reader.ReadValue();
  426. reader.Dispose();
  427. Assert.NotNull(instance2);
  428. Assert.Equal(instance.X, instance2.X);
  429. Assert.Equal(instance.Y, instance2.Y);
  430. }
  431. [Serializable]
  432. private class RawSerializableClass
  433. {
  434. internal readonly int X;
  435. internal readonly string Y;
  436. public RawSerializableClass(int x, string y)
  437. {
  438. this.X = x;
  439. this.Y = y;
  440. }
  441. }
  442. [Fact]
  443. public void TestRoundTripSingletonClass()
  444. {
  445. var instance = SingletonClass.Singleton;
  446. var stream = new MemoryStream();
  447. var writer = new ObjectWriter(stream);
  448. writer.WriteValue(instance);
  449. writer.Dispose();
  450. stream.Position = 0;
  451. var reader = new ObjectReader(stream);
  452. var instance2 = (SingletonClass)reader.ReadValue();
  453. reader.Dispose();
  454. Assert.Same(instance, instance2);
  455. }
  456. [Serializable]
  457. private class SingletonClass : IObjectReference
  458. {
  459. internal readonly int X;
  460. internal readonly string Y;
  461. private SingletonClass(int x, string y)
  462. {
  463. this.X = x;
  464. this.Y = y;
  465. }
  466. public static readonly SingletonClass Singleton = new SingletonClass(999, "999");
  467. public object GetRealObject(StreamingContext context)
  468. {
  469. return Singleton;
  470. }
  471. }
  472. #endif
  473. [Fact]
  474. public void TestRoundTripGraph()
  475. {
  476. var oneNode = new Node("one");
  477. TestRoundTripGraphCore(oneNode);
  478. TestRoundTripGraphCore(new Node("a", new Node("b"), new Node("c")));
  479. TestRoundTripGraphCore(new Node("x", oneNode, oneNode, oneNode, oneNode));
  480. #if false // cycles not supported
  481. var cyclicNode = new Node("cyclic", oneNode);
  482. cyclicNode.Children[0] = cyclicNode;
  483. TestRoundTripGraph(cyclicNode);
  484. #endif
  485. }
  486. private void TestRoundTripGraphCore(Node graph)
  487. {
  488. var stream = new MemoryStream();
  489. var writer = new ObjectWriter(stream);
  490. writer.WriteValue(graph);
  491. writer.Dispose();
  492. stream.Position = 0;
  493. var reader = new ObjectReader(stream, binder: writer.Binder);
  494. var newGraph = (Node)reader.ReadValue();
  495. reader.Dispose();
  496. Assert.NotNull(newGraph);
  497. Assert.Equal(true, graph.IsEquivalentTo(newGraph));
  498. }
  499. private class Node : IObjectWritable, IObjectReadable
  500. {
  501. internal readonly string Name;
  502. internal readonly Node[] Children;
  503. public Node(string name, params Node[] children)
  504. {
  505. this.Name = name;
  506. this.Children = children;
  507. }
  508. private Node(ObjectReader reader)
  509. {
  510. this.Name = reader.ReadString();
  511. this.Children = (Node[])reader.ReadValue();
  512. }
  513. private static readonly Func<ObjectReader, object> s_createInstance = r => new Node(r);
  514. public void WriteTo(ObjectWriter writer)
  515. {
  516. writer.WriteString(this.Name);
  517. writer.WriteValue(this.Children);
  518. }
  519. Func<ObjectReader, object> IObjectReadable.GetReader()
  520. {
  521. return (r) => new Node(r);
  522. }
  523. public bool IsEquivalentTo(Node node)
  524. {
  525. if (this.Name != node.Name)
  526. {
  527. return false;
  528. }
  529. if (this.Children.Length != node.Children.Length)
  530. {
  531. return false;
  532. }
  533. for (int i = 0; i < this.Children.Length; i++)
  534. {
  535. if (!this.Children[i].IsEquivalentTo(node.Children[i]))
  536. {
  537. return false;
  538. }
  539. }
  540. return true;
  541. }
  542. }
  543. }
  544. }