AggregatesTest   A
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 569
Duplicated Lines 0 %

Importance

Changes 3
Bugs 1 Features 1
Metric Value
eloc 142
c 3
b 1
f 1
dl 0
loc 569
rs 10
wmc 18

16 Methods

Rating   Name   Duplication   Size   Complexity  
A testAgg08b() 0 19 1
A testAgg08() 0 18 1
A testAgg05() 0 33 1
A testAgg01() 0 25 1
A testAgg02() 0 34 1
A setUp() 0 6 1
A testAgg04() 0 24 1
A testAggMax01() 0 28 1
A testAggMin01() 0 28 1
A testAgg09() 0 29 1
A testAggEmptyGroup() 0 12 1
A testAgg10() 0 29 1
A testAggMax02() 0 48 1
A testAggAvg01() 0 28 1
A testAggSum01() 0 43 2
A testAggSum02() 0 74 2
1
<?php
2
3
/**
4
 * This file is part of the sweetrdf/InMemoryStoreSqlite package and licensed under
5
 * the terms of the GPL-2 license.
6
 *
7
 * (c) Konrad Abicht <[email protected]>
8
 * (c) Benjamin Nowack
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Tests\Integration\Store\InMemoryStoreSqlite\SPARQL11;
15
16
use Exception;
17
18
/**
19
 * Runs W3C tests from https://www.w3.org/2009/sparql/docs/tests/.
20
 *
21
 * Version: 2012-10-23 20:52 (sparql11-test-suite-20121023.tar.gz)
22
 *
23
 * Tests are located in the w3c-tests folder.
24
 *
25
 * @group linux
26
 */
27
class AggregatesTest extends ComplianceTestCase
28
{
29
    protected function setUp(): void
30
    {
31
        parent::setUp();
32
33
        $this->w3cTestsFolderPath = __DIR__.'/w3c-tests/aggregates';
34
        $this->testPref = 'http://www.w3.org/2009/sparql/docs/tests/data-sparql11/aggregates/manifest#';
35
    }
36
37
    public function testAgg01()
38
    {
39
        $this->store->query('
40
            PREFIX : <http://www.example.org/> .
41
            INSERT INTO <http://agg> {
42
                :s :p1 :o1, :o2, :o3.
43
                :s :p2 :o1, :o2.
44
            }
45
        ');
46
47
        $query = 'PREFIX : <http://www.example.org>
48
            SELECT (COUNT(?O) AS ?C)
49
            WHERE { ?S ?P ?O }
50
        ';
51
52
        $result = $this->store->query($query);
53
54
        $this->assertEquals(
55
            [
56
                [
57
                    'C' => '5',
58
                    'C type' => 'literal',
59
                ],
60
            ],
61
            $result['result']['rows']
62
        );
63
    }
64
65
    public function testAgg02()
66
    {
67
        $this->store->query('
68
            PREFIX : <http://www.example.org/> .
69
            INSERT INTO <http://agg> {
70
                :s :p1 :o1, :o2, :o3.
71
                :s :p2 :o1, :o2.
72
            }
73
        ');
74
75
        $query = 'PREFIX : <http://www.example.org>
76
            SELECT ?P (COUNT(?O) AS ?C)
77
            WHERE { ?S ?P ?O }
78
            GROUP BY ?P
79
        ';
80
81
        $result = $this->store->query($query);
82
83
        $this->assertEquals(
84
            [
85
                [
86
                    'P' => 'http://www.example.org/p1',
87
                    'P type' => 'uri',
88
                    'C' => '3',
89
                    'C type' => 'literal',
90
                ],
91
                [
92
                    'P' => 'http://www.example.org/p2',
93
                    'P type' => 'uri',
94
                    'C' => '2',
95
                    'C type' => 'literal',
96
                ],
97
            ],
98
            $result['result']['rows']
99
        );
100
    }
101
102
    /*
103
     * agg03 fails, because store cant properly handle:
104
     *
105
     *      HAVING (COUNT(?O) > 2 )
106
     *
107
     * in query:
108
     *
109
     *      PREFIX : <http://www.example.org>
110
     *
111
     *      SELECT ?P (COUNT(?O) AS ?C)
112
     *      WHERE { ?S ?P ?O }
113
     *      GROUP BY ?P
114
     *      HAVING (COUNT(?O) > 2 )
115
     */
116
117
    public function testAgg04()
118
    {
119
        $this->store->query('
120
            PREFIX : <http://www.example.org/> .
121
            INSERT INTO <http://agg> {
122
                :s :p1 :o1, :o2, :o3.
123
                :s :p2 :o1, :o2.
124
            }
125
        ');
126
127
        $query = 'PREFIX : <http://www.example.org>
128
            SELECT (COUNT(*) AS ?C)
129
            WHERE { ?S ?P ?O }';
130
131
        $result = $this->store->query($query);
132
133
        $this->assertEquals(
134
            [
135
                [
136
                    'C' => '5',
137
                    'C type' => 'literal',
138
                ],
139
            ],
140
            $result['result']['rows']
141
        );
142
    }
143
144
    public function testAgg05()
145
    {
146
        $this->store->query('
147
            PREFIX : <http://www.example.org/> .
148
            INSERT INTO <http://agg> {
149
                :s :p1 :o1, :o2, :o3.
150
                :s :p2 :o1, :o2.
151
            }
152
        ');
153
154
        $query = 'PREFIX : <http://www.example.org>
155
            SELECT ?P (COUNT(*) AS ?C)
156
            WHERE { ?S ?P ?O }
157
            GROUP BY ?P';
158
159
        $result = $this->store->query($query);
160
161
        $this->assertEquals(
162
            [
163
                [
164
                    'P' => 'http://www.example.org/p1',
165
                    'P type' => 'uri',
166
                    'C' => '3',
167
                    'C type' => 'literal',
168
                ],
169
                [
170
                    'P' => 'http://www.example.org/p2',
171
                    'P type' => 'uri',
172
                    'C' => '2',
173
                    'C type' => 'literal',
174
                ],
175
            ],
176
            $result['result']['rows']
177
        );
178
    }
179
180
    /*
181
     * agg06, agg07 fails, because store cant properly handle:
182
     *
183
     *      HAVING (COUNT(?O) > 0)
184
     */
185
186
    public function testAgg08()
187
    {
188
        $this->expectException(Exception::class);
189
190
        $this->store->query('
191
            PREFIX : <http://www.example.org/> .
192
            INSERT INTO <http://agg> {
193
                :s :p1 :o1, :o2, :o3.
194
                :s :p2 :o1, :o2.
195
            }
196
        ');
197
198
        $query = 'PREFIX : <http://www.example.org/>
199
            SELECT ((?O1 + ?O2) AS ?O12) (COUNT(?O1) AS ?C)
200
            WHERE { ?S :p ?O1; :q ?O2 } GROUP BY (?O1 + ?O2)
201
            ORDER BY ?O12';
202
203
        $this->store->query($query);
204
    }
205
206
    public function testAgg08b()
207
    {
208
        $this->expectException(Exception::class);
209
210
        $this->store->query('
211
            PREFIX : <http://www.example.org/> .
212
            INSERT INTO <http://agg> {
213
                :s :p1 :o1, :o2, :o3.
214
                :s :p2 :o1, :o2.
215
            }
216
        ');
217
218
        $query = 'PREFIX : <http://www.example.org/>
219
            SELECT ?O12 (COUNT(?O1) AS ?C)
220
            WHERE { ?S :p ?O1; :q ?O2 } GROUP BY ((?O1 + ?O2) AS ?O12)
221
            ORDER BY ?O12
222
        ';
223
224
        $this->store->query($query);
225
    }
226
227
    /**
228
     * Using original SELECT query returns a different result on scrutinizer,
229
     * which leads to failing test. It used p2 instead of p1 on scrutinizer.
230
     *
231
     * @see https://scrutinizer-ci.com/g/sweetrdf/in-memory-store-sqlite/inspections/88339e50-3676-4224-b0d2-8cd0f5d56bf7
232
     *
233
     * Therefore removing ?P from SELECT header.
234
     */
235
    public function testAgg09()
236
    {
237
        $this->store->query('
238
            PREFIX : <http://www.example.org/> .
239
            INSERT INTO <http://agg> {
240
                :s :p1 :o1,
241
                       :o2,
242
                       :o3 .
243
                :s :p2 :o1,
244
                       :o2 .
245
            }
246
        ');
247
248
        // originally there was a ?P in the select header
249
        $query = 'PREFIX : <http://www.example.org/>
250
            SELECT (COUNT(?O) AS ?C)
251
            WHERE { ?S ?P ?O } GROUP BY ?S
252
        ';
253
254
        $result = $this->store->query($query);
255
256
        $this->assertEquals(
257
            [
258
                [
259
                    'C' => '5',
260
                    'C type' => 'literal',
261
                ],
262
            ],
263
            $result['result']['rows']
264
        );
265
    }
266
267
    /**
268
     * Using original SELECT query returns a different result on scrutinizer,
269
     * which leads to failing test. It used p2 instead of p1 on scrutinizer.
270
     *
271
     * @see https://scrutinizer-ci.com/g/sweetrdf/in-memory-store-sqlite/inspections/88339e50-3676-4224-b0d2-8cd0f5d56bf7
272
     *
273
     * Therefore removing ?P from SELECT header.
274
     */
275
    public function testAgg10()
276
    {
277
        $this->store->query('
278
            PREFIX : <http://www.example.org/> .
279
            INSERT INTO <http://agg> {
280
                :s :p1 :o1,
281
                       :o2,
282
                       :o3 .
283
                :s :p2 :o1,
284
                       :o2 .
285
            }
286
        ');
287
288
        // originally there was a ?P in the select header
289
        $query = 'PREFIX : <http://www.example.org/>
290
            SELECT (COUNT(?O) AS ?C)
291
            WHERE { ?S ?P ?O }
292
        ';
293
294
        $result = $this->store->query($query);
295
296
        $this->assertEquals(
297
            [
298
                [
299
                    'C' => '5',
300
                    'C type' => 'literal',
301
                ],
302
            ],
303
            $result['result']['rows']
304
        );
305
    }
306
307
    /*
308
     * agg11, agg12 fails
309
     */
310
311
    public function testAggMin01()
312
    {
313
        $this->store->query('
314
            PREFIX : <http://www.example.org/> .
315
            PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> .
316
            INSERT INTO <http://agg> {
317
                :ints :int 1, 2, 3 .
318
                :decimals :dec 1.0, 2.2, 3.5 .
319
                :doubles :double 1.0E2, 2.0E3, 3.0E4 .
320
                :mixed1 :int 1 ; :dec 2.2 .
321
                :mixed2 :double 2E-1 ; :dec 2.2 .
322
            }
323
        ');
324
325
        $query = 'PREFIX : <http://www.example.org/>
326
            SELECT (MIN(?o) AS ?min)
327
            WHERE {
328
                ?s :dec ?o
329
            }
330
        ';
331
332
        $result = $this->store->query($query);
333
334
        $this->assertEquals(
335
            [
336
                ['min' => 1, 'min type' => 'literal'],
337
            ],
338
            $result['result']['rows']
339
        );
340
    }
341
342
    public function testAggAvg01()
343
    {
344
        $this->store->query('
345
            PREFIX : <http://www.example.org/> .
346
            PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> .
347
            INSERT INTO <http://agg> {
348
                :ints :int 1, 2, 3 .
349
                :decimals :dec 1.0, 2.2, 3.5 .
350
                :doubles :double 1.0E2, 2.0E3, 3.0E4 .
351
                :mixed1 :int 1 ; :dec 2.2 .
352
                :mixed2 :double 2E-1 ; :dec 2.2 .
353
            }
354
        ');
355
356
        $query = 'PREFIX : <http://www.example.org/>
357
            SELECT (AVG(?o) AS ?avg)
358
            WHERE {
359
                ?s :dec ?o
360
            }
361
        ';
362
363
        $result = $this->store->query($query);
364
365
        $this->assertEquals(
366
            [
367
                ['avg' => 2.22, 'avg type' => 'literal'],
368
            ],
369
            $result['result']['rows']
370
        );
371
    }
372
373
    /*
374
     * aggAvg02 fails because store can't properly handle:
375
     *
376
     *      HAVING (...)
377
     */
378
379
    public function testAggEmptyGroup()
380
    {
381
        $query = 'PREFIX ex: <http://example.com/>
382
            SELECT ?x (MAX(?value) AS ?max)
383
            WHERE {
384
                ?x ex:p ?value
385
            } GROUP BY ?x
386
        ';
387
388
        $result = $this->store->query($query);
389
390
        $this->assertCount(0, $result['result']['rows']);
391
    }
392
393
    public function testAggMax01()
394
    {
395
        $this->store->query('
396
            PREFIX : <http://www.example.org/> .
397
            PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> .
398
            INSERT INTO <http://agg> {
399
                :ints :int 1, 2, 3 .
400
                :decimals :dec 1.0, 2.2, 3.5 .
401
                :doubles :double 1.0E2, 2.0E3, 3.0E4 .
402
                :mixed1 :int 1 ; :dec 2.2 .
403
                :mixed2 :double 2E-1 ; :dec 2.2 .
404
            }
405
        ');
406
407
        $query = 'PREFIX : <http://www.example.org/>
408
            SELECT (MAX(?o) AS ?max)
409
            WHERE {
410
                ?s ?p ?o
411
            }
412
        ';
413
414
        $result = $this->store->query($query);
415
416
        $this->assertEquals(
417
            [
418
                ['max' => 30000, 'max type' => 'literal'],
419
            ],
420
            $result['result']['rows']
421
        );
422
    }
423
424
    public function testAggMax02()
425
    {
426
        $this->store->query('
427
            PREFIX : <http://www.example.org/> .
428
            PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> .
429
            INSERT INTO <http://agg> {
430
                :ints :int 1, 2, 3 .
431
                :decimals :dec 1.0, 2.2, 3.5 .
432
                :doubles :double 1.0E2, 2.0E3, 3.0E4 .
433
                :mixed1 :int 1 ; :dec 2.2 .
434
                :mixed2 :double 2E-1 ; :dec 2.2 .
435
            }
436
        ');
437
438
        $query = 'PREFIX : <http://www.example.org/>
439
            SELECT ?s (MAX(?o) AS ?max)
440
            WHERE {
441
                ?s ?p ?o
442
            }
443
            GROUP BY ?s
444
        ';
445
446
        $result = $this->store->query($query);
447
448
        $this->assertEquals(
449
            [
450
                [
451
                    's' => 'http://www.example.org/ints', 's type' => 'uri',
452
                    'max' => '3', 'max type' => 'literal',
453
                ],
454
                [
455
                    's' => 'http://www.example.org/decimals', 's type' => 'uri',
456
                    'max' => '3.5', 'max type' => 'literal',
457
                ],
458
                [
459
                    's' => 'http://www.example.org/doubles', 's type' => 'uri',
460
                    'max' => '30000', 'max type' => 'literal',
461
                ],
462
                [
463
                    's' => 'http://www.example.org/mixed1', 's type' => 'uri',
464
                    'max' => '2.2', 'max type' => 'literal',
465
                ],
466
                [
467
                    's' => 'http://www.example.org/mixed2', 's type' => 'uri',
468
                    'max' => '2.2', 'max type' => 'literal',
469
                ],
470
            ],
471
            $result['result']['rows']
472
        );
473
    }
474
475
    public function testAggSum01()
476
    {
477
        $this->store->query('
478
            PREFIX : <http://www.example.org/> .
479
            PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> .
480
            INSERT INTO <http://agg> {
481
                :ints :int 1, 2, 3 .
482
                :decimals :dec 1.0, 2.2, 3.5 .
483
                :doubles :double 1.0E2, 2.0E3, 3.0E4 .
484
                :mixed1 :int 1 ;
485
                    :dec 2.2 .
486
                :mixed2 :double 2E-1 ;
487
                    :dec 2.2 .
488
            }
489
        ');
490
491
        $query = 'PREFIX : <http://www.example.org/>
492
            SELECT (SUM(?o) AS ?sum)
493
            WHERE {
494
                ?s :dec ?o
495
            }
496
        ';
497
498
        $result = $this->store->query($query);
499
500
        // PHP works differently prior to 8.1.0 therefore the if-else here
501
        if (version_compare(PHP_VERSION, '8.1.0', '<')) {
502
            $this->assertEquals(
503
                [
504
                    [
505
                        'sum' => 11.1, 'sum type' => 'literal',
506
                    ],
507
                ],
508
                $result['result']['rows']
509
            );
510
        } else {
511
            $this->assertEquals(
512
                [
513
                    [
514
                        'sum' => 11.100000000000001, 'sum type' => 'literal',
515
                    ],
516
                ],
517
                $result['result']['rows']
518
            );
519
        }
520
    }
521
522
    public function testAggSum02()
523
    {
524
        $this->store->query('
525
            PREFIX : <http://www.example.org/> .
526
            PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> .
527
            INSERT INTO <http://agg> {
528
                :ints :int 1, 2, 3 .
529
                :decimals :dec 1.0, 2.2, 3.5 .
530
                :doubles :double 1.0E2, 2.0E3, 3.0E4 .
531
                :mixed1 :int 1 ;
532
                    :dec 2.2 .
533
                :mixed2 :double 2E-1 ;
534
                    :dec 2.2 .
535
            }
536
        ');
537
538
        $query = 'PREFIX : <http://www.example.org/>
539
            SELECT ?s (SUM(?o) AS ?sum)
540
            WHERE {
541
                ?s ?p ?o
542
            }
543
            GROUP BY ?s
544
        ';
545
546
        $result = $this->store->query($query);
547
548
        $this->assertEquals(
549
            [
550
                's' => 'http://www.example.org/ints', 's type' => 'uri',
551
                'sum' => '6', 'sum type' => 'literal',
552
            ],
553
            $result['result']['rows'][0]
554
        );
555
556
        $this->assertEquals(
557
            [
558
                's' => 'http://www.example.org/decimals', 's type' => 'uri',
559
                'sum' => '6.7', 'sum type' => 'literal',
560
            ],
561
            $result['result']['rows'][1]
562
        );
563
564
        $this->assertEquals(
565
            [
566
                's' => 'http://www.example.org/doubles', 's type' => 'uri',
567
                'sum' => '32100', 'sum type' => 'literal',
568
            ],
569
            $result['result']['rows'][2]
570
        );
571
572
        $this->assertEquals(
573
            [
574
                's' => 'http://www.example.org/mixed1', 's type' => 'uri',
575
                'sum' => '3.2', 'sum type' => 'literal',
576
            ],
577
            $result['result']['rows'][3]
578
        );
579
580
        // PHP works differently prior to 8.1.0 therefore the if-else here
581
        if (version_compare(PHP_VERSION, '8.1.0', '<')) {
582
            $this->assertEquals(
583
                [
584
                    's' => 'http://www.example.org/mixed2', 's type' => 'uri',
585
                    'sum' => 2.4, 'sum type' => 'literal',
586
                ],
587
                $result['result']['rows'][4]
588
            );
589
        } else {
590
            $this->assertEquals(
591
                [
592
                    's' => 'http://www.example.org/mixed2', 's type' => 'uri',
593
                    'sum' => 2.4000000000000004, 'sum type' => 'literal',
594
                ],
595
                $result['result']['rows'][4]
596
            );
597
        }
598
    }
599
}
600