2008-09-19 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web.Extensions / Test / System.Web.Script.Serialization / JavaScriptSerializerTest.cs
1 //
2 // JavaScriptSerializer.cs
3 //
4 // Author:
5 //   Konstantin Triger <kostat@mainsoft.com>
6 //
7 // (C) 2007 Mainsoft, Inc.  http://www.mainsoft.com
8 //
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System;
31 using System.Collections.Generic;
32 using System.Text;
33 using NUnit.Framework;
34 using System.Web.Script.Serialization;
35 using System.Reflection;
36 using System.Collections;
37 using System.Drawing;
38 using ComponentModel = System.ComponentModel;
39 using System.Globalization;
40 using System.Threading;
41 using System.Text.RegularExpressions;
42 using System.ComponentModel;
43 using CategoryAttribute = NUnit.Framework.CategoryAttribute;
44 using System.Web.UI.WebControls;
45 using System.Collections.ObjectModel;
46
47
48 namespace Tests.System.Web.Script.Serialization
49 {
50         [TestFixture]
51         public class JavaScriptSerializerTest
52         {
53                 enum MyEnum
54                 {
55                         AAA,
56                         BBB,
57                         CCC
58                 }
59 #pragma warning disable 659
60                 class bug
61                 {
62                         //public DateTime dt;
63                         //public DateTime dt1;
64                         //public DateTime dt2;
65                         public bool bb;
66                         //Hashtable hash;
67
68                         public void Init() {
69                                 //dt = DateTime.MaxValue;
70                                 //dt1 = DateTime.MinValue;
71                                 //dt2 = new DateTime ((DateTime.Now.Ticks / 10000) * 10000);
72                                 bb = true;
73                                 //hash = new Hashtable ();
74                                 //hash.Add ("mykey", 1);
75                         }
76
77                         public override bool Equals (object obj) {
78                                 if (!(obj is bug))
79                                         return false;
80                                 JavaScriptSerializerTest.FieldsEqual (this, obj);
81                                 return true;
82                         }
83                 }
84                 class X
85                 {
86                         int x = 5;
87                         //int y;
88                         ulong _bb;
89                         Y[] _yy;
90                         Y [] _yyy = new Y [] { new Y (), new Y () };
91                         public int z;
92                         public char ch;
93                         public char ch_null;
94                         public string str;
95                         public byte b;
96                         public sbyte sb;
97                         public short sh;
98                         public ushort ush;
99                         public int i;
100                         public uint ui;
101                         public long l;
102                         public ulong ul;
103                         
104                         public float f;
105                         public float f1;
106                         public float f2;
107                         public float f3;
108                         public float f4;
109
110                         public double d;
111                         public double d1;
112                         public double d2;
113                         public double d3;
114                         public double d4;
115
116                         public decimal de;
117                         public decimal de1;
118                         public decimal de2;
119                         public decimal de3;
120                         public decimal de4;
121
122                         
123
124                         public Guid g;
125                         
126                         public Nullable<bool> nb;
127                         public DBNull dbn;
128                         IEnumerable<int> enum_int;
129                         IEnumerable enum_int1;
130                         public Uri uri;
131                         public Dictionary<string, Y> hash;
132                         public Point point;
133
134                         public void Init () {
135                                 //y = 6;
136                                 _bb = ulong.MaxValue - 5;
137                                 _yy = new Y [] { new Y (), new Y () };
138                                 z = 8;
139                                 ch = (char) 0xFF56;
140                                 ch_null = '\0';
141                                 str = "\uFF56\uFF57\uF58FF59g";
142                                 b = 253;
143                                 sb = -48;
144                                 sh = short.MinValue + 28;
145                                 ush = ushort.MaxValue - 24;
146                                 i = -234235453;
147                                 ui = uint.MaxValue - 234234;
148                                 l = long.MinValue + 28;
149                                 ul = ulong.MaxValue - 3;
150
151                                 f = float.NaN;
152                                 f1 = float.NegativeInfinity;
153                                 f2 = float.PositiveInfinity;
154                                 f3 = float.MinValue;
155                                 f4 = float.MaxValue;
156
157                                 d = double.NaN;
158                                 d1 = double.NegativeInfinity;
159                                 d2 = double.PositiveInfinity;
160                                 d3 = double.MinValue;
161                                 d4 = double.MaxValue;
162
163                                 de = decimal.MinusOne;
164                                 de1 = decimal.Zero;
165                                 de2 = decimal.One;
166                                 de3 = decimal.MinValue;
167                                 de4 = decimal.MaxValue;
168
169                                 g = new Guid (234, 2, 354, new byte [] { 1, 2, 3, 4, 5, 6, 7, 8 });
170                                 
171                                 nb = null;
172                                 dbn = null;
173
174                                 enum_int = new List<int> (MyEnum);
175                                 enum_int1 = new ArrayList ();
176                                 foreach (object obj in MyEnum1)
177                                         ((ArrayList) enum_int1).Add (obj);
178                                 uri = new Uri ("http://kostat@mainsoft/adfasdf/asdfasdf.aspx/asda/ads?a=b&c=d", UriKind.RelativeOrAbsolute);
179
180                                 hash = new Dictionary<string, Y> ();
181                                 Y y = new Y ();
182                                 hash ["mykey"] = y;
183                                 point = new Point (150, 150);
184                         }
185
186                         public IEnumerable<int> MyEnum {
187                                 get {
188                                         yield return 1;
189                                         yield return 10;
190                                         yield return 345;
191                                 }
192
193                                 set {
194                                         enum_int = value;
195                                 }
196                         }
197
198                         public IEnumerable MyEnum1 {
199                                 get {
200                                         yield return 1;
201                                         yield return 10;
202                                         yield return 345;
203                                 }
204
205                                 set {
206                                         enum_int1 = value;
207                                 }
208                         }
209
210                         public int AA {
211                                 get { return x; }
212                         }
213
214                         public Y[] AA1 {
215                                 get { return _yyy; }
216                         }
217
218                         public ulong BB {
219                                 get { return _bb; }
220                                 set { _bb = value; }
221                         }
222
223                         public Y[] YY {
224                                 get { return _yy; }
225                                 set { _yy = value; }
226                         }
227
228                         public override bool Equals (object obj) {
229                                 if (!(obj is X))
230                                         return false;
231                                 JavaScriptSerializerTest.FieldsEqual (this, obj);
232                                 return true;
233                         }
234                 }
235
236                 class Y
237                 {
238
239                         long _bb = 10;
240
241                         public long BB {
242                                 get { return _bb; }
243                                 set { _bb = value; }
244                         }
245
246                         public override bool Equals (object obj) {
247                                 if (!(obj is Y))
248                                         return false;
249                                 JavaScriptSerializerTest.FieldsEqual(this, obj);
250                                 return true;
251                         }
252                 }
253
254                 class YY
255                 {
256                         public YY () 
257                         {
258                                 Y1 = new Y ();
259                                 Y2 = new Y ();
260                         }
261
262                         public Y Y1;
263                         public Y Y2;
264                 }
265
266                 [TypeConverter (typeof (MyUriConverter))]
267                 class MyUri : Uri
268                 {
269                         public MyUri (string uriString, UriKind uriKind)
270                                 : base (uriString, uriKind) {
271                         }
272
273                         public MyUri (Uri value)
274                                 : base (value.AbsoluteUri) {
275                         }
276                 }
277
278                 class MyUriConverter : UriTypeConverter
279                 {
280                         public override object ConvertTo (ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) 
281                         {
282                                 return base.ConvertTo (context, culture, value, destinationType);
283                         }
284
285                         public override object ConvertFrom (ITypeDescriptorContext context, CultureInfo culture, object value) 
286                         {
287                                 Uri convertedUri = (Uri)base.ConvertFrom (context, culture, value);
288                                 return new MyUri (convertedUri);
289                         }
290                 }
291
292                 [TypeConverter(typeof(MyPointConverter))]
293                 class MyPointContainer
294                 {
295                         public MyPointContainer () 
296                         {
297                         }
298
299                         public MyPointContainer (Point v) 
300                         {
301                                 p = v;
302                         }
303
304                         internal Point p;
305                 }
306
307                 class MyPointConverter : TypeConverter
308                 {
309                         public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType) 
310                         {
311                                 if (destinationType == typeof (string)) {
312                                         return true;
313                                 }
314                                 return base.CanConvertTo (context, destinationType);
315                         }
316
317                         public override object ConvertTo (ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) 
318                         {
319                                 if (destinationType == typeof (string)) {
320                                         MyPointContainer pc = (MyPointContainer) value;
321                                         return pc.p.X + "," + pc.p.Y;
322                                 }
323                                 return base.ConvertTo (context, culture, value, destinationType);
324                         }
325
326                         public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType) 
327                         {
328                                 if (sourceType == typeof (string)) {
329                                         return true;
330                                 }
331                                 return base.CanConvertFrom (context, sourceType);
332                         }
333
334                         public override object ConvertFrom (ITypeDescriptorContext context, CultureInfo culture, object value) 
335                         {
336                                 if (value is string) {
337                                         string [] v = ((string) value).Split (new char [] { ',' });
338                                         return new MyPointContainer(new Point (int.Parse (v [0]), int.Parse (v [1])));
339                                 }
340                                 return base.ConvertFrom (context, culture, value);
341                         }
342                 }
343
344 #pragma warning restore 659
345
346                 [Test]
347                 [Category ("NotDotNet")]
348                 public void TestDefaults () {
349                         JavaScriptSerializer ser = new JavaScriptSerializer ();
350                         Assert.AreEqual (102400, ser.MaxJsonLength);
351                         Assert.AreEqual (100, ser.RecursionLimit);
352                         //List<JavaScriptConverter> l = new List<JavaScriptConverter> ();
353                         //l.Add (new MyJavaScriptConverter ());
354                         //ser.RegisterConverters (l);
355                         //string x = ser.Serialize (new X [] { new X (), new X () });
356                         //string s = ser.Serialize (new X());
357                         //"{\"BB\":10,\"__type\":\"Tests.System.Web.Script.Serialization.JavaScriptSerializerTest+Y, Tests, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null\"}"
358                         //X x = ser.Deserialize<X> (s);
359                         //object ddd = typeof (Y).GetMember ("BB");
360                         //object x1 = ser.Deserialize<X []> (null);
361                         //object x2 = ser.Deserialize<X []> ("");
362                         //object d = ser.Deserialize<X[]> (x);
363                 }
364
365                 [Test]
366                 public void TestDeserialize () {
367                         JavaScriptSerializer ser = new JavaScriptSerializer ();
368                         Assert.IsNull (ser.Deserialize<X> (""));
369
370                         X s = new X ();
371                         s.Init ();
372                         string x = ser.Serialize (s);
373                         X n = ser.Deserialize<X> (x);
374                         Assert.AreEqual (s, n);
375
376                         //string json = "\\uFF56";
377                         //string result = ser.Deserialize<string> (json);
378                         //Assert.AreEqual ("\uFF56", result);
379
380                         //object oo = ser.DeserializeObject ("{value:'Purple\\r \\n monkey\\'s:\\tdishwasher'}");
381                 }
382
383                 [Test]
384                 public void TestDeserializeTypeResolver () 
385                 {
386                         JavaScriptSerializer ser = new JavaScriptSerializer (new SimpleTypeResolver ());
387                         X x = new X ();
388                         x.Init ();
389
390                         string s = ser.Serialize (x);
391                         X x2 = ser.Deserialize<X> (s);
392                         Assert.AreEqual (x, x2);
393                 }
394
395                 [Test]
396                 public void TestDeserializeBugs () {
397                         JavaScriptSerializer ser = new JavaScriptSerializer ();
398
399                         bug s = new bug ();
400                         s.Init ();
401                         string x = ser.Serialize (s);
402                         bug n = ser.Deserialize<bug> (x);
403                         Assert.AreEqual (s, n);
404
405                         // Should check correctness with .Net GA:
406                         //js = ser.Serialize (Color.Red);
407                         //Color ccc = ser.Deserialize<Color> (js);
408                         //string xml = @"<root><node attr=""xxx""/></root>";
409
410                         //XmlDocument doc = new XmlDocument ();
411                         //doc.LoadXml (xml);
412                         //string js = ser.Serialize (doc);
413                         //DataTable table = new DataTable();
414                         //table.Columns.Add ("col1", typeof (int));
415                         //table.Columns.Add ("col2", typeof (float));
416                         //table.Rows.Add (1, 1f);
417                         //table.Rows.Add (234234, 2.4f);
418
419                         //string js = ser.Serialize (table);
420                 }
421
422                 static void FieldsEqual (object expected, object actual) {
423                         Assert.AreEqual (expected.GetType (), actual.GetType ());
424                         FieldInfo [] infos = expected.GetType ().GetFields (BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
425                         foreach (FieldInfo info in infos) {
426                                 object value1 = info.GetValue (expected);
427                                 object value2 = info.GetValue (actual);
428                                 if (value1 is IEnumerable) {
429                                         IEnumerator yenum = ((IEnumerable) value2).GetEnumerator ();
430                                         int index = -1;
431                                         foreach (object x in (IEnumerable) value1) {
432                                                 if (!yenum.MoveNext ())
433                                                         Assert.Fail (info.Name + " index:" + index);
434                                                 index++;
435                                                 if (x is DictionaryEntry) {
436                                                         DictionaryEntry entry = (DictionaryEntry)x;
437                                                         IDictionary dict = (IDictionary) value2;
438                                                         Assert.AreEqual (entry.Value, dict [entry.Key], info.Name + ", key:" + entry.Key);
439                                                 }
440                                                 else
441                                                         Assert.AreEqual (x, yenum.Current, info.Name + ", index:" + index);
442                                         }
443                                         Assert.IsFalse (yenum.MoveNext (), info.Name);
444                                         continue;
445                                 }
446                                 Assert.AreEqual (value1, value2, info.Name);
447                         }
448
449                 }
450
451                 [Test]
452                 [ExpectedException (typeof (ArgumentNullException))]
453                 public void TestDeserialize1 () {
454                         JavaScriptSerializer ser = new JavaScriptSerializer ();
455                         ser.Deserialize<string> (null);
456                 }
457
458                 [Test]
459                 [ExpectedException (typeof (ArgumentNullException))]
460                 public void TestDeserializeNullConverter () {
461                         JavaScriptSerializer ser = new JavaScriptSerializer ();
462                         ser.RegisterConverters (null);
463                 }
464
465                 [Test]
466                 public void TestDeserializeConverter () {
467                         JavaScriptSerializer ser = new JavaScriptSerializer ();
468                         List<JavaScriptConverter> list = new List<JavaScriptConverter> ();
469                         list.Add (new MyJavaScriptConverter ());
470                         list.Add (new CultureInfoConverter ());
471                         ser.RegisterConverters (list);
472                         string result = ser.Serialize (new X [] { new X (), new X () });
473                         Assert.AreEqual ("{\"0\":1,\"1\":2}", result);
474                         result = ser.Serialize (Thread.CurrentThread.CurrentCulture);
475                 }
476
477                 [Test]
478                 public void TestDeserializeConverter1 () {
479                         JavaScriptSerializer serializer = new JavaScriptSerializer ();
480
481                         serializer.RegisterConverters (new JavaScriptConverter [] { 
482             new ListItemCollectionConverter() });
483
484                         ListBox ListBox1 = new ListBox ();
485                         ListBox1.Items.Add ("a1");
486                         ListBox1.Items.Add ("a2");
487                         ListBox1.Items.Add ("a3");
488
489                         string x = serializer.Serialize (ListBox1.Items);
490                         ListItemCollection recoveredList = serializer.Deserialize<ListItemCollection> (x);
491                         Assert.AreEqual (3, recoveredList.Count);
492                 }
493
494                 [Test]
495                 public void TestSerialize1 () {
496                         JavaScriptSerializer ser = new JavaScriptSerializer ();
497                         Assert.AreEqual("null", ser.Serialize(null));
498
499                         string js = ser.Serialize (1234);
500                         Assert.AreEqual ("1234", js);
501                         Assert.AreEqual (1234, ser.Deserialize<int> (js));
502                         js = ser.Serialize (1.1);
503                         Assert.AreEqual ("1.1", js);
504                         Assert.AreEqual (1.1f, ser.Deserialize<float> (js));
505                         char [] chars = "faskjhfasd0981234".ToCharArray ();
506                         js = ser.Serialize (chars);
507                         char[] actual = ser.Deserialize<char[]> (js);
508                         Assert.AreEqual (chars.Length, actual.Length);
509                         for (int i = 0; i < chars.Length; i++)
510                                 Assert.AreEqual (chars[i], actual[i]);
511
512                         string expected = @"""\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\""#$%&\u0027()*+,-./0123456789:;\u003c=\u003e?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~""";
513                         string data = "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\"#$%&\u0027()*+,-./0123456789:;\u003c=\u003e?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
514
515                         string serRes = ser.Serialize (data);
516                         Assert.AreEqual (expected, serRes);
517                         string deserRes = ser.Deserialize<string> (serRes);
518                         Assert.AreEqual (data, deserRes);
519                 }
520
521                 [Test]
522                 [ExpectedException (typeof (ArgumentNullException))]
523                 [Category ("NotDotNet")]
524                 public void TestSerialize2 () {
525                         JavaScriptSerializer ser = new JavaScriptSerializer ();
526                         ser.Serialize ("aaa", null);
527                 }
528
529                 static readonly long InitialJavaScriptDateTicks = new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks;
530
531                 [Test]
532                 public void TestSerializeDate () {
533                         JavaScriptSerializer ser = new JavaScriptSerializer ();
534                         DateTime now = new DateTime (633213894056010000L);
535
536                         string actual = ser.Serialize (now);
537                         DateTime dateTime = now.ToUniversalTime ();
538                         long javaScriptTicks = (dateTime.Ticks - InitialJavaScriptDateTicks) / (long) 10000;
539
540                         object dd = ser.DeserializeObject (@"""\/Datte(" + javaScriptTicks + @")\/""");
541                         Assert.AreEqual (@"""\/Date(" + javaScriptTicks + @")\/""", actual);
542                         Assert.AreEqual (now.ToUniversalTime(), ser.DeserializeObject (actual));
543                 }
544
545                 [Test]
546                 public void TestSerializeEnum () {
547                         JavaScriptSerializer ser = new JavaScriptSerializer ();
548                         string result = ser.Serialize (MyEnum.BBB);
549                         Assert.AreEqual ("1", result);
550                         Assert.AreEqual (MyEnum.BBB, ser.Deserialize<MyEnum> (result));
551                 }
552
553                 class MyJavaScriptConverter : JavaScriptConverter
554                 {
555                         public override object Deserialize (IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) {
556                                 throw new Exception ("The method or operation is not implemented.");
557                         }
558
559                         public override IDictionary<string, object> Serialize (object obj, JavaScriptSerializer serializer) {
560                                 Array a = (Array) obj;
561                                 Dictionary<string, object> d = new Dictionary<string, object> ();
562                                 d.Add ("0", 1);
563                                 d.Add ("1", 2);
564                                 return d;
565                                 //throw new Exception ("The method or operation is not implemented.");
566                         }
567
568                         public override IEnumerable<Type> SupportedTypes {
569                                 get {
570                                         yield return typeof (X[]);
571                                 }
572                         }
573                 }
574
575                 sealed class CultureInfoConverter : JavaScriptConverter
576                 {
577                         static readonly Type typeofCultureInfo = typeof (CultureInfo);
578                         public override IEnumerable<Type> SupportedTypes {
579                                 get { yield return typeofCultureInfo; }
580                         }
581
582                         public override object Deserialize (IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) {
583                                 throw new NotSupportedException ();
584                         }
585
586                         public override IDictionary<string, object> Serialize (object obj, JavaScriptSerializer serializer) {
587                                 CultureInfo ci = (CultureInfo)obj;
588                                 if (ci == null)
589                                         return null;
590                                 Dictionary<string, object> d = new Dictionary<string, object> ();
591                                 d.Add ("name", ci.Name);
592                                 d.Add ("numberFormat", ci.NumberFormat);
593                                 d.Add ("dateTimeFormat", ci.DateTimeFormat);
594                                 return d;
595                         }
596                 }
597
598                 public class ListItemCollectionConverter : JavaScriptConverter
599                 {
600                         public override IEnumerable<Type> SupportedTypes {
601                                 //Define the ListItemCollection as a supported type.
602                                 get { return new ReadOnlyCollection<Type> (new Type [] { typeof (ListItemCollection) }); }
603                         }
604
605                         public override IDictionary<string, object> Serialize (object obj, JavaScriptSerializer serializer) {
606                                 ListItemCollection listType = obj as ListItemCollection;
607
608                                 if (listType != null) {
609                                         // Create the representation.
610                                         Dictionary<string, object> result = new Dictionary<string, object> ();
611                                         ArrayList itemsList = new ArrayList ();
612                                         foreach (ListItem item in listType) {
613                                                 //Add each entry to the dictionary.
614                                                 Dictionary<string, object> listDict = new Dictionary<string, object> ();
615                                                 listDict.Add ("Value", item.Value);
616                                                 listDict.Add ("Text", item.Text);
617                                                 itemsList.Add (listDict);
618                                         }
619                                         result ["List"] = itemsList;
620
621                                         return result;
622                                 }
623                                 return new Dictionary<string, object> ();
624                         }
625
626                         public override object Deserialize (IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) {
627                                 if (dictionary == null)
628                                         throw new ArgumentNullException ("dictionary");
629
630                                 if (type == typeof (ListItemCollection)) {
631                                         // Create the instance to deserialize into.
632                                         ListItemCollection list = new ListItemCollection ();
633
634                                         // Deserialize the ListItemCollection's items.
635                                         ArrayList itemsList = (ArrayList) dictionary ["List"];
636                                         for (int i = 0; i < itemsList.Count; i++)
637                                                 list.Add (serializer.ConvertToType<ListItem> (itemsList [i]));
638
639                                         return list;
640                                 }
641                                 return null;
642                         }
643                 }
644
645                 [Test]
646                 public void DeserializeObject () {
647                         object o = new JavaScriptSerializer ().DeserializeObject ("{\"Numeric\":0,\"Array\":[true,false,0]}");
648                         Assert.IsNotNull (o as Dictionary<string, object>, "type");
649                         Dictionary<string, object> dictionary = (Dictionary<string, object>) o;
650                         Assert.AreEqual (0, (int) dictionary ["Numeric"], "Numeric");
651                         Assert.IsNotNull (dictionary ["Array"] as object [], "Array type");
652                         object [] array = (object []) dictionary ["Array"];
653                         Assert.AreEqual (true, (bool) array [0], "array [0]");
654                         Assert.AreEqual (false, (bool) array [1], "array [1]");
655                         Assert.AreEqual (0, (int) array [2], "array [2]");
656                 }
657
658                 [Test]
659                 public void DeserializeObject2 () 
660                 {
661                         JavaScriptSerializer ser = new JavaScriptSerializer ();
662                         Y y = new Y ();
663                         string s = ser.Serialize (y);
664                         object y2 = ser.DeserializeObject (s);
665                         Assert.AreEqual (typeof (Dictionary<string, object>), y2.GetType (), "DeserializeObject to Dictionary");
666                 }
667
668                 [Test]
669                 public void DeserializeObject3 () 
670                 {
671                         JavaScriptSerializer ser = new JavaScriptSerializer (new SimpleTypeResolver());
672                         Y y = new Y ();
673                         string s = ser.Serialize (y);
674                         object y2 = ser.DeserializeObject (s);
675                         Assert.AreEqual (typeof (Y), y2.GetType (), "DeserializeObject to Dictionary");
676                 }
677
678                 [Test]
679                 public void DeserializeObject4 () 
680                 {
681                         JavaScriptSerializer ser = new JavaScriptSerializer (new CustomResolver());
682                         Y y = new Y ();
683                         string s = ser.Serialize (y);
684                         object y2 = ser.DeserializeObject (s);
685                         Assert.AreEqual (typeof (Y), y2.GetType (), "DeserializeObject to Dictionary");
686                         Assert.AreEqual (1, CustomResolver.ResolvedIds.Count, "ResolvedIds Count");
687                         Assert.AreEqual ("Y", CustomResolver.ResolvedIds [0], "ResolvedIds.Y");
688                         Assert.AreEqual (1, CustomResolver.ResolvedTypes.Count, "ResolvedTypes Count");
689                         Assert.AreEqual ("Y", CustomResolver.ResolvedTypes [0], "ResolvedTypes.Y");
690                 }
691
692                 [Test]
693                 [ExpectedException(typeof(ArgumentNullException))]
694                 public void SerializeWithResolverDeserializeWithout () 
695                 {
696                         JavaScriptSerializer ser = new JavaScriptSerializer (new SimpleTypeResolver ());
697                         Y y = new Y ();
698                         string s = ser.Serialize (y);
699                         ser = new JavaScriptSerializer ();
700                         object y2 = ser.DeserializeObject (s);
701                 }
702
703                 [Test]
704                 public void SerializeWithoutResolverDeserializeWith ()
705                 {
706                         JavaScriptSerializer ser = new JavaScriptSerializer ();
707                         Y y = new Y ();
708                         string s = ser.Serialize (y);
709                         ser = new JavaScriptSerializer (new SimpleTypeResolver ());
710                         object y2 = ser.DeserializeObject (s);
711                         Assert.AreEqual (typeof (Dictionary<string, object>), y2.GetType (), "DeserializeObject to Dictionary");
712                 }
713
714                 class B
715                 {
716                         public int v1 = 15;
717                         public string s1 = "s1";
718                 }
719
720                 class D : B
721                 {
722                         public int v2 = 16;
723                         public string s2 = "s2";
724                 }
725
726                 class C
727                 {
728                         public B b1 = new B ();
729                         public B b2 = new D ();
730                 }
731
732                 [Test]
733                 public void SerializeDerivedType () 
734                 {
735                         JavaScriptSerializer ser = new JavaScriptSerializer (new SimpleTypeResolver ());
736                         B b = new D ();
737                         string s = ser.Serialize (b);
738                         B b2 = ser.Deserialize<B> (s);
739                         Assert.AreEqual (typeof (D), b2.GetType (), "Deserialize Derived Type");
740                 }
741
742                 [Test]
743                 public void SerializeDerivedType2 () 
744                 {
745                         JavaScriptSerializer ser = new JavaScriptSerializer (new SimpleTypeResolver ());
746                         B b = new D ();
747                         string s = ser.Serialize (b);
748                         B b2 = (B)ser.DeserializeObject (s);
749                         Assert.AreEqual (typeof (D), b2.GetType (), "Deserialize Derived Type");
750                 }
751
752                 [Test]
753                 public void SerializeContainedDerivedType () 
754                 {
755                         JavaScriptSerializer ser = new JavaScriptSerializer (new SimpleTypeResolver ());
756                         C c = new C ();
757                         string s = ser.Serialize (c);
758                         C c2 = ser.Deserialize<C> (s);
759                         Assert.AreEqual (typeof (C), c2.GetType (), "Deserialize Derived Type");
760                         Assert.AreEqual (typeof (D), c2.b2.GetType (), "Deserialize Derived Type");
761                 }
762
763                 [Test]
764                 public void SerializeContainedDerivedType2 () 
765                 {
766                         JavaScriptSerializer ser = new JavaScriptSerializer (new SimpleTypeResolver ());
767                         C c = new C ();
768                         string s = ser.Serialize (c);
769                         C c2 = (C)ser.DeserializeObject (s);
770                         Assert.AreEqual (typeof (C), c2.GetType (), "Deserialize Derived Type");
771                         Assert.AreEqual (typeof (D), c2.b2.GetType (), "Deserialize Derived Type");
772                 }
773
774                 [Test]
775                 public void SerializeWithTypeConverter () 
776                 {
777                         JavaScriptSerializer ser = new JavaScriptSerializer ();
778                         MyUri uri = new MyUri ("http://kostat@mainsoft/adfasdf/asdfasdf.aspx/asda/ads?a=b&c=d", UriKind.RelativeOrAbsolute);
779                         string s = ser.Serialize (uri);
780                         MyUri uri2 = ser.Deserialize<MyUri> (s);
781                         Assert.AreEqual (uri, uri2);
782                 }
783
784                 [Test]
785                 public void SerializeWithTypeConverter2 () 
786                 {
787                         JavaScriptSerializer ser = new JavaScriptSerializer ();
788                         MyPointContainer pc = new MyPointContainer(new Point(15, 16));
789                         string s = ser.Serialize(pc);
790                         MyPointContainer pc2 = ser.Deserialize<MyPointContainer>(s);
791                 }
792
793                 [Test]
794                 public void MaxJsonLengthDeserializeObject () 
795                 {
796                         JavaScriptSerializer ser = new JavaScriptSerializer ();
797                         ser.MaxJsonLength = 16;
798                         object o = ser.DeserializeObject ("{s:'1234567890'}");
799                 }
800
801                 [Test]
802                 [ExpectedException(typeof(ArgumentException))]
803                 public void MaxJsonLengthDeserializeObjectToLong () 
804                 {
805                         JavaScriptSerializer ser = new JavaScriptSerializer ();
806                         ser.MaxJsonLength = 15;
807                         object o = ser.DeserializeObject ("{s:'1234567890'}");
808                 }
809
810                 [Test]
811                 public void MaxJsonLengthSerialize () 
812                 {
813                         JavaScriptSerializer ser = new JavaScriptSerializer ();
814                         ser.MaxJsonLength = 9;
815                         Y y = new Y ();
816                         string s = ser.Serialize (y);
817                 }
818
819                 [Test]
820                 [ExpectedException (typeof (InvalidOperationException))]
821                 public void MaxJsonLengthSerializeToLong () 
822                 {
823                         JavaScriptSerializer ser = new JavaScriptSerializer ();
824                         ser.MaxJsonLength = 8;
825                         Y y = new Y ();
826                         string s = ser.Serialize (y);
827                 }
828
829                 [Test]
830                 public void RecursionLimitDeserialize1 () 
831                 {
832                         JavaScriptSerializer ser = new JavaScriptSerializer ();
833                         ser.RecursionLimit = 3;
834                         YY yy = ser.Deserialize<YY> ("{\"Y1\":{\"BB\":10},\"Y2\":{\"BB\":10}}");
835                 }
836
837                 [Test]
838                 public void RecursionLimitDeserialize2 () 
839                 {
840                         JavaScriptSerializer ser = new JavaScriptSerializer ();
841                         ser.RecursionLimit = 2;
842                         YY yy = ser.Deserialize<YY> ("{\"Y1\":{},\"Y2\":{}}");
843                 }
844
845                 [Test]
846                 public void RecursionLimitDeserialize3 () 
847                 {
848                         JavaScriptSerializer ser = new JavaScriptSerializer ();
849                         ser.RecursionLimit = 1;
850                         object o = ser.DeserializeObject ("\"xxx\"");
851                 }
852
853                 [Test]
854                 [ExpectedException(typeof(ArgumentException))]
855                 public void RecursionLimitDeserializeToDeep () 
856                 {
857                         JavaScriptSerializer ser = new JavaScriptSerializer ();
858                         ser.RecursionLimit = 2;
859                         YY yy = ser.Deserialize<YY> ("{\"Y1\":{\"BB\":10},\"Y2\":{\"BB\":10}}");
860                 }
861
862                 [Test]
863                 public void RecursionLimitSerialize () 
864                 {
865                         JavaScriptSerializer ser = new JavaScriptSerializer ();
866                         ser.RecursionLimit = 3;
867                         YY yy = new YY();
868                         string s = ser.Serialize (yy);
869                 }
870
871                 [Test]
872                 [ExpectedException(typeof(ArgumentException))]
873                 public void RecursionLimitSerializeToDeep () 
874                 {
875                         JavaScriptSerializer ser = new JavaScriptSerializer ();
876                         ser.RecursionLimit = 2;
877                         YY yy = new YY ();
878                         string s = ser.Serialize (yy);
879                 }
880
881                 [Test]
882                 public void RecursionLimitSerialize2 () 
883                 {
884                         JavaScriptSerializer ser = new JavaScriptSerializer ();
885                         ser.RecursionLimit = 2;
886                         YY yy = new YY ();
887                         StringBuilder b = new StringBuilder ();
888                         bool caughtException = false;
889                         try {
890                                 ser.Serialize (yy, b);
891                         }
892                         catch {
893                                 caughtException = true;
894                         }
895                         Assert.IsTrue (caughtException, "RecursionLimitSerialize2 Expected an exception!");
896                         Assert.AreEqual ("{\"Y1\":{\"BB\":", b.ToString (), "RecursionLimitSerialize2");
897                 }
898
899                 [Test]
900                 public void SimpleTypeResolver () 
901                 {
902                         JavaScriptSerializer ser = new JavaScriptSerializer (new SimpleTypeResolver ());
903                         YY yy = new YY ();
904                         string s = ser.Serialize (yy);
905                         string expected = String.Format("\"__type\":\"{0}\"", yy.GetType().AssemblyQualifiedName);
906
907                         Assert.IsTrue (s.Contains (expected), "YY: expected {0} to contain {1}", s, expected);
908                         
909                         expected = String.Format ("\"__type\":\"{0}\"", yy.Y1.GetType ().AssemblyQualifiedName);
910                         Assert.IsTrue (s.Contains (expected), "Y: expected {0} to contain {1}", s, expected);
911                 }
912
913                 public class CustomResolver : JavaScriptTypeResolver
914                 {
915                         public CustomResolver () 
916                         {
917                                 Reset ();
918                         }
919
920                         public override Type ResolveType (string id) 
921                         {
922                                 ResolvedIds.Add (id);
923
924                                 switch (id) {
925                                 case "YY":
926                                         return typeof(YY);
927
928                                 case "Y":
929                                         return typeof (Y);
930
931                                 case "X":
932                                         return typeof (X);
933
934                                 case "int":
935                                         return typeof (int);
936
937                                 case "long":
938                                         return typeof (long);
939
940                                 case "string":
941                                         return typeof (string);
942
943                                 case "point":
944                                         return typeof(Point);
945                                 }
946                                 return null;
947                         }
948
949                         public override string ResolveTypeId (Type type) 
950                         {
951                                 if (type == null) {
952                                         throw new ArgumentNullException ("type");
953                                 }
954
955                                 ResolvedTypes.Add (type.Name);
956
957                                 if (type == typeof (YY))
958                                         return "YY";
959
960                                 if (type == typeof (Y))
961                                         return "Y";
962
963                                 if (type == typeof (X))
964                                         return "X";
965
966                                 if (type == typeof (int))
967                                         return "int";
968
969                                 if (type == typeof (long))
970                                         return "long";
971
972                                 if (type == typeof (string))
973                                         return "string";
974
975                                 if (type == typeof(Point))
976                                         return "point";
977
978                                 return null;
979                         }
980
981                         public static List<string> ResolvedTypes {
982                                 get {
983                                         if (resolvedTypes == null) {
984                                                 resolvedTypes = new List<string> ();
985                                         }
986                                         return resolvedTypes;
987                                 }
988                         }
989
990                         public static List<string> ResolvedIds {
991                                 get {
992                                         if (resolvedIds == null) {
993                                                 resolvedIds = new List<string> ();
994                                         }
995                                         return resolvedIds;
996                                 }
997                         }
998
999                         public static void Reset () 
1000                         {
1001                                 resolvedIds = null;
1002                                 resolvedTypes = null;
1003                         }
1004
1005                         private static List<string> resolvedTypes;
1006                         private static List<string> resolvedIds;
1007                 }
1008
1009                 [Test]
1010                 [NUnit.Framework.Category ("NotWorking")]
1011                 public void CustomTypeResolver ()
1012                 {
1013                         JavaScriptSerializer ser = new JavaScriptSerializer (new CustomResolver ());
1014                         X x = new X ();
1015                         x.Init ();
1016
1017                         string s = ser.Serialize (x);
1018
1019                         CustomResolver.Reset ();
1020                         X x1 = (X) ser.DeserializeObject (s);
1021                         Assert.IsTrue (x.Equals (x1), "x != x1");
1022
1023                         CustomResolver.Reset ();
1024                         X x2 = ser.Deserialize<X> (s);
1025                         Assert.IsTrue (x.Equals (x2), "x != x2");
1026                 }
1027         }
1028 }