n3 0.4.2 → 0.5.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/.eslintrc +173 -0
- package/.travis.yml +3 -6
- package/README.md +43 -8
- package/lib/N3Lexer.js +22 -45
- package/lib/N3Parser.js +120 -54
- package/lib/N3Store.js +97 -81
- package/lib/N3Util.js +33 -4
- package/lib/N3Writer.js +85 -26
- package/package.json +9 -9
- package/perf/.eslintrc +5 -0
- package/perf/N3Parser-perf.js +5 -4
- package/perf/N3Store-perf.js +66 -11
- package/spec/.eslintrc +10 -0
- package/spec/SpecTester.js +16 -17
- package/spec/trig/LICENSE +48 -0
- package/spec/turtle/LICENSE +117 -0
- package/test/.eslintrc +15 -0
- package/test/N3Lexer-test.js +4 -4
- package/test/N3Parser-test.js +480 -12
- package/test/N3Store-test.js +190 -71
- package/test/N3StreamParser-test.js +1 -1
- package/test/N3StreamWriter-test.js +1 -2
- package/test/N3Util-test.js +71 -5
- package/test/N3Writer-test.js +246 -5
- package/.jshintrc +0 -20
package/lib/N3Util.js
CHANGED
|
@@ -94,23 +94,52 @@ var N3Util = {
|
|
|
94
94
|
(/^[a-z]+(-[a-z0-9]+)*$/i.test(modifier) ? '"@' + modifier.toLowerCase()
|
|
95
95
|
: '"^^' + modifier);
|
|
96
96
|
},
|
|
97
|
+
|
|
98
|
+
// Creates a function that prepends the given IRI to a local name
|
|
99
|
+
prefix: function (iri) {
|
|
100
|
+
return N3Util.prefixes({ '': iri })('');
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
// Creates a function that allows registering and expanding prefixes
|
|
104
|
+
prefixes: function (defaultPrefixes) {
|
|
105
|
+
// Add all of the default prefixes
|
|
106
|
+
var prefixes = Object.create(null);
|
|
107
|
+
for (var prefix in defaultPrefixes)
|
|
108
|
+
processPrefix(prefix, defaultPrefixes[prefix]);
|
|
109
|
+
|
|
110
|
+
// Registers a new prefix (if an IRI was specified)
|
|
111
|
+
// or retrieves a function that expands an existing prefix (if no IRI was specified)
|
|
112
|
+
function processPrefix(prefix, iri) {
|
|
113
|
+
// Create a new prefix if an IRI is specified or the prefix doesn't exist
|
|
114
|
+
if (iri || !(prefix in prefixes)) {
|
|
115
|
+
var cache = Object.create(null);
|
|
116
|
+
iri = iri || '';
|
|
117
|
+
// Create a function that expands the prefix
|
|
118
|
+
prefixes[prefix] = function (localName) {
|
|
119
|
+
return cache[localName] || (cache[localName] = iri + localName);
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
return prefixes[prefix];
|
|
123
|
+
}
|
|
124
|
+
return processPrefix;
|
|
125
|
+
},
|
|
97
126
|
};
|
|
98
127
|
|
|
99
128
|
// Add the N3Util functions to the given object or its prototype
|
|
100
|
-
function
|
|
129
|
+
function addN3Util(parent, toPrototype) {
|
|
101
130
|
for (var name in N3Util)
|
|
102
131
|
if (!toPrototype)
|
|
103
132
|
parent[name] = N3Util[name];
|
|
104
133
|
else
|
|
105
|
-
parent.prototype[name] =
|
|
134
|
+
parent.prototype[name] = applyToThis(N3Util[name]);
|
|
106
135
|
|
|
107
136
|
return parent;
|
|
108
137
|
}
|
|
109
138
|
|
|
110
139
|
// Returns a function that applies `f` to the `this` object
|
|
111
|
-
function
|
|
140
|
+
function applyToThis(f) {
|
|
112
141
|
return function (a) { return f(this, a); };
|
|
113
142
|
}
|
|
114
143
|
|
|
115
144
|
// Expose N3Util, attaching all functions to it
|
|
116
|
-
module.exports =
|
|
145
|
+
module.exports = addN3Util(addN3Util);
|
package/lib/N3Writer.js
CHANGED
|
@@ -21,21 +21,24 @@ function N3Writer(outputStream, options) {
|
|
|
21
21
|
// Shift arguments if the first argument is not a stream
|
|
22
22
|
if (outputStream && typeof outputStream.write !== 'function')
|
|
23
23
|
options = outputStream, outputStream = null;
|
|
24
|
+
options = options || {};
|
|
24
25
|
|
|
25
26
|
// If no output stream given, send the output as string through the end callback
|
|
26
27
|
if (!outputStream) {
|
|
27
|
-
|
|
28
|
-
this.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
callback && callback();
|
|
28
|
+
var output = '';
|
|
29
|
+
this._outputStream = {
|
|
30
|
+
write: function (chunk, encoding, done) { output += chunk; done && done(); },
|
|
31
|
+
end: function (done) { done && done(null, output); },
|
|
32
32
|
};
|
|
33
|
+
this._endStream = true;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
this._outputStream = outputStream;
|
|
37
|
+
this._endStream = options.end === undefined ? true : !!options.end;
|
|
33
38
|
}
|
|
34
|
-
this._outputStream = outputStream;
|
|
35
39
|
|
|
36
40
|
// Initialize writer, depending on the format
|
|
37
41
|
this._subject = null;
|
|
38
|
-
options = options || {};
|
|
39
42
|
if (!(/triple|quad/i).test(options.format)) {
|
|
40
43
|
this._graph = '';
|
|
41
44
|
this._prefixIRIs = Object.create(null);
|
|
@@ -62,7 +65,9 @@ N3Writer.prototype = {
|
|
|
62
65
|
// Close the previous graph and start the new one
|
|
63
66
|
this._write((this._subject === null ? '' : (this._graph ? '\n}\n' : '.\n')) +
|
|
64
67
|
(graph ? this._encodeIriOrBlankNode(graph) + ' {\n' : ''));
|
|
65
|
-
this.
|
|
68
|
+
this._subject = null;
|
|
69
|
+
// Don't treat identical blank nodes as repeating graphs
|
|
70
|
+
this._graph = graph[0] !== '[' ? graph : ']';
|
|
66
71
|
}
|
|
67
72
|
// Don't repeat the subject if it's the same
|
|
68
73
|
if (this._subject === subject) {
|
|
@@ -100,16 +105,18 @@ N3Writer.prototype = {
|
|
|
100
105
|
},
|
|
101
106
|
|
|
102
107
|
// ### `_encodeIriOrBlankNode` represents an IRI or blank node
|
|
103
|
-
_encodeIriOrBlankNode: function (
|
|
104
|
-
// A blank node is represented as-is
|
|
105
|
-
|
|
108
|
+
_encodeIriOrBlankNode: function (entity) {
|
|
109
|
+
// A blank node or list is represented as-is
|
|
110
|
+
var firstChar = entity[0];
|
|
111
|
+
if (firstChar === '[' || firstChar === '(' || firstChar === '_' && entity[1] === ':')
|
|
112
|
+
return entity;
|
|
106
113
|
// Escape special characters
|
|
107
|
-
if (escape.test(
|
|
108
|
-
|
|
114
|
+
if (escape.test(entity))
|
|
115
|
+
entity = entity.replace(escapeAll, characterReplacer);
|
|
109
116
|
// Try to represent the IRI as prefixed name
|
|
110
|
-
var prefixMatch = this._prefixRegex.exec(
|
|
111
|
-
return !prefixMatch ? '<' +
|
|
112
|
-
(!prefixMatch[1] ?
|
|
117
|
+
var prefixMatch = this._prefixRegex.exec(entity);
|
|
118
|
+
return !prefixMatch ? '<' + entity + '>' :
|
|
119
|
+
(!prefixMatch[1] ? entity : this._prefixIRIs[prefixMatch[1]] + prefixMatch[2]);
|
|
113
120
|
},
|
|
114
121
|
|
|
115
122
|
// ### `_encodeLiteral` represents a literal
|
|
@@ -130,6 +137,9 @@ N3Writer.prototype = {
|
|
|
130
137
|
_encodeSubject: function (subject) {
|
|
131
138
|
if (subject[0] === '"')
|
|
132
139
|
throw new Error('A literal as subject is not allowed: ' + subject);
|
|
140
|
+
// Don't treat identical blank nodes as repeating subjects
|
|
141
|
+
if (subject[0] === '[')
|
|
142
|
+
this._subject = ']';
|
|
133
143
|
return this._encodeIriOrBlankNode(subject);
|
|
134
144
|
},
|
|
135
145
|
|
|
@@ -159,7 +169,7 @@ N3Writer.prototype = {
|
|
|
159
169
|
// ### `addTriple` adds the triple to the output stream
|
|
160
170
|
addTriple: function (subject, predicate, object, graph, done) {
|
|
161
171
|
// The triple was given as a triple object, so shift parameters
|
|
162
|
-
if (
|
|
172
|
+
if (object === undefined)
|
|
163
173
|
this._writeTriple(subject.subject, subject.predicate, subject.object,
|
|
164
174
|
subject.graph || '', predicate);
|
|
165
175
|
// The optional `graph` parameter was not provided
|
|
@@ -217,6 +227,58 @@ N3Writer.prototype = {
|
|
|
217
227
|
this._write(hasPrefixes ? '\n' : '', done);
|
|
218
228
|
},
|
|
219
229
|
|
|
230
|
+
// ### `blank` creates a blank node with the given content
|
|
231
|
+
blank: function (predicate, object) {
|
|
232
|
+
var children = predicate, child, length;
|
|
233
|
+
// Empty blank node
|
|
234
|
+
if (predicate === undefined)
|
|
235
|
+
children = [];
|
|
236
|
+
// Blank node passed as blank("predicate", "object")
|
|
237
|
+
else if (typeof predicate === 'string')
|
|
238
|
+
children = [{ predicate: predicate, object: object }];
|
|
239
|
+
// Blank node passed as blank({ predicate: predicate, object: object })
|
|
240
|
+
else if (!('length' in predicate))
|
|
241
|
+
children = [predicate];
|
|
242
|
+
|
|
243
|
+
switch (length = children.length) {
|
|
244
|
+
// Generate an empty blank node
|
|
245
|
+
case 0:
|
|
246
|
+
return '[]';
|
|
247
|
+
// Generate a non-nested one-triple blank node
|
|
248
|
+
case 1:
|
|
249
|
+
child = children[0];
|
|
250
|
+
if (child.object[0] !== '[')
|
|
251
|
+
return '[ ' + this._encodePredicate(child.predicate) + ' ' +
|
|
252
|
+
this._encodeObject(child.object) + ' ]';
|
|
253
|
+
// Generate a multi-triple or nested blank node
|
|
254
|
+
default:
|
|
255
|
+
var contents = '[';
|
|
256
|
+
// Write all triples in order
|
|
257
|
+
for (var i = 0; i < length; i++) {
|
|
258
|
+
child = children[i];
|
|
259
|
+
// Write only the object is the predicate is the same as the previous
|
|
260
|
+
if (child.predicate === predicate)
|
|
261
|
+
contents += ', ' + this._encodeObject(child.object);
|
|
262
|
+
// Otherwise, write the predicate and the object
|
|
263
|
+
else {
|
|
264
|
+
contents += (i ? ';\n ' : '\n ') +
|
|
265
|
+
this._encodePredicate(child.predicate) + ' ' +
|
|
266
|
+
this._encodeObject(child.object);
|
|
267
|
+
predicate = child.predicate;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return contents + '\n]';
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
|
|
274
|
+
// ### `list` creates a list node with the given content
|
|
275
|
+
list: function (elements) {
|
|
276
|
+
var length = elements && elements.length || 0, contents = new Array(length);
|
|
277
|
+
for (var i = 0; i < length; i++)
|
|
278
|
+
contents[i] = this._encodeObject(elements[i]);
|
|
279
|
+
return '(' + contents.join(' ') + ')';
|
|
280
|
+
},
|
|
281
|
+
|
|
220
282
|
// ### `_prefixRegex` matches a prefixed name or IRI that begins with one of the added prefixes
|
|
221
283
|
_prefixRegex: /$0^/,
|
|
222
284
|
|
|
@@ -230,16 +292,13 @@ N3Writer.prototype = {
|
|
|
230
292
|
// Disallow further writing
|
|
231
293
|
this._write = this._blockedWrite;
|
|
232
294
|
|
|
233
|
-
// If writing to a string instead of an actual stream, send the string
|
|
234
|
-
if (this === this._outputStream)
|
|
235
|
-
return done && done(null, this._output);
|
|
236
|
-
|
|
237
295
|
// Try to end the underlying stream, ensuring done is called exactly one time
|
|
238
|
-
var singleDone = done && function () { singleDone = null, done(); };
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
296
|
+
var singleDone = done && function (error, result) { singleDone = null, done(error, result); };
|
|
297
|
+
if (this._endStream) {
|
|
298
|
+
try { return this._outputStream.end(singleDone); }
|
|
299
|
+
catch (error) { /* error closing stream */ }
|
|
300
|
+
}
|
|
301
|
+
singleDone && singleDone();
|
|
243
302
|
},
|
|
244
303
|
};
|
|
245
304
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n3",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Lightning fast, asynchronous, streaming Turtle / N3 / RDF library.",
|
|
5
5
|
"author": "Ruben Verborgh <ruben.verborgh@gmail.com>",
|
|
6
6
|
"keywords": [
|
|
@@ -17,21 +17,21 @@
|
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"async": "~0.9.0",
|
|
20
|
+
"browserify": "~3.x",
|
|
20
21
|
"chai": "~1.4.2",
|
|
21
22
|
"chai-things": "~0.1.1",
|
|
22
23
|
"colors": "~0.6.0",
|
|
23
24
|
"docco": "~0.6.2",
|
|
24
|
-
"
|
|
25
|
-
"request": "~2.22.0",
|
|
26
|
-
"mocha": "~1.15.0",
|
|
25
|
+
"eslint": "~1.2.1",
|
|
27
26
|
"istanbul": "~0.3.0",
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
27
|
+
"mocha": "~2.3.0",
|
|
28
|
+
"pre-commit": "~0.0.9",
|
|
29
|
+
"request": "~2.22.0",
|
|
30
|
+
"uglify-js": "~2.4.3"
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
33
33
|
"test": "mocha",
|
|
34
|
-
"
|
|
34
|
+
"lint": "eslint lib perf test spec",
|
|
35
35
|
"browser": "node browser/build-browser-versions",
|
|
36
36
|
"coverage": "istanbul cover node_modules/.bin/_mocha -- -R spec --timeout 100",
|
|
37
37
|
"spec": "node spec/turtle-spec && node spec/trig-spec && node spec/ntriples-spec && node spec/nquads-spec",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
]
|
|
59
59
|
},
|
|
60
60
|
"pre-commit": [
|
|
61
|
-
"
|
|
61
|
+
"lint",
|
|
62
62
|
"test"
|
|
63
63
|
]
|
|
64
64
|
}
|
package/perf/N3Parser-perf.js
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
var N3 = require('../N3');
|
|
3
3
|
var fs = require('fs'),
|
|
4
|
+
path = require('path'),
|
|
4
5
|
assert = require('assert');
|
|
5
6
|
|
|
6
7
|
if (process.argv.length !== 3)
|
|
7
8
|
return console.error('Usage: N3Parser-perf.js filename');
|
|
8
9
|
|
|
9
|
-
var filename = process.argv[2]
|
|
10
|
+
var filename = path.resolve(process.cwd(), process.argv[2]),
|
|
11
|
+
base = 'file://' + filename;
|
|
10
12
|
|
|
11
13
|
var TEST = '- Parsing file ' + filename;
|
|
12
14
|
console.time(TEST);
|
|
13
15
|
|
|
14
16
|
var count = 0;
|
|
15
|
-
new N3.Parser().parse(fs.createReadStream(filename), function (error, triple) {
|
|
17
|
+
new N3.Parser({ documentIRI: base }).parse(fs.createReadStream(filename), function (error, triple) {
|
|
16
18
|
assert(!error, error);
|
|
17
|
-
if (triple)
|
|
19
|
+
if (triple)
|
|
18
20
|
count++;
|
|
19
|
-
}
|
|
20
21
|
else {
|
|
21
22
|
console.timeEnd(TEST);
|
|
22
23
|
console.log('* Triples parsed: ' + count);
|
package/perf/N3Store-perf.js
CHANGED
|
@@ -4,25 +4,48 @@ var assert = require('assert');
|
|
|
4
4
|
|
|
5
5
|
console.log('N3Store performance test');
|
|
6
6
|
|
|
7
|
-
var TEST;
|
|
8
|
-
var dim = parseInt(process.argv[2], 10) || 256;
|
|
9
|
-
var dimSquared = dim * dim;
|
|
10
|
-
var dimCubed = dimSquared * dim;
|
|
11
7
|
var prefix = 'http://example.org/#';
|
|
8
|
+
var TEST, dim, dimSquared, dimCubed, dimQuads, store;
|
|
12
9
|
|
|
13
|
-
|
|
10
|
+
/* Test triples */
|
|
11
|
+
dim = parseInt(process.argv[2], 10) || 256;
|
|
12
|
+
dimSquared = dim * dim;
|
|
13
|
+
dimCubed = dimSquared * dim;
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
store = new N3.Store();
|
|
16
|
+
TEST = '- Adding ' + dimCubed + ' triples in the default graph';
|
|
16
17
|
console.time(TEST);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
var i, j, k, l;
|
|
19
|
+
for (i = 0; i < dim; i++)
|
|
20
|
+
for (j = 0; j < dim; j++)
|
|
21
|
+
for (k = 0; k < dim; k++)
|
|
20
22
|
store.addTriple(prefix + i, prefix + j, prefix + k);
|
|
21
23
|
console.timeEnd(TEST);
|
|
22
24
|
|
|
23
|
-
console.log('* Memory usage: ' + Math.round(process.memoryUsage().rss / 1024 / 1024) + 'MB');
|
|
25
|
+
console.log('* Memory usage for triples: ' + Math.round(process.memoryUsage().rss / 1024 / 1024) + 'MB');
|
|
26
|
+
|
|
27
|
+
TEST = '- Finding all ' + dimCubed + ' triples to the default graph ' + dimSquared * 1 + ' times (0 variables)';
|
|
28
|
+
console.time(TEST);
|
|
29
|
+
for (i = 0; i < dim; i++)
|
|
30
|
+
for (j = 0; j < dim; j++)
|
|
31
|
+
for (k = 0; k < dim; k++)
|
|
32
|
+
assert.equal(store.find(prefix + i, prefix + j, prefix + k).length, 1);
|
|
33
|
+
console.timeEnd(TEST);
|
|
34
|
+
|
|
35
|
+
TEST = '- Finding all ' + dimCubed + ' triples to the default graph ' + dimSquared * 2 + ' times (1 variable)';
|
|
36
|
+
console.time(TEST);
|
|
37
|
+
for (i = 0; i < dim; i++)
|
|
38
|
+
for (j = 0; j < dim; j++)
|
|
39
|
+
assert.equal(store.find(prefix + i, prefix + j, null).length, dim);
|
|
40
|
+
for (i = 0; i < dim; i++)
|
|
41
|
+
for (j = 0; j < dim; j++)
|
|
42
|
+
assert.equal(store.find(prefix + i, null, prefix + j).length, dim);
|
|
43
|
+
for (i = 0; i < dim; i++)
|
|
44
|
+
for (j = 0; j < dim; j++)
|
|
45
|
+
assert.equal(store.find(null, prefix + i, prefix + j).length, dim);
|
|
46
|
+
console.timeEnd(TEST);
|
|
24
47
|
|
|
25
|
-
TEST = '- Finding all ' + dimCubed + ' triples ' + dimSquared * 3 + ' times';
|
|
48
|
+
TEST = '- Finding all ' + dimCubed + ' triples to the default graph ' + dimSquared * 3 + ' times (2 variables)';
|
|
26
49
|
console.time(TEST);
|
|
27
50
|
for (i = 0; i < dim; i++)
|
|
28
51
|
assert.equal(store.find(prefix + i, null, null).length, dimSquared);
|
|
@@ -31,3 +54,35 @@ for (j = 0; j < dim; j++)
|
|
|
31
54
|
for (k = 0; k < dim; k++)
|
|
32
55
|
assert.equal(store.find(null, null, prefix + k).length, dimSquared);
|
|
33
56
|
console.timeEnd(TEST);
|
|
57
|
+
|
|
58
|
+
console.log();
|
|
59
|
+
|
|
60
|
+
/* Test quads */
|
|
61
|
+
dim /= 4,
|
|
62
|
+
dimSquared = dim * dim;
|
|
63
|
+
dimCubed = dimSquared * dim;
|
|
64
|
+
dimQuads = dimCubed * dim;
|
|
65
|
+
|
|
66
|
+
store = new N3.Store();
|
|
67
|
+
TEST = '- Adding ' + dimQuads + ' quads';
|
|
68
|
+
console.time(TEST);
|
|
69
|
+
for (i = 0; i < dim; i++)
|
|
70
|
+
for (j = 0; j < dim; j++)
|
|
71
|
+
for (k = 0; k < dim; k++)
|
|
72
|
+
for (l = 0; l < dim; l++)
|
|
73
|
+
store.addTriple(prefix + i, prefix + j, prefix + k, prefix + l);
|
|
74
|
+
console.timeEnd(TEST);
|
|
75
|
+
|
|
76
|
+
console.log('* Memory usage for quads: ' + Math.round(process.memoryUsage().rss / 1024 / 1024) + 'MB');
|
|
77
|
+
|
|
78
|
+
TEST = '- Finding all ' + dimQuads + ' quads ' + dimCubed * 4 + ' times';
|
|
79
|
+
console.time(TEST);
|
|
80
|
+
for (i = 0; i < dim; i++)
|
|
81
|
+
assert.equal(store.find(prefix + i, null, null, null).length, dimCubed);
|
|
82
|
+
for (j = 0; j < dim; j++)
|
|
83
|
+
assert.equal(store.find(null, prefix + j, null, null).length, dimCubed);
|
|
84
|
+
for (k = 0; k < dim; k++)
|
|
85
|
+
assert.equal(store.find(null, null, prefix + k, null).length, dimCubed);
|
|
86
|
+
for (l = 0; l < dim; l++)
|
|
87
|
+
assert.equal(store.find(null, null, null, prefix + l).length, dimCubed);
|
|
88
|
+
console.timeEnd(TEST);
|
package/spec/.eslintrc
ADDED
package/spec/SpecTester.js
CHANGED
|
@@ -65,15 +65,16 @@ SpecTester.prototype.run = function () {
|
|
|
65
65
|
// 1.2.1 Execute an individual test
|
|
66
66
|
function (test, callback) {
|
|
67
67
|
async.series({ actionStream: self._fetch.bind(self, test.action),
|
|
68
|
-
resultStream: self._fetch.bind(self, test.result)
|
|
69
|
-
function (
|
|
68
|
+
resultStream: self._fetch.bind(self, test.result) },
|
|
69
|
+
function (error, results) {
|
|
70
|
+
if (error) return callback(error);
|
|
70
71
|
self._performTest(test, results.actionStream, callback);
|
|
71
72
|
});
|
|
72
73
|
},
|
|
73
74
|
// 1.2.2 Show the summary of all performed tests
|
|
74
75
|
function showSummary(error, tests) {
|
|
75
76
|
var score = tests.reduce(function (sum, test) { return sum + test.success; }, 0);
|
|
76
|
-
manifest.skipped.forEach(function (test) {
|
|
77
|
+
manifest.skipped.forEach(function (test) { self._verifyResult(test); });
|
|
77
78
|
console.log(('* passed ' + score +
|
|
78
79
|
' out of ' + manifest.tests.length + ' tests' +
|
|
79
80
|
' (' + manifest.skipped.length + ' skipped)').bold);
|
|
@@ -87,7 +88,7 @@ SpecTester.prototype.run = function () {
|
|
|
87
88
|
// 3. Return with the proper exit code
|
|
88
89
|
function (tests) {
|
|
89
90
|
process.exit(tests.every(function (test) { return test.success; }) ? 0 : 1);
|
|
90
|
-
}
|
|
91
|
+
},
|
|
91
92
|
],
|
|
92
93
|
function (error) {
|
|
93
94
|
if (error) {
|
|
@@ -156,7 +157,7 @@ SpecTester.prototype._performTest = function (test, actionStream, callback) {
|
|
|
156
157
|
var resultFile = path.join(this._testFolder, test.action.replace(/\.\w+$/, '-result.nq')),
|
|
157
158
|
resultWriter = new N3.Writer(fs.createWriteStream(resultFile), { format: 'N-Quads' }),
|
|
158
159
|
config = { format: this._name, documentIRI: url.resolve(this._manifest, test.action) },
|
|
159
|
-
parser = N3.Parser(config), self = this;
|
|
160
|
+
parser = new N3.Parser(config), self = this;
|
|
160
161
|
parser.parse(actionStream, function (error, triple) {
|
|
161
162
|
if (error) test.error = error;
|
|
162
163
|
if (triple) resultWriter.addTriple(triple);
|
|
@@ -177,14 +178,12 @@ SpecTester.prototype._verifyResult = function (test, resultFile, correctFile, ca
|
|
|
177
178
|
}
|
|
178
179
|
// Positive tests are successful if the results are equal,
|
|
179
180
|
// or if the correct solution is not given but no error occurred
|
|
180
|
-
else
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
this._compareResultFiles(resultFile, correctFile, displayResult);
|
|
187
|
-
}
|
|
181
|
+
else if (!correctFile)
|
|
182
|
+
displayResult(null, !test.error);
|
|
183
|
+
else if (!resultFile)
|
|
184
|
+
displayResult(null, false);
|
|
185
|
+
else
|
|
186
|
+
this._compareResultFiles(resultFile, correctFile, displayResult);
|
|
188
187
|
|
|
189
188
|
// Display the test result
|
|
190
189
|
function displayResult(error, success, comparison) {
|
|
@@ -219,13 +218,13 @@ SpecTester.prototype._compareResultFiles = function (actual, expected, callback)
|
|
|
219
218
|
else {
|
|
220
219
|
// SWObjects doesn't support N-Quads, so convert to TriG if necessary
|
|
221
220
|
if (/\.nq/.test(expected)) {
|
|
222
|
-
fs.writeFileSync(actual += '.trig',
|
|
223
|
-
fs.writeFileSync(expected += '.trig',
|
|
221
|
+
fs.writeFileSync(actual += '.trig', quadsToTrig(results.actualContents));
|
|
222
|
+
fs.writeFileSync(expected += '.trig', quadsToTrig(results.expectedContents));
|
|
224
223
|
}
|
|
225
224
|
exec('sparql -d ' + expected + ' --compare ' + actual,
|
|
226
225
|
function (error, stdout) { callback(error, /^matched\s*$/.test(stdout), stdout); });
|
|
227
226
|
}
|
|
228
|
-
function
|
|
227
|
+
function quadsToTrig(nquad) {
|
|
229
228
|
return nquad.replace(/^([^\s]+)\s+([^\s]+)\s+(.+)\s+([^\s"]+)\s*\.$/mg, '$4 { $1 $2 $3 }');
|
|
230
229
|
}
|
|
231
230
|
});
|
|
@@ -239,7 +238,7 @@ SpecTester.prototype._compareResultFiles = function (actual, expected, callback)
|
|
|
239
238
|
SpecTester.prototype._generateEarlReport = function (tests, callback) {
|
|
240
239
|
// Create the report file
|
|
241
240
|
var reportFile = path.join(this._reportFolder, 'n3js-earl-report-' + this._name + '.ttl'),
|
|
242
|
-
report = new N3.Writer(fs.createWriteStream(reportFile), {
|
|
241
|
+
report = new N3.Writer(fs.createWriteStream(reportFile), { prefixes: prefixes }),
|
|
243
242
|
date = '"' + new Date().toISOString() + '"^^' + prefixes.xsd + 'dateTime',
|
|
244
243
|
homepage = 'https://github.com/RubenVerborgh/N3.js', app = homepage + '#n3js',
|
|
245
244
|
developer = 'http://ruben.verborgh.org/#me', manifest = this._manifest + '#';
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
Summary
|
|
2
|
+
=======
|
|
3
|
+
|
|
4
|
+
Distributed under both the W3C Test Suite License[1] and the W3C 3-clause BSD License[2]. To contribute to a W3C Test Suite, see the policies and contribution forms [3]
|
|
5
|
+
|
|
6
|
+
1. http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
|
|
7
|
+
2. http://www.w3.org/Consortium/Legal/2008/03-bsd-license
|
|
8
|
+
3. http://www.w3.org/2004/10/27-testcases
|
|
9
|
+
|
|
10
|
+
DISCLAIMER
|
|
11
|
+
|
|
12
|
+
UNDER BOTH MUTUALLY EXCLUSIVE LICENSES, THIS DOCUMENT AND ALL DOCUMENTS, TESTS AND SOFTWARE THAT LINK THIS STATEMENT ARE PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE DOCUMENT ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
|
|
13
|
+
COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE DOCUMENT OR THE PERFORMANCE OR IMPLEMENTATION OF THE CONTENTS THEREOF.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
W3C Test Suite License
|
|
17
|
+
======================
|
|
18
|
+
|
|
19
|
+
This document, Test Suites and other documents that link to this statement are provided by the copyright holders under the following license: By using and/or copying this document, or the W3C document from which this statement is linked, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions:
|
|
20
|
+
|
|
21
|
+
Permission to copy, and distribute the contents of this document, or the W3C document from which this statement is linked, in any medium for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the document, or portions thereof, that you use:
|
|
22
|
+
|
|
23
|
+
A link or URL to the original W3C document.
|
|
24
|
+
The pre-existing copyright notice of the original author, or if it doesn't exist, a notice (hypertext is preferred, but a textual representation is permitted) of the form: "Copyright © [$date-of-document] World Wide Web Consortium, (Massachusetts Institute of Technology, European Research Consortium for Informatics and Mathematics, Keio University) and others. All Rights Reserved. http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html"
|
|
25
|
+
If it exists, the STATUS of the W3C document.
|
|
26
|
+
When space permits, inclusion of the full text of this NOTICE should be provided. We request that authorship attribution be provided in any software, documents, or other items or products that you create pursuant to the implementation of the contents of this document, or any portion thereof.
|
|
27
|
+
|
|
28
|
+
No right to create modifications or derivatives of W3C documents is granted pursuant to this license. However, if additional requirements (documented in the Copyright FAQ) are satisfied, the right to create modifications or derivatives is sometimes granted by the W3C to individuals complying with those requirements.
|
|
29
|
+
|
|
30
|
+
If a Test Suite distinguishes the test harness (or, framework for navigation) and the actual tests, permission is given to remove or alter the harness or navigation if the Test Suite in question allows to do so. The tests themselves shall NOT be changed in any way.
|
|
31
|
+
|
|
32
|
+
The name and trademarks of W3C and other copyright holders may NOT be used in advertising or publicity pertaining to this document or other documents that link to this statement without specific, written prior permission. Title to copyright in this document will at all times remain with copyright holders. Permission is given to use the trademarked string W3C within claims of performance concerning W3C Specifications or features described therein, and there only, if the test suite so authorizes.
|
|
33
|
+
|
|
34
|
+
THIS WORK IS PROVIDED BY W3C, MIT, ERCIM, KEIO UNIVERSITY, THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL W3C, MIT, ERCIM, KEIO UNIVERSITY, THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
W3C 3-clause BSD License
|
|
38
|
+
========================
|
|
39
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
40
|
+
|
|
41
|
+
Redistributions of works must retain the original copyright notice, this list of conditions and the following disclaimer.
|
|
42
|
+
|
|
43
|
+
Redistributions in binary form must reproduce the original copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
44
|
+
|
|
45
|
+
Neither the name of the W3C nor the names of its contributors may be used to endorse or promote products derived from this work without specific prior written permission.
|
|
46
|
+
|
|
47
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
48
|
+
|