Reject invalid uploads and expand flow tests.

This commit is contained in:
tim
2026-09-26 15:27:51 +02:00
parent 716a609f4e
commit 8f4851e576
9 changed files with 427 additions and 11 deletions
+66
View File
@@ -1,6 +1,7 @@
<?php
namespace Xxx\Tests\Unit;
use PHPUnit\Framework\Attributes\DataProvider;
use Xxx\Tests\Support\FakeDb;
use Xxx\Tests\Support\Mail;
use Xxx\Tests\Support\SiteData;
@@ -110,6 +111,71 @@ class SaveDataTest extends TestCase {
$this->assertContains("O'Brien\"; DROP TABLE xxx; --", $insert['params']);
}
public static function failedQueries(): array {
return array(
'visitor insert' => array(FALSE, 'post', array(), array(), '/^INSERT INTO queue/'),
'editor insert' => array(TRUE, 'submit', array(), array(), '/^INSERT INTO queue/'),
'queue update' => array(TRUE, 'submit', array('id' => '5'), array(), '/^UPDATE queue/'),
'live update' => array(TRUE, 'post', array('id' => '1'), array(), '/^UPDATE xxx/'),
'move from queue' => array(TRUE, 'post', array('id' => '5'), array('queue' => '1'), '/^INSERT INTO xxx/'),
'queue image lookup' => array(TRUE, 'post', array('id' => '5', 'uploaded' => '5'), array('queue' => '1'), '/^SELECT img, mime FROM queue/'),
);
}
#[DataProvider('failedQueries')]
public function testAFailedQueryKeepsTheStoryAndUploadWithoutSendingMail(bool $admin, string $action, array $post, array $get, string $pattern): void {
$pending = $this->pendingImage();
$session = $_SESSION + array('captcha_ok' => time());
$state = $this->tmp . '/failed-save';
file_put_contents($state, serialize(array(
'tables' => self::TABLES, 'admin' => $admin, 'action' => $action, 'pattern' => $pattern,
'post' => $post + array('title' => 'Title', 'author' => 'Ann', 'story' => '<p>Text.</p>', 'uploaded' => 'pending'),
'get' => $get, 'session' => $session,
)));
$file = var_export($state, TRUE);
$code = <<<PHP
\$state = unserialize(file_get_contents($file));
Xxx\Tests\Support\SiteData::install(\$state['tables']);
Xxx\Tests\Support\FakeDb::on(\$state['pattern'], FALSE);
open_db('open');
\$is_admin = \$state['admin'];
\$action = \$state['action'];
\$_POST = \$state['post'];
\$_GET = \$state['get'];
\$_REQUEST = array_merge(\$_GET, \$_POST);
\$_SESSION = \$state['session'];
\$before = Xxx\Tests\Support\SiteData::\$tables;
\$returned = FALSE;
// db_fail() exits, so save the result at shutdown.
register_shutdown_function(function () use (\$before, &\$returned) {
file_put_contents($file, serialize(array(
'before' => \$before, 'tables' => Xxx\Tests\Support\SiteData::\$tables,
'session' => \$_SESSION, 'queries' => Xxx\Tests\Support\FakeDb::queries(),
'returned' => \$returned, 'status' => http_response_code(),
)));
});
save_data();
\$returned = TRUE;
PHP;
$result = Mail::run($code, array('UPLOAD_DIR' => $this->tmp . '/uploads'));
$this->assertSame(0, $result['status'], $result['stderr']);
$this->assertSame('', $result['stderr']);
$this->assertSame('<p>Sorry, something went wrong. Please try again later.</p>', $result['stdout']);
$this->assertStringContainsString('xxx: database error at post.lib.php:', $result['log']);
$this->assertStringNotContainsString('Warning', $result['log']);
$this->assertStringNotContainsString('Notice', $result['log']);
$this->assertSame(array(), $result['mails']);
$saved = unserialize(file_get_contents($state));
$this->assertFalse($saved['returned']);
$this->assertSame(500, $saved['status']);
$this->assertSame($saved['before'], $saved['tables']);
$this->assertSame($session, $saved['session']);
$this->assertFileExists($pending);
$this->assertSame(self::png(), file_get_contents($pending));
$this->assertCount(1, preg_grep($pattern, $saved['queries']));
$this->assertMatchesRegularExpression($pattern, end($saved['queries']), 'no queries run after the failure');
}
// Visitors always add to the queue, and each story sends mail
public function testVisitorsCanOnlyAddToTheQueue(): void {
$state = $this->tmp . '/state';