]> git.openstreetmap.org Git - nominatim.git/commitdiff
Nominatim::DB tests against separate postgresql database
authormarc tobias <mtmail@gmx.net>
Mon, 13 Apr 2020 15:48:20 +0000 (17:48 +0200)
committermarc tobias <mtmail@gmx.net>
Mon, 13 Apr 2020 16:01:37 +0000 (18:01 +0200)
.travis.yml
lib/DB.php
lib/setup/SetupClass.php
test/README.md
test/php/Nominatim/DBTest.php
utils/check_import_finished.php

index f53447422c303ed9740a02edbd18a41acbd768e6..dd973aecbc2649f7ae1e86b29a41be32f121e59b 100644 (file)
@@ -25,7 +25,7 @@ script:
   - cd $TRAVIS_BUILD_DIR/
   - if [[ $TEST_SUITE == "tests" ]]; then phpcs --report-width=120 . ; fi
   - cd $TRAVIS_BUILD_DIR/test/php
-  - if [[ $TEST_SUITE == "tests" ]]; then /usr/bin/phpunit ./ ; fi
+  - if [[ $TEST_SUITE == "tests" ]]; then UNIT_TEST_DSN='pgsql:dbname=nominatim_unit_tests' /usr/bin/phpunit ./ ; fi
   - cd $TRAVIS_BUILD_DIR/test/bdd
   - # behave --format=progress3 api
   - if [[ $TEST_SUITE == "tests" ]]; then behave -DREMOVE_TEMPLATE=1 --format=progress3 db ; fi
index 6307d6ca2847bdf2a9d90354c33d79983c4c8077..5915b2e81242a727c82b9118c7ba0892114fb399 100644 (file)
@@ -240,6 +240,28 @@ class DB
         return ($this->getOne($sSQL, array(':tablename' => $sTableName)) == 1);
     }
 
+    /**
+    * Returns a list of table names in the database
+    *
+    * @return array[]
+    */
+    public function getListOfTables()
+    {
+        return $this->getCol("SELECT tablename FROM pg_tables WHERE schemaname='public'");
+    }
+
+    /**
+     * Deletes a table. Returns true on success. Returns true if the table didn't exist.
+     *
+     * @param string  $sTableName
+     *
+     * @return boolean
+     */
+    public function deleteTable($sTableName)
+    {
+        return $this->exec('DROP TABLE IF EXISTS '.$sTableName.' CASCADE') == 0;
+    }
+
     /**
     * Check if an index exists in the database. Optional filtered by tablename
     *
@@ -311,11 +333,11 @@ END;
     }
 
     /**
-     * Since the DSN includes the database name, checks if the connection works.
+     * Tries to connect to the database but on failure doesn't throw an exception.
      *
      * @return boolean
      */
-    public function databaseExists()
+    public function checkConnection()
     {
         $bExists = true;
         try {
@@ -350,6 +372,13 @@ END;
         return (float) ($aMatches[1].'.'.$aMatches[2]);
     }
 
+    /**
+     * Returns an associate array of postgresql database connection settings. Keys can
+     * be 'database', 'hostspec', 'port', 'username', 'password'.
+     * Returns empty array on failure, thus check if at least 'database' is set.
+     *
+     * @return array[]
+     */
     public static function parseDSN($sDSN)
     {
         // https://secure.php.net/manual/en/ref.pdo-pgsql.connection.php
@@ -365,4 +394,41 @@ END;
         }
         return $aInfo;
     }
+
+    /**
+     * Takes an array of settings and return the DNS string. Key names can be
+     * 'database', 'hostspec', 'port', 'username', 'password' but aliases
+     * 'dbname', 'host' and 'user' are also supported.
+     *
+     * @return string
+     *
+     */
+    public static function generateDSN($aInfo)
+    {
+        $sDSN = 'pgsql:';
+        if (isset($aInfo['host'])) {
+            $sDSN .= 'host=' . $aInfo['host'] . ';';
+        } elseif (isset($aInfo['hostspec'])) {
+            $sDSN .= 'host=' . $aInfo['hostspec'] . ';';
+        }
+        if (isset($aInfo['port'])) {
+            $sDSN .= 'port=' . $aInfo['port'] . ';';
+        }
+        if (isset($aInfo['dbname'])) {
+            $sDSN .= 'dbname=' . $aInfo['dbname'] . ';';
+        } elseif (isset($aInfo['database'])) {
+            $sDSN .= 'dbname=' . $aInfo['database'] . ';';
+        }
+        if (isset($aInfo['user'])) {
+            $sDSN .= 'user=' . $aInfo['user'] . ';';
+        } elseif (isset($aInfo['username'])) {
+            $sDSN .= 'user=' . $aInfo['username'] . ';';
+        }
+        if (isset($aInfo['password'])) {
+            $sDSN .= 'password=' . $aInfo['password'] . ';';
+        }
+        $sDSN = preg_replace('/;$/', '', $sDSN);
+
+        return $sDSN;
+    }
 }
index ac0f8f02f89e33ccc6d0cae4a23c14fb042f98cb..7c1c628e0e70171b08a60d103b17cdaf152fdf60 100755 (executable)
@@ -84,7 +84,7 @@ class SetupFunctions
         info('Create DB');
         $oDB = new \Nominatim\DB;
 
-        if ($oDB->databaseExists()) {
+        if ($oDB->checkConnection()) {
             fail('database already exists ('.CONST_Database_DSN.')');
         }
 
@@ -651,7 +651,7 @@ class SetupFunctions
                        );
 
         $aDropTables = array();
-        $aHaveTables = $this->oDB->getCol("SELECT tablename FROM pg_tables WHERE schemaname='public'");
+        $aHaveTables = $this->oDB->getListOfTables();
 
         foreach ($aHaveTables as $sTable) {
             $bFound = false;
@@ -858,7 +858,7 @@ class SetupFunctions
     private function dropTable($sName)
     {
         if ($this->bVerbose) echo "Dropping table $sName\n";
-        $this->oDB->exec('DROP TABLE IF EXISTS '.$sName.' CASCADE');
+        $this->oDB->deleteTable($sName);
     }
 
     /**
index ab5f7f4c653ef98cd65c454aa6dccfec43f2ce3e..5de08759532fb962cefb5d1afc87331d8576f777 100644 (file)
@@ -46,11 +46,13 @@ Very low coverage.
 To execute the test suite run
 
     cd test/php
-    phpunit ../
+    UNIT_TEST_DSN='pgsql:dbname=nominatim_unit_tests' phpunit ../
 
 It will read phpunit.xml which points to the library, test path, bootstrap
 strip and set other parameters.
 
+The database set by `UNIT_TEST_DSN` will be deleted and recreated. Not setting
+it will skip some tests as pending, but not fail the tests.
 
 BDD Functional Tests
 ====================
index 38874c880ec52cb2cc18f684ddf02a89ce8ab820..e47919758a449175683fa5721d3ab75d1ec7fa38 100644 (file)
@@ -24,10 +24,10 @@ class DBTest extends \PHPUnit\Framework\TestCase
         $this->assertTrue($oDB->connect());
     }
 
-    public function testDatabaseExists()
+    public function testCheckConnection()
     {
         $oDB = new \Nominatim\DB('');
-        $this->assertFalse($oDB->databaseExists());
+        $this->assertFalse($oDB->checkConnection());
     }
 
     public function testErrorHandling()
@@ -113,4 +113,126 @@ class DBTest extends \PHPUnit\Framework\TestCase
             \Nominatim\DB::parseDSN('pgsql:dbname=db1;host=machine1;port=1234;user=john;password=secret')
         );
     }
+
+    public function testGenerateDSN()
+    {
+        $this->assertEquals(
+            'pgsql:',
+            \Nominatim\DB::generateDSN(array())
+        );
+        $this->assertEquals(
+            'pgsql:host=machine1;dbname=db1',
+            \Nominatim\DB::generateDSN(\Nominatim\DB::parseDSN('pgsql:host=machine1;dbname=db1'))
+        );
+    }
+
+    public function testAgainstDatabase()
+    {
+        if (getenv('UNIT_TEST_DSN') == false) $this->markTestSkipped('UNIT_TEST_DSN not set');
+
+        ## Create the database.
+        {
+            $aDSNParsed = \Nominatim\DB::parseDSN(getenv('UNIT_TEST_DSN'));
+            $sDbname = $aDSNParsed['database'];
+            $aDSNParsed['database'] = 'postgres';
+
+            $oDB = new \Nominatim\DB(\Nominatim\DB::generateDSN($aDSNParsed));
+            $oDB->connect();
+            $oDB->exec('DROP DATABASE IF EXISTS ' . $sDbname);
+            $oDB->exec('CREATE DATABASE ' . $sDbname);
+        }
+
+        $oDB = new \Nominatim\DB(getenv('UNIT_TEST_DSN'));
+        $oDB->connect();
+
+        $this->assertTrue(
+            $oDB->checkConnection($sDbname)
+        );
+
+        # Tables, Indices
+        {
+            $this->assertEmpty($oDB->getListOfTables());
+            $oDB->exec('CREATE TABLE table1 (id integer, city varchar, country varchar)');
+            $oDB->exec('CREATE TABLE table2 (id integer, city varchar, country varchar)');
+            $this->assertEquals(
+                array('table1', 'table2'),
+                $oDB->getListOfTables()
+            );
+            $this->assertTrue($oDB->deleteTable('table2'));
+            $this->assertTrue($oDB->deleteTable('table99'));
+            $this->assertEquals(
+                array('table1'),
+                $oDB->getListOfTables()
+            );
+
+            $this->assertTrue($oDB->tableExists('table1'));
+            $this->assertFalse($oDB->tableExists('table99'));
+            $this->assertFalse($oDB->tableExists(null));
+
+            $this->assertEmpty($oDB->getListOfIndices());
+            $oDB->exec('CREATE UNIQUE INDEX table1_index ON table1 (id)');
+            $this->assertEquals(
+                array('table1_index'),
+                $oDB->getListOfIndices()
+            );
+            $this->assertEmpty($oDB->getListOfIndices('table2'));
+        }
+
+        # select queries
+        {
+            $oDB->exec(
+                "INSERT INTO table1 VALUES (1, 'Berlin', 'Germany'), (2, 'Paris', 'France')"
+            );
+
+            $this->assertEquals(
+                array(
+                    array('city' => 'Berlin'),
+                    array('city' => 'Paris')
+                ),
+                $oDB->getAll('SELECT city FROM table1')
+            );
+            $this->assertEquals(
+                array(),
+                $oDB->getAll('SELECT city FROM table1 WHERE id=999')
+            );
+
+
+            $this->assertEquals(
+                array('id' => 1, 'city' => 'Berlin', 'country' => 'Germany'),
+                $oDB->getRow('SELECT * FROM table1 WHERE id=1')
+            );
+            $this->assertEquals(
+                false,
+                $oDB->getRow('SELECT * FROM table1 WHERE id=999')
+            );
+
+
+            $this->assertEquals(
+                array('Berlin', 'Paris'),
+                $oDB->getCol('SELECT city FROM table1')
+            );
+            $this->assertEquals(
+                array(),
+                $oDB->getCol('SELECT city FROM table1 WHERE id=999')
+            );
+
+            $this->assertEquals(
+                'Berlin',
+                $oDB->getOne('SELECT city FROM table1 WHERE id=1')
+            );
+            $this->assertEquals(
+                null,
+                $oDB->getOne('SELECT city FROM table1 WHERE id=999')
+            );
+
+            $this->assertEquals(
+                array('Berlin' => 'Germany', 'Paris' => 'France'),
+                $oDB->getAssoc('SELECT city, country FROM table1')
+            );
+            $this->assertEquals(
+                array(),
+                $oDB->getAssoc('SELECT city, country FROM table1 WHERE id=999')
+            );
+        }
+    }
 }
index b81cace1702d3af50392d7682d56c3f11fbbe9ba..4529c69394b53c8cab1e50775c549fe516d942c5 100755 (executable)
@@ -28,7 +28,7 @@ function isReverseOnlyInstallation()
 
 
 echo 'Checking database got created ... ';
-if ($oDB->databaseExists()) {
+if ($oDB->checkConnection()) {
     $print_success();
 } else {
     $print_fail();