-
Notifications
You must be signed in to change notification settings - Fork 632
Expand file tree
/
Copy pathFindManualPageTest.php
More file actions
114 lines (91 loc) · 4.51 KB
/
Copy pathFindManualPageTest.php
File metadata and controls
114 lines (91 loc) · 4.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<?php
declare(strict_types=1);
namespace {
// include/manual-lookup.inc defines global functions and depends on the global
// get_manual_search_sections() (normally from include/site.inc). Provide the same
// section list here so the file can be exercised without pulling in all of site.inc.
if (!function_exists('get_manual_search_sections')) {
function get_manual_search_sections(): array
{
return ['', 'book.', 'ref.', 'function.', 'class.', 'enum.', 'features.', 'control-structures.', 'language.', 'about.', 'faq.'];
}
}
require_once __DIR__ . '/../../../include/manual-lookup.inc';
}
namespace phpweb\Test\Unit\ManualLookup {
use PHPUnit\Framework;
#[Framework\Attributes\CoversFunction('find_manual_page')]
#[Framework\Attributes\CoversFunction('find_manual_page_slow')]
final class FindManualPageTest extends Framework\TestCase
{
private string $root;
private ?string $originalDocumentRoot;
protected function setUp(): void
{
$this->root = sys_get_temp_dir() . '/phpweb-ml-' . uniqid('', true);
mkdir($this->root . '/backend', 0777, true);
mkdir($this->root . '/manual/en', 0777, true);
// Filesystem (slow-path) target for the keyword "echo".
file_put_contents($this->root . '/manual/en/function.echo.php', '<?php');
$this->originalDocumentRoot = $_SERVER['DOCUMENT_ROOT'] ?? null;
$_SERVER['DOCUMENT_ROOT'] = $this->root;
}
protected function tearDown(): void
{
if ($this->originalDocumentRoot === null) {
unset($_SERVER['DOCUMENT_ROOT']);
} else {
$_SERVER['DOCUMENT_ROOT'] = $this->originalDocumentRoot;
}
array_map('unlink', glob($this->root . '/backend/*') ?: []);
array_map('unlink', glob($this->root . '/manual/en/*') ?: []);
@rmdir($this->root . '/backend');
@rmdir($this->root . '/manual/en');
@rmdir($this->root . '/manual');
@rmdir($this->root);
}
/**
* Regression test for the production fatal:
* Uncaught PDOException: SQLSTATE[HY000]: General error: 8
* attempt to write a readonly database in include/manual-lookup.inc
*
* When the sqlite fast-path fails for ANY reason (a read-only/locked database,
* or a corrupt/truncated one from an interrupted rsync), find_manual_page() must
* fall back to the filesystem search instead of throwing an uncaught exception.
*/
public function testFallsBackToSlowSearchWhenSqliteQueryFails(): void
{
file_put_contents($this->root . '/backend/manual-lookup.sqlite', 'this is not a sqlite database');
$result = find_manual_page('en', 'echo');
self::assertSame('/manual/en/function.echo.php', $result);
}
public function testFallsBackToSlowSearchForDottedKeywordWhenSqliteQueryFails(): void
{
// A dotted keyword takes the other SQL branch in find_manual_page(); it must
// fall back to the filesystem search on a broken database too.
file_put_contents($this->root . '/backend/manual-lookup.sqlite', 'this is not a sqlite database');
$result = find_manual_page('en', 'function.echo');
self::assertSame('/manual/en/function.echo.php', $result);
}
#[Framework\Attributes\RequiresPhpExtension('pdo_sqlite')]
public function testUsesSqliteFastPathWhenDatabaseIsValid(): void
{
$this->buildValidDatabase();
$result = find_manual_page('en', 'function.echo');
self::assertSame('/manual/en/function.echo.php', $result);
}
public function testFallsBackToSlowSearchWhenNoDatabasePresent(): void
{
// No backend/manual-lookup.sqlite at all -> slow (filesystem) search only.
$result = find_manual_page('en', 'echo');
self::assertSame('/manual/en/function.echo.php', $result);
}
private function buildValidDatabase(): void
{
$dbh = new \PDO('sqlite:' . $this->root . '/backend/manual-lookup.sqlite');
$dbh->exec('CREATE TABLE fs (lang TEXT, prefix TEXT, keyword TEXT, name TEXT, prio INT)');
$dbh->exec("INSERT INTO fs (lang, prefix, keyword, name, prio) VALUES ('en', 'function.', 'echo', '/manual/en/function.echo.php', 3)");
$dbh = null;
}
}
}