context: //
  // System.Runtime.Serialization.Formatters.Soap.SerializationCallbackTest.cs
  //
  // Author: Robert Jordan (robertj@gmx.net)
  //
  
  #if NET_2_0
  
  using System;
  using System.Diagnostics;
  using System.IO;
  using System.Reflection;
  using System.Runtime.Serialization;
  using System.Runtime.Serialization.Formatters.Soap;
  using System.Text;
  using NUnit.Framework;
  
  namespace MonoTests.System.Runtime.Serialization.Formatters.Soap
  {
          [TestFixture]
          public class SerializationCallbackTest
          {
                  [Test]
                  public void Test ()
                  {
                          Log.Clear ();
                          Driver (new SoapFormatter (), new A (new B()));
                          Console.WriteLine (Log.Text);
                          Assert.AreEqual (Log.Text, "A1B1A2B2A3B3B4A4");
                  }
  
                  [Test]
                  public void TestInheritance ()
                  {
                          Log.Clear ();
                          Driver (new SoapFormatter (), new C (new B()));
                          Console.WriteLine (Log.Text);
                          Assert.AreEqual (Log.Text, "A1C1B1A2C2B2A3B3B4A4");
                  }
  
                  [Test]
                  public void TestISerializable ()
                  {
                          Log.Clear ();
                          Driver (new SoapFormatter (), new A (new D()));
                          Console.WriteLine (Log.Text);
                          Assert.AreEqual (Log.Text, "A1B1A2B2A3B3B4A4");
                  }
  
                  void Driver (IFormatter formatter, A a)
                  {
                          MemoryStream stream = new MemoryStream();
                          formatter.Serialize(stream, a);
                          stream.Position = 0;
  
                          a.CheckSerializationStatus ();
                          a = (A) formatter.Deserialize (stream);
                          a.CheckDeserializationStatus ();
                  }
          }
  
          class Log
          {
                  static StringBuilder b = new StringBuilder ();
  
                  public static void Write (string msg)
                  {
                          b.Append (msg);
                  }
  
                  public static void Clear ()
                  {
                          b = new StringBuilder ();
                  }
  
                  public static string Text {
                          get { return b.ToString (); }
                  }
          }
  
          [Serializable]
          class A : IDeserializationCallback
          {
                  public int Status = 0;
                  B inner;
  
                  public A (B inner)
                  {
                          this.inner = inner;
                          this.inner.Outer = this;
                  }
  
                  public void CheckSerializationStatus ()
                  {
                          Assert.AreEqual (2, Status, "#A01");
                  }
  
                  public void CheckDeserializationStatus ()
                  {
                          Assert.AreEqual (2, Status, "#A01");
                  }
  
                  [OnSerializing]
                  void OnSerializing (StreamingContext ctx)
                  {
                          Log.Write ("A1");
                          Assert.AreEqual (0, Status, "#A01");
                          Assert.AreEqual (0, inner.Status, "#A02");
                          Status++;
                  }
  
                  [OnSerialized]
                  void OnSerialized (StreamingContext ctx)
                  {
                          Log.Write ("A2");
                          Assert.AreEqual (1, Status, "#A03");
                          Assert.AreEqual (1, inner.Status, "#A04");
                          // must have no effect after deserialization
                          Status++;
                  }
  
                  [OnDeserializing]
                  void OnDeserializing (StreamingContext ctx)
                  {
                          Log.Write ("A3");
                          Assert.IsNull (inner, "#A05");
                          Assert.AreEqual(0, Status, "#A06");
                          // must have no effect after deserialization
                          Status = 42;
                  }
  
                  [OnDeserialized]
                  void OnDeserialized (StreamingContext ctx)
                  {
                          Log.Write ("A4");
                          Assert.IsNotNull (inner, "#A07");
                          Assert.AreEqual(1, Status, "#A08");
                          Assert.AreEqual(1, inner.Status, "#A10");
                          Status++;
                  }
  
                  void IDeserializationCallback.OnDeserialization (object sender)
                  {
                          // don't log the order because it's undefined
                          CheckDeserializationStatus ();
                  }
  
          }
  
          [Serializable]
          class B : IDeserializationCallback
          {
                  public int Status = 0;
                  public A Outer;
  
                  [OnSerializing]
                  void OnSerializing (StreamingContext ctx)
                  {
                          Log.Write ("B1");
                          Assert.AreEqual (0, Status, "#B01");
                          Assert.AreEqual (1, Outer.Status, "#B01.2");
                          Status++;
                  }
  
                  [OnSerialized]
                  void OnSerialized (StreamingContext ctx)
                  {
                          Log.Write ("B2");
                          Assert.AreEqual (1, Status, "#B02");
                          Assert.AreEqual (2, Outer.Status, "#B03");
                          // must have no effect after deserialization
                          Status++;
                  }
  
                  [OnDeserializing]
                  void OnDeserializing (StreamingContext ctx)
                  {
                          Log.Write ("B3");
                          Assert.IsNull (Outer, "#B05");
                          Assert.AreEqual (0, Status, "#B06");
                          // must have no effect after deserialization
                          Status = 42;
                  }
  
                  [OnDeserialized]
                  void OnDeserialized (StreamingContext ctx)
                  {
                          Log.Write ("B4");
                  }
  
                  void IDeserializationCallback.OnDeserialization (object sender)
                  {
                          // don't log the order because it's undefined
                          Assert.AreEqual (1, Status);
                  }
          }
  
          [Serializable]
          class C : A
          {
                  public C (B inner) : base (inner)
                  {
                  }
  
                  [OnSerializing]
                  void OnSerializing (StreamingContext ctx)
                  {
                          Log.Write ("C1");
                          Assert.AreEqual (1, Status, "#C01");
                  }
  
                  [OnSerialized]
                  void OnSerialized (StreamingContext ctx)
                  {
                          Log.Write ("C2");
                          Assert.AreEqual (2, Status, "#C02");
                  }
          }
  
          [Serializable]
          class D : B, ISerializable
          {
                  public D ()
                  {
                  }
  
                  void ISerializable.GetObjectData (SerializationInfo info, StreamingContext ctx)
                  {
                          info.AddValue ("Status", Status);
  
gt:                         info.AddValue ("Outer", Outer);