PageRenderTime 28ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/src/JsonFx.Tests/Model/ModelWalkerTests.cs

http://github.com/jsonfx/jsonfx
C# | 1088 lines | 905 code | 150 blank | 33 comment | 0 complexity | c3925b1b19349c609dd5cc877384df70 MD5 | raw file
  1. #region License
  2. /*---------------------------------------------------------------------------------*\
  3. Distributed under the terms of an MIT-style license:
  4. The MIT License
  5. Copyright (c) 2006-2010 Stephen M. McKamey
  6. Permission is hereby granted, free of charge, to any person obtaining a copy
  7. of this software and associated documentation files (the "Software"), to deal
  8. in the Software without restriction, including without limitation the rights
  9. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. copies of the Software, and to permit persons to whom the Software is
  11. furnished to do so, subject to the following conditions:
  12. The above copyright notice and this permission notice shall be included in
  13. all copies or substantial portions of the Software.
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. THE SOFTWARE.
  21. \*---------------------------------------------------------------------------------*/
  22. #endregion License
  23. using System;
  24. using System.Collections.Generic;
  25. using System.Dynamic;
  26. using System.Linq;
  27. using JsonFx.Model;
  28. using JsonFx.Serialization.GraphCycles;
  29. using Xunit;
  30. using Assert=JsonFx.AssertPatched;
  31. namespace JsonFx.Serialization
  32. {
  33. public class ModelWalkerTests
  34. {
  35. #region Constants
  36. private const string TraitName = "Common Model";
  37. private const string TraitValue = "Walker";
  38. #endregion Constants
  39. #region Test Types
  40. public class Person
  41. {
  42. public string Name { get; set; }
  43. public Person Father { get; set; }
  44. public Person Mother { get; set; }
  45. public Person[] Children { get; set; }
  46. }
  47. public class DynamicExample : DynamicObject
  48. {
  49. internal readonly Dictionary<string, object> Values = new Dictionary<string, object>();
  50. public override IEnumerable<string> GetDynamicMemberNames()
  51. {
  52. return Values.Keys;
  53. }
  54. public override bool TryDeleteMember(DeleteMemberBinder binder)
  55. {
  56. return this.Values.Remove(binder.Name);
  57. }
  58. public override bool TryGetMember(GetMemberBinder binder, out object result)
  59. {
  60. return this.Values.TryGetValue(binder.Name, out result);
  61. }
  62. public override bool TrySetMember(SetMemberBinder binder, object value)
  63. {
  64. this.Values[binder.Name] = value;
  65. return true;
  66. }
  67. }
  68. #endregion Test Types
  69. #region Array Tests
  70. [Fact]
  71. [Trait(TraitName, TraitValue)]
  72. public void GetTokens_ArrayEmpty_ReturnsEmptyArrayTokens()
  73. {
  74. var input = new object[0];
  75. var expected = new[]
  76. {
  77. ModelGrammar.TokenArrayBegin("array"),
  78. ModelGrammar.TokenArrayEnd
  79. };
  80. var walker = new ModelWalker(new DataWriterSettings());
  81. var actual = walker.GetTokens(input).ToArray();
  82. Assert.Equal(expected, actual);
  83. }
  84. [Fact]
  85. [Trait(TraitName, TraitValue)]
  86. public void GetTokens_ListEmpty_ReturnsEmptyArrayTokens()
  87. {
  88. var input = new List<object>(0);
  89. var expected = new[]
  90. {
  91. ModelGrammar.TokenArrayBegin("array"),
  92. ModelGrammar.TokenArrayEnd
  93. };
  94. var walker = new ModelWalker(new DataWriterSettings());
  95. var actual = walker.GetTokens(input).ToArray();
  96. Assert.Equal(expected, actual);
  97. }
  98. [Fact]
  99. [Trait(TraitName, TraitValue)]
  100. public void GetTokens_ArraySingleItem_ReturnsSingleItemArrayTokens()
  101. {
  102. var input = new object[]
  103. {
  104. null
  105. };
  106. var expected = new[]
  107. {
  108. ModelGrammar.TokenArrayBegin("array"),
  109. ModelGrammar.TokenNull,
  110. ModelGrammar.TokenArrayEnd
  111. };
  112. var walker = new ModelWalker(new DataWriterSettings());
  113. var actual = walker.GetTokens(input).ToArray();
  114. Assert.Equal(expected, actual);
  115. }
  116. [Fact]
  117. [Trait(TraitName, TraitValue)]
  118. public void GetTokens_ArrayMultiItem_ReturnsArrayTokens()
  119. {
  120. var input = new object[]
  121. {
  122. false,
  123. true,
  124. null,
  125. 'a',
  126. 'b',
  127. 'c',
  128. 1,
  129. 2,
  130. 3
  131. };
  132. var expected = new[]
  133. {
  134. ModelGrammar.TokenArrayBegin("array"),
  135. ModelGrammar.TokenFalse,
  136. ModelGrammar.TokenTrue,
  137. ModelGrammar.TokenNull,
  138. ModelGrammar.TokenPrimitive('a'),
  139. ModelGrammar.TokenPrimitive('b'),
  140. ModelGrammar.TokenPrimitive('c'),
  141. ModelGrammar.TokenPrimitive(1),
  142. ModelGrammar.TokenPrimitive(2),
  143. ModelGrammar.TokenPrimitive(3),
  144. ModelGrammar.TokenArrayEnd
  145. };
  146. var walker = new ModelWalker(new DataWriterSettings());
  147. var actual = walker.GetTokens(input).ToArray();
  148. Assert.Equal(expected, actual);
  149. }
  150. [Fact]
  151. [Trait(TraitName, TraitValue)]
  152. public void GetTokens_ArrayNested_ReturnsNestedArrayTokens()
  153. {
  154. var input = new object[]
  155. {
  156. false,
  157. true,
  158. null,
  159. new []
  160. {
  161. 'a',
  162. 'b',
  163. 'c'
  164. },
  165. new []
  166. {
  167. 1,
  168. 2,
  169. 3
  170. }
  171. };
  172. var expected = new[]
  173. {
  174. ModelGrammar.TokenArrayBegin("array"),
  175. ModelGrammar.TokenFalse,
  176. ModelGrammar.TokenTrue,
  177. ModelGrammar.TokenNull,
  178. ModelGrammar.TokenArrayBegin("array"),
  179. ModelGrammar.TokenPrimitive('a'),
  180. ModelGrammar.TokenPrimitive('b'),
  181. ModelGrammar.TokenPrimitive('c'),
  182. ModelGrammar.TokenArrayEnd,
  183. ModelGrammar.TokenArrayBegin("array"),
  184. ModelGrammar.TokenPrimitive(1),
  185. ModelGrammar.TokenPrimitive(2),
  186. ModelGrammar.TokenPrimitive(3),
  187. ModelGrammar.TokenArrayEnd,
  188. ModelGrammar.TokenArrayEnd
  189. };
  190. var walker = new ModelWalker(new DataWriterSettings());
  191. var actual = walker.GetTokens(input).ToArray();
  192. Assert.Equal(expected, actual);
  193. }
  194. #endregion Array Tests
  195. #region Object Tests
  196. [Fact]
  197. [Trait(TraitName, TraitValue)]
  198. public void GetTokens_EmptyObject_ReturnsEmptyObjectTokens()
  199. {
  200. var input = new object();
  201. var expected = new[]
  202. {
  203. ModelGrammar.TokenObjectBegin("object"),
  204. ModelGrammar.TokenObjectEnd
  205. };
  206. var walker = new ModelWalker(new DataWriterSettings());
  207. var actual = walker.GetTokens(input).ToArray();
  208. Assert.Equal(expected, actual);
  209. }
  210. [Fact]
  211. [Trait(TraitName, TraitValue)]
  212. public void GetTokens_EmptyDictionary_ReturnsEmptyObjectTokens()
  213. {
  214. var input = new Dictionary<string, object>(0);
  215. var expected = new[]
  216. {
  217. ModelGrammar.TokenObjectBegin("object"),
  218. ModelGrammar.TokenObjectEnd
  219. };
  220. var walker = new ModelWalker(new DataWriterSettings());
  221. var actual = walker.GetTokens(input).ToArray();
  222. Assert.Equal(expected, actual);
  223. }
  224. [Fact]
  225. [Trait(TraitName, TraitValue)]
  226. public void GetTokens_ObjectAnonymous_ReturnsObjectTokens()
  227. {
  228. var input = new
  229. {
  230. One = 1,
  231. Two = 2,
  232. Three = 3,
  233. Four = new
  234. {
  235. A = 'a',
  236. B = 'b',
  237. C = 'c'
  238. }
  239. };
  240. var expected = new[]
  241. {
  242. ModelGrammar.TokenObjectBegin("object"),
  243. ModelGrammar.TokenProperty("One"),
  244. ModelGrammar.TokenPrimitive(1),
  245. ModelGrammar.TokenProperty("Two"),
  246. ModelGrammar.TokenPrimitive(2),
  247. ModelGrammar.TokenProperty("Three"),
  248. ModelGrammar.TokenPrimitive(3),
  249. ModelGrammar.TokenProperty("Four"),
  250. ModelGrammar.TokenObjectBegin("object"),
  251. ModelGrammar.TokenProperty("A"),
  252. ModelGrammar.TokenPrimitive('a'),
  253. ModelGrammar.TokenProperty("B"),
  254. ModelGrammar.TokenPrimitive('b'),
  255. ModelGrammar.TokenProperty("C"),
  256. ModelGrammar.TokenPrimitive('c'),
  257. ModelGrammar.TokenObjectEnd,
  258. ModelGrammar.TokenObjectEnd
  259. };
  260. var walker = new ModelWalker(new DataWriterSettings());
  261. var actual = walker.GetTokens(input).ToArray();
  262. Assert.Equal(expected, actual);
  263. }
  264. [Fact]
  265. [Trait(TraitName, TraitValue)]
  266. public void GetTokens_ObjectDictionary_ReturnsObjectTokens()
  267. {
  268. var input = new Dictionary<string, object>
  269. {
  270. { "One", 1 },
  271. { "Two", 2 },
  272. { "Three", 3 }
  273. };
  274. var expected = new[]
  275. {
  276. ModelGrammar.TokenObjectBegin("object"),
  277. ModelGrammar.TokenProperty("One"),
  278. ModelGrammar.TokenPrimitive(1),
  279. ModelGrammar.TokenProperty("Two"),
  280. ModelGrammar.TokenPrimitive(2),
  281. ModelGrammar.TokenProperty("Three"),
  282. ModelGrammar.TokenPrimitive(3),
  283. ModelGrammar.TokenObjectEnd
  284. };
  285. var walker = new ModelWalker(new DataWriterSettings());
  286. var actual = walker.GetTokens(input).ToArray();
  287. Assert.Equal(expected, actual);
  288. }
  289. #endregion Object Tests
  290. #region Boolean Tests
  291. [Fact]
  292. [Trait(TraitName, TraitValue)]
  293. public void GetTokens_False_ReturnsFalseToken()
  294. {
  295. var input = false;
  296. var expected = new[]
  297. {
  298. ModelGrammar.TokenFalse
  299. };
  300. var walker = new ModelWalker(new DataWriterSettings());
  301. var actual = walker.GetTokens(input).ToArray();
  302. Assert.Equal(expected, actual);
  303. }
  304. [Fact]
  305. [Trait(TraitName, TraitValue)]
  306. public void GetTokens_True_ReturnsTrueToken()
  307. {
  308. var input = true;
  309. var expected = new[]
  310. {
  311. ModelGrammar.TokenTrue
  312. };
  313. var walker = new ModelWalker(new DataWriterSettings());
  314. var actual = walker.GetTokens(input).ToArray();
  315. Assert.Equal(expected, actual);
  316. }
  317. #endregion Boolean Tests
  318. #region Number Case Tests
  319. [Fact]
  320. [Trait(TraitName, TraitValue)]
  321. public void GetTokens_DoubleNaN_ReturnsNaNToken()
  322. {
  323. var input = Double.NaN;
  324. var expected = new[]
  325. {
  326. ModelGrammar.TokenPrimitive(Double.NaN)
  327. };
  328. var walker = new ModelWalker(new DataWriterSettings());
  329. var actual = walker.GetTokens(input).ToArray();
  330. Assert.Equal(expected, actual);
  331. }
  332. [Fact]
  333. [Trait(TraitName, TraitValue)]
  334. public void GetTokens_DoublePosInfinity_ReturnsPosInfinityToken()
  335. {
  336. var input = Double.PositiveInfinity;
  337. var expected = new[]
  338. {
  339. ModelGrammar.TokenPrimitive(Double.PositiveInfinity)
  340. };
  341. var walker = new ModelWalker(new DataWriterSettings());
  342. var actual = walker.GetTokens(input).ToArray();
  343. Assert.Equal(expected, actual);
  344. }
  345. [Fact]
  346. [Trait(TraitName, TraitValue)]
  347. public void GetTokens_DoubleNegInfinity_ReturnsNegInfinityToken()
  348. {
  349. var input = Double.NegativeInfinity;
  350. var expected = new[]
  351. {
  352. ModelGrammar.TokenPrimitive(Double.NegativeInfinity)
  353. };
  354. var walker = new ModelWalker(new DataWriterSettings());
  355. var actual = walker.GetTokens(input).ToArray();
  356. Assert.Equal(expected, actual);
  357. }
  358. [Fact]
  359. [Trait(TraitName, TraitValue)]
  360. public void GetTokens_SingleNaN_ReturnsNaNToken()
  361. {
  362. var input = Single.NaN;
  363. var expected = new[]
  364. {
  365. ModelGrammar.TokenPrimitive(Double.NaN)
  366. };
  367. var walker = new ModelWalker(new DataWriterSettings());
  368. var actual = walker.GetTokens(input).ToArray();
  369. Assert.Equal(expected, actual);
  370. }
  371. [Fact]
  372. [Trait(TraitName, TraitValue)]
  373. public void GetTokens_SinglePosInfinity_ReturnsPosInfinityToken()
  374. {
  375. var input = Single.PositiveInfinity;
  376. var expected = new[]
  377. {
  378. ModelGrammar.TokenPrimitive(Double.PositiveInfinity)
  379. };
  380. var walker = new ModelWalker(new DataWriterSettings());
  381. var actual = walker.GetTokens(input).ToArray();
  382. Assert.Equal(expected, actual);
  383. }
  384. [Fact]
  385. [Trait(TraitName, TraitValue)]
  386. public void GetTokens_SingleNegInfinity_ReturnsNegInfinityToken()
  387. {
  388. var input = Single.NegativeInfinity;
  389. var expected = new[]
  390. {
  391. ModelGrammar.TokenPrimitive(Double.NegativeInfinity)
  392. };
  393. var walker = new ModelWalker(new DataWriterSettings());
  394. var actual = walker.GetTokens(input).ToArray();
  395. Assert.Equal(expected, actual);
  396. }
  397. #endregion Number Tests
  398. #region Dynamic Tests
  399. [Fact]
  400. [Trait(TraitName, TraitValue)]
  401. public void GetTokens_ExpandoObject_ReturnsObjectTokens()
  402. {
  403. dynamic input = new ExpandoObject();
  404. input.One = 1;
  405. input.Two = 2;
  406. input.Three = 3;
  407. var expected = new[]
  408. {
  409. ModelGrammar.TokenObjectBegin("object"),
  410. ModelGrammar.TokenProperty("One"),
  411. ModelGrammar.TokenPrimitive(1),
  412. ModelGrammar.TokenProperty("Two"),
  413. ModelGrammar.TokenPrimitive(2),
  414. ModelGrammar.TokenProperty("Three"),
  415. ModelGrammar.TokenPrimitive(3),
  416. ModelGrammar.TokenObjectEnd
  417. };
  418. var walker = new ModelWalker(new DataWriterSettings());
  419. var actual = walker.GetTokens((object)input).ToArray();
  420. Assert.Equal(expected, actual);
  421. }
  422. [Fact]
  423. [Trait(TraitName, TraitValue)]
  424. public void GetTokens_ExpandoObjectNested_ReturnsObjectTokens()
  425. {
  426. dynamic input = new ExpandoObject();
  427. input.foo = true;
  428. input.array = new object[]
  429. {
  430. false, 1, 2, Math.PI, null, "hello world."
  431. };
  432. var expected = new[]
  433. {
  434. ModelGrammar.TokenObjectBegin("object"),
  435. ModelGrammar.TokenProperty("foo"),
  436. ModelGrammar.TokenPrimitive(true),
  437. ModelGrammar.TokenProperty("array"),
  438. ModelGrammar.TokenArrayBegin("array"),
  439. ModelGrammar.TokenPrimitive(false),
  440. ModelGrammar.TokenPrimitive(1),
  441. ModelGrammar.TokenPrimitive(2),
  442. ModelGrammar.TokenPrimitive(Math.PI),
  443. ModelGrammar.TokenPrimitive(null),
  444. ModelGrammar.TokenPrimitive("hello world."),
  445. ModelGrammar.TokenArrayEnd,
  446. ModelGrammar.TokenObjectEnd
  447. };
  448. var walker = new ModelWalker(new DataWriterSettings());
  449. var actual = walker.GetTokens(input).ToArray();
  450. Assert.Equal(expected, actual);
  451. }
  452. [Fact]
  453. [Trait(TraitName, TraitValue)]
  454. public void GetTokens_DynamicExample_ReturnsDynamicObject()
  455. {
  456. dynamic input = new DynamicExample();
  457. input.foo = "hello world";
  458. input.number = 42;
  459. input.boolean = false;
  460. input.@null = null;
  461. var expected = new[]
  462. {
  463. ModelGrammar.TokenObjectBegin("DynamicExample"),
  464. ModelGrammar.TokenProperty("foo"),
  465. ModelGrammar.TokenPrimitive("hello world"),
  466. ModelGrammar.TokenProperty("number"),
  467. ModelGrammar.TokenPrimitive(42),
  468. ModelGrammar.TokenProperty("boolean"),
  469. ModelGrammar.TokenPrimitive(false),
  470. ModelGrammar.TokenProperty("null"),
  471. ModelGrammar.TokenPrimitive(null),
  472. ModelGrammar.TokenObjectEnd
  473. };
  474. var walker = new ModelWalker(new DataWriterSettings());
  475. var actual = walker.GetTokens(input).ToArray();
  476. Assert.Equal(expected, actual, false);
  477. }
  478. #endregion Dynamic Tests
  479. #region Complex Graph Tests
  480. [Fact]
  481. [Trait(TraitName, TraitValue)]
  482. public void GetTokens_GraphComplex_ReturnsObjectTokens()
  483. {
  484. var input = new object[] {
  485. "JSON Test Pattern pass1",
  486. new Dictionary<string, object>
  487. {
  488. { "object with 1 member", new[] { "array with 1 element" } },
  489. },
  490. new Dictionary<string, object>(),
  491. new object[0],
  492. -42,
  493. true,
  494. false,
  495. null,
  496. new Dictionary<string, object> {
  497. { "integer", 1234567890 },
  498. { "real", -9876.543210 },
  499. { "e", 0.123456789e-12 },
  500. { "E", 1.234567890E+34 },
  501. { "", 23456789012E66 },
  502. { "zero", 0 },
  503. { "one", 1 },
  504. { "space", " " },
  505. { "quote", "\"" },
  506. { "backslash", "\\" },
  507. { "controls", "\b\f\n\r\t" },
  508. { "slash", "/ & /" },
  509. { "alpha", "abcdefghijklmnopqrstuvwyz" },
  510. { "ALPHA", "ABCDEFGHIJKLMNOPQRSTUVWYZ" },
  511. { "digit", "0123456789" },
  512. { "0123456789", "digit" },
  513. { "special", "`1~!@#$%^&*()_+-={':[,]}|;.</>?" },
  514. { "hex", "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A" },
  515. { "true", true },
  516. { "false", false },
  517. { "null", null },
  518. { "array", new object[0] },
  519. { "object", new Dictionary<string, object>() },
  520. { "address", "50 St. James Street" },
  521. { "url", "http://www.JSON.org/" },
  522. { "comment", "// /* <!-- --" },
  523. { "# -- --> */", " " },
  524. { " s p a c e d ", new [] { 1,2,3,4,5,6,7 } },
  525. { "compact", new [] { 1,2,3,4,5,6,7 } },
  526. { "jsontext", "{\"object with 1 member\":[\"array with 1 element\"]}" },
  527. { "quotes", "&#34; \u0022 %22 0x22 034 &#x22;" },
  528. { "/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?", "A key can be any string" }
  529. },
  530. 0.5,
  531. 98.6,
  532. 99.44,
  533. 1066,
  534. 1e1,
  535. 0.1e1,
  536. 1e-1,
  537. 1e00,
  538. 2e+00,
  539. 2e-00,
  540. "rosebud"
  541. };
  542. var expected = new[]
  543. {
  544. ModelGrammar.TokenArrayBegin("array"),
  545. ModelGrammar.TokenPrimitive("JSON Test Pattern pass1"),
  546. ModelGrammar.TokenObjectBegin("object"),
  547. ModelGrammar.TokenProperty("object with 1 member"),
  548. ModelGrammar.TokenArrayBegin("array"),
  549. ModelGrammar.TokenPrimitive("array with 1 element"),
  550. ModelGrammar.TokenArrayEnd,
  551. ModelGrammar.TokenObjectEnd,
  552. ModelGrammar.TokenObjectBegin("object"),
  553. ModelGrammar.TokenObjectEnd,
  554. ModelGrammar.TokenArrayBegin("array"),
  555. ModelGrammar.TokenArrayEnd,
  556. ModelGrammar.TokenPrimitive(-42),
  557. ModelGrammar.TokenTrue,
  558. ModelGrammar.TokenFalse,
  559. ModelGrammar.TokenNull,
  560. ModelGrammar.TokenObjectBegin("object"),
  561. ModelGrammar.TokenProperty("integer"),
  562. ModelGrammar.TokenPrimitive(1234567890),
  563. ModelGrammar.TokenProperty("real"),
  564. ModelGrammar.TokenPrimitive(-9876.543210),
  565. ModelGrammar.TokenProperty("e"),
  566. ModelGrammar.TokenPrimitive(0.123456789e-12),
  567. ModelGrammar.TokenProperty("E"),
  568. ModelGrammar.TokenPrimitive(1.234567890E+34),
  569. ModelGrammar.TokenProperty(""),
  570. ModelGrammar.TokenPrimitive(23456789012E66),
  571. ModelGrammar.TokenProperty("zero"),
  572. ModelGrammar.TokenPrimitive(0),
  573. ModelGrammar.TokenProperty("one"),
  574. ModelGrammar.TokenPrimitive(1),
  575. ModelGrammar.TokenProperty("space"),
  576. ModelGrammar.TokenPrimitive(" "),
  577. ModelGrammar.TokenProperty("quote"),
  578. ModelGrammar.TokenPrimitive("\""),
  579. ModelGrammar.TokenProperty("backslash"),
  580. ModelGrammar.TokenPrimitive("\\"),
  581. ModelGrammar.TokenProperty("controls"),
  582. ModelGrammar.TokenPrimitive("\b\f\n\r\t"),
  583. ModelGrammar.TokenProperty("slash"),
  584. ModelGrammar.TokenPrimitive("/ & /"),
  585. ModelGrammar.TokenProperty("alpha"),
  586. ModelGrammar.TokenPrimitive("abcdefghijklmnopqrstuvwyz"),
  587. ModelGrammar.TokenProperty("ALPHA"),
  588. ModelGrammar.TokenPrimitive("ABCDEFGHIJKLMNOPQRSTUVWYZ"),
  589. ModelGrammar.TokenProperty("digit"),
  590. ModelGrammar.TokenPrimitive("0123456789"),
  591. ModelGrammar.TokenProperty("0123456789"),
  592. ModelGrammar.TokenPrimitive("digit"),
  593. ModelGrammar.TokenProperty("special"),
  594. ModelGrammar.TokenPrimitive("`1~!@#$%^&*()_+-={':[,]}|;.</>?"),
  595. ModelGrammar.TokenProperty("hex"),
  596. ModelGrammar.TokenPrimitive("\u0123\u4567\u89AB\uCDEF\uabcd\uef4A"),
  597. ModelGrammar.TokenProperty("true"),
  598. ModelGrammar.TokenTrue,
  599. ModelGrammar.TokenProperty("false"),
  600. ModelGrammar.TokenFalse,
  601. ModelGrammar.TokenProperty("null"),
  602. ModelGrammar.TokenNull,
  603. ModelGrammar.TokenProperty("array"),
  604. ModelGrammar.TokenArrayBegin("array"),
  605. ModelGrammar.TokenArrayEnd,
  606. ModelGrammar.TokenProperty("object"),
  607. ModelGrammar.TokenObjectBegin("object"),
  608. ModelGrammar.TokenObjectEnd,
  609. ModelGrammar.TokenProperty("address"),
  610. ModelGrammar.TokenPrimitive("50 St. James Street"),
  611. ModelGrammar.TokenProperty("url"),
  612. ModelGrammar.TokenPrimitive("http://www.JSON.org/"),
  613. ModelGrammar.TokenProperty("comment"),
  614. ModelGrammar.TokenPrimitive("// /* <!-- --"),
  615. ModelGrammar.TokenProperty("# -- --> */"),
  616. ModelGrammar.TokenPrimitive(" "),
  617. ModelGrammar.TokenProperty(" s p a c e d "),
  618. ModelGrammar.TokenArrayBegin("array"),
  619. ModelGrammar.TokenPrimitive(1),
  620. ModelGrammar.TokenPrimitive(2),
  621. ModelGrammar.TokenPrimitive(3),
  622. ModelGrammar.TokenPrimitive(4),
  623. ModelGrammar.TokenPrimitive(5),
  624. ModelGrammar.TokenPrimitive(6),
  625. ModelGrammar.TokenPrimitive(7),
  626. ModelGrammar.TokenArrayEnd,
  627. ModelGrammar.TokenProperty("compact"),
  628. ModelGrammar.TokenArrayBegin("array"),
  629. ModelGrammar.TokenPrimitive(1),
  630. ModelGrammar.TokenPrimitive(2),
  631. ModelGrammar.TokenPrimitive(3),
  632. ModelGrammar.TokenPrimitive(4),
  633. ModelGrammar.TokenPrimitive(5),
  634. ModelGrammar.TokenPrimitive(6),
  635. ModelGrammar.TokenPrimitive(7),
  636. ModelGrammar.TokenArrayEnd,
  637. ModelGrammar.TokenProperty("jsontext"),
  638. ModelGrammar.TokenPrimitive("{\"object with 1 member\":[\"array with 1 element\"]}"),
  639. ModelGrammar.TokenProperty("quotes"),
  640. ModelGrammar.TokenPrimitive("&#34; \u0022 %22 0x22 034 &#x22;"),
  641. ModelGrammar.TokenProperty("/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"),
  642. ModelGrammar.TokenPrimitive("A key can be any string"),
  643. ModelGrammar.TokenObjectEnd,
  644. ModelGrammar.TokenPrimitive(0.5),
  645. ModelGrammar.TokenPrimitive(98.6),
  646. ModelGrammar.TokenPrimitive(99.44),
  647. ModelGrammar.TokenPrimitive(1066),
  648. ModelGrammar.TokenPrimitive(10.0),
  649. ModelGrammar.TokenPrimitive(1.0),
  650. ModelGrammar.TokenPrimitive(0.1),
  651. ModelGrammar.TokenPrimitive(1.0),
  652. ModelGrammar.TokenPrimitive(2.0),
  653. ModelGrammar.TokenPrimitive(2.0),
  654. ModelGrammar.TokenPrimitive("rosebud"),
  655. ModelGrammar.TokenArrayEnd
  656. };
  657. var walker = new ModelWalker(new DataWriterSettings());
  658. var actual = walker.GetTokens(input).ToArray();
  659. Assert.Equal(expected, actual);
  660. }
  661. #endregion Complex Graph Tests
  662. #region Graph Cycles Tests
  663. [Fact]
  664. [Trait(TraitName, TraitValue)]
  665. public void GetTokens_GraphCycleTypeIgnore_ReplacesCycleStartWithNull()
  666. {
  667. var input = new Person
  668. {
  669. Name = "John, Jr.",
  670. Father = new Person
  671. {
  672. Name = "John, Sr."
  673. },
  674. Mother = new Person
  675. {
  676. Name = "Sally"
  677. }
  678. };
  679. // create multiple cycles
  680. input.Father.Children = input.Mother.Children = new Person[]
  681. {
  682. input
  683. };
  684. var walker = new ModelWalker(new DataWriterSettings
  685. {
  686. GraphCycles = GraphCycleType.Ignore
  687. });
  688. var expected = new[]
  689. {
  690. ModelGrammar.TokenObjectBegin("Person"),
  691. ModelGrammar.TokenProperty("Name"),
  692. ModelGrammar.TokenPrimitive("John, Jr."),
  693. ModelGrammar.TokenProperty("Father"),
  694. ModelGrammar.TokenObjectBegin("Person"),
  695. ModelGrammar.TokenProperty("Name"),
  696. ModelGrammar.TokenPrimitive("John, Sr."),
  697. ModelGrammar.TokenProperty("Father"),
  698. ModelGrammar.TokenNull,
  699. ModelGrammar.TokenProperty("Mother"),
  700. ModelGrammar.TokenNull,
  701. ModelGrammar.TokenProperty("Children"),
  702. ModelGrammar.TokenArrayBegin("array"),
  703. ModelGrammar.TokenNull,
  704. ModelGrammar.TokenArrayEnd,
  705. ModelGrammar.TokenObjectEnd,
  706. ModelGrammar.TokenProperty("Mother"),
  707. ModelGrammar.TokenObjectBegin("Person"),
  708. ModelGrammar.TokenProperty("Name"),
  709. ModelGrammar.TokenPrimitive("Sally"),
  710. ModelGrammar.TokenProperty("Father"),
  711. ModelGrammar.TokenNull,
  712. ModelGrammar.TokenProperty("Mother"),
  713. ModelGrammar.TokenNull,
  714. ModelGrammar.TokenProperty("Children"),
  715. ModelGrammar.TokenArrayBegin("array"),
  716. ModelGrammar.TokenNull,
  717. ModelGrammar.TokenArrayEnd,
  718. ModelGrammar.TokenObjectEnd,
  719. ModelGrammar.TokenProperty("Children"),
  720. ModelGrammar.TokenNull,
  721. ModelGrammar.TokenObjectEnd
  722. };
  723. var actual = walker.GetTokens(input).ToArray();
  724. Assert.Equal(expected, actual);
  725. }
  726. [Fact]
  727. [Trait(TraitName, TraitValue)]
  728. public void GetTokens_GraphCycleTypeReferences_ThrowsGraphCycleException()
  729. {
  730. var input = new Person
  731. {
  732. Name = "John, Jr.",
  733. Father = new Person
  734. {
  735. Name = "John, Sr."
  736. },
  737. Mother = new Person
  738. {
  739. Name = "Sally"
  740. }
  741. };
  742. // create multiple cycles
  743. input.Father.Children = input.Mother.Children = new Person[]
  744. {
  745. input
  746. };
  747. var walker = new ModelWalker(new DataWriterSettings
  748. {
  749. GraphCycles = GraphCycleType.Reference
  750. });
  751. GraphCycleException ex = Assert.Throws<GraphCycleException>(
  752. delegate
  753. {
  754. walker.GetTokens(input).ToArray();
  755. });
  756. Assert.Equal(GraphCycleType.Reference, ex.CycleType);
  757. }
  758. [Fact]
  759. [Trait(TraitName, TraitValue)]
  760. public void GetTokens_GraphCycleTypeMaxDepth_ThrowsGraphCycleException()
  761. {
  762. var input = new Person
  763. {
  764. Name = "John, Jr.",
  765. Father = new Person
  766. {
  767. Name = "John, Sr."
  768. },
  769. Mother = new Person
  770. {
  771. Name = "Sally"
  772. }
  773. };
  774. // create multiple cycles
  775. input.Father.Children = input.Mother.Children = new Person[]
  776. {
  777. input
  778. };
  779. var walker = new ModelWalker(new DataWriterSettings
  780. {
  781. GraphCycles = GraphCycleType.MaxDepth,
  782. MaxDepth = 25
  783. });
  784. GraphCycleException ex = Assert.Throws<GraphCycleException>(
  785. delegate
  786. {
  787. walker.GetTokens(input).ToArray();
  788. });
  789. Assert.Equal(GraphCycleType.MaxDepth, ex.CycleType);
  790. }
  791. [Fact]
  792. [Trait(TraitName, TraitValue)]
  793. public void GetTokens_GraphCycleTypeMaxDepthNoMaxDepth_ThrowsArgumentException()
  794. {
  795. var input = new Person
  796. {
  797. Name = "John, Jr.",
  798. Father = new Person
  799. {
  800. Name = "John, Sr."
  801. },
  802. Mother = new Person
  803. {
  804. Name = "Sally"
  805. }
  806. };
  807. // create multiple cycles
  808. input.Father.Children = input.Mother.Children = new Person[]
  809. {
  810. input
  811. };
  812. var walker = new ModelWalker(new DataWriterSettings
  813. {
  814. GraphCycles = GraphCycleType.MaxDepth,
  815. MaxDepth = 0
  816. });
  817. ArgumentException ex = Assert.Throws<ArgumentException>(
  818. delegate
  819. {
  820. walker.GetTokens(input).ToArray();
  821. });
  822. Assert.Equal("maxDepth", ex.ParamName);
  823. }
  824. [Fact]
  825. [Trait(TraitName, TraitValue)]
  826. public void GetTokens_GraphCycleTypeMaxDepthFalsePositive_ThrowsGraphCycleException()
  827. {
  828. // input from fail18.json in test suite at http://www.json.org/JSON_checker/
  829. var input = new[]
  830. {
  831. new []
  832. {
  833. new []
  834. {
  835. new []
  836. {
  837. new []
  838. {
  839. new []
  840. {
  841. new []
  842. {
  843. new []
  844. {
  845. new []
  846. {
  847. new []
  848. {
  849. new []
  850. {
  851. new []
  852. {
  853. new []
  854. {
  855. new []
  856. {
  857. new []
  858. {
  859. new []
  860. {
  861. new []
  862. {
  863. new []
  864. {
  865. new []
  866. {
  867. new []
  868. {
  869. "Too deep"
  870. }
  871. }
  872. }
  873. }
  874. }
  875. }
  876. }
  877. }
  878. }
  879. }
  880. }
  881. }
  882. }
  883. }
  884. }
  885. }
  886. }
  887. }
  888. }
  889. };
  890. var walker = new ModelWalker(new DataWriterSettings
  891. {
  892. GraphCycles = GraphCycleType.MaxDepth,
  893. MaxDepth = 19
  894. });
  895. GraphCycleException ex = Assert.Throws<GraphCycleException>(
  896. delegate
  897. {
  898. walker.GetTokens(input).ToArray();
  899. });
  900. Assert.Equal(GraphCycleType.MaxDepth, ex.CycleType);
  901. }
  902. #endregion Graph Cycles Tests
  903. #region Input Edge Case Tests
  904. [Fact]
  905. [Trait(TraitName, TraitValue)]
  906. public void GetTokens_Null_ReturnsNullToken()
  907. {
  908. var input = (object)null;
  909. var expected = new[]
  910. {
  911. ModelGrammar.TokenNull
  912. };
  913. var walker = new ModelWalker(new DataWriterSettings());
  914. var actual = walker.GetTokens(input).ToArray();
  915. Assert.Equal(expected, actual);
  916. }
  917. [Fact]
  918. [Trait(TraitName, TraitValue)]
  919. public void Ctor_NullSettings_ThrowsArgumentNullException()
  920. {
  921. ArgumentNullException ex = Assert.Throws<ArgumentNullException>(
  922. delegate
  923. {
  924. var walker = new ModelWalker(null);
  925. });
  926. // verify exception is coming from expected param
  927. Assert.Equal("settings", ex.ParamName);
  928. }
  929. #endregion Input Edge Case Tests
  930. }
  931. }