rdf-test-suite 2.7.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -1
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/index.js.map +1 -1
- package/lib/TestSuiteRunner.js +5 -0
- package/lib/TestSuiteRunner.js.map +1 -1
- package/lib/context-manifest.json +2 -0
- package/lib/testcase/TestCaseHandlers.js +2 -2
- package/lib/testcase/TestCaseHandlers.js.map +1 -1
- package/lib/testcase/sparql/IQueryEngine.d.ts +6 -0
- package/lib/testcase/sparql/IQueryEngine.js.map +1 -1
- package/lib/testcase/sparql/TestCaseGraphStoreProtocol.d.ts +152 -0
- package/lib/testcase/sparql/TestCaseGraphStoreProtocol.js +376 -0
- package/lib/testcase/sparql/TestCaseGraphStoreProtocol.js.map +1 -0
- package/lib/testcase/sparql/TestCaseProtocol.d.ts +9 -10
- package/lib/testcase/sparql/TestCaseProtocol.js +0 -2
- package/lib/testcase/sparql/TestCaseProtocol.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -262,6 +262,15 @@ $ rdf-test-suite myengine.js http://w3c.github.io/rdf-tests/sparql/sparql11/mani
|
|
|
262
262
|
-i '{ "protocolEndpoint": "http://localhost:3000/sparql" }'
|
|
263
263
|
```
|
|
264
264
|
|
|
265
|
+
The SPARQL 1.1 Graph Store Protocol tests do the same, through the optional
|
|
266
|
+
`startGraphStoreEndpoint` method and the `graphStoreEndpoint` option.
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
$ rdf-test-suite myengine.js http://w3c.github.io/rdf-tests/sparql/sparql11/manifest-all.ttl \
|
|
270
|
+
-s http://www.w3.org/TR/sparql11-http-rdf-update/ \
|
|
271
|
+
-i '{ "graphStoreEndpoint": "http://localhost:3000/sparql" }'
|
|
272
|
+
```
|
|
273
|
+
|
|
265
274
|
### Test timeouts
|
|
266
275
|
|
|
267
276
|
By default, all tests are allowed to run 3000 ms.
|
|
@@ -324,7 +333,7 @@ $ rdf-test-suite myengine.js https://w3c.github.io/rdf-tests/sparql/sparql11/man
|
|
|
324
333
|
| [SPARQL 1.1 tests](https://w3c.github.io/rdf-tests/sparql/sparql11/) | [SPARQL 1.1 Entailment](http://www.w3.org/TR/sparql11-entailment/) | ✖ | http://w3c.github.io/rdf-tests/sparql/sparql11/manifest-all.ttl |
|
|
325
334
|
| [SPARQL 1.1 tests](https://w3c.github.io/rdf-tests/sparql/sparql11/) | [SPARQL 1.1 Service Description](http://www.w3.org/TR/sparql11-service-description/) | ✔ | http://w3c.github.io/rdf-tests/sparql/sparql11/manifest-all.ttl |
|
|
326
335
|
| [SPARQL 1.1 tests](https://w3c.github.io/rdf-tests/sparql/sparql11/) | [SPARQL 1.1 Protocol](http://www.w3.org/TR/sparql11-protocol/) | ✔ | http://w3c.github.io/rdf-tests/sparql/sparql11/manifest-all.ttl |
|
|
327
|
-
| [SPARQL 1.1 tests](https://w3c.github.io/rdf-tests/sparql/sparql11/) | [SPARQL 1.1 HTTP RDF Update](http://www.w3.org/TR/sparql11-http-rdf-update/) |
|
|
336
|
+
| [SPARQL 1.1 tests](https://w3c.github.io/rdf-tests/sparql/sparql11/) | [SPARQL 1.1 HTTP RDF Update](http://www.w3.org/TR/sparql11-http-rdf-update/) | ✔ | http://w3c.github.io/rdf-tests/sparql/sparql11/manifest-all.ttl |
|
|
328
337
|
| [RDF/XML Syntax Tests](https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-xml/) | [RDF 1.1 XML Syntax](https://www.w3.org/TR/rdf-syntax-grammar/) | [`IParser`](https://github.com/rubensworks/rdf-test-suite.js/blob/master/lib/testcase/rdfsyntax/IParser.ts) | https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-xml/manifest.ttl |
|
|
329
338
|
| [N-Triples Tests](https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-n-triples//) | [RDF 1.1 N-Triples](https://www.w3.org/TR/n-triples/) | [`IParser`](https://github.com/rubensworks/rdf-test-suite.js/blob/master/lib/testcase/rdfsyntax/IParser.ts) | https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-n-triples/manifest.ttl |
|
|
330
339
|
| [N-Quads Tests](https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-n-quads/) | [RDF 1.1 N-Quads](https://www.w3.org/TR/n-quads/) | [`IParser`](https://github.com/rubensworks/rdf-test-suite.js/blob/master/lib/testcase/rdfsyntax/IParser.ts) | https://w3c.github.io/rdf-tests/rdf/rdf11/rdf-n-quads/manifest.ttl |
|
package/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export * from './lib/testcase/sparql/QueryResultBindings';
|
|
|
15
15
|
export * from './lib/testcase/sparql/QueryResultBoolean';
|
|
16
16
|
export * from './lib/testcase/sparql/QueryResultQuads';
|
|
17
17
|
export * from './lib/testcase/sparql/TestCaseCsvResultFormat';
|
|
18
|
+
export * from './lib/testcase/sparql/TestCaseGraphStoreProtocol';
|
|
18
19
|
export * from './lib/testcase/sparql/TestCaseNegativeSyntax';
|
|
19
20
|
export * from './lib/testcase/sparql/TestCasePositiveSyntax';
|
|
20
21
|
export * from './lib/testcase/sparql/TestCaseProtocol';
|
package/index.js
CHANGED
|
@@ -31,6 +31,7 @@ __exportStar(require("./lib/testcase/sparql/QueryResultBindings"), exports);
|
|
|
31
31
|
__exportStar(require("./lib/testcase/sparql/QueryResultBoolean"), exports);
|
|
32
32
|
__exportStar(require("./lib/testcase/sparql/QueryResultQuads"), exports);
|
|
33
33
|
__exportStar(require("./lib/testcase/sparql/TestCaseCsvResultFormat"), exports);
|
|
34
|
+
__exportStar(require("./lib/testcase/sparql/TestCaseGraphStoreProtocol"), exports);
|
|
34
35
|
__exportStar(require("./lib/testcase/sparql/TestCaseNegativeSyntax"), exports);
|
|
35
36
|
__exportStar(require("./lib/testcase/sparql/TestCasePositiveSyntax"), exports);
|
|
36
37
|
__exportStar(require("./lib/testcase/sparql/TestCaseProtocol"), exports);
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wFAAsE;AACtE,uFAAqE;AACrE,sFAAoE;AACpE,8FAA4E;AAC5E,wEAAsD;AACtD,0EAAwD;AACxD,mEAAiD;AACjD,uEAAqD;AACrD,kFAAgE;AAChE,8EAA4D;AAC5D,qEAAmD;AACnD,wEAAsD;AACtD,sEAAoD;AACpD,4EAA0D;AAC1D,2EAAyD;AACzD,yEAAuD;AACvD,gFAA8D;AAC9D,+EAA6D;AAC7D,+EAA6D;AAC7D,yEAAuD;AACvD,gFAA8D;AAC9D,mFAAiE;AACjE,iFAA+D;AAC/D,2DAAyC;AACzC,kEAAgD;AAChD,qEAAmD;AACnD,kDAAgC;AAChC,uDAAqC;AACrC,wDAAsC;AACtC,6CAA2B;AAC3B,qDAAmC;AACnC,kDAAgC;AAChC,6DAA2C;AAC3C,oEAAkD","sourcesContent":["export * from './lib/testcase/rdfsyntax/jsonld/TestCaseJsonLdFromRdf';\nexport * from './lib/testcase/rdfsyntax/jsonld/TestCaseJsonLdSyntax';\nexport * from './lib/testcase/rdfsyntax/jsonld/TestCaseJsonLdToRdf';\nexport * from './lib/testcase/rdfsyntax/jsonld/TestCaseJsonLdToRdfNegative';\nexport * from './lib/testcase/rdfsyntax/TestCaseEval';\nexport * from './lib/testcase/rdfsyntax/TestCaseSyntax';\nexport * from './lib/testcase/rdfsyntax/IParser';\nexport * from './lib/testcase/rdfsyntax/ISerializer';\nexport * from './lib/testcase/rdfsyntax/ITestCaseFromRdfSyntax';\nexport * from './lib/testcase/rdfsyntax/ITestCaseRdfSyntax';\nexport * from './lib/testcase/sparql/IQueryEngine';\nexport * from './lib/testcase/sparql/ITestCaseSparql';\nexport * from './lib/testcase/sparql/IUpdateEngine';\nexport * from './lib/testcase/sparql/QueryResultBindings';\nexport * from './lib/testcase/sparql/QueryResultBoolean';\nexport * from './lib/testcase/sparql/QueryResultQuads';\nexport * from './lib/testcase/sparql/TestCaseCsvResultFormat';\nexport * from './lib/testcase/sparql/TestCaseNegativeSyntax';\nexport * from './lib/testcase/sparql/TestCasePositiveSyntax';\nexport * from './lib/testcase/sparql/TestCaseProtocol';\nexport * from './lib/testcase/sparql/TestCaseQueryEvaluation';\nexport * from './lib/testcase/sparql/TestCaseServiceDescription';\nexport * from './lib/testcase/sparql/TestCaseUpdateEvaluation';\nexport * from './lib/testcase/ITestCase';\nexport * from './lib/testcase/ITestCaseHandler';\nexport * from './lib/testcase/TestCaseUnsupported';\nexport * from './lib/IManifest';\nexport * from './lib/ManifestLoader';\nexport * from './lib/TestSuiteRunner';\nexport * from './lib/Util';\nexport * from './lib/ErrorSkipped';\nexport * from './lib/ErrorTest';\nexport * from './lib/DocumentLoaderCached';\nexport * from './lib/testcase/TestCaseMediaTypes';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wFAAsE;AACtE,uFAAqE;AACrE,sFAAoE;AACpE,8FAA4E;AAC5E,wEAAsD;AACtD,0EAAwD;AACxD,mEAAiD;AACjD,uEAAqD;AACrD,kFAAgE;AAChE,8EAA4D;AAC5D,qEAAmD;AACnD,wEAAsD;AACtD,sEAAoD;AACpD,4EAA0D;AAC1D,2EAAyD;AACzD,yEAAuD;AACvD,gFAA8D;AAC9D,mFAAiE;AACjE,+EAA6D;AAC7D,+EAA6D;AAC7D,yEAAuD;AACvD,gFAA8D;AAC9D,mFAAiE;AACjE,iFAA+D;AAC/D,2DAAyC;AACzC,kEAAgD;AAChD,qEAAmD;AACnD,kDAAgC;AAChC,uDAAqC;AACrC,wDAAsC;AACtC,6CAA2B;AAC3B,qDAAmC;AACnC,kDAAgC;AAChC,6DAA2C;AAC3C,oEAAkD","sourcesContent":["export * from './lib/testcase/rdfsyntax/jsonld/TestCaseJsonLdFromRdf';\nexport * from './lib/testcase/rdfsyntax/jsonld/TestCaseJsonLdSyntax';\nexport * from './lib/testcase/rdfsyntax/jsonld/TestCaseJsonLdToRdf';\nexport * from './lib/testcase/rdfsyntax/jsonld/TestCaseJsonLdToRdfNegative';\nexport * from './lib/testcase/rdfsyntax/TestCaseEval';\nexport * from './lib/testcase/rdfsyntax/TestCaseSyntax';\nexport * from './lib/testcase/rdfsyntax/IParser';\nexport * from './lib/testcase/rdfsyntax/ISerializer';\nexport * from './lib/testcase/rdfsyntax/ITestCaseFromRdfSyntax';\nexport * from './lib/testcase/rdfsyntax/ITestCaseRdfSyntax';\nexport * from './lib/testcase/sparql/IQueryEngine';\nexport * from './lib/testcase/sparql/ITestCaseSparql';\nexport * from './lib/testcase/sparql/IUpdateEngine';\nexport * from './lib/testcase/sparql/QueryResultBindings';\nexport * from './lib/testcase/sparql/QueryResultBoolean';\nexport * from './lib/testcase/sparql/QueryResultQuads';\nexport * from './lib/testcase/sparql/TestCaseCsvResultFormat';\nexport * from './lib/testcase/sparql/TestCaseGraphStoreProtocol';\nexport * from './lib/testcase/sparql/TestCaseNegativeSyntax';\nexport * from './lib/testcase/sparql/TestCasePositiveSyntax';\nexport * from './lib/testcase/sparql/TestCaseProtocol';\nexport * from './lib/testcase/sparql/TestCaseQueryEvaluation';\nexport * from './lib/testcase/sparql/TestCaseServiceDescription';\nexport * from './lib/testcase/sparql/TestCaseUpdateEvaluation';\nexport * from './lib/testcase/ITestCase';\nexport * from './lib/testcase/ITestCaseHandler';\nexport * from './lib/testcase/TestCaseUnsupported';\nexport * from './lib/IManifest';\nexport * from './lib/ManifestLoader';\nexport * from './lib/TestSuiteRunner';\nexport * from './lib/Util';\nexport * from './lib/ErrorSkipped';\nexport * from './lib/ErrorTest';\nexport * from './lib/DocumentLoaderCached';\nexport * from './lib/testcase/TestCaseMediaTypes';\n"]}
|
package/lib/TestSuiteRunner.js
CHANGED
|
@@ -68,6 +68,11 @@ const ENDPOINT_SPECIFICATIONS = [
|
|
|
68
68
|
option: 'protocolEndpoint',
|
|
69
69
|
start: engine => { var _a; return (_a = engine.startProtocolEndpoint) === null || _a === void 0 ? void 0 : _a.call(engine); },
|
|
70
70
|
},
|
|
71
|
+
{
|
|
72
|
+
specification: 'http://www.w3.org/TR/sparql11-http-rdf-update/',
|
|
73
|
+
option: 'graphStoreEndpoint',
|
|
74
|
+
start: engine => { var _a; return (_a = engine.startGraphStoreEndpoint) === null || _a === void 0 ? void 0 : _a.call(engine); },
|
|
75
|
+
},
|
|
71
76
|
];
|
|
72
77
|
/**
|
|
73
78
|
* TestSuiteRunner runs a certain test suite manifest.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TestSuiteRunner.js","sourceRoot":"","sources":["TestSuiteRunner.ts"],"names":[],"mappings":"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","sourcesContent":["import type * as RDF from '@rdfjs/types';\nimport * as LogSymbols from 'log-symbols';\nimport { DataFactory } from 'rdf-data-factory';\nimport type { IManifest } from './IManifest';\nimport { ManifestLoader } from './ManifestLoader';\nimport type { ITestCase } from './testcase/ITestCase';\nimport type { IQueryEngine, ISparqlEndpoint } from './testcase/sparql/IQueryEngine';\nimport { Util } from './Util';\nimport WriteStream = NodeJS.WriteStream;\nimport Timeout = NodeJS.Timeout;\n\n// eslint-disable-next-line ts/no-require-imports, ts/no-var-requires\nconst quad = require('rdf-quad');\n// eslint-disable-next-line ts/no-require-imports, ts/no-var-requires\nconst streamifyArray = require('streamify-array').streamifyArray;\n\nconst DF = new DataFactory();\n\n/**\n * The specifications that are tested against a running endpoint,\n * together with the engine method that starts it,\n * and the custom engine option that its URL is passed to.\n */\nconst ENDPOINT_SPECIFICATIONS: {\n specification: string;\n option: string;\n start: (engine: IQueryEngine) => Promise<ISparqlEndpoint> | undefined;\n}[] = [\n {\n specification: 'http://www.w3.org/TR/sparql11-service-description/',\n option: 'serviceDescriptionEndpoint',\n start: engine => engine.startServiceDescriptionEndpoint?.(),\n },\n {\n specification: 'http://www.w3.org/TR/sparql11-protocol/',\n option: 'protocolEndpoint',\n start: engine => engine.startProtocolEndpoint?.(),\n },\n];\n\nexport interface ITestSuiteConfig {\n exitWithStatusCode0: boolean;\n explicitApproval?: boolean;\n runRejected?: boolean;\n outputFormat: string;\n timeOutDuration: number;\n customEngingeOptions: object;\n specification?: string;\n cachePath?: string;\n testRegex?: RegExp;\n skipRegex?: RegExp;\n urlToFileMapping?: string;\n}\n\n/**\n * TestSuiteRunner runs a certain test suite manifest.\n */\nexport class TestSuiteRunner {\n /**\n * Parse an URL to file mapping string.\n * @param {string} urlToFileMapping An URL to file mapping string\n * @return {{url: string; path: string}[]} A parsed URL to file mapping array.\n */\n public fromUrlToMappingString(urlToFileMapping?: string): { url: string; path: string }[] {\n const urlToFileMappings: { url: string; path: string }[] = [];\n if (urlToFileMapping) {\n const [ url, path ]: string[] = urlToFileMapping.split('~');\n urlToFileMappings.push({ url, path });\n }\n return urlToFileMappings;\n }\n\n /**\n * Run the manifest with the given URL.\n * @param {string} manifestUrl The URL of a manifest.\n * @param handler The handler to run the tests with.\n * @param config The test suite configuration.\n * @return {Promise<ITestResult[]>} A promise resolving to an array of test results.\n */\n public async runManifest(manifestUrl: string, handler: any, config: ITestSuiteConfig): Promise<ITestResult[]> {\n const { cachePath, specification, urlToFileMapping } = config;\n const urlToFileMappings = this.fromUrlToMappingString(urlToFileMapping);\n const manifest: IManifest = await new ManifestLoader().from(manifestUrl, { cachePath, urlToFileMappings });\n const results: ITestResult[] = [];\n\n // Only run the tests for the given specification if one was defined.\n if (specification) {\n if (!manifest.specifications || !manifest.specifications[specification]) {\n return [];\n }\n await this.runManifestWithEndpoint(manifest.specifications[specification], handler, config, results);\n return results;\n }\n\n await this.runManifestWithEndpoint(manifest, handler, config, results);\n return results;\n }\n\n /**\n * Run a manifest, starting an endpoint if the selected specification requires one.\n * @param {string} manifest A manifest.\n * @param handler The handler to run the tests with.\n * @param config The test suite configuration.\n * @param {ITestResult[]} results An array to append the test results to.\n * @return {Promise<void>} A promise resolving when the tests are finished.\n */\n private async runManifestWithEndpoint(\n manifest: IManifest,\n handler: any,\n config: ITestSuiteConfig,\n results: ITestResult[],\n ): Promise<void> {\n const customEngineOptions = <Record<string, unknown>> config.customEngingeOptions;\n const endpointSpecification = ENDPOINT_SPECIFICATIONS\n .find(entry => entry.specification === config.specification && !customEngineOptions[entry.option]);\n const endpoint = endpointSpecification ? await endpointSpecification.start(<IQueryEngine> handler) : undefined;\n\n if (!endpoint) {\n await this.runManifestConcrete(manifest, handler, config, results);\n return;\n }\n\n try {\n await this.runManifestConcrete(manifest, handler, {\n ...config,\n customEngingeOptions: {\n ...customEngineOptions,\n [endpointSpecification.option]: endpoint.endpoint,\n },\n }, results);\n } finally {\n await endpoint.close();\n }\n }\n\n /**\n * Run the given manifest.\n * @param {string} manifest A manifest.\n * @param handler The handler to run the tests with.\n * @param config The test suite configuration.\n * @param {ITestResult[]} results An array to append the test results to\n * @return {Promise<void>} A promise resolving when the tests are finished.\n */\n public async runManifestConcrete(\n manifest: IManifest,\n handler: any,\n config: ITestSuiteConfig,\n results: ITestResult[],\n ) {\n // Execute all tests in this manifest\n if (manifest.testEntries) {\n for (const test of manifest.testEntries) {\n if ((!config.testRegex || config.testRegex.test(test.uri)) && !(config.skipRegex && config.skipRegex.test(test.uri))) {\n if (!config.runRejected && test.approval === 'http://www.w3.org/ns/rdftest#Rejected') {\n // Skip tests that are explicitly rejected\n results.push({ test, ok: false, skipped: true, error: new Error('Rejected Test') });\n } else if (config.explicitApproval && test.approval !== 'http://www.w3.org/ns/rdftest#Approved') {\n // Skip tests that are explicitly rejected\n results.push({ test, ok: false, skipped: true, error: new Error('Test not explicitly approved') });\n } else {\n let timeout: Timeout = null;\n const timeStart = process.hrtime();\n let testResultOverride: ITestResultOverride | undefined;\n try {\n await Promise.race([\n test.test(handler, config.customEngingeOptions)\n .then((result) => {\n if (result) {\n testResultOverride = result;\n }\n }),\n new Promise((res, rej) => {\n // Global.setTimeout is used here to avoid browser/node compatibility issues\n timeout = globalThis.setTimeout(\n () => rej(new Error(`Test case '${test.uri}' timed out`)),\n config.timeOutDuration,\n );\n }),\n ]);\n } catch (error) {\n clearTimeout(timeout);\n results.push({ test, ok: false, error: <any> error, skipped: (<any> error).skipped });\n continue;\n }\n const timeEnd = process.hrtime(timeStart);\n clearTimeout(timeout);\n results.push({ test, ok: true, duration: (timeEnd[0] * 1000) + (timeEnd[1] / 1000000), ...testResultOverride });\n }\n }\n }\n }\n\n // Recursively handle all sub-manifests\n if (manifest.subManifests) {\n for (const subManifest of manifest.subManifests) {\n await (this.runManifestConcrete(subManifest, handler, config, results));\n }\n }\n }\n\n /**\n * Print the given test results to a text stream.\n * @param {WriteStream} stdout The output stream to write to.\n * @param {ITestResult[]} results An array of test results.\n * @param {boolean} compact If the results should be printed in compact-mode.\n */\n public resultsToText(stdout: WriteStream, results: ITestResult[], compact: boolean) {\n const failedTests: ITestResult[] = [];\n let success = 0;\n let skipped = 0;\n for (const result of results) {\n if (result.ok) {\n success++;\n stdout.write(`${LogSymbols.success} ${result.test.name} (${result.test.uri})${` ${Util.withColor(`${result.duration}ms`, Util.colorGray)}`}\\n`);\n } else if (result.skipped) {\n skipped++;\n stdout.write(`${LogSymbols.info} ${result.test.name} (${result.test.uri})\\n`);\n } else {\n failedTests.push(result);\n stdout.write(`${LogSymbols.error} ${result.test.name} (${result.test.uri})\\n`);\n }\n }\n\n if (!compact) {\n for (const result of failedTests) {\n stdout.write(`\n${LogSymbols.error} ${Util.withColor(result.test.name, Util.colorRed)}\n ${result.test.comment || ''}\n ${'test' in result.error ? result.error : result.error.stack}\n ${Util.withColor(`More info: ${result.test.uri}`, Util.colorBlue)}\n\n`);\n }\n }\n\n const skippedString = skipped ? ` (skipped ${skipped})` : '';\n success += skipped;\n if (success === results.length) {\n stdout.write(`${LogSymbols.success} ${success} / ${results.length} tests succeeded!${skippedString}\\n`);\n } else {\n stdout.write(`${LogSymbols.error} ${success} / ${results.length} tests succeeded!${skippedString}\\n`);\n }\n }\n\n /**\n * Convert test results to an RDF stream.\n * @param {ITestResult[]} results Test results.\n * @param {IEarlProperties} properties EARL properties.\n * @param {Date} testDate The date at which the tests were executed.\n * @return {Stream} An RDF stream of quads.\n */\n public resultsToEarl(results: ITestResult[], properties: IEarlProperties, testDate: Date): RDF.Stream {\n // eslint-disable-next-line ts/no-require-imports, ts/no-var-requires\n const p = require('./prefixes.json');\n const dateRaw = testDate.toISOString();\n const date = `\"${dateRaw}\"^^${p.xsd}dateTime`;\n const quads: RDF.Quad[] = [];\n\n // Describe report\n const report = properties.reportUri || '';\n quads.push(DF.quad(DF.namedNode(report), DF.namedNode(`${p.foaf}primaryTopic`), DF.namedNode(properties.applicationUri)));\n quads.push(DF.quad(DF.namedNode(report), DF.namedNode(`${p.dc}issued`), DF.literal(testDate.toISOString(), DF.namedNode(`${p.xsd}dateTime`))));\n for (const author of properties.authors) {\n quads.push(DF.quad(DF.namedNode(report), DF.namedNode(`${p.foaf}maker`), DF.namedNode(author.uri)));\n }\n\n // Describe application\n const app = properties.applicationUri;\n quads.push(quad(app, `${p.rdf}type`, `${p.earl}Software`));\n quads.push(quad(app, `${p.rdf}type`, `${p.earl}TestSubject`));\n quads.push(quad(app, `${p.rdf}type`, `${p.doap}Project`));\n quads.push(quad(app, `${p.doap}name`, `\"${properties.applicationNameFull}\"`));\n quads.push(quad(app, `${p.dc}title`, `\"${properties.applicationNameFull}\"`));\n if (properties.version) {\n quads.push(quad(app, `${p.doap}release`, '_:b_release'));\n quads.push(quad('_:b_release', `${p.doap}revision`, `\"${properties.version}\"`));\n }\n quads.push(quad(app, `${p.doap}homepage`, properties.applicationHomepageUrl));\n quads.push(quad(app, `${p.doap}license`, properties.licenseUri));\n quads.push(quad(app, `${p.doap}programming-language`, '\"JavaScript\"'));\n for (const spec of properties.specificationUris) {\n quads.push(quad(app, `${p.doap}implements`, spec));\n }\n quads.push(quad(app, `${p.doap}category`, 'http://dbpedia.org/resource/Resource_Description_Framework'));\n quads.push(quad(app, `${p.doap}download-page`, `https://npmjs.org/package/${properties.applicationNameNpm}`));\n if (properties.applicationBugsUrl) {\n quads.push(quad(app, `${p.doap}bug-database`, properties.applicationBugsUrl));\n }\n if (properties.applicationBlogUrl) {\n quads.push(quad(app, `${p.doap}blog`, properties.applicationBlogUrl));\n }\n for (const author of properties.authors) {\n quads.push(quad(app, `${p.doap}developer`, author.uri));\n quads.push(quad(app, `${p.doap}maintainer`, author.uri));\n quads.push(quad(app, `${p.doap}documenter`, author.uri));\n quads.push(quad(app, `${p.doap}maker`, author.uri));\n quads.push(quad(app, `${p.dc}creator`, author.uri));\n }\n quads.push(quad(app, `${p.dc}description`, `\"${properties.applicationDescription}\"@en`));\n quads.push(quad(app, `${p.doap}description`, `\"${properties.applicationDescription}\"@en`));\n\n // Describe authors\n for (const author of properties.authors) {\n quads.push(quad(author.uri, `${p.rdf}type`, `${p.foaf}Person`));\n quads.push(quad(author.uri, `${p.rdf}type`, `${p.earl}Assertor`));\n if (author.name) {\n quads.push(quad(author.uri, `${p.foaf}name`, `\"${author.name}\"`));\n }\n if (author.homepage) {\n quads.push(quad(author.uri, `${p.foaf}homepage`, author.homepage));\n }\n if (author.primaryTopic) {\n quads.push(quad(author.uri, `${p.foaf}primaryTopicOf`, author.primaryTopic));\n }\n }\n\n // Describe test results\n let id = 0;\n for (const result of results) {\n const testUri = result.test.uri;\n quads.push(quad(testUri, `${p.rdf}type`, `${p.earl}TestCriterion`));\n quads.push(quad(testUri, `${p.rdf}type`, `${p.earl}TestCase`));\n quads.push(quad(testUri, `${p.dc}title`, `\"${result.test.name}\"`));\n if (result.test.comment) {\n quads.push(quad(testUri, `${p.dc}description`, `\"${result.test.comment}\"`));\n }\n quads.push(quad(testUri, `${p.earl}assertions`, `_:assertions${id}`));\n quads.push(quad(`_:assertions${id}`, `${p.rdf}first`, `_:assertion${id}`));\n quads.push(quad(`_:assertions${id}`, `${p.rdf}rest`, `${p.rdf}nil`));\n quads.push(quad(`_:assertion${id}`, `${p.rdf}type`, `${p.earl}Assertion`));\n for (const author of properties.authors) {\n quads.push(quad(`_:assertion${id}`, `${p.earl}assertedBy`, author.uri));\n }\n quads.push(quad(`_:assertion${id}`, `${p.earl}test`, testUri));\n quads.push(quad(`_:assertion${id}`, `${p.earl}subject`, app));\n quads.push(quad(`_:assertion${id}`, `${p.earl}mode`, `${p.earl}automatic`));\n quads.push(quad(`_:assertion${id}`, `${p.earl}result`, `_:result${id}`));\n quads.push(quad(`_:result${id}`, `${p.rdf}type`, `${p.earl}TestResult`));\n quads.push(quad(`_:result${id}`, `${p.earl}outcome`, p.earl + (result.ok ? 'passed' : (result.skipped ? 'inapplicable' : 'failed'))));\n quads.push(quad(`_:result${id}`, `${p.dc}date`, date));\n id++;\n }\n\n return streamifyArray(quads);\n }\n\n /**\n * Create an {#link IEarlProperties} data object based on package.json contents.\n * @param packageJson Package.json contents.\n * @return {IEarlProperties} A data object.\n */\n public packageJsonToEarlProperties(packageJson: any): IEarlProperties {\n return {\n applicationBugsUrl: packageJson.bugs && packageJson.bugs.url ? packageJson.bugs.url : packageJson.bugs,\n applicationDescription: packageJson.description,\n applicationHomepageUrl: packageJson.homepage,\n applicationNameFull: packageJson.name,\n applicationNameNpm: packageJson.name,\n applicationUri: packageJson.name ? `https://www.npmjs.com/package/${packageJson.name}/` : null,\n authors: [\n {\n homepage: null,\n name: packageJson.author,\n uri: `https://www.npmjs.com/package/${packageJson.name}/#author`,\n },\n ],\n licenseUri: packageJson.license ? Util.licenseToUri(packageJson.license) : null,\n reportUri: null,\n specificationUris: [],\n version: packageJson.version,\n };\n }\n}\n\nexport interface IEarlProperties {\n reportUri: string;\n authors: IAuthor[];\n licenseUri: string;\n applicationUri: string;\n applicationHomepageUrl: string;\n applicationBugsUrl?: string;\n applicationBlogUrl?: string;\n applicationNameFull: string;\n applicationNameNpm: string;\n applicationDescription: string;\n specificationUris: string[];\n version?: string;\n}\n\nexport interface IAuthor {\n uri: string;\n name?: string;\n homepage?: string;\n primaryTopic?: string;\n}\n\nexport interface ITestResult extends ITestResultOverride {\n test: ITestCase<any>;\n ok: boolean;\n error?: Error;\n skipped?: boolean;\n}\n\nexport interface ITestResultOverride {\n duration?: number; // In ms\n}\n"]}
|
|
1
|
+
{"version":3,"file":"TestSuiteRunner.js","sourceRoot":"","sources":["TestSuiteRunner.ts"],"names":[],"mappings":"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","sourcesContent":["import type * as RDF from '@rdfjs/types';\nimport * as LogSymbols from 'log-symbols';\nimport { DataFactory } from 'rdf-data-factory';\nimport type { IManifest } from './IManifest';\nimport { ManifestLoader } from './ManifestLoader';\nimport type { ITestCase } from './testcase/ITestCase';\nimport type { IQueryEngine, ISparqlEndpoint } from './testcase/sparql/IQueryEngine';\nimport { Util } from './Util';\nimport WriteStream = NodeJS.WriteStream;\nimport Timeout = NodeJS.Timeout;\n\n// eslint-disable-next-line ts/no-require-imports, ts/no-var-requires\nconst quad = require('rdf-quad');\n// eslint-disable-next-line ts/no-require-imports, ts/no-var-requires\nconst streamifyArray = require('streamify-array').streamifyArray;\n\nconst DF = new DataFactory();\n\n/**\n * The specifications that are tested against a running endpoint,\n * together with the engine method that starts it,\n * and the custom engine option that its URL is passed to.\n */\nconst ENDPOINT_SPECIFICATIONS: {\n specification: string;\n option: string;\n start: (engine: IQueryEngine) => Promise<ISparqlEndpoint> | undefined;\n}[] = [\n {\n specification: 'http://www.w3.org/TR/sparql11-service-description/',\n option: 'serviceDescriptionEndpoint',\n start: engine => engine.startServiceDescriptionEndpoint?.(),\n },\n {\n specification: 'http://www.w3.org/TR/sparql11-protocol/',\n option: 'protocolEndpoint',\n start: engine => engine.startProtocolEndpoint?.(),\n },\n {\n specification: 'http://www.w3.org/TR/sparql11-http-rdf-update/',\n option: 'graphStoreEndpoint',\n start: engine => engine.startGraphStoreEndpoint?.(),\n },\n];\n\nexport interface ITestSuiteConfig {\n exitWithStatusCode0: boolean;\n explicitApproval?: boolean;\n runRejected?: boolean;\n outputFormat: string;\n timeOutDuration: number;\n customEngingeOptions: object;\n specification?: string;\n cachePath?: string;\n testRegex?: RegExp;\n skipRegex?: RegExp;\n urlToFileMapping?: string;\n}\n\n/**\n * TestSuiteRunner runs a certain test suite manifest.\n */\nexport class TestSuiteRunner {\n /**\n * Parse an URL to file mapping string.\n * @param {string} urlToFileMapping An URL to file mapping string\n * @return {{url: string; path: string}[]} A parsed URL to file mapping array.\n */\n public fromUrlToMappingString(urlToFileMapping?: string): { url: string; path: string }[] {\n const urlToFileMappings: { url: string; path: string }[] = [];\n if (urlToFileMapping) {\n const [ url, path ]: string[] = urlToFileMapping.split('~');\n urlToFileMappings.push({ url, path });\n }\n return urlToFileMappings;\n }\n\n /**\n * Run the manifest with the given URL.\n * @param {string} manifestUrl The URL of a manifest.\n * @param handler The handler to run the tests with.\n * @param config The test suite configuration.\n * @return {Promise<ITestResult[]>} A promise resolving to an array of test results.\n */\n public async runManifest(manifestUrl: string, handler: any, config: ITestSuiteConfig): Promise<ITestResult[]> {\n const { cachePath, specification, urlToFileMapping } = config;\n const urlToFileMappings = this.fromUrlToMappingString(urlToFileMapping);\n const manifest: IManifest = await new ManifestLoader().from(manifestUrl, { cachePath, urlToFileMappings });\n const results: ITestResult[] = [];\n\n // Only run the tests for the given specification if one was defined.\n if (specification) {\n if (!manifest.specifications || !manifest.specifications[specification]) {\n return [];\n }\n await this.runManifestWithEndpoint(manifest.specifications[specification], handler, config, results);\n return results;\n }\n\n await this.runManifestWithEndpoint(manifest, handler, config, results);\n return results;\n }\n\n /**\n * Run a manifest, starting an endpoint if the selected specification requires one.\n * @param {string} manifest A manifest.\n * @param handler The handler to run the tests with.\n * @param config The test suite configuration.\n * @param {ITestResult[]} results An array to append the test results to.\n * @return {Promise<void>} A promise resolving when the tests are finished.\n */\n private async runManifestWithEndpoint(\n manifest: IManifest,\n handler: any,\n config: ITestSuiteConfig,\n results: ITestResult[],\n ): Promise<void> {\n const customEngineOptions = <Record<string, unknown>> config.customEngingeOptions;\n const endpointSpecification = ENDPOINT_SPECIFICATIONS\n .find(entry => entry.specification === config.specification && !customEngineOptions[entry.option]);\n const endpoint = endpointSpecification ? await endpointSpecification.start(<IQueryEngine> handler) : undefined;\n\n if (!endpoint) {\n await this.runManifestConcrete(manifest, handler, config, results);\n return;\n }\n\n try {\n await this.runManifestConcrete(manifest, handler, {\n ...config,\n customEngingeOptions: {\n ...customEngineOptions,\n [endpointSpecification.option]: endpoint.endpoint,\n },\n }, results);\n } finally {\n await endpoint.close();\n }\n }\n\n /**\n * Run the given manifest.\n * @param {string} manifest A manifest.\n * @param handler The handler to run the tests with.\n * @param config The test suite configuration.\n * @param {ITestResult[]} results An array to append the test results to\n * @return {Promise<void>} A promise resolving when the tests are finished.\n */\n public async runManifestConcrete(\n manifest: IManifest,\n handler: any,\n config: ITestSuiteConfig,\n results: ITestResult[],\n ) {\n // Execute all tests in this manifest\n if (manifest.testEntries) {\n for (const test of manifest.testEntries) {\n if ((!config.testRegex || config.testRegex.test(test.uri)) && !(config.skipRegex && config.skipRegex.test(test.uri))) {\n if (!config.runRejected && test.approval === 'http://www.w3.org/ns/rdftest#Rejected') {\n // Skip tests that are explicitly rejected\n results.push({ test, ok: false, skipped: true, error: new Error('Rejected Test') });\n } else if (config.explicitApproval && test.approval !== 'http://www.w3.org/ns/rdftest#Approved') {\n // Skip tests that are explicitly rejected\n results.push({ test, ok: false, skipped: true, error: new Error('Test not explicitly approved') });\n } else {\n let timeout: Timeout = null;\n const timeStart = process.hrtime();\n let testResultOverride: ITestResultOverride | undefined;\n try {\n await Promise.race([\n test.test(handler, config.customEngingeOptions)\n .then((result) => {\n if (result) {\n testResultOverride = result;\n }\n }),\n new Promise((res, rej) => {\n // Global.setTimeout is used here to avoid browser/node compatibility issues\n timeout = globalThis.setTimeout(\n () => rej(new Error(`Test case '${test.uri}' timed out`)),\n config.timeOutDuration,\n );\n }),\n ]);\n } catch (error) {\n clearTimeout(timeout);\n results.push({ test, ok: false, error: <any> error, skipped: (<any> error).skipped });\n continue;\n }\n const timeEnd = process.hrtime(timeStart);\n clearTimeout(timeout);\n results.push({ test, ok: true, duration: (timeEnd[0] * 1000) + (timeEnd[1] / 1000000), ...testResultOverride });\n }\n }\n }\n }\n\n // Recursively handle all sub-manifests\n if (manifest.subManifests) {\n for (const subManifest of manifest.subManifests) {\n await (this.runManifestConcrete(subManifest, handler, config, results));\n }\n }\n }\n\n /**\n * Print the given test results to a text stream.\n * @param {WriteStream} stdout The output stream to write to.\n * @param {ITestResult[]} results An array of test results.\n * @param {boolean} compact If the results should be printed in compact-mode.\n */\n public resultsToText(stdout: WriteStream, results: ITestResult[], compact: boolean) {\n const failedTests: ITestResult[] = [];\n let success = 0;\n let skipped = 0;\n for (const result of results) {\n if (result.ok) {\n success++;\n stdout.write(`${LogSymbols.success} ${result.test.name} (${result.test.uri})${` ${Util.withColor(`${result.duration}ms`, Util.colorGray)}`}\\n`);\n } else if (result.skipped) {\n skipped++;\n stdout.write(`${LogSymbols.info} ${result.test.name} (${result.test.uri})\\n`);\n } else {\n failedTests.push(result);\n stdout.write(`${LogSymbols.error} ${result.test.name} (${result.test.uri})\\n`);\n }\n }\n\n if (!compact) {\n for (const result of failedTests) {\n stdout.write(`\n${LogSymbols.error} ${Util.withColor(result.test.name, Util.colorRed)}\n ${result.test.comment || ''}\n ${'test' in result.error ? result.error : result.error.stack}\n ${Util.withColor(`More info: ${result.test.uri}`, Util.colorBlue)}\n\n`);\n }\n }\n\n const skippedString = skipped ? ` (skipped ${skipped})` : '';\n success += skipped;\n if (success === results.length) {\n stdout.write(`${LogSymbols.success} ${success} / ${results.length} tests succeeded!${skippedString}\\n`);\n } else {\n stdout.write(`${LogSymbols.error} ${success} / ${results.length} tests succeeded!${skippedString}\\n`);\n }\n }\n\n /**\n * Convert test results to an RDF stream.\n * @param {ITestResult[]} results Test results.\n * @param {IEarlProperties} properties EARL properties.\n * @param {Date} testDate The date at which the tests were executed.\n * @return {Stream} An RDF stream of quads.\n */\n public resultsToEarl(results: ITestResult[], properties: IEarlProperties, testDate: Date): RDF.Stream {\n // eslint-disable-next-line ts/no-require-imports, ts/no-var-requires\n const p = require('./prefixes.json');\n const dateRaw = testDate.toISOString();\n const date = `\"${dateRaw}\"^^${p.xsd}dateTime`;\n const quads: RDF.Quad[] = [];\n\n // Describe report\n const report = properties.reportUri || '';\n quads.push(DF.quad(DF.namedNode(report), DF.namedNode(`${p.foaf}primaryTopic`), DF.namedNode(properties.applicationUri)));\n quads.push(DF.quad(DF.namedNode(report), DF.namedNode(`${p.dc}issued`), DF.literal(testDate.toISOString(), DF.namedNode(`${p.xsd}dateTime`))));\n for (const author of properties.authors) {\n quads.push(DF.quad(DF.namedNode(report), DF.namedNode(`${p.foaf}maker`), DF.namedNode(author.uri)));\n }\n\n // Describe application\n const app = properties.applicationUri;\n quads.push(quad(app, `${p.rdf}type`, `${p.earl}Software`));\n quads.push(quad(app, `${p.rdf}type`, `${p.earl}TestSubject`));\n quads.push(quad(app, `${p.rdf}type`, `${p.doap}Project`));\n quads.push(quad(app, `${p.doap}name`, `\"${properties.applicationNameFull}\"`));\n quads.push(quad(app, `${p.dc}title`, `\"${properties.applicationNameFull}\"`));\n if (properties.version) {\n quads.push(quad(app, `${p.doap}release`, '_:b_release'));\n quads.push(quad('_:b_release', `${p.doap}revision`, `\"${properties.version}\"`));\n }\n quads.push(quad(app, `${p.doap}homepage`, properties.applicationHomepageUrl));\n quads.push(quad(app, `${p.doap}license`, properties.licenseUri));\n quads.push(quad(app, `${p.doap}programming-language`, '\"JavaScript\"'));\n for (const spec of properties.specificationUris) {\n quads.push(quad(app, `${p.doap}implements`, spec));\n }\n quads.push(quad(app, `${p.doap}category`, 'http://dbpedia.org/resource/Resource_Description_Framework'));\n quads.push(quad(app, `${p.doap}download-page`, `https://npmjs.org/package/${properties.applicationNameNpm}`));\n if (properties.applicationBugsUrl) {\n quads.push(quad(app, `${p.doap}bug-database`, properties.applicationBugsUrl));\n }\n if (properties.applicationBlogUrl) {\n quads.push(quad(app, `${p.doap}blog`, properties.applicationBlogUrl));\n }\n for (const author of properties.authors) {\n quads.push(quad(app, `${p.doap}developer`, author.uri));\n quads.push(quad(app, `${p.doap}maintainer`, author.uri));\n quads.push(quad(app, `${p.doap}documenter`, author.uri));\n quads.push(quad(app, `${p.doap}maker`, author.uri));\n quads.push(quad(app, `${p.dc}creator`, author.uri));\n }\n quads.push(quad(app, `${p.dc}description`, `\"${properties.applicationDescription}\"@en`));\n quads.push(quad(app, `${p.doap}description`, `\"${properties.applicationDescription}\"@en`));\n\n // Describe authors\n for (const author of properties.authors) {\n quads.push(quad(author.uri, `${p.rdf}type`, `${p.foaf}Person`));\n quads.push(quad(author.uri, `${p.rdf}type`, `${p.earl}Assertor`));\n if (author.name) {\n quads.push(quad(author.uri, `${p.foaf}name`, `\"${author.name}\"`));\n }\n if (author.homepage) {\n quads.push(quad(author.uri, `${p.foaf}homepage`, author.homepage));\n }\n if (author.primaryTopic) {\n quads.push(quad(author.uri, `${p.foaf}primaryTopicOf`, author.primaryTopic));\n }\n }\n\n // Describe test results\n let id = 0;\n for (const result of results) {\n const testUri = result.test.uri;\n quads.push(quad(testUri, `${p.rdf}type`, `${p.earl}TestCriterion`));\n quads.push(quad(testUri, `${p.rdf}type`, `${p.earl}TestCase`));\n quads.push(quad(testUri, `${p.dc}title`, `\"${result.test.name}\"`));\n if (result.test.comment) {\n quads.push(quad(testUri, `${p.dc}description`, `\"${result.test.comment}\"`));\n }\n quads.push(quad(testUri, `${p.earl}assertions`, `_:assertions${id}`));\n quads.push(quad(`_:assertions${id}`, `${p.rdf}first`, `_:assertion${id}`));\n quads.push(quad(`_:assertions${id}`, `${p.rdf}rest`, `${p.rdf}nil`));\n quads.push(quad(`_:assertion${id}`, `${p.rdf}type`, `${p.earl}Assertion`));\n for (const author of properties.authors) {\n quads.push(quad(`_:assertion${id}`, `${p.earl}assertedBy`, author.uri));\n }\n quads.push(quad(`_:assertion${id}`, `${p.earl}test`, testUri));\n quads.push(quad(`_:assertion${id}`, `${p.earl}subject`, app));\n quads.push(quad(`_:assertion${id}`, `${p.earl}mode`, `${p.earl}automatic`));\n quads.push(quad(`_:assertion${id}`, `${p.earl}result`, `_:result${id}`));\n quads.push(quad(`_:result${id}`, `${p.rdf}type`, `${p.earl}TestResult`));\n quads.push(quad(`_:result${id}`, `${p.earl}outcome`, p.earl + (result.ok ? 'passed' : (result.skipped ? 'inapplicable' : 'failed'))));\n quads.push(quad(`_:result${id}`, `${p.dc}date`, date));\n id++;\n }\n\n return streamifyArray(quads);\n }\n\n /**\n * Create an {#link IEarlProperties} data object based on package.json contents.\n * @param packageJson Package.json contents.\n * @return {IEarlProperties} A data object.\n */\n public packageJsonToEarlProperties(packageJson: any): IEarlProperties {\n return {\n applicationBugsUrl: packageJson.bugs && packageJson.bugs.url ? packageJson.bugs.url : packageJson.bugs,\n applicationDescription: packageJson.description,\n applicationHomepageUrl: packageJson.homepage,\n applicationNameFull: packageJson.name,\n applicationNameNpm: packageJson.name,\n applicationUri: packageJson.name ? `https://www.npmjs.com/package/${packageJson.name}/` : null,\n authors: [\n {\n homepage: null,\n name: packageJson.author,\n uri: `https://www.npmjs.com/package/${packageJson.name}/#author`,\n },\n ],\n licenseUri: packageJson.license ? Util.licenseToUri(packageJson.license) : null,\n reportUri: null,\n specificationUris: [],\n version: packageJson.version,\n };\n }\n}\n\nexport interface IEarlProperties {\n reportUri: string;\n authors: IAuthor[];\n licenseUri: string;\n applicationUri: string;\n applicationHomepageUrl: string;\n applicationBugsUrl?: string;\n applicationBlogUrl?: string;\n applicationNameFull: string;\n applicationNameNpm: string;\n applicationDescription: string;\n specificationUris: string[];\n version?: string;\n}\n\nexport interface IAuthor {\n uri: string;\n name?: string;\n homepage?: string;\n primaryTopic?: string;\n}\n\nexport interface ITestResult extends ITestResultOverride {\n test: ITestCase<any>;\n ok: boolean;\n error?: Error;\n skipped?: boolean;\n}\n\nexport interface ITestResultOverride {\n duration?: number; // In ms\n}\n"]}
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"resultCardinality": "mf:resultCardinality",
|
|
26
26
|
"requires": "mf:requires",
|
|
27
27
|
"expectedStatus": "mf:expectedStatus",
|
|
28
|
+
"expectedLocation": "mf:expectedLocation",
|
|
28
29
|
"expectedFormat": "mf:expectedFormat",
|
|
29
30
|
"expectedBoolean": "mf:expectedBoolean",
|
|
30
31
|
|
|
@@ -44,6 +45,7 @@
|
|
|
44
45
|
|
|
45
46
|
"ht": "http://www.w3.org/2011/http#",
|
|
46
47
|
"httpRequests": "ht:requests",
|
|
48
|
+
"httpConnectionAuthority": "ht:connectionAuthority",
|
|
47
49
|
"httpAbsolutePath": "ht:absolutePath",
|
|
48
50
|
"httpMethodName": "ht:methodName",
|
|
49
51
|
"httpHeaders": "ht:headers",
|
|
@@ -8,13 +8,13 @@ const TestCaseJsonLdToRdfNegative_1 = require("./rdfsyntax/jsonld/TestCaseJsonLd
|
|
|
8
8
|
const TestCaseEval_1 = require("./rdfsyntax/TestCaseEval");
|
|
9
9
|
const TestCaseSyntax_1 = require("./rdfsyntax/TestCaseSyntax");
|
|
10
10
|
const TestCaseCsvResultFormat_1 = require("./sparql/TestCaseCsvResultFormat");
|
|
11
|
+
const TestCaseGraphStoreProtocol_1 = require("./sparql/TestCaseGraphStoreProtocol");
|
|
11
12
|
const TestCaseNegativeSyntax_1 = require("./sparql/TestCaseNegativeSyntax");
|
|
12
13
|
const TestCasePositiveSyntax_1 = require("./sparql/TestCasePositiveSyntax");
|
|
13
14
|
const TestCaseProtocol_1 = require("./sparql/TestCaseProtocol");
|
|
14
15
|
const TestCaseQueryEvaluation_1 = require("./sparql/TestCaseQueryEvaluation");
|
|
15
16
|
const TestCaseServiceDescription_1 = require("./sparql/TestCaseServiceDescription");
|
|
16
17
|
const TestCaseUpdateEvaluation_1 = require("./sparql/TestCaseUpdateEvaluation");
|
|
17
|
-
const TestCaseUnsupported_1 = require("./TestCaseUnsupported");
|
|
18
18
|
module.exports = {
|
|
19
19
|
// SPARQL 1.0, SPARQL 1.1 test suite
|
|
20
20
|
'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#NegativeSyntaxTest': new TestCaseNegativeSyntax_1.TestCaseNegativeSyntaxHandler(),
|
|
@@ -31,7 +31,7 @@ module.exports = {
|
|
|
31
31
|
'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#CSVResultFormatTest': new TestCaseCsvResultFormat_1.TestCaseCsvResultFormatHandler(),
|
|
32
32
|
'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#ServiceDescriptionTest': new TestCaseServiceDescription_1.TestCaseServiceDescriptionHandler(),
|
|
33
33
|
'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#ProtocolTest': new TestCaseProtocol_1.TestCaseProtocolHandler(),
|
|
34
|
-
'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#GraphStoreProtocolTest': new
|
|
34
|
+
'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#GraphStoreProtocolTest': new TestCaseGraphStoreProtocol_1.TestCaseGraphStoreProtocolHandler(),
|
|
35
35
|
// RDF/XML test suite
|
|
36
36
|
'http://www.w3.org/ns/rdftest#TestXMLEval': new TestCaseEval_1.TestCaseEvalHandler(),
|
|
37
37
|
'http://www.w3.org/ns/rdftest#TestXMLNegativeSyntax': new TestCaseSyntax_1.TestCaseSyntaxHandler(false),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TestCaseHandlers.js","sourceRoot":"","sources":["TestCaseHandlers.ts"],"names":[],"mappings":";;AAAA,oFAAwF;AACxF,oGAAwG;AACxG,kFAAsF;AACtF,gFAAoF;AACpF,gGAAoG;AACpG,2DAA+D;AAC/D,+DAAmE;AACnE,8EAAkF;AAClF,4EAAgF;AAChF,4EAAgF;AAChF,gEAAoE;AACpE,8EAAkF;AAClF,oFAAwF;AACxF,gFAAoF;
|
|
1
|
+
{"version":3,"file":"TestCaseHandlers.js","sourceRoot":"","sources":["TestCaseHandlers.ts"],"names":[],"mappings":"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","sourcesContent":["import { TestCaseJsonLdFromRdfHandler } from './rdfsyntax/jsonld/TestCaseJsonLdFromRdf';\nimport { TestCaseJsonLdFromRdfNegativeHandler } from './rdfsyntax/jsonld/TestCaseJsonLdFromRdfNegative';\nimport { TestCaseJsonLdSyntaxHandler } from './rdfsyntax/jsonld/TestCaseJsonLdSyntax';\nimport { TestCaseJsonLdToRdfHandler } from './rdfsyntax/jsonld/TestCaseJsonLdToRdf';\nimport { TestCaseJsonLdToRdfNegativeHandler } from './rdfsyntax/jsonld/TestCaseJsonLdToRdfNegative';\nimport { TestCaseEvalHandler } from './rdfsyntax/TestCaseEval';\nimport { TestCaseSyntaxHandler } from './rdfsyntax/TestCaseSyntax';\nimport { TestCaseCsvResultFormatHandler } from './sparql/TestCaseCsvResultFormat';\nimport { TestCaseGraphStoreProtocolHandler } from './sparql/TestCaseGraphStoreProtocol';\nimport { TestCaseNegativeSyntaxHandler } from './sparql/TestCaseNegativeSyntax';\nimport { TestCasePositiveSyntaxHandler } from './sparql/TestCasePositiveSyntax';\nimport { TestCaseProtocolHandler } from './sparql/TestCaseProtocol';\nimport { TestCaseQueryEvaluationHandler } from './sparql/TestCaseQueryEvaluation';\nimport { TestCaseServiceDescriptionHandler } from './sparql/TestCaseServiceDescription';\nimport { TestCaseUpdateEvaluationHandler } from './sparql/TestCaseUpdateEvaluation';\n\nmodule.exports = {\n // SPARQL 1.0, SPARQL 1.1 test suite\n 'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#NegativeSyntaxTest':\n new TestCaseNegativeSyntaxHandler(),\n 'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#PositiveSyntaxTest':\n new TestCasePositiveSyntaxHandler(),\n 'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#NegativeUpdateSyntaxTest':\n new TestCaseNegativeSyntaxHandler(),\n 'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#PositiveUpdateSyntaxTest':\n new TestCasePositiveSyntaxHandler(),\n 'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#QueryEvaluationTest':\n new TestCaseQueryEvaluationHandler(),\n\n // SPARQL 1.1 test suite\n 'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#NegativeSyntaxTest11':\n new TestCaseNegativeSyntaxHandler(),\n 'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#PositiveSyntaxTest11':\n new TestCasePositiveSyntaxHandler(),\n 'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#NegativeUpdateSyntaxTest11':\n new TestCaseNegativeSyntaxHandler(),\n 'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#PositiveUpdateSyntaxTest11':\n new TestCasePositiveSyntaxHandler(),\n 'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#UpdateEvaluationTest':\n new TestCaseUpdateEvaluationHandler(),\n 'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#CSVResultFormatTest':\n new TestCaseCsvResultFormatHandler(),\n 'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#ServiceDescriptionTest':\n new TestCaseServiceDescriptionHandler(),\n 'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#ProtocolTest':\n new TestCaseProtocolHandler(),\n 'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#GraphStoreProtocolTest':\n new TestCaseGraphStoreProtocolHandler(),\n\n // RDF/XML test suite\n 'http://www.w3.org/ns/rdftest#TestXMLEval':\n new TestCaseEvalHandler(),\n 'http://www.w3.org/ns/rdftest#TestXMLNegativeSyntax':\n new TestCaseSyntaxHandler(false),\n\n // N-Triples test suite\n 'http://www.w3.org/ns/rdftest#TestNTriplesPositiveSyntax':\n new TestCaseSyntaxHandler(true),\n 'http://www.w3.org/ns/rdftest#TestNTriplesNegativeSyntax':\n new TestCaseSyntaxHandler(false),\n\n // N-Quads test suite\n 'http://www.w3.org/ns/rdftest#TestNQuadsPositiveSyntax':\n new TestCaseSyntaxHandler(true),\n 'http://www.w3.org/ns/rdftest#TestNQuadsNegativeSyntax':\n new TestCaseSyntaxHandler(false),\n\n // Turtle test suite\n 'http://www.w3.org/ns/rdftest#TestTurtleEval':\n new TestCaseEvalHandler(),\n 'http://www.w3.org/ns/rdftest#TestTurtlePositiveSyntax':\n new TestCaseSyntaxHandler(true),\n 'http://www.w3.org/ns/rdftest#TestTurtleNegativeSyntax':\n new TestCaseSyntaxHandler(false),\n 'http://www.w3.org/ns/rdftest#TestTurtleNegativeEval':\n new TestCaseSyntaxHandler(false),\n\n // TriG test suite\n 'http://www.w3.org/ns/rdftest#TestTrigEval':\n new TestCaseEvalHandler(),\n 'http://www.w3.org/ns/rdftest#TestTrigPositiveSyntax':\n new TestCaseSyntaxHandler(true),\n 'http://www.w3.org/ns/rdftest#TestTrigNegativeSyntax':\n new TestCaseSyntaxHandler(false),\n 'http://www.w3.org/ns/rdftest#TestTrigNegativeEval':\n new TestCaseSyntaxHandler(false),\n\n // JSON-LD test suite\n 'https://w3c.github.io/json-ld-api/tests/vocab#ToRDFTest https://w3c.github.io/json-ld-api/tests/vocab#PositiveEvaluationTest':\n new TestCaseJsonLdToRdfHandler(),\n 'https://w3c.github.io/json-ld-api/tests/vocab#ToRDFTest https://w3c.github.io/json-ld-api/tests/vocab#PositiveSyntaxTest':\n new TestCaseJsonLdSyntaxHandler(true),\n 'https://w3c.github.io/json-ld-api/tests/vocab#ToRDFTest https://w3c.github.io/json-ld-api/tests/vocab#NegativeEvaluationTest':\n new TestCaseJsonLdToRdfNegativeHandler(),\n 'https://w3c.github.io/json-ld-api/tests/vocab#FromRDFTest https://w3c.github.io/json-ld-api/tests/vocab#PositiveEvaluationTest':\n new TestCaseJsonLdFromRdfHandler(),\n 'https://w3c.github.io/json-ld-api/tests/vocab#FromRDFTest https://w3c.github.io/json-ld-api/tests/vocab#NegativeEvaluationTest':\n new TestCaseJsonLdFromRdfNegativeHandler(),\n\n // RDFa test suite\n 'http://rdfa.info/vocabs/rdfa-test#PositiveEvaluationTest':\n new TestCaseEvalHandler(),\n 'http://rdfa.info/vocabs/rdfa-test#NegativeEvaluationTest':\n new TestCaseSyntaxHandler(true), // RDFa test suite never expect errors, just empty documents\n\n // Microdata-RDF test suite\n 'http://www.w3.org/ns/rdftest#TestMicrodataEval':\n new TestCaseEvalHandler({ normalizeUrl: true }),\n 'http://www.w3.org/ns/rdftest#TestMicrodataNegativeSyntax':\n new TestCaseSyntaxHandler(true), // Microdata-RDF test suite never expect errors, just empty documents\n\n // N3 test suite\n 'https://w3c.github.io/N3/tests/test.n3#TestN3PositiveSyntax':\n new TestCaseSyntaxHandler(true),\n 'https://w3c.github.io/N3/tests/test.n3#TestN3NegativeSyntax':\n new TestCaseSyntaxHandler(false),\n 'https://w3c.github.io/N3/tests/test.n3#TestN3Eval':\n new TestCaseEvalHandler(),\n\n};\n"]}
|
|
@@ -16,6 +16,11 @@ export interface IServiceDescriptionEndpoint extends ISparqlEndpoint {
|
|
|
16
16
|
*/
|
|
17
17
|
export interface IProtocolEndpoint extends ISparqlEndpoint {
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* A running endpoint for SPARQL Graph Store Protocol conformance tests.
|
|
21
|
+
*/
|
|
22
|
+
export interface IGraphStoreEndpoint extends ISparqlEndpoint {
|
|
23
|
+
}
|
|
19
24
|
/**
|
|
20
25
|
* A query engine handler.
|
|
21
26
|
*/
|
|
@@ -25,6 +30,7 @@ export interface IQueryEngine {
|
|
|
25
30
|
queryResultFormat?: (data: RDF.Quad[], queryString: string, mediaType: string, options: Record<string, any>) => Promise<NodeJS.ReadableStream>;
|
|
26
31
|
startServiceDescriptionEndpoint?: () => Promise<IServiceDescriptionEndpoint>;
|
|
27
32
|
startProtocolEndpoint?: () => Promise<IProtocolEndpoint>;
|
|
33
|
+
startGraphStoreEndpoint?: () => Promise<IGraphStoreEndpoint>;
|
|
28
34
|
}
|
|
29
35
|
/**
|
|
30
36
|
* Super type for all query result types.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IQueryEngine.js","sourceRoot":"","sources":["IQueryEngine.ts"],"names":[],"mappings":"","sourcesContent":["import type * as RDF from '@rdfjs/types';\n\n/**\n * A running SPARQL endpoint that conformance tests are executed against.\n */\nexport interface ISparqlEndpoint {\n endpoint: string;\n close: () => Promise<void>;\n}\n\n/**\n * A running endpoint for Service Description conformance tests.\n */\nexport interface IServiceDescriptionEndpoint extends ISparqlEndpoint {}\n\n/**\n * A running endpoint for SPARQL Protocol conformance tests.\n */\nexport interface IProtocolEndpoint extends ISparqlEndpoint {}\n\n/**\n * A query engine handler.\n */\nexport interface IQueryEngine {\n parse: (queryString: string, options: Record<string, any>) => Promise<void>;\n query: (data: RDF.Quad[], queryString: string, options: Record<string, any>) => Promise<IQueryResult>;\n queryResultFormat?: (data: RDF.Quad[], queryString: string, mediaType: string, options: Record<string, any>) => Promise<NodeJS.ReadableStream>;\n startServiceDescriptionEndpoint?: () => Promise<IServiceDescriptionEndpoint>;\n startProtocolEndpoint?: () => Promise<IProtocolEndpoint>;\n}\n\n/**\n * Super type for all query result types.\n */\nexport type IQueryResult = IQueryResultBoolean | IQueryResultQuads | IQueryResultBindings;\n\n/**\n * Holds a boolean query result.\n */\nexport interface IQueryResultBoolean {\n type: 'boolean';\n value: boolean;\n equals: (that: IQueryResult, laxCardinality?: boolean) => boolean;\n toString: () => string;\n}\n\n/**\n * Holds quad-based query results.\n */\nexport interface IQueryResultQuads {\n type: 'quads';\n value: RDF.Quad[];\n equals: (that: IQueryResult, laxCardinality?: boolean) => boolean;\n toString: () => string;\n}\n\n/**\n * Holds bindings-based query results.\n */\nexport interface IQueryResultBindings {\n type: 'bindings';\n variables: string[];\n value: Record<string, RDF.Term>[];\n checkOrder: boolean;\n equals: (that: IQueryResult, laxCardinality?: boolean) => boolean;\n toString: () => string;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"IQueryEngine.js","sourceRoot":"","sources":["IQueryEngine.ts"],"names":[],"mappings":"","sourcesContent":["import type * as RDF from '@rdfjs/types';\n\n/**\n * A running SPARQL endpoint that conformance tests are executed against.\n */\nexport interface ISparqlEndpoint {\n endpoint: string;\n close: () => Promise<void>;\n}\n\n/**\n * A running endpoint for Service Description conformance tests.\n */\nexport interface IServiceDescriptionEndpoint extends ISparqlEndpoint {}\n\n/**\n * A running endpoint for SPARQL Protocol conformance tests.\n */\nexport interface IProtocolEndpoint extends ISparqlEndpoint {}\n\n/**\n * A running endpoint for SPARQL Graph Store Protocol conformance tests.\n */\nexport interface IGraphStoreEndpoint extends ISparqlEndpoint {}\n\n/**\n * A query engine handler.\n */\nexport interface IQueryEngine {\n parse: (queryString: string, options: Record<string, any>) => Promise<void>;\n query: (data: RDF.Quad[], queryString: string, options: Record<string, any>) => Promise<IQueryResult>;\n queryResultFormat?: (data: RDF.Quad[], queryString: string, mediaType: string, options: Record<string, any>) => Promise<NodeJS.ReadableStream>;\n startServiceDescriptionEndpoint?: () => Promise<IServiceDescriptionEndpoint>;\n startProtocolEndpoint?: () => Promise<IProtocolEndpoint>;\n startGraphStoreEndpoint?: () => Promise<IGraphStoreEndpoint>;\n}\n\n/**\n * Super type for all query result types.\n */\nexport type IQueryResult = IQueryResultBoolean | IQueryResultQuads | IQueryResultBindings;\n\n/**\n * Holds a boolean query result.\n */\nexport interface IQueryResultBoolean {\n type: 'boolean';\n value: boolean;\n equals: (that: IQueryResult, laxCardinality?: boolean) => boolean;\n toString: () => string;\n}\n\n/**\n * Holds quad-based query results.\n */\nexport interface IQueryResultQuads {\n type: 'quads';\n value: RDF.Quad[];\n equals: (that: IQueryResult, laxCardinality?: boolean) => boolean;\n toString: () => string;\n}\n\n/**\n * Holds bindings-based query results.\n */\nexport interface IQueryResultBindings {\n type: 'bindings';\n variables: string[];\n value: Record<string, RDF.Term>[];\n checkOrder: boolean;\n equals: (that: IQueryResult, laxCardinality?: boolean) => boolean;\n toString: () => string;\n}\n"]}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type * as RDF from '@rdfjs/types';
|
|
2
|
+
import type { Resource } from 'rdf-object';
|
|
3
|
+
import type { ITestCaseData } from '../ITestCase';
|
|
4
|
+
import type { ITestCaseHandler } from '../ITestCaseHandler';
|
|
5
|
+
import type { IQueryEngine } from './IQueryEngine';
|
|
6
|
+
import type { ITestCaseSparql } from './ITestCaseSparql';
|
|
7
|
+
import type { IHttpContent } from './TestCaseProtocol';
|
|
8
|
+
/**
|
|
9
|
+
* A single HTTP request of a graph store protocol test, together with its expected response.
|
|
10
|
+
*/
|
|
11
|
+
export interface IGraphStoreRequest {
|
|
12
|
+
absolutePath: string;
|
|
13
|
+
method: string;
|
|
14
|
+
headers: [string, string][];
|
|
15
|
+
body?: IHttpContent;
|
|
16
|
+
expectedStatuses: number[];
|
|
17
|
+
expectedStatusClasses: number[];
|
|
18
|
+
expectedLocation?: string;
|
|
19
|
+
expectedHeaders: [string, string][];
|
|
20
|
+
expectedBody?: IHttpContent;
|
|
21
|
+
}
|
|
22
|
+
export interface IGraphStoreProtocolTestOptions {
|
|
23
|
+
/** The SPARQL Graph Store Protocol endpoint that the requests are sent to. */
|
|
24
|
+
graphStoreEndpoint?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface ITestCaseGraphStoreProtocolProps {
|
|
27
|
+
requests: IGraphStoreRequest[];
|
|
28
|
+
requiredFeatures: string[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Test case handler for http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#GraphStoreProtocolTest.
|
|
32
|
+
*/
|
|
33
|
+
export declare class TestCaseGraphStoreProtocolHandler implements ITestCaseHandler<TestCaseGraphStoreProtocol> {
|
|
34
|
+
/**
|
|
35
|
+
* Interpret the ht:headers of a ht:Request or ht:Response.
|
|
36
|
+
* @param resource A ht:Request or ht:Response resource.
|
|
37
|
+
*/
|
|
38
|
+
static getHeaders(resource: Resource): [string, string][];
|
|
39
|
+
/**
|
|
40
|
+
* Interpret a cnt:ContentAsText resource.
|
|
41
|
+
* @param content A cnt:ContentAsText resource.
|
|
42
|
+
*/
|
|
43
|
+
static getContent(content: Resource): IHttpContent;
|
|
44
|
+
/**
|
|
45
|
+
* Interpret a mf:expectedStatus value as either a concrete status code or a status code class.
|
|
46
|
+
* @param status A mf:expectedStatus value.
|
|
47
|
+
* @param uri The URI of the test case the status belongs to, used for error reporting.
|
|
48
|
+
*/
|
|
49
|
+
static getExpectedStatus(status: string, uri: string): {
|
|
50
|
+
status?: number;
|
|
51
|
+
statusClass?: number;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Interpret a single ht:Request resource, together with the ht:Response it is expected to produce.
|
|
55
|
+
* @param request A ht:Request resource.
|
|
56
|
+
* @param uri The URI of the test case the request belongs to, used for error reporting.
|
|
57
|
+
*/
|
|
58
|
+
static getRequest(request: Resource, uri: string): IGraphStoreRequest;
|
|
59
|
+
resourceToTestCase(resource: Resource, testCaseData: ITestCaseData): Promise<TestCaseGraphStoreProtocol>;
|
|
60
|
+
}
|
|
61
|
+
export declare class TestCaseGraphStoreProtocol implements ITestCaseSparql {
|
|
62
|
+
readonly type = "sparql";
|
|
63
|
+
readonly approval: string;
|
|
64
|
+
readonly approvedBy: string;
|
|
65
|
+
readonly comment: string;
|
|
66
|
+
readonly types: string[];
|
|
67
|
+
readonly name: string;
|
|
68
|
+
readonly uri: string;
|
|
69
|
+
readonly requests: IGraphStoreRequest[];
|
|
70
|
+
readonly requiredFeatures: string[];
|
|
71
|
+
constructor(testCaseData: ITestCaseData, props: ITestCaseGraphStoreProtocolProps);
|
|
72
|
+
/**
|
|
73
|
+
* Determine the endpoint that the graph store protocol requests must be sent to.
|
|
74
|
+
* @param injectArguments The custom engine options.
|
|
75
|
+
*/
|
|
76
|
+
static getEndpoint(injectArguments: IGraphStoreProtocolTestOptions): string;
|
|
77
|
+
/**
|
|
78
|
+
* Replace the manifest path prefix of the given request path with the path of the endpoint under test.
|
|
79
|
+
* @param endpoint The endpoint under test.
|
|
80
|
+
* @param absolutePath A ht:absolutePath value.
|
|
81
|
+
*/
|
|
82
|
+
static resolveRequestUrl(endpoint: string, absolutePath: string): string;
|
|
83
|
+
/**
|
|
84
|
+
* Determine the class of the given HTTP status code, e.g. 2 for 204.
|
|
85
|
+
* @param status An HTTP status code.
|
|
86
|
+
*/
|
|
87
|
+
static statusClass(status: number): number;
|
|
88
|
+
/**
|
|
89
|
+
* Determine the media type of a content type header value, without any of its parameters.
|
|
90
|
+
* @param contentType A content type header value.
|
|
91
|
+
*/
|
|
92
|
+
static mediaType(contentType: string): string;
|
|
93
|
+
/**
|
|
94
|
+
* Replace all template variables in the given string with the values they have been bound to.
|
|
95
|
+
* @param value The string to fill the template variables in.
|
|
96
|
+
* @param templates The values of the template variables, indexed by variable.
|
|
97
|
+
*/
|
|
98
|
+
static fillTemplates(value: string, templates: Record<string, string>): string;
|
|
99
|
+
test(_engine: IQueryEngine, injectArguments: IGraphStoreProtocolTestOptions): Promise<void>;
|
|
100
|
+
/**
|
|
101
|
+
* Delete every graph that this test case addresses, so that it starts from a known state.
|
|
102
|
+
* The responses are ignored, as the graphs are not required to exist.
|
|
103
|
+
* @param endpoint The endpoint under test.
|
|
104
|
+
*/
|
|
105
|
+
protected clearGraphs(endpoint: string): Promise<void>;
|
|
106
|
+
/**
|
|
107
|
+
* Send a single request of this test case to the endpoint, and validate its response.
|
|
108
|
+
* @param endpoint The endpoint under test.
|
|
109
|
+
* @param request The request to send.
|
|
110
|
+
* @param templates The template variables bound by the previous requests, extended by this request.
|
|
111
|
+
*/
|
|
112
|
+
protected testRequest(endpoint: string, request: IGraphStoreRequest, templates: Record<string, string>): Promise<void>;
|
|
113
|
+
/**
|
|
114
|
+
* Validate that the status of a response is one of the statuses that the manifest expects.
|
|
115
|
+
* @param request The request that was sent.
|
|
116
|
+
* @param url The URL the request was sent to.
|
|
117
|
+
* @param status The status of the response.
|
|
118
|
+
* @param body The body of the response.
|
|
119
|
+
*/
|
|
120
|
+
protected validateStatus(request: IGraphStoreRequest, url: string, status: number, body: string): void;
|
|
121
|
+
/**
|
|
122
|
+
* Determine the location that a response points to, which subsequent requests in this test case refer to.
|
|
123
|
+
* @param request The request that was sent.
|
|
124
|
+
* @param url The URL the request was sent to.
|
|
125
|
+
* @param response The response that was received.
|
|
126
|
+
*/
|
|
127
|
+
static getLocation(request: IGraphStoreRequest, url: string, response: Response): string;
|
|
128
|
+
/**
|
|
129
|
+
* Validate that the headers of a response match the headers that the manifest expects.
|
|
130
|
+
* Content type parameters such as the character encoding are not compared.
|
|
131
|
+
* @param request The request that was sent.
|
|
132
|
+
* @param url The URL the request was sent to.
|
|
133
|
+
* @param response The response that was received.
|
|
134
|
+
*/
|
|
135
|
+
static validateHeaders(request: IGraphStoreRequest, url: string, response: Response): void;
|
|
136
|
+
/**
|
|
137
|
+
* Validate that the body of a response is isomorphic to the graph that the manifest expects.
|
|
138
|
+
* @param request The request that was sent.
|
|
139
|
+
* @param url The URL the request was sent to.
|
|
140
|
+
* @param response The response that was received.
|
|
141
|
+
* @param body The body of the response.
|
|
142
|
+
*/
|
|
143
|
+
static validateBody(request: IGraphStoreRequest, url: string, response: Response, body: string): Promise<void>;
|
|
144
|
+
/**
|
|
145
|
+
* Parse an RDF graph that was sent over HTTP.
|
|
146
|
+
* @param contentType The content type the graph is serialized in.
|
|
147
|
+
* @param url The URL that the graph is a representation of, which relative IRIs are resolved against.
|
|
148
|
+
* @param body The serialized graph.
|
|
149
|
+
* @param label The kind of body that is being parsed, used for error reporting.
|
|
150
|
+
*/
|
|
151
|
+
static parseBody(contentType: string, url: string, body: string, label: string): Promise<RDF.Quad[]>;
|
|
152
|
+
}
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.TestCaseGraphStoreProtocol = exports.TestCaseGraphStoreProtocolHandler = void 0;
|
|
13
|
+
const arrayify_stream_1 = require("arrayify-stream");
|
|
14
|
+
const rdf_isomorphic_1 = require("rdf-isomorphic");
|
|
15
|
+
const ErrorSkipped_1 = require("../../ErrorSkipped");
|
|
16
|
+
const ErrorTest_1 = require("../../ErrorTest");
|
|
17
|
+
const Util_1 = require("../../Util");
|
|
18
|
+
const TestCaseProtocol_1 = require("./TestCaseProtocol");
|
|
19
|
+
// eslint-disable-next-line ts/no-require-imports, ts/no-var-requires
|
|
20
|
+
const streamifyString = require('streamify-string');
|
|
21
|
+
const MF = 'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#';
|
|
22
|
+
/**
|
|
23
|
+
* The path prefix that every ht:absolutePath in the SPARQL 1.1 Graph Store Protocol manifest starts with.
|
|
24
|
+
* It is replaced by the path of the graph store endpoint under test.
|
|
25
|
+
*/
|
|
26
|
+
const MANIFEST_PATH_PREFIX = '/gsp';
|
|
27
|
+
const STATUS_CODE_CLASS_REGEX = /^http:\/\/www\.w3\.org\/2011\/http-statusCodes#StatusCode(\d)xx$/u;
|
|
28
|
+
const STATUS_CODE_PREFIX = 'http://www.w3.org/2011/http-statusCodes#';
|
|
29
|
+
/**
|
|
30
|
+
* The status codes of the HTTP status codes vocabulary that the manifests refer to by name.
|
|
31
|
+
*/
|
|
32
|
+
const STATUS_CODES = {
|
|
33
|
+
OK: 200,
|
|
34
|
+
Created: 201,
|
|
35
|
+
NoContent: 204,
|
|
36
|
+
NotFound: 404,
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* The features that an endpoint must support for a test to be applicable,
|
|
40
|
+
* as expressed through mf:requires in the manifest.
|
|
41
|
+
*/
|
|
42
|
+
const KNOWN_FEATURES = new Set([
|
|
43
|
+
`${MF}DirectGraphIdentification`,
|
|
44
|
+
`${MF}IndirectGraphIdentification`,
|
|
45
|
+
`${MF}POSTGraphCreation`,
|
|
46
|
+
]);
|
|
47
|
+
/**
|
|
48
|
+
* Test case handler for http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#GraphStoreProtocolTest.
|
|
49
|
+
*/
|
|
50
|
+
class TestCaseGraphStoreProtocolHandler {
|
|
51
|
+
/**
|
|
52
|
+
* Interpret the ht:headers of a ht:Request or ht:Response.
|
|
53
|
+
* @param resource A ht:Request or ht:Response resource.
|
|
54
|
+
*/
|
|
55
|
+
static getHeaders(resource) {
|
|
56
|
+
var _a;
|
|
57
|
+
const headers = [];
|
|
58
|
+
for (const headerList of resource.properties.httpHeaders) {
|
|
59
|
+
for (const header of (_a = headerList.list) !== null && _a !== void 0 ? _a : []) {
|
|
60
|
+
headers.push([header.property.httpFieldName.value, header.property.httpFieldValue.value]);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return headers;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Interpret a cnt:ContentAsText resource.
|
|
67
|
+
* @param content A cnt:ContentAsText resource.
|
|
68
|
+
*/
|
|
69
|
+
static getContent(content) {
|
|
70
|
+
return {
|
|
71
|
+
chars: content.property.contentChars.value,
|
|
72
|
+
characterEncoding: content.property.contentCharacterEncoding.value,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Interpret a mf:expectedStatus value as either a concrete status code or a status code class.
|
|
77
|
+
* @param status A mf:expectedStatus value.
|
|
78
|
+
* @param uri The URI of the test case the status belongs to, used for error reporting.
|
|
79
|
+
*/
|
|
80
|
+
static getExpectedStatus(status, uri) {
|
|
81
|
+
const classMatch = STATUS_CODE_CLASS_REGEX.exec(status);
|
|
82
|
+
if (classMatch) {
|
|
83
|
+
return { statusClass: Number.parseInt(classMatch[1], 10) };
|
|
84
|
+
}
|
|
85
|
+
if (status.startsWith(STATUS_CODE_PREFIX)) {
|
|
86
|
+
const code = STATUS_CODES[status.slice(STATUS_CODE_PREFIX.length)];
|
|
87
|
+
if (code) {
|
|
88
|
+
return { status: code };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
throw new Error(`Unsupported mf:expectedStatus ${status} in ${uri}`);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Interpret a single ht:Request resource, together with the ht:Response it is expected to produce.
|
|
95
|
+
* @param request A ht:Request resource.
|
|
96
|
+
* @param uri The URI of the test case the request belongs to, used for error reporting.
|
|
97
|
+
*/
|
|
98
|
+
static getRequest(request, uri) {
|
|
99
|
+
if (!request.property.httpAbsolutePath) {
|
|
100
|
+
throw new Error(`Missing ht:absolutePath in a ht:Request of ${uri}`);
|
|
101
|
+
}
|
|
102
|
+
if (!request.property.httpMethodName) {
|
|
103
|
+
throw new Error(`Missing ht:methodName in a ht:Request of ${uri}`);
|
|
104
|
+
}
|
|
105
|
+
if (!request.property.httpResponse) {
|
|
106
|
+
throw new Error(`Missing ht:resp in a ht:Request of ${uri}`);
|
|
107
|
+
}
|
|
108
|
+
const response = request.property.httpResponse;
|
|
109
|
+
const expectedStatuses = [];
|
|
110
|
+
const expectedStatusClasses = [];
|
|
111
|
+
for (const expected of response.properties.expectedStatus) {
|
|
112
|
+
const { status, statusClass } = TestCaseGraphStoreProtocolHandler.getExpectedStatus(expected.value, uri);
|
|
113
|
+
if (status === undefined) {
|
|
114
|
+
expectedStatusClasses.push(statusClass);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
expectedStatuses.push(status);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (expectedStatuses.length === 0 && expectedStatusClasses.length === 0) {
|
|
121
|
+
throw new Error(`Missing mf:expectedStatus in a ht:Response of ${uri}`);
|
|
122
|
+
}
|
|
123
|
+
return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ absolutePath: request.property.httpAbsolutePath.value, method: request.property.httpMethodName.value, headers: TestCaseGraphStoreProtocolHandler.getHeaders(request) }, request.property.httpBody && {
|
|
124
|
+
body: TestCaseGraphStoreProtocolHandler.getContent(request.property.httpBody),
|
|
125
|
+
}), { expectedStatuses,
|
|
126
|
+
expectedStatusClasses }), response.property.expectedLocation && { expectedLocation: response.property.expectedLocation.value }), { expectedHeaders: TestCaseGraphStoreProtocolHandler.getHeaders(response) }), response.property.httpBody && {
|
|
127
|
+
expectedBody: TestCaseGraphStoreProtocolHandler.getContent(response.property.httpBody),
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
resourceToTestCase(resource, testCaseData) {
|
|
131
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
132
|
+
var _a;
|
|
133
|
+
if (!resource.property.action) {
|
|
134
|
+
throw new Error(`Missing mf:action in ${resource}`);
|
|
135
|
+
}
|
|
136
|
+
const connection = resource.property.action;
|
|
137
|
+
if (!connection.property.httpRequests) {
|
|
138
|
+
throw new Error(`Missing ht:requests in mf:action of ${resource}`);
|
|
139
|
+
}
|
|
140
|
+
const requests = ((_a = connection.property.httpRequests.list) !== null && _a !== void 0 ? _a : [])
|
|
141
|
+
.map(request => TestCaseGraphStoreProtocolHandler.getRequest(request, resource.value));
|
|
142
|
+
if (requests.length === 0) {
|
|
143
|
+
throw new Error(`Missing ht:Request entries in ht:requests of ${resource}`);
|
|
144
|
+
}
|
|
145
|
+
return new TestCaseGraphStoreProtocol(testCaseData, {
|
|
146
|
+
requests,
|
|
147
|
+
requiredFeatures: resource.properties.requires.map(feature => feature.value),
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
exports.TestCaseGraphStoreProtocolHandler = TestCaseGraphStoreProtocolHandler;
|
|
153
|
+
class TestCaseGraphStoreProtocol {
|
|
154
|
+
constructor(testCaseData, props) {
|
|
155
|
+
this.type = 'sparql';
|
|
156
|
+
Object.assign(this, testCaseData);
|
|
157
|
+
Object.assign(this, props);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Determine the endpoint that the graph store protocol requests must be sent to.
|
|
161
|
+
* @param injectArguments The custom engine options.
|
|
162
|
+
*/
|
|
163
|
+
static getEndpoint(injectArguments) {
|
|
164
|
+
const endpoint = injectArguments && injectArguments.graphStoreEndpoint;
|
|
165
|
+
if (!endpoint) {
|
|
166
|
+
throw new ErrorTest_1.ErrorTest('Graph store protocol tests require an endpoint from startGraphStoreEndpoint or the graphStoreEndpoint option.');
|
|
167
|
+
}
|
|
168
|
+
return endpoint;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Replace the manifest path prefix of the given request path with the path of the endpoint under test.
|
|
172
|
+
* @param endpoint The endpoint under test.
|
|
173
|
+
* @param absolutePath A ht:absolutePath value.
|
|
174
|
+
*/
|
|
175
|
+
static resolveRequestUrl(endpoint, absolutePath) {
|
|
176
|
+
const suffix = absolutePath.slice(MANIFEST_PATH_PREFIX.length);
|
|
177
|
+
if (!absolutePath.startsWith(MANIFEST_PATH_PREFIX) || (suffix && !suffix.startsWith('/') && !suffix.startsWith('?'))) {
|
|
178
|
+
throw new ErrorTest_1.ErrorTest(`Expected the request path ${absolutePath} to start with ${MANIFEST_PATH_PREFIX}`);
|
|
179
|
+
}
|
|
180
|
+
return endpoint + suffix;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Determine the class of the given HTTP status code, e.g. 2 for 204.
|
|
184
|
+
* @param status An HTTP status code.
|
|
185
|
+
*/
|
|
186
|
+
static statusClass(status) {
|
|
187
|
+
return Math.floor(status / 100);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Determine the media type of a content type header value, without any of its parameters.
|
|
191
|
+
* @param contentType A content type header value.
|
|
192
|
+
*/
|
|
193
|
+
static mediaType(contentType) {
|
|
194
|
+
return contentType.split(';')[0].trim().toLowerCase();
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Replace all template variables in the given string with the values they have been bound to.
|
|
198
|
+
* @param value The string to fill the template variables in.
|
|
199
|
+
* @param templates The values of the template variables, indexed by variable.
|
|
200
|
+
*/
|
|
201
|
+
static fillTemplates(value, templates) {
|
|
202
|
+
return Object.entries(templates)
|
|
203
|
+
.reduce((filled, [variable, binding]) => filled.split(variable).join(binding), value);
|
|
204
|
+
}
|
|
205
|
+
test(_engine, injectArguments) {
|
|
206
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
207
|
+
const unsupported = this.requiredFeatures.filter(feature => !KNOWN_FEATURES.has(feature));
|
|
208
|
+
if (unsupported.length > 0) {
|
|
209
|
+
throw new ErrorSkipped_1.ErrorSkipped(`Unsupported graph store protocol features: ${unsupported.join(', ')}`);
|
|
210
|
+
}
|
|
211
|
+
const endpoint = TestCaseGraphStoreProtocol.getEndpoint(injectArguments);
|
|
212
|
+
yield this.clearGraphs(endpoint);
|
|
213
|
+
const templates = {};
|
|
214
|
+
for (const request of this.requests) {
|
|
215
|
+
yield this.testRequest(endpoint, request, templates);
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Delete every graph that this test case addresses, so that it starts from a known state.
|
|
221
|
+
* The responses are ignored, as the graphs are not required to exist.
|
|
222
|
+
* @param endpoint The endpoint under test.
|
|
223
|
+
*/
|
|
224
|
+
clearGraphs(endpoint) {
|
|
225
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
226
|
+
const variables = this.requests
|
|
227
|
+
.map(request => request.expectedLocation)
|
|
228
|
+
.filter((variable) => variable !== undefined);
|
|
229
|
+
const paths = new Set(this.requests
|
|
230
|
+
.map(request => request.absolutePath)
|
|
231
|
+
.filter(absolutePath => absolutePath !== MANIFEST_PATH_PREFIX)
|
|
232
|
+
.filter(absolutePath => !variables.some(variable => absolutePath.includes(variable))));
|
|
233
|
+
for (const absolutePath of paths) {
|
|
234
|
+
const url = TestCaseGraphStoreProtocol.resolveRequestUrl(endpoint, absolutePath);
|
|
235
|
+
try {
|
|
236
|
+
yield fetch(url, { method: 'DELETE' });
|
|
237
|
+
}
|
|
238
|
+
catch (_a) {
|
|
239
|
+
// The graphs are cleared on a best-effort basis, failures are reported by the test requests themselves
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Send a single request of this test case to the endpoint, and validate its response.
|
|
246
|
+
* @param endpoint The endpoint under test.
|
|
247
|
+
* @param request The request to send.
|
|
248
|
+
* @param templates The template variables bound by the previous requests, extended by this request.
|
|
249
|
+
*/
|
|
250
|
+
testRequest(endpoint, request, templates) {
|
|
251
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
252
|
+
const url = TestCaseGraphStoreProtocol
|
|
253
|
+
.resolveRequestUrl(endpoint, TestCaseGraphStoreProtocol.fillTemplates(request.absolutePath, templates));
|
|
254
|
+
let response;
|
|
255
|
+
try {
|
|
256
|
+
response = yield fetch(url, Object.assign({ method: request.method, headers: request.headers, redirect: 'manual' }, request.body && {
|
|
257
|
+
body: TestCaseProtocol_1.TestCaseProtocol.encodeBody(Object.assign(Object.assign({}, request.body), { chars: TestCaseGraphStoreProtocol.fillTemplates(request.body.chars, templates) })),
|
|
258
|
+
}));
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
throw new ErrorTest_1.ErrorTest(`Could not send a ${request.method} request to ${url}: ${error.message}`);
|
|
262
|
+
}
|
|
263
|
+
const body = yield response.text();
|
|
264
|
+
this.validateStatus(request, url, response.status, body);
|
|
265
|
+
if (request.expectedLocation) {
|
|
266
|
+
templates[request.expectedLocation] = TestCaseGraphStoreProtocol
|
|
267
|
+
.getLocation(request, url, response);
|
|
268
|
+
}
|
|
269
|
+
TestCaseGraphStoreProtocol.validateHeaders(request, url, response);
|
|
270
|
+
if (request.expectedBody) {
|
|
271
|
+
yield TestCaseGraphStoreProtocol.validateBody(request, url, response, body);
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Validate that the status of a response is one of the statuses that the manifest expects.
|
|
277
|
+
* @param request The request that was sent.
|
|
278
|
+
* @param url The URL the request was sent to.
|
|
279
|
+
* @param status The status of the response.
|
|
280
|
+
* @param body The body of the response.
|
|
281
|
+
*/
|
|
282
|
+
validateStatus(request, url, status, body) {
|
|
283
|
+
if (request.expectedStatuses.includes(status) ||
|
|
284
|
+
request.expectedStatusClasses.includes(TestCaseGraphStoreProtocol.statusClass(status))) {
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
const expected = [
|
|
288
|
+
...request.expectedStatuses.map(String),
|
|
289
|
+
...request.expectedStatusClasses.map(statusClass => `${statusClass}xx`),
|
|
290
|
+
];
|
|
291
|
+
throw new ErrorTest_1.ErrorTest(`Invalid response status for ${request.method} ${url}
|
|
292
|
+
|
|
293
|
+
Expected one of: ${expected.join(', ')}
|
|
294
|
+
|
|
295
|
+
Got: ${status}\n\n${body}`);
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Determine the location that a response points to, which subsequent requests in this test case refer to.
|
|
299
|
+
* @param request The request that was sent.
|
|
300
|
+
* @param url The URL the request was sent to.
|
|
301
|
+
* @param response The response that was received.
|
|
302
|
+
*/
|
|
303
|
+
static getLocation(request, url, response) {
|
|
304
|
+
const location = response.headers.get('location');
|
|
305
|
+
if (!location) {
|
|
306
|
+
throw new ErrorTest_1.ErrorTest(`Missing Location response header for ${request.method} ${url}`);
|
|
307
|
+
}
|
|
308
|
+
return new URL(location, url).href;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Validate that the headers of a response match the headers that the manifest expects.
|
|
312
|
+
* Content type parameters such as the character encoding are not compared.
|
|
313
|
+
* @param request The request that was sent.
|
|
314
|
+
* @param url The URL the request was sent to.
|
|
315
|
+
* @param response The response that was received.
|
|
316
|
+
*/
|
|
317
|
+
static validateHeaders(request, url, response) {
|
|
318
|
+
for (const [name, value] of request.expectedHeaders) {
|
|
319
|
+
const actual = response.headers.get(name);
|
|
320
|
+
const equal = name.toLowerCase() === 'content-type' && actual ?
|
|
321
|
+
TestCaseGraphStoreProtocol.mediaType(actual) === TestCaseGraphStoreProtocol.mediaType(value) :
|
|
322
|
+
actual === value;
|
|
323
|
+
if (!equal) {
|
|
324
|
+
throw new ErrorTest_1.ErrorTest(`Invalid ${name} response header for ${request.method} ${url}
|
|
325
|
+
|
|
326
|
+
Expected: ${value}
|
|
327
|
+
|
|
328
|
+
Got: ${actual}`);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Validate that the body of a response is isomorphic to the graph that the manifest expects.
|
|
334
|
+
* @param request The request that was sent.
|
|
335
|
+
* @param url The URL the request was sent to.
|
|
336
|
+
* @param response The response that was received.
|
|
337
|
+
* @param body The body of the response.
|
|
338
|
+
*/
|
|
339
|
+
static validateBody(request, url, response, body) {
|
|
340
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
341
|
+
var _a, _b, _c;
|
|
342
|
+
const expectedContentType = (_b = (_a = request.expectedHeaders
|
|
343
|
+
.find(([name]) => name.toLowerCase() === 'content-type')) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : '';
|
|
344
|
+
const expected = yield TestCaseGraphStoreProtocol
|
|
345
|
+
.parseBody(expectedContentType, url, request.expectedBody.chars, 'expected');
|
|
346
|
+
const actual = yield TestCaseGraphStoreProtocol
|
|
347
|
+
.parseBody((_c = response.headers.get('content-type')) !== null && _c !== void 0 ? _c : '', url, body, 'actual');
|
|
348
|
+
if (!(0, rdf_isomorphic_1.isomorphic)(expected, actual)) {
|
|
349
|
+
throw new ErrorTest_1.ErrorTest(`Invalid response body for ${request.method} ${url}
|
|
350
|
+
|
|
351
|
+
Expected: ${request.expectedBody.chars}
|
|
352
|
+
|
|
353
|
+
Got: ${body}`);
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Parse an RDF graph that was sent over HTTP.
|
|
359
|
+
* @param contentType The content type the graph is serialized in.
|
|
360
|
+
* @param url The URL that the graph is a representation of, which relative IRIs are resolved against.
|
|
361
|
+
* @param body The serialized graph.
|
|
362
|
+
* @param label The kind of body that is being parsed, used for error reporting.
|
|
363
|
+
*/
|
|
364
|
+
static parseBody(contentType, url, body, label) {
|
|
365
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
366
|
+
try {
|
|
367
|
+
return yield (0, arrayify_stream_1.arrayifyStream)(Util_1.Util.parseRdfRaw(contentType, url, streamifyString(body)));
|
|
368
|
+
}
|
|
369
|
+
catch (error) {
|
|
370
|
+
throw new ErrorTest_1.ErrorTest(`Could not parse the ${label} response body of ${url}: ${error.message}\n\n${body}`);
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
exports.TestCaseGraphStoreProtocol = TestCaseGraphStoreProtocol;
|
|
376
|
+
//# sourceMappingURL=TestCaseGraphStoreProtocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TestCaseGraphStoreProtocol.js","sourceRoot":"","sources":["TestCaseGraphStoreProtocol.ts"],"names":[],"mappings":"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","sourcesContent":["import type * as RDF from '@rdfjs/types';\nimport { arrayifyStream } from 'arrayify-stream';\nimport { isomorphic } from 'rdf-isomorphic';\nimport type { Resource } from 'rdf-object';\nimport { ErrorSkipped } from '../../ErrorSkipped';\nimport { ErrorTest } from '../../ErrorTest';\nimport { Util } from '../../Util';\nimport type { ITestCaseData } from '../ITestCase';\nimport type { ITestCaseHandler } from '../ITestCaseHandler';\nimport type { IQueryEngine } from './IQueryEngine';\nimport type { ITestCaseSparql } from './ITestCaseSparql';\nimport type { IHttpContent } from './TestCaseProtocol';\nimport { TestCaseProtocol } from './TestCaseProtocol';\n\n// eslint-disable-next-line ts/no-require-imports, ts/no-var-requires\nconst streamifyString = require('streamify-string');\n\nconst MF = 'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#';\n\n/**\n * The path prefix that every ht:absolutePath in the SPARQL 1.1 Graph Store Protocol manifest starts with.\n * It is replaced by the path of the graph store endpoint under test.\n */\nconst MANIFEST_PATH_PREFIX = '/gsp';\n\nconst STATUS_CODE_CLASS_REGEX = /^http:\\/\\/www\\.w3\\.org\\/2011\\/http-statusCodes#StatusCode(\\d)xx$/u;\n\nconst STATUS_CODE_PREFIX = 'http://www.w3.org/2011/http-statusCodes#';\n\n/**\n * The status codes of the HTTP status codes vocabulary that the manifests refer to by name.\n */\nconst STATUS_CODES: Record<string, number> = {\n OK: 200,\n Created: 201,\n NoContent: 204,\n NotFound: 404,\n};\n\n/**\n * The features that an endpoint must support for a test to be applicable,\n * as expressed through mf:requires in the manifest.\n */\nconst KNOWN_FEATURES = new Set([\n `${MF}DirectGraphIdentification`,\n `${MF}IndirectGraphIdentification`,\n `${MF}POSTGraphCreation`,\n]);\n\n/**\n * A single HTTP request of a graph store protocol test, together with its expected response.\n */\nexport interface IGraphStoreRequest {\n absolutePath: string;\n method: string;\n headers: [string, string][];\n body?: IHttpContent;\n expectedStatuses: number[];\n expectedStatusClasses: number[];\n expectedLocation?: string;\n expectedHeaders: [string, string][];\n expectedBody?: IHttpContent;\n}\n\nexport interface IGraphStoreProtocolTestOptions {\n /** The SPARQL Graph Store Protocol endpoint that the requests are sent to. */\n graphStoreEndpoint?: string;\n}\n\nexport interface ITestCaseGraphStoreProtocolProps {\n requests: IGraphStoreRequest[];\n requiredFeatures: string[];\n}\n\n/**\n * Test case handler for http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#GraphStoreProtocolTest.\n */\nexport class TestCaseGraphStoreProtocolHandler implements ITestCaseHandler<TestCaseGraphStoreProtocol> {\n /**\n * Interpret the ht:headers of a ht:Request or ht:Response.\n * @param resource A ht:Request or ht:Response resource.\n */\n public static getHeaders(resource: Resource): [string, string][] {\n const headers: [string, string][] = [];\n for (const headerList of resource.properties.httpHeaders) {\n for (const header of headerList.list ?? []) {\n headers.push([ header.property.httpFieldName.value, header.property.httpFieldValue.value ]);\n }\n }\n return headers;\n }\n\n /**\n * Interpret a cnt:ContentAsText resource.\n * @param content A cnt:ContentAsText resource.\n */\n public static getContent(content: Resource): IHttpContent {\n return {\n chars: content.property.contentChars.value,\n characterEncoding: content.property.contentCharacterEncoding.value,\n };\n }\n\n /**\n * Interpret a mf:expectedStatus value as either a concrete status code or a status code class.\n * @param status A mf:expectedStatus value.\n * @param uri The URI of the test case the status belongs to, used for error reporting.\n */\n public static getExpectedStatus(status: string, uri: string): { status?: number; statusClass?: number } {\n const classMatch = STATUS_CODE_CLASS_REGEX.exec(status);\n if (classMatch) {\n return { statusClass: Number.parseInt(classMatch[1], 10) };\n }\n if (status.startsWith(STATUS_CODE_PREFIX)) {\n const code = STATUS_CODES[status.slice(STATUS_CODE_PREFIX.length)];\n if (code) {\n return { status: code };\n }\n }\n throw new Error(`Unsupported mf:expectedStatus ${status} in ${uri}`);\n }\n\n /**\n * Interpret a single ht:Request resource, together with the ht:Response it is expected to produce.\n * @param request A ht:Request resource.\n * @param uri The URI of the test case the request belongs to, used for error reporting.\n */\n public static getRequest(request: Resource, uri: string): IGraphStoreRequest {\n if (!request.property.httpAbsolutePath) {\n throw new Error(`Missing ht:absolutePath in a ht:Request of ${uri}`);\n }\n if (!request.property.httpMethodName) {\n throw new Error(`Missing ht:methodName in a ht:Request of ${uri}`);\n }\n if (!request.property.httpResponse) {\n throw new Error(`Missing ht:resp in a ht:Request of ${uri}`);\n }\n const response = request.property.httpResponse;\n\n const expectedStatuses: number[] = [];\n const expectedStatusClasses: number[] = [];\n for (const expected of response.properties.expectedStatus) {\n const { status, statusClass } = TestCaseGraphStoreProtocolHandler.getExpectedStatus(expected.value, uri);\n if (status === undefined) {\n expectedStatusClasses.push(statusClass);\n } else {\n expectedStatuses.push(status);\n }\n }\n if (expectedStatuses.length === 0 && expectedStatusClasses.length === 0) {\n throw new Error(`Missing mf:expectedStatus in a ht:Response of ${uri}`);\n }\n\n return {\n absolutePath: request.property.httpAbsolutePath.value,\n method: request.property.httpMethodName.value,\n headers: TestCaseGraphStoreProtocolHandler.getHeaders(request),\n ...request.property.httpBody && {\n body: TestCaseGraphStoreProtocolHandler.getContent(request.property.httpBody),\n },\n expectedStatuses,\n expectedStatusClasses,\n ...response.property.expectedLocation && { expectedLocation: response.property.expectedLocation.value },\n expectedHeaders: TestCaseGraphStoreProtocolHandler.getHeaders(response),\n ...response.property.httpBody && {\n expectedBody: TestCaseGraphStoreProtocolHandler.getContent(response.property.httpBody),\n },\n };\n }\n\n public async resourceToTestCase(resource: Resource, testCaseData: ITestCaseData): Promise<TestCaseGraphStoreProtocol> {\n if (!resource.property.action) {\n throw new Error(`Missing mf:action in ${resource}`);\n }\n const connection = resource.property.action;\n if (!connection.property.httpRequests) {\n throw new Error(`Missing ht:requests in mf:action of ${resource}`);\n }\n\n const requests = (connection.property.httpRequests.list ?? [])\n .map(request => TestCaseGraphStoreProtocolHandler.getRequest(request, resource.value));\n if (requests.length === 0) {\n throw new Error(`Missing ht:Request entries in ht:requests of ${resource}`);\n }\n\n return new TestCaseGraphStoreProtocol(testCaseData, {\n requests,\n requiredFeatures: resource.properties.requires.map(feature => feature.value),\n });\n }\n}\n\nexport class TestCaseGraphStoreProtocol implements ITestCaseSparql {\n public readonly type = 'sparql';\n public readonly approval: string;\n public readonly approvedBy: string;\n public readonly comment: string;\n public readonly types: string[];\n public readonly name: string;\n public readonly uri: string;\n\n public readonly requests: IGraphStoreRequest[];\n public readonly requiredFeatures: string[];\n\n public constructor(testCaseData: ITestCaseData, props: ITestCaseGraphStoreProtocolProps) {\n Object.assign(this, testCaseData);\n Object.assign(this, props);\n }\n\n /**\n * Determine the endpoint that the graph store protocol requests must be sent to.\n * @param injectArguments The custom engine options.\n */\n public static getEndpoint(injectArguments: IGraphStoreProtocolTestOptions): string {\n const endpoint = injectArguments && injectArguments.graphStoreEndpoint;\n if (!endpoint) {\n throw new ErrorTest('Graph store protocol tests require an endpoint from startGraphStoreEndpoint or the graphStoreEndpoint option.');\n }\n return endpoint;\n }\n\n /**\n * Replace the manifest path prefix of the given request path with the path of the endpoint under test.\n * @param endpoint The endpoint under test.\n * @param absolutePath A ht:absolutePath value.\n */\n public static resolveRequestUrl(endpoint: string, absolutePath: string): string {\n const suffix = absolutePath.slice(MANIFEST_PATH_PREFIX.length);\n if (!absolutePath.startsWith(MANIFEST_PATH_PREFIX) || (suffix && !suffix.startsWith('/') && !suffix.startsWith('?'))) {\n throw new ErrorTest(`Expected the request path ${absolutePath} to start with ${MANIFEST_PATH_PREFIX}`);\n }\n return endpoint + suffix;\n }\n\n /**\n * Determine the class of the given HTTP status code, e.g. 2 for 204.\n * @param status An HTTP status code.\n */\n public static statusClass(status: number): number {\n return Math.floor(status / 100);\n }\n\n /**\n * Determine the media type of a content type header value, without any of its parameters.\n * @param contentType A content type header value.\n */\n public static mediaType(contentType: string): string {\n return contentType.split(';')[0].trim().toLowerCase();\n }\n\n /**\n * Replace all template variables in the given string with the values they have been bound to.\n * @param value The string to fill the template variables in.\n * @param templates The values of the template variables, indexed by variable.\n */\n public static fillTemplates(value: string, templates: Record<string, string>): string {\n return Object.entries(templates)\n .reduce((filled, [ variable, binding ]) => filled.split(variable).join(binding), value);\n }\n\n public async test(_engine: IQueryEngine, injectArguments: IGraphStoreProtocolTestOptions): Promise<void> {\n const unsupported = this.requiredFeatures.filter(feature => !KNOWN_FEATURES.has(feature));\n if (unsupported.length > 0) {\n throw new ErrorSkipped(`Unsupported graph store protocol features: ${unsupported.join(', ')}`);\n }\n\n const endpoint = TestCaseGraphStoreProtocol.getEndpoint(injectArguments);\n await this.clearGraphs(endpoint);\n\n const templates: Record<string, string> = {};\n for (const request of this.requests) {\n await this.testRequest(endpoint, request, templates);\n }\n }\n\n /**\n * Delete every graph that this test case addresses, so that it starts from a known state.\n * The responses are ignored, as the graphs are not required to exist.\n * @param endpoint The endpoint under test.\n */\n protected async clearGraphs(endpoint: string): Promise<void> {\n const variables = this.requests\n .map(request => request.expectedLocation)\n .filter((variable): variable is string => variable !== undefined);\n const paths = new Set(this.requests\n .map(request => request.absolutePath)\n .filter(absolutePath => absolutePath !== MANIFEST_PATH_PREFIX)\n .filter(absolutePath => !variables.some(variable => absolutePath.includes(variable))));\n\n for (const absolutePath of paths) {\n const url = TestCaseGraphStoreProtocol.resolveRequestUrl(endpoint, absolutePath);\n try {\n await fetch(url, { method: 'DELETE' });\n } catch {\n // The graphs are cleared on a best-effort basis, failures are reported by the test requests themselves\n }\n }\n }\n\n /**\n * Send a single request of this test case to the endpoint, and validate its response.\n * @param endpoint The endpoint under test.\n * @param request The request to send.\n * @param templates The template variables bound by the previous requests, extended by this request.\n */\n protected async testRequest(\n endpoint: string,\n request: IGraphStoreRequest,\n templates: Record<string, string>,\n ): Promise<void> {\n const url = TestCaseGraphStoreProtocol\n .resolveRequestUrl(endpoint, TestCaseGraphStoreProtocol.fillTemplates(request.absolutePath, templates));\n let response: Response;\n try {\n response = await fetch(url, {\n method: request.method,\n headers: request.headers,\n redirect: 'manual',\n ...request.body && {\n body: TestCaseProtocol.encodeBody({\n ...request.body,\n chars: TestCaseGraphStoreProtocol.fillTemplates(request.body.chars, templates),\n }),\n },\n });\n } catch (error: unknown) {\n throw new ErrorTest(`Could not send a ${request.method} request to ${url}: ${(<Error> error).message}`);\n }\n const body = await response.text();\n\n this.validateStatus(request, url, response.status, body);\n if (request.expectedLocation) {\n templates[request.expectedLocation] = TestCaseGraphStoreProtocol\n .getLocation(request, url, response);\n }\n TestCaseGraphStoreProtocol.validateHeaders(request, url, response);\n if (request.expectedBody) {\n await TestCaseGraphStoreProtocol.validateBody(request, url, response, body);\n }\n }\n\n /**\n * Validate that the status of a response is one of the statuses that the manifest expects.\n * @param request The request that was sent.\n * @param url The URL the request was sent to.\n * @param status The status of the response.\n * @param body The body of the response.\n */\n protected validateStatus(request: IGraphStoreRequest, url: string, status: number, body: string): void {\n if (request.expectedStatuses.includes(status) ||\n request.expectedStatusClasses.includes(TestCaseGraphStoreProtocol.statusClass(status))) {\n return;\n }\n const expected = [\n ...request.expectedStatuses.map(String),\n ...request.expectedStatusClasses.map(statusClass => `${statusClass}xx`),\n ];\n throw new ErrorTest(`Invalid response status for ${request.method} ${url}\n\n Expected one of: ${expected.join(', ')}\n\n Got: ${status}\\n\\n${body}`);\n }\n\n /**\n * Determine the location that a response points to, which subsequent requests in this test case refer to.\n * @param request The request that was sent.\n * @param url The URL the request was sent to.\n * @param response The response that was received.\n */\n public static getLocation(request: IGraphStoreRequest, url: string, response: Response): string {\n const location = response.headers.get('location');\n if (!location) {\n throw new ErrorTest(`Missing Location response header for ${request.method} ${url}`);\n }\n return new URL(location, url).href;\n }\n\n /**\n * Validate that the headers of a response match the headers that the manifest expects.\n * Content type parameters such as the character encoding are not compared.\n * @param request The request that was sent.\n * @param url The URL the request was sent to.\n * @param response The response that was received.\n */\n public static validateHeaders(request: IGraphStoreRequest, url: string, response: Response): void {\n for (const [ name, value ] of request.expectedHeaders) {\n const actual = response.headers.get(name);\n const equal = name.toLowerCase() === 'content-type' && actual ?\n TestCaseGraphStoreProtocol.mediaType(actual) === TestCaseGraphStoreProtocol.mediaType(value) :\n actual === value;\n if (!equal) {\n throw new ErrorTest(`Invalid ${name} response header for ${request.method} ${url}\n\n Expected: ${value}\n\n Got: ${actual}`);\n }\n }\n }\n\n /**\n * Validate that the body of a response is isomorphic to the graph that the manifest expects.\n * @param request The request that was sent.\n * @param url The URL the request was sent to.\n * @param response The response that was received.\n * @param body The body of the response.\n */\n public static async validateBody(\n request: IGraphStoreRequest,\n url: string,\n response: Response,\n body: string,\n ): Promise<void> {\n const expectedContentType = request.expectedHeaders\n .find(([ name ]) => name.toLowerCase() === 'content-type')?.[1] ?? '';\n const expected = await TestCaseGraphStoreProtocol\n .parseBody(expectedContentType, url, request.expectedBody.chars, 'expected');\n const actual = await TestCaseGraphStoreProtocol\n .parseBody(response.headers.get('content-type') ?? '', url, body, 'actual');\n\n if (!isomorphic(expected, actual)) {\n throw new ErrorTest(`Invalid response body for ${request.method} ${url}\n\n Expected: ${request.expectedBody.chars}\n\n Got: ${body}`);\n }\n }\n\n /**\n * Parse an RDF graph that was sent over HTTP.\n * @param contentType The content type the graph is serialized in.\n * @param url The URL that the graph is a representation of, which relative IRIs are resolved against.\n * @param body The serialized graph.\n * @param label The kind of body that is being parsed, used for error reporting.\n */\n public static async parseBody(\n contentType: string,\n url: string,\n body: string,\n label: string,\n ): Promise<RDF.Quad[]> {\n try {\n return await arrayifyStream(Util.parseRdfRaw(contentType, url, streamifyString(body)));\n } catch (error: unknown) {\n throw new ErrorTest(`Could not parse the ${label} response body of ${url}: ${(<Error> error).message}\\n\\n${body}`);\n }\n }\n}\n"]}
|
|
@@ -10,6 +10,13 @@ export interface IProtocolTestOptions {
|
|
|
10
10
|
/** The SPARQL endpoint that the protocol requests are sent to. */
|
|
11
11
|
protocolEndpoint?: string;
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* The contents of an HTTP message body, as described by a cnt:ContentAsText resource.
|
|
15
|
+
*/
|
|
16
|
+
export interface IHttpContent {
|
|
17
|
+
chars: string;
|
|
18
|
+
characterEncoding: string;
|
|
19
|
+
}
|
|
13
20
|
/**
|
|
14
21
|
* A single HTTP request of a protocol test, together with its expected response.
|
|
15
22
|
*/
|
|
@@ -17,10 +24,7 @@ export interface IProtocolRequest {
|
|
|
17
24
|
absolutePath: string;
|
|
18
25
|
method: string;
|
|
19
26
|
headers: [string, string][];
|
|
20
|
-
body?:
|
|
21
|
-
chars: string;
|
|
22
|
-
characterEncoding: string;
|
|
23
|
-
};
|
|
27
|
+
body?: IHttpContent;
|
|
24
28
|
expectedStatusClasses: number[];
|
|
25
29
|
expectedFormat?: string;
|
|
26
30
|
expectedBoolean?: boolean;
|
|
@@ -90,13 +94,8 @@ export declare class TestCaseProtocol implements ITestCaseSparql {
|
|
|
90
94
|
/**
|
|
91
95
|
* Encode the body of a request in the character encoding that the manifest declares for it.
|
|
92
96
|
* @param body A ht:body value.
|
|
93
|
-
* @param body.chars The characters of the body.
|
|
94
|
-
* @param body.characterEncoding The character encoding to encode the body in.
|
|
95
97
|
*/
|
|
96
|
-
static encodeBody(body:
|
|
97
|
-
chars: string;
|
|
98
|
-
characterEncoding: string;
|
|
99
|
-
}): ArrayBuffer;
|
|
98
|
+
static encodeBody(body: IHttpContent): ArrayBuffer;
|
|
100
99
|
/**
|
|
101
100
|
* Validate that the content type of a response matches the format that the manifest expects.
|
|
102
101
|
* @param request The request that was sent.
|
|
@@ -232,8 +232,6 @@ class TestCaseProtocol {
|
|
|
232
232
|
/**
|
|
233
233
|
* Encode the body of a request in the character encoding that the manifest declares for it.
|
|
234
234
|
* @param body A ht:body value.
|
|
235
|
-
* @param body.chars The characters of the body.
|
|
236
|
-
* @param body.characterEncoding The character encoding to encode the body in.
|
|
237
235
|
*/
|
|
238
236
|
static encodeBody(body) {
|
|
239
237
|
const encoding = body.characterEncoding.toUpperCase();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TestCaseProtocol.js","sourceRoot":"","sources":["TestCaseProtocol.ts"],"names":[],"mappings":"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","sourcesContent":["import type * as RDF from '@rdfjs/types';\nimport type { Resource } from 'rdf-object';\nimport { termToString } from 'rdf-string-ttl';\nimport { ErrorTest } from '../../ErrorTest';\nimport type { IFetchOptions } from '../../Util';\nimport type { ITestCaseData } from '../ITestCase';\nimport type { ITestCaseHandler } from '../ITestCaseHandler';\nimport type { IQueryEngine, IQueryResultBoolean } from './IQueryEngine';\nimport type { ITestCaseSparql } from './ITestCaseSparql';\nimport type { IQueryDataLink } from './TestCaseQueryEvaluation';\nimport { TestCaseQueryEvaluationHandler } from './TestCaseQueryEvaluation';\nimport { TestCaseUpdateEvaluationHandler } from './TestCaseUpdateEvaluation';\n\n// eslint-disable-next-line ts/no-require-imports, ts/no-var-requires\nconst streamifyString = require('streamify-string');\n\n/**\n * The path prefix that every ht:absolutePath in the SPARQL 1.1 Protocol manifest starts with.\n * It is replaced by the path of the endpoint under test.\n */\nconst MANIFEST_PATH_PREFIX = '/sparql/';\n\nconst STATUS_CODE_CLASS_REGEX = /^http:\\/\\/www\\.w3\\.org\\/2011\\/http-statusCodes#StatusCode(\\d)xx$/u;\n\n/**\n * The content types that are considered valid for each of the mf:expectedFormat values.\n */\nconst EXPECTED_FORMAT_CONTENT_TYPES: Record<string, string[]> = {\n boolean: [\n 'application/sparql-results+json',\n 'application/sparql-results+xml',\n ],\n tabular: [\n 'application/sparql-results+json',\n 'application/sparql-results+xml',\n 'text/csv',\n 'text/tab-separated-values',\n ],\n RDF: [\n 'application/rdf+xml',\n 'text/turtle',\n 'application/x-turtle',\n 'application/n-triples',\n 'application/n-quads',\n 'application/trig',\n 'application/ld+json',\n ],\n};\n\nexport interface IProtocolTestOptions {\n /** The SPARQL endpoint that the protocol requests are sent to. */\n protocolEndpoint?: string;\n}\n\n/**\n * A single HTTP request of a protocol test, together with its expected response.\n */\nexport interface IProtocolRequest {\n absolutePath: string;\n method: string;\n headers: [string, string][];\n body?: { chars: string; characterEncoding: string };\n expectedStatusClasses: number[];\n expectedFormat?: string;\n expectedBoolean?: boolean;\n}\n\nexport interface ITestCaseProtocolProps {\n requests: IProtocolRequest[];\n graphData: RDF.Quad[];\n graphDataLinks: IQueryDataLink[];\n}\n\n/**\n * Test case handler for http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#ProtocolTest.\n */\nexport class TestCaseProtocolHandler implements ITestCaseHandler<TestCaseProtocol> {\n /**\n * Interpret a single ht:Request resource, together with the ht:Response it is expected to produce.\n * @param request A ht:Request resource.\n * @param uri The URI of the test case the request belongs to, used for error reporting.\n */\n public static getRequest(request: Resource, uri: string): IProtocolRequest {\n if (!request.property.httpAbsolutePath) {\n throw new Error(`Missing ht:absolutePath in a ht:Request of ${uri}`);\n }\n if (!request.property.httpMethodName) {\n throw new Error(`Missing ht:methodName in a ht:Request of ${uri}`);\n }\n if (!request.property.httpResponse) {\n throw new Error(`Missing ht:resp in a ht:Request of ${uri}`);\n }\n const response = request.property.httpResponse;\n\n const headers: [string, string][] = [];\n for (const headerList of request.properties.httpHeaders) {\n for (const header of headerList.list ?? []) {\n headers.push([ header.property.httpFieldName.value, header.property.httpFieldValue.value ]);\n }\n }\n\n const expectedStatusClasses = response.properties.expectedStatus\n .map((status) => {\n const match = STATUS_CODE_CLASS_REGEX.exec(status.value);\n if (!match) {\n throw new Error(`Unsupported mf:expectedStatus ${status.value} in ${uri}`);\n }\n return Number.parseInt(match[1], 10);\n });\n if (expectedStatusClasses.length === 0) {\n throw new Error(`Missing mf:expectedStatus in a ht:Response of ${uri}`);\n }\n\n return {\n absolutePath: request.property.httpAbsolutePath.value,\n method: request.property.httpMethodName.value,\n headers,\n ...request.property.httpBody && {\n body: {\n chars: request.property.httpBody.property.contentChars.value,\n characterEncoding: request.property.httpBody.property.contentCharacterEncoding.value,\n },\n },\n expectedStatusClasses,\n ...response.property.expectedFormat && { expectedFormat: response.property.expectedFormat.value },\n ...response.property.expectedBoolean && {\n expectedBoolean: response.property.expectedBoolean.value === 'true',\n },\n };\n }\n\n public async resourceToTestCase(resource: Resource, testCaseData: ITestCaseData, options?: IFetchOptions): Promise<TestCaseProtocol> {\n if (!resource.property.action) {\n throw new Error(`Missing mf:action in ${resource}`);\n }\n const connection = resource.property.action;\n if (!connection.property.httpRequests) {\n throw new Error(`Missing ht:requests in mf:action of ${resource}`);\n }\n\n const requests = (connection.property.httpRequests.list ?? [])\n .map(request => TestCaseProtocolHandler.getRequest(request, resource.value));\n if (requests.length === 0) {\n throw new Error(`Missing ht:Request entries in ht:requests of ${resource}`);\n }\n\n const graphDataLinks: IQueryDataLink[] = TestCaseUpdateEvaluationHandler.getQueryDataLinks(resource);\n\n return new TestCaseProtocol(testCaseData, {\n requests,\n graphData: await TestCaseQueryEvaluationHandler.resolveQueryDataLinks(graphDataLinks, options),\n graphDataLinks,\n });\n }\n}\n\nexport class TestCaseProtocol implements ITestCaseSparql {\n public readonly type = 'sparql';\n public readonly approval: string;\n public readonly approvedBy: string;\n public readonly comment: string;\n public readonly types: string[];\n public readonly name: string;\n public readonly uri: string;\n\n public readonly requests: IProtocolRequest[];\n public readonly graphData: RDF.Quad[];\n public readonly graphDataLinks: IQueryDataLink[];\n\n public constructor(testCaseData: ITestCaseData, props: ITestCaseProtocolProps) {\n Object.assign(this, testCaseData);\n Object.assign(this, props);\n }\n\n /**\n * Determine the endpoint that the protocol requests must be sent to.\n * @param injectArguments The custom engine options.\n */\n public static getEndpoint(injectArguments: IProtocolTestOptions): string {\n const endpoint = injectArguments && injectArguments.protocolEndpoint;\n if (!endpoint) {\n throw new ErrorTest('Protocol tests require an endpoint from startProtocolEndpoint or the protocolEndpoint option.');\n }\n return endpoint;\n }\n\n /**\n * Replace the manifest path prefix of the given request path with the path of the endpoint under test.\n * @param endpoint The endpoint under test.\n * @param absolutePath A ht:absolutePath value.\n */\n public static resolveRequestUrl(endpoint: string, absolutePath: string): string {\n if (!absolutePath.startsWith(MANIFEST_PATH_PREFIX)) {\n throw new ErrorTest(`Expected the request path ${absolutePath} to start with ${MANIFEST_PATH_PREFIX}`);\n }\n return endpoint + absolutePath.slice(MANIFEST_PATH_PREFIX.length);\n }\n\n /**\n * Serialize the given quads into a SPARQL update that resets the endpoint to just those quads.\n * @param quads The quads to load, which must all be contained in a named graph.\n */\n public static createLoadUpdate(quads: RDF.Quad[]): string {\n const graphs: Record<string, string[]> = {};\n for (const quad of quads) {\n const graph = termToString(quad.graph);\n const triple = `${termToString(quad.subject)} ${termToString(quad.predicate)} ${termToString(quad.object)} .`;\n (graphs[graph] ||= []).push(triple);\n }\n const groups = Object.entries(graphs)\n .map(([ graph, triples ]) => `GRAPH ${graph} { ${triples.join('\\n')} }`);\n return `DROP SILENT ALL ;\\nINSERT DATA { ${groups.join('\\n')} }`;\n }\n\n /**\n * Determine the class of the given HTTP status code, e.g. 2 for 204.\n * @param status An HTTP status code.\n */\n public static statusClass(status: number): number {\n return Math.floor(status / 100);\n }\n\n public async test(_engine: IQueryEngine, injectArguments: IProtocolTestOptions): Promise<void> {\n const endpoint = TestCaseProtocol.getEndpoint(injectArguments);\n\n if (this.graphData.length > 0) {\n await this.loadGraphData(endpoint);\n }\n\n for (const request of this.requests) {\n await this.testRequest(endpoint, request);\n }\n }\n\n /**\n * Load the ut:graphData of this test case into the endpoint via a SPARQL update.\n * @param endpoint The endpoint under test.\n */\n protected async loadGraphData(endpoint: string): Promise<void> {\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: { 'content-type': 'application/sparql-update' },\n body: TestCaseProtocol.createLoadUpdate(this.graphData),\n });\n const body = await response.text();\n if (!response.ok) {\n throw new ErrorTest(`Could not load the test data into ${endpoint} (HTTP ${response.status}): ${body}`);\n }\n }\n\n /**\n * Send a single request of this test case to the endpoint, and validate its response.\n * @param endpoint The endpoint under test.\n * @param request The request to send.\n */\n protected async testRequest(endpoint: string, request: IProtocolRequest): Promise<void> {\n const url = TestCaseProtocol.resolveRequestUrl(endpoint, request.absolutePath);\n let response: Response;\n try {\n response = await fetch(url, {\n method: request.method,\n headers: request.headers,\n redirect: 'manual',\n ...request.body && { body: TestCaseProtocol.encodeBody(request.body) },\n });\n } catch (error: unknown) {\n throw new ErrorTest(`Could not send a ${request.method} request to ${url}: ${(<Error> error).message}`);\n }\n const body = await response.text();\n\n if (!request.expectedStatusClasses.includes(TestCaseProtocol.statusClass(response.status))) {\n throw new ErrorTest(`Invalid response status for ${request.method} ${url}\n\n Expected one of: ${request.expectedStatusClasses.map(statusClass => `${statusClass}xx`).join(', ')}\n\n Got: ${response.status}\\n\\n${body}`);\n }\n\n const contentType = response.headers.get('content-type') ?? '';\n if (request.expectedFormat) {\n TestCaseProtocol.validateFormat(request, url, contentType);\n }\n if (request.expectedBoolean !== undefined) {\n await TestCaseProtocol.validateBoolean(request, url, contentType, body);\n }\n }\n\n /**\n * Encode the body of a request in the character encoding that the manifest declares for it.\n * @param body A ht:body value.\n * @param body.chars The characters of the body.\n * @param body.characterEncoding The character encoding to encode the body in.\n */\n public static encodeBody(body: { chars: string; characterEncoding: string }): ArrayBuffer {\n const encoding = body.characterEncoding.toUpperCase();\n if (encoding === 'UTF-8') {\n return new TextEncoder().encode(body.chars).buffer;\n }\n if (encoding === 'UTF-16') {\n return new Uint8Array(Buffer.from(`\\uFEFF${body.chars}`, 'utf16le')).buffer;\n }\n throw new ErrorTest(`Unsupported cnt:characterEncoding ${body.characterEncoding}`);\n }\n\n /**\n * Validate that the content type of a response matches the format that the manifest expects.\n * @param request The request that was sent.\n * @param url The URL the request was sent to.\n * @param contentType The content type of the response.\n */\n public static validateFormat(request: IProtocolRequest, url: string, contentType: string): void {\n const contentTypes = EXPECTED_FORMAT_CONTENT_TYPES[request.expectedFormat];\n if (!contentTypes) {\n throw new ErrorTest(`Unsupported mf:expectedFormat ${request.expectedFormat}`);\n }\n if (!contentTypes.some(expected => contentType.includes(expected))) {\n throw new ErrorTest(`Invalid response content type for ${request.method} ${url}\n\n Expected a ${request.expectedFormat} format, which is one of: ${contentTypes.join(', ')}\n\n Got: ${contentType}`);\n }\n }\n\n /**\n * Validate that the body of a response contains the boolean result that the manifest expects.\n * @param request The request that was sent.\n * @param url The URL the request was sent to.\n * @param contentType The content type of the response.\n * @param body The body of the response.\n */\n public static async validateBoolean(\n request: IProtocolRequest,\n url: string,\n contentType: string,\n body: string,\n ): Promise<void> {\n let result: IQueryResultBoolean;\n try {\n const parsed = await TestCaseQueryEvaluationHandler\n .parseQueryResult(contentType, url, streamifyString(body));\n if (parsed.type !== 'boolean') {\n throw new Error(`Expected a boolean result, but got a result of type ${parsed.type}`);\n }\n result = parsed;\n } catch (error: unknown) {\n throw new ErrorTest(`Could not read a boolean result from the response of ${request.method} ${url}: ${(<Error> error).message}\\n\\n${body}`);\n }\n if (result.value !== request.expectedBoolean) {\n throw new ErrorTest(`Invalid boolean response for ${request.method} ${url}\n\n Expected: ${request.expectedBoolean}\n\n Got: ${result.value}`);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"TestCaseProtocol.js","sourceRoot":"","sources":["TestCaseProtocol.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEA,mDAA8C;AAC9C,+CAA4C;AAO5C,uEAA2E;AAC3E,yEAA6E;AAE7E,qEAAqE;AACrE,MAAM,eAAe,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAEpD;;;GAGG;AACH,MAAM,oBAAoB,GAAG,UAAU,CAAC;AAExC,MAAM,uBAAuB,GAAG,mEAAmE,CAAC;AAEpG;;GAEG;AACH,MAAM,6BAA6B,GAA6B;IAC9D,OAAO,EAAE;QACP,iCAAiC;QACjC,gCAAgC;KACjC;IACD,OAAO,EAAE;QACP,iCAAiC;QACjC,gCAAgC;QAChC,UAAU;QACV,2BAA2B;KAC5B;IACD,GAAG,EAAE;QACH,qBAAqB;QACrB,aAAa;QACb,sBAAsB;QACtB,uBAAuB;QACvB,qBAAqB;QACrB,kBAAkB;QAClB,qBAAqB;KACtB;CACF,CAAC;AAkCF;;GAEG;AACH,MAAa,uBAAuB;IAClC;;;;OAIG;IACI,MAAM,CAAC,UAAU,CAAC,OAAiB,EAAE,GAAW;;QACrD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,8CAA8C,GAAG,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,4CAA4C,GAAG,EAAE,CAAC,CAAC;QACrE,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,sCAAsC,GAAG,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;QAE/C,MAAM,OAAO,GAAuB,EAAE,CAAC;QACvC,KAAK,MAAM,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;YACxD,KAAK,MAAM,MAAM,IAAI,MAAA,UAAU,CAAC,IAAI,mCAAI,EAAE,EAAE,CAAC;gBAC3C,OAAO,CAAC,IAAI,CAAC,CAAE,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAE,CAAC,CAAC;YAC9F,CAAC;QACH,CAAC;QAED,MAAM,qBAAqB,GAAG,QAAQ,CAAC,UAAU,CAAC,cAAc;aAC7D,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;YACd,MAAM,KAAK,GAAG,uBAAuB,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACzD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,KAAK,CAAC,iCAAiC,MAAM,CAAC,KAAK,OAAO,GAAG,EAAE,CAAC,CAAC;YAC7E,CAAC;YACD,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QACL,IAAI,qBAAqB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,iDAAiD,GAAG,EAAE,CAAC,CAAC;QAC1E,CAAC;QAED,iEACE,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,KAAK,EACrD,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,KAAK,EAC7C,OAAO,IACJ,OAAO,CAAC,QAAQ,CAAC,QAAQ,IAAI;YAC9B,IAAI,EAAE;gBACJ,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,KAAK;gBAC5D,iBAAiB,EAAE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,wBAAwB,CAAC,KAAK;aACrF;SACF,KACD,qBAAqB,KAClB,QAAQ,CAAC,QAAQ,CAAC,cAAc,IAAI,EAAE,cAAc,EAAE,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,KAAK,EAAE,GAC9F,QAAQ,CAAC,QAAQ,CAAC,eAAe,IAAI;YACtC,eAAe,EAAE,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC,KAAK,KAAK,MAAM;SACpE,EACD;IACJ,CAAC;IAEY,kBAAkB,CAAC,QAAkB,EAAE,YAA2B,EAAE,OAAuB;;;YACtG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;gBAC9B,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,EAAE,CAAC,CAAC;YACtD,CAAC;YACD,MAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC5C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;gBACtC,MAAM,IAAI,KAAK,CAAC,uCAAuC,QAAQ,EAAE,CAAC,CAAC;YACrE,CAAC;YAED,MAAM,QAAQ,GAAG,CAAC,MAAA,UAAU,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,mCAAI,EAAE,CAAC;iBAC3D,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,uBAAuB,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;YAC/E,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,gDAAgD,QAAQ,EAAE,CAAC,CAAC;YAC9E,CAAC;YAED,MAAM,cAAc,GAAqB,0DAA+B,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YAErG,OAAO,IAAI,gBAAgB,CAAC,YAAY,EAAE;gBACxC,QAAQ;gBACR,SAAS,EAAE,MAAM,wDAA8B,CAAC,qBAAqB,CAAC,cAAc,EAAE,OAAO,CAAC;gBAC9F,cAAc;aACf,CAAC,CAAC;QACL,CAAC;KAAA;CACF;AA9ED,0DA8EC;AAED,MAAa,gBAAgB;IAa3B,YAAmB,YAA2B,EAAE,KAA6B;QAZ7D,SAAI,GAAG,QAAQ,CAAC;QAa9B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED;;;OAGG;IACI,MAAM,CAAC,WAAW,CAAC,eAAqC;QAC7D,MAAM,QAAQ,GAAG,eAAe,IAAI,eAAe,CAAC,gBAAgB,CAAC;QACrE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,qBAAS,CAAC,+FAA+F,CAAC,CAAC;QACvH,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,iBAAiB,CAAC,QAAgB,EAAE,YAAoB;QACpE,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,oBAAoB,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,qBAAS,CAAC,6BAA6B,YAAY,kBAAkB,oBAAoB,EAAE,CAAC,CAAC;QACzG,CAAC;QACD,OAAO,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;IACpE,CAAC;IAED;;;OAGG;IACI,MAAM,CAAC,gBAAgB,CAAC,KAAiB;QAC9C,MAAM,MAAM,GAA6B,EAAE,CAAC;QAC5C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,KAAK,GAAG,IAAA,6BAAY,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACvC,MAAM,MAAM,GAAG,GAAG,IAAA,6BAAY,EAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAA,6BAAY,EAAC,IAAI,CAAC,SAAS,CAAC,IAAI,IAAA,6BAAY,EAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YAC9G,CAAC,MAAM,CAAC,KAAK,MAAZ,MAAM,CAAC,KAAK,IAAM,EAAE,EAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;aAClC,GAAG,CAAC,CAAC,CAAE,KAAK,EAAE,OAAO,CAAE,EAAE,EAAE,CAAC,SAAS,KAAK,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3E,OAAO,oCAAoC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACnE,CAAC;IAED;;;OAGG;IACI,MAAM,CAAC,WAAW,CAAC,MAAc;QACtC,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;IAClC,CAAC;IAEY,IAAI,CAAC,OAAqB,EAAE,eAAqC;;YAC5E,MAAM,QAAQ,GAAG,gBAAgB,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;YAE/D,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9B,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YACrC,CAAC;YAED,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACpC,MAAM,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;KAAA;IAED;;;OAGG;IACa,aAAa,CAAC,QAAgB;;YAC5C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE;gBACrC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,2BAA2B,EAAE;gBACxD,IAAI,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC;aACxD,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,qBAAS,CAAC,qCAAqC,QAAQ,UAAU,QAAQ,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;YAC1G,CAAC;QACH,CAAC;KAAA;IAED;;;;OAIG;IACa,WAAW,CAAC,QAAgB,EAAE,OAAyB;;;YACrE,MAAM,GAAG,GAAG,gBAAgB,CAAC,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;YAC/E,IAAI,QAAkB,CAAC;YACvB,IAAI,CAAC;gBACH,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,kBACxB,MAAM,EAAE,OAAO,CAAC,MAAM,EACtB,OAAO,EAAE,OAAO,CAAC,OAAO,EACxB,QAAQ,EAAE,QAAQ,IACf,OAAO,CAAC,IAAI,IAAI,EAAE,IAAI,EAAE,gBAAgB,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EACtE,CAAC;YACL,CAAC;YAAC,OAAO,KAAc,EAAE,CAAC;gBACxB,MAAM,IAAI,qBAAS,CAAC,oBAAoB,OAAO,CAAC,MAAM,eAAe,GAAG,KAAc,KAAM,CAAC,OAAO,EAAE,CAAC,CAAC;YAC1G,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAEnC,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,gBAAgB,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;gBAC3F,MAAM,IAAI,qBAAS,CAAC,+BAA+B,OAAO,CAAC,MAAM,IAAI,GAAG;;qBAEzD,OAAO,CAAC,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,GAAG,WAAW,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;SAE3F,QAAQ,CAAC,MAAM,OAAO,IAAI,EAAE,CAAC,CAAC;YACnC,CAAC;YAED,MAAM,WAAW,GAAG,MAAA,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,mCAAI,EAAE,CAAC;YAC/D,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;gBAC3B,gBAAgB,CAAC,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;YAC7D,CAAC;YACD,IAAI,OAAO,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;gBAC1C,MAAM,gBAAgB,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;KAAA;IAED;;;OAGG;IACI,MAAM,CAAC,UAAU,CAAC,IAAkB;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,CAAC,WAAW,EAAE,CAAC;QACtD,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;YACzB,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;QACrD,CAAC;QACD,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC1B,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;QAC9E,CAAC;QACD,MAAM,IAAI,qBAAS,CAAC,qCAAqC,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACrF,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,cAAc,CAAC,OAAyB,EAAE,GAAW,EAAE,WAAmB;QACtF,MAAM,YAAY,GAAG,6BAA6B,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAC3E,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,qBAAS,CAAC,iCAAiC,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;QACjF,CAAC;QACD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;YACnE,MAAM,IAAI,qBAAS,CAAC,qCAAqC,OAAO,CAAC,MAAM,IAAI,GAAG;;eAErE,OAAO,CAAC,cAAc,6BAA6B,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;;SAEhF,WAAW,EAAE,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACI,MAAM,CAAO,eAAe,CACjC,OAAyB,EACzB,GAAW,EACX,WAAmB,EACnB,IAAY;;YAEZ,IAAI,MAA2B,CAAC;YAChC,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,wDAA8B;qBAChD,gBAAgB,CAAC,WAAW,EAAE,GAAG,EAAE,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC7D,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;oBAC9B,MAAM,IAAI,KAAK,CAAC,uDAAuD,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;gBACxF,CAAC;gBACD,MAAM,GAAG,MAAM,CAAC;YAClB,CAAC;YAAC,OAAO,KAAc,EAAE,CAAC;gBACxB,MAAM,IAAI,qBAAS,CAAC,wDAAwD,OAAO,CAAC,MAAM,IAAI,GAAG,KAAc,KAAM,CAAC,OAAO,OAAO,IAAI,EAAE,CAAC,CAAC;YAC9I,CAAC;YACD,IAAI,MAAM,CAAC,KAAK,KAAK,OAAO,CAAC,eAAe,EAAE,CAAC;gBAC7C,MAAM,IAAI,qBAAS,CAAC,gCAAgC,OAAO,CAAC,MAAM,IAAI,GAAG;;cAEjE,OAAO,CAAC,eAAe;;SAE5B,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;KAAA;CACF;AAtMD,4CAsMC","sourcesContent":["import type * as RDF from '@rdfjs/types';\nimport type { Resource } from 'rdf-object';\nimport { termToString } from 'rdf-string-ttl';\nimport { ErrorTest } from '../../ErrorTest';\nimport type { IFetchOptions } from '../../Util';\nimport type { ITestCaseData } from '../ITestCase';\nimport type { ITestCaseHandler } from '../ITestCaseHandler';\nimport type { IQueryEngine, IQueryResultBoolean } from './IQueryEngine';\nimport type { ITestCaseSparql } from './ITestCaseSparql';\nimport type { IQueryDataLink } from './TestCaseQueryEvaluation';\nimport { TestCaseQueryEvaluationHandler } from './TestCaseQueryEvaluation';\nimport { TestCaseUpdateEvaluationHandler } from './TestCaseUpdateEvaluation';\n\n// eslint-disable-next-line ts/no-require-imports, ts/no-var-requires\nconst streamifyString = require('streamify-string');\n\n/**\n * The path prefix that every ht:absolutePath in the SPARQL 1.1 Protocol manifest starts with.\n * It is replaced by the path of the endpoint under test.\n */\nconst MANIFEST_PATH_PREFIX = '/sparql/';\n\nconst STATUS_CODE_CLASS_REGEX = /^http:\\/\\/www\\.w3\\.org\\/2011\\/http-statusCodes#StatusCode(\\d)xx$/u;\n\n/**\n * The content types that are considered valid for each of the mf:expectedFormat values.\n */\nconst EXPECTED_FORMAT_CONTENT_TYPES: Record<string, string[]> = {\n boolean: [\n 'application/sparql-results+json',\n 'application/sparql-results+xml',\n ],\n tabular: [\n 'application/sparql-results+json',\n 'application/sparql-results+xml',\n 'text/csv',\n 'text/tab-separated-values',\n ],\n RDF: [\n 'application/rdf+xml',\n 'text/turtle',\n 'application/x-turtle',\n 'application/n-triples',\n 'application/n-quads',\n 'application/trig',\n 'application/ld+json',\n ],\n};\n\nexport interface IProtocolTestOptions {\n /** The SPARQL endpoint that the protocol requests are sent to. */\n protocolEndpoint?: string;\n}\n\n/**\n * The contents of an HTTP message body, as described by a cnt:ContentAsText resource.\n */\nexport interface IHttpContent {\n chars: string;\n characterEncoding: string;\n}\n\n/**\n * A single HTTP request of a protocol test, together with its expected response.\n */\nexport interface IProtocolRequest {\n absolutePath: string;\n method: string;\n headers: [string, string][];\n body?: IHttpContent;\n expectedStatusClasses: number[];\n expectedFormat?: string;\n expectedBoolean?: boolean;\n}\n\nexport interface ITestCaseProtocolProps {\n requests: IProtocolRequest[];\n graphData: RDF.Quad[];\n graphDataLinks: IQueryDataLink[];\n}\n\n/**\n * Test case handler for http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#ProtocolTest.\n */\nexport class TestCaseProtocolHandler implements ITestCaseHandler<TestCaseProtocol> {\n /**\n * Interpret a single ht:Request resource, together with the ht:Response it is expected to produce.\n * @param request A ht:Request resource.\n * @param uri The URI of the test case the request belongs to, used for error reporting.\n */\n public static getRequest(request: Resource, uri: string): IProtocolRequest {\n if (!request.property.httpAbsolutePath) {\n throw new Error(`Missing ht:absolutePath in a ht:Request of ${uri}`);\n }\n if (!request.property.httpMethodName) {\n throw new Error(`Missing ht:methodName in a ht:Request of ${uri}`);\n }\n if (!request.property.httpResponse) {\n throw new Error(`Missing ht:resp in a ht:Request of ${uri}`);\n }\n const response = request.property.httpResponse;\n\n const headers: [string, string][] = [];\n for (const headerList of request.properties.httpHeaders) {\n for (const header of headerList.list ?? []) {\n headers.push([ header.property.httpFieldName.value, header.property.httpFieldValue.value ]);\n }\n }\n\n const expectedStatusClasses = response.properties.expectedStatus\n .map((status) => {\n const match = STATUS_CODE_CLASS_REGEX.exec(status.value);\n if (!match) {\n throw new Error(`Unsupported mf:expectedStatus ${status.value} in ${uri}`);\n }\n return Number.parseInt(match[1], 10);\n });\n if (expectedStatusClasses.length === 0) {\n throw new Error(`Missing mf:expectedStatus in a ht:Response of ${uri}`);\n }\n\n return {\n absolutePath: request.property.httpAbsolutePath.value,\n method: request.property.httpMethodName.value,\n headers,\n ...request.property.httpBody && {\n body: {\n chars: request.property.httpBody.property.contentChars.value,\n characterEncoding: request.property.httpBody.property.contentCharacterEncoding.value,\n },\n },\n expectedStatusClasses,\n ...response.property.expectedFormat && { expectedFormat: response.property.expectedFormat.value },\n ...response.property.expectedBoolean && {\n expectedBoolean: response.property.expectedBoolean.value === 'true',\n },\n };\n }\n\n public async resourceToTestCase(resource: Resource, testCaseData: ITestCaseData, options?: IFetchOptions): Promise<TestCaseProtocol> {\n if (!resource.property.action) {\n throw new Error(`Missing mf:action in ${resource}`);\n }\n const connection = resource.property.action;\n if (!connection.property.httpRequests) {\n throw new Error(`Missing ht:requests in mf:action of ${resource}`);\n }\n\n const requests = (connection.property.httpRequests.list ?? [])\n .map(request => TestCaseProtocolHandler.getRequest(request, resource.value));\n if (requests.length === 0) {\n throw new Error(`Missing ht:Request entries in ht:requests of ${resource}`);\n }\n\n const graphDataLinks: IQueryDataLink[] = TestCaseUpdateEvaluationHandler.getQueryDataLinks(resource);\n\n return new TestCaseProtocol(testCaseData, {\n requests,\n graphData: await TestCaseQueryEvaluationHandler.resolveQueryDataLinks(graphDataLinks, options),\n graphDataLinks,\n });\n }\n}\n\nexport class TestCaseProtocol implements ITestCaseSparql {\n public readonly type = 'sparql';\n public readonly approval: string;\n public readonly approvedBy: string;\n public readonly comment: string;\n public readonly types: string[];\n public readonly name: string;\n public readonly uri: string;\n\n public readonly requests: IProtocolRequest[];\n public readonly graphData: RDF.Quad[];\n public readonly graphDataLinks: IQueryDataLink[];\n\n public constructor(testCaseData: ITestCaseData, props: ITestCaseProtocolProps) {\n Object.assign(this, testCaseData);\n Object.assign(this, props);\n }\n\n /**\n * Determine the endpoint that the protocol requests must be sent to.\n * @param injectArguments The custom engine options.\n */\n public static getEndpoint(injectArguments: IProtocolTestOptions): string {\n const endpoint = injectArguments && injectArguments.protocolEndpoint;\n if (!endpoint) {\n throw new ErrorTest('Protocol tests require an endpoint from startProtocolEndpoint or the protocolEndpoint option.');\n }\n return endpoint;\n }\n\n /**\n * Replace the manifest path prefix of the given request path with the path of the endpoint under test.\n * @param endpoint The endpoint under test.\n * @param absolutePath A ht:absolutePath value.\n */\n public static resolveRequestUrl(endpoint: string, absolutePath: string): string {\n if (!absolutePath.startsWith(MANIFEST_PATH_PREFIX)) {\n throw new ErrorTest(`Expected the request path ${absolutePath} to start with ${MANIFEST_PATH_PREFIX}`);\n }\n return endpoint + absolutePath.slice(MANIFEST_PATH_PREFIX.length);\n }\n\n /**\n * Serialize the given quads into a SPARQL update that resets the endpoint to just those quads.\n * @param quads The quads to load, which must all be contained in a named graph.\n */\n public static createLoadUpdate(quads: RDF.Quad[]): string {\n const graphs: Record<string, string[]> = {};\n for (const quad of quads) {\n const graph = termToString(quad.graph);\n const triple = `${termToString(quad.subject)} ${termToString(quad.predicate)} ${termToString(quad.object)} .`;\n (graphs[graph] ||= []).push(triple);\n }\n const groups = Object.entries(graphs)\n .map(([ graph, triples ]) => `GRAPH ${graph} { ${triples.join('\\n')} }`);\n return `DROP SILENT ALL ;\\nINSERT DATA { ${groups.join('\\n')} }`;\n }\n\n /**\n * Determine the class of the given HTTP status code, e.g. 2 for 204.\n * @param status An HTTP status code.\n */\n public static statusClass(status: number): number {\n return Math.floor(status / 100);\n }\n\n public async test(_engine: IQueryEngine, injectArguments: IProtocolTestOptions): Promise<void> {\n const endpoint = TestCaseProtocol.getEndpoint(injectArguments);\n\n if (this.graphData.length > 0) {\n await this.loadGraphData(endpoint);\n }\n\n for (const request of this.requests) {\n await this.testRequest(endpoint, request);\n }\n }\n\n /**\n * Load the ut:graphData of this test case into the endpoint via a SPARQL update.\n * @param endpoint The endpoint under test.\n */\n protected async loadGraphData(endpoint: string): Promise<void> {\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: { 'content-type': 'application/sparql-update' },\n body: TestCaseProtocol.createLoadUpdate(this.graphData),\n });\n const body = await response.text();\n if (!response.ok) {\n throw new ErrorTest(`Could not load the test data into ${endpoint} (HTTP ${response.status}): ${body}`);\n }\n }\n\n /**\n * Send a single request of this test case to the endpoint, and validate its response.\n * @param endpoint The endpoint under test.\n * @param request The request to send.\n */\n protected async testRequest(endpoint: string, request: IProtocolRequest): Promise<void> {\n const url = TestCaseProtocol.resolveRequestUrl(endpoint, request.absolutePath);\n let response: Response;\n try {\n response = await fetch(url, {\n method: request.method,\n headers: request.headers,\n redirect: 'manual',\n ...request.body && { body: TestCaseProtocol.encodeBody(request.body) },\n });\n } catch (error: unknown) {\n throw new ErrorTest(`Could not send a ${request.method} request to ${url}: ${(<Error> error).message}`);\n }\n const body = await response.text();\n\n if (!request.expectedStatusClasses.includes(TestCaseProtocol.statusClass(response.status))) {\n throw new ErrorTest(`Invalid response status for ${request.method} ${url}\n\n Expected one of: ${request.expectedStatusClasses.map(statusClass => `${statusClass}xx`).join(', ')}\n\n Got: ${response.status}\\n\\n${body}`);\n }\n\n const contentType = response.headers.get('content-type') ?? '';\n if (request.expectedFormat) {\n TestCaseProtocol.validateFormat(request, url, contentType);\n }\n if (request.expectedBoolean !== undefined) {\n await TestCaseProtocol.validateBoolean(request, url, contentType, body);\n }\n }\n\n /**\n * Encode the body of a request in the character encoding that the manifest declares for it.\n * @param body A ht:body value.\n */\n public static encodeBody(body: IHttpContent): ArrayBuffer {\n const encoding = body.characterEncoding.toUpperCase();\n if (encoding === 'UTF-8') {\n return new TextEncoder().encode(body.chars).buffer;\n }\n if (encoding === 'UTF-16') {\n return new Uint8Array(Buffer.from(`\\uFEFF${body.chars}`, 'utf16le')).buffer;\n }\n throw new ErrorTest(`Unsupported cnt:characterEncoding ${body.characterEncoding}`);\n }\n\n /**\n * Validate that the content type of a response matches the format that the manifest expects.\n * @param request The request that was sent.\n * @param url The URL the request was sent to.\n * @param contentType The content type of the response.\n */\n public static validateFormat(request: IProtocolRequest, url: string, contentType: string): void {\n const contentTypes = EXPECTED_FORMAT_CONTENT_TYPES[request.expectedFormat];\n if (!contentTypes) {\n throw new ErrorTest(`Unsupported mf:expectedFormat ${request.expectedFormat}`);\n }\n if (!contentTypes.some(expected => contentType.includes(expected))) {\n throw new ErrorTest(`Invalid response content type for ${request.method} ${url}\n\n Expected a ${request.expectedFormat} format, which is one of: ${contentTypes.join(', ')}\n\n Got: ${contentType}`);\n }\n }\n\n /**\n * Validate that the body of a response contains the boolean result that the manifest expects.\n * @param request The request that was sent.\n * @param url The URL the request was sent to.\n * @param contentType The content type of the response.\n * @param body The body of the response.\n */\n public static async validateBoolean(\n request: IProtocolRequest,\n url: string,\n contentType: string,\n body: string,\n ): Promise<void> {\n let result: IQueryResultBoolean;\n try {\n const parsed = await TestCaseQueryEvaluationHandler\n .parseQueryResult(contentType, url, streamifyString(body));\n if (parsed.type !== 'boolean') {\n throw new Error(`Expected a boolean result, but got a result of type ${parsed.type}`);\n }\n result = parsed;\n } catch (error: unknown) {\n throw new ErrorTest(`Could not read a boolean result from the response of ${request.method} ${url}: ${(<Error> error).message}\\n\\n${body}`);\n }\n if (result.value !== request.expectedBoolean) {\n throw new ErrorTest(`Invalid boolean response for ${request.method} ${url}\n\n Expected: ${request.expectedBoolean}\n\n Got: ${result.value}`);\n }\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rdf-test-suite",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e",
|
|
5
5
|
"description": "Executes the RDF and SPARQL test suites.",
|
|
6
6
|
"typings": "index",
|