Skip to content

Commit

Permalink
test: fix EE integration test
Browse files Browse the repository at this point in the history
  • Loading branch information
jitsedesmet committed Oct 3, 2023
1 parent b88a89f commit 4de1891
Show file tree
Hide file tree
Showing 24 changed files with 187 additions and 390 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { ActionContext, Bus } from '@comunica/core';
import { ExpressionEvaluatorFactory } from '@comunica/expression-evaluator';
import type { IExpressionEvaluatorFactory } from '@comunica/types';
import { ArrayIterator } from 'asynciterator';
import { Algebra } from 'sparqlalgebrajs';
import { Wildcard } from 'sparqljs';
import { ActorBindingsAggregatorFactoryCount } from '../lib';
import { BF, DF, makeAggregate } from './util';
import { makeAggregate } from './util';

describe('ActorExpressionEvaluatorAggregateCount', () => {
let bus: any;
Expand All @@ -15,16 +14,7 @@ describe('ActorExpressionEvaluatorAggregateCount', () => {
bus = new Bus({ name: 'bus' });

const mediatorQueryOperation: any = {
mediate: (arg: any) => Promise.resolve({
bindingsStream: new ArrayIterator([
BF.bindings([[ DF.variable('x'), DF.literal('1') ]]),
BF.bindings([[ DF.variable('x'), DF.literal('2') ]]),
BF.bindings([[ DF.variable('x'), DF.literal('3') ]]),
], { autoStart: false }),
metadata: () => Promise.resolve({ cardinality: 3, canContainUndefs: false, variables: [ DF.variable('x') ]}),
operated: arg,
type: 'bindings',
}),
async mediate(arg: any) { return {}; },
};

expressionEvaluatorFactory = new ExpressionEvaluatorFactory({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,11 @@ export class ExpressionEvaluator implements IExpressionEvaluator {
return this.comparePrimitives(termA.value, termB.value);
}

private orderLiteralTypes(litA: RDF.Literal, litB: RDF.Literal, context: IAsyncEvaluatorContext): -1 | 0 | 1 {
private orderLiteralTypes(litA: RDF.Literal, litB: RDF.Literal, context: ICompleteEEContext): -1 | 0 | 1 {
const isGreater = regularFunctions[C.RegularOperator.GT];
const isEqual = regularFunctions[C.RegularOperator.EQUAL];

const completeContext = ExpressionEvaluator.completeContext(context);

const termTransformer = new TermTransformer(completeContext.superTypeProvider);
const termTransformer = new TermTransformer(context.superTypeProvider);
const myLitA = termTransformer.transformLiteral(litA);
const myLitB = termTransformer.transformLiteral(litB);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { KeysInitQuery } from '@comunica/context-entries';
import { BlankNodeBindingsScoped } from '@comunica/data-factory';
import type { IActionContext, IBindingAggregator, IExpressionEvaluatorFactory } from '@comunica/types';
import type { Algebra as Alg } from 'sparqlalgebrajs';
import type { IAsyncEvaluatorContext } from './ExpressionEvaluator';
import { ExpressionEvaluator } from './ExpressionEvaluator';

/**
Expand All @@ -24,17 +25,21 @@ export class ExpressionEvaluatorFactory implements IExpressionEvaluatorFactory {
this.mediatorQueryOperation = args.mediatorQueryOperation;
}

public createEvaluator(algExpr: Alg.Expression, context: IActionContext): ExpressionEvaluator {
// TODO: remove legacyContext in *final* update (probably when preparing the EE for function bussification)
public createEvaluator(algExpr: Alg.Expression, context: IActionContext,
legacyContext: Partial<IAsyncEvaluatorContext> = {}): ExpressionEvaluator {
return new ExpressionEvaluator(algExpr, {
now: context.get(KeysInitQuery.queryTimestamp),
baseIRI: context.get(KeysInitQuery.baseIRI),
actionContext: context,
bnode: (input?: string) => Promise.resolve(new BlankNodeBindingsScoped(input || `BNODE_${bnodeCounter++}`)),
exists: ActorQueryOperation.createExistenceResolver(context, this.mediatorQueryOperation),
...legacyContext,
}, this);
}

public async createAggregator(algExpr: Alg.AggregateExpression, context: IActionContext): Promise<IBindingAggregator> {
public async createAggregator(algExpr: Alg.AggregateExpression, context: IActionContext):
Promise<IBindingAggregator> {
return (await this.mediatorBindingsAggregatorFactory.mediate({
expr: algExpr,
factory: this,
Expand Down
6 changes: 2 additions & 4 deletions packages/expression-evaluator/lib/expressions/Term.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,13 @@ export class Quad extends Term {

export class DefaultGraph extends Term {
public termType: TermType = 'defaultGraph';
private readonly valueTerm: RDF.DefaultGraph;

public constructor(input: RDF.DefaultGraph) {
public constructor() {
super();
this.valueTerm = input;
}

public toRDF(): RDF.DefaultGraph {
return this.valueTerm;
return DF.defaultGraph();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export class TermTransformer implements ITermTransformer {
case 'Quad':
return new E.Quad(term.term, this.superTypeProvider);
case 'DefaultGraph':
return new E.DefaultGraph(term.term);
return new E.DefaultGraph();
default:
throw new Err.InvalidTermType(term);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,93 +1,58 @@
import { BindingsFactory } from '@comunica/bindings-factory';
import { ActionContext } from '@comunica/core';
import { DataFactory } from 'rdf-data-factory';
import { translate } from 'sparqlalgebrajs';
import { AsyncEvaluator, SyncEvaluator } from '../../../lib';
import type { ExpressionEvaluatorFactory } from '../../../lib';
import { IntegerLiteral } from '../../../lib/expressions';
import { TypeURL as DT } from '../../../lib/util/Consts';
import * as Err from '../../../lib/util/Errors';
import { getMockEEFactory, getMockExpression } from '../../util/utils';

const DF = new DataFactory();
const BF = new BindingsFactory();
const two = DF.literal('2', DF.namedNode(DT.XSD_INTEGER));

function parse(expr: string) {
return translate(`SELECT * WHERE { ?s ?p ?o FILTER (${expr})}`).input.expression;
}

describe('evaluators', () => {
describe('SyncEvaluator', () => {
describe('evaluate', () => {
it('is able to evaluate', () => {
const evaluator = new SyncEvaluator(parse('1 + 1'));
expect(evaluator.evaluate(BF.bindings())).toEqual(two);
});

it('has proper default extended XSD type support', () => {
const evaluator = new SyncEvaluator(parse('1 + 1'));
expect(evaluator.evaluate(BF.bindings())).toEqual(two);
});
let factory: ExpressionEvaluatorFactory;
let actionContext: ActionContext;
beforeEach(() => {
factory = getMockEEFactory();
actionContext = new ActionContext({});
});

it('has proper extended XSD type support', () => {
const evaluator = new SyncEvaluator(parse('1 + "1"^^<http://example.com>'));
expect(() => evaluator.evaluate(BF.bindings())).toThrow(Err.InvalidArgumentTypes);
});
describe('evaluate', () => {
it('is able to evaluate', async() => {
const evaluator = factory.createEvaluator(getMockExpression('1 + 1'), actionContext);
expect(await evaluator.evaluate(BF.bindings())).toEqual(two);
});

describe('evaluateAsEBV', () => {
it('is able to evaluate to true', () => {
const evaluator = new SyncEvaluator(parse('1 + 1'));
expect(evaluator.evaluateAsEBV(BF.bindings())).toEqual(true);
});

it('is able to evaluate to false', () => {
const evaluator = new SyncEvaluator(parse('0'));
expect(evaluator.evaluateAsEBV(BF.bindings())).toEqual(false);
});
it('has proper default extended XSD type support', async() => {
const evaluator = factory.createEvaluator(getMockExpression('1 + 1'), actionContext);
expect(await evaluator.evaluate(BF.bindings())).toEqual(two);
});

describe('evaluateAsInternal', () => {
it('is able to evaluate', () => {
const evaluator = new SyncEvaluator(parse('1 + 1'));
expect(evaluator.evaluateAsInternal(BF.bindings())).toEqual(new IntegerLiteral(2));
});
it('has proper extended XSD type support', async() => {
const evaluator = factory.createEvaluator(getMockExpression('1 + "1"^^<http://example.com>'),
actionContext);
await expect(evaluator.evaluate(BF.bindings())).rejects.toThrow(Err.InvalidArgumentTypes);
});
});

describe('AsyncEvaluator', () => {
describe('evaluate', () => {
it('is able to evaluate', async() => {
const evaluator = new AsyncEvaluator(parse('1 + 1'));
expect(await evaluator.evaluate(BF.bindings())).toEqual(two);
});

it('has proper default extended XSD type support', async() => {
const evaluator = new AsyncEvaluator(parse('1 + 1'));
expect(await evaluator.evaluate(BF.bindings())).toEqual(two);
});

it('has proper extended XSD type support', async() => {
const evaluator = new AsyncEvaluator(parse('1 + "1"^^<http://example.com>'));
await expect(evaluator.evaluate(BF.bindings())).rejects.toThrow(Err.InvalidArgumentTypes);
});
describe('evaluateAsEBV', () => {
it('is able to evaluate to true', async() => {
const evaluator = factory.createEvaluator(getMockExpression('1 + 1'), actionContext);
expect(await evaluator.evaluateAsEBV(BF.bindings())).toEqual(true);
});

describe('evaluateAsEBV', () => {
it('is able to evaluate to true', async() => {
const evaluator = new AsyncEvaluator(parse('1 + 1'));
expect(await evaluator.evaluateAsEBV(BF.bindings())).toEqual(true);
});

it('is able to evaluate to false', async() => {
const evaluator = new AsyncEvaluator(parse('0'));
expect(await evaluator.evaluateAsEBV(BF.bindings())).toEqual(false);
});
it('is able to evaluate to false', async() => {
const evaluator = factory.createEvaluator(getMockExpression('0'), actionContext);
expect(await evaluator.evaluateAsEBV(BF.bindings())).toEqual(false);
});
});

describe('evaluateAsInternal', () => {
it('is able to evaluate', async() => {
const evaluator = new AsyncEvaluator(parse('1 + 1'));
expect(await evaluator.evaluateAsInternal(BF.bindings())).toEqual(new IntegerLiteral(2));
});
describe('evaluateAsInternal', () => {
it('is able to evaluate', async() => {
const evaluator = factory.createEvaluator(getMockExpression('1 + 1'), actionContext);
expect(await evaluator.evaluateAsInternal(BF.bindings())).toEqual(new IntegerLiteral(2));
});
});
});
Original file line number Diff line number Diff line change
@@ -1,121 +1,21 @@
import { BindingsFactory } from '@comunica/bindings-factory';
import { LRUCache } from 'lru-cache';
import { DataFactory } from 'rdf-data-factory';
import { translate } from 'sparqlalgebrajs';
import { expressionTypes, types } from 'sparqlalgebrajs/lib/algebra';
import { Wildcard } from 'sparqljs';
import { AsyncRecursiveEvaluator } from '../../../lib/evaluators/evaluatorHelpers/AsyncRecursiveEvaluator';
import { SyncRecursiveEvaluator } from '../../../lib/evaluators/evaluatorHelpers/SyncRecursiveEvaluator';
import { ExpressionType } from '../../../lib/expressions';
import * as E from '../../../lib/expressions';
import * as Err from '../../../lib/util/Errors';
import { getMockEEActionContext, getMockEEFactory } from '../../util/utils';

const BF = new BindingsFactory();
const DF = new DataFactory();

describe('recursive evaluators', () => {
const defaultTimeZone = { zoneMinutes: 0, zoneHours: 0 };

describe('SyncRecursiveEvaluator', () => {
const evaluator = new SyncRecursiveEvaluator({
now: new Date(),
functionArgumentsCache: {},
superTypeProvider: {
cache: new LRUCache({ max: 1_000 }),
discoverer: _ => 'term',
},
defaultTimeZone,
});

it('is able to evaluate operator', () => {
expect(evaluator.evaluate(new E.IntegerLiteral(1), BF.bindings())).toEqual(new E.IntegerLiteral(1));
});

it('is not able to evaluate existence by default', () => {
expect(() => evaluator.evaluate(new E.Existence({
type: types.EXPRESSION,
expressionType: expressionTypes.EXISTENCE,
not: false,
input: {
type: types.VALUES,
variables: [],
bindings: [],
},
}), BF.bindings())).toThrow(Err.NoExistenceHook);
});

it('is able to evaluate existence if configured', () => {
const customEvaluator = new SyncRecursiveEvaluator({
now: new Date(),
functionArgumentsCache: {},
superTypeProvider: {
cache: new LRUCache({ max: 1_000 }),
discoverer: _ => 'term',
},
exists: _ => true,
defaultTimeZone,
});

expect(customEvaluator.evaluate(new E.Existence({
type: types.EXPRESSION,
expressionType: expressionTypes.EXISTENCE,
not: false,
input: {
type: types.VALUES,
variables: [],
bindings: [],
},
}), BF.bindings())).toEqual(new E.BooleanLiteral(true));
});

it('is not able to evaluate aggregates by default', () => {
expect(() => evaluator.evaluate(new E.Aggregate('count', {
type: types.EXPRESSION,
expressionType: expressionTypes.AGGREGATE,
aggregator: 'count',
distinct: false,
expression: {
type: types.EXPRESSION,
expressionType: expressionTypes.WILDCARD,
wildcard: new Wildcard(),
},
}), BF.bindings())).toThrow(Err.NoAggregator);
});

it('is able to evaluate aggregates if configured', () => {
const customEvaluator = new SyncRecursiveEvaluator({
now: new Date(),
functionArgumentsCache: {},
superTypeProvider: {
cache: new LRUCache({ max: 1_000 }),
discoverer: _ => 'term',
},
aggregate: _ => DF.literal('42'),
defaultTimeZone,
});

expect(customEvaluator.evaluate(new E.Aggregate('count', {
type: types.EXPRESSION,
expressionType: expressionTypes.AGGREGATE,
aggregator: 'count',
distinct: false,
expression: {
type: types.EXPRESSION,
expressionType: expressionTypes.WILDCARD,
wildcard: new Wildcard(),
},
}), BF.bindings())).toEqual(new E.StringLiteral('42'));
});

it('is not able to evaluate async extensions', () => {
expect(() => evaluator.evaluate({
expressionType: ExpressionType.AsyncExtension,
name: DF.namedNode('http://example.com'),
async apply(_) { throw new Error('Error'); },
args: [],
}, BF.bindings())).toThrow(Err.InvalidExpressionType);
});
});

describe('AsyncRecursiveEvaluator', () => {
const evaluator = new AsyncRecursiveEvaluator({
now: new Date(),
Expand All @@ -125,7 +25,9 @@ describe('recursive evaluators', () => {
discoverer: _ => 'term',
},
defaultTimeZone,
});
actionContext: getMockEEActionContext(),
}, getMockEEFactory().createEvaluator(translate('SELECT * WHERE { ?s ?p ?o FILTER (1 + 1)}').input.expression,
getMockEEActionContext()));

it('is able to evaluate operator', async() => {
expect(await evaluator.evaluate(new E.IntegerLiteral(1), BF.bindings())).toEqual(new E.IntegerLiteral(1));
Expand Down Expand Up @@ -154,7 +56,9 @@ describe('recursive evaluators', () => {
},
exists: async _ => true,
defaultTimeZone,
});
actionContext: getMockEEActionContext(),
}, getMockEEFactory().createEvaluator(translate('SELECT * WHERE { ?s ?p ?o FILTER (1 + 1)}').input.expression,
getMockEEActionContext()));

expect(await customEvaluator.evaluate(new E.Existence({
type: types.EXPRESSION,
Expand Down Expand Up @@ -192,7 +96,9 @@ describe('recursive evaluators', () => {
},
aggregate: async _ => DF.literal('42'),
defaultTimeZone,
});
actionContext: getMockEEActionContext(),
}, getMockEEFactory().createEvaluator(translate('SELECT * WHERE { ?s ?p ?o FILTER (1 + 1)}').input.expression,
getMockEEActionContext()));

expect(await customEvaluator.evaluate(new E.Aggregate('count', {
type: types.EXPRESSION,
Expand Down
Loading

0 comments on commit 4de1891

Please sign in to comment.