]> git.openstreetmap.org Git - nominatim.git/blob - test/php/Nominatim/DBTest.php
Merge pull request #2248 from darkshredder/special-term-test
[nominatim.git] / test / php / Nominatim / DBTest.php
1 <?php
2
3 namespace Nominatim;
4
5 require_once(CONST_LibDir.'/lib.php');
6 require_once(CONST_LibDir.'/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             $oDB->exec('CREATE TABLE table1 (id integer, city varchar, country varchar)');
163
164             $this->assertTrue($oDB->tableExists('table1'));
165             $this->assertFalse($oDB->tableExists('table99'));
166             $this->assertFalse($oDB->tableExists(null));
167         }
168
169         # select queries
170         {
171             $oDB->exec(
172                 "INSERT INTO table1 VALUES (1, 'Berlin', 'Germany'), (2, 'Paris', 'France')"
173             );
174
175             $this->assertEquals(
176                 array(
177                     array('city' => 'Berlin'),
178                     array('city' => 'Paris')
179                 ),
180                 $oDB->getAll('SELECT city FROM table1')
181             );
182             $this->assertEquals(
183                 array(),
184                 $oDB->getAll('SELECT city FROM table1 WHERE id=999')
185             );
186
187
188             $this->assertEquals(
189                 array('id' => 1, 'city' => 'Berlin', 'country' => 'Germany'),
190                 $oDB->getRow('SELECT * FROM table1 WHERE id=1')
191             );
192             $this->assertEquals(
193                 false,
194                 $oDB->getRow('SELECT * FROM table1 WHERE id=999')
195             );
196
197
198             $this->assertEquals(
199                 array('Berlin', 'Paris'),
200                 $oDB->getCol('SELECT city FROM table1')
201             );
202             $this->assertEquals(
203                 array(),
204                 $oDB->getCol('SELECT city FROM table1 WHERE id=999')
205             );
206
207             $this->assertEquals(
208                 'Berlin',
209                 $oDB->getOne('SELECT city FROM table1 WHERE id=1')
210             );
211             $this->assertEquals(
212                 null,
213                 $oDB->getOne('SELECT city FROM table1 WHERE id=999')
214             );
215
216             $this->assertEquals(
217                 array('Berlin' => 'Germany', 'Paris' => 'France'),
218                 $oDB->getAssoc('SELECT city, country FROM table1')
219             );
220             $this->assertEquals(
221                 array(),
222                 $oDB->getAssoc('SELECT city, country FROM table1 WHERE id=999')
223             );
224         }
225     }
226 }