BindingFlags.Public needed here as Exception.HResult is now public in .NET 4.5. This...
[mono.git] / mcs / class / corlib / Test / System.Runtime.Serialization.Formatters.Binary / VersionTolerantSerialization / BinarySerializationOverVersions.cs
1 using System;
2 using System.Collections;
3 using System.Text;
4 using System.Diagnostics;
5 using System.Reflection;
6 using System.IO;
7 using System.Runtime.Serialization;
8 using System.Runtime.Serialization.Formatters.Binary;
9 using NUnit.Framework;
10
11 namespace MonoTests.System.Runtime.Serialization.Formatters.Binary
12 {
13         [TestFixture]
14         public class BinarySerializationOverVersions {
15
16                 static readonly string dirName = typeof(VersionTolerantSerializationTestLib.Address).Namespace;
17                 static readonly string assemblyName = typeof(VersionTolerantSerializationTestLib.Address).Name;
18                 static readonly string assemblyFileName = assemblyName + ".dll";
19                 static readonly string binName = Path.GetFileName (Assembly.GetExecutingAssembly ().Location);
20                 const bool cleanup = true;
21                 enum OopOperation { Serialize, Deserialize }
22                 static IFormatter formatter = new BinaryFormatter ();
23
24
25                 //TODO: add tests that use SoapFormatter (if you go this
26                 //        path, it would be interesting also to test a
27                 //        custom formatter, like the XML-RPC.net one!)
28                 public virtual IFormatter Formatter { get { return formatter; } }
29
30                 static void Main (string [] args)
31                 {
32                         var p = new BinarySerializationOverVersions ();
33
34                         /* this block is useful for testing this without NUnit:
35                         if (args.Length == 0)
36                         {
37                                 Console.WriteLine ("Starting...");
38                                 p.TestDroppedField ();
39                                 Console.Write ("x");
40                                 p.TestAddedField ();
41                                 Console.Write ("x");
42
43                                 p.TestAddedFieldWithData ();
44                                 Console.Write ("x");
45                                 p.TestDroppedFieldWithData ();
46                                 Console.Write ("x");
47
48                                 p.TestAddedFieldWithOptionalAttrib ();
49                                 Console.Write ("x");
50                                 p.TestDroppedFieldWithOptionalAttrib ();
51                                 Console.Write ("x");
52
53                                 p.TestAddedFieldWithOptionalAttribAndData ();
54                                 Console.Write ("x");
55                                 p.TestDroppedFieldWithOptionalAttribAndData ();
56                                 Console.Write ("x");
57                                 
58                                 Console.WriteLine ();
59                                 Environment.Exit (0);
60                         }*/
61
62                         if (args.Length < 2)
63                                 throw new Exception ("Please specify arguments");
64
65                         if (args [0] == OopOperation.Serialize.ToString ())
66                         {
67                                 p.SerializeToFile (args [1]);
68                         }
69                         else if (args [0] == OopOperation.Deserialize.ToString ())
70                         {
71                                 p.DeserializeFromFile (args [1]);
72                         }
73                         else
74                         {
75                                 throw new Exception(String.Format ("{0} operation not recognized. Only {Serialize|Deserialize} operations are supported.", args [0]));
76                         }
77                 }
78
79                 [Test]
80                 public void TestDroppedField () //eliminate CountryCode
81                 {
82                         Deserialize ("2.0", Serialize ("3.0"));
83                 }
84
85                 [Test]
86                 public void TestAddedField () //add CountryCode
87                 {
88                         Deserialize ("3.0", Serialize ("2.0"));
89                 }
90
91                 [Test]
92                 public void TestAddedFieldWithData () //add Country
93                 {
94                         Deserialize( "1.0", Serialize ("2.0"));
95                 }
96
97                 [Test]
98                 public void TestDroppedFieldWithData () //eliminate Country
99                 {
100                         Deserialize ("2.0", Serialize ("3.0"));
101                 }
102
103                 [Test]
104                 public void TestAddedFieldWithOptionalAttrib () //add PostCode
105                 {
106                         Deserialize ("4.0", Serialize ("3.0"));
107                 }
108
109                 [Test]
110                 public void TestDroppedFieldWithOptionalAttrib () //eliminate PostCode
111                 {
112                         Deserialize ("3.0", Serialize ("4.0"));
113                 }
114
115                 [Test]
116                 public void TestAddedFieldWithOptionalAttribAndData () //add AreaCode
117                 {
118                         Deserialize ("5.0", Serialize ("4.0"));
119                 }
120
121                 [Test]
122                 public void TestDroppedFieldWithOptionalAttribAndData () //eliminate AreaCode
123                 {
124                         Deserialize ("4.0", Serialize ("5.0"));
125                 }
126
127                 [Test]
128                 public void TestDroppedPrimitiveTypeField() //eliminate Id (int)
129                 {
130                         Deserialize ("5.0", Serialize ("6.0"));
131                 }
132
133                 [Test]
134                 public void TestAddedPrimitiveTypeField () //add Id (int)
135                 {
136                         Deserialize ("6.0", Serialize ("5.0"));
137                 }
138
139                 private static string Serialize (string assemblyVersion)
140                 {
141                         return SerializeOOP (SetEnvironment (assemblyVersion)); ;
142                 }
143
144                 private static void Deserialize (string assemblyVersion, string filename)
145                 {
146                         DeserializeOOP (SetEnvironment (assemblyVersion), filename);
147                 }
148
149                 private static string SerializeOOP (string executionDir)
150                 {
151                         string filename = Path.GetTempFileName ();
152                         var p = new Process ();
153                         p.StartInfo.WorkingDirectory = executionDir;
154                         p.StartInfo.FileName = Path.Combine (executionDir, binName);
155                         p.StartInfo.Arguments = OopOperation.Serialize.ToString () + " \"" + filename + "\"";
156                         p.StartInfo.UseShellExecute = false;
157                         p.Start();
158                         p.WaitForExit();
159                         if (p.ExitCode != 0)
160                                 throw new Exception ("Problem in serialization operation");
161
162                         if (cleanup)
163                                 Directory.Delete (executionDir, true);
164
165                         return filename;
166                 }
167
168                 private static void DeserializeOOP (string executionDir, string filename)
169                 {
170                         var p = new Process ();
171                         p.StartInfo.WorkingDirectory = executionDir;
172                         p.StartInfo.FileName = Path.Combine (executionDir, binName);
173                         p.StartInfo.Arguments = OopOperation.Deserialize.ToString () + " \"" + filename + "\"";
174                         p.StartInfo.UseShellExecute = false;
175                         p.Start ();
176                         p.WaitForExit ();
177                         if (p.ExitCode != 0)
178                                 throw new Exception("Problem in deserialization operation");
179
180                         if (cleanup)
181                         {
182                                 Directory.Delete (executionDir, true);
183                                 File.Delete (filename);
184                         }
185                 }
186
187                 private static string SetEnvironment (string assemblyVersion)
188                 {
189                         if (!assemblyVersion.Contains ("."))
190                                 throw new NotSupportedException ("The version number should contain a dot, i.e.: 2.0");
191
192                         string tmpDir = Path.Combine (Path.GetTempPath (), "deleteme" + Guid.NewGuid ());
193                         Directory.CreateDirectory (tmpDir);
194                         string currentBin = Assembly.GetExecutingAssembly ().Location;
195                         File.Copy (currentBin, Path.Combine (tmpDir, Path.GetFileName (currentBin)));
196
197                         string ass = Find (assemblyVersion);
198                         File.Copy (ass, Path.Combine (tmpDir, Path.GetFileName (ass)));
199                         return tmpDir;
200                 }
201
202                 private static string Find (string assemblyVersion)
203                 {
204                         string initDir = Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location);
205                         return Find (assemblyVersion, initDir);
206                 }
207
208                 private static string Find (string assemblyVersion, string path)
209                 {
210                         return  Path.Combine (Path.Combine (path, assemblyVersion), assemblyFileName);
211 /*                      
212                         Console.WriteLine ("Looking in " + path);
213                         string test;
214
215                         if (!path.Contains(assemblyVersion))
216                         {
217                                 //outside or here
218
219                                 if (Path.GetFileName(path) == dirName)
220                                 {
221                                         test = Path.Combine (path, assemblyVersion);
222                                         if (Directory.Exists (test))
223                                                 return Find (assemblyVersion, test);
224                                         else
225                                                 throw new DirectoryNotFoundException (String.Format ("{0} was not found", test));
226                                 }
227
228                                 test = Path.Combine (path, dirName);
229                                 if (Directory.Exists (test))
230                                         return Find (assemblyVersion, test);
231
232                                 return Find (assemblyVersion, Path.Combine (path, ".."));
233                         }
234                         else
235                         {
236                                 //inside
237                                 test = Path.Combine (path, assemblyFileName);
238                                 if (File.Exists (test))
239                                         return test;
240
241                                 test = Path.Combine (path, "bin");
242                                 if (Directory.Exists (test))
243                                         return Find (assemblyVersion, test);
244
245                                 test = Path.Combine (path, "Debug");
246                                 if (Directory.Exists (test))
247                                         return Find (assemblyVersion, test);
248
249                                 test = Path.Combine (path, "Release");
250                                 if (Directory.Exists (test))
251                                         return Find (assemblyVersion, test);
252
253                                 test = Path.Combine (path.Replace ("Debug", "Release"), assemblyFileName);
254                                 if (File.Exists (test))
255                                         return test;
256
257                                 throw new NotSupportedException(
258                                         String.Format(
259                                                 "The tree is not predictible according to the philosophy of the test. (Stuck in {0})",
260                                                 path));
261                         }
262 */
263                 }
264
265                 private void SerializeToFile (string filename)
266                 {
267                         var type = typeof (VersionTolerantSerializationTestLib.Address);
268                         object obj = Activator.CreateInstance (type);
269                         Stream stream = new FileStream (filename,
270                                                                                    FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
271                         Formatter.Serialize (stream, obj);
272                         stream.Dispose ();
273                 }
274
275                 private void DeserializeFromFile (string filename)
276                 {
277                         //Console.WriteLine("Trying to deserialize {0}...", filename);
278                         FileStream readStream = new FileStream (filename, FileMode.Open);
279                         //var readData = 
280                         Formatter.Deserialize (readStream);
281                 }
282         }
283 }