Skip to content

Commit

Permalink
WIP: run eye tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jeswr committed Oct 13, 2023
1 parent bec3571 commit 36d6011
Show file tree
Hide file tree
Showing 6 changed files with 225 additions and 59 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ node_modules
coverage
dist
bundle
eye
lib/eye.ts
perf/output.txt
135 changes: 135 additions & 0 deletions __tests__/upstream-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/* eslint-disable */
// TODO: Remove the above before merging
import fs from 'fs-extra';
import path from 'path';
import { Parser, Store, DataFactory as DF } from 'n3';
import { mapTerms } from 'rdf-terms';
import { execFileSync, exec, execSync } from 'child_process';

import { n3reasoner } from '../dist';
import 'jest-rdf';
import { Quad } from '@rdfjs/types';

const examplesPath = path.join(__dirname, '..', 'eye', 'reasoning');
const expectedStart = 'eye "$@"';
const cacheComponent = ' --wcache http://eyereasoner.github.io/eye/reasoning .. ';
const longStart = expectedStart + cacheComponent;

const ignoreFolders = [
// n3reasoner does not support extra images
'dt', 'image',
// n3reasoner does not support multiquery
'mq',
];

// These exceptions should eventually be removed
const ignoreOutputs = [
// This complains because `$` is used as a term
'bi/biA.n3',
// This complains because of https://github.com/rdfjs/N3.js/issues/328
'crypto/crypto-proof.n3',
// This just states `true .` but it's not a valid N3 file
'entail/socrates-check.n3',
// This complains because of https://github.com/rdfjs/N3.js/issues/328
'preduction/palindrome-proof.n3',
// This complains because of https://github.com/rdfjs/N3.js/issues/328
'preduction/palindrome2-proof.n3',
];

function readFile(subPath: string) {
return fs.readFileSync(path.join(examplesPath, subPath)).toString();
}

function dereference(subPath: string) {
const parser = new Parser({ format: 'text/n3', baseIRI: `http://eyereasoner.github.io/eye/reasoning${subPath}` });
// @ts-expect-error
parser._supportsRDFStar = true;
return parser.parse(readFile(subPath));
}

function loadFiles(files: string[]) {
return [...new Store(files.map((file) => dereference(file)).flat())]
// Workaround for https://github.com/rdfjs/N3.js/issues/332
.map((quad) => mapTerms(quad, (term) => (term.termType === 'BlankNode' ? DF.blankNode(term.value.replace(/^\./, '')) : term)));
}

const invMapping = {
derivations: '--pass-only-new',
deductive_closure: '--pass',
deductive_closure_plus_rules: '--pass-all',
grounded_deductive_closure_plus_rules: '--pass-all-ground',
} as const;

describe('Testing examples from eye repository', () => {
const cases: [string, string[]][] = [];

for (const folder of fs.readdirSync(examplesPath).filter(folder => fs.statSync(path.join(examplesPath, folder)).isDirectory())) {
if (ignoreFolders.includes(folder))
continue;

try {
// FIXME: Don't have stderr show in the console
const tests = execSync(
fs.readFileSync(path.join(examplesPath, folder, 'test')).toString().replace(/eye /g, 'echo ')
).toString().split('\n').slice(0, -1);

// FIXME: Add a verification to make sure we are only skipping what we want
if (tests.length > 0) {
cases.push([folder, tests])
}
} catch (e) {
if (!(e as any).toString().includes('swipl')) {
throw e;
}
// Don't error if the problem is just that the test is trying to test the swipl command
}
}

describe.each(cases)('Testing examples for %s', (folder, args) => {
it.each(args)('%s', async (args) => {
let argsArray = args.split(/\ |\=/g)
// Remove the --turtle flag because it's just a performance optimisation
.filter((arg) => !['--turtle'].includes(arg))
//
.map(arg => arg.replace('http://eyereasoner.github.io/eye/reasoning/', ''));


if (argsArray[argsArray.length - 2] !== '--output') {
throw new Error(`Expected --output to be the last argument on [${args}]`);
}

if (argsArray[0] !== '--wcache' || argsArray[1] !== 'http://eyereasoner.github.io/eye/reasoning' || argsArray[2] !== '..') {
throw new Error(`Expected --wcache to be the first argument on [${args}]`);
}

const subPath = path.join(folder, argsArray[argsArray.length - 1]);
argsArray = argsArray.slice(3, -2);

let query: Quad[] | undefined = undefined;

if (argsArray.includes('--query')) {
const qind = argsArray.indexOf('--query');
query = loadFiles([argsArray[qind + 1]]);
argsArray = [...argsArray.slice(0, qind), ...argsArray.slice(qind + 2)];
}

const output = (Object.keys(invMapping) as (keyof typeof invMapping)[]).find(key => argsArray.includes(invMapping[key]));

if (output) {
argsArray = argsArray.filter(arg => arg !== invMapping[output]);
}

if (argsArray.includes('--nope') && !ignoreOutputs.includes(subPath)) {
await expect(
n3reasoner(
loadFiles(argsArray.filter(arg => arg !== '--nope')),
query,
{ output },
),
)
.resolves
.toBeRdfIsomorphic(dereference(subPath));
}
});
});
});
110 changes: 57 additions & 53 deletions lib/n3Writer.temp.ts
Original file line number Diff line number Diff line change
@@ -1,64 +1,68 @@

// This is a workaround for https://github.com/rdfjs/N3.js/issues/316
import { Quad, Term } from '@rdfjs/types';
import { DataFactory as DF, Store, Writer } from 'n3';
// import { Quad, Term } from '@rdfjs/types';
// import { DataFactory as DF, Store, Writer } from 'n3';
export { write } from "@jeswr/pretty-turtle";

function isQuoted(term: Term, store: Store) {
return term.termType === 'BlankNode' && store.getQuads(null, null, null, term).length > 0;
}
// function isQuoted(term: Term, store: Store) {
// return term.termType === 'BlankNode' && store.getQuads(null, null, null, term).length > 0;
// }

export class N3Writer {
private _writer: any = new Writer();
// export class N3Writer {
// private _writer: any = new Writer();

_encodePredicate(term: Term): string {
if (term.termType === 'NamedNode') {
switch (term.value) {
case 'http://www.w3.org/2000/10/swap/log#implies':
return '=>';
case 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type':
return 'a'
}
}
return this._writer._encodeIriOrBlank(term);
}
// _encodePredicate(term: Term): string {
// if (term.termType === 'NamedNode') {
// switch (term.value) {
// case 'http://www.w3.org/2000/10/swap/log#implies':
// return '=>';
// case 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type':
// return 'a'
// }
// }
// return this._writer._encodeIriOrBlank(term);
// }

_encodeSubject(entity: Term, store: Store): string {
if (isQuoted(entity, store)) {
return `{${this.quadsStoreToString(store, entity)}}`
}
return this._writer._encodeSubject(entity)
}
// _encodeSubject(entity: Term, store: Store): string {
// if (isQuoted(entity, store)) {
// return `{${this.quadsStoreToString(store, entity)}}`
// }
// if (entity.termType === 'Literal') {
// return this._writer._encodeObject(entity);
// }
// return this._writer._encodeSubject(entity);
// }

_encodeObject(entity: Term, store: Store): string {
if (isQuoted(entity, store)) {
return `{${this.quadsStoreToString(store, entity)}}`
}
return this._writer._encodeObject(entity)
}
// _encodeObject(entity: Term, store: Store): string {
// if (isQuoted(entity, store)) {
// return `{${this.quadsStoreToString(store, entity)}}`
// }
// return this._writer._encodeObject(entity)
// }

// ### `quadToString` serializes a quad as a string
quadToString(t: Quad, store: Store): string {
return `${
this._encodeSubject(t.subject, store)
} ${
this._encodePredicate(t.predicate as any)
} ${
this._encodeObject(t.object, store)
}`;
}
// // ### `quadToString` serializes a quad as a string
// quadToString(t: Quad, store: Store): string {
// return `${
// this._encodeSubject(t.subject, store)
// } ${
// this._encodePredicate(t.predicate as any)
// } ${
// this._encodeObject(t.object, store)
// }`;
// }

// ### `quadsToString` serializes an array of quads as a string
quadsStoreToString(store: Store, graph: Term = DF.defaultGraph()): string {
return store.getQuads(null, null, null, graph)
.map(t => this.quadToString(t, store))
.join(' . ') + ' . ';
}
// // ### `quadsToString` serializes an array of quads as a string
// quadsStoreToString(store: Store, graph: Term = DF.defaultGraph()): string {
// return store.getQuads(null, null, null, graph)
// .map(t => this.quadToString(t, store))
// .join(' . ') + ' . ';
// }

quadsToString(quads: Quad[]): string {
return this.quadsStoreToString(new Store(quads))
}
}
// quadsToString(quads: Quad[]): string {
// return this.quadsStoreToString(new Store(quads))
// }
// }

export function write(quads: Quad[]) {
return (new N3Writer).quadsToString(quads);
}
// export function write(quads: Quad[]) {
// return (new N3Writer).quadsToString(quads);
// }
12 changes: 6 additions & 6 deletions lib/transformers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ export function runQuery(
queryString?: string,
{ output }: Options = {},
): SWIPLModule {
const args: string[] = ['--nope', '--quiet', 'data.nq'];
const args: string[] = ['--nope', '--quiet', 'data.n3s'];

if (queryString) {
if (output) {
throw new Error('Cannot use explicit output with explicit query');
}
Module.FS.writeFile('query.nq', queryString);
args.push('--query', './query.nq');
Module.FS.writeFile('query.n3s', queryString);
args.push('--query', './query.n3s');
} else {
switch (output) {
case undefined:
Expand All @@ -76,7 +76,7 @@ export function runQuery(
}
}

Module.FS.writeFile('data.nq', data);
Module.FS.writeFile('data.n3s', data);

queryOnce(Module, 'main', args);
return Module;
Expand Down Expand Up @@ -122,8 +122,8 @@ export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: Data, quer
});
runQuery(
Module,
typeof data === 'string' ? data : write(data),
query && (typeof query === 'string' ? query : write(query)),
typeof data === 'string' ? data : await write(data, { format: 'text/n3' }),
query && (typeof query === 'string' ? query : await write(query, { format: 'text/n3' })),
options,
);

Expand Down
24 changes: 24 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"eye:pvm:test": "ts-node scripts/run-pvm",
"eye:prepare": "npm run eye:pvm",
"eye:update": "ts-node scripts/update",
"clone:eye": "rm -rf ./eye && git clone https://github.com/eyereasoner/eye ./eye --depth 1 --branch $npm_package_config_eye_name",
"perf": "ts-node perf/bench 2>&1 | tee perf/output.txt"
},
"repository": {
Expand Down Expand Up @@ -58,6 +59,7 @@
},
"homepage": "https://github.com/eyereasoner/eye-js#readme",
"devDependencies": {
"@jeswr/pretty-turtle": "^1.4.0",
"@memlab/api": "^1.0.20",
"@qiwi/semantic-release-gh-pages-plugin": "^5.2.4",
"@rollup/plugin-commonjs": "^25.0.0",
Expand Down

0 comments on commit 36d6011

Please sign in to comment.