AtteanX-Query-Cache
view release on metacpan or search on metacpan
t/simple-sparql-planner.t view on Meta::CPAN
=pod
=encoding utf-8
=head1 PURPOSE
Test that produced plans are correct.
=head1 SYNOPSIS
It may come in handy to enable logging for debugging purposes, e.g.:
LOG_ADAPTER=Screen DEBUG=1 prove -lv t/idp_sparql_planner.t
This requires that L<Log::Any::Adapter::Screen> is installed.
=head1 AUTHOR
Kjetil Kjernsmo E<lt>kjetilk@cpan.orgE<gt>.
=head1 COPYRIGHT AND LICENCE
This software is copyright (c) 2015, 2016 by Kjetil Kjernsmo.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut
use v5.14;
use autodie;
use utf8;
use Test::Modern;
use CHI;
use Attean;
use Attean::RDF;
use AtteanX::QueryPlanner::Cache;
use AtteanX::Store::Memory;
#use Carp::Always;
use Data::Dumper;
use AtteanX::Store::SPARQL;
use AtteanX::Model::SPARQLCache;
use Log::Any::Adapter;
Log::Any::Adapter->set($ENV{LOG_ADAPTER} ) if ($ENV{LOG_ADAPTER});
my $cache = CHI->new( driver => 'Memory', global => 1 );
my $p = AtteanX::QueryPlanner::Cache->new;
isa_ok($p, 'Attean::QueryPlanner');
isa_ok($p, 'AtteanX::QueryPlanner::Cache');
does_ok($p, 'Attean::API::CostPlanner');
{
# These tests does not actually look up anything in a real store, it just simulates
my $store = Attean->get_store('SPARQL')->new('endpoint_url' => iri('http://test.invalid/'));
isa_ok($store, 'AtteanX::Store::SPARQL');
my $model = AtteanX::Model::SPARQLCache->new( store => $store, cache => $cache );
my $graph = iri('http://test.invalid/graph');
my $t = triplepattern(variable('s'), iri('p'), literal('1'));
my $u = triplepattern(variable('s'), iri('p'), variable('o'));
my $v = triplepattern(variable('s'), iri('q'), blank('xyz'));
my $w = triplepattern(variable('a'), iri('b'), iri('c'));
my $x = triplepattern(variable('s'), iri('q'), iri('a'));
my $y = triplepattern(variable('o'), iri('b'), literal('2'));
my $z = triplepattern(variable('a'), iri('c'), variable('s'));
my $s = triplepattern(iri('a'), variable('p'), variable('o'));
subtest 'Empty BGP, to test basics' => sub {
note("An empty BGP should produce the join identity table plan");
my $bgp = Attean::Algebra::BGP->new(triples => []);
my $plan = $p->plan_for_algebra($bgp, $model, [$graph]);
does_ok($plan, 'Attean::API::Plan', 'Empty BGP');
isa_ok($plan, 'Attean::Plan::Table');
my $rows = $plan->rows;
is(scalar(@$rows), 1);
};
subtest '1-triple BGP single variable, with cache, not cached' => sub {
note("A 1-triple BGP should produce a single Attean::Plan::Iterator plan object");
$cache->set('?v001 <p> "1" .', ['<http://example.org/foo>', '<http://example.org/bar>']);
$cache->set('?v001 <p> "dahut" .', ['<http://example.com/foo>', '<http://example.com/bar>']);
$cache->set('?v001 <dahut> "1" .', ['<http://example.org/dahut>']);
ok($model->is_cached(triplepattern(variable('foo'), iri('p'), literal('1'))->canonicalize->tuples_string), 'Cache has been set');
ok(! $model->is_cached(triplepattern(variable('foo'), iri('q'), literal('1'))->canonicalize->tuples_string), 'Cache has not been set');
my $bgp = Attean::Algebra::BGP->new(triples => [$u]);
my $plan = $p->plan_for_algebra($bgp, $model, [$graph]);
does_ok($plan, 'Attean::API::Plan', '1-triple BGP');
isa_ok($plan, 'AtteanX::Plan::SPARQLBGP');
is(scalar @{$plan->children}, 1, '1-triple BGP child');
like($plan->as_string, qr|SPARQLBGP.*?Quad \{ \?s, <p>, \?o, <http://test.invalid/graph> }|s, 'Good plan');
is($plan->plan_as_string, 'SPARQLBGP', 'Good plan_as_string');
};
subtest '4-triple BGP with join variable with cache one cached' => sub {
my $bgp = Attean::Algebra::BGP->new(triples => [$t, $u, $y, $x]);
my @plans = $p->plans_for_algebra($bgp, $model, [$graph]);
is(scalar @plans, 5, 'Got 5 plans');
my $plan = $plans[0];
does_ok($plan, 'Attean::API::Plan::Join');
my @c1plans = sort @{$plan->children};
isa_ok($c1plans[0], 'Attean::Plan::Iterator', 'First child when sorted is an iterator');
isa_ok($c1plans[1], 'AtteanX::Plan::SPARQLBGP', 'Second child when sorted is a BGP');
is(scalar @{$c1plans[1]->children}, 3, '...with three children');
foreach my $plan (@{$c1plans[1]->children}) {
isa_ok($plan, 'Attean::Plan::Quad', 'All children are quads');
}
};
subtest '1-triple BGP two variables, with cache' => sub {
note("A 1-triple BGP should produce a single Attean::Plan::Iterator plan object");
$cache->set('?v002 <p> ?v001 .', {'<http://example.org/foo>' => ['<http://example.org/bar>'],
'<http://example.com/foo>' => ['<http://example.org/baz>', '<http://example.org/foobar>']});
( run in 1.518 second using v1.01-cache-2.11-cpan-39bf76dae61 )