45e7bc9294ceae70fef06afa9aaf8c4c4e7cbb9b
[mono.git] / mcs / class / System.Web.Services / Test / standalone / wstest.cs
1 using System;
2 using System.IO;
3 using System.Collections;
4 using System.Text;
5 using System.Xml;
6 using System.Xml.Xsl;
7 using System.Xml.Serialization;
8 using System.ComponentModel;
9 using System.Diagnostics;
10 using System.Threading;
11 using System.Web.Services.Discovery;
12 using System.Web.Services.Description;
13 using System.Net;
14
15 public class Driver
16 {
17         static bool foundErrors = false;
18         static string basePath;
19         static int runningCount;
20         
21         static ServiceCollection services;
22         static ServiceStatusCollection serviceStatus;
23         
24         public static void Main (string[] args)
25         {
26                 if (args.Length == 0)
27                 {
28                         Console.WriteLine ();
29                         Console.WriteLine ("Usage: wstest [options]");
30                         Console.WriteLine ();
31                         Console.WriteLine ("Options:");
32                         Console.WriteLine ("  ur <url>: Update service references from DISCO or WSDL document");
33                         Console.WriteLine ("  dw: download wsdl documents for registered services");
34                         Console.WriteLine ("  gp: Generate proxies");
35                         Console.WriteLine ("  gc <url>: Generate test client class");
36                         Console.WriteLine ();
37                         return;
38                 }
39                 
40                 basePath = ".";
41                 
42                 LoadInfo ();
43                 
44                 if (args[0] == "gp")
45                 {
46                         BuildProxies (GetArg (args,1));
47                 }
48                 else if (args[0] == "gc")
49                 {
50                         BuildClients (GetArg (args,1));
51                 }
52                 else if (args[0] == "ur")
53                 {
54                         UpdateReferences (GetArg (args,1), GetArg (args,2));
55                 }
56                 else if (args[0] == "stat")
57                 {
58                         ShowStatus ();
59                 }
60                 else if (args[0] == "dw")
61                 {
62                         DownloadWsdls (GetArg (args,1));
63                 }
64                 else if (args[0] == "clean")
65                 {
66                         Clean ();
67                 }
68                 else if (args[0] == "checkdiff")
69                 {
70                         CheckDiff (GetArg (args,1));
71                 }
72                 else if (args[0] == "msfix")
73                 {
74                         MsFix (GetArg (args,1));
75                 }
76                 else if (args[0] == "genfiles")
77                 {
78                         GenerateFiles (GetArg (args,1));
79                 }
80                 
81                 SaveInfo ();
82                 
83                 if (foundErrors)
84                         Console.WriteLine ("Please check error log at " + Path.Combine (GetErrorPath(), "error.log"));
85         }
86         
87         static void LoadInfo ()
88         {
89                 XmlSerializer ser = new XmlSerializer (typeof(ServiceCollection));
90                 
91                 string servicesFile = Path.Combine (basePath, "services.xml");
92                 if (!File.Exists (servicesFile)) 
93                         services = new ServiceCollection ();
94                 else
95                 {
96                         StreamReader sr = new StreamReader (servicesFile);
97                         services = (ServiceCollection) ser.Deserialize (sr);
98                         sr.Close ();
99                 }
100                 
101                 ser = new XmlSerializer (typeof(ServiceStatusCollection));
102                 
103                 servicesFile = Path.Combine (basePath, "serviceStatus.xml");
104                 if (!File.Exists (servicesFile)) 
105                         serviceStatus = new ServiceStatusCollection ();
106                 else
107                 {
108                         StreamReader sr = new StreamReader (servicesFile);
109                         serviceStatus = (ServiceStatusCollection) ser.Deserialize (sr);
110                         sr.Close ();
111                 }
112         }
113         
114         static void SaveInfo ()
115         {
116                 XmlSerializer ser = new XmlSerializer (typeof(ServiceCollection));
117                 string servicesFile = Path.Combine (basePath, "services.xml");
118                 StreamWriter sw = new StreamWriter (servicesFile);
119                 ser.Serialize (sw, services);
120                 sw.Close ();
121                 
122                 ser = new XmlSerializer (typeof(ServiceStatusCollection));
123                 servicesFile = Path.Combine (basePath, "serviceStatus.xml");
124                 sw = new StreamWriter (servicesFile);
125                 ser.Serialize (sw, serviceStatus);
126                 sw.Close ();
127         }
128         
129         static string GetArg (string[] args, int n)
130         {
131                 if (n >= args.Length) return null;
132                 else return args[n];
133         }
134         
135         static void Cleanup ()
136         {
137                 string pp = GetProxyPath ();
138                 DirectoryInfo di = new DirectoryInfo (pp);
139                 if (di.Exists) di.Delete (true);
140                 di.Create ();
141         }
142         
143         static void Clean ()
144         {
145                 Hashtable clientHash = new Hashtable ();
146                 
147                 foreach (ServiceData sd in services.services)
148                 {
149                         if (sd.ClientTest)
150                                 clientHash [GetClientFile (sd)] = sd;
151                                 
152                         if (sd.Protocols != null)
153                         {
154                                 foreach (string prot in sd.Protocols)
155                                         clientHash [GetProxyFile (sd, prot)] = sd;
156                         }
157                         clientHash [GetWsdlFile (sd)] = sd;
158                 }
159                         
160                 Clean (clientHash, GetClientPath ());
161                 Clean (clientHash, GetProxyPath ());
162                 Clean (clientHash, GetWsdlPath ());
163         }
164         
165         static void Clean (Hashtable clientHash, string path)
166         {
167                 if (Path.GetFileName (path) == "CVS") return;
168                 
169                 string[] files = Directory.GetFiles (path);
170
171                 foreach (string file in files)
172                 {
173                         ServiceData sd = clientHash [file] as ServiceData;
174                         if (sd != null) continue;
175                         
176                         File.Delete (file);
177                         Console.WriteLine ("Deleted file '" + file + "'");
178                 }
179                 
180                 string [] dirs = Directory.GetDirectories (path);
181                 foreach (string dir in dirs)
182                         Clean (clientHash, dir);
183                         
184                 int count = Directory.GetFiles (path).Length + Directory.GetDirectories (path).Length;
185                 if (count == 0 && path != GetClientPath () && path != GetProxyPath ())
186                 {
187                         Directory.Delete (path);
188                         Console.WriteLine ("Deleted directory '" + path + "'");
189                 }
190         }
191         
192         static void UpdateReferences (string url, string ignoreFile)
193         {       
194                 Console.WriteLine ();
195                 Console.WriteLine ("Updating service references");
196                 Console.WriteLine ("---------------------------");
197                 
198                 ArrayList ignoreList = new ArrayList ();
199                 
200                 if (ignoreFile != null)
201                 {
202                         StreamReader sr = new StreamReader (ignoreFile);
203                         string line;
204                         while ((line = sr.ReadLine ()) != null)
205                         {
206                                 int i = line.IndexOfAny (new char[] {' ','\t'});
207                                 if (i != -1) line = line.Substring (0,i);
208                                 ignoreList.Add (line);
209                         }
210                 }
211                 
212                 DiscoveryClientProtocol client = new DiscoveryClientProtocol ();
213                 client.DiscoverAny (url);
214                 
215                 ArrayList list = new ArrayList (client.References.Values);
216                 foreach (DiscoveryReference re in list)
217                 {
218                         if (!(re is ContractReference)) continue;
219                         
220                         bool ignore = ignoreList.Contains (re.Url);
221                         
222                         ServiceData sd = FindService (re.Url);
223                         
224                         if (ignore)
225                         {
226                                 if (sd != null) {
227                                         RemoveService (re.Url);
228                                         Console.WriteLine ("Removed " + re.Url);
229                                 }
230                                 continue;
231                         }
232                         
233                         if (sd == null)
234                         {
235                                 sd = CreateServiceData (re);
236                                 Console.WriteLine ("Added " + re.Url);
237                                 services.services.Add (sd);
238                         }
239                 }
240                 Console.WriteLine ("Done");
241                 Console.WriteLine ();
242         }
243         
244         static void DownloadWsdls (string host)
245         {
246                 Console.WriteLine ();
247                 Console.WriteLine ("Downloading WSDL documents");
248                 Console.WriteLine ("---------------------------");
249                 
250                 foreach (ServiceData sd in services.services) {
251                         if (host != null && host != new Uri (sd.Wsdl).Host) continue;
252                         if (!File.Exists (GetWsdlFile(sd)))
253                                 Resolve (sd);
254                 }
255                                 
256                 Console.WriteLine ("Done");
257                 Console.WriteLine ();
258         }
259         
260         static void Resolve (ServiceData sd)
261         {
262                 Console.Write ("Resolving " + sd.Wsdl + " ");
263                 try
264                 {
265                         DiscoveryClientProtocol contract = new DiscoveryClientProtocol ();
266                         contract.DiscoverAny (sd.Wsdl);
267                         
268                         if (sd.Protocols == null || sd.Protocols.Length==0) 
269                                 RetrieveServiceData (sd, contract);
270                                 
271                         string wsdlFile = GetWsdlFile (sd);
272                         CreateFolderForFile (wsdlFile);
273                         
274                         ServiceDescription doc = (ServiceDescription) contract.Documents [sd.Wsdl];
275                         doc.Write (wsdlFile);
276                         
277                         Console.WriteLine ("OK");
278                         CleanFailures (sd);
279                 }
280                 catch (Exception ex)
281                 {
282                         Console.WriteLine ("FAILED");
283                         ReportError ("Error resolving: " + sd.Wsdl, ex.ToString ());
284                         RegisterFailure (sd);
285                 }
286         }
287         
288         public static ServiceData CreateServiceData (DiscoveryReference dref)
289         {
290                 ServiceData sd = new ServiceData ();
291                 
292                 string name = GetServiceName (dref);
293                 sd.Name = name;
294                 int nc = 2;
295                 while (FindServiceByName (sd.Name) != null)
296                 {
297                         sd.Name = name + nc;
298                         nc++;
299                 }
300                 
301                 sd.Wsdl = dref.Url;
302                 return sd;
303         }
304         
305         public static void RetrieveServiceData (ServiceData sd, DiscoveryClientProtocol contract)
306         {
307                 ServiceDescriptionCollection col = new ServiceDescriptionCollection ();
308                 foreach (object doc in contract.Documents.Values)
309                         if (doc is ServiceDescription) col.Add ((ServiceDescription)doc);
310                 
311                 string loc = GetLocation (col[0]);
312                 if (loc != null)
313                 {
314                         WebResponse res = null;
315                         try
316                         {
317                                 WebRequest req = (WebRequest)WebRequest.Create (loc);
318                                 req.Timeout = 15000;
319                                 res = req.GetResponse ();
320                         }
321                         catch (Exception ex)
322                         {
323                                 WebException wex = ex as WebException;
324                                 if (wex != null) res = wex.Response;
325                         }
326                         if (res != null)
327                         {
328                                 sd.ServerType = res.Headers ["Server"] + " # " + res.Headers ["X-Powered-By"];
329                         }
330                 }
331                 
332                 ArrayList bins = GetBindingTypes (col);
333                 sd.Protocols = (string[]) bins.ToArray(typeof(string));
334         }
335         
336         static ArrayList GetBindingTypes (ServiceDescriptionCollection col)
337         {
338                 ServiceDescription doc = col [0];
339                 ArrayList list = new ArrayList ();
340                 foreach (Service s in doc.Services)
341                 {
342                         foreach (Port p in s.Ports)
343                         {
344                                 Binding bin = col.GetBinding (p.Binding);
345                                 if (bin.Extensions.Find (typeof (System.Web.Services.Description.SoapBinding)) != null)
346                                         if (!list.Contains ("Soap")) list.Add ("Soap");
347                                         
348                                 HttpBinding ext = (HttpBinding) bin.Extensions.Find (typeof (HttpBinding));
349                                 if (ext != null)
350                                 {
351                                         if (ext.Verb == "POST") list.Add ("HttpPost");
352                                         else list.Add ("HttpGet");
353                                 }
354                         }
355                 }
356                 return list;
357         }
358         
359         static string GetLocation (ServiceDescription doc)
360         {
361                 foreach (Service s in doc.Services)
362                 {
363                         foreach (Port p in s.Ports)
364                         {
365                                 SoapAddressBinding loc = (SoapAddressBinding) p.Extensions.Find (typeof (System.Web.Services.Description.SoapAddressBinding));
366                                 if (loc != null)
367                                         return loc.Location;
368                         }
369                 }
370                 return null;
371         }
372         
373         static string GetServiceName (DiscoveryReference dref)
374         {
375                 string name = dref.DefaultFilename;
376                 
377                 if (name.EndsWith (".wsdl")) name = name.Substring (0,name.Length-5);
378                 if (name == "wsd")
379                 {
380                         int i = dref.Url.IndexOf ("service=");
381                         if (i == -1) name = dref.Url.Substring (7);
382                         else name = dref.Url.Substring (i+8);
383                 }
384                 
385                 name = name + "Test";
386                 if (Char.IsDigit (name,0)) name = "Ws" + name;
387                 return Normalize (name);
388         }
389         
390         static string Normalize (string s)
391         {
392                 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
393                 for (int n=0; n<s.Length; n++)
394                         if (Char.IsLetterOrDigit (s[n]) || s[n] == '_') sb.Append (s[n]);
395                         
396                 return sb.ToString ();
397         }
398         
399 /*      static string GetFileName (DiscoveryReference dref)
400         {
401                 return Path.Combine (classPath, GetServiceName (dref) + ".cs");
402         }
403 */
404
405         static ServiceData FindService (string url)
406         {
407                 foreach (ServiceData sd in services.services)
408                         if (sd.Wsdl == url) return sd;
409
410                 return null;
411         }
412
413         static void RemoveService (string url)
414         {
415                 for (int n=0; n<services.services.Count; n++)
416                 {
417                         ServiceData sd  = (ServiceData) services.services [n];
418                         if (sd.Wsdl == url) { services.services.RemoveAt (n); return; }
419                 }
420         }
421
422         static ServiceData FindServiceByName (string name)
423         {
424                 foreach (ServiceData sd in services.services)
425                         if (sd.Name == name) return sd;
426
427                 return null;
428         }
429         
430         static void ShowStatus ()
431         {
432                 int total = 0;
433                 int soap = 0;
434                 int post = 0;
435                 int get = 0;
436                 int tests = 0;
437                 
438                 Hashtable servers = new Hashtable ();
439                 
440                 foreach (ServiceData sd in services.services)
441                 {
442                         if (sd.Protocols != null)
443                         {
444                                 if (Array.IndexOf(sd.Protocols, "Soap") != -1) soap++;
445                                 if (Array.IndexOf(sd.Protocols, "HttpPost") != -1) post++;
446                                 if (Array.IndexOf(sd.Protocols, "HttpGet") != -1) get++;
447                         }
448                         
449                         if (sd.ClientTest) tests++;
450                         
451                         string st = sd.ServerType;
452                         if (st == null) st = "Unknown";
453                         object on = servers [st];
454                         
455                         if (on == null)
456                                 servers [st] = 1;
457                         else
458                                 servers [st] = ((int)on)+1;
459                 }
460                 
461                 Console.WriteLine ("Total services: " + services.services.Count);
462                 Console.WriteLine ("Soap Protocol: " + soap);
463                 Console.WriteLine ("HttpPost Protocol: " + post);
464                 Console.WriteLine ("HttpGet Protocol:  " + get);
465                 Console.WriteLine ("Total proxies: " + (soap + post + get));
466                 Console.WriteLine ("Nunit Tests: " + tests);
467                 Console.WriteLine ();
468                 Console.WriteLine ("Server Types:");
469                 
470                 string[] serverNames = new string[servers.Count];
471                 int[] serverCounts = new int[servers.Count];
472                 int n=0;
473                 
474                 foreach (DictionaryEntry ent in servers)
475                 {
476                         serverNames [n] = (string) ent.Key;
477                         serverCounts [n++] = (int) ent.Value;
478                 }
479                 
480                 Array.Sort (serverCounts, serverNames);
481                 for (n=serverNames.Length-1; n >=0; n--)
482                         Console.WriteLine ("{0,-3} {1}", serverCounts[n], serverNames[n]);
483         }
484
485         static void BuildProxies (string host)
486         {
487                 Console.WriteLine ();
488                 Console.WriteLine ("Generating proxies");
489                 Console.WriteLine ("------------------");
490                 
491                 XmlDocument doc = new XmlDocument ();
492                 XmlElement ele = doc.CreateElement ("errors");
493                 doc.AppendChild (ele);
494                 
495                 bool buildAll = host == "*";
496                 if (buildAll) host = null;
497                 
498                 ArrayList proxies = new ArrayList ();
499                 
500                 foreach (ServiceData fd in services.services) {
501                         if (host != null && host != new Uri (fd.Wsdl).Host) continue;
502                         BuildProxy (fd, buildAll, proxies, ele);
503                 }
504                 
505                 StreamWriter sw = new StreamWriter (Path.Combine (basePath, "proxies.sources"));
506                 foreach (string f in proxies)
507                         sw.WriteLine (f);
508                 sw.Close ();
509                 
510                 doc.Save ("proxy-gen-error.xml");               
511                 Console.WriteLine ("Done");
512                 Console.WriteLine ();
513         }
514         
515         static void BuildProxy (ServiceData fd, bool rebuild, ArrayList proxies, XmlElement errdoc)
516         {
517                 string wsdl = GetWsdlFile (fd);
518                 if (!File.Exists (wsdl)) 
519                         return;
520                 
521                 if (fd.Protocols == null)
522                 {
523                         ReportError ("Client test '" + fd.Name + "': no protocols declared", "");
524                         return;
525                 }
526                 
527                 foreach (string prot in fd.Protocols)
528                 {
529                         string ns = fd.Namespace;
530                         ns = CodeIdentifier.MakeValid (ns) + "." + prot;
531                 
532                         string pfile = GetProxyFile (fd, prot);
533                         if (File.Exists (pfile) && !rebuild) { proxies.Add (pfile); continue; }
534                         
535                         CreateFolderForFile     (pfile);
536
537                         Console.Write (prot + " proxy for " + wsdl + "... ");
538                         Process proc = new Process ();
539                         proc.StartInfo.UseShellExecute = false;
540                         proc.StartInfo.RedirectStandardOutput = true;
541                         proc.StartInfo.RedirectStandardError = true;
542                         proc.StartInfo.FileName = "wsdl";
543                         proc.StartInfo.Arguments = "/out:" + pfile + " /nologo /namespace:" + ns + " /protocol:" + prot + " " + wsdl;
544                         proc.Start();
545                         
546                         if (!proc.WaitForExit (30000))
547                         {
548                                 try {
549                                         proc.Kill ();
550                                 } catch {}
551                                 
552                                 Console.WriteLine ("FAIL (timeout)");
553                                 if (File.Exists (pfile)) File.Delete (pfile);
554                                 WriteError (errdoc, ns, "Errors found while generating " + prot + " proxy for WSDL: " + wsdl, "wsdl.exe timeout");
555                         }
556                         else if (proc.ExitCode != 0)
557                         {
558                                 Console.WriteLine ("FAIL " + proc.ExitCode);
559                                 
560                                 string err = proc.StandardOutput.ReadToEnd ();
561                                 err += "\n" + proc.StandardError.ReadToEnd ();
562
563                                 if (File.Exists (pfile))
564                                 {
565                                         if (proc.ExitCode == 1) {
566                                                 string fn = fd.Name + prot + "Proxy.cs";
567                                                 fn = Path.Combine (GetErrorPath(), fn);
568                                                 CreateFolderForFile (fn);
569                                                 File.Move (pfile, fn);
570                                                 
571                                                 StreamWriter sw = new StreamWriter (fn, true);
572                                                 sw.WriteLine ();
573                                                 sw.WriteLine ("// " + fd.Wsdl);
574                                                 sw.WriteLine ();
575                                                 sw.Close ();
576                                                 
577                                         }
578                                         else
579                                                 File.Delete (pfile);
580                                 }
581                                 
582                                 WriteError (errdoc, ns, "Errors found while generating " + prot + " proxy for WSDL: " + wsdl, err);
583                         }
584                         else
585                         {
586                                 if (File.Exists (pfile)) {
587                                         Console.WriteLine ("OK");
588                                         proxies.Add (pfile);
589                                 }
590                                 else {
591                                         Console.WriteLine ("FAIL");
592                                         string err = proc.StandardOutput.ReadToEnd ();
593                                         err += "\n" + proc.StandardError.ReadToEnd ();
594                                         WriteError (errdoc, ns, "Errors found while generating " + prot + " proxy for WSDL: " + wsdl, err);
595                                 }
596                         }
597                 }
598         }
599         
600         static void WriteError (XmlElement err, string ns, string error, string detail)
601         {
602                 XmlElement ele = err.OwnerDocument.CreateElement ("error");
603                 ele.SetAttribute ("ns",ns);
604                 XmlText text = err.OwnerDocument.CreateTextNode (error + "\n" + detail);
605                 ele.AppendChild (text);
606                 err.AppendChild (ele);
607         }
608         
609         static void BuildClients (string wsdl)
610         {
611                 StreamWriter sw = new StreamWriter (Path.Combine (basePath, "client.sources"));
612                 
613                 foreach (ServiceData fd in services.services)
614                 {
615                         if (wsdl != null && fd.Wsdl == wsdl) fd.ClientTest = true;
616                         
617                         if (!fd.ClientTest) continue;
618                         
619                         BuildClient (fd);
620                         sw.WriteLine (GetClientFile (fd));
621                 }
622                 
623                 sw.Close ();
624         }
625         
626         public static void BuildClient (ServiceData sd)
627         {
628                 string file = GetClientFile (sd);
629                 
630                 if (File.Exists (file)) return;
631
632                 CreateFolderForFile (file);
633                 
634                 StreamWriter sw = new StreamWriter (file);
635                 sw.WriteLine ("// Web service test for WSDL document:");
636                 sw.WriteLine ("// " + sd.Wsdl);
637                 
638                 sw.WriteLine ();
639                 sw.WriteLine ("using System;");
640                 sw.WriteLine ("using NUnit.Framework;");
641                 
642                 foreach (string prot in sd.Protocols)
643                         sw.WriteLine ("using " + sd.Namespace + "." + prot + ";");
644                 
645                 sw.WriteLine ();
646                 sw.WriteLine ("namespace " + sd.Namespace);
647                 sw.WriteLine ("{");
648                 sw.WriteLine ("\tpublic class " + sd.Name + ": WebServiceTest");
649                 sw.WriteLine ("\t{");
650                 sw.WriteLine ("\t\t[Test]");
651                 sw.WriteLine ("\t\tpublic void TestService ()");
652                 sw.WriteLine ("\t\t{");
653                 sw.WriteLine ("\t\t}");
654                 sw.WriteLine ("\t}");
655                 sw.WriteLine ("}");
656                 sw.Close ();
657                 
658                 Console.WriteLine ("Written file '" + file + "'");
659         }
660         
661         public static void CheckDiff (string diffFile)
662         {
663                 int suc=0, tot=0, ign=0;
664                 XmlDocument doc = new XmlDocument ();
665                 doc.Load (diffFile);
666                 
667                 XmlDocument errdoc = new XmlDocument ();
668                 errdoc.Load ("proxy-gen-error.xml");
669                 
670                 XmlDocument result = new XmlDocument ();
671                 XmlElement res = result.CreateElement ("test-results");
672                 res.SetAttribute ("name", "wsdl-tests");
673                 res.SetAttribute ("date", DateTime.Now.ToShortDateString ());
674                 res.SetAttribute ("time", DateTime.Now.ToShortTimeString ());
675                 result.AppendChild (res);
676                 
677                 XmlElement ts = result.CreateElement ("test-suite");
678                 ts.SetAttribute ("name", "wsdl");
679                 ts.SetAttribute ("asserts", "0");
680                 ts.SetAttribute ("time", "0");
681                 res.AppendChild (ts);
682
683                 XmlElement tsres = result.CreateElement ("results");
684                 ts.AppendChild (tsres);
685                 
686                 XslTransform xsl = new XslTransform ();
687                 xsl.Load ("cormissing.xsl");
688                 
689                 foreach (ServiceData sd in services.services)
690                 {
691                         if (sd.Protocols == null) continue;
692
693                         foreach (string prot in sd.Protocols)
694                         {
695                                 string ns = sd.Namespace + "." + prot;
696                                 
697                                 XmlElement elem = doc.SelectSingleNode ("assemblies/assembly/namespaces/namespace[@name='" + ns + "']") as XmlElement;
698                                 if (elem == null) {
699                                         ign++;
700                                         continue;
701                                 }
702                                 
703                                 if (!File.Exists (GetWsdlFile(sd))) {
704                                         Console.WriteLine ("WARNING: wsdl file not found: " + GetWsdlFile(sd));
705                                         ign++;
706                                         continue;
707                                 }
708                                 
709                                 tot++;
710
711                                 bool extrans = elem.GetAttribute ("presence") == "extra";
712                                 
713                                 if ((elem.GetAttribute ("error") != "" || elem.GetAttribute ("missing") != "" || elem.GetAttribute ("extra") != "") && !extrans)
714                                 {
715                                         XmlElement errelem = errdoc.SelectSingleNode ("/errors/error[@ns='" + ns + "']") as XmlElement;                 
716                                         if (errelem != null) {
717                                                 WriteResult (tsres, ns, false, sd.Wsdl + "\n" + errelem.InnerText);
718                                         }
719                                         else {
720                                                 StringWriter str = new StringWriter ();
721                                                 xsl.Transform (elem, null, str, null);
722                                                 WriteResult (tsres, ns, false, sd.Wsdl + "\n" + str.ToString ());
723                                         }
724                                 }
725                                 else 
726                                 {
727                                         if (extrans) Console.WriteLine ("BONUS CLASS: " + ns);
728                                         suc++;
729                                         WriteResult (tsres, ns, true, sd.Wsdl);
730                                 }
731                                 
732                         }
733                 }
734                 ts.SetAttribute ("success", (suc < tot).ToString());
735                 
736                 res.SetAttribute ("total", tot.ToString());
737                 res.SetAttribute ("failures", (tot-suc).ToString());
738                 res.SetAttribute ("not-run", "0");
739
740                 result.Save ("WsdlTestResult.xml");
741                 Console.WriteLine ("Compared:" + tot + " Ignored:" + ign + " Sucess:" + suc + " Fail:" + (tot - suc));
742         }
743         
744         static void WriteResult (XmlElement res, string name, bool success, string msg)
745         {
746                 XmlDocument doc = res.OwnerDocument;
747                 XmlElement test = doc.CreateElement ("test-case");
748                 test.SetAttribute ("name", name);
749                 test.SetAttribute ("executed", "True");
750                 test.SetAttribute ("success", success.ToString());
751                 test.SetAttribute ("time", "0");
752                 test.SetAttribute ("asserts", "0");
753                 
754                 if (!success) {
755                         XmlElement fail = doc.CreateElement ("failure");
756                         test.AppendChild (fail);
757                         XmlElement xmsg = doc.CreateElement ("message");
758                         fail.AppendChild (xmsg);
759                         xmsg.AppendChild (doc.CreateCDataSection (msg));
760                         fail.AppendChild (doc.CreateElement ("stack-trace"));
761                 }
762                 res.AppendChild (test);
763         }
764         
765         static void MsFix (string fileName)
766         {
767                 StreamReader sr = new StreamReader ("msfix");
768                 XmlDocument doc = new XmlDocument ();
769                 doc.Load (fileName);
770                 
771                 string line;
772                 while ((line = sr.ReadLine ()) != null)
773                 {
774                         string[] ss = line.Split ('/');
775                         XmlElement elem = doc.SelectSingleNode ("assemblies/assembly/namespaces/namespace[@name='" + ss[0] + "']/classes/class[@name='" + ss[1] + "']") as XmlElement;
776                         if (elem != null) elem.ParentNode.RemoveChild (elem);
777                 }
778                 doc.Save (fileName);
779                 sr.Close ();
780         }
781         
782         static void GenerateFiles (string templateFile)
783         {
784                 XmlDocument doc = new XmlDocument ();
785                 doc.Load (templateFile);
786                 
787                 XmlNodeList targets = doc.SelectNodes ("fileGeneration/targets/target");
788                 XmlElement gvarset = (XmlElement) doc.SelectSingleNode ("fileGeneration/vars[@name='_global']");
789                 
790                 foreach (XmlElement node in targets) {
791                         string tid = node.GetAttribute ("template");
792                         string file = node.GetAttribute ("file");
793                         XmlElement xtemp = (XmlElement) doc.SelectSingleNode ("fileGeneration/templates/template[@id='" + tid + "']");
794                         if (xtemp == null) throw new Exception ("Template " + tid + " not found");
795                         string tempFile = xtemp.GetAttribute ("file");
796                         
797                         StreamReader sr = new StreamReader (tempFile);
798                         string template = sr.ReadToEnd ();
799                         sr.Close ();
800                         
801                         string content = ReplaceVars (template, node);
802                         content = ReplaceVars (content, gvarset);
803                         
804                         StreamWriter sw = new StreamWriter (file);
805                         sw.Write (content);
806                         sw.Close ();
807                         Console.WriteLine ("Writen " + file);
808                 }
809         }
810         
811         static string ReplaceVars (string content, XmlElement root)
812         {
813                 XmlNodeList nodes = root.SelectNodes ("var");
814                 foreach (XmlElement elem in nodes) {
815                         string include = elem.GetAttribute ("include");
816                         if (include != "") {
817                                 XmlElement varset = (XmlElement) root.OwnerDocument.SelectSingleNode ("fileGeneration/vars[@name='" + include + "']");
818                                 if (varset == null) throw new Exception ("varset '" + include + "' not found");
819                                 content = ReplaceVars (content, varset);
820                         }
821                         else {
822                                 content = content.Replace ("$" + elem.GetAttribute ("name") + "$", elem.InnerText);
823                         }
824                 }
825                 
826                 return content;
827         }
828         
829         static void RegisterFailure (ServiceData sd)
830         {
831                 ServiceStatus status = null;
832                 foreach (ServiceStatus ss in serviceStatus.services)
833                 {
834                         if (ss.Name == sd.Name)
835                         {
836                                 status = ss;
837                                 break;
838                         }
839                 }
840                 
841                 if (status == null)
842                 {
843                         status = new ServiceStatus ();
844                         status.Name = sd.Name;
845                         status.Retries = 1;
846                         status.LastTestDate = DateTime.Now;
847                         serviceStatus.services.Add (status);
848                 }
849                 else
850                 {
851                         if ((DateTime.Now - status.LastTestDate).TotalHours >= 24)
852                                 status.Retries++;
853                 }
854         }
855
856         static void CleanFailures (ServiceData sd)
857         {
858                 ServiceStatus status = null;
859                 foreach (ServiceStatus ss in serviceStatus.services)
860                 {
861                         if (ss.Name == sd.Name)
862                         {
863                                 serviceStatus.services.Remove (ss);
864                                 break;
865                         }
866                 }
867         }
868         
869         static string GetProxyFile (ServiceData fd, string protocol)
870         {
871                 string fn = Path.Combine (new Uri (fd.Wsdl).Host, fd.Name + protocol + "Proxy.cs");
872                 return Path.Combine (GetProxyPath(), fn);
873         }
874         
875         static string GetClientFile (ServiceData sd)
876         {
877                 return Path.Combine (GetClientPath(), sd.TestFile);
878         }
879         
880         static string GetWsdlFile (ServiceData fd)
881         {
882                 string fn = Path.Combine (new Uri (fd.Wsdl).Host, fd.Name + ".wsdl");
883                 return Path.Combine (GetWsdlPath(), fn);
884         }
885         
886         static void ReportError (string error, string detail)
887         {
888                 string fn = Path.Combine (GetErrorPath(), "error.log");
889                 CreateFolderForFile (fn);
890
891                 StreamWriter sw = new StreamWriter (fn, true);
892                 sw.WriteLine ("*** " + error);
893                 sw.WriteLine ("   " + detail.Replace ("\n","\n   "));
894                 sw.WriteLine ();
895                 sw.Close ();
896                 foundErrors = true;
897         }
898         
899         static string GetProxyPath ()
900         {
901                 return Path.Combine (basePath, "proxies");
902         }
903         
904         static string GetClientPath ()
905         {
906                 return Path.Combine (basePath, "client");
907         }
908         
909         static string GetErrorPath ()
910         {
911                 return Path.Combine (basePath, "error");
912         }
913         
914         static string GetWsdlPath ()
915         {
916                 return Path.Combine (basePath, "wsdlcache");
917         }
918         
919         static string GetTempWsdlPath ()
920         {
921                 return Path.Combine (basePath, "wsdlcache");
922         }
923         
924         static void CreateFolderForFile (string file)
925         {
926                 string dir = Path.GetDirectoryName (file);
927                 DirectoryInfo di = new DirectoryInfo (dir);
928                 if (!di.Exists) di.Create ();
929         }
930 }
931
932 [XmlType("services")]
933 public class ServiceCollection
934 {
935         [XmlElement("service", typeof(ServiceData))]
936         public ArrayList services = new ArrayList ();
937 }
938
939 [XmlType("service")]
940 public class ServiceData
941 {
942         [XmlElement("wsdl")]
943         public string Wsdl;
944         
945         [XmlElement("name")]
946         public string Name;
947         
948         [XmlElement("serverType")]
949         public string ServerType;
950         
951         [XmlArray("protocols")]
952         [XmlArrayItem("protocol")]
953         public string[] Protocols;
954         
955         [XmlElement("clientTest")]
956         public bool ClientTest;
957         
958         [XmlIgnore]
959         public string Namespace
960         {
961                 get { return Name + "s"; }
962         }
963         
964         [XmlIgnore]
965         public string TestFile
966         {
967                 get 
968                 { 
969                         string dir = new Uri (Wsdl).Host;
970                         if (dir != "localhost") dir = "external";
971                         return Path.Combine (dir, Name + ".cs");
972                 }
973         }
974 }
975
976 [XmlType("serviceStatus")]
977 public class ServiceStatusCollection
978 {
979         [XmlElement("service", typeof(ServiceStatus))]
980         public ArrayList services = new ArrayList ();
981 }
982
983 public class ServiceStatus
984 {
985         [XmlElement("name")]
986         public string Name;
987         
988         [XmlElement("lastTestDate")]
989         public DateTime LastTestDate;
990         
991         [XmlElement("retries")]
992         public int Retries;
993 }
994