Passed
Push — master ( 28ca8c...059b59 )
by William
12:16
created

ShapeFileTest::testLoadEmptyFilename()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 5
rs 10
c 1
b 0
f 1
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * phpMyAdmin ShapeFile library
7
 * <https://github.com/phpmyadmin/shapefile/>.
8
 *
9
 * Copyright 2006-2007 Ovidio <ovidio AT users.sourceforge.net>
10
 * Copyright 2016 - 2017 Michal Čihař <[email protected]>
11
 *
12
 * This program is free software; you can redistribute it and/or
13
 * modify it under the terms of the GNU General Public License
14
 * as published by the Free Software Foundation.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 * along with this program; if not, you can download one from
23
 * https://www.gnu.org/copyleft/gpl.html.
24
 */
25
26
namespace ShapeFileTest;
27
28
use PhpMyAdmin\ShapeFile\ShapeFile;
29
use PhpMyAdmin\ShapeFile\ShapeRecord;
30
use PHPUnit\Framework\TestCase;
31
use function count;
32
33
class ShapeFileTest extends TestCase
34
{
35
    /**
36
     * Tests loading of a file.
37
     *
38
     * @param string   $filename Name of file
39
     * @param int      $records  Expected number of records
40
     * @param int|null $parts    Expected number of parts in first record
41
     *
42
     * @dataProvider provideFiles
43
     */
44
    public function testLoad(string $filename, int $records, ?int $parts): void
45
    {
46
        $shp = new ShapeFile(1);
47
        $shp->loadFromFile($filename);
48
        $this->assertEquals('', $shp->lastError);
49
        $this->assertEquals($records, count($shp->records));
50
        if ($parts === null) {
51
            return;
52
        }
53
54
        $this->assertEquals($parts, count($shp->records[0]->shpData['parts']));
55
    }
56
57
    /**
58
     * Data provider for file loading tests.
59
     *
60
     * @return array
61
     */
62
    public function provideFiles(): array
63
    {
64
        return [
65
            [
66
                'data/capitals.*',
67
                652,
68
                null,
69
            ],
70
            [
71
                'data/mexico.*',
72
                32,
73
                3,
74
            ],
75
            [
76
                'data/Czech_Republic_AL2.*',
77
                1,
78
                1,
79
            ],
80
            [
81
                'data/w001n05f.*',
82
                16,
83
                1,
84
            ],
85
            [
86
                'data/bc_hospitals.*',
87
                44,
88
                null,
89
            ],
90
            [
91
                'data/multipoint.*',
92
                312,
93
                null,
94
            ],
95
        ];
96
    }
97
98
    /**
99
     * Test error handling in loader.
100
     *
101
     * @param string $filename name to load
102
     *
103
     * @dataProvider provideErrorFiles
104
     */
105
    public function testLoadError(string $filename): void
106
    {
107
        $shp = new ShapeFile(1);
108
        $shp->loadFromFile($filename);
109
        $this->assertNotEquals('', $shp->lastError);
110
    }
111
112
    /**
113
     * Test load an empty file name
114
     */
115
    public function testLoadEmptyFilename(): void
116
    {
117
        $shp = new ShapeFile(1);
118
        $shp->loadFromFile('');
119
        $this->assertEquals('Not a SHP file (file code mismatch)', $shp->lastError);
120
    }
121
122
    /**
123
     * Data provider for file loading error tests.
124
     *
125
     * @return array
126
     */
127
    public function provideErrorFiles(): array
128
    {
129
        $result = [
130
            ['data/no-shp.*'],
131
            ['data/missing.*'],
132
            ['data/invalid-shp.*'],
133
        ];
134
135
        if (ShapeFile::supportsDbase()) {
136
            $result[] = ['data/no-dbf.*'];
137
            $result[] = ['data/invalid-dbf.*'];
138
        }
139
140
        return $result;
141
    }
142
143
    /**
144
     * Creates test data.
145
     */
146
    private function createTestData(): void
147
    {
148
        $shp = new ShapeFile(1);
149
150
        $record0 = new ShapeRecord(1);
151
        $record0->addPoint(['x' => 482131.764567, 'y' => 2143634.39608]);
152
153
        $record1 = new ShapeRecord(11);
154
        $record1->addPoint(['x' => 472131.764567, 'y' => 2143634.39608, 'z' => 220, 'm' => 120]);
155
156
        $record2 = new ShapeRecord(21);
157
        $record2->addPoint(['x' => 492131.764567, 'y' => 2143634.39608, 'z' => 150, 'm' => 80]);
158
159
        $record3 = new ShapeRecord(3);
160
        $record3->addPoint(['x' => 482131.764567, 'y' => 2143634.39608], 0);
161
        $record3->addPoint(['x' => 482132.764567, 'y' => 2143635.39608], 0);
162
        $record3->addPoint(['x' => 482131.764567, 'y' => 2143635.39608], 1);
163
        $record3->addPoint(['x' => 482132.764567, 'y' => 2143636.39608], 1);
164
165
        $shp->addRecord($record0);
166
        $shp->addRecord($record1);
167
        $shp->addRecord($record2);
168
        $shp->addRecord($record3);
169
170
        $shp->setDBFHeader(
171
            [
172
                [
173
                    'ID',
174
                    'N',
175
                    8,
176
                    0,
177
                ],
178
                [
179
                    'DESC',
180
                    'C',
181
                    50,
182
                    0,
183
                ],
184
            ]
185
        );
186
187
        $shp->records[0]->dbfData['ID'] = '1';
188
        $shp->records[0]->dbfData['DESC'] = 'AAAAAAAAA';
189
190
        $shp->records[1]->dbfData['ID'] = '2';
191
        $shp->records[1]->dbfData['DESC'] = 'BBBBBBBBBB';
192
193
        $shp->records[2]->dbfData['ID'] = '3';
194
        $shp->records[2]->dbfData['DESC'] = 'CCCCCCCCCCC';
195
196
        $shp->records[3]->dbfData['ID'] = '4';
197
        $shp->records[3]->dbfData['DESC'] = 'CCCCCCCCCCC';
198
199
        $shp->saveToFile('./data/test_shape.*');
200
    }
201
202
    /**
203
     * Tests creating file.
204
     */
205
    public function testCreate(): void
206
    {
207
        if (! ShapeFile::supportsDbase()) {
208
            $this->markTestSkipped('dbase extension missing');
209
        }
210
211
        $this->createTestData();
212
213
        $shp = new ShapeFile(1);
214
        $shp->loadFromFile('./data/test_shape.*');
215
        $this->assertEquals(4, count($shp->records));
216
    }
217
218
    /**
219
     * Tests removing record from a file.
220
     */
221
    public function testDelete(): void
222
    {
223
        if (! ShapeFile::supportsDbase()) {
224
            $this->markTestSkipped('dbase extension missing');
225
        }
226
227
        $this->createTestData();
228
229
        $shp = new ShapeFile(1);
230
        $shp->loadFromFile('./data/test_shape.*');
231
        $shp->deleteRecord(1);
232
        $shp->saveToFile();
233
        $this->assertEquals(3, count($shp->records));
234
235
        $shp = new ShapeFile(1);
236
        $shp->loadFromFile('./data/test_shape.*');
237
        $this->assertEquals(3, count($shp->records));
238
    }
239
240
    /**
241
     * Test adding record to a file.
242
     */
243
    public function testAdd(): void
244
    {
245
        if (! ShapeFile::supportsDbase()) {
246
            $this->markTestSkipped('dbase extension missing');
247
        }
248
249
        $this->createTestData();
250
251
        $shp = new ShapeFile(1);
252
        $shp->loadFromFile('./data/test_shape.*');
253
254
        $record0 = new ShapeRecord(1);
255
        $record0->addPoint(['x' => 482131.764567, 'y' => 2143634.39608]);
256
257
        $shp->addRecord($record0);
258
        $shp->records[4]->dbfData['ID'] = '4';
259
        $shp->records[4]->dbfData['DESC'] = 'CCCCCCCCCCC';
260
261
        $shp->saveToFile();
262
        $this->assertEquals(5, count($shp->records));
263
264
        $shp = new ShapeFile(1);
265
        $shp->loadFromFile('./data/test_shape.*');
266
        $this->assertEquals(5, count($shp->records));
267
    }
268
269
    /**
270
     * Tests saving without DBF.
271
     */
272
    public function testSaveNoDBF(): void
273
    {
274
        $shp = new ShapeFile(1);
275
        $shp->saveToFile('./data/test_nodbf.*');
276
        $this->assertFileNotExists('./data/test_nodbf.dbf');
277
    }
278
279
    /**
280
     * Test shape naming.
281
     */
282
    public function testShapeName(): void
283
    {
284
        $obj = new ShapeRecord(1);
285
        $this->assertEquals('Point', $obj->getShapeName());
286
        $obj = new ShapeFile(1);
287
        $this->assertEquals('Point', $obj->getShapeName());
288
        $obj = new ShapeRecord(-1);
289
        $this->assertEquals('Shape -1', $obj->getShapeName());
290
    }
291
292
    /**
293
     * Test shapes save/load round robin.
294
     *
295
     * @param int   $type   Shape type
296
     * @param array $points Points
297
     *
298
     * @dataProvider shapes
299
     */
300
    public function testShapeSaveLoad(int $type, array $points): void
301
    {
302
        $filename = './data/test_shape-' . $type . '.*';
303
        $shp = new ShapeFile($type);
304
        $shp->setDBFHeader([
305
            [
306
                'ID',
307
                'N',
308
                19,
309
                0,
310
            ],
311
            [
312
                'DESC',
313
                'C',
314
                14,
315
                0,
316
            ],
317
        ]);
318
319
        $record0 = new ShapeRecord($type);
320
321
        foreach ($points as $point) {
322
            $record0->addPoint($point[0], $point[1]);
323
        }
324
325
        $shp->addRecord($record0);
326
327
        $shp->saveToFile($filename);
328
329
        $shp2 = new ShapeFile($type);
330
        $shp2->loadFromFile($filename);
331
332
        $this->assertEquals(
333
            count($shp->records),
334
            count($shp2->records)
335
        );
336
337
        $record = $shp->records[0];
338
        $record2 = $shp2->records[0];
339
340
        $items = [
341
            'numparts',
342
            'numpoints',
343
        ];
344
        foreach ($items as $item) {
345
            if (! isset($record->shpData[$item])) {
346
                continue;
347
            }
348
349
            $this->assertEquals(
350
                $record->shpData[$item],
351
                $record2->shpData[$item]
352
            );
353
        }
354
355
        /* Test deletion works */
356
        $record->deletePoint();
357
    }
358
359
    /**
360
     * Test shapes save/load round robin with z coordinate.
361
     *
362
     * @param int   $type   Shape type
363
     * @param array $points Points
364
     *
365
     * @dataProvider shapes
366
     */
367
    public function testZetShapeSaveLoad(int $type, array $points): void
368
    {
369
        $this->testShapeSaveLoad($type + 10, $points);
370
    }
371
372
    /**
373
     * Test shapes save/load round robin with measure.
374
     *
375
     * @param int   $type   Shape type
376
     * @param array $points Points
377
     *
378
     * @dataProvider shapes
379
     */
380
    public function testMeasureShapeSaveLoad(int $type, array $points): void
381
    {
382
        $this->testShapeSaveLoad($type + 20, $points);
383
    }
384
385
    /**
386
     * Data provider for save/load testing.
387
     *
388
     * @return array
389
     */
390
    public function shapes(): array
391
    {
392
        return [
393
            [
394
                1,
395
                [
396
                    [
397
                        [
398
                            'x' => 10,
399
                            'y' => 20,
400
                        ],
401
                        0,
402
                    ],
403
                ],
404
            ],
405
            [
406
                3,
407
                [
408
                    [
409
                        [
410
                            'x' => 10,
411
                            'y' => 20,
412
                        ],
413
                        0,
414
                    ],
415
                    [
416
                        [
417
                            'x' => 20,
418
                            'y' => 20,
419
                        ],
420
                        0,
421
                    ],
422
                    [
423
                        [
424
                            'x' => 20,
425
                            'y' => 20,
426
                        ],
427
                        1,
428
                    ],
429
                    [
430
                        [
431
                            'x' => 20,
432
                            'y' => 10,
433
                        ],
434
                        1,
435
                    ],
436
                ],
437
            ],
438
            [
439
                5,
440
                [
441
                    [
442
                        [
443
                            'x' => 10,
444
                            'y' => 20,
445
                        ],
446
                        0,
447
                    ],
448
                    [
449
                        [
450
                            'x' => 20,
451
                            'y' => 20,
452
                        ],
453
                        0,
454
                    ],
455
                    [
456
                        [
457
                            'x' => 20,
458
                            'y' => 20,
459
                        ],
460
                        1,
461
                    ],
462
                    [
463
                        [
464
                            'x' => 20,
465
                            'y' => 10,
466
                        ],
467
                        1,
468
                    ],
469
                    [
470
                        [
471
                            'x' => 20,
472
                            'y' => 10,
473
                        ],
474
                        2,
475
                    ],
476
                    [
477
                        [
478
                            'x' => 10,
479
                            'y' => 20,
480
                        ],
481
                        2,
482
                    ],
483
                ],
484
            ],
485
            [
486
                8,
487
                [
488
                    [
489
                        [
490
                            'x' => 10,
491
                            'y' => 20,
492
                        ],
493
                        0,
494
                    ],
495
                    [
496
                        [
497
                            'x' => 20,
498
                            'y' => 20,
499
                        ],
500
                        0,
501
                    ],
502
                    [
503
                        [
504
                            'x' => 20,
505
                            'y' => 10,
506
                        ],
507
                        0,
508
                    ],
509
                ],
510
            ],
511
        ];
512
    }
513
514
    public function testSearch(): void
515
    {
516
        $shp = new ShapeFile(0);
517
        $shp->loadFromFile('data/capitals.*');
518
        /* Nonexisting entry or no dbase support */
519
        $this->assertEquals(
520
            -1,
521
            $shp->getIndexFromDBFData('CNTRY_NAME', 'nonexisting')
522
        );
523
        if (! ShapeFile::supportsDbase()) {
524
            return;
525
        }
526
527
        $this->assertEquals(
528
            218,
529
            $shp->getIndexFromDBFData('CNTRY_NAME', 'Czech Republic')
530
        );
531
    }
532
}
533