]> git.openstreetmap.org Git - nominatim.git/blob - test/php/Nominatim/DBTest.php
Merge remote-tracking branch 'upstream/master'
[nominatim.git] / test / php / Nominatim / DBTest.php
1 <?php
2
3 namespace Nominatim;
4
5 require_once(CONST_BasePath.'/lib/lib.php');
6 require_once(CONST_BasePath.'/lib/DB.php');
7
8 // subclassing so we can set the protected connection variable
9 class NominatimSubClassedDB extends \Nominatim\DB
10 {
11     public function setConnection($oConnection)
12     {
13         $this->connection = $oConnection;
14     }
15 }
16
17 // phpcs:ignore PSR1.Classes.ClassDeclaration.MultipleClasses
18 class DBTest extends \PHPUnit\Framework\TestCase
19 {
20     public function testReusingConnection()
21     {
22         $oDB = new NominatimSubClassedDB('');
23         $oDB->setConnection('anything');
24         $this->assertTrue($oDB->connect());
25     }
26
27     public function testCheckConnection()
28     {
29         $oDB = new \Nominatim\DB('');
30         $this->assertFalse($oDB->checkConnection());
31     }
32
33     public function testErrorHandling()
34     {
35         $this->expectException(DatabaseError::class);
36         $this->expectExceptionMessage('Failed to establish database connection');
37
38         $oDB = new \Nominatim\DB('pgsql:dbname=abc');
39         $oDB->connect();
40     }
41
42     public function testErrorHandling2()
43     {
44         $this->expectException(DatabaseError::class);
45         $this->expectExceptionMessage('Database query failed');
46
47         $oPDOStub = $this->getMockBuilder(PDO::class)
48                          ->setMethods(array('query', 'quote'))
49                          ->getMock();
50
51         $oPDOStub->method('query')
52                  ->will($this->returnCallback(function ($sVal) {
53                     return "'$sVal'";
54                  }));
55
56         $oPDOStub->method('query')
57                  ->will($this->returnCallback(function () {
58                      throw new \PDOException('ERROR:  syntax error at or near "FROM"');
59                  }));
60
61         $oDB = new NominatimSubClassedDB('');
62         $oDB->setConnection($oPDOStub);
63         $oDB->getOne('SELECT name FROM');
64     }
65
66     public function testGetPostgresVersion()
67     {
68         $oDBStub = $this->getMockBuilder(\Nominatim\DB::class)
69                         ->disableOriginalConstructor()
70                         ->setMethods(array('getOne'))
71                         ->getMock();
72
73         $oDBStub->method('getOne')
74                 ->willReturn('100006');
75
76         $this->assertEquals(10, $oDBStub->getPostgresVersion());
77     }
78
79     public function testGetPostgisVersion()
80     {
81         $oDBStub = $this->getMockBuilder(\Nominatim\DB::class)
82                         ->disableOriginalConstructor()
83                         ->setMethods(array('getOne'))
84                         ->getMock();
85
86         $oDBStub->method('getOne')
87                 ->willReturn('2.4.4');
88
89         $this->assertEquals(2.4, $oDBStub->getPostgisVersion());
90     }
91
92     public function testParseDSN()
93     {
94         $this->assertEquals(
95             array(),
96             \Nominatim\DB::parseDSN('')
97         );
98         $this->assertEquals(
99             array(
100              'database' => 'db1',
101              'hostspec' => 'machine1'
102             ),
103             \Nominatim\DB::parseDSN('pgsql:dbname=db1;host=machine1')
104         );
105         $this->assertEquals(
106             array(
107              'database' => 'db1',
108              'hostspec' => 'machine1',
109              'port' => '1234',
110              'username' => 'john',
111              'password' => 'secret'
112             ),
113             \Nominatim\DB::parseDSN('pgsql:dbname=db1;host=machine1;port=1234;user=john;password=secret')
114         );
115     }
116
117     public function testGenerateDSN()
118     {
119         $this->assertEquals(
120             'pgsql:',
121             \Nominatim\DB::generateDSN(array())
122         );
123         $this->assertEquals(
124             'pgsql:host=machine1;dbname=db1',
125             \Nominatim\DB::generateDSN(\Nominatim\DB::parseDSN('pgsql:host=machine1;dbname=db1'))
126         );
127     }
128
129     public function testAgainstDatabase()
130     {
131         $unit_test_dsn = getenv('UNIT_TEST_DSN') != false ?
132                             getenv('UNIT_TEST_DSN') :
133                             'pgsql:dbname=nominatim_unit_tests';
134
135         $this->assertRegExp(
136             '/unit_test/',
137             $unit_test_dsn,
138             'Test database will get destroyed, thus should have a name like unit_test to be safe'
139         );
140
141         ## Create the database.
142         {
143             $aDSNParsed = \Nominatim\DB::parseDSN($unit_test_dsn);
144             $sDbname = $aDSNParsed['database'];
145             $aDSNParsed['database'] = 'postgres';
146
147             $oDB = new \Nominatim\DB(\Nominatim\DB::generateDSN($aDSNParsed));
148             $oDB->connect();
149             $oDB->exec('DROP DATABASE IF EXISTS ' . $sDbname);
150             $oDB->exec('CREATE DATABASE ' . $sDbname);
151         }
152
153         $oDB = new \Nominatim\DB($unit_test_dsn);
154         $oDB->connect();
155
156         $this->assertTrue(
157             $oDB->checkConnection($sDbname)
158         );
159
160         # Tables, Indices
161         {
162             $this->assertEmpty($oDB->getListOfTables());
163             $oDB->exec('CREATE TABLE table1 (id integer, city varchar, country varchar)');
164             $oDB->exec('CREATE TABLE table2 (id integer, city varchar, country varchar)');
165             $this->assertEquals(
166                 array('table1', 'table2'),
167                 $oDB->getListOfTables()
168             );
169             $this->assertTrue($oDB->deleteTable('table2'));
170             $this->assertTrue($oDB->deleteTable('table99'));
171             $this->assertEquals(
172                 array('table1'),
173                 $oDB->getListOfTables()
174             );
175
176             $this->assertTrue($oDB->tableExists('table1'));
177             $this->assertFalse($oDB->tableExists('table99'));
178             $this->assertFalse($oDB->tableExists(null));
179
180             $this->assertEmpty($oDB->getListOfIndices());
181             $oDB->exec('CREATE UNIQUE INDEX table1_index ON table1 (id)');
182             $this->assertEquals(
183                 array('table1_index'),
184                 $oDB->getListOfIndices()
185             );
186             $this->assertEmpty($oDB->getListOfIndices('table2'));
187         }
188
189         # select queries
190         {
191             $oDB->exec(
192                 "INSERT INTO table1 VALUES (1, 'Berlin', 'Germany'), (2, 'Paris', 'France')"
193             );
194
195             $this->assertEquals(
196                 array(
197                     array('city' => 'Berlin'),
198                     array('city' => 'Paris')
199                 ),
200                 $oDB->getAll('SELECT city FROM table1')
201             );
202             $this->assertEquals(
203                 array(),
204                 $oDB->getAll('SELECT city FROM table1 WHERE id=999')
205             );
206
207
208             $this->assertEquals(
209                 array('id' => 1, 'city' => 'Berlin', 'country' => 'Germany'),
210                 $oDB->getRow('SELECT * FROM table1 WHERE id=1')
211             );
212             $this->assertEquals(
213                 false,
214                 $oDB->getRow('SELECT * FROM table1 WHERE id=999')
215             );
216
217
218             $this->assertEquals(
219                 array('Berlin', 'Paris'),
220                 $oDB->getCol('SELECT city FROM table1')
221             );
222             $this->assertEquals(
223                 array(),
224                 $oDB->getCol('SELECT city FROM table1 WHERE id=999')
225             );
226
227             $this->assertEquals(
228                 'Berlin',
229                 $oDB->getOne('SELECT city FROM table1 WHERE id=1')
230             );
231             $this->assertEquals(
232                 null,
233                 $oDB->getOne('SELECT city FROM table1 WHERE id=999')
234             );
235
236             $this->assertEquals(
237                 array('Berlin' => 'Germany', 'Paris' => 'France'),
238                 $oDB->getAssoc('SELECT city, country FROM table1')
239             );
240             $this->assertEquals(
241                 array(),
242                 $oDB->getAssoc('SELECT city, country FROM table1 WHERE id=999')
243             );
244         }
245     }
246 }