TestWriterFormatJson.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. using System;
  2. using System.IO;
  3. using Google.ProtocolBuffers.Serialization;
  4. using NUnit.Framework;
  5. using Google.ProtocolBuffers.TestProtos;
  6. namespace Google.ProtocolBuffers
  7. {
  8. [TestFixture]
  9. public class TestWriterFormatJson
  10. {
  11. protected string Content;
  12. [System.Diagnostics.DebuggerNonUserCode]
  13. protected void FormatterAssert<TMessage>(TMessage message, params string[] expecting) where TMessage : IMessageLite
  14. {
  15. StringWriter sw = new StringWriter();
  16. JsonFormatWriter.CreateInstance(sw).WriteMessage(message);
  17. Content = sw.ToString();
  18. ExtensionRegistry registry = ExtensionRegistry.CreateInstance();
  19. UnitTestXmlSerializerTestProtoFile.RegisterAllExtensions(registry);
  20. IMessageLite copy =
  21. JsonFormatReader.CreateInstance(Content)
  22. .Merge(message.WeakCreateBuilderForType(), registry).WeakBuild();
  23. Assert.AreEqual(typeof(TMessage), copy.GetType());
  24. Assert.AreEqual(message, copy);
  25. foreach (string expect in expecting)
  26. Assert.IsTrue(Content.IndexOf(expect) >= 0, "Expected to find content '{0}' in: \r\n{1}", expect, Content);
  27. }
  28. [Test]
  29. public void TestToJsonParseFromJson()
  30. {
  31. TestAllTypes msg = new TestAllTypes.Builder().SetDefaultBool(true).Build();
  32. string json = msg.ToJson();
  33. Assert.AreEqual("{\"default_bool\":true}", json);
  34. TestAllTypes copy = TestAllTypes.ParseFromJson(json);
  35. Assert.IsTrue(copy.HasDefaultBool && copy.DefaultBool);
  36. Assert.AreEqual(msg, copy);
  37. }
  38. [Test]
  39. public void TestToJsonParseFromJsonReader()
  40. {
  41. TestAllTypes msg = new TestAllTypes.Builder().SetDefaultBool(true).Build();
  42. string json = msg.ToJson();
  43. Assert.AreEqual("{\"default_bool\":true}", json);
  44. TestAllTypes copy = TestAllTypes.ParseFromJson(new StringReader(json));
  45. Assert.IsTrue(copy.HasDefaultBool && copy.DefaultBool);
  46. Assert.AreEqual(msg, copy);
  47. }
  48. [Test]
  49. public void TestJsonFormatted()
  50. {
  51. TestXmlMessage message = TestXmlMessage.CreateBuilder()
  52. .SetValid(true)
  53. .SetNumber(0x1010)
  54. .AddChildren(TestXmlMessage.Types.Children.CreateBuilder())
  55. .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.ONE))
  56. .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.ONE).AddOptions(EnumOptions.TWO))
  57. .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().SetBinary(ByteString.CopyFromUtf8("abc")))
  58. .Build();
  59. StringWriter sw = new StringWriter();
  60. JsonFormatWriter.CreateInstance(sw).Formatted()
  61. .WriteMessage(message);
  62. string json = sw.ToString();
  63. TestXmlMessage copy = JsonFormatReader.CreateInstance(json)
  64. .Merge(TestXmlMessage.CreateBuilder()).Build();
  65. Assert.AreEqual(message, copy);
  66. }
  67. [Test]
  68. public void TestEmptyMessage()
  69. {
  70. FormatterAssert(
  71. TestXmlChild.CreateBuilder()
  72. .Build(),
  73. @"{}"
  74. );
  75. }
  76. [Test]
  77. public void TestRepeatedField()
  78. {
  79. FormatterAssert(
  80. TestXmlChild.CreateBuilder()
  81. .AddOptions(EnumOptions.ONE)
  82. .AddOptions(EnumOptions.TWO)
  83. .Build(),
  84. @"{""options"":[""ONE"",""TWO""]}"
  85. );
  86. }
  87. [Test]
  88. public void TestNestedEmptyMessage()
  89. {
  90. FormatterAssert(
  91. TestXmlMessage.CreateBuilder()
  92. .SetChild(TestXmlChild.CreateBuilder().Build())
  93. .Build(),
  94. @"{""child"":{}}"
  95. );
  96. }
  97. [Test]
  98. public void TestNestedMessage()
  99. {
  100. FormatterAssert(
  101. TestXmlMessage.CreateBuilder()
  102. .SetChild(TestXmlChild.CreateBuilder().AddOptions(EnumOptions.TWO).Build())
  103. .Build(),
  104. @"{""child"":{""options"":[""TWO""]}}"
  105. );
  106. }
  107. [Test]
  108. public void TestBooleanTypes()
  109. {
  110. FormatterAssert(
  111. TestXmlMessage.CreateBuilder()
  112. .SetValid(true)
  113. .Build(),
  114. @"{""valid"":true}"
  115. );
  116. }
  117. [Test]
  118. public void TestFullMessage()
  119. {
  120. FormatterAssert(
  121. TestXmlMessage.CreateBuilder()
  122. .SetValid(true)
  123. .SetText("text")
  124. .AddTextlines("a")
  125. .AddTextlines("b")
  126. .AddTextlines("c")
  127. .SetNumber(0x1010101010)
  128. .AddNumbers(1)
  129. .AddNumbers(2)
  130. .AddNumbers(3)
  131. .SetChild(TestXmlChild.CreateBuilder().AddOptions(EnumOptions.ONE).SetBinary(ByteString.CopyFrom(new byte[1])))
  132. .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.TWO).SetBinary(ByteString.CopyFrom(new byte[2])))
  133. .AddChildren(TestXmlMessage.Types.Children.CreateBuilder().AddOptions(EnumOptions.THREE).SetBinary(ByteString.CopyFrom(new byte[3])))
  134. .Build(),
  135. @"""text"":""text""",
  136. @"[""a"",""b"",""c""]",
  137. @"[1,2,3]",
  138. @"""child"":{",
  139. @"""children"":[{",
  140. @"AA==",
  141. @"AAA=",
  142. @"AAAA",
  143. 0x1010101010L.ToString()
  144. );
  145. }
  146. [Test]
  147. public void TestMessageWithXmlText()
  148. {
  149. FormatterAssert(
  150. TestXmlMessage.CreateBuilder()
  151. .SetText("<text></text>")
  152. .Build(),
  153. @"{""text"":""<text><\/text>""}"
  154. );
  155. }
  156. [Test]
  157. public void TestWithEscapeChars()
  158. {
  159. FormatterAssert(
  160. TestXmlMessage.CreateBuilder()
  161. .SetText(" \t <- \"leading space and trailing\" -> \\ \xef54 \x0000 \xFF \xFFFF \b \f \r \n \t ")
  162. .Build(),
  163. "{\"text\":\" \\t <- \\\"leading space and trailing\\\" -> \\\\ \\uef54 \\u0000 \\u00ff \\uffff \\b \\f \\r \\n \\t \"}"
  164. );
  165. }
  166. [Test]
  167. public void TestWithExtensionText()
  168. {
  169. FormatterAssert(
  170. TestXmlMessage.CreateBuilder()
  171. .SetValid(false)
  172. .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionText, " extension text value ! ")
  173. .Build(),
  174. @"{""valid"":false,""extension_text"":"" extension text value ! ""}"
  175. );
  176. }
  177. [Test]
  178. public void TestWithExtensionNumber()
  179. {
  180. FormatterAssert(
  181. TestXmlMessage.CreateBuilder()
  182. .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionMessage,
  183. new TestXmlExtension.Builder().SetNumber(42).Build())
  184. .Build(),
  185. @"{""number"":42}"
  186. );
  187. }
  188. [Test]
  189. public void TestWithExtensionArray()
  190. {
  191. FormatterAssert(
  192. TestXmlMessage.CreateBuilder()
  193. .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 100)
  194. .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 101)
  195. .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 102)
  196. .Build(),
  197. @"{""extension_number"":[100,101,102]}"
  198. );
  199. }
  200. [Test]
  201. public void TestWithExtensionEnum()
  202. {
  203. FormatterAssert(
  204. TestXmlMessage.CreateBuilder()
  205. .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionEnum, EnumOptions.ONE)
  206. .Build(),
  207. @"{""extension_enum"":""ONE""}"
  208. );
  209. }
  210. [Test]
  211. public void TestMessageWithExtensions()
  212. {
  213. FormatterAssert(
  214. TestXmlMessage.CreateBuilder()
  215. .SetValid(true)
  216. .SetText("text")
  217. .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionText, "extension text")
  218. .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionMessage, new TestXmlExtension.Builder().SetNumber(42).Build())
  219. .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 100)
  220. .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 101)
  221. .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 102)
  222. .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionEnum, EnumOptions.ONE)
  223. .Build(),
  224. @"""text"":""text""",
  225. @"""valid"":true",
  226. @"""extension_enum"":""ONE""",
  227. @"""extension_text"":""extension text""",
  228. @"""extension_number"":[100,101,102]",
  229. @"""extension_message"":{""number"":42}"
  230. );
  231. }
  232. [Test]
  233. public void TestMessageMissingExtensions()
  234. {
  235. TestXmlMessage original = TestXmlMessage.CreateBuilder()
  236. .SetValid(true)
  237. .SetText("text")
  238. .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionText, " extension text value ! ")
  239. .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionMessage, new TestXmlExtension.Builder().SetNumber(42).Build())
  240. .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 100)
  241. .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 101)
  242. .AddExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber, 102)
  243. .SetExtension(UnitTestXmlSerializerTestProtoFile.ExtensionEnum, EnumOptions.ONE)
  244. .Build();
  245. TestXmlMessage message = original.ToBuilder()
  246. .ClearExtension(UnitTestXmlSerializerTestProtoFile.ExtensionText)
  247. .ClearExtension(UnitTestXmlSerializerTestProtoFile.ExtensionMessage)
  248. .ClearExtension(UnitTestXmlSerializerTestProtoFile.ExtensionNumber)
  249. .ClearExtension(UnitTestXmlSerializerTestProtoFile.ExtensionEnum)
  250. .Build();
  251. JsonFormatWriter writer = JsonFormatWriter.CreateInstance();
  252. writer.WriteMessage(original);
  253. Content = writer.ToString();
  254. IMessageLite copy = JsonFormatReader.CreateInstance(Content)
  255. .Merge(message.CreateBuilderForType()).Build();
  256. Assert.AreNotEqual(original, message);
  257. Assert.AreNotEqual(original, copy);
  258. Assert.AreEqual(message, copy);
  259. }
  260. [Test]
  261. public void TestMergeFields()
  262. {
  263. TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
  264. builder.MergeFrom(JsonFormatReader.CreateInstance("\"valid\": true"));
  265. builder.MergeFrom(JsonFormatReader.CreateInstance("\"text\": \"text\", \"number\": \"411\""));
  266. Assert.AreEqual(true, builder.Valid);
  267. Assert.AreEqual("text", builder.Text);
  268. Assert.AreEqual(411, builder.Number);
  269. }
  270. [Test]
  271. public void TestMessageArray()
  272. {
  273. JsonFormatWriter writer = JsonFormatWriter.CreateInstance().Formatted();
  274. using (writer.StartArray())
  275. {
  276. writer.WriteMessage(TestXmlMessage.CreateBuilder().SetNumber(1).AddTextlines("a").Build());
  277. writer.WriteMessage(TestXmlMessage.CreateBuilder().SetNumber(2).AddTextlines("b").Build());
  278. writer.WriteMessage(TestXmlMessage.CreateBuilder().SetNumber(3).AddTextlines("c").Build());
  279. }
  280. string json = writer.ToString();
  281. JsonFormatReader reader = JsonFormatReader.CreateInstance(json);
  282. TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
  283. int ordinal = 0;
  284. foreach (JsonFormatReader r in reader.EnumerateArray())
  285. {
  286. r.Merge(builder);
  287. Assert.AreEqual(++ordinal, builder.Number);
  288. }
  289. Assert.AreEqual(3, ordinal);
  290. Assert.AreEqual(3, builder.TextlinesCount);
  291. }
  292. [Test]
  293. public void TestNestedMessageArray()
  294. {
  295. JsonFormatWriter writer = JsonFormatWriter.CreateInstance();
  296. using (writer.StartArray())
  297. {
  298. using (writer.StartArray())
  299. {
  300. writer.WriteMessage(TestXmlMessage.CreateBuilder().SetNumber(1).AddTextlines("a").Build());
  301. writer.WriteMessage(TestXmlMessage.CreateBuilder().SetNumber(2).AddTextlines("b").Build());
  302. }
  303. using (writer.StartArray())
  304. writer.WriteMessage(TestXmlMessage.CreateBuilder().SetNumber(3).AddTextlines("c").Build());
  305. }
  306. string json = writer.ToString();
  307. JsonFormatReader reader = JsonFormatReader.CreateInstance(json);
  308. TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
  309. int ordinal = 0;
  310. foreach (JsonFormatReader r in reader.EnumerateArray())
  311. foreach (JsonFormatReader r2 in r.EnumerateArray())
  312. {
  313. r2.Merge(builder);
  314. Assert.AreEqual(++ordinal, builder.Number);
  315. }
  316. Assert.AreEqual(3, ordinal);
  317. Assert.AreEqual(3, builder.TextlinesCount);
  318. }
  319. [Test, ExpectedException(typeof(FormatException))]
  320. public void FailWithEmptyText()
  321. {
  322. JsonFormatReader.CreateInstance("")
  323. .Merge(TestXmlMessage.CreateBuilder());
  324. }
  325. [Test, ExpectedException(typeof(FormatException))]
  326. public void FailWithUnexpectedValue()
  327. {
  328. JsonFormatReader.CreateInstance("{{}}")
  329. .Merge(TestXmlMessage.CreateBuilder());
  330. }
  331. [Test, ExpectedException(typeof(FormatException))]
  332. public void FailWithUnQuotedName()
  333. {
  334. JsonFormatReader.CreateInstance("{name:{}}")
  335. .Merge(TestXmlMessage.CreateBuilder());
  336. }
  337. [Test, ExpectedException(typeof(FormatException))]
  338. public void FailWithUnexpectedType()
  339. {
  340. JsonFormatReader.CreateInstance("{\"valid\":{}}")
  341. .Merge(TestXmlMessage.CreateBuilder());
  342. }
  343. }
  344. }