using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
+using System.Reflection;
using NUnit.Framework;
-namespace MonoTests.System.Runtime.Serialization.Formatters.Binary {
-
+namespace MonoTests.System.Runtime.Serialization.Formatters.Binary
+{
[Serializable]
- public class SerializationTest {
+ public class SerializationTest
+ {
private int integer;
[NonSerialized]
private bool boolean;
}
}
- class SurrogateSelector: ISurrogateSelector {
+ namespace NestedA
+ {
+ [Serializable]
+ public class QualifiedFieldTest
+ {
+ int value = 0;
+
+ public int ValueA {
+ get { return value; }
+ set { this.value = value; }
+ }
+ }
+ }
+
+ namespace NestedB
+ {
+ [Serializable]
+ public class QualifiedFieldTest : NestedA.QualifiedFieldTest
+ {
+ int value = 0;
+
+ public int ValueB {
+ get { return value; }
+ set { this.value = value; }
+ }
+ }
+ }
+
+ [Serializable]
+ public class QualifiedFieldTest : NestedB.QualifiedFieldTest
+ {
+ int value = 0;
+
+ public int Value {
+ get { return value; }
+ set { this.value = value; }
+ }
+ }
+
+ class SurrogateSelector: ISurrogateSelector
+ {
public void ChainSelector (ISurrogateSelector selector)
{
}
}
}
- [TestFixture]
- public class BinaryFormatterTest {
+ [Serializable]
+ class Foo
+ {
+ private int privateFoo;
+ protected int familyFoo;
+ protected internal int familyANDAssemFoo;
+ public int publicFoo;
+ internal int assemblyFoo;
+
+ public int PrivateFoo {
+ get { return privateFoo; }
+ }
+
+ public int FamilyFoo {
+ get { return familyFoo; }
+ }
+
+ public int FamilyANDAssemFoo {
+ get { return familyANDAssemFoo; }
+ }
+
+ public int PublicFoo {
+ get { return publicFoo; }
+ }
+
+ public int AssemblyFoo {
+ get { return assemblyFoo; }
+ }
+ public virtual void Init ()
+ {
+ privateFoo = 1;
+ familyFoo = 2;
+ familyANDAssemFoo = 4;
+ publicFoo = 8;
+ assemblyFoo = 16;
+ }
+ }
+
+ [Serializable]
+ class Bar : Foo
+ {
+ private int privateBar;
+ protected int familyBar;
+ protected internal int familyANDAssemBar;
+ public int publicBar;
+ internal int assemblyBar;
+
+ public int PrivateBar {
+ get { return privateBar; }
+ }
+
+ public int FamilyBar {
+ get { return familyBar; }
+ }
+
+ public int FamilyANDAssemBar {
+ get { return familyANDAssemBar; }
+ }
+
+ public int PublicBar {
+ get { return publicBar; }
+ }
+
+ public int AssemblyBar {
+ get { return assemblyBar; }
+ }
+
+ public override void Init ()
+ {
+ privateBar = 1;
+ familyBar = 2;
+ familyANDAssemBar = 4;
+ publicBar = 8;
+ assemblyBar = 16;
+
+ base.Init ();
+ }
+ }
+
+ [Serializable]
+ public class Comparable
+ {
+ public int Foo {
+ get;
+ set;
+ }
+
+ public override bool Equals (object obj)
+ {
+ var other = obj as Comparable;
+ if (other == null)
+ return false;
+ return other.Foo == Foo;
+ }
+
+ public override int GetHashCode ()
+ {
+ return Foo;
+ }
+ }
+
+ class Class
+ {
+ public string Name;
+
+ public virtual Instance NewInstance()
+ {
+ return new Instance { Class = this };
+ }
+ }
+
+ class Instance
+ {
+ public Class Class;
+ }
+
+
+ [Serializable]
+ class ClassSerializationProxy : IObjectReference
+ {
+ string className;
+
+ public ClassSerializationProxy (Class klass)
+ {
+ this.className = klass.Name;
+ }
+
+ public object GetRealObject(StreamingContext context)
+ {
+ return new Class { Name = className };
+ }
+ }
+
+ [Serializable]
+ class ObjectStreamClass : Class, IObjectReference, ISerializable
+ {
+ Class klass;
+
+ public ObjectStreamClass (Class klass)
+ {
+ this.klass = klass;
+ }
+
+ public ObjectStreamClass(SerializationInfo info, StreamingContext context)
+ {
+ klass = (Class)info.GetValue("0", typeof(object));
+ }
+
+ public object GetRealObject (StreamingContext context)
+ {
+ return this;
+ }
+
+ public void GetObjectData (SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue ("0", new ClassSerializationProxy (klass));
+ }
+
+ public override Instance NewInstance()
+ {
+ return klass.NewInstance();
+ }
+ }
+
+ [Serializable]
+ class DynamicProxy: IObjectReference, ISerializable
+ {
+ Instance obj;
+
+ public DynamicProxy (Instance obj)
+ {
+ this.obj = obj;
+ }
+
+ public DynamicProxy (SerializationInfo info, StreamingContext context)
+ {
+ ObjectStreamClass osc = (ObjectStreamClass) info.GetValue("0", typeof(object));
+ obj = osc.NewInstance();
+ }
+
+ public object GetRealObject (StreamingContext context)
+ {
+ return obj;
+ }
+
+ public void GetObjectData (SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue ("0", new ObjectStreamClass (obj.Class));
+ }
+ }
+
+ [TestFixture]
+ public class BinaryFormatterTest
+ {
[Test]
public void Constructor_Default ()
{
BinaryFormatter bf = new BinaryFormatter ();
-#if NET_2_0
Assert.AreEqual (FormatterAssemblyStyle.Simple, bf.AssemblyFormat, "AssemblyFormat");
-#else
- Assert.AreEqual (FormatterAssemblyStyle.Full, bf.AssemblyFormat, "AssemblyFormat");
-#endif
Assert.IsNull (bf.Binder, "Binder");
Assert.AreEqual (StreamingContextStates.All, bf.Context.State, "Context");
Assert.AreEqual (TypeFilterLevel.Full, bf.FilterLevel, "FilterLevel");
{
SurrogateSelector ss = new SurrogateSelector ();
BinaryFormatter bf = new BinaryFormatter (ss, new StreamingContext (StreamingContextStates.CrossMachine));
-#if NET_2_0
Assert.AreEqual (FormatterAssemblyStyle.Simple, bf.AssemblyFormat, "AssemblyFormat");
-#else
- Assert.AreEqual (FormatterAssemblyStyle.Full, bf.AssemblyFormat, "AssemblyFormat");
-#endif
Assert.IsNull (bf.Binder, "Binder");
Assert.AreEqual (StreamingContextStates.CrossMachine, bf.Context.State, "Context");
Assert.AreEqual (TypeFilterLevel.Full, bf.FilterLevel, "FilterLevel");
Assert.AreEqual (FormatterTypeStyle.TypesAlways, bf.TypeFormat, "TypeFormat");
}
- public Stream GetSerializedStream ()
+ [Test]
+ public void Inheritance ()
{
- SerializationTest test = new SerializationTest (true, Int32.MinValue);
- BinaryFormatter bf = new BinaryFormatter ();
MemoryStream ms = new MemoryStream ();
- bf.Serialize (ms, test);
+ BinaryFormatter bf = new BinaryFormatter ();
+
+ Bar bar = new Bar ();
+ bar.Init ();
+
+ bf.Serialize (ms, bar);
ms.Position = 0;
- return ms;
+
+ Bar clone = (Bar) bf.Deserialize (ms);
+ Assert.AreEqual (bar.PrivateBar, clone.PrivateBar, "#1");
+ Assert.AreEqual (bar.FamilyBar, clone.FamilyBar, "#2");
+ Assert.AreEqual (bar.FamilyANDAssemBar, clone.FamilyANDAssemBar, "#3");
+ Assert.AreEqual (bar.PublicBar, clone.PublicBar, "#4");
+ Assert.AreEqual (bar.AssemblyBar, clone.AssemblyBar, "#5");
+ Assert.AreEqual (bar.PrivateFoo, clone.PrivateFoo, "#6");
+ Assert.AreEqual (bar.FamilyFoo, clone.FamilyFoo, "#7");
+ Assert.AreEqual (bar.FamilyANDAssemFoo, clone.FamilyANDAssemFoo, "#8");
+ Assert.AreEqual (bar.PublicFoo, clone.PublicFoo, "#9");
+ Assert.AreEqual (bar.AssemblyFoo, clone.AssemblyFoo, "#10");
}
[Test]
bf.Deserialize(ms);
Assert.AreEqual (2, ThisObjectReference.Count, "#2");
Assert.AreEqual (0, NewObjectReference.Count, "#3");
- try
- {
+ try {
bf.Deserialize(ms);
- }
- catch (SerializationException e)
- {
+ } catch (SerializationException) {
}
Assert.AreEqual (101, NewObjectReference.Count, "#4");
}
for (int i = 0; i < e.Length; ++i)
Assert.AreEqual (e [i], a [i], names [i]);
}
+
+ [Test]
+ public void GenericArray ()
+ {
+ Comparable [] a = new Comparable [1];
+ a [0] = new Comparable ();
+
+ BinaryFormatter bf = new BinaryFormatter ();
+ MemoryStream ms = new MemoryStream ();
+
+ bf.Serialize (ms, a);
+
+ ms.Position = 0;
+ Comparable [] b = (Comparable []) bf.Deserialize (ms);
+
+ Assert.AreEqual (a.Length, b.Length, "#1");
+ Assert.AreEqual (a [0], b [0], "#2");
+ }
+
+ public Stream GetSerializedStream ()
+ {
+ SerializationTest test = new SerializationTest (true, Int32.MinValue);
+ BinaryFormatter bf = new BinaryFormatter ();
+ MemoryStream ms = new MemoryStream ();
+ bf.Serialize (ms, test);
+ ms.Position = 0;
+ return ms;
+ }
+
+ [Test]
+ public void QualifiedField()
+ {
+ QualifiedFieldTest a = new QualifiedFieldTest ();
+ a.ValueA = 1;
+ a.ValueB = 2;
+ a.Value = 3;
+ Stream ms = new MemoryStream ();
+ BinaryFormatter bf = new BinaryFormatter ();
+ bf.Serialize(ms, a);
+ ms.Position = 0;
+ QualifiedFieldTest b = (QualifiedFieldTest)bf.Deserialize (ms);
+ Assert.AreEqual (a.ValueA, b.ValueA, "#1");
+ Assert.AreEqual (a.ValueB, b.ValueB, "#2");
+ Assert.AreEqual (a.Value, b.Value, "#3");
+ }
+
+#if NET_4_0
+ [Test]
+ public void SerializationBindToName ()
+ {
+ BinaryFormatter bf = new BinaryFormatter ();
+ bf.AssemblyFormat = FormatterAssemblyStyle.Full;
+ bf.Binder = new SimpleSerializationBinder ();
+ MemoryStream ms = new MemoryStream ();
+
+ SimpleSerializableObject o = new SimpleSerializableObject ();
+ o.Name = "MonoObject";
+ o.Id = 666;
+
+ bf.Serialize (ms, o);
+ ms.Position = 0;
+
+ o = (SimpleSerializableObject)bf.Deserialize (ms);
+ Assert.AreEqual ("MonoObject", o.Name);
+ Assert.AreEqual (666, o.Id);
+ }
+
+ class SimpleSerializationBinder : SerializationBinder
+ {
+ public override Type BindToType (string assemblyName, string typeName)
+ {
+ // We *should* be getting a SimpleSerializableObject2 instance
+ // Otherwise it means we are not getting called our BindToName method.
+ if (!typeName.EndsWith ("SimpleSerializableObject2"))
+ Assert.Fail ("#BindToType-TypeName");
+
+ // We are also supposed to be getting a 9.9.9.9 version here,
+ // and if we get a different version, it likely means BindToName was called.
+ AssemblyName aname = Assembly.GetExecutingAssembly ().GetName ();
+ aname.Version = new Version (9, 9, 9, 9);
+ if (aname.ToString () != assemblyName)
+ Assert.Fail ("#BindToType-AssemblyName");
+
+ // No need to call Type.GetType
+ return typeof (SimpleSerializableObject);
+ }
+
+ public override void BindToName (Type serializedType, out string assemblyName, out string typeName)
+ {
+ AssemblyName aname = Assembly.GetExecutingAssembly ().GetName ();
+ aname.Version = new Version (9, 9, 9, 9);
+
+ // Serialize mapping to this same assembly with 9.9.9.9 version
+ // and a different type name.
+ assemblyName = aname.ToString ();
+ typeName = serializedType.FullName.Replace ("SimpleSerializableObject", "SimpleSerializableObject2");
+ }
+ }
+
+ [Serializable]
+ class SimpleSerializableObject
+ {
+ public string Name { get; set; }
+ public int Id { get; set; }
+ }
+
+ [Test]
+ public void SerializationBindToName2 ()
+ {
+ BinaryFormatter bf = new BinaryFormatter ();
+ bf.AssemblyFormat = FormatterAssemblyStyle.Full;
+ bf.Binder = new SimpleSerializationBinder2 ();
+ MemoryStream ms = new MemoryStream ();
+
+ SimpleISerializableObject o = new SimpleISerializableObject ();
+ o.Name = "MonoObject";
+ o.Id = 666;
+
+ bf.Serialize (ms, o);
+ ms.Position = 0;
+
+ o = (SimpleISerializableObject)bf.Deserialize (ms);
+ Assert.AreEqual ("MonoObject", o.Name);
+ Assert.AreEqual (666, o.Id);
+
+ ms.Close ();
+ }
+
+ [Test]
+ public void NestedObjectReferences ()
+ {
+ MemoryStream ms = new MemoryStream ();
+
+ var cls = new Class { Name = "MyClass" };
+ var ob = cls.NewInstance ();
+
+ BinaryFormatter bf = new BinaryFormatter();
+ bf.Serialize (ms, new DynamicProxy (ob));
+
+ ms.Position = 0;
+
+ Instance ins = (Instance) bf.Deserialize (ms);
+ Assert.AreEqual ("MyClass", ins.Class.Name);
+ }
+
+ class SimpleSerializationBinder2 : SerializationBinder
+ {
+ public override void BindToName (Type serializedType, out string assemblyName, out string typeName)
+ {
+ AssemblyName aname = Assembly.GetExecutingAssembly ().GetName ();
+ aname.Version = new Version (9, 9, 9, 9);
+
+ // Serialize mapping to this same assembly with 9.9.9.9 version
+ // and a different type name.
+ assemblyName = aname.ToString ();
+ typeName = serializedType.FullName.Replace ("SimpleISerializableObject", "SimpleISerializableObject2");
+ }
+
+ public override Type BindToType (string assemblyName, string typeName)
+ {
+ // We *should* be getting a SimpleISerializableObject2 instance
+ if (!typeName.EndsWith ("SimpleISerializableObject2"))
+ Assert.Fail ("#BindToType-TypeName");
+
+ // We are also supposed to be getting a 9.9.9.9 version here,
+ // and if we get a different version, it likely means BindToName was called.
+ AssemblyName aname = Assembly.GetExecutingAssembly ().GetName ();
+ aname.Version = new Version (9, 9, 9, 9);
+ if (aname.ToString () != assemblyName)
+ Assert.Fail ("#BindToType-AssemblyName");
+
+ return typeof (SimpleISerializableObject);
+ }
+ }
+
+ [Serializable]
+ class SimpleISerializableObject : ISerializable
+ {
+ public string Name { get; set; }
+ public int Id { get; set; }
+
+ public SimpleISerializableObject ()
+ {
+ }
+
+ protected SimpleISerializableObject (SerializationInfo info, StreamingContext context)
+ {
+ Name = info.GetString ("Name");
+ Id = info.GetInt32 ("Id");
+ }
+
+ public void GetObjectData (SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue ("Name", Name);
+ info.AddValue ("Id", Id);
+ }
+ }
+
+ [Serializable]
+ public class OtherClass
+ {
+ }
+
+ [Serializable]
+ public class BaseClass
+ {
+ public OtherClass Other { get; set; }
+ }
+
+ public class CustomSerBinder: SerializationBinder
+ {
+ public override void BindToName (Type serializedType, out string assemblyName, out string typeName)
+ {
+ assemblyName = null;
+ if (serializedType == typeof (BaseClass))
+ typeName = "base";
+ else if (serializedType == typeof (OtherClass))
+ typeName = "other";
+ else
+ throw new ArgumentException ("Unknown type", "serializedType");
+ }
+
+ public override Type BindToType (string assemblyName, string typeName)
+ {
+ switch (typeName) {
+ case "base":
+ return typeof (BaseClass);
+ case "other":
+ return typeof (OtherClass);
+ default:
+ throw new ArgumentException ("Unknown type name", "typeName");
+ }
+ }
+ }
+
+ [Test]
+ public void BinderShouldBeUsedForProperties ()
+ {
+ using (var serStream = new MemoryStream ()) {
+ var binder = new CustomSerBinder ();
+
+ // serialize
+ var original = new BaseClass () {
+ Other = new OtherClass ()
+ };
+ var formatter = new BinaryFormatter ();
+ formatter.Binder = binder;
+ formatter.Serialize (serStream, original);
+
+ // deserialize, making sure we're using a new formatter, just to be thorough
+ formatter = new BinaryFormatter ();
+ formatter.Binder = binder;
+ serStream.Seek (0, SeekOrigin.Begin);
+ var deserialized = formatter.Deserialize (serStream);
+
+ Assert.AreEqual (original.GetType (), deserialized.GetType ());
+ Assert.AreEqual (original.Other.GetType (), ((BaseClass)deserialized).Other.GetType ());
+ }
+ }
+#endif
}
}