xref: /dokuwiki/_test/tests/Search/IntegrityTest.php (revision b188a75bce0b8a807acf7eb725e2e5c6239fa50d)
121fbd01bSAndreas Gohr<?php
221fbd01bSAndreas Gohr
321fbd01bSAndreas Gohrnamespace dokuwiki\test\Search;
421fbd01bSAndreas Gohr
521fbd01bSAndreas Gohruse dokuwiki\Search\Collection\PageFulltextCollection;
621fbd01bSAndreas Gohruse dokuwiki\Search\Collection\PageTitleCollection;
721fbd01bSAndreas Gohruse dokuwiki\Search\Exception\IndexIntegrityException;
821fbd01bSAndreas Gohruse dokuwiki\Search\Indexer;
921fbd01bSAndreas Gohr
1021fbd01bSAndreas Gohr/**
1121fbd01bSAndreas Gohr * Tests the index integrity checking
1221fbd01bSAndreas Gohr */
1321fbd01bSAndreas Gohrclass IntegrityTest extends \DokuWikiTest
1421fbd01bSAndreas Gohr{
1521fbd01bSAndreas Gohr    /**
16*b188a75bSAndreas Gohr     * Clear the index directory and indexing metadata before each test
1721fbd01bSAndreas Gohr     */
1821fbd01bSAndreas Gohr    public function setUp(): void
1921fbd01bSAndreas Gohr    {
2021fbd01bSAndreas Gohr        parent::setUp();
2121fbd01bSAndreas Gohr        global $conf;
2221fbd01bSAndreas Gohr        $files = glob($conf['indexdir'] . '/*.idx');
2321fbd01bSAndreas Gohr        foreach ($files as $file) {
2421fbd01bSAndreas Gohr            @unlink($file);
2521fbd01bSAndreas Gohr        }
26*b188a75bSAndreas Gohr        // remove the .indexed tag so needsIndexing() won't skip re-indexing
27*b188a75bSAndreas Gohr        @unlink(metaFN('integritytest', '.indexed'));
2821fbd01bSAndreas Gohr        \dokuwiki\Search\Index\Lock::releaseAll();
2921fbd01bSAndreas Gohr    }
3021fbd01bSAndreas Gohr
3121fbd01bSAndreas Gohr    /**
3221fbd01bSAndreas Gohr     * Index a page so we have data to check
3321fbd01bSAndreas Gohr     */
3421fbd01bSAndreas Gohr    protected function indexTestPage(): void
3521fbd01bSAndreas Gohr    {
3621fbd01bSAndreas Gohr        saveWikiText('integritytest', 'Hello world testing integrity check.', 'Test');
3721fbd01bSAndreas Gohr        $indexer = new Indexer();
3821fbd01bSAndreas Gohr        $indexer->addPage('integritytest');
3921fbd01bSAndreas Gohr    }
4021fbd01bSAndreas Gohr
4121fbd01bSAndreas Gohr    /**
4221fbd01bSAndreas Gohr     * A healthy index should not throw
4321fbd01bSAndreas Gohr     */
4421fbd01bSAndreas Gohr    public function testHealthyIndex()
4521fbd01bSAndreas Gohr    {
4621fbd01bSAndreas Gohr        $this->indexTestPage();
4721fbd01bSAndreas Gohr
4821fbd01bSAndreas Gohr        $indexer = new Indexer();
4921fbd01bSAndreas Gohr        $indexer->checkIntegrity();
5021fbd01bSAndreas Gohr        $this->assertFalse($indexer->isIndexEmpty());
5121fbd01bSAndreas Gohr    }
5221fbd01bSAndreas Gohr
5321fbd01bSAndreas Gohr    /**
5421fbd01bSAndreas Gohr     * An empty index should not throw
5521fbd01bSAndreas Gohr     */
5621fbd01bSAndreas Gohr    public function testEmptyIndex()
5721fbd01bSAndreas Gohr    {
5821fbd01bSAndreas Gohr        $indexer = new Indexer();
5921fbd01bSAndreas Gohr        $indexer->checkIntegrity();
6021fbd01bSAndreas Gohr        $this->assertTrue($indexer->isIndexEmpty());
6121fbd01bSAndreas Gohr    }
6221fbd01bSAndreas Gohr
6321fbd01bSAndreas Gohr    /**
6421fbd01bSAndreas Gohr     * Corrupted fulltext index (token/frequency mismatch) should throw
6521fbd01bSAndreas Gohr     */
6621fbd01bSAndreas Gohr    public function testCorruptedFulltextTokenFrequency()
6721fbd01bSAndreas Gohr    {
6821fbd01bSAndreas Gohr        global $conf;
6921fbd01bSAndreas Gohr        $this->indexTestPage();
7021fbd01bSAndreas Gohr
7121fbd01bSAndreas Gohr        // Append an extra line to a token index to create a mismatch
7221fbd01bSAndreas Gohr        $collection = new PageFulltextCollection();
7321fbd01bSAndreas Gohr        $max = $collection->getTokenIndexMaximum();
7421fbd01bSAndreas Gohr        $this->assertGreaterThan(0, $max);
7521fbd01bSAndreas Gohr
7621fbd01bSAndreas Gohr        $tokenFile = $conf['indexdir'] . '/w' . $max . '.idx';
7721fbd01bSAndreas Gohr        $this->assertFileExists($tokenFile);
7821fbd01bSAndreas Gohr        file_put_contents($tokenFile, "corruptedentry\n", FILE_APPEND);
7921fbd01bSAndreas Gohr
8021fbd01bSAndreas Gohr        $this->expectException(IndexIntegrityException::class);
8121fbd01bSAndreas Gohr        (new PageFulltextCollection())->checkIntegrity();
8221fbd01bSAndreas Gohr    }
8321fbd01bSAndreas Gohr
8421fbd01bSAndreas Gohr    /**
8521fbd01bSAndreas Gohr     * Corrupted fulltext index (entity/reverse mismatch) should throw
8621fbd01bSAndreas Gohr     */
8721fbd01bSAndreas Gohr    public function testCorruptedFulltextEntityReverse()
8821fbd01bSAndreas Gohr    {
8921fbd01bSAndreas Gohr        global $conf;
9021fbd01bSAndreas Gohr        $this->indexTestPage();
9121fbd01bSAndreas Gohr
9221fbd01bSAndreas Gohr        $reverseFile = $conf['indexdir'] . '/pageword.idx';
9321fbd01bSAndreas Gohr        $this->assertFileExists($reverseFile);
9421fbd01bSAndreas Gohr        file_put_contents($reverseFile, "0\n", FILE_APPEND);
9521fbd01bSAndreas Gohr
9621fbd01bSAndreas Gohr        $this->expectException(IndexIntegrityException::class);
9721fbd01bSAndreas Gohr        (new PageFulltextCollection())->checkIntegrity();
9821fbd01bSAndreas Gohr    }
9921fbd01bSAndreas Gohr
10021fbd01bSAndreas Gohr    /**
10121fbd01bSAndreas Gohr     * Corrupted title index (entity/token mismatch) should throw
10221fbd01bSAndreas Gohr     */
10321fbd01bSAndreas Gohr    public function testCorruptedTitleIndex()
10421fbd01bSAndreas Gohr    {
10521fbd01bSAndreas Gohr        global $conf;
10621fbd01bSAndreas Gohr        $this->indexTestPage();
10721fbd01bSAndreas Gohr
10821fbd01bSAndreas Gohr        $titleFile = $conf['indexdir'] . '/title.idx';
10921fbd01bSAndreas Gohr        $this->assertFileExists($titleFile);
11021fbd01bSAndreas Gohr        file_put_contents($titleFile, "extra title\n", FILE_APPEND);
11121fbd01bSAndreas Gohr
11221fbd01bSAndreas Gohr        $this->expectException(IndexIntegrityException::class);
11321fbd01bSAndreas Gohr        (new PageTitleCollection())->checkIntegrity();
11421fbd01bSAndreas Gohr    }
11521fbd01bSAndreas Gohr
11621fbd01bSAndreas Gohr    /**
11721fbd01bSAndreas Gohr     * Indexer.checkIntegrity aggregates all collection checks
11821fbd01bSAndreas Gohr     */
11921fbd01bSAndreas Gohr    public function testIndexerCheckIntegrityDetectsCorruption()
12021fbd01bSAndreas Gohr    {
12121fbd01bSAndreas Gohr        global $conf;
12221fbd01bSAndreas Gohr        $this->indexTestPage();
12321fbd01bSAndreas Gohr
12421fbd01bSAndreas Gohr        // Corrupt title index
12521fbd01bSAndreas Gohr        $titleFile = $conf['indexdir'] . '/title.idx';
12621fbd01bSAndreas Gohr        file_put_contents($titleFile, "extra title\n", FILE_APPEND);
12721fbd01bSAndreas Gohr
12821fbd01bSAndreas Gohr        $this->expectException(IndexIntegrityException::class);
12921fbd01bSAndreas Gohr        (new Indexer())->checkIntegrity();
13021fbd01bSAndreas Gohr    }
13121fbd01bSAndreas Gohr}
132