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;
23 namespace MonoTests.System.Runtime.Serialization
26 public class SerializationTest
32 [Category ("MobileNotWorking")]
33 public void TestSerialization ()
35 MethodTester mt = new MethodTester();
36 RemotingServices.Marshal (mt);
37 uri = RemotingServices.GetObjectUri (mt);
42 RemotingServices.Disconnect (mt);
47 public void DelegateSerializationTest ()
49 var a = new DelegateSerialization ();
52 var d2 = Delegate.CreateDelegate (typeof(Func<StringBuilder, int>), "val", typeof(SerializationTest).GetMethod ("HandleE2"));
53 a.E += (Func<StringBuilder, int>) d2;
55 using (var ms = new MemoryStream ()) {
56 var fmt = new BinaryFormatter ();
57 fmt.Serialize (ms, a);
60 ms.Seek (0, SeekOrigin.Begin);
61 var a2 = (DelegateSerialization) fmt.Deserialize (ms);
67 static int HandleE1 (StringBuilder arg)
73 public static int HandleE2 (object o, StringBuilder arg)
82 StreamingContext context = new StreamingContext (StreamingContextStates.Other);
83 SurrogateSelector sel = new SurrogateSelector();
84 sel.AddSurrogate (typeof (Point), context, new PointSurrogate());
85 sel.AddSurrogate (typeof (FalseISerializable), context, new FalseISerializableSurrogate());
87 List list = CreateTestData();
88 BinderTester_A bta = CreateBinderTestData();
90 ms = new MemoryStream();
91 BinaryFormatter f = new BinaryFormatter (sel, new StreamingContext(StreamingContextStates.Other));
92 f.Serialize (ms, list);
93 ProcessMessages (ms, null);
94 f.Serialize (ms, bta);
101 StreamingContext context = new StreamingContext (StreamingContextStates.Other);
102 SurrogateSelector sel = new SurrogateSelector();
103 sel.AddSurrogate (typeof (Point), context, new PointSurrogate());
104 sel.AddSurrogate (typeof (FalseISerializable), context, new FalseISerializableSurrogate());
106 BinaryFormatter f = new BinaryFormatter (sel, context);
108 object list = f.Deserialize (ms);
110 object[][] originalMsgData = null;
111 IMessage[] calls = null;
112 IMessage[] resps = null;
114 originalMsgData = ProcessMessages (null, null);
116 calls = new IMessage[originalMsgData.Length];
117 resps = new IMessage[originalMsgData.Length];
120 for (int n=0; n<originalMsgData.Length; n++)
122 calls[n] = (IMessage) f.Deserialize (ms);
123 resps[n] = (IMessage) f.DeserializeMethodResponse (ms, null, (IMethodCallMessage)calls[n]);
126 f.Binder = new TestBinder ();
127 object btbob = f.Deserialize (ms);
131 List expected = CreateTestData ();
132 List actual = (List) list;
133 expected.CheckEquals (actual, "List");
135 for (int i = 0; i < actual.children.Length - 1; ++i)
136 if (actual.children [i].next != actual.children [i+1])
137 Assert.Fail ("Deserialization did not restore pointer graph");
139 BinderTester_A bta = CreateBinderTestData();
140 Assert.AreEqual (btbob.GetType(), typeof (BinderTester_B), "BinderTest.class");
141 BinderTester_B btb = btbob as BinderTester_B;
144 Assert.AreEqual (btb.x, bta.x, "BinderTest.x");
145 Assert.AreEqual (btb.y, bta.y, "BinderTest.y");
148 CheckMessages ("MethodCall", originalMsgData, ProcessMessages (null, calls));
149 CheckMessages ("MethodResponse", originalMsgData, ProcessMessages (null, resps));
152 BinderTester_A CreateBinderTestData ()
154 BinderTester_A bta = new BinderTester_A();
156 bta.y = "binder tester";
160 List CreateTestData()
162 List list = new List();
163 list.name = "my list";
164 list.values = new SomeValues();
167 ListItem item1 = new ListItem();
168 ListItem item2 = new ListItem();
169 ListItem item3 = new ListItem();
171 item1.label = "value label 1";
173 item1.value.color = 111;
174 item1.value.point = new Point();
175 item1.value.point.x = 11;
176 item1.value.point.y = 22;
178 item2.label = "value label 2";
180 item2.value.color = 222;
182 item2.value.point = new Point();
183 item2.value.point.x = 33;
184 item2.value.point.y = 44;
186 item3.label = "value label 3";
187 item3.value.color = 333;
188 item3.value.point = new Point();
189 item3.value.point.x = 55;
190 item3.value.point.y = 66;
192 list.children = new ListItem[3];
194 list.children[0] = item1;
195 list.children[1] = item2;
196 list.children[2] = item3;
202 object[][] ProcessMessages (Stream stream, IMessage[] messages)
204 object[][] results = new object[9][];
206 AuxProxy prx = new AuxProxy (stream, uri);
207 MethodTester mt = (MethodTester)prx.GetTransparentProxy();
210 if (messages != null) prx.SetTestMessage (messages[0]);
211 res = mt.OverloadedMethod();
212 results[0] = new object[] {res};
214 if (messages != null) prx.SetTestMessage (messages[1]);
215 res = mt.OverloadedMethod(22);
216 results[1] = new object[] {res};
218 if (messages != null) prx.SetTestMessage (messages[2]);
219 int[] par1 = new int[] {1,2,3};
220 res = mt.OverloadedMethod(par1);
221 results[2] = new object[] { res, par1 };
223 if (messages != null) prx.SetTestMessage (messages[3]);
226 if (messages != null) prx.SetTestMessage (messages[4]);
227 res = mt.Simple ("hello",44);
228 results[4] = new object[] { res };
230 if (messages != null) prx.SetTestMessage (messages[5]);
231 res = mt.Simple2 ('F');
232 results[5] = new object[] { res };
234 if (messages != null) prx.SetTestMessage (messages[6]);
235 char[] par2 = new char[] { 'G' };
236 res = mt.Simple3 (par2);
237 results[6] = new object[] { res, par2 };
239 if (messages != null) prx.SetTestMessage (messages[7]);
240 res = mt.Simple3 (null);
241 results[7] = new object[] { res };
243 if (messages != null) prx.SetTestMessage (messages[8]);
245 SimpleClass b = new SimpleClass ('H');
246 res = mt.SomeMethod (123456, b);
247 results[8] = new object[] { res, b };
252 void CheckMessages (string label, object[][] original, object[][] serialized)
254 for (int n=0; n<original.Length; n++)
255 EqualsArray (label + " " + n, original[n], serialized[n]);
258 public static void AssertEquals(string message, Object expected, Object actual)
260 if (expected != null && expected.GetType().IsArray)
261 EqualsArray (message, (Array)expected, (Array)actual);
263 Assert.AreEqual (expected, actual, message);
266 public static void EqualsArray (string message, object oar1, object oar2)
268 if (oar1 == null || oar2 == null || !(oar1 is Array) || !(oar2 is Array))
270 Assert.AreEqual (oar1, oar2, message);
274 Array ar1 = (Array) oar1;
275 Array ar2 = (Array) oar2;
277 Assert.AreEqual (ar1.Length, ar2.Length, message + ".Length");
279 for (int n=0; n<ar1.Length; n++)
281 object av1 = ar1.GetValue(n);
282 object av2 = ar2.GetValue(n);
283 SerializationTest.AssertEquals (message + "[" + n + "]", av1, av2);
290 class PointSurrogate: ISerializationSurrogate
292 public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
294 Point p = (Point) obj;
295 info.AddValue ("xv",p.x);
296 info.AddValue ("yv",p.y);
299 public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
301 typeof (Point).GetField ("x").SetValue (obj, info.GetInt32 ("xv"));
302 typeof (Point).GetField ("y").SetValue (obj, info.GetInt32 ("yv"));
310 public string name = null;
311 public ListItem[] children = null;
312 public SomeValues values;
314 public void CheckEquals (List val, string context)
316 Assert.AreEqual (name, val.name, context + ".name");
317 values.CheckEquals (val.values, context + ".values");
319 Assert.AreEqual (children.Length, val.children.Length, context + ".children.Length");
321 for (int n=0; n<children.Length; n++)
322 children[n].CheckEquals (val.children[n], context + ".children[" + n + "]");
327 public class ListItem: ISerializable
333 ListItem (SerializationInfo info, StreamingContext ctx)
335 next = (ListItem)info.GetValue ("next", typeof (ListItem));
336 value = (ListValue)info.GetValue ("value", typeof (ListValue));
337 label = info.GetString ("label");
340 public void GetObjectData (SerializationInfo info, StreamingContext ctx)
342 info.AddValue ("next", next);
343 info.AddValue ("value", value);
344 info.AddValue ("label", label);
347 public void CheckEquals (ListItem val, string context)
349 Assert.AreEqual (label, val.label, context + ".label");
350 value.CheckEquals (val.value, context + ".value");
353 Assert.IsNull (val.next, context + ".next == null");
355 Assert.IsNotNull (val.next, context + ".next != null");
356 next.CheckEquals (val.next, context + ".next");
360 public override bool Equals(object obj)
362 ListItem val = (ListItem)obj;
363 if ((next == null || val.next == null) && (next != val.next)) return false;
364 if (next == null) return true;
365 if (!next.Equals(val.next)) return false;
366 return value.Equals (val.value) && label == val.label;
369 public override int GetHashCode ()
371 return base.GetHashCode ();
374 public ListItem next;
375 public ListValue value;
380 public struct ListValue
385 public override bool Equals(object obj)
387 ListValue val = (ListValue)obj;
388 return (color == val.color && point.Equals(val.point));
391 public void CheckEquals (ListValue val, string context)
393 Assert.AreEqual (color, val.color, context + ".color");
394 point.CheckEquals (val.point, context + ".point");
397 public override int GetHashCode ()
399 return base.GetHashCode ();
408 public override bool Equals(object obj)
410 Point p = (Point)obj;
411 return (x == p.x && y == p.y);
414 public void CheckEquals (Point p, string context)
416 Assert.AreEqual (x, p.x, context + ".x");
417 Assert.AreEqual (y, p.y, context + ".y");
420 public override int GetHashCode ()
422 return base.GetHashCode ();
427 public class FalseISerializable : ISerializable
431 public FalseISerializable (int n)
436 public void GetObjectData(SerializationInfo info, StreamingContext context)
438 throw new InvalidOperationException ("Serialize:We should not pass here.");
441 public FalseISerializable (SerializationInfo info, StreamingContext context)
443 throw new InvalidOperationException ("Deserialize:We should not pass here.");
447 public class FalseISerializableSurrogate : ISerializationSurrogate
449 public void GetObjectData (object obj, SerializationInfo info, StreamingContext context)
451 info.AddValue("field", Convert.ToString (((FalseISerializable)obj).field));
454 public object SetObjectData (object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
456 ((FalseISerializable)obj).field = Convert.ToInt32 (info.GetValue("field", typeof(string)));
462 public class SimpleClass
464 public SimpleClass (char v) { val = v; }
466 public override bool Equals(object obj)
468 if (obj == null) return false;
469 return val == ((SimpleClass)obj).val;
472 public override int GetHashCode()
474 return val.GetHashCode();
477 public int SampleCall (string str, SomeValues sv, ref int acum)
486 enum IntEnum { aaa, bbb, ccc }
487 enum ByteEnum: byte { aaa=221, bbb=3, ccc=44 }
489 delegate int SampleDelegate (string str, SomeValues sv, ref int acum);
492 public class SomeValues
520 public int[,,] _intsMulti;
522 SimpleClass[] _simples;
523 SimpleClass[,] _simplesMulti;
524 SimpleClass[][] _simplesJagged;
526 object[] _almostEmpty;
528 object[] _emptyObjectArray;
529 Type[] _emptyTypeArray;
530 SimpleClass[] _emptySimpleArray;
531 int[] _emptyIntArray;
532 string[] _emptyStringArray;
533 Point[] _emptyPointArray;
536 SampleDelegate _sampleDelegate;
537 SampleDelegate _sampleDelegate2;
538 SampleDelegate _sampleDelegate3;
539 SampleDelegate _sampleDelegateStatic;
540 SampleDelegate _sampleDelegateCombined;
542 SimpleClass _shared1;
543 SimpleClass _shared2;
544 SimpleClass _shared3;
546 FalseISerializable _falseSerializable;
550 _type = typeof (string);
551 _type2 = typeof (SomeValues);
552 _dbnull = DBNull.Value;
553 _assembly = typeof (SomeValues).Assembly;
554 _intEnum = IntEnum.bbb;
555 _byteEnum = ByteEnum.ccc;
560 _dateTime = new DateTime (1972,7,13,1,20,59);
561 _decimal = (decimal)101010.10101;
562 _double = 123456.6789;
567 _float = (float)654321.321;
572 Point p = new Point();
574 object boxedPoint = p;
577 object boxedLong = i;
579 _objects = new object[] { "string", (int)1234, null , /*boxedPoint, boxedPoint,*/ boxedLong, boxedLong};
580 _strings = new string[] { "an", "array", "of", "strings","I","repeat","an", "array", "of", "strings" };
581 _ints = new int[] { 4,5,6,7,8 };
582 _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} } };
583 _intsJagged = new int[2][] { new int[3] {1,2,3}, new int[2] {4,5} };
584 _simples = new SimpleClass[] { new SimpleClass('a'),new SimpleClass('b'),new SimpleClass('c') };
585 _simplesMulti = new SimpleClass[2,3] {{new SimpleClass('d'),new SimpleClass('e'),new SimpleClass('f')}, {new SimpleClass('g'),new SimpleClass('j'),new SimpleClass('h')}};
586 _simplesJagged = new SimpleClass[2][] { new SimpleClass[1] { new SimpleClass('i') }, new SimpleClass[2] {null, new SimpleClass('k')}};
587 _almostEmpty = new object[2000];
588 _almostEmpty[1000] = 4;
590 _emptyObjectArray = new object[0];
591 _emptyTypeArray = new Type[0];
592 _emptySimpleArray = new SimpleClass[0];
593 _emptyIntArray = new int[0];
594 _emptyStringArray = new string[0];
595 _emptyPointArray = new Point[0];
597 _doubles = new double[] { 1010101.101010, 292929.29292, 3838383.38383, 4747474.474, 56565.5656565, 0, Double.NaN, Double.MaxValue, Double.MinValue, Double.NegativeInfinity, Double.PositiveInfinity };
599 _sampleDelegate = new SampleDelegate(SampleCall);
600 _sampleDelegate2 = new SampleDelegate(_simples[0].SampleCall);
601 _sampleDelegate3 = new SampleDelegate(new SimpleClass('x').SampleCall);
602 _sampleDelegateStatic = new SampleDelegate(SampleStaticCall);
603 _sampleDelegateCombined = (SampleDelegate)Delegate.Combine (new Delegate[] {_sampleDelegate, _sampleDelegate2, _sampleDelegate3, _sampleDelegateStatic });
605 // This is to test that references are correctly solved
606 _shared1 = new SimpleClass('A');
607 _shared2 = new SimpleClass('A');
610 _falseSerializable = new FalseISerializable (2);
613 public int SampleCall (string str, SomeValues sv, ref int acum)
619 public static int SampleStaticCall (string str, SomeValues sv, ref int acum)
625 public void CheckEquals (SomeValues obj, string context)
627 Assert.AreEqual (_type, obj._type, context + "._type");
628 Assert.AreEqual (_type2, obj._type2, context + "._type2");
629 Assert.AreEqual (_dbnull, obj._dbnull, context + "._dbnull");
630 Assert.AreEqual (_assembly, obj._assembly, context + "._assembly");
632 Assert.AreEqual (_intEnum, obj._intEnum, context + "._intEnum");
633 Assert.AreEqual (_byteEnum, obj._byteEnum, context + "._byteEnum");
634 Assert.AreEqual (_bool, obj._bool, context + "._bool");
635 Assert.AreEqual (_bool2, obj._bool2, context + "._bool2");
636 Assert.AreEqual (_byte, obj._byte, context + "._byte");
637 Assert.AreEqual (_char, obj._char, context + "._char");
638 Assert.AreEqual (_dateTime, obj._dateTime, context + "._dateTime");
639 Assert.AreEqual (_decimal, obj._decimal, context + "._decimal");
640 Assert.AreEqual (_double, obj._double, context + "._double");
641 Assert.AreEqual (_short, obj._short, context = "._short");
642 Assert.AreEqual (_int, obj._int, context + "._int");
643 Assert.AreEqual (_long, obj._long, context + "._long");
644 Assert.AreEqual (_sbyte, obj._sbyte, context + "._sbyte");
645 Assert.AreEqual (_float, obj._float, context + "._float");
646 Assert.AreEqual (_ushort, obj._ushort, context + "._ushort");
647 Assert.AreEqual (_uint, obj._uint, context + "._uint");
648 Assert.AreEqual (_ulong, obj._ulong, context + "._ulong");
650 SerializationTest.EqualsArray (context + "._objects", _objects, obj._objects);
651 SerializationTest.EqualsArray (context + "._strings", _strings, obj._strings);
652 SerializationTest.EqualsArray (context + "._doubles", _doubles, obj._doubles);
653 SerializationTest.EqualsArray (context + "._ints", _ints, obj._ints);
654 SerializationTest.EqualsArray (context + "._simples", _simples, obj._simples);
655 SerializationTest.EqualsArray (context + "._almostEmpty", _almostEmpty, obj._almostEmpty);
657 SerializationTest.EqualsArray (context + "._emptyObjectArray", _emptyObjectArray, obj._emptyObjectArray);
658 SerializationTest.EqualsArray (context + "._emptyTypeArray", _emptyTypeArray, obj._emptyTypeArray);
659 SerializationTest.EqualsArray (context + "._emptySimpleArray", _emptySimpleArray, obj._emptySimpleArray);
660 SerializationTest.EqualsArray (context + "._emptyIntArray", _emptyIntArray, obj._emptyIntArray);
661 SerializationTest.EqualsArray (context + "._emptyStringArray", _emptyStringArray, obj._emptyStringArray);
662 SerializationTest.EqualsArray (context + "._emptyPointArray", _emptyPointArray, obj._emptyPointArray);
664 for (int i=0; i<2; i++)
665 for (int j=0; j<3; j++)
666 for (int k=0; k<4; k++)
667 SerializationTest.AssertEquals("SomeValues._intsMulti[" + i + "," + j + "," + k + "]", _intsMulti[i,j,k], obj._intsMulti[i,j,k]);
669 for (int i=0; i<_intsJagged.Length; i++)
670 for (int j=0; j<_intsJagged[i].Length; j++)
671 SerializationTest.AssertEquals ("SomeValues._intsJagged[" + i + "][" + j + "]", _intsJagged[i][j], obj._intsJagged[i][j]);
673 for (int i=0; i<2; i++)
674 for (int j=0; j<3; j++)
675 SerializationTest.AssertEquals ("SomeValues._simplesMulti[" + i + "," + j + "]", _simplesMulti[i,j], obj._simplesMulti[i,j]);
677 for (int i=0; i<_simplesJagged.Length; i++)
678 SerializationTest.EqualsArray ("SomeValues._simplesJagged", _simplesJagged[i], obj._simplesJagged[i]);
681 SerializationTest.AssertEquals ("SomeValues._sampleDelegate", _sampleDelegate ("hi", this, ref acum), _int);
682 SerializationTest.AssertEquals ("SomeValues._sampleDelegate_bis", _sampleDelegate ("hi", this, ref acum), obj._sampleDelegate ("hi", this, ref acum));
684 SerializationTest.AssertEquals ("SomeValues._sampleDelegate2", _sampleDelegate2 ("hi", this, ref acum), (int)_simples[0].val);
685 SerializationTest.AssertEquals ("SomeValues._sampleDelegate2_bis", _sampleDelegate2 ("hi", this, ref acum), obj._sampleDelegate2 ("hi", this, ref acum));
687 SerializationTest.AssertEquals ("SomeValues._sampleDelegate3", _sampleDelegate3 ("hi", this, ref acum), (int)'x');
688 SerializationTest.AssertEquals ("SomeValues._sampleDelegate3_bis", _sampleDelegate3 ("hi", this, ref acum), obj._sampleDelegate3 ("hi", this, ref acum));
690 SerializationTest.AssertEquals ("SomeValues._sampleDelegateStatic", _sampleDelegateStatic ("hi", this, ref acum), 99);
691 SerializationTest.AssertEquals ("SomeValues._sampleDelegateStatic_bis", _sampleDelegateStatic ("hi", this, ref acum), obj._sampleDelegateStatic ("hi", this, ref acum));
695 _sampleDelegateCombined ("hi", this, ref acum1);
696 obj._sampleDelegateCombined ("hi", this, ref acum2);
698 SerializationTest.AssertEquals ("_sampleDelegateCombined", acum1, _int + (int)_simples[0].val + (int)'x' + 99);
699 SerializationTest.AssertEquals ("_sampleDelegateCombined_bis", acum1, acum2);
701 SerializationTest.AssertEquals ("SomeValues._shared1", _shared1, _shared2);
702 SerializationTest.AssertEquals ("SomeValues._shared1_bis", _shared1, _shared3);
705 SerializationTest.AssertEquals ("SomeValues._shared2", _shared2.val, 'A');
706 SerializationTest.AssertEquals ("SomeValues._shared3", _shared3.val, 'B');
708 SerializationTest.AssertEquals ("SomeValues._falseSerializable", _falseSerializable.field, 2);
712 class MethodTester : MarshalByRefObject
714 public int OverloadedMethod ()
719 public int OverloadedMethod (int a)
724 public int OverloadedMethod (int[] a)
729 public void NoReturn ()
732 public string Simple (string a, int b)
737 public SimpleClass Simple2 (char c)
739 return new SimpleClass(c);
742 public SimpleClass Simple3 (char[] c)
744 if (c != null) return new SimpleClass(c[0]);
748 public int SomeMethod (int a, SimpleClass b)
752 int r = a + c.Length;
760 class AuxProxy: RealProxy
762 public static bool useHeaders = false;
765 IMethodMessage _testMsg;
767 public AuxProxy(Stream stream, string uri): base(typeof(MethodTester))
773 public void SetTestMessage (IMessage msg)
775 _testMsg = (IMethodMessage)msg;
776 _testMsg.Properties["__Uri"] = _uri;
779 public override IMessage Invoke(IMessage msg)
781 IMethodCallMessage call = (IMethodCallMessage)msg;
782 if (call.MethodName.StartsWith ("Initialize")) return new ReturnMessage(null,null,0,null,(IMethodCallMessage)msg);
784 call.Properties["__Uri"] = _uri;
788 SerializeCall (call);
789 IMessage response = ChannelServices.SyncDispatchMessage (call);
790 SerializeResponse (response);
793 else if (_testMsg != null)
795 if (_testMsg is IMethodCallMessage)
796 return ChannelServices.SyncDispatchMessage (_testMsg);
801 return ChannelServices.SyncDispatchMessage (call);
804 void SerializeCall (IMessage call)
806 RemotingSurrogateSelector rss = new RemotingSurrogateSelector();
807 var fmt = new BinaryFormatter (rss, new StreamingContext(StreamingContextStates.Remoting));
808 fmt.Serialize (_stream, call, GetHeaders());
811 void SerializeResponse (IMessage resp)
813 RemotingSurrogateSelector rss = new RemotingSurrogateSelector();
814 var fmt = new BinaryFormatter (rss, new StreamingContext(StreamingContextStates.Remoting));
815 fmt.Serialize (_stream, resp, GetHeaders());
818 Header[] GetHeaders()
824 hs[0] = new Header("unom",new SimpleClass('R'));
830 public class TestBinder : SerializationBinder
832 public override Type BindToType (string assemblyName, string typeName)
834 if (typeName.IndexOf("BinderTester_A") != -1)
835 typeName = typeName.Replace ("BinderTester_A", "BinderTester_B");
837 return Assembly.Load (assemblyName).GetType (typeName);
842 public class BinderTester_A
849 public class BinderTester_B
856 class DelegateSerialization
858 public event Func<StringBuilder, int> E;
862 var sb = new StringBuilder ();
863 Assert.AreEqual (2, E (sb), "#1");
864 Assert.AreEqual ("E1E2|val", sb.ToString (), "#2");