Add unit test for AggregateException.GetBaseException that works on .net but is broke...
[mono.git] / mcs / class / corlib / Test / System.Runtime.Serialization.Formatters.Binary / BinaryFormatterTest.cs
1 //
2 // BinaryFormatterTest.cs - Unit tests for 
3 //      System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
4 //
5 // Author:
6 //      Sebastien Pouliot  <sebastien@ximian.com>
7 //
8 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
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.IO;
32 using System.Runtime.Serialization;
33 using System.Runtime.Serialization.Formatters;
34 using System.Runtime.Serialization.Formatters.Binary;
35 using System.Reflection;
36
37 using NUnit.Framework;
38
39 namespace MonoTests.System.Runtime.Serialization.Formatters.Binary
40 {
41         [Serializable]
42         public class SerializationTest
43         {
44                 private int integer;
45                 [NonSerialized]
46                 private bool boolean;
47
48                 public SerializationTest (bool b, int i)
49                 {
50                         boolean = b;
51                         integer = i;
52                 }
53
54                 public bool Boolean {
55                         get { return boolean; }
56                         set { boolean = value; }
57                 }
58
59                 public int Integer {
60                         get { return integer; }
61                         set { integer = value; }
62                 }
63         }
64
65         class SurrogateSelector: ISurrogateSelector
66         {
67                 public void ChainSelector (ISurrogateSelector selector)
68                 {
69                 }
70
71                 public ISurrogateSelector GetNextSelector ()
72                 {
73                         return null;
74                 }
75
76                 public ISerializationSurrogate GetSurrogate (Type type, StreamingContext context, out ISurrogateSelector selector)
77                 {
78                         selector = null;
79                         return null;
80                 }
81         }
82
83         [Serializable]
84         sealed class ThisObjectReference : IObjectReference
85         {
86                 internal static int Count;
87
88                 internal ThisObjectReference()
89                 {
90                 }
91
92                 public object GetRealObject(StreamingContext context)
93                 {
94                         Count++;
95                         return this;
96                 }
97         }
98
99         [Serializable]
100         sealed class NewObjectReference : IObjectReference
101         {
102                 internal static int Count;
103
104                 internal NewObjectReference()
105                 {
106                 }
107
108                 public object GetRealObject(StreamingContext context)
109                 {
110                         Count++;
111                         return new NewObjectReference();
112                 }
113         }
114
115         [Serializable]
116         class Foo
117         {
118                 private int privateFoo;
119                 protected int familyFoo;
120                 protected internal int familyANDAssemFoo;
121                 public int publicFoo;
122                 internal int assemblyFoo;
123
124                 public int PrivateFoo {
125                         get { return privateFoo; }
126                 }
127
128                 public int FamilyFoo {
129                         get { return familyFoo; }
130                 }
131
132                 public int FamilyANDAssemFoo {
133                         get { return familyANDAssemFoo; }
134                 }
135
136                 public int PublicFoo {
137                         get { return publicFoo; }
138                 }
139
140                 public int AssemblyFoo {
141                         get { return assemblyFoo; }
142                 }
143
144                 public virtual void Init ()
145                 {
146                         privateFoo = 1;
147                         familyFoo = 2;
148                         familyANDAssemFoo = 4;
149                         publicFoo = 8;
150                         assemblyFoo = 16;
151                 }
152         }
153
154         [Serializable]
155         class Bar : Foo
156         {
157                 private int privateBar;
158                 protected int familyBar;
159                 protected internal int familyANDAssemBar;
160                 public int publicBar;
161                 internal int assemblyBar;
162
163                 public int PrivateBar {
164                         get { return privateBar; }
165                 }
166
167                 public int FamilyBar {
168                         get { return familyBar; }
169                 }
170
171                 public int FamilyANDAssemBar {
172                         get { return familyANDAssemBar; }
173                 }
174
175                 public int PublicBar {
176                         get { return publicBar; }
177                 }
178
179                 public int AssemblyBar {
180                         get { return assemblyBar; }
181                 }
182
183                 public override void Init ()
184                 {
185                         privateBar = 1;
186                         familyBar = 2;
187                         familyANDAssemBar = 4;
188                         publicBar = 8;
189                         assemblyBar = 16;
190
191                         base.Init ();
192                 }
193         }
194
195         [Serializable]
196         public class Comparable
197         {
198                 public int Foo {
199                         get;
200                         set;
201                 }
202
203                 public override bool Equals (object obj)
204                 {
205                         var other = obj as Comparable;
206                         if (other == null)
207                                 return false;
208                         return other.Foo == Foo;
209                 }
210
211                 public override int GetHashCode ()
212                 {
213                         return Foo;
214                 }
215         }
216
217         [TestFixture]
218         public class BinaryFormatterTest
219         {
220                 [Test]
221                 public void Constructor_Default ()
222                 {
223                         BinaryFormatter bf = new BinaryFormatter ();
224 #if NET_2_0
225                         Assert.AreEqual (FormatterAssemblyStyle.Simple, bf.AssemblyFormat, "AssemblyFormat");
226 #else
227                         Assert.AreEqual (FormatterAssemblyStyle.Full, bf.AssemblyFormat, "AssemblyFormat");
228 #endif
229                         Assert.IsNull (bf.Binder, "Binder");
230                         Assert.AreEqual (StreamingContextStates.All, bf.Context.State, "Context");
231                         Assert.AreEqual (TypeFilterLevel.Full, bf.FilterLevel, "FilterLevel");
232                         Assert.IsNull (bf.SurrogateSelector, "SurrogateSelector");
233                         Assert.AreEqual (FormatterTypeStyle.TypesAlways, bf.TypeFormat, "TypeFormat");
234                 }
235
236                 [Test]
237                 public void Constructor ()
238                 {
239                         SurrogateSelector ss = new SurrogateSelector ();
240                         BinaryFormatter bf = new BinaryFormatter (ss, new StreamingContext (StreamingContextStates.CrossMachine));
241 #if NET_2_0
242                         Assert.AreEqual (FormatterAssemblyStyle.Simple, bf.AssemblyFormat, "AssemblyFormat");
243 #else
244                         Assert.AreEqual (FormatterAssemblyStyle.Full, bf.AssemblyFormat, "AssemblyFormat");
245 #endif
246                         Assert.IsNull (bf.Binder, "Binder");
247                         Assert.AreEqual (StreamingContextStates.CrossMachine, bf.Context.State, "Context");
248                         Assert.AreEqual (TypeFilterLevel.Full, bf.FilterLevel, "FilterLevel");
249                         Assert.AreSame (ss, bf.SurrogateSelector, "SurrogateSelector");
250                         Assert.AreEqual (FormatterTypeStyle.TypesAlways, bf.TypeFormat, "TypeFormat");
251                 }
252
253                 [Test]
254                 public void Inheritance ()
255                 {
256                         MemoryStream ms = new MemoryStream ();
257                         BinaryFormatter bf = new BinaryFormatter ();
258
259                         Bar bar = new Bar ();
260                         bar.Init ();
261
262                         bf.Serialize (ms, bar);
263                         ms.Position = 0;
264
265                         Bar clone = (Bar) bf.Deserialize (ms);
266                         Assert.AreEqual (bar.PrivateBar, clone.PrivateBar, "#1");
267                         Assert.AreEqual (bar.FamilyBar, clone.FamilyBar, "#2");
268                         Assert.AreEqual (bar.FamilyANDAssemBar, clone.FamilyANDAssemBar, "#3");
269                         Assert.AreEqual (bar.PublicBar, clone.PublicBar, "#4");
270                         Assert.AreEqual (bar.AssemblyBar, clone.AssemblyBar, "#5");
271                         Assert.AreEqual (bar.PrivateFoo, clone.PrivateFoo, "#6");
272                         Assert.AreEqual (bar.FamilyFoo, clone.FamilyFoo, "#7");
273                         Assert.AreEqual (bar.FamilyANDAssemFoo, clone.FamilyANDAssemFoo, "#8");
274                         Assert.AreEqual (bar.PublicFoo, clone.PublicFoo, "#9");
275                         Assert.AreEqual (bar.AssemblyFoo, clone.AssemblyFoo, "#10");
276                 }
277
278                 [Test]
279                 public void SerializationRoundtrip ()
280                 {
281                         Stream s = GetSerializedStream ();
282                         BinaryFormatter bf = new BinaryFormatter ();
283                         SerializationTest clone = (SerializationTest) bf.Deserialize (s);
284                         Assert.AreEqual (Int32.MinValue, clone.Integer, "Integer");
285                         Assert.IsFalse (clone.Boolean, "Boolean");
286                 }
287
288                 [Test]
289                 public void SerializationUnsafeRoundtrip ()
290                 {
291                         Stream s = GetSerializedStream ();
292                         BinaryFormatter bf = new BinaryFormatter ();
293                         SerializationTest clone = (SerializationTest) bf.UnsafeDeserialize (s, null);
294                         Assert.AreEqual (Int32.MinValue, clone.Integer, "Integer");
295                         Assert.IsFalse (clone.Boolean, "Boolean");
296                 }
297                 
298                 [Test]
299                 public void NestedObjectReference ()
300                 {
301                         MemoryStream ms = new MemoryStream();
302                         BinaryFormatter bf = new BinaryFormatter();
303
304                         bf.Serialize(ms, new ThisObjectReference());
305                         bf.Serialize(ms, new NewObjectReference());
306                         ms.Position = 0;
307                         Assert.AreEqual (0, ThisObjectReference.Count, "#1");
308
309                         bf.Deserialize(ms);
310                         Assert.AreEqual (2, ThisObjectReference.Count, "#2");
311                         Assert.AreEqual (0, NewObjectReference.Count, "#3");
312                         try {
313                                 bf.Deserialize(ms);
314                         } catch (SerializationException) {
315                         }
316                         Assert.AreEqual (101, NewObjectReference.Count, "#4");
317                 }
318
319                 [Test]
320                 public void DateTimeArray ()
321                 {
322                         DateTime [] e = new DateTime [6];
323                         string [] names = new string [6];
324
325                         names [0] = "Today";  e [0] = DateTime.Today;
326                         names [1] = "Min";    e [1] = DateTime.MinValue;
327                         names [2] = "Max";    e [2] = DateTime.MaxValue;
328                         names [3] = "BiCent"; e [3] = new DateTime (1976, 07, 04);
329                         names [4] = "Now";    e [4] = DateTime.Now;
330                         names [5] = "UtcNow"; e [5] = DateTime.UtcNow;
331
332                         BinaryFormatter bf = new BinaryFormatter ();
333                         MemoryStream ms = new MemoryStream ();
334
335                         bf.Serialize (ms, e);
336
337                         ms.Position = 0;
338                         DateTime [] a = (DateTime []) bf.Deserialize (ms);
339
340                         Assert.AreEqual (e.Length, a.Length);
341                         for (int i = 0; i < e.Length; ++i)
342                                 Assert.AreEqual (e [i], a [i], names [i]);
343                 }
344
345                 [Test]
346                 public void GenericArray ()
347                 {
348                         Comparable [] a = new Comparable [1];
349                         a [0] = new Comparable ();
350
351                         BinaryFormatter bf = new BinaryFormatter ();
352                         MemoryStream ms = new MemoryStream ();
353
354                         bf.Serialize (ms, a);
355
356                         ms.Position = 0;
357                         Comparable [] b = (Comparable []) bf.Deserialize (ms);
358
359                         Assert.AreEqual (a.Length, b.Length, "#1");
360                         Assert.AreEqual (a [0], b [0], "#2");
361                 }
362
363                 public Stream GetSerializedStream ()
364                 {
365                         SerializationTest test = new SerializationTest (true, Int32.MinValue);
366                         BinaryFormatter bf = new BinaryFormatter ();
367                         MemoryStream ms = new MemoryStream ();
368                         bf.Serialize (ms, test);
369                         ms.Position = 0;
370                         return ms;
371                 }
372
373 #if NET_4_0
374                 [Test]
375                 public void SerializationBindToName ()
376                 {
377                         BinaryFormatter bf = new BinaryFormatter ();
378                         bf.AssemblyFormat = FormatterAssemblyStyle.Full;
379                         bf.Binder = new SimpleSerializationBinder ();
380                         MemoryStream ms = new MemoryStream ();
381
382                         SimpleSerializableObject o = new SimpleSerializableObject ();
383                         o.Name = "MonoObject";
384                         o.Id = 666;
385
386                         bf.Serialize (ms, o);
387                         ms.Position = 0;
388
389                         o = (SimpleSerializableObject)bf.Deserialize (ms);
390                         Assert.AreEqual ("MonoObject", o.Name);
391                         Assert.AreEqual (666, o.Id);
392                 }
393
394                 class SimpleSerializationBinder : SerializationBinder
395                 {
396                         public override Type BindToType (string assemblyName, string typeName)
397                         {
398                                 // We *should* be getting a SimpleSerializableObject2 instance
399                                 // Otherwise it means we are not getting called our BindToName method.
400                                 if (!typeName.EndsWith ("SimpleSerializableObject2"))
401                                         Assert.Fail ("#BindToType-TypeName");
402
403                                 // We are also supposed to be getting a 9.9.9.9 version here,
404                                 // and if we get a different version, it likely means BindToName was called.
405                                 AssemblyName aname = Assembly.GetExecutingAssembly ().GetName ();
406                                 aname.Version = new Version (9, 9, 9, 9);
407                                 if (aname.ToString () != assemblyName)
408                                         Assert.Fail ("#BindToType-AssemblyName");
409
410                                 // No need to call Type.GetType
411                                 return typeof (SimpleSerializableObject);
412                         }
413
414                         public override void BindToName (Type serializedType, out string assemblyName, out string typeName)
415                         {
416                                 AssemblyName aname = Assembly.GetExecutingAssembly ().GetName ();
417                                 aname.Version = new Version (9, 9, 9, 9);
418
419                                 // Serialize mapping to this same assembly with 9.9.9.9 version
420                                 // and a different type name.
421                                 assemblyName = aname.ToString ();
422                                 typeName = serializedType.FullName.Replace ("SimpleSerializableObject", "SimpleSerializableObject2");
423                         }
424                 }
425
426                 [Serializable]
427                 class SimpleSerializableObject
428                 {
429                         public string Name { get; set; }
430                         public int Id { get; set; }
431                 }
432
433                 [Test]
434                 public void SerializationBindToName2 ()
435                 {
436                         BinaryFormatter bf = new BinaryFormatter ();
437                         bf.AssemblyFormat = FormatterAssemblyStyle.Full;
438                         bf.Binder = new SimpleSerializationBinder2 ();
439                         MemoryStream ms = new MemoryStream ();
440
441                         SimpleISerializableObject o = new SimpleISerializableObject ();
442                         o.Name = "MonoObject";
443                         o.Id = 666;
444
445                         bf.Serialize (ms, o);
446                         ms.Position = 0;
447
448                         o = (SimpleISerializableObject)bf.Deserialize (ms);
449                         Assert.AreEqual ("MonoObject", o.Name);
450                         Assert.AreEqual (666, o.Id);
451
452                         ms.Close ();
453                 }
454
455                 class SimpleSerializationBinder2 : SerializationBinder
456                 {
457                         public override void BindToName (Type serializedType, out string assemblyName, out string typeName)
458                         {
459                                 AssemblyName aname = Assembly.GetExecutingAssembly ().GetName ();
460                                 aname.Version = new Version (9, 9, 9, 9);
461
462                                 // Serialize mapping to this same assembly with 9.9.9.9 version
463                                 // and a different type name.
464                                 assemblyName = aname.ToString ();
465                                 typeName = serializedType.FullName.Replace ("SimpleISerializableObject", "SimpleISerializableObject2");
466                         }
467
468                         public override Type BindToType (string assemblyName, string typeName)
469                         {
470                                 // We *should* be getting a SimpleISerializableObject2 instance
471                                 if (!typeName.EndsWith ("SimpleISerializableObject2"))
472                                         Assert.Fail ("#BindToType-TypeName");
473
474                                 // We are also supposed to be getting a 9.9.9.9 version here,
475                                 // and if we get a different version, it likely means BindToName was called.
476                                 AssemblyName aname = Assembly.GetExecutingAssembly ().GetName ();
477                                 aname.Version = new Version (9, 9, 9, 9);
478                                 if (aname.ToString () != assemblyName)
479                                         Assert.Fail ("#BindToType-AssemblyName");
480
481                                 return typeof (SimpleISerializableObject);
482                         }
483                 }
484
485                 [Serializable]
486                 class SimpleISerializableObject : ISerializable
487                 {
488                         public string Name { get; set; }
489                         public int Id { get; set; }
490
491                         public SimpleISerializableObject ()
492                         {
493                         }
494
495                         protected SimpleISerializableObject (SerializationInfo info, StreamingContext context)
496                         {
497                                 Name = info.GetString ("Name");
498                                 Id = info.GetInt32 ("Id");
499                         }
500
501                         public void GetObjectData (SerializationInfo info, StreamingContext context)
502                         {
503                                 info.AddValue ("Name", Name);
504                                 info.AddValue ("Id", Id);
505                         }
506                 }
507 #endif
508         }
509 }