Update database tests to prepare for more (#6500)

* Update database tests to prepare for more
Add test_db_name, test_db_user, test_db_pass to allow developers to have a dedicated testing database.
Extract DBTestCase to include common functionality for database based tests. Use transactions to isolate tests.
Enable STRICT_TRANS_TABLE, test for it's existence (only when we have a user that can set it)
Move the database cleanup to register_shutdown_function, this makes it happen every time at the end of tests.
If the was not empty, only truncate the tables (that aren't prepopulated) instead of drop the database.
Use our schema functions for schema tests.
Fix some missing array indexes so it doesn't clutter test output.

* Fix style
This commit is contained in:
Tony Murray
2017-04-26 07:56:00 -05:00
committed by GitHub
parent 562c8b3d06
commit 1b1907a09f
5 changed files with 115 additions and 35 deletions

View File

@ -1966,10 +1966,12 @@ function initStats()
'insert_sec' => 0.0,
'update' => 0,
'update_sec' => 0.0,
'delete' => 0,
'delete_sec' => 0.0,
'fetchcell' => 0,
'fetchcell_sec' => 0.0,
'fetchcol' => 0,
'fetchcol_sec' => 0.0,
'fetchcolumn' => 0,
'fetchcolumn_sec' => 0.0,
'fetchrow' => 0,
'fetchrow_sec' => 0.0,
'fetchrows' => 0,

View File

@ -104,6 +104,19 @@ if ($config['memcached']['enable'] === true) {
}
if (!module_selected('nodb', $init_modules)) {
// Check for testing database
if (getenv('DBTEST')) {
if (isset($config['test_db_name'])) {
$config['db_name'] = $config['test_db_name'];
}
if (isset($config['test_db_user'])) {
$config['db_user'] = $config['test_db_user'];
}
if (isset($config['test_db_pass'])) {
$config['db_pass'] = $config['test_db_pass'];
}
}
// Connect to database
try {
dbConnect();

View File

@ -27,29 +27,8 @@ namespace LibreNMS\Tests;
use PHPUnit_Framework_ExpectationFailedException as PHPUnitException;
class DBSetupTest extends \PHPUnit_Framework_TestCase
class DBSetupTest extends DBTestCase
{
public static function tearDownAfterClass()
{
if (getenv('DBTEST')) {
global $config, $empty_db;
if ($empty_db) {
dbQuery("DROP DATABASE " . $config['db_name']);
}
}
}
public function setUp()
{
if (getenv('DBTEST')) {
dbConnect();
} else {
$this->markTestSkipped('Database tests not enabled. Set DBTEST=1 to enable.');
}
}
public function testSetupDB()
{
global $schema;
@ -62,15 +41,9 @@ class DBSetupTest extends \PHPUnit_Framework_TestCase
public function testSchema()
{
global $config;
$schema = (int)@dbFetchCell('SELECT `version` FROM `dbSchema` LIMIT 1');
$schema = get_db_schema();
$this->assertGreaterThan(0, $schema, "Database has no schema!");
$files = glob($config['install_dir'] . '/sql-schema/*.sql');
end($files);
$expected = (int)basename(current($files), '.sql');
$this->assertEquals($expected, $schema, 'Schema not fully up-to-date');
$this->assertTrue(db_schema_is_current(), "Schema not fully up-to-date, at $schema");
}
public function testCheckDBCollation()
@ -114,6 +87,19 @@ class DBSetupTest extends \PHPUnit_Framework_TestCase
{
global $sql_mode;
$this->assertNotNull($sql_mode, 'Query to save SQL Mode in bootstrap.php failed');
// sql_mode can only be set by users with access
$access = array(
'GRANT ALL PRIVILEGES ON *.*',
'SUPER'
);
if (str_contains(join(PHP_EOL, dbFetchColumn('SHOW GRANTS')), $access)) {
$this->assertEquals(
array('ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'),
dbFetchColumn("SELECT @@global.sql_mode")
);
}
}
public function testValidateSchema()

48
tests/DBTestCase.php Normal file
View File

@ -0,0 +1,48 @@
<?php
/**
* DBTestCase.php
*
* Base Test Case for Database tests
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2017 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace LibreNMS\Tests;
class DBTestCase extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
parent::setUp();
if (getenv('DBTEST')) {
dbConnect();
dbBeginTransaction();
} else {
$this->markTestSkipped('Database tests not enabled. Set DBTEST=1 to enable.');
}
}
public function tearDown()
{
parent::tearDown();
if (getenv('DBTEST')) {
dbRollbackTransaction();
}
}
}

View File

@ -49,11 +49,11 @@ error_reporting(E_ALL & ~E_WARNING);
if (getenv('DBTEST')) {
global $empty_db, $schema;
global $schema, $sql_mode;
$sql_mode = dbFetchCell("SELECT @@global.sql_mode as sql_mode");
$sql_mode = dbFetchCell("SELECT @@global.sql_mode");
$empty_db = (dbFetchCell("SELECT count(*) FROM `information_schema`.`tables` WHERE `table_type` = 'BASE TABLE' AND `table_schema` = ?", array($config['db_name'])) == 0);
dbQuery("SET GLOBAL sql_mode='ONLY_FULL_GROUP_BY,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'");
dbQuery("SET GLOBAL sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'");
if ($empty_db) {
$cmd = $config['install_dir'] . '/build-base.php';
@ -61,4 +61,35 @@ if (getenv('DBTEST')) {
$cmd = '/usr/bin/env php ' . $config['install_dir'] . '/includes/sql-schema/update.php';
}
exec($cmd, $schema);
register_shutdown_function(function () use ($empty_db, $sql_mode) {
global $config;
dbConnect();
// restore sql_mode
dbQuery("SET GLOBAL sql_mode='$sql_mode'");
if ($empty_db) {
dbQuery("DROP DATABASE " . $config['db_name']);
} elseif (isset($config['test_db_name']) && $config['db_name'] == $config['test_db_name']) {
// truncate tables
$tables = dbFetchColumn('SHOW TABLES');
$excluded = array(
'alert_templates',
'config', // not sure about this one
'dbSchema',
'graph_types',
'port_association_mode',
'widgets',
);
$truncate = array_diff($tables, $excluded);
dbQuery("SET FOREIGN_KEY_CHECKS = 0");
foreach ($truncate as $table) {
dbQuery("TRUNCATE TABLE $table");
}
dbQuery("SET FOREIGN_KEY_CHECKS = 1");
}
});
}