rdf-test-suite 2.6.0 → 2.7.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 +28 -12
- package/lib/TestSuiteRunner.js.map +1 -1
- package/lib/context-manifest.json +17 -0
- package/lib/testcase/TestCaseHandlers.js +2 -1
- package/lib/testcase/TestCaseHandlers.js.map +1 -1
- package/lib/testcase/sparql/IQueryEngine.d.ts +13 -2
- package/lib/testcase/sparql/IQueryEngine.js.map +1 -1
- package/lib/testcase/sparql/TestCaseProtocol.d.ts +115 -0
- package/lib/testcase/sparql/TestCaseProtocol.js +299 -0
- package/lib/testcase/sparql/TestCaseProtocol.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -253,6 +253,15 @@ $ rdf-test-suite myengine.js http://w3c.github.io/rdf-tests/sparql/sparql11/mani
|
|
|
253
253
|
-i '{ "serviceDescriptionEndpoint": "http://localhost:3000/sparql" }'
|
|
254
254
|
```
|
|
255
255
|
|
|
256
|
+
The SPARQL 1.1 Protocol tests work in the same way, through the optional
|
|
257
|
+
`startProtocolEndpoint` method and the `protocolEndpoint` option.
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
$ rdf-test-suite myengine.js http://w3c.github.io/rdf-tests/sparql/sparql11/manifest-all.ttl \
|
|
261
|
+
-s http://www.w3.org/TR/sparql11-protocol/ \
|
|
262
|
+
-i '{ "protocolEndpoint": "http://localhost:3000/sparql" }'
|
|
263
|
+
```
|
|
264
|
+
|
|
256
265
|
### Test timeouts
|
|
257
266
|
|
|
258
267
|
By default, all tests are allowed to run 3000 ms.
|
|
@@ -314,7 +323,7 @@ $ rdf-test-suite myengine.js https://w3c.github.io/rdf-tests/sparql/sparql11/man
|
|
|
314
323
|
| [SPARQL 1.1 tests](https://w3c.github.io/rdf-tests/sparql/sparql11/) | [SPARQL 1.1 Federated Query](http://www.w3.org/TR/sparql11-federated-query/) | ✖ | http://w3c.github.io/rdf-tests/sparql/sparql11/manifest-all.ttl |
|
|
315
324
|
| [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 |
|
|
316
325
|
| [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 |
|
|
317
|
-
| [SPARQL 1.1 tests](https://w3c.github.io/rdf-tests/sparql/sparql11/) | [SPARQL 1.1 Protocol](http://www.w3.org/TR/sparql11-protocol/) |
|
|
326
|
+
| [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 |
|
|
318
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/) | ✖ | http://w3c.github.io/rdf-tests/sparql/sparql11/manifest-all.ttl |
|
|
319
328
|
| [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 |
|
|
320
329
|
| [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 |
|
package/index.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export * from './lib/testcase/sparql/QueryResultQuads';
|
|
|
17
17
|
export * from './lib/testcase/sparql/TestCaseCsvResultFormat';
|
|
18
18
|
export * from './lib/testcase/sparql/TestCaseNegativeSyntax';
|
|
19
19
|
export * from './lib/testcase/sparql/TestCasePositiveSyntax';
|
|
20
|
+
export * from './lib/testcase/sparql/TestCaseProtocol';
|
|
20
21
|
export * from './lib/testcase/sparql/TestCaseQueryEvaluation';
|
|
21
22
|
export * from './lib/testcase/sparql/TestCaseServiceDescription';
|
|
22
23
|
export * from './lib/testcase/sparql/TestCaseUpdateEvaluation';
|
package/index.js
CHANGED
|
@@ -33,6 +33,7 @@ __exportStar(require("./lib/testcase/sparql/QueryResultQuads"), exports);
|
|
|
33
33
|
__exportStar(require("./lib/testcase/sparql/TestCaseCsvResultFormat"), exports);
|
|
34
34
|
__exportStar(require("./lib/testcase/sparql/TestCaseNegativeSyntax"), exports);
|
|
35
35
|
__exportStar(require("./lib/testcase/sparql/TestCasePositiveSyntax"), exports);
|
|
36
|
+
__exportStar(require("./lib/testcase/sparql/TestCaseProtocol"), exports);
|
|
36
37
|
__exportStar(require("./lib/testcase/sparql/TestCaseQueryEvaluation"), exports);
|
|
37
38
|
__exportStar(require("./lib/testcase/sparql/TestCaseServiceDescription"), exports);
|
|
38
39
|
__exportStar(require("./lib/testcase/sparql/TestCaseUpdateEvaluation"), 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,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/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,+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"]}
|
package/lib/TestSuiteRunner.js
CHANGED
|
@@ -52,7 +52,23 @@ const quad = require('rdf-quad');
|
|
|
52
52
|
// eslint-disable-next-line ts/no-require-imports, ts/no-var-requires
|
|
53
53
|
const streamifyArray = require('streamify-array').streamifyArray;
|
|
54
54
|
const DF = new rdf_data_factory_1.DataFactory();
|
|
55
|
-
|
|
55
|
+
/**
|
|
56
|
+
* The specifications that are tested against a running endpoint,
|
|
57
|
+
* together with the engine method that starts it,
|
|
58
|
+
* and the custom engine option that its URL is passed to.
|
|
59
|
+
*/
|
|
60
|
+
const ENDPOINT_SPECIFICATIONS = [
|
|
61
|
+
{
|
|
62
|
+
specification: 'http://www.w3.org/TR/sparql11-service-description/',
|
|
63
|
+
option: 'serviceDescriptionEndpoint',
|
|
64
|
+
start: engine => { var _a; return (_a = engine.startServiceDescriptionEndpoint) === null || _a === void 0 ? void 0 : _a.call(engine); },
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
specification: 'http://www.w3.org/TR/sparql11-protocol/',
|
|
68
|
+
option: 'protocolEndpoint',
|
|
69
|
+
start: engine => { var _a; return (_a = engine.startProtocolEndpoint) === null || _a === void 0 ? void 0 : _a.call(engine); },
|
|
70
|
+
},
|
|
71
|
+
];
|
|
56
72
|
/**
|
|
57
73
|
* TestSuiteRunner runs a certain test suite manifest.
|
|
58
74
|
*/
|
|
@@ -105,20 +121,20 @@ class TestSuiteRunner {
|
|
|
105
121
|
*/
|
|
106
122
|
runManifestWithEndpoint(manifest, handler, config, results) {
|
|
107
123
|
return __awaiter(this, void 0, void 0, function* () {
|
|
108
|
-
const engine = handler;
|
|
109
124
|
const customEngineOptions = config.customEngingeOptions;
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
finally {
|
|
117
|
-
yield serviceDescription.close();
|
|
118
|
-
}
|
|
125
|
+
const endpointSpecification = ENDPOINT_SPECIFICATIONS
|
|
126
|
+
.find(entry => entry.specification === config.specification && !customEngineOptions[entry.option]);
|
|
127
|
+
const endpoint = endpointSpecification ? yield endpointSpecification.start(handler) : undefined;
|
|
128
|
+
if (!endpoint) {
|
|
129
|
+
yield this.runManifestConcrete(manifest, handler, config, results);
|
|
119
130
|
return;
|
|
120
131
|
}
|
|
121
|
-
|
|
132
|
+
try {
|
|
133
|
+
yield this.runManifestConcrete(manifest, handler, Object.assign(Object.assign({}, config), { customEngingeOptions: Object.assign(Object.assign({}, customEngineOptions), { [endpointSpecification.option]: endpoint.endpoint }) }), results);
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
yield endpoint.close();
|
|
137
|
+
}
|
|
122
138
|
});
|
|
123
139
|
}
|
|
124
140
|
/**
|
|
@@ -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 } 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();\nconst SERVICE_DESCRIPTION_SPECIFICATION = 'http://www.w3.org/TR/sparql11-service-description/';\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 engine = <IQueryEngine> handler;\n const customEngineOptions = <Record<string, unknown>> config.customEngingeOptions;\n if (config.specification === SERVICE_DESCRIPTION_SPECIFICATION &&\n !customEngineOptions.serviceDescriptionEndpoint && engine.startServiceDescriptionEndpoint) {\n const serviceDescription = await engine.startServiceDescriptionEndpoint();\n try {\n await this.runManifestConcrete(manifest, handler, {\n ...config,\n customEngingeOptions: {\n ...customEngineOptions,\n serviceDescriptionEndpoint: serviceDescription.endpoint,\n },\n }, results);\n } finally {\n await serviceDescription.close();\n }\n return;\n }\n\n await this.runManifestConcrete(manifest, handler, config, results);\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\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"]}
|
|
@@ -24,6 +24,9 @@
|
|
|
24
24
|
"result": "mf:result",
|
|
25
25
|
"resultCardinality": "mf:resultCardinality",
|
|
26
26
|
"requires": "mf:requires",
|
|
27
|
+
"expectedStatus": "mf:expectedStatus",
|
|
28
|
+
"expectedFormat": "mf:expectedFormat",
|
|
29
|
+
"expectedBoolean": "mf:expectedBoolean",
|
|
27
30
|
|
|
28
31
|
"q": "http://www.w3.org/2001/sw/DataAccess/tests/test-query#",
|
|
29
32
|
"data": "q:data",
|
|
@@ -39,6 +42,20 @@
|
|
|
39
42
|
"updateGraph": "ut:graph",
|
|
40
43
|
"updateGraphData": "ut:graphData",
|
|
41
44
|
|
|
45
|
+
"ht": "http://www.w3.org/2011/http#",
|
|
46
|
+
"httpRequests": "ht:requests",
|
|
47
|
+
"httpAbsolutePath": "ht:absolutePath",
|
|
48
|
+
"httpMethodName": "ht:methodName",
|
|
49
|
+
"httpHeaders": "ht:headers",
|
|
50
|
+
"httpFieldName": "ht:fieldName",
|
|
51
|
+
"httpFieldValue": "ht:fieldValue",
|
|
52
|
+
"httpBody": "ht:body",
|
|
53
|
+
"httpResponse": "ht:resp",
|
|
54
|
+
|
|
55
|
+
"cnt": "http://www.w3.org/2011/content#",
|
|
56
|
+
"contentChars": "cnt:chars",
|
|
57
|
+
"contentCharacterEncoding": "cnt:characterEncoding",
|
|
58
|
+
|
|
42
59
|
"jld": "https://w3c.github.io/json-ld-api/tests/vocab#",
|
|
43
60
|
"jsonLdOptions": "jld:option",
|
|
44
61
|
"jsonLdProduceGeneralizedRdf": "jld:produceGeneralizedRdf",
|
|
@@ -10,6 +10,7 @@ const TestCaseSyntax_1 = require("./rdfsyntax/TestCaseSyntax");
|
|
|
10
10
|
const TestCaseCsvResultFormat_1 = require("./sparql/TestCaseCsvResultFormat");
|
|
11
11
|
const TestCaseNegativeSyntax_1 = require("./sparql/TestCaseNegativeSyntax");
|
|
12
12
|
const TestCasePositiveSyntax_1 = require("./sparql/TestCasePositiveSyntax");
|
|
13
|
+
const TestCaseProtocol_1 = require("./sparql/TestCaseProtocol");
|
|
13
14
|
const TestCaseQueryEvaluation_1 = require("./sparql/TestCaseQueryEvaluation");
|
|
14
15
|
const TestCaseServiceDescription_1 = require("./sparql/TestCaseServiceDescription");
|
|
15
16
|
const TestCaseUpdateEvaluation_1 = require("./sparql/TestCaseUpdateEvaluation");
|
|
@@ -29,7 +30,7 @@ module.exports = {
|
|
|
29
30
|
'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#UpdateEvaluationTest': new TestCaseUpdateEvaluation_1.TestCaseUpdateEvaluationHandler(),
|
|
30
31
|
'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#CSVResultFormatTest': new TestCaseCsvResultFormat_1.TestCaseCsvResultFormatHandler(),
|
|
31
32
|
'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#ServiceDescriptionTest': new TestCaseServiceDescription_1.TestCaseServiceDescriptionHandler(),
|
|
32
|
-
'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#ProtocolTest': new
|
|
33
|
+
'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#ProtocolTest': new TestCaseProtocol_1.TestCaseProtocolHandler(),
|
|
33
34
|
'http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#GraphStoreProtocolTest': new TestCaseUnsupported_1.TestCaseUnsupportedHandler('sparql:GraphStoreProtocolTest'), // TODO: implement
|
|
34
35
|
// RDF/XML test suite
|
|
35
36
|
'http://www.w3.org/ns/rdftest#TestXMLEval': new TestCaseEval_1.TestCaseEvalHandler(),
|
|
@@ -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,8EAAkF;AAClF,oFAAwF;AACxF,gFAAoF;AACpF,+DAAmE;AAEnE,MAAM,CAAC,OAAO,GAAG;IACf,oCAAoC;IACpC,6EAA6E,EAC3E,IAAI,sDAA6B,EAAE;IACrC,6EAA6E,EAC3E,IAAI,sDAA6B,EAAE;IACrC,mFAAmF,EACjF,IAAI,sDAA6B,EAAE;IACrC,mFAAmF,EACjF,IAAI,sDAA6B,EAAE;IACrC,8EAA8E,EAC5E,IAAI,wDAA8B,EAAE;IAEtC,wBAAwB;IACxB,+EAA+E,EAC7E,IAAI,sDAA6B,EAAE;IACrC,+EAA+E,EAC7E,IAAI,sDAA6B,EAAE;IACrC,qFAAqF,EACnF,IAAI,sDAA6B,EAAE;IACrC,qFAAqF,EACnF,IAAI,sDAA6B,EAAE;IACrC,+EAA+E,EAC7E,IAAI,0DAA+B,EAAE;IACvC,8EAA8E,EAC5E,IAAI,wDAA8B,EAAE;IACtC,iFAAiF,EAC/E,IAAI,8DAAiC,EAAE;IACzC,uEAAuE,EACrE,IAAI,
|
|
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 { 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';\nimport { TestCaseUnsupportedHandler } from './TestCaseUnsupported';\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 TestCaseUnsupportedHandler('sparql:GraphStoreProtocolTest'), // TODO: implement\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"]}
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import type * as RDF from '@rdfjs/types';
|
|
2
2
|
/**
|
|
3
|
-
* A running endpoint
|
|
3
|
+
* A running SPARQL endpoint that conformance tests are executed against.
|
|
4
4
|
*/
|
|
5
|
-
export interface
|
|
5
|
+
export interface ISparqlEndpoint {
|
|
6
6
|
endpoint: string;
|
|
7
7
|
close: () => Promise<void>;
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* A running endpoint for Service Description conformance tests.
|
|
11
|
+
*/
|
|
12
|
+
export interface IServiceDescriptionEndpoint extends ISparqlEndpoint {
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A running endpoint for SPARQL Protocol conformance tests.
|
|
16
|
+
*/
|
|
17
|
+
export interface IProtocolEndpoint extends ISparqlEndpoint {
|
|
18
|
+
}
|
|
9
19
|
/**
|
|
10
20
|
* A query engine handler.
|
|
11
21
|
*/
|
|
@@ -14,6 +24,7 @@ export interface IQueryEngine {
|
|
|
14
24
|
query: (data: RDF.Quad[], queryString: string, options: Record<string, any>) => Promise<IQueryResult>;
|
|
15
25
|
queryResultFormat?: (data: RDF.Quad[], queryString: string, mediaType: string, options: Record<string, any>) => Promise<NodeJS.ReadableStream>;
|
|
16
26
|
startServiceDescriptionEndpoint?: () => Promise<IServiceDescriptionEndpoint>;
|
|
27
|
+
startProtocolEndpoint?: () => Promise<IProtocolEndpoint>;
|
|
17
28
|
}
|
|
18
29
|
/**
|
|
19
30
|
* 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 endpoint
|
|
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"]}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type * as RDF from '@rdfjs/types';
|
|
2
|
+
import type { Resource } from 'rdf-object';
|
|
3
|
+
import type { IFetchOptions } from '../../Util';
|
|
4
|
+
import type { ITestCaseData } from '../ITestCase';
|
|
5
|
+
import type { ITestCaseHandler } from '../ITestCaseHandler';
|
|
6
|
+
import type { IQueryEngine } from './IQueryEngine';
|
|
7
|
+
import type { ITestCaseSparql } from './ITestCaseSparql';
|
|
8
|
+
import type { IQueryDataLink } from './TestCaseQueryEvaluation';
|
|
9
|
+
export interface IProtocolTestOptions {
|
|
10
|
+
/** The SPARQL endpoint that the protocol requests are sent to. */
|
|
11
|
+
protocolEndpoint?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A single HTTP request of a protocol test, together with its expected response.
|
|
15
|
+
*/
|
|
16
|
+
export interface IProtocolRequest {
|
|
17
|
+
absolutePath: string;
|
|
18
|
+
method: string;
|
|
19
|
+
headers: [string, string][];
|
|
20
|
+
body?: {
|
|
21
|
+
chars: string;
|
|
22
|
+
characterEncoding: string;
|
|
23
|
+
};
|
|
24
|
+
expectedStatusClasses: number[];
|
|
25
|
+
expectedFormat?: string;
|
|
26
|
+
expectedBoolean?: boolean;
|
|
27
|
+
}
|
|
28
|
+
export interface ITestCaseProtocolProps {
|
|
29
|
+
requests: IProtocolRequest[];
|
|
30
|
+
graphData: RDF.Quad[];
|
|
31
|
+
graphDataLinks: IQueryDataLink[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Test case handler for http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#ProtocolTest.
|
|
35
|
+
*/
|
|
36
|
+
export declare class TestCaseProtocolHandler implements ITestCaseHandler<TestCaseProtocol> {
|
|
37
|
+
/**
|
|
38
|
+
* Interpret a single ht:Request resource, together with the ht:Response it is expected to produce.
|
|
39
|
+
* @param request A ht:Request resource.
|
|
40
|
+
* @param uri The URI of the test case the request belongs to, used for error reporting.
|
|
41
|
+
*/
|
|
42
|
+
static getRequest(request: Resource, uri: string): IProtocolRequest;
|
|
43
|
+
resourceToTestCase(resource: Resource, testCaseData: ITestCaseData, options?: IFetchOptions): Promise<TestCaseProtocol>;
|
|
44
|
+
}
|
|
45
|
+
export declare class TestCaseProtocol implements ITestCaseSparql {
|
|
46
|
+
readonly type = "sparql";
|
|
47
|
+
readonly approval: string;
|
|
48
|
+
readonly approvedBy: string;
|
|
49
|
+
readonly comment: string;
|
|
50
|
+
readonly types: string[];
|
|
51
|
+
readonly name: string;
|
|
52
|
+
readonly uri: string;
|
|
53
|
+
readonly requests: IProtocolRequest[];
|
|
54
|
+
readonly graphData: RDF.Quad[];
|
|
55
|
+
readonly graphDataLinks: IQueryDataLink[];
|
|
56
|
+
constructor(testCaseData: ITestCaseData, props: ITestCaseProtocolProps);
|
|
57
|
+
/**
|
|
58
|
+
* Determine the endpoint that the protocol requests must be sent to.
|
|
59
|
+
* @param injectArguments The custom engine options.
|
|
60
|
+
*/
|
|
61
|
+
static getEndpoint(injectArguments: IProtocolTestOptions): string;
|
|
62
|
+
/**
|
|
63
|
+
* Replace the manifest path prefix of the given request path with the path of the endpoint under test.
|
|
64
|
+
* @param endpoint The endpoint under test.
|
|
65
|
+
* @param absolutePath A ht:absolutePath value.
|
|
66
|
+
*/
|
|
67
|
+
static resolveRequestUrl(endpoint: string, absolutePath: string): string;
|
|
68
|
+
/**
|
|
69
|
+
* Serialize the given quads into a SPARQL update that resets the endpoint to just those quads.
|
|
70
|
+
* @param quads The quads to load, which must all be contained in a named graph.
|
|
71
|
+
*/
|
|
72
|
+
static createLoadUpdate(quads: RDF.Quad[]): string;
|
|
73
|
+
/**
|
|
74
|
+
* Determine the class of the given HTTP status code, e.g. 2 for 204.
|
|
75
|
+
* @param status An HTTP status code.
|
|
76
|
+
*/
|
|
77
|
+
static statusClass(status: number): number;
|
|
78
|
+
test(_engine: IQueryEngine, injectArguments: IProtocolTestOptions): Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* Load the ut:graphData of this test case into the endpoint via a SPARQL update.
|
|
81
|
+
* @param endpoint The endpoint under test.
|
|
82
|
+
*/
|
|
83
|
+
protected loadGraphData(endpoint: string): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Send a single request of this test case to the endpoint, and validate its response.
|
|
86
|
+
* @param endpoint The endpoint under test.
|
|
87
|
+
* @param request The request to send.
|
|
88
|
+
*/
|
|
89
|
+
protected testRequest(endpoint: string, request: IProtocolRequest): Promise<void>;
|
|
90
|
+
/**
|
|
91
|
+
* Encode the body of a request in the character encoding that the manifest declares for it.
|
|
92
|
+
* @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
|
+
*/
|
|
96
|
+
static encodeBody(body: {
|
|
97
|
+
chars: string;
|
|
98
|
+
characterEncoding: string;
|
|
99
|
+
}): ArrayBuffer;
|
|
100
|
+
/**
|
|
101
|
+
* Validate that the content type of a response matches the format that the manifest expects.
|
|
102
|
+
* @param request The request that was sent.
|
|
103
|
+
* @param url The URL the request was sent to.
|
|
104
|
+
* @param contentType The content type of the response.
|
|
105
|
+
*/
|
|
106
|
+
static validateFormat(request: IProtocolRequest, url: string, contentType: string): void;
|
|
107
|
+
/**
|
|
108
|
+
* Validate that the body of a response contains the boolean result that the manifest expects.
|
|
109
|
+
* @param request The request that was sent.
|
|
110
|
+
* @param url The URL the request was sent to.
|
|
111
|
+
* @param contentType The content type of the response.
|
|
112
|
+
* @param body The body of the response.
|
|
113
|
+
*/
|
|
114
|
+
static validateBoolean(request: IProtocolRequest, url: string, contentType: string, body: string): Promise<void>;
|
|
115
|
+
}
|
|
@@ -0,0 +1,299 @@
|
|
|
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.TestCaseProtocol = exports.TestCaseProtocolHandler = void 0;
|
|
13
|
+
const rdf_string_ttl_1 = require("rdf-string-ttl");
|
|
14
|
+
const ErrorTest_1 = require("../../ErrorTest");
|
|
15
|
+
const TestCaseQueryEvaluation_1 = require("./TestCaseQueryEvaluation");
|
|
16
|
+
const TestCaseUpdateEvaluation_1 = require("./TestCaseUpdateEvaluation");
|
|
17
|
+
// eslint-disable-next-line ts/no-require-imports, ts/no-var-requires
|
|
18
|
+
const streamifyString = require('streamify-string');
|
|
19
|
+
/**
|
|
20
|
+
* The path prefix that every ht:absolutePath in the SPARQL 1.1 Protocol manifest starts with.
|
|
21
|
+
* It is replaced by the path of the endpoint under test.
|
|
22
|
+
*/
|
|
23
|
+
const MANIFEST_PATH_PREFIX = '/sparql/';
|
|
24
|
+
const STATUS_CODE_CLASS_REGEX = /^http:\/\/www\.w3\.org\/2011\/http-statusCodes#StatusCode(\d)xx$/u;
|
|
25
|
+
/**
|
|
26
|
+
* The content types that are considered valid for each of the mf:expectedFormat values.
|
|
27
|
+
*/
|
|
28
|
+
const EXPECTED_FORMAT_CONTENT_TYPES = {
|
|
29
|
+
boolean: [
|
|
30
|
+
'application/sparql-results+json',
|
|
31
|
+
'application/sparql-results+xml',
|
|
32
|
+
],
|
|
33
|
+
tabular: [
|
|
34
|
+
'application/sparql-results+json',
|
|
35
|
+
'application/sparql-results+xml',
|
|
36
|
+
'text/csv',
|
|
37
|
+
'text/tab-separated-values',
|
|
38
|
+
],
|
|
39
|
+
RDF: [
|
|
40
|
+
'application/rdf+xml',
|
|
41
|
+
'text/turtle',
|
|
42
|
+
'application/x-turtle',
|
|
43
|
+
'application/n-triples',
|
|
44
|
+
'application/n-quads',
|
|
45
|
+
'application/trig',
|
|
46
|
+
'application/ld+json',
|
|
47
|
+
],
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Test case handler for http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#ProtocolTest.
|
|
51
|
+
*/
|
|
52
|
+
class TestCaseProtocolHandler {
|
|
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, uri) {
|
|
59
|
+
var _a;
|
|
60
|
+
if (!request.property.httpAbsolutePath) {
|
|
61
|
+
throw new Error(`Missing ht:absolutePath in a ht:Request of ${uri}`);
|
|
62
|
+
}
|
|
63
|
+
if (!request.property.httpMethodName) {
|
|
64
|
+
throw new Error(`Missing ht:methodName in a ht:Request of ${uri}`);
|
|
65
|
+
}
|
|
66
|
+
if (!request.property.httpResponse) {
|
|
67
|
+
throw new Error(`Missing ht:resp in a ht:Request of ${uri}`);
|
|
68
|
+
}
|
|
69
|
+
const response = request.property.httpResponse;
|
|
70
|
+
const headers = [];
|
|
71
|
+
for (const headerList of request.properties.httpHeaders) {
|
|
72
|
+
for (const header of (_a = headerList.list) !== null && _a !== void 0 ? _a : []) {
|
|
73
|
+
headers.push([header.property.httpFieldName.value, header.property.httpFieldValue.value]);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const expectedStatusClasses = response.properties.expectedStatus
|
|
77
|
+
.map((status) => {
|
|
78
|
+
const match = STATUS_CODE_CLASS_REGEX.exec(status.value);
|
|
79
|
+
if (!match) {
|
|
80
|
+
throw new Error(`Unsupported mf:expectedStatus ${status.value} in ${uri}`);
|
|
81
|
+
}
|
|
82
|
+
return Number.parseInt(match[1], 10);
|
|
83
|
+
});
|
|
84
|
+
if (expectedStatusClasses.length === 0) {
|
|
85
|
+
throw new Error(`Missing mf:expectedStatus in a ht:Response of ${uri}`);
|
|
86
|
+
}
|
|
87
|
+
return Object.assign(Object.assign(Object.assign(Object.assign({ absolutePath: request.property.httpAbsolutePath.value, method: request.property.httpMethodName.value, headers }, request.property.httpBody && {
|
|
88
|
+
body: {
|
|
89
|
+
chars: request.property.httpBody.property.contentChars.value,
|
|
90
|
+
characterEncoding: request.property.httpBody.property.contentCharacterEncoding.value,
|
|
91
|
+
},
|
|
92
|
+
}), { expectedStatusClasses }), response.property.expectedFormat && { expectedFormat: response.property.expectedFormat.value }), response.property.expectedBoolean && {
|
|
93
|
+
expectedBoolean: response.property.expectedBoolean.value === 'true',
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
resourceToTestCase(resource, testCaseData, options) {
|
|
97
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
98
|
+
var _a;
|
|
99
|
+
if (!resource.property.action) {
|
|
100
|
+
throw new Error(`Missing mf:action in ${resource}`);
|
|
101
|
+
}
|
|
102
|
+
const connection = resource.property.action;
|
|
103
|
+
if (!connection.property.httpRequests) {
|
|
104
|
+
throw new Error(`Missing ht:requests in mf:action of ${resource}`);
|
|
105
|
+
}
|
|
106
|
+
const requests = ((_a = connection.property.httpRequests.list) !== null && _a !== void 0 ? _a : [])
|
|
107
|
+
.map(request => TestCaseProtocolHandler.getRequest(request, resource.value));
|
|
108
|
+
if (requests.length === 0) {
|
|
109
|
+
throw new Error(`Missing ht:Request entries in ht:requests of ${resource}`);
|
|
110
|
+
}
|
|
111
|
+
const graphDataLinks = TestCaseUpdateEvaluation_1.TestCaseUpdateEvaluationHandler.getQueryDataLinks(resource);
|
|
112
|
+
return new TestCaseProtocol(testCaseData, {
|
|
113
|
+
requests,
|
|
114
|
+
graphData: yield TestCaseQueryEvaluation_1.TestCaseQueryEvaluationHandler.resolveQueryDataLinks(graphDataLinks, options),
|
|
115
|
+
graphDataLinks,
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
exports.TestCaseProtocolHandler = TestCaseProtocolHandler;
|
|
121
|
+
class TestCaseProtocol {
|
|
122
|
+
constructor(testCaseData, props) {
|
|
123
|
+
this.type = 'sparql';
|
|
124
|
+
Object.assign(this, testCaseData);
|
|
125
|
+
Object.assign(this, props);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Determine the endpoint that the protocol requests must be sent to.
|
|
129
|
+
* @param injectArguments The custom engine options.
|
|
130
|
+
*/
|
|
131
|
+
static getEndpoint(injectArguments) {
|
|
132
|
+
const endpoint = injectArguments && injectArguments.protocolEndpoint;
|
|
133
|
+
if (!endpoint) {
|
|
134
|
+
throw new ErrorTest_1.ErrorTest('Protocol tests require an endpoint from startProtocolEndpoint or the protocolEndpoint option.');
|
|
135
|
+
}
|
|
136
|
+
return endpoint;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Replace the manifest path prefix of the given request path with the path of the endpoint under test.
|
|
140
|
+
* @param endpoint The endpoint under test.
|
|
141
|
+
* @param absolutePath A ht:absolutePath value.
|
|
142
|
+
*/
|
|
143
|
+
static resolveRequestUrl(endpoint, absolutePath) {
|
|
144
|
+
if (!absolutePath.startsWith(MANIFEST_PATH_PREFIX)) {
|
|
145
|
+
throw new ErrorTest_1.ErrorTest(`Expected the request path ${absolutePath} to start with ${MANIFEST_PATH_PREFIX}`);
|
|
146
|
+
}
|
|
147
|
+
return endpoint + absolutePath.slice(MANIFEST_PATH_PREFIX.length);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Serialize the given quads into a SPARQL update that resets the endpoint to just those quads.
|
|
151
|
+
* @param quads The quads to load, which must all be contained in a named graph.
|
|
152
|
+
*/
|
|
153
|
+
static createLoadUpdate(quads) {
|
|
154
|
+
const graphs = {};
|
|
155
|
+
for (const quad of quads) {
|
|
156
|
+
const graph = (0, rdf_string_ttl_1.termToString)(quad.graph);
|
|
157
|
+
const triple = `${(0, rdf_string_ttl_1.termToString)(quad.subject)} ${(0, rdf_string_ttl_1.termToString)(quad.predicate)} ${(0, rdf_string_ttl_1.termToString)(quad.object)} .`;
|
|
158
|
+
(graphs[graph] || (graphs[graph] = [])).push(triple);
|
|
159
|
+
}
|
|
160
|
+
const groups = Object.entries(graphs)
|
|
161
|
+
.map(([graph, triples]) => `GRAPH ${graph} { ${triples.join('\n')} }`);
|
|
162
|
+
return `DROP SILENT ALL ;\nINSERT DATA { ${groups.join('\n')} }`;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Determine the class of the given HTTP status code, e.g. 2 for 204.
|
|
166
|
+
* @param status An HTTP status code.
|
|
167
|
+
*/
|
|
168
|
+
static statusClass(status) {
|
|
169
|
+
return Math.floor(status / 100);
|
|
170
|
+
}
|
|
171
|
+
test(_engine, injectArguments) {
|
|
172
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
173
|
+
const endpoint = TestCaseProtocol.getEndpoint(injectArguments);
|
|
174
|
+
if (this.graphData.length > 0) {
|
|
175
|
+
yield this.loadGraphData(endpoint);
|
|
176
|
+
}
|
|
177
|
+
for (const request of this.requests) {
|
|
178
|
+
yield this.testRequest(endpoint, request);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Load the ut:graphData of this test case into the endpoint via a SPARQL update.
|
|
184
|
+
* @param endpoint The endpoint under test.
|
|
185
|
+
*/
|
|
186
|
+
loadGraphData(endpoint) {
|
|
187
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
188
|
+
const response = yield fetch(endpoint, {
|
|
189
|
+
method: 'POST',
|
|
190
|
+
headers: { 'content-type': 'application/sparql-update' },
|
|
191
|
+
body: TestCaseProtocol.createLoadUpdate(this.graphData),
|
|
192
|
+
});
|
|
193
|
+
const body = yield response.text();
|
|
194
|
+
if (!response.ok) {
|
|
195
|
+
throw new ErrorTest_1.ErrorTest(`Could not load the test data into ${endpoint} (HTTP ${response.status}): ${body}`);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Send a single request of this test case to the endpoint, and validate its response.
|
|
201
|
+
* @param endpoint The endpoint under test.
|
|
202
|
+
* @param request The request to send.
|
|
203
|
+
*/
|
|
204
|
+
testRequest(endpoint, request) {
|
|
205
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
206
|
+
var _a;
|
|
207
|
+
const url = TestCaseProtocol.resolveRequestUrl(endpoint, request.absolutePath);
|
|
208
|
+
let response;
|
|
209
|
+
try {
|
|
210
|
+
response = yield fetch(url, Object.assign({ method: request.method, headers: request.headers, redirect: 'manual' }, request.body && { body: TestCaseProtocol.encodeBody(request.body) }));
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
throw new ErrorTest_1.ErrorTest(`Could not send a ${request.method} request to ${url}: ${error.message}`);
|
|
214
|
+
}
|
|
215
|
+
const body = yield response.text();
|
|
216
|
+
if (!request.expectedStatusClasses.includes(TestCaseProtocol.statusClass(response.status))) {
|
|
217
|
+
throw new ErrorTest_1.ErrorTest(`Invalid response status for ${request.method} ${url}
|
|
218
|
+
|
|
219
|
+
Expected one of: ${request.expectedStatusClasses.map(statusClass => `${statusClass}xx`).join(', ')}
|
|
220
|
+
|
|
221
|
+
Got: ${response.status}\n\n${body}`);
|
|
222
|
+
}
|
|
223
|
+
const contentType = (_a = response.headers.get('content-type')) !== null && _a !== void 0 ? _a : '';
|
|
224
|
+
if (request.expectedFormat) {
|
|
225
|
+
TestCaseProtocol.validateFormat(request, url, contentType);
|
|
226
|
+
}
|
|
227
|
+
if (request.expectedBoolean !== undefined) {
|
|
228
|
+
yield TestCaseProtocol.validateBoolean(request, url, contentType, body);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Encode the body of a request in the character encoding that the manifest declares for it.
|
|
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
|
+
*/
|
|
238
|
+
static encodeBody(body) {
|
|
239
|
+
const encoding = body.characterEncoding.toUpperCase();
|
|
240
|
+
if (encoding === 'UTF-8') {
|
|
241
|
+
return new TextEncoder().encode(body.chars).buffer;
|
|
242
|
+
}
|
|
243
|
+
if (encoding === 'UTF-16') {
|
|
244
|
+
return new Uint8Array(Buffer.from(`\uFEFF${body.chars}`, 'utf16le')).buffer;
|
|
245
|
+
}
|
|
246
|
+
throw new ErrorTest_1.ErrorTest(`Unsupported cnt:characterEncoding ${body.characterEncoding}`);
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Validate that the content type of a response matches the format that the manifest expects.
|
|
250
|
+
* @param request The request that was sent.
|
|
251
|
+
* @param url The URL the request was sent to.
|
|
252
|
+
* @param contentType The content type of the response.
|
|
253
|
+
*/
|
|
254
|
+
static validateFormat(request, url, contentType) {
|
|
255
|
+
const contentTypes = EXPECTED_FORMAT_CONTENT_TYPES[request.expectedFormat];
|
|
256
|
+
if (!contentTypes) {
|
|
257
|
+
throw new ErrorTest_1.ErrorTest(`Unsupported mf:expectedFormat ${request.expectedFormat}`);
|
|
258
|
+
}
|
|
259
|
+
if (!contentTypes.some(expected => contentType.includes(expected))) {
|
|
260
|
+
throw new ErrorTest_1.ErrorTest(`Invalid response content type for ${request.method} ${url}
|
|
261
|
+
|
|
262
|
+
Expected a ${request.expectedFormat} format, which is one of: ${contentTypes.join(', ')}
|
|
263
|
+
|
|
264
|
+
Got: ${contentType}`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Validate that the body of a response contains the boolean result that the manifest expects.
|
|
269
|
+
* @param request The request that was sent.
|
|
270
|
+
* @param url The URL the request was sent to.
|
|
271
|
+
* @param contentType The content type of the response.
|
|
272
|
+
* @param body The body of the response.
|
|
273
|
+
*/
|
|
274
|
+
static validateBoolean(request, url, contentType, body) {
|
|
275
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
276
|
+
let result;
|
|
277
|
+
try {
|
|
278
|
+
const parsed = yield TestCaseQueryEvaluation_1.TestCaseQueryEvaluationHandler
|
|
279
|
+
.parseQueryResult(contentType, url, streamifyString(body));
|
|
280
|
+
if (parsed.type !== 'boolean') {
|
|
281
|
+
throw new Error(`Expected a boolean result, but got a result of type ${parsed.type}`);
|
|
282
|
+
}
|
|
283
|
+
result = parsed;
|
|
284
|
+
}
|
|
285
|
+
catch (error) {
|
|
286
|
+
throw new ErrorTest_1.ErrorTest(`Could not read a boolean result from the response of ${request.method} ${url}: ${error.message}\n\n${body}`);
|
|
287
|
+
}
|
|
288
|
+
if (result.value !== request.expectedBoolean) {
|
|
289
|
+
throw new ErrorTest_1.ErrorTest(`Invalid boolean response for ${request.method} ${url}
|
|
290
|
+
|
|
291
|
+
Expected: ${request.expectedBoolean}
|
|
292
|
+
|
|
293
|
+
Got: ${result.value}`);
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
exports.TestCaseProtocol = TestCaseProtocol;
|
|
299
|
+
//# sourceMappingURL=TestCaseProtocol.js.map
|
|
@@ -0,0 +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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rdf-test-suite",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e",
|
|
5
5
|
"description": "Executes the RDF and SPARQL test suites.",
|
|
6
6
|
"typings": "index",
|