2 // BinaryFormatterTest.cs - Unit tests for
3 // System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
6 // Sebastien Pouliot <sebastien@ximian.com>
8 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
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:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
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.
32 using System.Runtime.Serialization;
33 using System.Runtime.Serialization.Formatters;
34 using System.Runtime.Serialization.Formatters.Binary;
35 using System.Reflection;
37 using NUnit.Framework;
39 namespace MonoTests.System.Runtime.Serialization.Formatters.Binary
42 public class SerializationTest
48 public SerializationTest (bool b, int i)
55 get { return boolean; }
56 set { boolean = value; }
60 get { return integer; }
61 set { integer = value; }
65 class SurrogateSelector: ISurrogateSelector
67 public void ChainSelector (ISurrogateSelector selector)
71 public ISurrogateSelector GetNextSelector ()
76 public ISerializationSurrogate GetSurrogate (Type type, StreamingContext context, out ISurrogateSelector selector)
84 sealed class ThisObjectReference : IObjectReference
86 internal static int Count;
88 internal ThisObjectReference()
92 public object GetRealObject(StreamingContext context)
100 sealed class NewObjectReference : IObjectReference
102 internal static int Count;
104 internal NewObjectReference()
108 public object GetRealObject(StreamingContext context)
111 return new NewObjectReference();
118 private int privateFoo;
119 protected int familyFoo;
120 protected internal int familyANDAssemFoo;
121 public int publicFoo;
122 internal int assemblyFoo;
124 public int PrivateFoo {
125 get { return privateFoo; }
128 public int FamilyFoo {
129 get { return familyFoo; }
132 public int FamilyANDAssemFoo {
133 get { return familyANDAssemFoo; }
136 public int PublicFoo {
137 get { return publicFoo; }
140 public int AssemblyFoo {
141 get { return assemblyFoo; }
144 public virtual void Init ()
148 familyANDAssemFoo = 4;
157 private int privateBar;
158 protected int familyBar;
159 protected internal int familyANDAssemBar;
160 public int publicBar;
161 internal int assemblyBar;
163 public int PrivateBar {
164 get { return privateBar; }
167 public int FamilyBar {
168 get { return familyBar; }
171 public int FamilyANDAssemBar {
172 get { return familyANDAssemBar; }
175 public int PublicBar {
176 get { return publicBar; }
179 public int AssemblyBar {
180 get { return assemblyBar; }
183 public override void Init ()
187 familyANDAssemBar = 4;
196 public class Comparable
203 public override bool Equals (object obj)
205 var other = obj as Comparable;
208 return other.Foo == Foo;
211 public override int GetHashCode ()
218 public class BinaryFormatterTest
221 public void Constructor_Default ()
223 BinaryFormatter bf = new BinaryFormatter ();
225 Assert.AreEqual (FormatterAssemblyStyle.Simple, bf.AssemblyFormat, "AssemblyFormat");
227 Assert.AreEqual (FormatterAssemblyStyle.Full, bf.AssemblyFormat, "AssemblyFormat");
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");
237 public void Constructor ()
239 SurrogateSelector ss = new SurrogateSelector ();
240 BinaryFormatter bf = new BinaryFormatter (ss, new StreamingContext (StreamingContextStates.CrossMachine));
242 Assert.AreEqual (FormatterAssemblyStyle.Simple, bf.AssemblyFormat, "AssemblyFormat");
244 Assert.AreEqual (FormatterAssemblyStyle.Full, bf.AssemblyFormat, "AssemblyFormat");
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");
254 public void Inheritance ()
256 MemoryStream ms = new MemoryStream ();
257 BinaryFormatter bf = new BinaryFormatter ();
259 Bar bar = new Bar ();
262 bf.Serialize (ms, bar);
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");
279 public void SerializationRoundtrip ()
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");
289 public void SerializationUnsafeRoundtrip ()
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");
299 public void NestedObjectReference ()
301 MemoryStream ms = new MemoryStream();
302 BinaryFormatter bf = new BinaryFormatter();
304 bf.Serialize(ms, new ThisObjectReference());
305 bf.Serialize(ms, new NewObjectReference());
307 Assert.AreEqual (0, ThisObjectReference.Count, "#1");
310 Assert.AreEqual (2, ThisObjectReference.Count, "#2");
311 Assert.AreEqual (0, NewObjectReference.Count, "#3");
314 } catch (SerializationException) {
316 Assert.AreEqual (101, NewObjectReference.Count, "#4");
320 public void DateTimeArray ()
322 DateTime [] e = new DateTime [6];
323 string [] names = new string [6];
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;
332 BinaryFormatter bf = new BinaryFormatter ();
333 MemoryStream ms = new MemoryStream ();
335 bf.Serialize (ms, e);
338 DateTime [] a = (DateTime []) bf.Deserialize (ms);
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]);
346 public void GenericArray ()
348 Comparable [] a = new Comparable [1];
349 a [0] = new Comparable ();
351 BinaryFormatter bf = new BinaryFormatter ();
352 MemoryStream ms = new MemoryStream ();
354 bf.Serialize (ms, a);
357 Comparable [] b = (Comparable []) bf.Deserialize (ms);
359 Assert.AreEqual (a.Length, b.Length, "#1");
360 Assert.AreEqual (a [0], b [0], "#2");
363 public Stream GetSerializedStream ()
365 SerializationTest test = new SerializationTest (true, Int32.MinValue);
366 BinaryFormatter bf = new BinaryFormatter ();
367 MemoryStream ms = new MemoryStream ();
368 bf.Serialize (ms, test);
375 public void SerializationBindToName ()
377 BinaryFormatter bf = new BinaryFormatter ();
378 bf.AssemblyFormat = FormatterAssemblyStyle.Full;
379 bf.Binder = new SimpleSerializationBinder ();
380 MemoryStream ms = new MemoryStream ();
382 SimpleSerializableObject o = new SimpleSerializableObject ();
383 o.Name = "MonoObject";
386 bf.Serialize (ms, o);
389 o = (SimpleSerializableObject)bf.Deserialize (ms);
390 Assert.AreEqual ("MonoObject", o.Name);
391 Assert.AreEqual (666, o.Id);
394 class SimpleSerializationBinder : SerializationBinder
396 public override Type BindToType (string assemblyName, string typeName)
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");
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");
410 // No need to call Type.GetType
411 return typeof (SimpleSerializableObject);
414 public override void BindToName (Type serializedType, out string assemblyName, out string typeName)
416 AssemblyName aname = Assembly.GetExecutingAssembly ().GetName ();
417 aname.Version = new Version (9, 9, 9, 9);
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");
427 class SimpleSerializableObject
429 public string Name { get; set; }
430 public int Id { get; set; }
434 public void SerializationBindToName2 ()
436 BinaryFormatter bf = new BinaryFormatter ();
437 bf.AssemblyFormat = FormatterAssemblyStyle.Full;
438 bf.Binder = new SimpleSerializationBinder2 ();
439 MemoryStream ms = new MemoryStream ();
441 SimpleISerializableObject o = new SimpleISerializableObject ();
442 o.Name = "MonoObject";
445 bf.Serialize (ms, o);
448 o = (SimpleISerializableObject)bf.Deserialize (ms);
449 Assert.AreEqual ("MonoObject", o.Name);
450 Assert.AreEqual (666, o.Id);
455 class SimpleSerializationBinder2 : SerializationBinder
457 public override void BindToName (Type serializedType, out string assemblyName, out string typeName)
459 AssemblyName aname = Assembly.GetExecutingAssembly ().GetName ();
460 aname.Version = new Version (9, 9, 9, 9);
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");
468 public override Type BindToType (string assemblyName, string typeName)
470 // We *should* be getting a SimpleISerializableObject2 instance
471 if (!typeName.EndsWith ("SimpleISerializableObject2"))
472 Assert.Fail ("#BindToType-TypeName");
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");
481 return typeof (SimpleISerializableObject);
486 class SimpleISerializableObject : ISerializable
488 public string Name { get; set; }
489 public int Id { get; set; }
491 public SimpleISerializableObject ()
495 protected SimpleISerializableObject (SerializationInfo info, StreamingContext context)
497 Name = info.GetString ("Name");
498 Id = info.GetInt32 ("Id");
501 public void GetObjectData (SerializationInfo info, StreamingContext context)
503 info.AddValue ("Name", Name);
504 info.AddValue ("Id", Id);