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