File Coverage

blib/lib/Test/RDF/Trine/Store.pm
Criterion Covered Total %
statement 556 562 98.9
branch 22 38 57.8
condition 2 4 50.0
subroutine 36 36 100.0
pod 21 21 100.0
total 637 661 96.3


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Test::RDF::Trine::Store - A collection of functions to test RDF::Trine::Stores
4              
5             =head1 VERSION
6              
7             This document describes RDF::Trine version 1.018
8              
9             =head1 SYNOPSIS
10              
11             For example, to test a Memory store, do something like:
12              
13             use Test::RDF::Trine::Store qw(all_store_tests number_of_tests);
14             use Test::More tests => 1 + Test::RDF::Trine::Store::number_of_tests;
15              
16             use RDF::Trine qw(iri variable store literal);
17             use RDF::Trine::Store;
18              
19             my $data = Test::RDF::Trine::Store::create_data;
20              
21             my $store = RDF::Trine::Store::Memory->temporary_store();
22             isa_ok( $store, 'RDF::Trine::Store::Memory' );
23             Test::RDF::Trine::Store::all_store_tests($store, $data);
24              
25              
26              
27             =head1 DESCRIPTION
28              
29             This module packages a few functions that you can call to test a
30             L<RDF::Trine::Store>, also if it is outside of the main RDF-Trine
31             distribution.
32              
33             There are different functions that will test different parts of the
34             functionality, but you should run them all at some point, thus for the
35             most part, you would just like to run the C<all_store_tests> function
36             for quad stores and C<all_triple_store_tests> for triple stores
37             (i.e. stores that doesn't support named graphs).
38              
39             All the below functions are exported.
40              
41              
42             =cut
43              
44             package Test::RDF::Trine::Store;
45              
46 7     7   29909 use Test::More;
  7         78426  
  7         49  
47 7     7   4512 use Test::Exception;
  7         17002  
  7         23  
48              
49 7     7   1421 use strict;
  7         15  
  7         117  
50 7     7   35 use warnings;
  7         14  
  7         154  
51 7     7   31 no warnings 'redefine';
  7         15  
  7         203  
52              
53 7     7   1426 use RDF::Trine qw(iri variable store literal statement);
  7         19  
  7         464  
54 7     7   89 use RDF::Trine::Node;
  7         26  
  7         253  
55 7     7   40 use RDF::Trine::Statement;
  7         15  
  7         141  
56 7     7   33 use RDF::Trine::Store::DBI;
  7         14  
  7         185  
57 7     7   41 use RDF::Trine::Namespace qw(xsd);
  7         13  
  7         59  
58              
59             our ($VERSION);
60             BEGIN {
61 7     7   459 $VERSION = '1.018';
62             }
63              
64 7     7   43 use Log::Log4perl;
  7         19  
  7         46  
65              
66             Log::Log4perl->easy_init if $ENV{TEST_VERBOSE};
67              
68             our @EXPORT = qw(number_of_tests number_of_triple_tests create_data all_store_tests all_triple_store_tests add_quads add_triples contexts_tests add_statement_tests_simple count_statements_tests_simple count_statements_tests_quads count_statements_tests_triples get_statements_tests_triples get_pattern_tests get_statements_tests_quads remove_statement_tests);
69              
70              
71              
72             =head1 FUNCTIONS
73              
74             =over 4
75              
76             =item C<< number_of_tests >>
77              
78             Returns the number of tests run with C<all_store_tests>.
79              
80             =cut
81              
82             sub number_of_tests {
83 4     4 1 148 return 231; # Remember to update whenever adding tests
84             }
85              
86             =item C<< number_of_triple_tests >>
87              
88             Returns the number of tests run with C<all_triple_store_tests>.
89              
90             =cut
91              
92             sub number_of_triple_tests {
93 1     1 1 78 return 71; # Remember to update whenever adding tests
94             }
95              
96              
97             =item C<< create_data >>
98              
99             Returns a hashref with generated test data nodes to be used by other
100             tests.
101              
102             =cut
103              
104              
105             sub create_data {
106 4     4 1 74 my $ex = RDF::Trine::Namespace->new('http://example.com/');
107 4         60 my @names = ('a' .. 'z');
108 4         13 my @triples;
109             my @quads;
110 4         39 my $nil = RDF::Trine::Node::Nil->new();
111 4         21 foreach my $i (@names[0..2]) {
112 12         73 my $w = $ex->$i();
113 12         36 foreach my $j (@names[0..2]) {
114 36         137 my $x = $ex->$j();
115 36         86 foreach my $k (@names[0..2]) {
116 108         368 my $y = $ex->$k();
117 108         324 my $triple = RDF::Trine::Statement->new($w,$x,$y);
118 108         213 push(@triples, $triple);
119 108         192 foreach my $l (@names[0..2]) {
120 324         1158 my $z = $ex->$l();
121 324         826 my $quad = RDF::Trine::Statement::Quad->new($w,$x,$y,$z);
122 324         653 push(@quads, $quad);
123             }
124             }
125             }
126             }
127 4         42 return { ex => $ex, names => \@names, triples => \@triples, quads => \@quads, nil => $nil };
128             }
129              
130             =item C<< all_store_tests ($store, $data, $todo, $args) >>
131              
132             Will run all available tests for the given store, given the data from
133             C<create_data>. You may also set a third argument to some true value
134             to mark all tests as TODO in case the store is in development.
135              
136             Finally, an C<$args> hashref can be passed. Valid keys are
137             C<update_sleep> (see the function with the same name below) and
138             C<suppress_dupe_tests> if the store should skip duplicate detection,
139             C<quads_unsupported> if the store is a triple store.
140              
141             =cut
142              
143             sub all_store_tests {
144 3     3 1 2058 my ($store, $data, $todo, $args) = @_;
145 3   50     27 $args ||= {};
146            
147 3         7 my $ex = $data->{ex};
148 3         7 my @names = @{$data->{names}};
  3         28  
149 3         7 my @triples = @{$data->{triples}};
  3         20  
150 3         8 my @quads = @{$data->{quads}};
  3         33  
151 3         7 my $nil = $data->{nil};
152              
153 3         22 note "## Testing store " . ref($store);
154 3         420 isa_ok( $store, 'RDF::Trine::Store' );
155              
156             TODO: {
157 3 50       1382 local $TODO = ($todo) ? ref($store) . ' functionality is being worked on' : undef;
  3         17  
158            
159             throws_ok {
160 3     3   204 my $st = RDF::Trine::Statement::Quad->new($ex->a, $ex->b, $ex->c, $ex->d);
161 3         38 $store->add_statement( $st, $ex->e );
162 3         38 } 'RDF::Trine::Error::MethodInvocationError', 'add_statement throws when called with quad and context';
163            
164            
165             throws_ok {
166 3     3   121 my $st = RDF::Trine::Statement::Quad->new($ex->a, $ex->b, $ex->c, $ex->d);
167 3         16 $store->remove_statement( $st, $ex->e );
168 3         1487 } 'RDF::Trine::Error::MethodInvocationError', 'remove_statement throws when called with quad and context';
169            
170 3         1201 add_statement_tests_simple( $store, $args, $ex );
171 3         14 update_sleep($args);
172            
173 3         14 bulk_add_statement_tests_simple( $store, $args, $ex );
174 3         17 update_sleep($args);
175            
176 3         15 literals_tests_simple( $store, $args, $ex );
177 3         19 blank_node_tests_quads( $store, $args, $ex );
178 3         17 count_statements_tests_simple( $store, $args, $ex );
179            
180 3         1377 add_quads( $store, $args, @quads );
181 3         659 update_sleep($args);
182            
183 3         23 count_statements_tests_quads( $store, $args, $ex );
184            
185 3         1799 add_triples( $store, $args, @triples );
186 3         280 update_sleep($args);
187            
188 3         17 count_statements_tests_triples( $store, $args, $ex, $nil );
189 3         1840 contexts_tests( $store, $args );
190 3         2251 get_statements_tests_triples( $store, $args, $ex );
191 3         319 get_pattern_tests( $store, $args, $ex );
192 3         1567 get_statements_tests_quads( $store, $args, $ex, $nil );
193            
194 3         324 remove_statement_tests( $store, $args, $ex, @names );
195 3         1817 update_sleep($args);
196             }
197             }
198              
199             =item C<< all_triple_store_tests ($store, $data, $todo, $args) >>
200              
201             Will run tests for the given B<triple> store, i.e. a store that only
202             accepts triples, given the data from C<create_data>. You may also set
203             a third argument to some true value to mark all tests as TODO in case
204             the store is in development.
205              
206             For C<$args>, see above.
207              
208             =cut
209              
210             sub all_triple_store_tests {
211 1     1 1 992 my ($store, $data, $todo, $args) = @_;
212 1   50     12 $args ||= {};
213 1         4 $args->{quads_unsupported} = 1;
214 1         3 my $ex = $data->{ex};
215 1         3 my @names = @{$data->{names}};
  1         15  
216 1         3 my @triples = @{$data->{triples}};
  1         7  
217 1         3 my @quads = @{$data->{quads}};
  1         16  
218 1         3 my $nil = $data->{nil};
219              
220 1         9 note "## Testing store " . ref($store);
221 1         230 isa_ok( $store, 'RDF::Trine::Store' );
222              
223             TODO: {
224 1 50       462 local $TODO = ($todo) ? ref($store) . ' functionality is being worked on' : undef;
  1         8  
225            
226             lives_ok {
227 1     1   52 $store->get_contexts;
228 1         13 } 'get_context lives';
229            
230             # add_statement_tests_simple( $store, $args, $ex );
231             # update_sleep($args);
232             #
233             # bulk_add_statement_tests_simple( $store, $args, $ex );
234             # update_sleep($args);
235            
236 1         497 literals_tests_simple( $store, $args, $ex );
237 1         6 blank_node_tests_triples( $store, $args, $ex );
238             # count_statements_tests_simple( $store, $args, $ex );
239            
240 1         10 add_triples( $store, $args, @triples );
241 1         6 update_sleep($args);
242            
243             # count_statements_tests_triples( $store, $args, $ex, $nil );
244 1         6 get_statements_tests_triples( $store, $args, $ex );
245 1         7 get_pattern_tests( $store, $args, $ex );
246             }
247             }
248              
249             =item C<< add_quads($store, $args, @quads) >>
250              
251             Helper function to add an array of quads to the given store.
252              
253             =cut
254              
255              
256             sub add_quads {
257 3     3 1 35 my ($store, $args, @quads) = @_;
258 3         9 foreach my $q (@quads) {
259 243         23548 $store->add_statement( $q );
260             }
261             }
262              
263              
264             =item C<< add_triples($store, $args, @triples) >>
265              
266             Helper function to add an array of triples to the given store.
267              
268             =cut
269              
270             sub add_triples {
271 4     4 1 29 my ($store, $args, @triples) = @_;
272 4         15 foreach my $t (@triples) {
273 108         7420 $store->add_statement( $t );
274             }
275             }
276              
277             =item C<< contexts_tests( $store, $args ) >>
278              
279             Testing contexts (aka. "graphs")
280              
281             =cut
282              
283              
284             sub contexts_tests {
285 3     3 1 28 note "contexts tests";
286 3         423 my $store = shift;
287 3         10 my $args = shift;
288 3         35 my $iter = $store->get_contexts();
289 3         23 isa_ok( $iter, 'RDF::Trine::Iterator' );
290 3         2051 my %seen;
291 3         24 while (my $c = $iter->next) {
292 9         37 isa_ok( $c, 'RDF::Trine::Node' );
293 9         4800 $seen{ $c->as_string }++;
294             }
295 3         17 my $expect = {
296             '<http://example.com/a>' => 1,
297             '<http://example.com/b>' => 1,
298             '<http://example.com/c>' => 1,
299             };
300 3         21 is_deeply( \%seen, $expect, 'expected contexts' );
301             }
302              
303              
304             =item C<< add_statement_tests_simple( $store, $args, $data->{ex} ) >>
305              
306             Tests to check add_statement.
307              
308             =cut
309              
310              
311             sub add_statement_tests_simple {
312 3     3 1 16 note "simple add_statement tests";
313 3         383 my ($store, $args, $ex) = @_;
314            
315 3         24 my $triple = RDF::Trine::Statement->new($ex->a, $ex->b, $ex->c);
316 3         17 my $quad = RDF::Trine::Statement::Quad->new($ex->a, $ex->b, $ex->c, $ex->d);
317 3         30 my $etag_before = $store->etag;
318 3         16 update_sleep($args);
319 3         17 $store->add_statement( $triple, $ex->d );
320 3         343 update_sleep($args);
321             SKIP: {
322 3 100       6 skip 'It is OK to not support etag', 1 unless defined($etag_before);
  3         23  
323 1         4 isnt($etag_before, $store->etag, 'Etag has changed');
324             }
325              
326 3         1249 is( $store->size, 1, 'store has 1 statement after (triple+context) add' );
327            
328             TODO: {
329 3 50       1458 local $TODO = 'Duplicate detection is unsupported' if $args->{suppress_dupe_tests};
  3         19  
330 3         18 $store->add_statement( $quad );
331 3         17 update_sleep($args);
332 3         18 is( $store->size, 1, 'store has 1 statement after duplicate (quad) add' );
333             }
334            
335 3         1518 $etag_before = $store->etag;
336 3         33 $store->remove_statement( $triple, $ex->d );
337 3         361 update_sleep($args);
338             SKIP: {
339 3 100       7 skip 'It is OK to not support etag', 1 unless defined($etag_before);
  3         23  
340 1         4 isnt($etag_before, $store->etag, 'Etag has changed');
341             }
342              
343 3         1203 is( $store->size, 0, 'store has 0 statements after (triple+context) remove' );
344            
345 3         1429 my $quad2 = RDF::Trine::Statement::Quad->new($ex->a, $ex->b, $ex->c, iri('graph'));
346 3         17 $store->add_statement( $quad2 );
347 3         315 update_sleep($args);
348            
349 3         17 is( $store->size, 1, 'store has 1 statement after (quad) add' );
350            
351 3         1553 my $count = $store->count_statements( undef, undef, undef, iri('graph') );
352 3         24 is( $count, 1, 'expected count of specific-context statements' );
353            
354 3         1486 $store->remove_statement( $quad2 );
355 3         354 update_sleep($args);
356            
357 3         18 is( $store->size, 0, 'expected zero size after remove statement' );
358             }
359              
360              
361             =item C<< bulk_add_statement_tests_simple( $store, $args, $data->{ex} ) >>
362              
363             Tests to check add_statement.
364              
365             =cut
366              
367              
368             sub bulk_add_statement_tests_simple {
369 3     3 1 16 note "bulk add_statement tests";
370 3         416 my ($store, $args, $ex) = @_;
371              
372 3 50       52 $store->_begin_bulk_ops if ($store->can('_begin_bulk_ops'));
373 3         30 my $triple = RDF::Trine::Statement->new($ex->a, $ex->b, $ex->c);
374 3         16 my $quad = RDF::Trine::Statement::Quad->new($ex->a, $ex->b, $ex->c, $ex->d);
375 3         16 $store->add_statement( $triple, $ex->d );
376 3 50       312 $store->_end_bulk_ops if ($store->can('_end_bulk_ops'));
377            
378 3         19 update_sleep($args);
379            
380 3         19 is( $store->size, 1, 'store has 1 statement after (triple+context) add' ) ;
381            
382 3 50       1546 $store->_begin_bulk_ops if ($store->can('_begin_bulk_ops'));
383              
384             TODO: {
385 3 50       8 local $TODO = 'Duplicate detection is unsupported' if $args->{suppress_dupe_tests};
  3         14  
386 3         16 $store->add_statement( $quad );
387 3         21 update_sleep($args);
388 3         17 is( $store->size, 1, 'store has 1 statement after duplicate (quad) add' ) ;
389             }
390              
391 3 50       1736 $store->_end_bulk_ops if ($store->can('_end_bulk_ops'));
392            
393 3 50       39 $store->_begin_bulk_ops if ($store->can('_begin_bulk_ops'));
394 3         35 $store->remove_statement( $triple, $ex->d );
395 3         352 is( $store->size, 0, 'store has 0 statements after (triple+context) remove' );
396            
397 3         1547 my $quad2 = RDF::Trine::Statement::Quad->new($ex->a, $ex->b, $ex->c, iri('graph'));
398 3         23 $store->add_statement( $quad2 );
399 3 50       338 $store->_end_bulk_ops if ($store->can('_end_bulk_ops'));
400 3         17 update_sleep($args);
401            
402 3         26 is( $store->size, 1, 'store has 1 statement after (quad) add' );
403            
404 3         1501 my $count = $store->count_statements( undef, undef, undef, iri('graph') );
405 3         23 is( $count, 1, 'expected count of specific-context statements' );
406            
407 3         1447 $store->remove_statement( $quad2 );
408 3         325 update_sleep($args);
409            
410 3         22 is( $store->size, 0, 'expected zero size after remove statement' );
411             }
412              
413              
414             =item C<< literals_tests_simple( $store, $args, $data->{ex}) >>
415              
416             Tests to check literals support.
417              
418             =cut
419              
420             sub literals_tests_simple {
421 4     4 1 23 note "simple tests with literals";
422 4         564 my ($store, $args, $ex) = @_;
423            
424 4         52 my $litplain = RDF::Trine::Node::Literal->new('dahut');
425 4         17 my $litlang1 = RDF::Trine::Node::Literal->new('dahu', 'fr' );
426 4         18 my $litlang2 = RDF::Trine::Node::Literal->new('dahut', 'en' );
427 4         16 my $litutf8 = RDF::Trine::Node::Literal->new('blÃ¥bærsyltetøy', 'nb' );
428 4         68 my $litstring = RDF::Trine::Node::Literal->new('dahut', undef, $xsd->string);
429 4         20 my $litint = RDF::Trine::Node::Literal->new(42, undef, $xsd->integer);
430 4         14 my $triple = RDF::Trine::Statement->new($ex->a, $ex->b, $litplain);
431 4         28 my $quad = RDF::Trine::Statement::Quad->new($ex->a, $ex->b, $litplain, $ex->d);
432 4         24 $store->add_statement( $triple, $ex->d );
433 4         306 is( $store->size, 1, 'store has 1 statement after (triple+context) add' );
434             TODO: {
435 4 50       1937 local $TODO = 'Duplicate detection is unsupported' if $args->{suppress_dupe_tests};
  4         23  
436 4         25 $store->add_statement( $quad );
437 4         25 is( $store->size, 1, 'store has 1 statement after duplicate (quad) add' );
438             }
439 4         1987 $store->remove_statement( $triple, $ex->d );
440 4         339 is( $store->size, 0, 'store has 0 statements after (triple+context) remove' );
441              
442 4         2006 $store->add_statement( $quad );
443 4         326 my $quad2 = RDF::Trine::Statement::Quad->new($ex->a, $ex->b, $litlang2, $ex->d);
444 4         25 $store->add_statement( $quad2 );
445 4         296 is( $store->size, 2, 'store has 2 statements after (quad) add' );
446            
447             {
448 4         25 my $count = $store->count_statements( undef, undef, $litplain, undef );
449 4         31 is( $count, 1, 'expected 1 plain literal' );
450             }
451              
452             {
453 4         2043 my $iter = $store->get_statements( undef, undef, $litplain, undef );
  4         38  
454 4         30 isa_ok( $iter, 'RDF::Trine::Iterator' );
455 4         2380 my $st = $iter->next;
456 4         21 isa_ok( $st, 'RDF::Trine::Statement' );
457 4         1748 my $obj = $st->object;
458 4         16 isa_ok($obj, 'RDF::Trine::Node::Literal');
459 4         1773 is($obj->literal_value, 'dahut', 'expected triple get_statements bound object value' );
460             }
461              
462             {
463 4         1852 my $count = $store->count_statements( undef, undef, $litlang2, undef );
  4         24  
464 4         29 is( $count, 1, 'expected 1 language literal' );
465             }
466              
467             {
468 4         769 my $count = $store->count_statements( undef, undef, $litlang1, undef );
  4         1745  
  4         22  
469 4         22 is( $count, 0, 'expected 0 language literal' );
470             }
471              
472 4         1812 my $quad3 = RDF::Trine::Statement::Quad->new($ex->a, $ex->b, $litlang1, $ex->d);
473 4         26 $store->add_statement( $quad3 );
474 4         309 is( $store->size, 3, 'store has 3 statements after integer literal add' );
475              
476             {
477 4         2080 my $iter = $store->get_statements( undef, undef, $litlang1, undef );
  4         52  
478 4         23 my $st = $iter->next;
479 4         19 is($st->object->literal_value, 'dahu', 'expected triple get_statements bound object value' );
480 4         1790 is($st->object->literal_value_language, 'fr', 'expected triple get_statements bound object language' );
481 4         1512 is($st->object->literal_datatype, undef, 'expected triple get_statements bound object datatype is undef' );
482             }
483              
484              
485 4         888 my $triple2 = RDF::Trine::Statement->new($ex->a, $ex->b, $litstring);
486 4         26 $store->add_statement( $triple2 );
487 4         252 is( $store->size, 4, 'store has 4 statements after (triple) add' );
488              
489             {
490 4         25 my $count = $store->count_statements( undef, undef, $litplain, undef );
491 4         32 is( $count, 1, 'expected 1 plain literal' );
492             }
493             {
494 4         2069 my $count = $store->count_statements( undef, undef, $litstring, undef );
  4         23  
495 4         33 is( $count, 1, 'expected 1 string literal' );
496             }
497              
498             {
499 4         1805 my $iter = $store->get_statements( undef, undef, $litstring, undef );
  4         1773  
  4         27  
500 4         27 my $st = $iter->next;
501 4         22 is($st->object->literal_value, 'dahut', 'expected triple get_statements bound object value' );
502 4         1896 is($st->object->literal_value_language, undef, 'expected triple get_statements bound object language is undef' );
503 4         1567 is($st->object->literal_datatype, $xsd->string->value, 'expected triple get_statements bound object datatype is string' );
504             }
505              
506             SKIP: {
507 4 100       792 skip 'Quad-only test', 1 if $args->{quads_unsupported};
  4         58  
508 3         25 my $count = $store->count_statements( undef, undef, $litstring, $ex->d );
509 3         52 is( $count, 0, 'expected 0 string literal with context' );
510             }
511              
512 4         1672 $store->remove_statement($quad);
513 4         364 is( $store->size, 3, 'store has 3 statements after plain literal remove' );
514              
515 4         2174 my $quad4 = RDF::Trine::Statement::Quad->new($ex->a, $ex->b, $litint, $ex->d);
516 4         28 $store->add_statement( $quad4 );
517 4         295 is( $store->size, 4, 'store has 4 statements after integer literal add' );
518              
519             {
520 4         44 my $count = $store->count_statements( $ex->a, $ex->b, undef, undef);
521 4         73 is( $count, 4, 'expected 4 triples with all literals' );
522             }
523              
524             {
525 4         1925 my $count = $store->count_statements( $ex->a, $ex->b, $litint, undef );
  4         36  
526 4         56 is( $count, 1, 'expected 1 triple with integer literal' );
527             }
528              
529             {
530 4         1826 my $count = $store->count_statements( $ex->a, undef, $litlang1, undef );
  4         1807  
  4         39  
531 4         62 is( $count, 1, 'expected 1 triple with language literal' );
532             }
533              
534              
535 4         1888 $store->remove_statement($triple2);
536 4         312 is( $store->size, 3, 'store has 3 statements after string literal remove' );
537              
538 4         1865 $store->remove_statements(undef, undef, $litlang2, undef );
539 4         168 is( $store->size, 2, 'expected 2 statements after language remove statements' );
540              
541 4         1900 my $triple3 = RDF::Trine::Statement->new($ex->a, $ex->b, $litutf8);
542 4         28 $store->add_statement( $triple3 );
543 4         246 is( $store->size, 3, 'store has 3 statements after addition of literal with utf8 chars' );
544              
545             {
546 4         2023 my $iter = $store->get_statements( undef, undef, $litutf8, undef );
  4         27  
547 4         97 my $st = $iter->next;
548 4         28 isa_ok( $st, 'RDF::Trine::Statement' );
549 4         2128 is($st->object->literal_value, 'blÃ¥bærsyltetøy', 'expected triple get_statements bound object value with utf8 chars' );
550 4         1530 $store->remove_statement($st);
551 4         287 is( $store->size, 2, 'store has 2 statements after removal of literal with utf8 chars' );
552             }
553              
554              
555 4         833 $store->remove_statements($ex->a, $ex->b, undef, undef );
556 4         221 is( $store->size, 0, 'expected zero size after remove statements' );
557             }
558              
559              
560             =item C<< blank_node_tests_quads( $store, $args, $data->{ex} ) >>
561              
562             Tests to check blank node support for quads.
563              
564             =cut
565              
566              
567             sub blank_node_tests_quads {
568 3     3 1 19 note "quad tests with blank nodes";
569 3         416 my ($store, $args, $ex) = @_;
570            
571 3         27 my $blankfoo = RDF::Trine::Node::Blank->new('foo');
572 3         14 my $blankbar = RDF::Trine::Node::Blank->new('bar');
573 3         29 my $triple = RDF::Trine::Statement->new($blankfoo, $ex->b, $ex->c);
574 3         17 my $quad = RDF::Trine::Statement::Quad->new($blankfoo, $ex->b, $ex->c, $ex->d);
575 3         16 $store->add_statement( $triple, $ex->d );
576 3         286 is( $store->size, 1, 'store has 1 statement after (triple+context) add' );
577             TODO: {
578 3 50       1607 local $TODO = 'Duplicate detection is unsupported' if $args->{suppress_dupe_tests};
  3         16  
579 3         18 $store->add_statement( $quad );
580 3         20 is( $store->size, 1, 'store has 1 statement after duplicate (quad) add' );
581             }
582 3         1644 $store->remove_statement( $triple, $ex->d );
583 3         335 is( $store->size, 0, 'store has 0 statements after (triple+context) remove' );
584            
585 3         1586 my $quad2 = RDF::Trine::Statement::Quad->new($blankbar, $ex->b, $ex->c, $ex->d);
586 3         19 $store->add_statement( $quad2 );
587 3         301 is( $store->size, 1, 'store has 1 statement after (quad) add' );
588 3         1623 $store->add_statement( $quad );
589 3         302 is( $store->size, 2, 'store has 2 statements after (quad) add' );
590              
591 3         1593 my $triple2 = RDF::Trine::Statement->new($ex->a, $ex->b, $blankfoo);
592 3         21 $store->add_statement( $triple2 );
593 3         254 is( $store->size, 3, 'store has 3 statements after (quad) add' );
594              
595             {
596 3         33 my $count = $store->count_statements( undef, undef, undef, $ex->d );
597 3         23 is( $count, 2, 'expected count of specific-context statements' );
598             }
599              
600             {
601 3         1520 my $count = $store->count_statements( undef, undef, $blankfoo, $ex->d );
  3         28  
602 3         51 is( $count, 0, 'expected zero of specific-context statements' );
603             }
604              
605             {
606 3         1335 my $count = $store->count_statements( undef, undef, $blankfoo, undef );
  3         18  
607 3         23 is( $count, 1, 'expected one object blank node' );
608             }
609              
610             {
611 3         1437 my $count = $store->count_statements( $blankbar, undef, $blankfoo, undef );
  3         20  
612 3         52 is( $count, 0, 'expected zero subject-object blank node' );
613             }
614              
615             {
616 3         1396 my $count = $store->count_statements( $blankbar, undef, undef, undef );
  3         19  
617 3         26 is( $count, 1, 'expected one subject blank node' );
618             }
619              
620             {
621 3         1417 my $count = $store->count_statements( $blankfoo, undef, undef, $ex->d );
  3         35  
622 3         55 is( $count, 1, 'expected one subject-context blank node' );
623             }
624              
625             {
626 3         1376 my $count = $store->count_statements( $blankfoo, $ex->b, undef, undef );
  3         1349  
  3         29  
627 3         57 is( $count, 1, 'expected one subject-predicate blank node' );
628             }
629              
630 3         1430 $store->remove_statements( undef, undef, $blankfoo, undef );
631 3         166 is( $store->size, 2, 'expected two triples after remove statements' );
632            
633 3         1473 $store->remove_statement( $quad2 );
634 3         364 is( $store->size, 1, 'expected single triples after remove statement' );
635 3         1636 $store->remove_statement( $quad );
636 3         329 is( $store->size, 0, 'expected zero size after remove statement' );
637             }
638              
639             =item C<< blank_node_tests_triples( $store, $args, $data->{ex} ) >>
640              
641             Tests to check blank node support for triples.
642              
643             =cut
644              
645              
646             sub blank_node_tests_triples {
647 1     1 1 7 note "triple tests with blank nodes";
648 1         191 my ($store, $args, $ex) = @_;
649            
650 1         13 my $blankfoo = RDF::Trine::Node::Blank->new('foo');
651 1         5 my $blankbar = RDF::Trine::Node::Blank->new('bar');
652 1         9 my $triple = RDF::Trine::Statement->new($blankfoo, $ex->b, $ex->c);
653 1         295 my $triple2 = RDF::Trine::Statement->new($ex->c, $ex->d, $blankbar);
654 1         8 $store->add_statement( $triple );
655 1         6 is( $store->size, 1, 'store has 1 statement after (triple) add' );
656             TODO: {
657 1 50       425 local $TODO = 'Duplicate detection is unsupported' if $args->{suppress_dupe_tests};
  1         5  
658 1         5 $store->add_statement( $triple );
659 1         5 is( $store->size, 1, 'store has 1 statement after duplicate (triple) add' );
660             }
661 1         408 $store->remove_statement( $triple );
662 1         4 is( $store->size, 0, 'store has 0 statements after (triple) remove' );
663            
664 1         421 $store->add_statement( $triple2 );
665 1         5 is( $store->size, 1, 'store has 1 statement after (triple) add' );
666 1         418 $store->add_statement( $triple );
667 1         7 is( $store->size, 2, 'store has 2 statements after (triple) add' );
668              
669 1         417 my $triple3 = RDF::Trine::Statement->new($ex->a, $ex->b, $blankfoo);
670 1         7 $store->add_statement( $triple3 );
671 1         5 is( $store->size, 3, 'store has 3 statements after (triple) add' );
672              
673             {
674 1         10 my $count = $store->count_statements( undef, undef, $blankfoo, undef );
675 1         6 is( $count, 1, 'expected one object blank node' );
676             }
677              
678             {
679 1         416 my $count = $store->count_statements( $blankbar, undef, $blankfoo, undef );
  1         7  
680 1         4 is( $count, 0, 'expected zero subject-object blank node' );
681             }
682              
683             {
684 1         427 my $count = $store->count_statements( $blankfoo, undef, undef, $ex->d );
  1         11  
685 1         6 is( $count, 0, 'expected zero subject-context blank node' );
686             }
687              
688             {
689 1         403 my $count = $store->count_statements( $blankfoo, $ex->b, undef, undef );
  1         403  
  1         9  
690 1         4 is( $count, 1, 'expected one subject-predicate blank node' );
691             }
692              
693 1         444 $store->remove_statements( undef, undef, $blankfoo, undef );
694 1         6 is( $store->size, 2, 'expected two triples after remove statements' );
695 1         501 $store->remove_statement( $triple2 );
696 1         6 is( $store->size, 1, 'expected single triples after remove statement' );
697 1         477 $store->remove_statement( $triple );
698 1         7 is( $store->size, 0, 'expected zero size after remove statement' );
699             }
700              
701              
702             =item C<< count_statements_tests_simple( $store, $args, $data->{ex} ) >>
703              
704             Tests to check that counts are correct.
705              
706             =cut
707              
708             sub count_statements_tests_simple {
709 3     3 1 19 note " simple count_statements tests";
710 3         416 my ($store, $args, $ex) = @_;
711            
712             {
713 3         8 is( $store->size, 0, 'expected zero size before add statement' );
  3         16  
714 3         1268 my $st = RDF::Trine::Statement::Quad->new( $ex->a, $ex->b, $ex->c, $ex->d );
715 3         20 $store->add_statement( $st );
716              
717 3         354 is( $store->size, 1, 'size' );
718 3         1642 is( $store->count_statements(), 1, 'count_statements()' );
719 3         1239 is( $store->count_statements(undef, undef, undef), 1, 'count_statements(fff) with undefs' );
720 3         1365 is( $store->count_statements(undef, undef, undef, undef), 1, 'count_statements(ffff) with undefs' );
721             SKIP: {
722 3 50       1164 skip 'Quad-only test', 2 if $args->{quads_unsupported};
  3         18  
723 3         12 is( $store->count_statements(map {variable($_)} qw(s p o)), 1, 'count_statements(fff) with variables' );
  9         31  
724 3         1248 is( $store->count_statements(map {variable($_)} qw(s p o g)), 1, 'count_statements(ffff) with variables' );
  12         34  
725             }
726              
727             # 1-bound
728 3         1488 is( $store->count_statements($ex->a, undef, undef, undef), 1, 'count_statements(bfff)' );
729 3         1417 is( $store->count_statements(undef, $ex->b, undef, undef), 1, 'count_statements(fbff)' );
730 3         1325 is( $store->count_statements(undef, undef, $ex->c, undef), 1, 'count_statements(ffbf)' );
731 3         1249 is( $store->count_statements(undef, undef, undef, $ex->d), 1, 'count_statements(fffb)' );
732            
733             # 2-bound
734             # local($::debug) = 1;
735 3         1222 is( $store->count_statements($ex->a, $ex->b, undef, undef), 1, 'count_statements(bbff)' );
736 3         1412 is( $store->count_statements(undef, $ex->b, $ex->c, undef), 1, 'count_statements(fbbf)' );
737 3         1476 is( $store->count_statements(undef, undef, $ex->c, $ex->d), 1, 'count_statements(ffbb)' );
738 3         1497 is( $store->count_statements($ex->a, undef, undef, $ex->d), 1, 'count_statements(bffb)' );
739            
740 3         1459 $store->remove_statement( $st );
741 3         357 is( $store->size, 0, 'size' );
742             }
743            
744 3         47 is( $store->count_statements( $ex->z, undef, undef, undef ), 0, 'count_statements(bfff) empty result set' );
745 3         1396 is( $store->count_statements( $ex->z, undef, undef, $ex->x ), 0, 'count_statements(bffb) empty result set' );
746            
747             }
748              
749              
750             =item C<< count_statements_tests_quads( $store, $args, $data->{ex} ) >>
751              
752             Count statement tests for quads.
753              
754              
755             =cut
756              
757              
758             sub count_statements_tests_quads {
759 3     3 1 28 note " quad count_statements tests";
760 3         921 my ($store, $args, $ex) = @_;
761             {
762 3         10 is( $store->count_statements, 27, 'count_statements()' );
  3         20  
763 3         1644 is( $store->count_statements(undef, undef, undef), 27, 'count_statements( fff )' );
764 3         1622 is( $store->count_statements(undef, undef, undef, undef), 81, 'count_statements( ffff )' );
765            
766 3         1394 is( $store->count_statements( $ex->a, undef, undef ), 9, 'count_statements( bff )' );
767 3         1721 is( $store->count_statements( $ex->a, undef, undef, undef ), 27, 'count_statements( bfff )' );
768 3         1854 is( $store->count_statements( $ex->a, undef, undef, $ex->a ), 9, 'count_statements( bffb )' );
769             }
770             }
771              
772              
773             =item C<< count_statements_tests_triples( $store, $args, $data->{ex}, $data->{nil} ) >>
774              
775             More tests for counts, with triples.
776              
777              
778             =cut
779              
780              
781             sub count_statements_tests_triples {
782 3     3 1 23 note " triple count_statements tests";
783 3         792 my ($store, $args, $ex, $nil) = @_;
784            
785             {
786 3         9 is( $store->count_statements, 27, 'count_statements() after triples added' );
  3         17  
787 3         1639 is( $store->count_statements(undef, undef, undef), 27, 'count_statements( fff ) after triples added' );
788 3         1418 is( $store->count_statements( $ex->a, undef, undef ), 9, 'count_statements( bff )' );
789 3         1702 is( $store->count_statements( $ex->a, undef, undef, $nil ), 9, 'count_statements( bffb )' );
790             SKIP: {
791 3 50       1637 skip 'Quad-only test', 2 if $args->{quads_unsupported};
  3         19  
792 3         22 is( $store->count_statements(undef, undef, undef, undef), 108, 'count_statements( ffff ) after triples added' );
793 3         1736 is( $store->count_statements( $ex->a, undef, undef, undef ), 27+9, 'count_statements( bfff )' );
794             }
795              
796             }
797             }
798              
799              
800             =item C<< get_statements_tests_triples( $store, $args, $data->{ex} ) >>
801              
802             Tests for getting statements using triples.
803              
804             =cut
805              
806              
807             sub get_statements_tests_triples {
808 4     4 1 26 note " triple get_statements tests";
809 4         902 my ($store, $args, $ex) = @_;
810            
811             {
812 4         32 my $iter = $store->get_statements( undef, undef, undef );
813 4         30 isa_ok( $iter, 'RDF::Trine::Iterator' );
814 4         2868 my $count = 0;
815 4         48 while (my $st = $iter->next()) {
816 108         287 $count++;
817             }
818 4         42 is( $count, 27, 'get_statements( fff ) expected result count' );
819 4         2230 is( $iter->next, undef, 'triple iterator end-of-stream' );
820             }
821            
822             {
823 4         13 my $iter = $store->get_statements( $ex->a, variable('p'), variable('o') );
  4         54  
824 4         30 isa_ok( $iter, 'RDF::Trine::Iterator' );
825 4         2579 my $count = 0;
826 4         24 while (my $st = $iter->next()) {
827 36         120 ok( $st->subject->equal( $ex->a ), 'expected triple get_statements bound subject' );
828 36         15378 $count++;
829             }
830 4         26 is( $count, 9, 'get_statements( bff ) expected result count' );
831             }
832            
833             {
834 4         1825 my $iter = $store->get_statements( $ex->d, undef, undef );
  4         331  
  4         45  
835 4         32 isa_ok( $iter, 'RDF::Trine::Iterator' );
836 4         2749 my $count = 0;
837 4         24 while (my $st = $iter->next()) {
838 0         0 $count++;
839             }
840 4         21 is( $count, 0, 'get_statements( bff ) expected empty results' );
841             }
842             }
843              
844              
845             =item C<< get_statements_tests_quads( $store, $args, $data->{ex}, $data->{nil} ) >>
846              
847             Tests for getting statements using quads.
848              
849             =cut
850              
851             sub get_statements_tests_quads {
852 3     3 1 20 note " quad get_statements tests";
853 3         509 my ($store, $args, $ex, $nil) = @_;
854            
855             {
856 3         22 my $iter = $store->get_statements( undef, undef, undef, undef );
857 3         19 isa_ok( $iter, 'RDF::Trine::Iterator' );
858 3         1838 my $count = 0;
859 3         19 while (my $st = $iter->next()) {
860 324         821 $count++;
861             }
862 3         19 is( $count, 108, 'get_statements( ffff ) expected result count' );
863 3         1849 is( $iter->next, undef, 'quad iterator end-of-stream' );
864             }
865            
866             {
867 3         10 my $iter = $store->get_statements( $ex->a, , variable('p'), variable('o'), variable('g') );
  3         47  
868 3         24 isa_ok( $iter, 'RDF::Trine::Iterator' );
869 3         1952 my $count = 0;
870 3         20 while (my $st = $iter->next()) {
871 108         422 ok( $st->subject->equal( $ex->a ), 'expected triple get_statements bound subject' );
872 108         49592 $count++;
873             }
874 3         18 is( $count, 27+9, 'get_statements( bfff ) expected result count' );
875             }
876            
877             {
878 3         1840 my $iter = $store->get_statements( $ex->d, undef, undef, undef );
  3         32  
879 3         22 isa_ok( $iter, 'RDF::Trine::Iterator' );
880 3         1900 my $count = 0;
881 3         20 while (my $st = $iter->next()) {
882 0         0 $count++;
883             }
884 3         21 is( $count, 0, 'get_statements( bfff ) expected empty results' );
885             }
886            
887             {
888 3         317 my $iter = $store->get_statements( undef, undef, undef, $nil );
  3         18  
889 3         21 isa_ok( $iter, 'RDF::Trine::Iterator' );
890 3         1984 my $count = 0;
891 3         20 while (my $st = $iter->next()) {
892 81         213 $count++;
893             }
894 3         21 is( $count, 27, 'get_statements( fffb ) expected result count 1' );
895             }
896            
897             {
898 3         312 my $iter = $store->get_statements( undef, undef, undef, $ex->a );
  3         38  
899 3         23 isa_ok( $iter, 'RDF::Trine::Iterator' );
900 3         1908 my $count = 0;
901 3         20 while (my $st = $iter->next()) {
902 81         247 ok( $st->context->equal( $ex->a ), 'expected triple get_statements bound context' );
903 81         31666 $count++;
904             }
905 3         18 is( $count, 27, 'get_statements( fffb ) expected result count 2' );
906             }
907            
908             {
909 3         1720 my $iter = $store->get_statements( $ex->a, $ex->b, undef, undef );
  3         25  
910 3         19 isa_ok( $iter, 'RDF::Trine::Iterator' );
911 3         1664 my $count = 0;
912 3         19 while (my $st = $iter->next()) {
913 36         120 ok( $st->subject->equal( $ex->a ), 'expected triple get_statements bound subject' );
914 36         14180 ok( $st->predicate->equal( $ex->b ), 'expected triple get_statements bound predicate' );
915 36         14162 $count++;
916             }
917 3         20 is( $count, 9+3, 'get_statements( bbff ) expected result count' );
918             }
919            
920             {
921 3         310 my $iter = $store->get_statements( $ex->a, $ex->z, undef, undef );
  3         317  
  3         28  
922 3         63 isa_ok( $iter, 'RDF::Trine::Iterator' );
923 3         2135 my $count = 0;
924 3         22 while (my $st = $iter->next()) {
925 0         0 $count++;
926             }
927 3         17 is( $count, 0, 'get_statements( bbff ) expected empty result' );
928             }
929            
930             }
931              
932              
933             =item C<< get_pattern_tests( $store, $args, $data->{ex} ) >>
934              
935             Tests for getting statements using with get_pattern.
936              
937             =cut
938              
939              
940             sub get_pattern_tests {
941 4     4 1 25 note " get_pattern tests";
942 4         640 my ($store, $args, $ex) = @_;
943 4         56 my $model = RDF::Trine::Model->new($store);
944 4         36 my $nil = RDF::Trine::Node::Nil->new();
945             {
946 4         42 my $iter = $model->get_pattern( RDF::Trine::Pattern->new(
947             statement(
948             $ex->a, $ex->b, variable('o1'), $nil,
949             ),
950             statement(
951             $ex->a, $ex->c, variable('o2'), $nil,
952             ),
953             )
954             );
955 4         40 isa_ok( $iter, 'RDF::Trine::Iterator::Bindings' );
956 4         2711 my $count = 0;
957 4         29 while (my $st = $iter->next()) {
958 36         125 $count++;
959             }
960 4         12 my $expected = 9;
961 4         32 is( $count, $expected, 'get_pattern( bbf, bbf ) expected result count' );
962 4         2130 is( $iter->next, undef, 'pattern iterator end-of-stream' );
963             }
964             {
965 4         12 my $iter = $model->get_pattern( RDF::Trine::Pattern->new(
  4         1728  
  4         50  
966             statement(
967             $ex->a, $ex->b, variable('o1'), $nil,
968             ),
969             statement(
970             $ex->a, $ex->c, literal('DAAAAHUUUT'), $nil,
971             ),
972             )
973             );
974 4         34 isa_ok( $iter, 'RDF::Trine::Iterator::Bindings' );
975 4         2900 my $count = 0;
976 4         26 while (my $st = $iter->next()) {
977 0         0 $count++;
978             }
979 4         24 is( $count, 0, 'get_pattern( bbf, bbu ) expected result count' );
980 4         1848 is( $iter->next, undef, 'pattern iterator end-of-stream' );
981             }
982             }
983              
984              
985              
986              
987             =item C<< remove_statement_tests( $store, $args, $data->{ex}, @{$data->{names}} ); >>
988              
989             Tests for removing statements.
990              
991              
992             =cut
993              
994              
995             sub remove_statement_tests {
996 3     3 1 20 note " remove_statement tests";
997 3         522 my ($store, $args, $ex, @names) = @_;
998 3         25 is( $store->count_statements( undef, undef, undef, undef ), 108, 'store size before quad removal' );
999 3         1376 foreach my $i (@names[0..2]) {
1000 9         83 my $w = $ex->$i();
1001 9         34 foreach my $j (@names[0..2]) {
1002 27         236 my $x = $ex->$j();
1003 27         98 foreach my $k (@names[0..2]) {
1004 81         599 my $y = $ex->$k();
1005 81         267 foreach my $l (@names[0..2]) {
1006 243         1714 my $z = $ex->$l();
1007 243         1108 my $quad = RDF::Trine::Statement::Quad->new($w,$x,$y,$z);
1008 243         923 $store->remove_statement( $quad );
1009             }
1010             }
1011             }
1012             }
1013 3         19 update_sleep($args);
1014            
1015 3         20 is( $store->count_statements( undef, undef, undef, undef ), 27, 'quad count after quad removal' );
1016 3         1812 is( $store->count_statements( undef, undef, undef ), 27, 'triple count after quad removal' );
1017            
1018 3         1201 $store->remove_statements( $ex->a, undef, undef, undef );
1019 3         154 update_sleep($args);
1020            
1021 3         16 is( $store->count_statements( undef, undef, undef ), 18, 'triple count after remove_statements( bfff )' );
1022            
1023 3         1459 foreach my $i (@names[0..2]) {
1024 9         97 my $w = $ex->$i();
1025 9         39 foreach my $j (@names[0..2]) {
1026 27         213 my $x = $ex->$j();
1027 27         97 foreach my $k (@names[0..2]) {
1028 81         642 my $y = $ex->$k();
1029 81         430 my $triple = RDF::Trine::Statement->new($w,$x,$y);
1030 81         344 $store->remove_statement( $triple );
1031             }
1032             }
1033             }
1034 3         20 update_sleep($args);
1035            
1036 3         20 is( $store->count_statements( undef, undef, undef, undef ), 0, 'quad count after triple removal' );
1037             }
1038              
1039              
1040             =item C<< update_sleep ( \%args ) >>
1041              
1042             If C<< $args{ update_sleep } >> is defined, sleeps for that many seconds.
1043             This function is called after update operations to aid in testing stores that
1044             perform updates asynchronously.
1045              
1046             =cut
1047              
1048             sub update_sleep {
1049 55     55 1 137 my $args = shift;
1050 55 50       297 if (defined($args->{ update_sleep })) {
1051 0           note ' sleeping ' . $args->{ update_sleep }. ' secs after store update';
1052 0           sleep($args->{ update_sleep });
1053             }
1054             }
1055              
1056             1;
1057             __END__
1058              
1059             =back
1060              
1061             =head1 BUGS
1062              
1063             Please report any bugs or feature requests to through the GitHub web interface
1064             at L<https://github.com/kasei/perlrdf/issues>.
1065              
1066             =head1 AUTHOR
1067              
1068             Gregory Todd Williams <gwilliams@cpan.org> and Kjetil Kjernsmo <kjetilk@cpan.org>
1069              
1070             =cut