Project

Profile

Help

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

he / latest9.4 / hen / csource / samples / XQueryTestSuiteDriver.cs @ c3c84ba2

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

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

    
30

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

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

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

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

    
67

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

    
73

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

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

    
85

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

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

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

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

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

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

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

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

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

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

    
161

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

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

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

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

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

    
200
        Hashtable sourceDocs = new Hashtable(50);
201

    
202
        // Load the catalog
203

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

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

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

    
219
        // Create the results file and log file
220

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

    
229
        // Pre-load all the schemas
230

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

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

    
247
        // Process the test cases in turn
248

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

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

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

    
266

    
267
            // Compile the query
268

    
269
            String errorCode = null;
270

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

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

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

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

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

    
322
                // Supply any input documents
323

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

    
346
                // Supply any input URIs
347

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

    
388
                // Supply the default collection if required
389

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

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

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

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

    
422
                // Supply the context item if required
423

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

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

    
439
                // Create a serializer for the output
440

    
441

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

    
459
                // Finally, run the query
460

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

    
486
            // Compare actual results with expected results
487

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

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

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

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

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

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

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

    
595
    }
596

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

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

    
607
        // Find the source element in the catalog
608

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

    
614
        // decide whether schema validation is needed
615

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

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

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

    
636

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

    
642

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

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

    
658
    private class XqtsModuleResolver : IQueryResolver
659
    {
660

    
661
        private XdmNode testCase;
662
        private XPathExecutable findModule;
663

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

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

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

    
697

    
698

    
699

    
700
}
701

    
702

    
(13-13/14)