Output the list of failed tests
[mono.git] / mcs / class / System.XML / Test / System.Xml.Xsl / standalone_tests / xslttest.cs
1 using System;
2 using System.Collections;
3 using System.IO;
4 using System.Text;
5 using System.Xml;
6 using System.Xml.XPath;
7 using System.Xml.Xsl;
8
9 namespace XsltTest
10 {
11         public class XsltTest
12         {
13 #region static Vars
14                 static bool noExclude;
15                 static bool reportDetails;
16                 static bool reportAsXml;
17                 static bool useDomStyle;
18                 static bool useDomInstance;
19                 static bool generateOutput;
20                 static bool listOutput;
21                 static bool whitespaceStyle;
22                 static bool whitespaceInstance;
23                 static bool stopImmediately;
24                 static bool outputAll;
25                 static readonly ArrayList skipTargets;
26                 static readonly ArrayList knownFailures = new ArrayList (new string [] { });
27                 static string explicitTarget;
28                 static TextWriter reportOutput = Console.Out;
29                 static XmlTextWriter reportXmlWriter;
30                 static StreamWriter missingFiles = new StreamWriter ("missing.lst");
31                 static StreamWriter failedTests = new StreamWriter ("failed.lst");
32 #endregion
33
34                 static XsltTest ()
35                 {
36                         skipTargets = new ArrayList (new string [] {
37                         }); 
38                 }
39                 
40                 static void Usage ()
41                 {
42                         Console.WriteLine (@"
43 mono xslttest.exe [options] [targetFileMatch] -report:reportfile
44
45 Options:
46         --details       Output detailed output differences.
47         --dom           Use XmlDocument for both stylesheet and input source.
48         --domxsl        Use XmlDocument for stylesheet.
49         --domsrc        Use XmlDocument for input source.
50         --generate      Generate output files specified in catalog.
51                         Use this feature only when you want to update
52                         reference output.
53         --list          Print output list to console.
54         --noExclude     Don't exclude meaningless comparison testcases.
55         --outall        Output fine results as OK (omitted by default).
56         --stoponerror   Stops the test process and throw detailed
57                         error if happened.
58         --ws            Preserve spaces for both stylesheet and input source.
59         --wsxsl         Preserve spaces for stylesheet.
60         --wssrc         Preserve spaces for input source.
61         --xml           Report into xml output.
62         --report        Write reports into specified file.
63
64 FileMatch:
65         arbitrary string that specifies part of file name.
66         (no * or ? available)
67 ");
68                 }
69
70                 public static void Main (string [] args)
71                 {
72                         try {
73                                 RunMain (args);
74                         } catch (Exception ex) {
75                                 reportOutput.WriteLine (ex);
76                         } finally {
77                                 reportOutput.Close ();
78                         }
79                 }
80
81                 static void ParseOptions (string [] args)
82                 {
83                         foreach (string arg in args) {
84                                 switch (arg) {
85                                 case "-?":
86                                         Usage ();
87                                         return;
88                                 case "--dom":
89                                         useDomStyle = true;
90                                         useDomInstance = true;
91                                         break;
92                                 case "--domxsl":
93                                         useDomStyle = true;
94                                         break;
95                                 case "--domsrc":
96                                         useDomInstance = true;
97                                         break;
98                                 case "--details":
99                                         reportDetails = true;
100                                         break;
101                                 case "--generate":
102                                         generateOutput = true;
103                                         break;
104                                 case "--list":
105                                         listOutput = true;
106                                         break;
107                                 case "--noExclude":
108                                         noExclude = true;
109                                         break;
110                                 case "--outall":
111                                         outputAll = true;
112                                         break;
113                                 case "--stoponerror":
114                                         stopImmediately = true;
115                                         break;
116                                 case "--ws":
117                                         whitespaceStyle = true;
118                                         whitespaceInstance = true;
119                                         break;
120                                 case "--wsxsl":
121                                         whitespaceStyle = true;
122                                         break;
123                                 case "--wssrc":
124                                         whitespaceInstance = true;
125                                         break;
126                                 case "--xml":
127                                         reportAsXml = true;
128                                         break;
129                                 default:
130                                         if (arg.StartsWith ("--report:")) {
131                                                 string reportFile = arg.Substring (9);
132                                                 if (reportFile.Length < 0) {
133                                                         Usage ();
134                                                         Console.WriteLine ("Error: --report option requires filename.");
135                                                         return;
136                                                 }
137                                                 reportOutput = new StreamWriter (reportFile);
138                                                 break;
139                                         }
140                                         if (arg.StartsWith ("--")) {
141                                                 Usage ();
142                                                 return;
143                                         }
144                                         explicitTarget = arg;
145                                         break;
146                                 }
147                         }
148                 }
149                         
150                 static void RunMain (string [] args)
151                 {
152                         ParseOptions (args);
153                         if (!noExclude) {
154                                 foreach (string s_ in new StreamReader ("ignore.lst").ReadToEnd ()
155                                                 .Split ("\n".ToCharArray ())) {
156                                         string s = s_.Trim ();
157                                         if (s.Length > 0)
158                                                 skipTargets.Add (s);
159                                 }
160                         }
161
162                         if (reportAsXml) {
163                                 reportXmlWriter = new XmlTextWriter (reportOutput);
164                                 reportXmlWriter.Formatting = Formatting.Indented;
165                                 reportXmlWriter.WriteStartElement ("test-results");
166                         }
167
168                         if (explicitTarget != null)
169                                 Console.WriteLine ("The specified target is "
170                                         + explicitTarget);
171
172                         XmlDocument whole = new XmlDocument ();
173                         whole.Load (@"testsuite/TESTS/catalog-fixed.xml");
174
175                         if (!listOutput)
176                                 Console.Error.WriteLine ("Started: " 
177                                                 + DateTime.Now.ToString ("yyyyMMdd-HHmmss.fff"));
178
179                         foreach (XmlElement testCase in whole.SelectNodes ("test-suite/test-catalog/test-case"))
180                                 ProcessTestCase (testCase);
181
182                         if (!listOutput)
183                                 Console.WriteLine ("Finished: " 
184                                                 + DateTime.Now.ToString ("yyyyMMdd-HHmmss.fff"));
185
186                         if (reportAsXml)
187                                 reportXmlWriter.WriteEndElement (); // test-results
188                 }
189                 
190                 static void ProcessTestCase (XmlElement testCase)
191                 {
192                         string stylesheetBase = null;
193                         string testid = testCase.GetAttribute ("id");
194                         if (skipTargets.Contains (testid))
195                                 return;
196                         try {
197                                 string submitter = testCase.SelectSingleNode ("./parent::test-catalog/@submitter")
198                                         .InnerText;
199                                 string filePath = testCase.SelectSingleNode ("file-path").InnerText;
200                                 string testAuthorDir;
201                                 if (submitter == "Lotus")
202                                         testAuthorDir =  "Xalan_Conformance_Tests";
203                                 else if (submitter == "Microsoft")
204                                         testAuthorDir =  "MSFT_Conformance_Tests";
205                                 else
206                                         return; //unknown directory
207
208                                 string path = @"testsuite/TESTS/" + testAuthorDir + "/" + filePath + "/";
209                                 foreach (XmlElement scenario in 
210                                                 testCase.SelectNodes ("scenario[@operation='standard']")) {
211                                         RunTest (testid, scenario, path, stylesheetBase);
212                                 }
213                         } catch (Exception ex) {
214                                 if (stopImmediately)
215                                         throw;
216                                 Report (false, testid, "Exception: " + ex.Message);
217                         }
218                 }
219
220                 static void RunTest (string testid, XmlElement scenario, string path, string stylesheetBase)
221                 {
222                         stylesheetBase = scenario.SelectSingleNode ("input-file[@role='principal-stylesheet']").InnerText;
223                         string stylesheet = path + stylesheetBase;
224                         
225                         if (!File.Exists (stylesheet)) {
226                                 missingFiles.WriteLine (stylesheet);
227                                 missingFiles.Flush ();
228                         }
229                         string srcxml = path + scenario.SelectSingleNode ("input-file[@role='principal-data']").InnerText;
230                         XmlNode outputNode = scenario.SelectSingleNode ("output-file[@role='principal']");
231                         string outfile = outputNode != null ? path + outputNode.InnerText : null;
232
233                         if (listOutput) {
234                                 if (outfile != null)
235                                         Console.WriteLine (outfile);
236                                 return;
237                         }
238
239                         XslTransform trans = new XslTransform ();
240
241                         if (explicitTarget != null && testid.IndexOf (explicitTarget) < 0)
242                                 return;
243                         if (skipTargets.Contains (stylesheetBase))
244                                 return;
245
246                         if (useDomStyle) {
247                                 XmlDocument styledoc = new XmlDocument ();
248                                 if (whitespaceStyle)
249                                         styledoc.PreserveWhitespace = true;
250                                 styledoc.Load (stylesheet);
251                                 trans.Load (styledoc, null, null);
252                         } else
253                                 trans.Load (new XPathDocument (
254                                                         stylesheet,
255                                                         whitespaceStyle ? XmlSpace.Preserve :
256                                                         XmlSpace.Default),
257                                                 null, null);
258
259                         XmlTextReader xtr = new XmlTextReader (srcxml);
260                         XmlValidatingReader xvr = new XmlValidatingReader (xtr);
261                         xvr.ValidationType = ValidationType.None;
262                         IXPathNavigable input = null;
263                         if (useDomInstance) {
264                                 XmlDocument dom = new XmlDocument ();
265                                 if (whitespaceInstance)
266                                         dom.PreserveWhitespace = true;
267                                 dom.Load (xvr);
268                                 input = dom;
269                         } else {
270                                 input = new XPathDocument (xvr,
271                                         whitespaceStyle ? XmlSpace.Preserve :
272                                         XmlSpace.Default);
273                         }
274                         StringWriter sw = new StringWriter ();
275                         trans.Transform (input, null, sw, null);
276                         if (generateOutput) {
277                                 StreamWriter fw = new StreamWriter (outfile,
278                                         false, Encoding.UTF8);
279                                 fw.Write (sw.ToString ());
280                                 fw.Close ();
281                                 // ... and don't run comparison
282                                 return;
283                         }
284
285                         if (!File.Exists (outfile)) {
286                                 // Reference output file does not exist.
287                                 Report (true, testid, "No reference file found");
288                                 return;
289                         }
290                         StreamReader sr = new StreamReader (outfile);
291                         string reference_out = sr.ReadToEnd ();
292                         string actual_out = sw.ToString ();
293                         if (reference_out != actual_out)
294                                 Report (false, testid, reference_out, actual_out);
295                         else if (outputAll)
296                                 Report (true, testid, "OK");
297                 }
298
299                 static void Report (bool passed, string testid, string message)
300                 {
301                         if (passed) {
302                                 Console.Error.Write (".");
303                                 return;
304                         }
305                         failedTests.WriteLine (testid + "\t" + message);
306                         failedTests.Flush ();
307                         if (reportAsXml) {
308                                 reportXmlWriter.WriteStartElement ("testcase");
309                                 reportXmlWriter.WriteAttributeString ("id", testid);
310                                 reportXmlWriter.WriteString (message);
311                                 reportXmlWriter.WriteEndElement ();
312                                 if (knownFailures.Contains (testid))
313                                         Console.Error.Write ("k");
314                                 else
315                                         Console.Error.Write ("E");
316                         }
317                         else
318                                 reportOutput.WriteLine (message);
319                 }
320
321                 static void Report (bool passed, string testid, string reference_out, string actual_out)
322                 {
323                         string baseMessage = reportAsXml ? "Different." : "Different: " + testid;
324                         if (!reportDetails)
325                                 Report (passed, testid, baseMessage);
326                         else
327                                 Report (passed, testid, baseMessage +
328                                         "\n Actual*****\n" + 
329                                         actual_out + 
330                                         "\n-------------------\nReference*****\n" + 
331                                         reference_out + 
332                                         "\n");
333                 }
334         }
335 }