XmlBinaryDictionaryWriterTest.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. //
  2. // XmlSimpleDictionaryWriterTest.cs
  3. //
  4. // Author:
  5. // Atsushi Enomoto <[email protected]>
  6. //
  7. // Copyright (C) 2005, 2007, 2009 Novell, Inc. http://www.novell.com
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining
  10. // a copy of this software and associated documentation files (the
  11. // "Software"), to deal in the Software without restriction, including
  12. // without limitation the rights to use, copy, modify, merge, publish,
  13. // distribute, sublicense, and/or sell copies of the Software, and to
  14. // permit persons to whom the Software is furnished to do so, subject to
  15. // the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be
  18. // included in all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  24. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  25. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. //
  28. using System;
  29. using System.IO;
  30. using System.Text;
  31. using System.Xml;
  32. using NUnit.Framework;
  33. using NUnit.Framework.Constraints;
  34. namespace MonoTests.System.Xml
  35. {
  36. [TestFixture]
  37. public class XmlBinaryDictionaryWriterTest
  38. {
  39. [Test]
  40. public void UseCase1 ()
  41. {
  42. Console.WriteLine ();
  43. MemoryStream ms = new MemoryStream ();
  44. XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter (ms, null, null);
  45. w.WriteStartDocument (true);
  46. w.WriteStartElement ("root");
  47. w.WriteAttributeString ("a", "");
  48. w.WriteComment ("");
  49. w.WriteWhitespace (" ");
  50. w.WriteStartElement ("AAA", "urn:AAA");
  51. w.WriteEndElement ();
  52. w.WriteStartElement ("ePfix", "AAA", "urn:AAABBB");
  53. w.WriteEndElement ();
  54. w.WriteStartElement ("AAA");
  55. w.WriteCData ("CCC\u3005\u4E00CCC");
  56. w.WriteString ("AAA&AAA");
  57. w.WriteRaw ("DDD&DDD");
  58. w.WriteCharEntity ('\u4E01');
  59. w.WriteComment ("COMMENT");
  60. w.WriteEndElement ();
  61. w.WriteStartElement ("AAA");
  62. w.WriteAttributeString ("BBB", "bbb");
  63. // mhm, how namespace URIs are serialized then?
  64. w.WriteAttributeString ("pfix", "BBB", "urn:bbb", "bbbbb");
  65. // 0x26-0x3F
  66. w.WriteAttributeString ("CCC", "urn:ccc", "ccccc");
  67. w.WriteAttributeString ("DDD", "urn:ddd", "ddddd");
  68. w.WriteAttributeString ("CCC", "urn:ddd", "cdcdc");
  69. // XmlLang
  70. w.WriteXmlAttribute ("lang", "ja");
  71. Assert.AreEqual ("ja", w.XmlLang, "XmlLang");
  72. // XmlSpace
  73. w.WriteStartAttribute ("xml", "space", "http://www.w3.org/XML/1998/namespace");
  74. w.WriteString ("pre");
  75. w.WriteString ("serve");
  76. w.WriteEndAttribute ();
  77. Assert.AreEqual (XmlSpace.Preserve, w.XmlSpace, "XmlSpace");
  78. w.WriteAttributeString ("xml", "base", "http://www.w3.org/XML/1998/namespace", "local:hogehoge");
  79. w.WriteString ("CCC");
  80. w.WriteBase64 (new byte [] {0x20, 0x20, 0x20, 0xFF, 0x80, 0x30}, 0, 6);
  81. w.WriteEndElement ();
  82. // this WriteEndElement() should result in one more
  83. // 0x3C, but .net does not output it.
  84. w.WriteEndElement ();
  85. w.WriteEndDocument ();
  86. w.Close ();
  87. Assert.AreEqual (usecase1_result, ms.ToArray ());
  88. }
  89. // $ : kind
  90. // ! : length
  91. static readonly byte [] usecase1_result = new byte [] {
  92. // $!root$! a....!__ ___.!AAA $!urn:AA A$$!ePfi
  93. 0x40, 4, 0x72, 0x6F, 0x6F, 0x74, 0x04, 1,
  94. 0x61, 0xA8, 0x02, 0x00, 0x98, 5, 0x20, 0x20,
  95. 0x20, 0x20, 0x20, 0x40, 3, 0x41, 0x41, 0x41,
  96. 0x08, 0x07, 0x75, 0x72, 0x6E, 0x3A, 0x41, 0x41,
  97. 0x41, 1, 0x41, 5, 0x65, 0x50, 0x66, 0x69,// 40
  98. // x!AAA$!e Pfix!urn :AAABBB$ $!AAA$!C CC(uni)$
  99. 0x78, 3, 0x41, 0x41, 0x41, 0x09, 5, 0x65,
  100. 0x50, 0x66, 0x69, 0x78, 10, 0x75, 0x72, 0x6E,
  101. 0x3A, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 1,
  102. 0x40, 3, 0x41, 0x41, 0x41, 0x98, 12, 0x43,
  103. 0x43, 0x43, 0xE3, 0x80, 0x85, 0xE4, 0xB8, 0x80,// 80
  104. // AAA$!DDD $AAA$!DD D$DDD... ..$!COMM ENT$$!AA
  105. 0x43, 0x43, 0x43, 0x98, 7, 0x41, 0x41, 0x41,
  106. 0x26, 0x41, 0x41, 0x41, 0x98, 7, 0x44, 0x44,
  107. 0x44, 0x26, 0x44, 0x44, 0x44, 0x98, 3, 0xE4,
  108. 0xB8, 0x81, 0x02, 7, 0x43, 0x4F, 0x4D, 0x4D,
  109. 0x45, 0x4E, 0x54, 0x01, 0x40, 3, 0x41, 0x41,// 120
  110. // A$!BBB$! bbb$!pfi x!BBB$!b bbbb$!CC C$!ccccc
  111. 0x41, 4, 0x03, 0x42, 0x42, 0x42, 0x98, 3,
  112. 0x62, 0x62, 0x62, 0x05, 0x04, 0x70, 0x66, 0x69,
  113. 0x78, 0x03, 0x42, 0x42, 0x42, 0x98, 0x05, 0x62,
  114. 0x62, 0x62, 0x62, 0x62, 0x26, 0x03, 0x43, 0x43,
  115. 0x43, 0x98, 0x05, 0x63, 0x63, 0x63, 0x63, 0x63,// 160
  116. // $!DDD$!d dddd$!cc c$!cdcdc $!xml!la ng$!ja$!
  117. 0x27, 0x03, 0x44, 0x44, 0x44, 0x98, 0x05, 0x64,
  118. 0x64, 0x64, 0x64, 0x64, 0x27, 0x03, 0x43, 0x43,
  119. 0x43, 0x98, 0x05, 0x63, 0x64, 0x63, 0x64, 0x63,
  120. 0x05, 0x03, 0x78, 0x6D, 0x6C, 0x04, 0x6C, 0x61,
  121. 0x6E, 0x67, 0x98, 0x02, 0x6A, 0x61, 0x05, 0x03,// 200
  122. // xml!spac e$!prese rve$!xml !lang$!l local:hog
  123. 0x78, 0x6D, 0x6C, 0x05, 0x73, 0x70, 0x61, 0x63,
  124. 0x65, 0x98, 0x08, 0x70, 0x72, 0x65, 0x73, 0x65,
  125. 0x72, 0x76, 0x65, 0x05, 0x03, 0x78, 0x6D, 0x6C,
  126. 0x04, 0x62, 0x61, 0x73, 0x65, 0x98, 0x0E, 0x6C,
  127. 0x6F, 0x63, 0x61, 0x6C, 0x3A, 0x68, 0x6F, 0x67,// 240
  128. // ehoge$!p fix!urn: bbb$!a!u rn:ccc$! b!urn:dd
  129. 0x65, 0x68, 0x6F, 0x67, 0x65, 0x09, 0x04, 0x70,
  130. 0x66, 0x69, 0x78, 0x07, 0x75, 0x72, 0x6E, 0x3A,
  131. 0x62, 0x62, 0x62, 0x09, 0x01, 0x61, 0x07, 0x75,
  132. 0x72, 0x6E, 0x3A, 0x63, 0x63, 0x63, 0x09, 0x01,
  133. 0x62, 0x07, 0x75, 0x72, 0x6E, 0x3A, 0x64, 0x64,// 280
  134. // d$!CCC$! (bs64)$
  135. 0x64, 0x98, 0x03, 0x43, 0x43, 0x43, 0x9F, 0x06,
  136. 0x20, 0x20, 0x20, 0xFF, 0x80, 0x30, 0x01,
  137. };
  138. [Test]
  139. [ExpectedException (typeof (ArgumentException))]
  140. public void ProcessingInstructions ()
  141. {
  142. MemoryStream ms = new MemoryStream ();
  143. XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter (ms, null, null);
  144. w.WriteStartDocument ();
  145. w.WriteProcessingInstruction ("myPI", "myValue");
  146. }
  147. [Test]
  148. public void UseCase2 ()
  149. {
  150. XmlDictionary dic = new XmlDictionary ();
  151. MemoryStream ms = new MemoryStream ();
  152. XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter (ms, dic, null);
  153. XmlDictionaryString empty = dic.Add (String.Empty);
  154. // empty ns
  155. w.WriteStartElement (dic.Add ("FOO"), empty);
  156. // non-dic string
  157. w.WriteStartElement ("BAR");
  158. // second time ns
  159. w.WriteStartElement (dic.Add ("FOO"), empty);
  160. // first time dic string but prior non-dic name existed
  161. w.WriteStartElement (dic.Add ("BAR"), empty);
  162. w.WriteEndElement ();
  163. w.WriteEndElement ();
  164. w.WriteEndElement ();
  165. // dicstr w/ ns with empty prefix
  166. w.WriteStartElement (dic.Add ("BAR"), dic.Add ("urn:bar"));
  167. // with prefix
  168. w.WriteStartElement ("ppp", dic.Add ("BAR"), dic.Add ("urn:bar"));
  169. w.WriteChars (new char [] {'x', 'y', 'z'}, 0, 3);
  170. // w.WriteString ("xyz"); // the same as WriteChars()
  171. w.WriteEndElement ();
  172. w.WriteString ("bbbb");
  173. w.WriteCData ("ccc");
  174. w.WriteValue (new Guid ("11112222333344445555666677778888"));
  175. w.WriteEndElement ();
  176. w.WriteStartElement ("FOO");
  177. w.WriteStartAttribute ("AAA");
  178. w.WriteValue (new Guid ("11112222333344445555666677778888"));
  179. w.WriteEndAttribute ();
  180. w.WriteStartAttribute ("BBB");
  181. w.WriteValue (TimeSpan.Zero);
  182. w.WriteEndAttribute ();
  183. w.WriteStartAttribute ("CC");
  184. w.WriteValue (new UniqueId ("uuid-00000000-0000-0000-0000-000000000000-1"));
  185. w.WriteEndAttribute ();
  186. w.WriteStartElement ("XX");
  187. w.WriteValue (true);
  188. w.WriteValue (false);
  189. w.WriteEndElement ();
  190. w.WriteStartElement ("xx", "aaa", "urn:zzz");
  191. w.WriteEndElement ();
  192. w.WriteEndElement ();
  193. w.Close ();
  194. Assert.AreEqual (usecase2_result, ms.ToArray ());
  195. }
  196. // $ : kind
  197. // / : especially. EndElement
  198. // ! : length
  199. // @ : dictionary index
  200. // ^ : missing ns decl?
  201. // FIXME: see fixmes in the test itself.
  202. static readonly byte [] usecase2_result = new byte [] {
  203. // $@$!BAR$ @$@///$@ ^@$!ppp! $!ppp@$! xyz$!bbb
  204. 0x42, 2, 0x40, 3, 0x42, 0x41, 0x52, 0x42,
  205. 2, 0x42, 4, 1, 1, 1, 0x42, 4,
  206. 10, 6, 0x43, 3, 0x70, 0x70, 0x70, 4,
  207. 11, 3, 0x70, 0x70, 0x70, 6, 0x99, 3,
  208. 0x78, 0x79, 0x7A, 0x98, 4, 0x62, 0x62, 0x62,
  209. // b$!ccc$G UIDGUIDG UIDGUID$ !FOO$!GU IDGUIDGU
  210. 0x62, 0x98, 3, 0x63, 0x63, 0x63, 0xB1, 0x22,
  211. 0x22, 0x11, 0x11, 0x33, 0x33, 0x44, 0x44, 0x55,
  212. 0x55, 0x66, 0x66, 0x77, 0x77, 0x88, 0x88, 0x40,
  213. 3, 0x46, 0x4F, 0x4F, 0x04, 3, 0x41, 0x41,
  214. 0x41, 0xB0, 0x22, 0x22, 0x11, 0x11, 0x33, 0x33,
  215. // IDGUIDGU ID$!BBB$T IMESPAN $!CC$!UN IQUEIDUN
  216. 0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77,
  217. 0x88, 0x88, 0x04, 3, 0x42, 0x42, 0x42, 0xAE,
  218. 0, 0, 0, 0, 0, 0, 0, 0,
  219. 0x04, 2, 0x43, 0x43, 0x98, 0x2B, 0x75, 0x75,
  220. 0x69, 0x64, 0x2D, 0x30, 0x30, 0x30, 0x30, 0x30,
  221. // IQUEIDUN IQUEIDUN IQUEIDUN IQUEID.. .$!XX$$$!
  222. 0x30, 0x30, 0x30, 0x2D, 0x30, 0x30, 0x30, 0x30,
  223. 0x2D, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x30, 0x30,
  224. 0x30, 0x30, 0x2D, 0x30, 0x30, 0x30, 0x30, 0x30,
  225. 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2D,
  226. 0x31, 0x40, 2, 0x58, 0x58, 0x86, 0x85, 0x41, 2,
  227. // xx!aaa$!x x!urn:xxx
  228. 0x78, 0x78, 3, 0x61, 0x61, 0x61, 0x09, 2, 0x78,
  229. 0x78, 0x07, 0x75, 0x72, 0x6E, 0x3A, 0x7A, 0x7A,
  230. 0x7A, 1, 1, 1
  231. };
  232. [Test]
  233. public void WriteDictionaryStringWithNullDictionary ()
  234. {
  235. MemoryStream ms = new MemoryStream ();
  236. XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter (ms, null, null);
  237. XmlDictionary dic = new XmlDictionary ();
  238. w.WriteStartElement (dic.Add ("FOO"), XmlDictionaryString.Empty);
  239. }
  240. class MyWriterSession1 : XmlBinaryWriterSession
  241. {
  242. int count;
  243. public override bool TryAdd (XmlDictionaryString d, out int idx)
  244. {
  245. base.TryAdd (d, out idx);
  246. Assert.AreEqual (count, idx, "#x1-" + count);
  247. if (count++ == 0)
  248. Assert.AreEqual (String.Empty, d.Value, "#x2");
  249. else
  250. Assert.AreEqual ("FOO", d.Value, "#x3");
  251. return true;
  252. }
  253. }
  254. [Test]
  255. public void WriteDictionaryStringWithSameDictionary ()
  256. {
  257. MemoryStream ms = new MemoryStream ();
  258. XmlDictionary dic = new XmlDictionary ();
  259. XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter (ms, dic, null);
  260. w.WriteStartElement (dic.Add ("FOO"), XmlDictionaryString.Empty);
  261. w.Close ();
  262. Assert.AreEqual (new byte [] {0x42, 0, 1}, ms.ToArray ());
  263. }
  264. [Test]
  265. public void WriteDictionaryStringWithDifferentDictionary () // it actually works
  266. {
  267. MemoryStream ms = new MemoryStream ();
  268. XmlBinaryWriterSession session = new XmlBinaryWriterSession ();
  269. XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter (ms, new XmlDictionary (), session);
  270. XmlDictionary dic = new XmlDictionary ();
  271. w.WriteStartElement (dic.Add ("FOO"), XmlDictionaryString.Empty);
  272. w.Close ();
  273. Assert.AreEqual (new byte [] {0x42, 1, 1}, ms.ToArray ());
  274. }
  275. [Test]
  276. public void IndicesFromDictionaryAndSession ()
  277. {
  278. // So, I found out the solution for the indices puzzle.
  279. MemoryStream ms = new MemoryStream ();
  280. XmlBinaryWriterSession session = new XmlBinaryWriterSession ();
  281. XmlDictionary dic = new XmlDictionary ();
  282. XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter (ms, dic, session);
  283. XmlDictionary dic2 = new XmlDictionary ();
  284. XmlDictionary dic3 = new XmlDictionary ();
  285. w.WriteStartElement (dic.Add ("FOO"), XmlDictionaryString.Empty);
  286. w.WriteStartElement (dic2.Add ("FOO"), XmlDictionaryString.Empty);
  287. w.WriteStartElement (dic3.Add ("FOO"), XmlDictionaryString.Empty);
  288. w.WriteStartElement (dic2.Add ("BAR"), XmlDictionaryString.Empty);
  289. w.WriteStartElement (dic.Add ("BAR"), XmlDictionaryString.Empty);
  290. w.Close ();
  291. // ... so, looks like even indices are for dictionary,
  292. // and odd indices are for session.
  293. byte [] bytes = new byte [] {
  294. 0x42, 0, 0x42, 1, 0x42, 1,0x42, 3,
  295. 0x42, 2, 1, 1, 1, 1, 1};
  296. Assert.AreEqual (bytes, ms.ToArray ());
  297. }
  298. [Test]
  299. public void UseStandardSession ()
  300. {
  301. MemoryStream ms = new MemoryStream ();
  302. XmlBinaryWriterSession session =
  303. new XmlBinaryWriterSession ();
  304. XmlDictionary dic = new XmlDictionary ();
  305. XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter (ms, dic, session);
  306. w.WriteStartElement (dic.Add ("FOO"), XmlDictionaryString.Empty);
  307. w.WriteStartElement (dic.Add ("blah"), XmlDictionaryString.Empty);
  308. w.WriteStartElement (dic.Add ("blabla"), XmlDictionaryString.Empty);
  309. w.Close ();
  310. Assert.AreEqual (new byte [] {0x42, 0, 0x42, 2, 0x42, 4, 1, 1, 1}, ms.ToArray ());
  311. }
  312. [Test]
  313. public void UseStandardSession2 ()
  314. {
  315. MemoryStream ms = new MemoryStream ();
  316. XmlBinaryWriterSession session =
  317. new XmlBinaryWriterSession ();
  318. XmlDictionary dic = new XmlDictionary ();
  319. XmlDictionaryString x = dic.Add ("urn:foo");
  320. XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter (ms, dic, session);
  321. w.WriteStartElement (dic.Add ("FOO"), x);
  322. w.WriteStartElement (dic.Add ("blah"), x);
  323. w.WriteStartElement (dic.Add ("blabla"), x);
  324. w.Close ();
  325. Assert.AreEqual (new byte [] {0x42, 2, 0x0A, 0, 0x42, 4, 0x42, 6, 1, 1, 1}, ms.ToArray (), "#1");
  326. XmlDictionaryString ds;
  327. Assert.IsTrue (dic.TryLookup (0, out ds), "#2-1");
  328. Assert.AreEqual ("urn:foo", ds.Value, "#2-2");
  329. Assert.AreEqual (0, ds.Key, "#2-3");
  330. Assert.IsTrue (dic.TryLookup (1, out ds), "#3-1");
  331. Assert.AreEqual ("FOO", ds.Value, "#3-2");
  332. Assert.AreEqual (1, ds.Key, "#3-3");
  333. Assert.IsTrue (dic.TryLookup (2, out ds), "#4-1");
  334. Assert.AreEqual ("blah", ds.Value, "#4-2");
  335. Assert.AreEqual (2, ds.Key, "#4-3");
  336. Assert.IsTrue (dic.TryLookup (3, out ds), "#5-1");
  337. Assert.AreEqual ("blabla", ds.Value, "#5-2");
  338. Assert.AreEqual (3, ds.Key, "#5-3");
  339. }
  340. class MyWriterSession2 : XmlBinaryWriterSession
  341. {
  342. int count;
  343. public override bool TryAdd (XmlDictionaryString d, out int idx)
  344. {
  345. // do nothing
  346. idx = d.Value.Length;
  347. return true;
  348. }
  349. }
  350. [Test]
  351. public void UseNOPSession ()
  352. {
  353. MemoryStream ms = new MemoryStream ();
  354. MyWriterSession2 session = new MyWriterSession2 ();
  355. XmlDictionary dic = new XmlDictionary ();
  356. XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter (ms, dic, session);
  357. w.WriteStartElement (dic.Add ("FOO"), XmlDictionaryString.Empty);
  358. w.WriteStartElement (dic.Add ("blah"), XmlDictionaryString.Empty);
  359. w.WriteStartElement (dic.Add ("blabla"), XmlDictionaryString.Empty);
  360. w.Close ();
  361. Assert.AreEqual (new byte [] {0x42, 0, 0x42, 2, 0x42, 4, 1, 1, 1}, ms.ToArray ());
  362. }
  363. [Test]
  364. public void WriteElementWithNS ()
  365. {
  366. byte [] bytes = new byte [] {
  367. 0x42, 0, 10, 2, 0x98, 3, 0x61, 0x61,
  368. 0x61, 0x42, 0, 0x42, 2, 1, 1, 1};
  369. XmlDictionaryString ds;
  370. MemoryStream ms = new MemoryStream ();
  371. XmlDictionary dic = new XmlDictionary ();
  372. XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter (ms, dic, null);
  373. w.WriteStartElement (dic.Add ("FOO"), dic.Add ("foo"));
  374. Assert.IsTrue (dic.TryLookup ("foo", out ds), "#1");
  375. Assert.AreEqual (1, ds.Key, "#2");
  376. w.WriteString ("aaa");
  377. w.WriteStartElement (dic.Add ("FOO"), dic.Add ("foo"));
  378. w.WriteStartElement (dic.Add ("foo"), dic.Add ("foo"));
  379. w.Close ();
  380. Assert.AreEqual (bytes, ms.ToArray (), "result");
  381. /*
  382. byte [] bytes2 = new byte [] {
  383. 0x42, 1, 10, 2, 0x98, 3, 0x61, 0x61,
  384. 0x61, 0x42, 0, 0x42, 2, 1, 1, 1};
  385. XmlDictionaryReader dr = XmlDictionaryReader.CreateBinaryReader (new MemoryStream (bytes2), dic, new XmlDictionaryReaderQuotas ());
  386. try {
  387. dr.Read ();
  388. Assert.Fail ("dictionary index 1 should be regarded as invalid.");
  389. } catch (XmlException) {
  390. }
  391. */
  392. }
  393. [Test]
  394. public void Beyond128DictionaryEntries ()
  395. {
  396. XmlDictionaryString ds;
  397. MemoryStream ms = new MemoryStream ();
  398. XmlDictionary dic = new XmlDictionary ();
  399. for (int i = 0; i < 260; i++)
  400. Assert.AreEqual (i, dic.Add ("n" + i).Key, "d");
  401. XmlDictionary dic2 = new XmlDictionary ();
  402. XmlBinaryWriterSession session = new XmlBinaryWriterSession ();
  403. int idx;
  404. for (int i = 0; i < 260; i++)
  405. session.TryAdd (dic2.Add ("n" + i), out idx);
  406. XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter (ms, dic, session);
  407. w.WriteStartElement (dic.Add ("n128"), dic.Add ("n129"));
  408. w.WriteStartElement (dic2.Add ("n130"), dic2.Add ("n131"));
  409. w.WriteStartElement (dic.Add ("n132"), dic2.Add ("n133"));
  410. w.WriteStartElement (dic.Add ("n256"), dic2.Add ("n256"));
  411. w.Close ();
  412. byte [] bytes = new byte [] {
  413. // so, when it went beyond 128, the index
  414. // becomes 2 bytes, where
  415. // - the first byte always becomes > 80, and
  416. // - the second byte becomes (n / 0x80) * 2.
  417. 0x42, 0x80, 2, 0x0A, 0x82, 2,
  418. 0x42, 0x85, 2, 0x0A, 0x87, 2,
  419. 0x42, 0x88, 2, 0x0A, 0x8B, 2,
  420. 0x42, 0x80, 4, 0x0A, 0x81, 4,
  421. 1, 1, 1, 1};
  422. Assert.AreEqual (bytes, ms.ToArray (), "result");
  423. }
  424. [Test]
  425. public void GlobalAttributes ()
  426. {
  427. XmlDictionaryString ds;
  428. MemoryStream ms = new MemoryStream ();
  429. XmlDictionary dic = new XmlDictionary ();
  430. int idx;
  431. XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter (ms, dic, null);
  432. dic.Add ("n1");
  433. dic.Add ("urn:foo");
  434. dic.Add ("n2");
  435. dic.Add ("n3");
  436. dic.Add ("n4");
  437. dic.Add ("urn:bar");
  438. dic.Add ("n7");
  439. w.WriteStartElement (dic.Add ("n1"), dic.Add ("urn:foo"));
  440. w.WriteAttributeString (dic.Add ("n2"), dic.Add ("urn:bar"), String.Empty);
  441. w.WriteAttributeString (dic.Add ("n3"), dic.Add ("urn:foo"), "v");
  442. w.WriteAttributeString ("aaa", dic.Add ("n4"), dic.Add ("urn:bar"), String.Empty);
  443. w.WriteAttributeString ("bbb", "n5", "urn:foo", String.Empty);
  444. w.WriteAttributeString ("n6", String.Empty);
  445. w.WriteAttributeString (dic.Add ("n7"), XmlDictionaryString.Empty, String.Empty); // local attribute
  446. w.WriteAttributeString ("bbb", "n8", "urn:foo", String.Empty); // xmlns:bbb mapping already exists (from StartElement = 'a'), so prefix "bbb" won't be used.
  447. w.Close ();
  448. // 0x0C nameidx (value) 0x0D nameidx (value)
  449. // 0x07 (prefix) nameidx (value)
  450. // 0x05 (prefix) (name) (value)
  451. // 0x04... 0x06... 0x05...
  452. // 0x0A nsidx
  453. // 0x0B (prefix) nsidx
  454. // 0x0B... 0x0B...
  455. // 0x09 (prefix) (ns)
  456. byte [] bytes = new byte [] {
  457. // $@$@$$@$ !v$!aaa@
  458. // $@!bbb!n 5$$@$!a@
  459. // $!aaa!$! bbb$urn:foo$
  460. 0x42, 0,
  461. 0x0C, 4, 0xA8,
  462. 0x0D, 6, 0x98, 1, 0x76,
  463. 0x07, 3, 0x61, 0x61, 0x61, 8, 0xA8, // 16
  464. 0x05, 3, 0x62, 0x62, 0x62, 2, 0x6E, 0x35, 0xA8,
  465. 0x04, 2, 0x6E, 0x36, 0xA8, // 30
  466. 0x06, 12, 0xA8,
  467. 0x05, 3, 0x62, 0x62, 0x62, 2, 0x6E, 0x38, 0xA8,
  468. 0x0A, 2,
  469. 0x0B, 1, 0x61, 10, // 48
  470. 0x0B, 1, 0x62, 2,
  471. 0x0B, 3, 0x61, 0x61, 0x61, 10,
  472. 0x09, 3, 0x62, 0x62, 0x62,
  473. 0x07, 0x75, 0x72, 0x6E, 0x3A, 0x66, 0x6F, 0x6F,
  474. 1};
  475. Assert.AreEqual (bytes, ms.ToArray (), "result");
  476. }
  477. [Test]
  478. public void WriteAttributeXmlns ()
  479. {
  480. // equivalent to WriteXmlnsAttribute()
  481. XmlDictionaryString ds;
  482. MemoryStream ms = new MemoryStream ();
  483. XmlDictionary dic = new XmlDictionary ();
  484. XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter (ms, dic, null);
  485. w.WriteStartElement ("root");
  486. w.WriteAttributeString ("xmlns", "foo", "http://www.w3.org/2000/xmlns/", "urn:foo");
  487. w.WriteAttributeString (dic.Add ("xmlns"), dic.Add ("http://www.w3.org/2000/xmlns/"), "urn:bar");
  488. w.WriteAttributeString ("a", String.Empty);
  489. w.Close ();
  490. byte [] bytes = new byte [] {
  491. // 40 (root) 04 (a) A8
  492. // 09 (foo) (urn:foo) 08 (urn:bar)
  493. 0x40, 4, 0x72, 0x6F, 0x6F, 0x74,
  494. 0x04, 1, 0x61, 0xA8,
  495. 0x09, 3, 0x66, 0x6F, 0x6F, 7, 0x75, 0x72, 0x6E, 0x3A, 0x66, 0x6F, 0x6F,
  496. 0x08, 7, 0x75, 0x72, 0x6E, 0x3A, 0x62, 0x61, 0x72, 1
  497. };
  498. Assert.AreEqual (bytes, ms.ToArray ());
  499. }
  500. [Test]
  501. public void WriteXmlnsAttributeWithNullPrefix ()
  502. {
  503. MemoryStream ms = new MemoryStream ();
  504. XmlDictionary dic = new XmlDictionary ();
  505. XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter (ms, dic, null);
  506. w.WriteStartElement ("root", "aaaaa");
  507. w.WriteXmlnsAttribute (null, "bbbbb");
  508. w.WriteStartElement ("child", "ccccc");
  509. w.WriteXmlnsAttribute (null, "ddddd");
  510. w.WriteEndElement ();
  511. w.WriteEndElement ();
  512. w.Close ();
  513. byte [] bytes = new byte [] {
  514. // 0x40 (root) 0x8 (aaaaa)
  515. 0x40, 0x4, 0x72, 0x6F, 0x6F, 0x74, 0x8, 0x5, 0x61, 0x61, 0x61, 0x61, 0x61,
  516. // 0x9 (a) (bbbbb)
  517. 0x9, 0x1, 0x61, 0x5, 0x62, 0x62, 0x62, 0x62, 0x62,
  518. // 0x40 (child) 0x8 (ccccc)
  519. 0x40, 0x5, 0x63, 0x68, 0x69, 0x6C, 0x64, 0x8, 0x5, 0x63, 0x63, 0x63, 0x63, 0x63,
  520. // 0x9 (b) (ddddd) 0x1 0x1
  521. 0x9, 0x1, 0x62, 0x5, 0x64, 0x64, 0x64, 0x64, 0x64, 0x1, 0x1
  522. };
  523. Assert.AreEqual (bytes, ms.ToArray ());
  524. }
  525. [Test]
  526. [ExpectedException (typeof (InvalidOperationException))]
  527. public void WriteAttributeWithoutElement ()
  528. {
  529. XmlDictionaryString ds;
  530. MemoryStream ms = new MemoryStream ();
  531. XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter (ms, null, null);
  532. w.WriteAttributeString ("foo", "value");
  533. }
  534. [Test]
  535. [ExpectedException (typeof (ArgumentException))]
  536. public void OverwriteXmlnsUri ()
  537. {
  538. XmlDictionaryString ds;
  539. MemoryStream ms = new MemoryStream ();
  540. XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter (ms, null, null);
  541. w.WriteStartElement ("root");
  542. w.WriteAttributeString ("xmlns", "foo", "urn:thisCausesError", "urn:foo");
  543. }
  544. [Test]
  545. public void WriteTypedValues ()
  546. {
  547. MemoryStream ms = new MemoryStream ();
  548. var dic = new XmlDictionary ();
  549. XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter (ms, dic, null);
  550. w.WriteStartElement ("root");
  551. w.WriteXmlnsAttribute ("x", "urn:x");
  552. w.WriteXmlnsAttribute ("xx", "urn:xx");
  553. w.WriteValue ((byte) 5);
  554. w.WriteValue ((short) 893);
  555. w.WriteValue ((int) 37564);
  556. w.WriteValue ((long) 141421356);
  557. w.WriteValue ((long) 5670000000);
  558. w.WriteValue ((float) 1.7320508);
  559. w.WriteValue ((double) 2.2360679);
  560. w.WriteValue ((decimal) 3.141592);
  561. w.WriteValue (new DateTime (2000, 1, 2, 3, 4, 5));
  562. w.WriteValue (new XmlDictionary ().Add ("xxx")); // from different dictionary -> string output, not index output
  563. // w.WriteValue ((object) null); ANE
  564. w.WriteValue (1);
  565. w.WriteQualifiedName (dic.Add ("local"), dic.Add ("urn:x"));
  566. w.WriteQualifiedName (dic.Add ("local"), dic.Add ("urn:xx")); // QName tag is not used, since the prefix is more than 1 byte
  567. w.Close ();
  568. Assert.AreEqual (typed_values, ms.ToArray ());
  569. }
  570. byte [] typed_values = new byte [] {
  571. 0x40, 4, 0x72, 0x6F, 0x6F, 0x74, // elem
  572. 0x09, 1, 0x78, 5, 0x75, 0x72, 0x6E, 0x3A, 0x78, // xmlns:x
  573. 0x09, 2, 0x78, 0x78, 6, 0x75, 0x72, 0x6E, 0x3A, 0x78, 0x78, // xmlns:xx
  574. 0x88, 5,
  575. 0x8A, 0x7D, 0x03,
  576. 0x8C, 0xBC, 0x92, 0, 0, // int
  577. 0x8C, 0x2C, 0xEB, 0x6D, 0x08, // 20
  578. 0x8E, 0x80, 0x55, 0xF5, 0x51, 0x01, 0, 0, 0,
  579. 0x90, 0xD7, 0xB3, 0xDD, 0x3F, // float
  580. 0x92, 0x4C, 0x15, 0x31, 0x91, 0x77, 0xE3, 0x01, 0x40, // 43
  581. 0x94, 0, 0, 6, 0, 0, 0, 0, 0, 0xD8, 0xEF, 0x2F, 0, 0, 0, 0, 0,
  582. 0x96, 0x80, 0x40, 0xA3, 0x29, 0xE5, 0x22, 0xC1, 8,
  583. 0x98, 3, 0x78, 0x78, 0x78, // dictionary string that is not in the in-use dictionary is just a string here
  584. 0x82,
  585. 0xBC, 23, 0, // QName dictionay string
  586. 0x98, 2, 0x78, 0x78, 0x98, 1, 0x3A, 0xAB, 0, // QName with longer prefix is written just as a string
  587. };
  588. const string xmlnsns = "http://www.w3.org/2000/xmlns/";
  589. [Test]
  590. public void WriteAutoIndexedAttribute ()
  591. {
  592. MemoryStream ms = new MemoryStream ();
  593. XmlDictionary dic = new XmlDictionary ();
  594. var w = XmlDictionaryWriter.CreateBinaryWriter (ms, dic, null);
  595. w.WriteStartElement ("root");
  596. w.WriteXmlnsAttribute ("c", "urn:foo");
  597. w.WriteAttributeString ("xmlns", "d", xmlnsns, "urn:bar");
  598. w.WriteAttributeString ("xmlns", "dd", xmlnsns, "urn:baz");
  599. w.WriteAttributeString ("a1", "urn:foo", "v1");
  600. w.WriteAttributeString ("a2", "urn:bar", "v2");
  601. w.WriteAttributeString ("a3", "urn:baz", "v3");
  602. w.Close ();
  603. Assert.AreEqual (auto_indexed_atts_value, ms.ToArray ());
  604. }
  605. byte [] auto_indexed_atts_value = {
  606. 0x40, 0x04, 0x72, 0x6F, 0x6F, 0x74, 0x28, 0x02, 0x61, 0x31, 0x98, 0x02, 0x76, 0x31, 0x29, 0x02,
  607. 0x61, 0x32, 0x98, 0x02, 0x76, 0x32, 0x05, 0x02, 0x64, 0x64, 0x02, 0x61, 0x33, 0x98, 0x02, 0x76,
  608. 0x33, 0x09, 0x01, 0x63, 0x07, 0x75, 0x72, 0x6E, 0x3A, 0x66, 0x6F, 0x6F, 0x09, 0x01, 0x64, 0x07,
  609. 0x75, 0x72, 0x6E, 0x3A, 0x62, 0x61, 0x72, 0x09, 0x02, 0x64, 0x64, 0x07, 0x75, 0x72, 0x6E, 0x3A,
  610. 0x62, 0x61, 0x7A, 0x01,
  611. };
  612. [Test]
  613. public void WriteShortPrefixedElement ()
  614. {
  615. MemoryStream ms = new MemoryStream ();
  616. XmlDictionary dic = new XmlDictionary ();
  617. var w = XmlDictionaryWriter.CreateBinaryWriter (ms, dic, null);
  618. w.WriteElementString ("p", "root", "urn:foo", "test");
  619. w.Close ();
  620. Assert.AreEqual (short_prefixed_elem_value, ms.ToArray ());
  621. }
  622. static readonly byte [] short_prefixed_elem_value = {
  623. 0x6D, 4, 0x72, 0x6F, 0x6F, 0x74,
  624. 0x09, 1, 0x70, 7, 0x75, 0x72, 0x6E, 0x3A, 0x66, 0x6F, 0x6F,
  625. 0x99, 4, 0x74, 0x65, 0x73, 0x74,
  626. };
  627. [Test]
  628. public void WriteValueInt16 ()
  629. {
  630. MemoryStream ms = new MemoryStream ();
  631. XmlDictionary dic = new XmlDictionary ();
  632. var w = XmlDictionaryWriter.CreateBinaryWriter (ms, dic, null);
  633. w.WriteStartElement ("a");
  634. w.WriteValue ((short) 0);
  635. w.WriteValue ((short) 2);
  636. w.Close ();
  637. Assert.AreEqual (value_int16, ms.ToArray ());
  638. }
  639. static readonly byte [] value_int16 = {
  640. 0x40, 1, 0x61,
  641. 0x80, // not Int16, but Zero
  642. 0x89, 2 // not Int16, but Int8
  643. };
  644. [Test]
  645. public void WriteArrayInt16 ()
  646. {
  647. MemoryStream ms = new MemoryStream ();
  648. XmlDictionary dic = new XmlDictionary ();
  649. var w = XmlDictionaryWriter.CreateBinaryWriter (ms, dic, null);
  650. short [] arr = new short [] {0, 2, 4, 6, 8, 10, 12, 14};
  651. w.WriteArray ("", "el", "", arr, 2, 5);
  652. w.Close ();
  653. Assert.AreEqual (array_int16, ms.ToArray ());
  654. }
  655. static readonly byte [] array_int16 = {
  656. 0x03, 0x40, 2, 0x65, 0x6C, 0x01,
  657. 0x8B, 5, 4, 0, 6, 0, 8, 0, 10, 0, 12, 0,
  658. };
  659. [Test]
  660. public void WriteArrayInt32 ()
  661. {
  662. MemoryStream ms = new MemoryStream ();
  663. XmlDictionary dic = new XmlDictionary ();
  664. var w = XmlDictionaryWriter.CreateBinaryWriter (ms, dic, null);
  665. int [] arr = new int [] {0, 2, 0, 6, 8, 10,};
  666. w.WriteArray ("", "el", "", arr, 2, 3);
  667. w.Close ();
  668. Assert.That (ms.ToArray (), new CollectionEquivalentConstraint (array_int32));
  669. }
  670. // make sure that 0 is not written in shortened format.
  671. static readonly byte [] array_int32 = {
  672. 0x03, 0x40, 2, 0x65, 0x6C, 0x01,
  673. 0x8D, 3, 0, 0, 0, 0, 6, 0, 0, 0, 8, 0, 0, 0,
  674. };
  675. [Test]
  676. public void WriteXmlXmlnsAttributesWithNullNS ()
  677. {
  678. var ms = new MemoryStream ();
  679. var xw = XmlDictionaryWriter.CreateBinaryWriter (ms);
  680. xw.WriteStartElement ("foo");
  681. xw.WriteAttributeString ("xmlns", "foo", null, "urn:foo");
  682. xw.WriteAttributeString ("xml", "lang", null, "en-US");
  683. xw.WriteEndElement ();
  684. }
  685. [Test]
  686. [ExpectedException (typeof (ArgumentException))]
  687. public void FailConflictingNamespace ()
  688. {
  689. var ms = new MemoryStream ();
  690. var xw = XmlDictionaryWriter.CreateBinaryWriter (ms);
  691. xw.WriteStartElement ("x", "foo", "urn:foo");
  692. xw.WriteAttributeString ("x", "a", "urn:baz", "v");
  693. }
  694. }
  695. }