2 // System.Runtime.Serialization.SerializationTest.cs
4 // Author: Lluis Sanchez Gual (lluis@ximian.com)
10 using System.Diagnostics;
12 using System.Runtime.Serialization;
13 using System.Runtime.Serialization.Formatters.Binary;
14 using System.Reflection;
15 using System.Runtime.Remoting;
16 using System.Runtime.Remoting.Channels;
17 using System.Runtime.Remoting.Proxies;
18 using System.Runtime.Remoting.Messaging;
19 using System.Collections;
20 using NUnit.Framework;
22 namespace MonoTests.System.Runtime.Serialization
25 public class SerializationTest
31 [Category ("MobileNotWorking")]
32 public void TestSerialization ()
34 MethodTester mt = new MethodTester();
35 RemotingServices.Marshal (mt);
36 uri = RemotingServices.GetObjectUri (mt);
41 RemotingServices.Disconnect (mt);
46 StreamingContext context = new StreamingContext (StreamingContextStates.Other);
47 SurrogateSelector sel = new SurrogateSelector();
48 sel.AddSurrogate (typeof (Point), context, new PointSurrogate());
49 sel.AddSurrogate (typeof (FalseISerializable), context, new FalseISerializableSurrogate());
51 List list = CreateTestData();
52 BinderTester_A bta = CreateBinderTestData();
54 ms = new MemoryStream();
55 BinaryFormatter f = new BinaryFormatter (sel, new StreamingContext(StreamingContextStates.Other));
56 f.Serialize (ms, list);
57 ProcessMessages (ms, null);
58 f.Serialize (ms, bta);
65 StreamingContext context = new StreamingContext (StreamingContextStates.Other);
66 SurrogateSelector sel = new SurrogateSelector();
67 sel.AddSurrogate (typeof (Point), context, new PointSurrogate());
68 sel.AddSurrogate (typeof (FalseISerializable), context, new FalseISerializableSurrogate());
70 BinaryFormatter f = new BinaryFormatter (sel, context);
72 object list = f.Deserialize (ms);
74 object[][] originalMsgData = null;
75 IMessage[] calls = null;
76 IMessage[] resps = null;
78 originalMsgData = ProcessMessages (null, null);
80 calls = new IMessage[originalMsgData.Length];
81 resps = new IMessage[originalMsgData.Length];
84 for (int n=0; n<originalMsgData.Length; n++)
86 calls[n] = (IMessage) f.Deserialize (ms);
87 resps[n] = (IMessage) f.DeserializeMethodResponse (ms, null, (IMethodCallMessage)calls[n]);
90 f.Binder = new TestBinder ();
91 object btbob = f.Deserialize (ms);
95 List expected = CreateTestData ();
96 List actual = (List) list;
97 expected.CheckEquals (actual, "List");
99 for (int i = 0; i < actual.children.Length - 1; ++i)
100 if (actual.children [i].next != actual.children [i+1])
101 Assert.Fail ("Deserialization did not restore pointer graph");
103 BinderTester_A bta = CreateBinderTestData();
104 Assert.AreEqual (btbob.GetType(), typeof (BinderTester_B), "BinderTest.class");
105 BinderTester_B btb = btbob as BinderTester_B;
108 Assert.AreEqual (btb.x, bta.x, "BinderTest.x");
109 Assert.AreEqual (btb.y, bta.y, "BinderTest.y");
112 CheckMessages ("MethodCall", originalMsgData, ProcessMessages (null, calls));
113 CheckMessages ("MethodResponse", originalMsgData, ProcessMessages (null, resps));
116 BinderTester_A CreateBinderTestData ()
118 BinderTester_A bta = new BinderTester_A();
120 bta.y = "binder tester";
124 List CreateTestData()
126 List list = new List();
127 list.name = "my list";
128 list.values = new SomeValues();
131 ListItem item1 = new ListItem();
132 ListItem item2 = new ListItem();
133 ListItem item3 = new ListItem();
135 item1.label = "value label 1";
137 item1.value.color = 111;
138 item1.value.point = new Point();
139 item1.value.point.x = 11;
140 item1.value.point.y = 22;
142 item2.label = "value label 2";
144 item2.value.color = 222;
146 item2.value.point = new Point();
147 item2.value.point.x = 33;
148 item2.value.point.y = 44;
150 item3.label = "value label 3";
151 item3.value.color = 333;
152 item3.value.point = new Point();
153 item3.value.point.x = 55;
154 item3.value.point.y = 66;
156 list.children = new ListItem[3];
158 list.children[0] = item1;
159 list.children[1] = item2;
160 list.children[2] = item3;
166 object[][] ProcessMessages (Stream stream, IMessage[] messages)
168 object[][] results = new object[9][];
170 AuxProxy prx = new AuxProxy (stream, uri);
171 MethodTester mt = (MethodTester)prx.GetTransparentProxy();
174 if (messages != null) prx.SetTestMessage (messages[0]);
175 res = mt.OverloadedMethod();
176 results[0] = new object[] {res};
178 if (messages != null) prx.SetTestMessage (messages[1]);
179 res = mt.OverloadedMethod(22);
180 results[1] = new object[] {res};
182 if (messages != null) prx.SetTestMessage (messages[2]);
183 int[] par1 = new int[] {1,2,3};
184 res = mt.OverloadedMethod(par1);
185 results[2] = new object[] { res, par1 };
187 if (messages != null) prx.SetTestMessage (messages[3]);
190 if (messages != null) prx.SetTestMessage (messages[4]);
191 res = mt.Simple ("hello",44);
192 results[4] = new object[] { res };
194 if (messages != null) prx.SetTestMessage (messages[5]);
195 res = mt.Simple2 ('F');
196 results[5] = new object[] { res };
198 if (messages != null) prx.SetTestMessage (messages[6]);
199 char[] par2 = new char[] { 'G' };
200 res = mt.Simple3 (par2);
201 results[6] = new object[] { res, par2 };
203 if (messages != null) prx.SetTestMessage (messages[7]);
204 res = mt.Simple3 (null);
205 results[7] = new object[] { res };
207 if (messages != null) prx.SetTestMessage (messages[8]);
209 SimpleClass b = new SimpleClass ('H');
210 res = mt.SomeMethod (123456, b);
211 results[8] = new object[] { res, b };
216 void CheckMessages (string label, object[][] original, object[][] serialized)
218 for (int n=0; n<original.Length; n++)
219 EqualsArray (label + " " + n, original[n], serialized[n]);
222 public static void AssertEquals(string message, Object expected, Object actual)
224 if (expected != null && expected.GetType().IsArray)
225 EqualsArray (message, (Array)expected, (Array)actual);
227 Assert.AreEqual (expected, actual, message);
230 public static void EqualsArray (string message, object oar1, object oar2)
232 if (oar1 == null || oar2 == null || !(oar1 is Array) || !(oar2 is Array))
234 Assert.AreEqual (oar1, oar2, message);
238 Array ar1 = (Array) oar1;
239 Array ar2 = (Array) oar2;
241 Assert.AreEqual (ar1.Length, ar2.Length, message + ".Length");
243 for (int n=0; n<ar1.Length; n++)
245 object av1 = ar1.GetValue(n);
246 object av2 = ar2.GetValue(n);
247 SerializationTest.AssertEquals (message + "[" + n + "]", av1, av2);
254 class PointSurrogate: ISerializationSurrogate
256 public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
258 Point p = (Point) obj;
259 info.AddValue ("xv",p.x);
260 info.AddValue ("yv",p.y);
263 public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
265 typeof (Point).GetField ("x").SetValue (obj, info.GetInt32 ("xv"));
266 typeof (Point).GetField ("y").SetValue (obj, info.GetInt32 ("yv"));
274 public string name = null;
275 public ListItem[] children = null;
276 public SomeValues values;
278 public void CheckEquals (List val, string context)
280 Assert.AreEqual (name, val.name, context + ".name");
281 values.CheckEquals (val.values, context + ".values");
283 Assert.AreEqual (children.Length, val.children.Length, context + ".children.Length");
285 for (int n=0; n<children.Length; n++)
286 children[n].CheckEquals (val.children[n], context + ".children[" + n + "]");
291 public class ListItem: ISerializable
297 ListItem (SerializationInfo info, StreamingContext ctx)
299 next = (ListItem)info.GetValue ("next", typeof (ListItem));
300 value = (ListValue)info.GetValue ("value", typeof (ListValue));
301 label = info.GetString ("label");
304 public void GetObjectData (SerializationInfo info, StreamingContext ctx)
306 info.AddValue ("next", next);
307 info.AddValue ("value", value);
308 info.AddValue ("label", label);
311 public void CheckEquals (ListItem val, string context)
313 Assert.AreEqual (label, val.label, context + ".label");
314 value.CheckEquals (val.value, context + ".value");
317 Assert.IsNull (val.next, context + ".next == null");
319 Assert.IsNotNull (val.next, context + ".next != null");
320 next.CheckEquals (val.next, context + ".next");
324 public override bool Equals(object obj)
326 ListItem val = (ListItem)obj;
327 if ((next == null || val.next == null) && (next != val.next)) return false;
328 if (next == null) return true;
329 if (!next.Equals(val.next)) return false;
330 return value.Equals (val.value) && label == val.label;
333 public override int GetHashCode ()
335 return base.GetHashCode ();
338 public ListItem next;
339 public ListValue value;
344 public struct ListValue
349 public override bool Equals(object obj)
351 ListValue val = (ListValue)obj;
352 return (color == val.color && point.Equals(val.point));
355 public void CheckEquals (ListValue val, string context)
357 Assert.AreEqual (color, val.color, context + ".color");
358 point.CheckEquals (val.point, context + ".point");
361 public override int GetHashCode ()
363 return base.GetHashCode ();
372 public override bool Equals(object obj)
374 Point p = (Point)obj;
375 return (x == p.x && y == p.y);
378 public void CheckEquals (Point p, string context)
380 Assert.AreEqual (x, p.x, context + ".x");
381 Assert.AreEqual (y, p.y, context + ".y");
384 public override int GetHashCode ()
386 return base.GetHashCode ();
391 public class FalseISerializable : ISerializable
395 public FalseISerializable (int n)
400 public void GetObjectData(SerializationInfo info, StreamingContext context)
402 throw new InvalidOperationException ("Serialize:We should not pass here.");
405 public FalseISerializable (SerializationInfo info, StreamingContext context)
407 throw new InvalidOperationException ("Deserialize:We should not pass here.");
411 public class FalseISerializableSurrogate : ISerializationSurrogate
413 public void GetObjectData (object obj, SerializationInfo info, StreamingContext context)
415 info.AddValue("field", Convert.ToString (((FalseISerializable)obj).field));
418 public object SetObjectData (object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
420 ((FalseISerializable)obj).field = Convert.ToInt32 (info.GetValue("field", typeof(string)));
426 public class SimpleClass
428 public SimpleClass (char v) { val = v; }
430 public override bool Equals(object obj)
432 if (obj == null) return false;
433 return val == ((SimpleClass)obj).val;
436 public override int GetHashCode()
438 return val.GetHashCode();
441 public int SampleCall (string str, SomeValues sv, ref int acum)
450 enum IntEnum { aaa, bbb, ccc }
451 enum ByteEnum: byte { aaa=221, bbb=3, ccc=44 }
453 delegate int SampleDelegate (string str, SomeValues sv, ref int acum);
456 public class SomeValues
484 public int[,,] _intsMulti;
486 SimpleClass[] _simples;
487 SimpleClass[,] _simplesMulti;
488 SimpleClass[][] _simplesJagged;
490 object[] _almostEmpty;
492 object[] _emptyObjectArray;
493 Type[] _emptyTypeArray;
494 SimpleClass[] _emptySimpleArray;
495 int[] _emptyIntArray;
496 string[] _emptyStringArray;
497 Point[] _emptyPointArray;
500 SampleDelegate _sampleDelegate;
501 SampleDelegate _sampleDelegate2;
502 SampleDelegate _sampleDelegate3;
503 SampleDelegate _sampleDelegateStatic;
504 SampleDelegate _sampleDelegateCombined;
506 SimpleClass _shared1;
507 SimpleClass _shared2;
508 SimpleClass _shared3;
510 FalseISerializable _falseSerializable;
514 _type = typeof (string);
515 _type2 = typeof (SomeValues);
516 _dbnull = DBNull.Value;
517 _assembly = typeof (SomeValues).Assembly;
518 _intEnum = IntEnum.bbb;
519 _byteEnum = ByteEnum.ccc;
524 _dateTime = new DateTime (1972,7,13,1,20,59);
525 _decimal = (decimal)101010.10101;
526 _double = 123456.6789;
531 _float = (float)654321.321;
536 Point p = new Point();
538 object boxedPoint = p;
541 object boxedLong = i;
543 _objects = new object[] { "string", (int)1234, null , /*boxedPoint, boxedPoint,*/ boxedLong, boxedLong};
544 _strings = new string[] { "an", "array", "of", "strings","I","repeat","an", "array", "of", "strings" };
545 _ints = new int[] { 4,5,6,7,8 };
546 _intsMulti = new int[2,3,4] { { {1,2,3,4},{5,6,7,8},{9,10,11,12}}, { {13,14,15,16},{17,18,19,20},{21,22,23,24} } };
547 _intsJagged = new int[2][] { new int[3] {1,2,3}, new int[2] {4,5} };
548 _simples = new SimpleClass[] { new SimpleClass('a'),new SimpleClass('b'),new SimpleClass('c') };
549 _simplesMulti = new SimpleClass[2,3] {{new SimpleClass('d'),new SimpleClass('e'),new SimpleClass('f')}, {new SimpleClass('g'),new SimpleClass('j'),new SimpleClass('h')}};
550 _simplesJagged = new SimpleClass[2][] { new SimpleClass[1] { new SimpleClass('i') }, new SimpleClass[2] {null, new SimpleClass('k')}};
551 _almostEmpty = new object[2000];
552 _almostEmpty[1000] = 4;
554 _emptyObjectArray = new object[0];
555 _emptyTypeArray = new Type[0];
556 _emptySimpleArray = new SimpleClass[0];
557 _emptyIntArray = new int[0];
558 _emptyStringArray = new string[0];
559 _emptyPointArray = new Point[0];
561 _doubles = new double[] { 1010101.101010, 292929.29292, 3838383.38383, 4747474.474, 56565.5656565, 0, Double.NaN, Double.MaxValue, Double.MinValue, Double.NegativeInfinity, Double.PositiveInfinity };
563 _sampleDelegate = new SampleDelegate(SampleCall);
564 _sampleDelegate2 = new SampleDelegate(_simples[0].SampleCall);
565 _sampleDelegate3 = new SampleDelegate(new SimpleClass('x').SampleCall);
566 _sampleDelegateStatic = new SampleDelegate(SampleStaticCall);
567 _sampleDelegateCombined = (SampleDelegate)Delegate.Combine (new Delegate[] {_sampleDelegate, _sampleDelegate2, _sampleDelegate3, _sampleDelegateStatic });
569 // This is to test that references are correctly solved
570 _shared1 = new SimpleClass('A');
571 _shared2 = new SimpleClass('A');
574 _falseSerializable = new FalseISerializable (2);
577 public int SampleCall (string str, SomeValues sv, ref int acum)
583 public static int SampleStaticCall (string str, SomeValues sv, ref int acum)
589 public void CheckEquals (SomeValues obj, string context)
591 Assert.AreEqual (_type, obj._type, context + "._type");
592 Assert.AreEqual (_type2, obj._type2, context + "._type2");
593 Assert.AreEqual (_dbnull, obj._dbnull, context + "._dbnull");
594 Assert.AreEqual (_assembly, obj._assembly, context + "._assembly");
596 Assert.AreEqual (_intEnum, obj._intEnum, context + "._intEnum");
597 Assert.AreEqual (_byteEnum, obj._byteEnum, context + "._byteEnum");
598 Assert.AreEqual (_bool, obj._bool, context + "._bool");
599 Assert.AreEqual (_bool2, obj._bool2, context + "._bool2");
600 Assert.AreEqual (_byte, obj._byte, context + "._byte");
601 Assert.AreEqual (_char, obj._char, context + "._char");
602 Assert.AreEqual (_dateTime, obj._dateTime, context + "._dateTime");
603 Assert.AreEqual (_decimal, obj._decimal, context + "._decimal");
604 Assert.AreEqual (_int, obj._int, context + "._int");
605 Assert.AreEqual (_long, obj._long, context + "._long");
606 Assert.AreEqual (_sbyte, obj._sbyte, context + "._sbyte");
607 Assert.AreEqual (_float, obj._float, context + "._float");
608 Assert.AreEqual (_ushort, obj._ushort, context + "._ushort");
609 Assert.AreEqual (_uint, obj._uint, context + "._uint");
610 Assert.AreEqual (_ulong, obj._ulong, context + "._ulong");
612 SerializationTest.EqualsArray (context + "._objects", _objects, obj._objects);
613 SerializationTest.EqualsArray (context + "._strings", _strings, obj._strings);
614 SerializationTest.EqualsArray (context + "._doubles", _doubles, obj._doubles);
615 SerializationTest.EqualsArray (context + "._ints", _ints, obj._ints);
616 SerializationTest.EqualsArray (context + "._simples", _simples, obj._simples);
617 SerializationTest.EqualsArray (context + "._almostEmpty", _almostEmpty, obj._almostEmpty);
619 SerializationTest.EqualsArray (context + "._emptyObjectArray", _emptyObjectArray, obj._emptyObjectArray);
620 SerializationTest.EqualsArray (context + "._emptyTypeArray", _emptyTypeArray, obj._emptyTypeArray);
621 SerializationTest.EqualsArray (context + "._emptySimpleArray", _emptySimpleArray, obj._emptySimpleArray);
622 SerializationTest.EqualsArray (context + "._emptyIntArray", _emptyIntArray, obj._emptyIntArray);
623 SerializationTest.EqualsArray (context + "._emptyStringArray", _emptyStringArray, obj._emptyStringArray);
624 SerializationTest.EqualsArray (context + "._emptyPointArray", _emptyPointArray, obj._emptyPointArray);
626 for (int i=0; i<2; i++)
627 for (int j=0; j<3; j++)
628 for (int k=0; k<4; k++)
629 SerializationTest.AssertEquals("SomeValues._intsMulti[" + i + "," + j + "," + k + "]", _intsMulti[i,j,k], obj._intsMulti[i,j,k]);
631 for (int i=0; i<_intsJagged.Length; i++)
632 for (int j=0; j<_intsJagged[i].Length; j++)
633 SerializationTest.AssertEquals ("SomeValues._intsJagged[" + i + "][" + j + "]", _intsJagged[i][j], obj._intsJagged[i][j]);
635 for (int i=0; i<2; i++)
636 for (int j=0; j<3; j++)
637 SerializationTest.AssertEquals ("SomeValues._simplesMulti[" + i + "," + j + "]", _simplesMulti[i,j], obj._simplesMulti[i,j]);
639 for (int i=0; i<_simplesJagged.Length; i++)
640 SerializationTest.EqualsArray ("SomeValues._simplesJagged", _simplesJagged[i], obj._simplesJagged[i]);
643 SerializationTest.AssertEquals ("SomeValues._sampleDelegate", _sampleDelegate ("hi", this, ref acum), _int);
644 SerializationTest.AssertEquals ("SomeValues._sampleDelegate_bis", _sampleDelegate ("hi", this, ref acum), obj._sampleDelegate ("hi", this, ref acum));
646 SerializationTest.AssertEquals ("SomeValues._sampleDelegate2", _sampleDelegate2 ("hi", this, ref acum), (int)_simples[0].val);
647 SerializationTest.AssertEquals ("SomeValues._sampleDelegate2_bis", _sampleDelegate2 ("hi", this, ref acum), obj._sampleDelegate2 ("hi", this, ref acum));
649 SerializationTest.AssertEquals ("SomeValues._sampleDelegate3", _sampleDelegate3 ("hi", this, ref acum), (int)'x');
650 SerializationTest.AssertEquals ("SomeValues._sampleDelegate3_bis", _sampleDelegate3 ("hi", this, ref acum), obj._sampleDelegate3 ("hi", this, ref acum));
652 SerializationTest.AssertEquals ("SomeValues._sampleDelegateStatic", _sampleDelegateStatic ("hi", this, ref acum), 99);
653 SerializationTest.AssertEquals ("SomeValues._sampleDelegateStatic_bis", _sampleDelegateStatic ("hi", this, ref acum), obj._sampleDelegateStatic ("hi", this, ref acum));
657 _sampleDelegateCombined ("hi", this, ref acum1);
658 obj._sampleDelegateCombined ("hi", this, ref acum2);
660 SerializationTest.AssertEquals ("_sampleDelegateCombined", acum1, _int + (int)_simples[0].val + (int)'x' + 99);
661 SerializationTest.AssertEquals ("_sampleDelegateCombined_bis", acum1, acum2);
663 SerializationTest.AssertEquals ("SomeValues._shared1", _shared1, _shared2);
664 SerializationTest.AssertEquals ("SomeValues._shared1_bis", _shared1, _shared3);
667 SerializationTest.AssertEquals ("SomeValues._shared2", _shared2.val, 'A');
668 SerializationTest.AssertEquals ("SomeValues._shared3", _shared3.val, 'B');
670 SerializationTest.AssertEquals ("SomeValues._falseSerializable", _falseSerializable.field, 2);
674 class MethodTester : MarshalByRefObject
676 public int OverloadedMethod ()
681 public int OverloadedMethod (int a)
686 public int OverloadedMethod (int[] a)
691 public void NoReturn ()
694 public string Simple (string a, int b)
699 public SimpleClass Simple2 (char c)
701 return new SimpleClass(c);
704 public SimpleClass Simple3 (char[] c)
706 if (c != null) return new SimpleClass(c[0]);
710 public int SomeMethod (int a, SimpleClass b)
714 int r = a + c.Length;
722 class AuxProxy: RealProxy
724 public static bool useHeaders = false;
727 IMethodMessage _testMsg;
729 public AuxProxy(Stream stream, string uri): base(typeof(MethodTester))
735 public void SetTestMessage (IMessage msg)
737 _testMsg = (IMethodMessage)msg;
738 _testMsg.Properties["__Uri"] = _uri;
741 public override IMessage Invoke(IMessage msg)
743 IMethodCallMessage call = (IMethodCallMessage)msg;
744 if (call.MethodName.StartsWith ("Initialize")) return new ReturnMessage(null,null,0,null,(IMethodCallMessage)msg);
746 call.Properties["__Uri"] = _uri;
750 SerializeCall (call);
751 IMessage response = ChannelServices.SyncDispatchMessage (call);
752 SerializeResponse (response);
755 else if (_testMsg != null)
757 if (_testMsg is IMethodCallMessage)
758 return ChannelServices.SyncDispatchMessage (_testMsg);
763 return ChannelServices.SyncDispatchMessage (call);
766 void SerializeCall (IMessage call)
768 RemotingSurrogateSelector rss = new RemotingSurrogateSelector();
769 var fmt = new BinaryFormatter (rss, new StreamingContext(StreamingContextStates.Remoting));
770 fmt.Serialize (_stream, call, GetHeaders());
773 void SerializeResponse (IMessage resp)
775 RemotingSurrogateSelector rss = new RemotingSurrogateSelector();
776 var fmt = new BinaryFormatter (rss, new StreamingContext(StreamingContextStates.Remoting));
777 fmt.Serialize (_stream, resp, GetHeaders());
780 Header[] GetHeaders()
786 hs[0] = new Header("unom",new SimpleClass('R'));
792 public class TestBinder : SerializationBinder
794 public override Type BindToType (string assemblyName, string typeName)
796 if (typeName.IndexOf("BinderTester_A") != -1)
797 typeName = typeName.Replace ("BinderTester_A", "BinderTester_B");
799 return Assembly.Load (assemblyName).GetType (typeName);
804 public class BinderTester_A
811 public class BinderTester_B