diff --git a/src/Codeception/Lib/DbPopulator.php b/src/Codeception/Lib/DbPopulator.php index 8f09f84223..1e88713f03 100644 --- a/src/Codeception/Lib/DbPopulator.php +++ b/src/Codeception/Lib/DbPopulator.php @@ -8,16 +8,14 @@ class DbPopulator { /** - * The command to be executed. - * - * @var string + * @var array */ - private $builtCommand; + protected $config; /** * @var array */ - protected $config; + protected $commands; /** * Constructs a DbPopulator object for the given command and Db module. @@ -29,8 +27,11 @@ class DbPopulator public function __construct($config) { $this->config = $config; - $command = $this->config['populator']; - $this->builtCommand = $this->buildCommand((string) $command); + + //Convert To Array Format + if (isset($this->config['dump']) && !is_array($this->config['dump'])) { + $this->config['dump'] = [$this->config['dump']]; + } } /** @@ -49,10 +50,10 @@ public function __construct($config) * ``` * * @param string $command The command to be evaluated using the given config - * @param array $config The configuration values used to replace any found $keys with values from this array. + * @param string|null $dumpFile The dump file to build the command with. * @return string The resulting command string after evaluating any configuration's key */ - protected function buildCommand($command) + protected function buildCommand($command, $dumpFile = null) { $dsn = isset($this->config['dsn']) ? $this->config['dsn'] : ''; $dsnVars = []; @@ -64,9 +65,18 @@ protected function buildCommand($command) $dsnVars[$k] = $v; } } + $vars = array_merge($dsnVars, $this->config); + + if ($dumpFile !== null) { + $vars['dump'] = $dumpFile; + } + foreach ($vars as $key => $value) { - $vars['$'.$key] = $value; + if (!is_array($value)) { + $vars['$'.$key] = $value; + } + unset($vars[$key]); } return str_replace(array_keys($vars), array_values($vars), $command); @@ -81,7 +91,15 @@ protected function buildCommand($command) */ public function run() { - $command = $this->getBuiltCommand(); + foreach ($this->buildCommands() as $command) { + $this->runCommand($command); + } + + return true; + } + + private function runCommand($command) + { codecept_debug("[Db] Executing Populator: `$command`"); exec($command, $output, $exitCode); @@ -95,11 +113,22 @@ public function run() } codecept_debug("[Db] Populator Finished."); - return true; } - public function getBuiltCommand() + public function buildCommands() { - return $this->builtCommand; + if ($this->commands !== null) { + return $this->commands; + } else if (!isset($this->config['dump']) || $this->config['dump'] === false) { + return [$this->buildCommand($this->config['populator'])]; + } + + $this->commands = []; + + foreach ($this->config['dump'] as $dumpFile) { + $this->commands[] = $this->buildCommand($this->config['populator'], $dumpFile); + } + + return $this->commands; } } diff --git a/src/Codeception/Module/Db.php b/src/Codeception/Module/Db.php index 7f2cebb3e5..efd0a5c4a4 100644 --- a/src/Codeception/Module/Db.php +++ b/src/Codeception/Module/Db.php @@ -74,6 +74,17 @@ * ssl_verify_server_cert: false * ssl_cipher: 'AES256-SHA' * + * ## Example with multi-dumps + * modules: + * enabled: + * - Db: + * dsn: 'mysql:host=localhost;dbname=testdb' + * user: 'root' + * password: '' + * dump: + * - 'tests/_data/dump.sql' + * - 'tests/_data/dump-2.sql' + * * ## Example with multi-databases * * modules: @@ -445,24 +456,45 @@ private function readSql($databaseKey = null, $databaseConfig = null) return; } - if (!file_exists(Configuration::projectDir() . $databaseConfig['dump'])) { + if (!is_array($databaseConfig['dump'])) { + $databaseConfig['dump'] = [$databaseConfig['dump']]; + } + + $sql = ''; + + foreach ($databaseConfig['dump'] as $filePath) { + $sql .= $this->readSqlFile($filePath); + } + + if (!empty($sql)) { + // split SQL dump into lines + $this->databasesSql[$databaseKey] = preg_split('/\r\n|\n|\r/', $sql, -1, PREG_SPLIT_NO_EMPTY); + } + } + + /** + * @param $filePath + * + * @return bool|null|string|string[] + * @throws \Codeception\Exception\ModuleConfigException + */ + private function readSqlFile($filePath) + { + if (!file_exists(Configuration::projectDir() . $filePath)) { throw new ModuleConfigException( __CLASS__, "\nFile with dump doesn't exist.\n" . "Please, check path for sql file: " - . $databaseConfig['dump'] + . $filePath ); } - $sql = file_get_contents(Configuration::projectDir() . $databaseConfig['dump']); + $sql = file_get_contents(Configuration::projectDir() . $filePath); // remove C-style comments (except MySQL directives) $sql = preg_replace('%/\*(?!!\d+).*?\*/%s', '', $sql); - if (!empty($sql)) { - // split SQL dump into lines - $this->databasesSql[$databaseKey] = preg_split('/\r\n|\n|\r/', $sql, -1, PREG_SPLIT_NO_EMPTY); - } + return $sql; } private function connect($databaseKey, $databaseConfig) @@ -511,6 +543,7 @@ private function connect($databaseKey, $databaseConfig) } try { + $this->debugSection('Connecting To Db', ['config' => $databaseConfig, 'options' => $options]); $this->drivers[$databaseKey] = Driver::create($databaseConfig['dsn'], $databaseConfig['user'], $databaseConfig['password'], $options); } catch (\PDOException $e) { $message = $e->getMessage(); diff --git a/tests/data/sqlite.db b/tests/data/sqlite.db index cd631d343e..e69de29bb2 100755 Binary files a/tests/data/sqlite.db and b/tests/data/sqlite.db differ diff --git a/tests/unit/Codeception/Module/Db/Populator/DbPopulatorTest.php b/tests/unit/Codeception/Module/Db/Populator/DbPopulatorTest.php index 16d72ec912..c1820b40ff 100644 --- a/tests/unit/Codeception/Module/Db/Populator/DbPopulatorTest.php +++ b/tests/unit/Codeception/Module/Db/Populator/DbPopulatorTest.php @@ -16,14 +16,39 @@ public function testCommandBuilderInterpolatesVariables() 'dsn' => 'mysql:host=127.0.0.1;dbname=my_db', 'dump' => 'tests/data/dumps/sqlite.sql', 'user' => 'root', + 'populator' => 'mysql -u $user -h $host -D $dbname < $dump', + 'databases' => [] + ] + ); + + $this->assertEquals( + ['mysql -u root -h 127.0.0.1 -D my_db < tests/data/dumps/sqlite.sql'], + $populator->buildCommands() + ); + } + + public function testCommandBuilderInterpolatesVariablesMultiDump() + { + $populator = new DbPopulator( + [ + 'populate' => true, + 'dsn' => 'mysql:host=127.0.0.1;dbname=my_db', + 'dump' => [ + 'tests/data/dumps/sqlite.sql', + 'tests/data/dumps/sqlite2.sql', + ], + 'user' => 'root', 'populator' => 'mysql -u $user -h $host -D $dbname < $dump' ] ); $this->assertEquals( - 'mysql -u root -h 127.0.0.1 -D my_db < tests/data/dumps/sqlite.sql', - $populator->getBuiltCommand() + [ + 'mysql -u root -h 127.0.0.1 -D my_db < tests/data/dumps/sqlite.sql', + 'mysql -u root -h 127.0.0.1 -D my_db < tests/data/dumps/sqlite2.sql' + ], + $populator->buildCommands() ); } @@ -34,8 +59,8 @@ public function testCommandBuilderWontTouchVariablesNotFound() 'user' => 'root', ]); $this->assertEquals( - 'noop_tool -u root -h $host -D $dbname < $dump', - $populator->getBuiltCommand() + ['noop_tool -u root -h $host -D $dbname < $dump'], + $populator->buildCommands() ); }