-
Notifications
You must be signed in to change notification settings - Fork 1
Handle missing database config entries #192
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| use APICalls\MdwikiSql\Database; | ||
| use FilesystemIterator; | ||
| use PHPUnit\Framework\TestCase; | ||
| use RecursiveDirectoryIterator; | ||
| use RecursiveIteratorIterator; | ||
| use RuntimeException; | ||
|
|
||
| final class DatabaseConfigTest extends TestCase | ||
| { | ||
|
Comment on lines
+12
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great job on adding tests for the new error handling! To make the test suite even more comprehensive, consider adding a few more test cases:
Here is an example for a missing user, which also incorporates the suggestion to move cleanup to public function testSetDbThrowsExceptionWhenUserMissing(): void
{
$this->tempHome = sys_get_temp_dir() . '/dbconfig_test_incomplete_' . uniqid();
$this->createTempHome($this->tempHome, ['password' => 'secret']); // No 'user' key
$this->expectException(RuntimeException::class);
$this->expectExceptionMessageMatches('/missing required "user" entry/');
new Database('tools');
} |
||
| private ?string $originalHome = null; | ||
|
|
||
| protected function setUp(): void | ||
| { | ||
| $this->originalHome = getenv('HOME') !== false ? getenv('HOME') : null; | ||
| } | ||
|
|
||
| protected function tearDown(): void | ||
| { | ||
| if ($this->originalHome !== null) { | ||
| putenv('HOME=' . $this->originalHome); | ||
| } else { | ||
| putenv('HOME'); | ||
| } | ||
| } | ||
|
|
||
| public function testSetDbThrowsExceptionWhenConfigMissing(): void | ||
| { | ||
| $tempHome = sys_get_temp_dir() . '/dbconfig_test_missing_' . uniqid(); | ||
| $this->createTempHome($tempHome); | ||
|
|
||
| $this->expectException(RuntimeException::class); | ||
| $this->expectExceptionMessage('could not be read or parsed'); | ||
|
|
||
| try { | ||
| new Database('localhost'); | ||
| } finally { | ||
| $this->cleanupTempHome($tempHome); | ||
| } | ||
|
Comment on lines
+38
to
+42
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Example: class DatabaseConfigTest extends TestCase
{
// ...
private ?string $tempHome = null;
protected function tearDown(): void
{
// ... restore HOME env
if ($this->tempHome !== null) {
$this->cleanupTempHome($this->tempHome);
$this->tempHome = null;
}
}
public function testSetDbThrowsExceptionWhenConfigMissing(): void
{
$this->tempHome = sys_get_temp_dir() . '/dbconfig_test_missing_' . uniqid();
$this->createTempHome($this->tempHome);
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('could not be read or parsed');
new Database('localhost');
}
// ...
} |
||
| } | ||
|
|
||
| public function testSetDbThrowsExceptionWhenPasswordMissing(): void | ||
| { | ||
| $tempHome = sys_get_temp_dir() . '/dbconfig_test_incomplete_' . uniqid(); | ||
| $this->createTempHome($tempHome, ['user' => 'exampleuser']); | ||
|
|
||
| $this->expectException(RuntimeException::class); | ||
| $this->expectExceptionMessage('password'); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The assertion for the exception message is very broad. A more specific assertion makes the test more robust and less likely to pass for the wrong reasons. You can use $this->expectExceptionMessageMatches('/missing required "password" entry/'); |
||
|
|
||
| try { | ||
| new Database('tools'); | ||
| } finally { | ||
| $this->cleanupTempHome($tempHome); | ||
| } | ||
| } | ||
|
|
||
| private function createTempHome(string $path, array $config = []): void | ||
| { | ||
| $configDir = $path . '/confs'; | ||
| if (!is_dir($configDir)) { | ||
| mkdir($configDir, 0777, true); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| } | ||
|
|
||
| putenv('HOME=' . $path); | ||
|
|
||
| if ($config !== []) { | ||
| $ini = ''; | ||
| foreach ($config as $key => $value) { | ||
| $ini .= sprintf("%s = \"%s\"\n", $key, $value); | ||
| } | ||
| file_put_contents($configDir . '/db.ini', $ini); | ||
| } | ||
| } | ||
|
|
||
| private function cleanupTempHome(string $path): void | ||
| { | ||
| if (!is_dir($path)) { | ||
| return; | ||
| } | ||
|
|
||
| $items = new RecursiveIteratorIterator( | ||
| new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS), | ||
| RecursiveIteratorIterator::CHILD_FIRST | ||
| ); | ||
|
|
||
| foreach ($items as $item) { | ||
| if ($item->isDir()) { | ||
| @rmdir($item->getPathname()); | ||
| } else { | ||
| @unlink($item->getPathname()); | ||
| } | ||
| } | ||
|
|
||
| @rmdir($path); | ||
|
Comment on lines
+89
to
+97
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using the error suppression operator ( foreach ($items as $item) {
if ($item->isDir()) {
rmdir($item->getPathname());
} else {
unlink($item->getPathname());
}
}
rmdir($path); |
||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using the error suppression operator (
@) can hide issues and makes debugging harder. It's better to explicitly check for the file's readability first. This allows for more specific error messages about whether the file is unreadable versus being unparsable.