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 public void TestSerialization ()
33 MethodTester mt = new MethodTester();
34 RemotingServices.Marshal (mt);
35 uri = RemotingServices.GetObjectUri (mt);
40 RemotingServices.Disconnect (mt);
45 StreamingContext context = new StreamingContext (StreamingContextStates.Other);
46 SurrogateSelector sel = new SurrogateSelector();
47 sel.AddSurrogate (typeof (Point), context, new PointSurrogate());
48 sel.AddSurrogate (typeof (FalseISerializable), context, new FalseISerializableSurrogate());
50 List list = CreateTestData();
51 BinderTester_A bta = CreateBinderTestData();
53 ms = new MemoryStream();
54 BinaryFormatter f = new BinaryFormatter (sel, new StreamingContext(StreamingContextStates.Other));
55 f.Serialize (ms, list);
56 ProcessMessages (ms, null);
57 f.Serialize (ms, bta);
64 StreamingContext context = new StreamingContext (StreamingContextStates.Other);
65 SurrogateSelector sel = new SurrogateSelector();
66 sel.AddSurrogate (typeof (Point), context, new PointSurrogate());
67 sel.AddSurrogate (typeof (FalseISerializable), context, new FalseISerializableSurrogate());
69 BinaryFormatter f = new BinaryFormatter (sel, context);
71 object list = f.Deserialize (ms);
73 object[][] originalMsgData = null;
74 IMessage[] calls = null;
75 IMessage[] resps = null;
77 originalMsgData = ProcessMessages (null, null);
79 calls = new IMessage[originalMsgData.Length];
80 resps = new IMessage[originalMsgData.Length];
83 for (int n=0; n<originalMsgData.Length; n++)
85 calls[n] = (IMessage) f.Deserialize (ms);
86 resps[n] = (IMessage) f.DeserializeMethodResponse (ms, null, (IMethodCallMessage)calls[n]);
89 f.Binder = new TestBinder ();
90 object btbob = f.Deserialize (ms);
94 List expected = CreateTestData ();
95 List actual = (List) list;
96 expected.CheckEquals (actual, "List");
98 for (int i = 0; i < actual.children.Length - 1; ++i)
99 if (actual.children [i].next != actual.children [i+1])
100 Assert.Fail ("Deserialization did not restore pointer graph");
102 BinderTester_A bta = CreateBinderTestData();
103 Assert.AreEqual (btbob.GetType(), typeof (BinderTester_B), "BinderTest.class");
104 BinderTester_B btb = btbob as BinderTester_B;
107 Assert.AreEqual (btb.x, bta.x, "BinderTest.x");
108 Assert.AreEqual (btb.y, bta.y, "BinderTest.y");
111 CheckMessages ("MethodCall", originalMsgData, ProcessMessages (null, calls));
112 CheckMessages ("MethodResponse", originalMsgData, ProcessMessages (null, resps));
115 BinderTester_A CreateBinderTestData ()
117 BinderTester_A bta = new BinderTester_A();
119 bta.y = "binder tester";
123 List CreateTestData()
125 List list = new List();
126 list.name = "my list";
127 list.values = new SomeValues();
130 ListItem item1 = new ListItem();
131 ListItem item2 = new ListItem();
132 ListItem item3 = new ListItem();
134 item1.label = "value label 1";
136 item1.value.color = 111;
137 item1.value.point = new Point();
138 item1.value.point.x = 11;
139 item1.value.point.y = 22;
141 item2.label = "value label 2";
143 item2.value.color = 222;
145 item2.value.point = new Point();
146 item2.value.point.x = 33;
147 item2.value.point.y = 44;
149 item3.label = "value label 3";
150 item3.value.color = 333;
151 item3.value.point = new Point();
152 item3.value.point.x = 55;
153 item3.value.point.y = 66;
155 list.children = new ListItem[3];
157 list.children[0] = item1;
158 list.children[1] = item2;
159 list.children[2] = item3;
165 object[][] ProcessMessages (Stream stream, IMessage[] messages)
167 object[][] results = new object[9][];
169 AuxProxy prx = new AuxProxy (stream, uri);
170 MethodTester mt = (MethodTester)prx.GetTransparentProxy();
173 if (messages != null) prx.SetTestMessage (messages[0]);
174 res = mt.OverloadedMethod();
175 results[0] = new object[] {res};
177 if (messages != null) prx.SetTestMessage (messages[1]);
178 res = mt.OverloadedMethod(22);
179 results[1] = new object[] {res};
181 if (messages != null) prx.SetTestMessage (messages[2]);
182 int[] par1 = new int[] {1,2,3};
183 res = mt.OverloadedMethod(par1);
184 results[2] = new object[] { res, par1 };
186 if (messages != null) prx.SetTestMessage (messages[3]);
189 if (messages != null) prx.SetTestMessage (messages[4]);
190 res = mt.Simple ("hello",44);
191 results[4] = new object[] { res };
193 if (messages != null) prx.SetTestMessage (messages[5]);
194 res = mt.Simple2 ('F');
195 results[5] = new object[] { res };
197 if (messages != null) prx.SetTestMessage (messages[6]);
198 char[] par2 = new char[] { 'G' };
199 res = mt.Simple3 (par2);
200 results[6] = new object[] { res, par2 };
202 if (messages != null) prx.SetTestMessage (messages[7]);
203 res = mt.Simple3 (null);
204 results[7] = new object[] { res };
206 if (messages != null) prx.SetTestMessage (messages[8]);
208 SimpleClass b = new SimpleClass ('H');
209 res = mt.SomeMethod (123456, b);
210 results[8] = new object[] { res, b };
215 void CheckMessages (string label, object[][] original, object[][] serialized)
217 for (int n=0; n<original.Length; n++)
218 EqualsArray (label + " " + n, original[n], serialized[n]);
221 public static void AssertEquals(string message, Object expected, Object actual)
223 if (expected != null && expected.GetType().IsArray)
224 EqualsArray (message, (Array)expected, (Array)actual);
226 Assert.AreEqual (expected, actual, message);
229 public static void EqualsArray (string message, object oar1, object oar2)
231 if (oar1 == null || oar2 == null || !(oar1 is Array) || !(oar2 is Array))
233 Assert.AreEqual (oar1, oar2, message);
237 Array ar1 = (Array) oar1;
238 Array ar2 = (Array) oar2;
240 Assert.AreEqual (ar1.Length, ar2.Length, message + ".Length");
242 for (int n=0; n<ar1.Length; n++)
244 object av1 = ar1.GetValue(n);
245 object av2 = ar2.GetValue(n);
246 SerializationTest.AssertEquals (message + "[" + n + "]", av1, av2);
253 class PointSurrogate: ISerializationSurrogate
255 public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
257 Point p = (Point) obj;
258 info.AddValue ("xv",p.x);
259 info.AddValue ("yv",p.y);
262 public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
264 typeof (Point).GetField ("x").SetValue (obj, info.GetInt32 ("xv"));
265 typeof (Point).GetField ("y").SetValue (obj, info.GetInt32 ("yv"));
273 public string name = null;
274 public ListItem[] children = null;
275 public SomeValues values;
277 public void CheckEquals (List val, string context)
279 Assert.AreEqual (name, val.name, context + ".name");
280 values.CheckEquals (val.values, context + ".values");
282 Assert.AreEqual (children.Length, val.children.Length, context + ".children.Length");
284 for (int n=0; n<children.Length; n++)
285 children[n].CheckEquals (val.children[n], context + ".children[" + n + "]");
290 public class ListItem: ISerializable
296 ListItem (SerializationInfo info, StreamingContext ctx)
298 next = (ListItem)info.GetValue ("next", typeof (ListItem));
299 value = (ListValue)info.GetValue ("value", typeof (ListValue));
300 label = info.GetString ("label");
303 public void GetObjectData (SerializationInfo info, StreamingContext ctx)
305 info.AddValue ("next", next);
306 info.AddValue ("value", value);
307 info.AddValue ("label", label);
310 public void CheckEquals (ListItem val, string context)
312 Assert.AreEqual (label, val.label, context + ".label");
313 value.CheckEquals (val.value, context + ".value");
316 Assert.IsNull (val.next, context + ".next == null");
318 Assert.IsNotNull (val.next, context + ".next != null");
319 next.CheckEquals (val.next, context + ".next");
323 public override bool Equals(object obj)
325 ListItem val = (ListItem)obj;
326 if ((next == null || val.next == null) && (next != val.next)) return false;
327 if (next == null) return true;
328 if (!next.Equals(val.next)) return false;
329 return value.Equals (val.value) && label == val.label;
332 public override int GetHashCode ()
334 return base.GetHashCode ();
337 public ListItem next;
338 public ListValue value;
343 public struct ListValue
348 public override bool Equals(object obj)
350 ListValue val = (ListValue)obj;
351 return (color == val.color && point.Equals(val.point));
354 public void CheckEquals (ListValue val, string context)
356 Assert.AreEqual (color, val.color, context + ".color");
357 point.CheckEquals (val.point, context + ".point");
360 public override int GetHashCode ()
362 return base.GetHashCode ();
371 public override bool Equals(object obj)
373 Point p = (Point)obj;
374 return (x == p.x && y == p.y);
377 public void CheckEquals (Point p, string context)
379 Assert.AreEqual (x, p.x, context + ".x");
380 Assert.AreEqual (y, p.y, context + ".y");
383 public override int GetHashCode ()
385 return base.GetHashCode ();
390 public class FalseISerializable : ISerializable
394 public FalseISerializable (int n)
399 public void GetObjectData(SerializationInfo info, StreamingContext context)
401 throw new InvalidOperationException ("Serialize:We should not pass here.");
404 public FalseISerializable (SerializationInfo info, StreamingContext context)
406 throw new InvalidOperationException ("Deserialize:We should not pass here.");
410 public class FalseISerializableSurrogate : ISerializationSurrogate
412 public void GetObjectData (object obj, SerializationInfo info, StreamingContext context)
414 info.AddValue("field", Convert.ToString (((FalseISerializable)obj).field));
417 public object SetObjectData (object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
419 ((FalseISerializable)obj).field = Convert.ToInt32 (info.GetValue("field", typeof(string)));
425 public class SimpleClass
427 public SimpleClass (char v) { val = v; }
429 public override bool Equals(object obj)
431 if (obj == null) return false;
432 return val == ((SimpleClass)obj).val;
435 public override int GetHashCode()
437 return val.GetHashCode();
440 public int SampleCall (string str, SomeValues sv, ref int acum)
449 enum IntEnum { aaa, bbb, ccc }
450 enum ByteEnum: byte { aaa=221, bbb=3, ccc=44 }
452 delegate int SampleDelegate (string str, SomeValues sv, ref int acum);
455 public class SomeValues
483 public int[,,] _intsMulti;
485 SimpleClass[] _simples;
486 SimpleClass[,] _simplesMulti;
487 SimpleClass[][] _simplesJagged;
489 object[] _almostEmpty;
491 object[] _emptyObjectArray;
492 Type[] _emptyTypeArray;
493 SimpleClass[] _emptySimpleArray;
494 int[] _emptyIntArray;
495 string[] _emptyStringArray;
496 Point[] _emptyPointArray;
499 SampleDelegate _sampleDelegate;
500 SampleDelegate _sampleDelegate2;
501 SampleDelegate _sampleDelegate3;
502 SampleDelegate _sampleDelegateStatic;
503 SampleDelegate _sampleDelegateCombined;
505 SimpleClass _shared1;
506 SimpleClass _shared2;
507 SimpleClass _shared3;
509 FalseISerializable _falseSerializable;
513 _type = typeof (string);
514 _type2 = typeof (SomeValues);
515 _dbnull = DBNull.Value;
516 _assembly = typeof (SomeValues).Assembly;
517 _intEnum = IntEnum.bbb;
518 _byteEnum = ByteEnum.ccc;
523 _dateTime = new DateTime (1972,7,13,1,20,59);
524 _decimal = (decimal)101010.10101;
525 _double = 123456.6789;
530 _float = (float)654321.321;
535 Point p = new Point();
537 object boxedPoint = p;
540 object boxedLong = i;
542 _objects = new object[] { "string", (int)1234, null , /*boxedPoint, boxedPoint,*/ boxedLong, boxedLong};
543 _strings = new string[] { "an", "array", "of", "strings","I","repeat","an", "array", "of", "strings" };
544 _ints = new int[] { 4,5,6,7,8 };
545 _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} } };
546 _intsJagged = new int[2][] { new int[3] {1,2,3}, new int[2] {4,5} };
547 _simples = new SimpleClass[] { new SimpleClass('a'),new SimpleClass('b'),new SimpleClass('c') };
548 _simplesMulti = new SimpleClass[2,3] {{new SimpleClass('d'),new SimpleClass('e'),new SimpleClass('f')}, {new SimpleClass('g'),new SimpleClass('j'),new SimpleClass('h')}};
549 _simplesJagged = new SimpleClass[2][] { new SimpleClass[1] { new SimpleClass('i') }, new SimpleClass[2] {null, new SimpleClass('k')}};
550 _almostEmpty = new object[2000];
551 _almostEmpty[1000] = 4;
553 _emptyObjectArray = new object[0];
554 _emptyTypeArray = new Type[0];
555 _emptySimpleArray = new SimpleClass[0];
556 _emptyIntArray = new int[0];
557 _emptyStringArray = new string[0];
558 _emptyPointArray = new Point[0];
560 _doubles = new double[] { 1010101.101010, 292929.29292, 3838383.38383, 4747474.474, 56565.5656565, 0, Double.NaN, Double.MaxValue, Double.MinValue, Double.NegativeInfinity, Double.PositiveInfinity };
562 _sampleDelegate = new SampleDelegate(SampleCall);
563 _sampleDelegate2 = new SampleDelegate(_simples[0].SampleCall);
564 _sampleDelegate3 = new SampleDelegate(new SimpleClass('x').SampleCall);
565 _sampleDelegateStatic = new SampleDelegate(SampleStaticCall);
566 _sampleDelegateCombined = (SampleDelegate)Delegate.Combine (new Delegate[] {_sampleDelegate, _sampleDelegate2, _sampleDelegate3, _sampleDelegateStatic });
568 // This is to test that references are correctly solved
569 _shared1 = new SimpleClass('A');
570 _shared2 = new SimpleClass('A');
573 _falseSerializable = new FalseISerializable (2);
576 public int SampleCall (string str, SomeValues sv, ref int acum)
582 public static int SampleStaticCall (string str, SomeValues sv, ref int acum)
588 public void CheckEquals (SomeValues obj, string context)
590 Assert.AreEqual (_type, obj._type, context + "._type");
591 Assert.AreEqual (_type2, obj._type2, context + "._type2");
592 Assert.AreEqual (_dbnull, obj._dbnull, context + "._dbnull");
593 Assert.AreEqual (_assembly, obj._assembly, context + "._assembly");
595 Assert.AreEqual (_intEnum, obj._intEnum, context + "._intEnum");
596 Assert.AreEqual (_byteEnum, obj._byteEnum, context + "._byteEnum");
597 Assert.AreEqual (_bool, obj._bool, context + "._bool");
598 Assert.AreEqual (_bool2, obj._bool2, context + "._bool2");
599 Assert.AreEqual (_byte, obj._byte, context + "._byte");
600 Assert.AreEqual (_char, obj._char, context + "._char");
601 Assert.AreEqual (_dateTime, obj._dateTime, context + "._dateTime");
602 Assert.AreEqual (_decimal, obj._decimal, context + "._decimal");
603 Assert.AreEqual (_int, obj._int, context + "._int");
604 Assert.AreEqual (_long, obj._long, context + "._long");
605 Assert.AreEqual (_sbyte, obj._sbyte, context + "._sbyte");
606 Assert.AreEqual (_float, obj._float, context + "._float");
607 Assert.AreEqual (_ushort, obj._ushort, context + "._ushort");
608 Assert.AreEqual (_uint, obj._uint, context + "._uint");
609 Assert.AreEqual (_ulong, obj._ulong, context + "._ulong");
611 SerializationTest.EqualsArray (context + "._objects", _objects, obj._objects);
612 SerializationTest.EqualsArray (context + "._strings", _strings, obj._strings);
613 SerializationTest.EqualsArray (context + "._doubles", _doubles, obj._doubles);
614 SerializationTest.EqualsArray (context + "._ints", _ints, obj._ints);
615 SerializationTest.EqualsArray (context + "._simples", _simples, obj._simples);
616 SerializationTest.EqualsArray (context + "._almostEmpty", _almostEmpty, obj._almostEmpty);
618 SerializationTest.EqualsArray (context + "._emptyObjectArray", _emptyObjectArray, obj._emptyObjectArray);
619 SerializationTest.EqualsArray (context + "._emptyTypeArray", _emptyTypeArray, obj._emptyTypeArray);
620 SerializationTest.EqualsArray (context + "._emptySimpleArray", _emptySimpleArray, obj._emptySimpleArray);
621 SerializationTest.EqualsArray (context + "._emptyIntArray", _emptyIntArray, obj._emptyIntArray);
622 SerializationTest.EqualsArray (context + "._emptyStringArray", _emptyStringArray, obj._emptyStringArray);
623 SerializationTest.EqualsArray (context + "._emptyPointArray", _emptyPointArray, obj._emptyPointArray);
625 for (int i=0; i<2; i++)
626 for (int j=0; j<3; j++)
627 for (int k=0; k<4; k++)
628 SerializationTest.AssertEquals("SomeValues._intsMulti[" + i + "," + j + "," + k + "]", _intsMulti[i,j,k], obj._intsMulti[i,j,k]);
630 for (int i=0; i<_intsJagged.Length; i++)
631 for (int j=0; j<_intsJagged[i].Length; j++)
632 SerializationTest.AssertEquals ("SomeValues._intsJagged[" + i + "][" + j + "]", _intsJagged[i][j], obj._intsJagged[i][j]);
634 for (int i=0; i<2; i++)
635 for (int j=0; j<3; j++)
636 SerializationTest.AssertEquals ("SomeValues._simplesMulti[" + i + "," + j + "]", _simplesMulti[i,j], obj._simplesMulti[i,j]);
638 for (int i=0; i<_simplesJagged.Length; i++)
639 SerializationTest.EqualsArray ("SomeValues._simplesJagged", _simplesJagged[i], obj._simplesJagged[i]);
642 SerializationTest.AssertEquals ("SomeValues._sampleDelegate", _sampleDelegate ("hi", this, ref acum), _int);
643 SerializationTest.AssertEquals ("SomeValues._sampleDelegate_bis", _sampleDelegate ("hi", this, ref acum), obj._sampleDelegate ("hi", this, ref acum));
645 SerializationTest.AssertEquals ("SomeValues._sampleDelegate2", _sampleDelegate2 ("hi", this, ref acum), (int)_simples[0].val);
646 SerializationTest.AssertEquals ("SomeValues._sampleDelegate2_bis", _sampleDelegate2 ("hi", this, ref acum), obj._sampleDelegate2 ("hi", this, ref acum));
648 SerializationTest.AssertEquals ("SomeValues._sampleDelegate3", _sampleDelegate3 ("hi", this, ref acum), (int)'x');
649 SerializationTest.AssertEquals ("SomeValues._sampleDelegate3_bis", _sampleDelegate3 ("hi", this, ref acum), obj._sampleDelegate3 ("hi", this, ref acum));
651 SerializationTest.AssertEquals ("SomeValues._sampleDelegateStatic", _sampleDelegateStatic ("hi", this, ref acum), 99);
652 SerializationTest.AssertEquals ("SomeValues._sampleDelegateStatic_bis", _sampleDelegateStatic ("hi", this, ref acum), obj._sampleDelegateStatic ("hi", this, ref acum));
656 _sampleDelegateCombined ("hi", this, ref acum1);
657 obj._sampleDelegateCombined ("hi", this, ref acum2);
659 SerializationTest.AssertEquals ("_sampleDelegateCombined", acum1, _int + (int)_simples[0].val + (int)'x' + 99);
660 SerializationTest.AssertEquals ("_sampleDelegateCombined_bis", acum1, acum2);
662 SerializationTest.AssertEquals ("SomeValues._shared1", _shared1, _shared2);
663 SerializationTest.AssertEquals ("SomeValues._shared1_bis", _shared1, _shared3);
666 SerializationTest.AssertEquals ("SomeValues._shared2", _shared2.val, 'A');
667 SerializationTest.AssertEquals ("SomeValues._shared3", _shared3.val, 'B');
669 SerializationTest.AssertEquals ("SomeValues._falseSerializable", _falseSerializable.field, 2);
673 class MethodTester : MarshalByRefObject
675 public int OverloadedMethod ()
680 public int OverloadedMethod (int a)
685 public int OverloadedMethod (int[] a)
690 public void NoReturn ()
693 public string Simple (string a, int b)
698 public SimpleClass Simple2 (char c)
700 return new SimpleClass(c);
703 public SimpleClass Simple3 (char[] c)
705 if (c != null) return new SimpleClass(c[0]);
709 public int SomeMethod (int a, SimpleClass b)
713 int r = a + c.Length;
721 class AuxProxy: RealProxy
723 public static bool useHeaders = false;
726 IMethodMessage _testMsg;
728 public AuxProxy(Stream stream, string uri): base(typeof(MethodTester))
734 public void SetTestMessage (IMessage msg)
736 _testMsg = (IMethodMessage)msg;
737 _testMsg.Properties["__Uri"] = _uri;
740 public override IMessage Invoke(IMessage msg)
742 IMethodCallMessage call = (IMethodCallMessage)msg;
743 if (call.MethodName.StartsWith ("Initialize")) return new ReturnMessage(null,null,0,null,(IMethodCallMessage)msg);
745 call.Properties["__Uri"] = _uri;
749 SerializeCall (call);
750 IMessage response = ChannelServices.SyncDispatchMessage (call);
751 SerializeResponse (response);
754 else if (_testMsg != null)
756 if (_testMsg is IMethodCallMessage)
757 return ChannelServices.SyncDispatchMessage (_testMsg);
762 return ChannelServices.SyncDispatchMessage (call);
765 void SerializeCall (IMessage call)
767 RemotingSurrogateSelector rss = new RemotingSurrogateSelector();
768 IRemotingFormatter fmt = new BinaryFormatter (rss, new StreamingContext(StreamingContextStates.Remoting));
769 fmt.Serialize (_stream, call, GetHeaders());
772 void SerializeResponse (IMessage resp)
774 RemotingSurrogateSelector rss = new RemotingSurrogateSelector();
775 IRemotingFormatter fmt = new BinaryFormatter (rss, new StreamingContext(StreamingContextStates.Remoting));
776 fmt.Serialize (_stream, resp, GetHeaders());
779 Header[] GetHeaders()
785 hs[0] = new Header("unom",new SimpleClass('R'));
791 public class TestBinder : SerializationBinder
793 public override Type BindToType (string assemblyName, string typeName)
795 if (typeName.IndexOf("BinderTester_A") != -1)
796 typeName = typeName.Replace ("BinderTester_A", "BinderTester_B");
798 return Assembly.Load (assemblyName).GetType (typeName);
803 public class BinderTester_A
810 public class BinderTester_B