Project

Profile

Help

How to connect?
Download (28.1 KB) Statistics
| Branch: | Revision:

he / src / samples / cs / TestRunner10.0 / XQueryTestSuiteDriver.cs @ be17ef52

1
using System;
2
using System.IO;
3
using System.Collections;
4
using System.Xml;
5
using System.Text;
6
using Saxon.Api;
7
using TestRunner;
8
using System.Collections.Generic;
9

    
10
/// <summary>
11
/// Test suite driver for running the XQTS test suite against Saxon on .NET.
12
/// </summary>
13
/// <remarks>
14
/// <paraThe test suite directory must contain a subdirectory named SaxonDriver.
15
/// In this subdirectory there must be a document named exceptions.xml, containing</para>
16
/// <example><![CDATA[
17
/// <exceptions>
18
///   <exception>
19
///     <tests>trivial-1 trivial-2 trivial-3 trivial-4</tests>
20
///     <description>No support in Saxon for trivial embedding feature</description>
21
///   </exception>
22
/// </exceptions>
23
/// ]]></example>
24
/// <para>The SaxonDriver directory should also have a subdirectory named <c>results</c>,
25
/// with the same structure as the supplied <c>expectedResults</c> directory.</para>
26
/// <para>Note that the submitted results for Saxon were obtained with the Java product;
27
/// this driver will produce different results. <b>At present this test driver is
28
/// reporting many spurious test failures where the results are in fact correct.</b></para>
29
/// </remarks>
30

    
31

    
32
public class XQueryTestSuiteDriver
33
{
34
    static void Mainxxxxx(string[] args)
35
    {
36
        if (args.Length == 0 || args[0].Equals("-?"))
37
        {
38
            Console.WriteLine("XQueryTestSuiteDriver testsuiteDir resultsDir testName?");
39
        }
40
        try
41
        {
42
            new XQueryTestSuiteDriver().go(args);
43
        }
44
        catch (Exception e)
45
        {
46
            Console.WriteLine(e.Message);
47
            Console.WriteLine(e.StackTrace);
48
        }
49
    }
50

    
51
    String testURI = "http://www.w3.org/2005/02/query-test-XQTSCatalog";
52
    String testSuiteDir;
53
    String saxonResultsDir;
54
    Processor processor = new Processor(true, true);  // processor is schema-aware
55
    
56
    // TODO: change to (true, false) when not debugging
57

    
58
    FileComparer fileComparer;
59
    IFeedbackListener feedback;
60
    int passed = 0;
61
    int failed = 0;
62
    int total = 0;
63

    
64
    XPathExecutable findSourcePath;
65
    XPathExecutable findCollection;
66
    XPathExecutable findModule;
67

    
68

    
69
    string testPattern = null;
70
    
71
    StreamWriter results;
72
    StreamWriter log;
73

    
74

    
75
    private XdmNode getChildElement(XdmNode parent, QName child)
76
    {
77
        IEnumerator e = parent.EnumerateAxis(XdmAxis.Child, child);
78
        return e.MoveNext() ? (XdmNode)e.Current : null;
79
    }
80

    
81
    public void setFeedbackListener(IFeedbackListener f)
82
    {
83
        feedback = f;
84
    }
85

    
86

    
87
    public void go(String[] args)
88
    {
89

    
90
        
91
        processor.SetProperty("http://saxon.sf.net/feature/trace-external-functions", "true");
92
        testSuiteDir = args[0];
93
        if (testSuiteDir.EndsWith("/"))
94
        {
95
            testSuiteDir = testSuiteDir.Substring(0, testSuiteDir.Length - 1);
96
        }
97
        saxonResultsDir = args[1];
98
        if (saxonResultsDir.EndsWith("/"))
99
        {
100
            saxonResultsDir = saxonResultsDir.Substring(0, testSuiteDir.Length - 1);
101
        }
102
        Hashtable exceptions = new Hashtable();
103

    
104
        if (args.Length > 1)
105
        {
106
            testPattern = (args[2]); // TODO: allow a regex
107
        }
108

    
109
        for (int i = 0; i < args.Length; i++)
110
        {
111
            if (args[i].Equals("-w"))
112
            {
113
                //showWarnings = true;
114
            }
115
            
116
        }
117

    
118
        fileComparer = new FileComparer(processor, testSuiteDir);
119

    
120
        XPathCompiler xpc = processor.NewXPathCompiler();
121
        xpc.DeclareNamespace("t", testURI);
122
        xpc.DeclareVariable(new QName("", "param"));
123
        findSourcePath = xpc.Compile("//t:test-suite/t:sources/t:source[@ID=$param]");
124

    
125
        findCollection = xpc.Compile("//t:test-suite/t:sources/t:collection[@ID=$param]");
126

    
127
        xpc = processor.NewXPathCompiler();
128
        xpc.DeclareNamespace("t", testURI);
129
        xpc.DeclareVariable(new QName("", "testcase"));
130
        xpc.DeclareVariable(new QName("", "moduleuri"));
131
        findModule = xpc.Compile("for $m in $testcase/t:module[@namespace=$moduleuri] " +
132
            "return concat('file:///" + testSuiteDir +
133
            "/', root($testcase)/t:test-suite/t:sources/t:module[@ID=string($m)]/@FileName, '.xq')");
134

    
135
        //xpc = processor.NewXPathCompiler();
136
        //xpc.DeclareNamespace("saxon", "http://saxon.sf.net/");
137
        //xpc.DeclareVariable(new QName("", "actual"));
138
        //xpc.DeclareVariable(new QName("", "gold"));
139
        //xpc.DeclareVariable(new QName("", "debug"));
140
        //compareDocuments = xpc.Compile("saxon:deep-equal($actual, $gold, (), if ($debug) then 'JNCPS?!' else 'JNCPS')");
141

    
142
        QName testCaseNT = new QName(testURI, "test-case");
143
        QName nameNT = new QName(testURI, "name");
144
        QName queryNT = new QName(testURI, "query");
145
        QName inputNT = new QName(testURI, "input");
146
        QName inputFileNT = new QName(testURI, "input-file");
147
        QName inputUriNT = new QName(testURI, "input-URI");
148
        QName defaultCollectionNT = new QName(testURI, "defaultCollection");
149
        QName outputFileNT = new QName(testURI, "output-file");
150
        QName expectedErrorNT = new QName(testURI, "expected-error");
151
        QName schemaNT = new QName(testURI, "schema");
152
        QName contextItemNT = new QName(testURI, "contextItem");
153
        QName inputQueryNT = new QName(testURI, "input-query");
154
        QName sourceDocumentNT = new QName(testURI, "source-document");
155
        QName errorNT = new QName(testURI, "error");
156
        QName validationNT = new QName(testURI, "validation");
157
        QName discretionaryItemsNT = new QName(testURI, "discretionary-items");
158
        QName discretionaryFeatureNT = new QName(testURI, "discretionary-feature");
159
        QName discretionaryChoiceNT = new QName(testURI, "discretionary-choice");
160
        QName initialContextNodeNT = new QName(testURI, "initial-context-node");
161

    
162

    
163
        QName fileAtt = new QName("", "file");
164
        QName filePathAtt = new QName("", "FilePath");
165
        QName fileNameAtt = new QName("", "FileName");
166
        QName errorIdAtt = new QName("", "error-id");
167
        QName compareAtt = new QName("", "compare");
168
        QName nameAtt = new QName("", "name");
169
        QName behaviorAtt = new QName("", "behavior");
170
        QName qnameAtt = new QName("", "qname");
171
        QName modeAtt = new QName("", "mode");
172
        QName validatesAtt = new QName("", "validates");
173
        QName variableAtt = new QName("", "variable");
174
        QName roleAtt = new QName("", "role");
175

    
176
        DocumentBuilder builder = processor.NewDocumentBuilder();
177
        XdmNode exceptionsDoc = builder.Build(new Uri(saxonResultsDir + "/exceptions.xml"));
178

    
179
        // The exceptions.xml file contains details of tests that aren't to be run, for example
180
        // because they have known bugs or require special configuration
181

    
182
        IEnumerator exceptionTestCases = exceptionsDoc.EnumerateAxis(XdmAxis.Descendant, new QName("", "exception"));
183
        while (exceptionTestCases.MoveNext())
184
        {
185
            XdmNode n = (XdmNode)exceptionTestCases.Current;
186
            String nameAttVal = n.StringValue;
187
            char[] seps = { ' ', '\n', '\t' };
188
            String[] parts = nameAttVal.Split(seps);
189
            foreach (string p in parts)
190
            {
191
                if (!exceptions.ContainsKey(p))
192
                {
193
                    exceptions.Add(p, "Exception");
194
                }
195
            }
196
        }
197

    
198
        // Hash table containing all source documents. The key is the document name in the
199
        // catalog, the value is the corresponding document node
200

    
201
        Hashtable sourceDocs = new Hashtable(50);
202

    
203
        // Load the catalog
204

    
205
        XdmNode catalog = builder.Build(new Uri(testSuiteDir + "/XQTScatalog.xml"));
206

    
207
        // Add all Static Typing test cases to the exceptions list
208

    
209
        xpc = processor.NewXPathCompiler();
210
        xpc.DeclareNamespace("t", testURI);
211
        XPathSelector st = xpc.Compile("//t:test-group[@name='StaticTyping']//t:test-case").Load();
212
        st.ContextItem = catalog;
213
        IEnumerator ste = st.GetEnumerator();
214
        while (ste.MoveNext())
215
        {
216
            XdmNode testCase = (XdmNode)ste.Current;
217
            exceptions.Add(testCase.GetAttributeValue(nameAtt), "StaticTypingException");
218
        }
219

    
220
        // Create the results file and log file
221

    
222
        results = new StreamWriter(saxonResultsDir + "/results"
223
                    + processor.ProductVersion + "n.xml");
224
        log = new StreamWriter(saxonResultsDir + "/log"
225
                    + processor.ProductVersion + "n.xml");
226
        
227
        log.WriteLine("Testing Saxon " + processor.ProductVersion);
228
        results.WriteLine("<test-suite-result xmlns='http://www.w3.org/2005/02/query-test-XQTSResult'>");
229

    
230
        // Pre-load all the schemas
231

    
232
        SchemaManager mgr = processor.SchemaManager;
233
        IEnumerator se = catalog.EnumerateAxis(XdmAxis.Descendant, schemaNT);
234
        while (se.MoveNext())
235
        {
236
            XdmNode schemaNode = (XdmNode)se.Current;
237
            log.WriteLine("Loading schema " + schemaNode.GetAttributeValue(fileNameAtt));
238
            Uri location = new Uri(testSuiteDir + "/" + schemaNode.GetAttributeValue(fileNameAtt));
239
            mgr.Compile(location);
240
        }
241

    
242
        total = 0;
243
        IEnumerator testCases = catalog.EnumerateAxis(XdmAxis.Descendant, testCaseNT);
244
        while (testCases.MoveNext()) {
245
            total++;
246
        }
247

    
248
        // Process the test cases in turn
249

    
250
        testCases = catalog.EnumerateAxis(XdmAxis.Descendant, testCaseNT);
251
        while (testCases.MoveNext())
252
        {
253
            XdmNode testCase = (XdmNode)testCases.Current;
254

    
255
            String testName = testCase.GetAttributeValue(nameAtt);
256
            if (testPattern != null && !testName.StartsWith(testPattern))
257
            {
258
                continue;
259
            }
260
            if (exceptions.ContainsKey(testName))
261
            {
262
                continue;
263
            }
264

    
265
            log.WriteLine("Test " + testName);
266

    
267

    
268
            // Compile the query
269

    
270
            String errorCode = null;
271

    
272
            String filePath = testCase.GetAttributeValue(filePathAtt);
273
            XdmNode query = getChildElement(testCase, queryNT);
274
            String queryName = query.GetAttributeValue(nameAtt);
275
            String queryPath = testSuiteDir + "/Queries/XQuery/" + filePath + queryName + ".xq";
276

    
277
            XQueryCompiler compiler = processor.NewXQueryCompiler();
278
            compiler.BaseUri = new Uri(queryPath).ToString();
279
            compiler.QueryResolver = new XqtsModuleResolver(testCase, findModule);
280
            compiler.SchemaAware = true;
281
            // Set all queries to schema-aware, because we don't really know whether they will have to handle typed input or not.
282

    
283
            IList<StaticError> errors = new List<StaticError>();
284
            compiler.ErrorList = errors;
285
            XQueryEvaluator xqe = null;
286
            FileStream stream = null;
287
            try
288
            {
289
                stream = new FileStream(queryPath, FileMode.Open, FileAccess.Read, FileShare.Read);
290
                xqe = compiler.Compile(stream).Load();
291
            }
292
            catch (Exception e)
293
            {
294
                if (errors.Count > 0 && ((StaticError)errors[0]).ErrorCode != null)
295
                {
296
                    errorCode = ((StaticError)errors[0]).ErrorCode.LocalName;
297
                }
298
                else if (e is StaticError && ((StaticError)e).ErrorCode != null)
299
                {
300
                    log.WriteLine(e.Message);
301
                    errorCode = ((StaticError)e).ErrorCode.LocalName;
302
                }
303
                else
304
                {
305
                    log.WriteLine(e.Message);
306
                    errorCode = "ErrorXXX";
307
                }
308
            }
309
            finally
310
            {
311
                if (stream != null)
312
                {
313
                    stream.Close();
314
                }
315
            }
316

    
317
            // if the query compiled successfully, try to run it
318

    
319
            String outputPath = null;
320
            if (errorCode == null && xqe != null)
321
            {
322

    
323
                // Supply any input documents
324

    
325
                IEnumerator en = testCase.EnumerateAxis(XdmAxis.Child, inputFileNT);
326
                while (en.MoveNext())
327
                {
328
                    XdmNode file = (XdmNode)en.Current;
329
                    String var = file.GetAttributeValue(variableAtt);
330
                    if (var != null)
331
                    {
332
                        String sourceName = file.StringValue;
333
                        XdmNode sourceDoc;
334
                        if (sourceDocs.ContainsKey(sourceName))
335
                        {
336
                            sourceDoc = (XdmNode)sourceDocs[sourceName];
337
                        }
338
                        else
339
                        {
340
                            sourceDoc = buildSource(catalog, builder, sourceName);
341
                            sourceDocs.Add(sourceName, sourceDoc);
342
                        }
343
                        xqe.SetExternalVariable(new QName("", var), sourceDoc);
344
                    }
345
                }
346

    
347
                // Supply any input URIs
348

    
349
                IEnumerator eu = testCase.EnumerateAxis(XdmAxis.Child, inputUriNT);
350
                while (eu.MoveNext())
351
                {
352
                    XdmNode file = (XdmNode)eu.Current;
353
                    String var = file.GetAttributeValue(variableAtt);
354
                    if (var != null)
355
                    {
356
                        String sourceName = file.StringValue;
357
                        if (sourceName.StartsWith("collection"))
358
                        {
359
                            // Supply a collection URI. 
360
                            // This seems to be the only way to distinguish a document URI 
361
                            // from a collection URI.
362
                            String uri = "collection:" + sourceName;
363
                            XPathSelector xpe = findCollection.Load();
364
                            xpe.SetVariable(new QName("", "param"), new XdmAtomicValue(sourceName));
365
                            xpe.ContextItem = catalog;
366
                            XdmNode collectionNode = (XdmNode)xpe.EvaluateSingle();
367
                            if (collectionNode == null)
368
                            {
369
                                log.WriteLine("*** Collection " + sourceName + " not found");
370
                            }
371
                            processor.RegisterCollection(new Uri(uri), getCollection(collectionNode));
372
                            xqe.SetExternalVariable(new QName("", var), new XdmAtomicValue(uri));
373
                        }
374
                        else
375
                        {
376
                            // Supply a document URI.
377
                            // We exploit the fact that the short name of the document is
378
                            // always the same as the file name in these tests. With one exception!
379
                            if (sourceName == "Char010D")
380
                            {
381
                                sourceName = "0x010D";
382
                            }
383
                            String uri = "file:///" + testSuiteDir + "/TestSources/" + sourceName + ".xml";
384
                            xqe.SetExternalVariable(new QName("", var), new XdmAtomicValue(uri));
385
                        }
386
                    }
387
                }
388

    
389
                // Supply the default collection if required
390

    
391
                XdmNode defaultCollection = getChildElement(testCase, defaultCollectionNT);
392
                if (defaultCollection != null)
393
                {
394
                    String sourceName = defaultCollection.StringValue;
395
                    XPathSelector xpe = findCollection.Load();
396
                    xpe.SetVariable(new QName("", "param"), new XdmAtomicValue(sourceName));
397
                    xpe.ContextItem = catalog;
398
                    XdmNode collectionNode = (XdmNode)xpe.EvaluateSingle();
399
                    if (collectionNode == null)
400
                    {
401
                        log.WriteLine("*** Collection " + sourceName + " not found");
402
                    }
403
                    processor.RegisterCollection(null, getCollection(collectionNode));
404
                }
405

    
406
                // Supply any external variables defined as the result of a separate query
407

    
408
                IEnumerator ev = testCase.EnumerateAxis(XdmAxis.Child, inputQueryNT);
409
                while (ev.MoveNext())
410
                {
411
                    XdmNode inputQuery = (XdmNode)ev.Current;
412

    
413
                    String fileName = inputQuery.GetAttributeValue(nameAtt);
414
                    String subQueryPath = testSuiteDir + "/Queries/XQuery/" + filePath + fileName + ".xq";
415
                    XQueryCompiler subCompiler = processor.NewXQueryCompiler();
416
                    compiler.BaseUri = new Uri(subQueryPath).ToString();
417
                    FileStream subStream = new FileStream(subQueryPath, FileMode.Open, FileAccess.Read, FileShare.Read);
418
                    XdmValue value = subCompiler.Compile(subStream).Load().Evaluate();
419
                    String var = inputQuery.GetAttributeValue(variableAtt);
420
                    xqe.SetExternalVariable(new QName("", var), value);
421
                }
422

    
423
                // Supply the context item if required
424

    
425
                IEnumerator ci = testCase.EnumerateAxis(XdmAxis.Child, contextItemNT);
426
                while (ci.MoveNext())
427
                {
428
                    XdmNode file = (XdmNode)ci.Current;
429

    
430
                    String sourceName = file.StringValue;
431
                    if (!sourceDocs.ContainsKey(sourceName))
432
                    {
433
                        XdmNode doc = buildSource(catalog, builder, sourceName);
434
                        sourceDocs.Add(sourceName, doc);
435
                    }
436
                    XdmNode sourceDoc = (XdmNode)sourceDocs[sourceName];
437
                    xqe.ContextItem = sourceDoc;
438
                }
439

    
440
                // Create a serializer for the output
441

    
442

    
443
                outputPath = saxonResultsDir + "/results.net/" + filePath + queryName + ".out";
444
                Serializer sr = processor.NewSerializer();
445
                try
446
                {
447
                    sr.SetOutputFile(outputPath);
448
                    sr.SetOutputProperty(new QName("", "method"), "xml");
449
                    sr.SetOutputProperty(new QName("", "omit-xml-declaration"), "yes");
450
                    sr.SetOutputProperty(new QName("", "indent"), "no");
451
                }
452
                catch (DynamicError)
453
                {
454
                    // probably means that no output directory exists, which is probably because
455
                    // an error is expected
456
                    outputPath = saxonResultsDir + "/results.net/" + filePath + queryName + ".out";
457
                    sr.SetOutputFile(outputPath);
458
                }
459

    
460
                // Finally, run the query
461

    
462
                try
463
                {
464
                    xqe.Run(sr);
465
                }
466
                catch (DynamicError e)
467
                {
468
                    log.WriteLine(e.Message);
469
                    QName code = e.ErrorCode;
470
                    if (code != null && code.LocalName != null)
471
                    {
472
                        errorCode = code.LocalName;
473
                    }
474
                    else
475
                    {
476
                        errorCode = "ErrYYYYY";
477
                    }
478
                }
479
                catch (Exception e2)
480
                {
481
                    log.WriteLine("Unexpected exception: " + e2.Message);
482
                    log.WriteLine(e2.StackTrace);
483
                    errorCode = "CRASH!!!";
484
                }
485
            }
486

    
487
            // Compare actual results with expected results
488

    
489
            if (errorCode != null)
490
            {
491
                // query returned an error at compile time or run-time, check this was expected
492

    
493
                string expectedError = "";
494
                bool matched = false;
495
                IEnumerator en = testCase.EnumerateAxis(XdmAxis.Child, expectedErrorNT);
496
                while (en.MoveNext())
497
                {
498
                    XdmNode error = (XdmNode)en.Current;
499
                    String expectedErrorCode = error.StringValue;
500
                    expectedError += (expectedErrorCode + " ");
501
                    if (expectedErrorCode.Equals(errorCode))
502
                    {
503
                        matched = true;
504
                        feedback.Feedback(passed++, failed, total);
505
                        log.WriteLine("Error " + errorCode + " as expected");
506
                        results.WriteLine("<test-case name='" + testName + "' result='pass'/>");
507
                        break;
508
                    }
509
                }
510
                if (!matched)
511
                {
512
                    if (expectedError.Equals(""))
513
                    {
514
                        feedback.Feedback(passed, failed++, total);
515
                        log.WriteLine("Error " + errorCode + ", expected success");
516
                        results.WriteLine("<test-case name='" + testName + "' result='fail' comment='error " + errorCode + ", expected success'/>");
517
                        results.WriteLine("<--" + filePath + queryName + "-->");
518
                    }
519
                    else
520
                    {
521
                        feedback.Feedback(passed++, failed, total);
522
                        log.WriteLine("Error " + errorCode + ", expected " + expectedError);
523
                        results.WriteLine("<test-case name='" + testName + "' result='pass' comment='error " + errorCode + ", expected " + expectedError + "'/>");
524
                        results.WriteLine("<--" + filePath + queryName + "-->");
525
                    }
526
                }
527

    
528
            }
529
            else
530
            {
531
                // query returned no error
532

    
533
                bool matched = false;
534
                String diag = "";
535
                IEnumerator en = testCase.EnumerateAxis(XdmAxis.Child, outputFileNT);
536
                while (en.MoveNext())
537
                {
538
                    XdmNode outputFile = (XdmNode)en.Current;
539
                    String fileName = testSuiteDir + "/ExpectedTestResults/" + filePath + outputFile.StringValue;
540
                    String comparator = outputFile.GetAttributeValue(compareAtt);
541
                    if (comparator.Equals("Inspect"))
542
                    {
543
                        matched = true;
544
                        feedback.Feedback(passed++, failed, total);
545
                        results.WriteLine("<test-case name='" + testName + "' result='inspect'/>");
546
                        results.WriteLine("<--" + filePath + queryName + "-->");
547
                        break;
548
                    }
549
                    else
550
                    {
551
                        String comparison = fileComparer.compare(outputPath, fileName, comparator);
552
                        matched = (comparison == "OK" || comparison.StartsWith("#"));
553
                        if (matched)
554
                        {
555
                            feedback.Feedback(passed++, failed, total);
556
                            results.WriteLine("<test-case name='" + testName + "' result='pass'/>");
557
                            diag = diag + ("<!-- " + comparison + " -->\n");
558
                            break;
559
                        }
560
                    }
561
                }
562

    
563
                if (!matched)
564
                {
565
                    string expectedError = "";
566
                    IEnumerator ee = testCase.EnumerateAxis(XdmAxis.Child, expectedErrorNT);
567
                    while (ee.MoveNext())
568
                    {
569
                        XdmNode error = (XdmNode)ee.Current;
570
                        String expectedErrorCode = error.StringValue;
571
                        expectedError += (expectedErrorCode + " ");
572
                    }
573

    
574
                    if (expectedError.Equals(""))
575
                    {
576
                        feedback.Feedback(passed, failed++, total);
577
                        log.WriteLine("Results differ from expected results");
578
                        results.WriteLine("<test-case name='" + testName + "' result='fail'/>");
579
                        results.WriteLine("<--" + filePath + queryName + "-->");
580
                    }
581
                    else
582
                    {
583
                        feedback.Feedback(passed, failed++, total);
584
                        log.WriteLine("Error " + expectedError + "expected but not reported");
585
                        results.WriteLine("<test-case name='" + testName + "' result='fail' comment='expected error " + expectedError + "not reported'/>");
586
                        results.WriteLine("<--" + filePath + queryName + "-->");
587
                    }
588
                }
589
            }
590
        }
591

    
592
        results.WriteLine("</test-suite-result>");
593
        results.Close();
594
        log.Close();
595

    
596
    }
597

    
598
    /**
599
     * Construct source object. This method allows subclassing e.g. to build a DOM or XOM source.
600
     * @param xml
601
     * @return
602
     * @throws XPathException
603
     */
604

    
605
    protected XdmNode buildSource(XdmNode catalog, DocumentBuilder builder, String sourceName)
606
    {
607

    
608
        // Find the source element in the catalog
609

    
610
        XPathSelector xps = findSourcePath.Load();
611
        xps.SetVariable(new QName("", "param"), new XdmAtomicValue(sourceName));
612
        xps.ContextItem = catalog;
613
        XdmNode source = (XdmNode)xps.EvaluateSingle();
614

    
615
        // decide whether schema validation is needed
616

    
617
        bool validate = source.GetAttributeValue(new QName("", "schema")) != null;
618
        if (validate)
619
        {
620
            builder.SchemaValidationMode = SchemaValidationMode.Strict;
621
        }
622
        else
623
        {
624
            builder.SchemaValidationMode = SchemaValidationMode.None;
625
        }
626

    
627
        // build the document tree from the source file
628

    
629
        string filename = testSuiteDir + "/" + source.GetAttributeValue(new QName("", "FileName"));
630
        if (source == null)
631
        {
632
            throw new ArgumentException("Source " + sourceName + " not found in catalog");
633
        }
634
        return builder.Build(new Uri(filename));
635
    }
636

    
637

    
638
    private void outputDiscretionaryItems()
639
    {
640
        results.WriteLine("  <discretionary-items/>");
641
    }
642

    
643

    
644
    private IList getCollection(XdmNode collectionNode)
645
    {
646
        ArrayList list = new ArrayList(10);
647
        IEnumerator e = collectionNode.EnumerateAxis(
648
            XdmAxis.Child, new QName(testURI, "input-document"));
649
        while (e.MoveNext())
650
        {
651
            XdmNode node = (XdmNode)e.Current;
652
            list.Add(new Uri(testSuiteDir + "/TestSources/" + node.StringValue + ".xml"));
653
        }
654
        return list;
655
    }
656

    
657
    // Implementation of IQueryResolver used to locate library modules
658

    
659
    private class XqtsModuleResolver : IQueryResolver
660
    {
661

    
662
        private XdmNode testCase;
663
        private XPathExecutable findModule;
664

    
665
        public XqtsModuleResolver(XdmNode testCase, XPathExecutable findModule)
666
        {
667
            this.testCase = testCase;
668
            this.findModule = findModule;
669
        }
670

    
671
        public Uri[] GetModules(String moduleUri, Uri baseUri, String[] locationHints)
672
        {
673
            XPathSelector xps = findModule.Load();
674
            xps.SetVariable(new QName("", "testcase"), testCase);
675
            xps.SetVariable(new QName("", "moduleuri"), new XdmAtomicValue(moduleUri));
676
            ArrayList uris = new ArrayList();
677
            foreach (XdmItem i in xps) {
678
                uris.Add(new Uri((String)((XdmAtomicValue)i).Value));
679
            }
680
            return (Uri[])uris.ToArray(typeof(Uri));
681
        }
682

    
683
        public Object GetEntity(Uri absoluteUri)
684
        {
685
            String u = absoluteUri.ToString();
686
            if (u.StartsWith("file:///"))
687
            {
688
                u = u.Substring(8);
689
            }
690
            else if (u.StartsWith("file:/"))
691
            {
692
                u = u.Substring(6);
693
            }
694
            return new FileStream(u, FileMode.Open, FileAccess.Read, FileShare.Read);
695
        }
696
    }
697

    
698

    
699

    
700

    
701
}
702

    
703

    
(16-16/19)