xref: /dokuwiki/_test/tests/Search/Collection/LookupCollectionTest.php (revision 21fbd01b3c3eea88b767376b7b158f31f0f63127)
1ede46466SAndreas Gohr<?php
2ede46466SAndreas Gohr
3ede46466SAndreas Gohrnamespace dokuwiki\test\Search\Collection;
4ede46466SAndreas Gohr
5ede46466SAndreas Gohruse dokuwiki\Search\Collection\PageMetaCollection;
6*21fbd01bSAndreas Gohruse dokuwiki\Search\Exception\IndexIntegrityException;
7ede46466SAndreas Gohruse dokuwiki\Search\Exception\IndexLockException;
8ede46466SAndreas Gohruse dokuwiki\Search\Index\MemoryIndex;
9ede46466SAndreas Gohr
10ede46466SAndreas Gohrclass LookupCollectionTest extends \DokuWikiTest
11ede46466SAndreas Gohr{
12ede46466SAndreas Gohr    /**
13ede46466SAndreas Gohr     * Add data and directly check the underlying indexes for correctness
14ede46466SAndreas Gohr     */
15ede46466SAndreas Gohr    public function testAddEntity()
16ede46466SAndreas Gohr    {
17ede46466SAndreas Gohr        $index = new MockLookupCollection('a_entity', 'a_token', 'a_freq', 'a_reverse');
18ede46466SAndreas Gohr        $index->lock();
19ede46466SAndreas Gohr        $index->addEntity('wiki:start', ['wiki:logo.png', 'wiki:banner.jpg', 'wiki:icon.svg']);
20ede46466SAndreas Gohr        $index->unlock();
21ede46466SAndreas Gohr
22ede46466SAndreas Gohr        // check entity index
23ede46466SAndreas Gohr        $idxEntity = new MemoryIndex('a_entity');
24ede46466SAndreas Gohr        $this->assertEquals('wiki:start', $idxEntity->retrieveRow(0));
25ede46466SAndreas Gohr
26ede46466SAndreas Gohr        // check token index (single file, no suffix)
27ede46466SAndreas Gohr        $idxToken = new MemoryIndex('a_token');
28ede46466SAndreas Gohr        $this->assertEquals('wiki:logo.png', $idxToken->retrieveRow(0));
29ede46466SAndreas Gohr        $this->assertEquals('wiki:banner.jpg', $idxToken->retrieveRow(1));
30ede46466SAndreas Gohr        $this->assertEquals('wiki:icon.svg', $idxToken->retrieveRow(2));
31ede46466SAndreas Gohr
32ede46466SAndreas Gohr        // check frequency index — all frequencies are 1 (written without *1)
33ede46466SAndreas Gohr        $idxFreq = new MemoryIndex('a_freq');
34ede46466SAndreas Gohr        $this->assertEquals('0', $idxFreq->retrieveRow(0)); // entity 0 with implicit freq 1
35ede46466SAndreas Gohr        $this->assertEquals('0', $idxFreq->retrieveRow(1));
36ede46466SAndreas Gohr        $this->assertEquals('0', $idxFreq->retrieveRow(2));
37ede46466SAndreas Gohr
38ede46466SAndreas Gohr        // check reverse index
39ede46466SAndreas Gohr        $idxRev = new MemoryIndex('a_reverse');
40ede46466SAndreas Gohr        $this->assertEquals('0:1:2', $idxRev->retrieveRow(0));
41ede46466SAndreas Gohr    }
42ede46466SAndreas Gohr
43ede46466SAndreas Gohr    /**
44ede46466SAndreas Gohr     * Duplicate tokens should be deduplicated
45ede46466SAndreas Gohr     */
46ede46466SAndreas Gohr    public function testAddEntityDedup()
47ede46466SAndreas Gohr    {
48ede46466SAndreas Gohr        $index = new MockLookupCollection('b_entity', 'b_token', 'b_freq', 'b_reverse');
49ede46466SAndreas Gohr        $index->lock();
50ede46466SAndreas Gohr        $index->addEntity('wiki:start', ['wiki:logo.png', 'wiki:logo.png', 'wiki:banner.jpg']);
51ede46466SAndreas Gohr        $index->unlock();
52ede46466SAndreas Gohr
53ede46466SAndreas Gohr        $idxToken = new MemoryIndex('b_token');
54ede46466SAndreas Gohr        $this->assertEquals('wiki:logo.png', $idxToken->retrieveRow(0));
55ede46466SAndreas Gohr        $this->assertEquals('wiki:banner.jpg', $idxToken->retrieveRow(1));
56ede46466SAndreas Gohr
57ede46466SAndreas Gohr        $idxRev = new MemoryIndex('b_reverse');
58ede46466SAndreas Gohr        $this->assertEquals('0:1', $idxRev->retrieveRow(0));
59ede46466SAndreas Gohr    }
60ede46466SAndreas Gohr
61ede46466SAndreas Gohr    /**
62ede46466SAndreas Gohr     * Updating an entity should remove old tokens and add new ones
63ede46466SAndreas Gohr     */
64ede46466SAndreas Gohr    public function testUpdateEntity()
65ede46466SAndreas Gohr    {
66ede46466SAndreas Gohr        $index = new MockLookupCollection('c_entity', 'c_token', 'c_freq', 'c_reverse');
67ede46466SAndreas Gohr
68ede46466SAndreas Gohr        // initial add
69ede46466SAndreas Gohr        $index->lock();
70ede46466SAndreas Gohr        $index->addEntity('wiki:start', ['wiki:logo.png', 'wiki:banner.jpg']);
71ede46466SAndreas Gohr        $index->unlock();
72ede46466SAndreas Gohr
73ede46466SAndreas Gohr        // update: remove logo, keep banner, add icon
74ede46466SAndreas Gohr        $index->lock();
75ede46466SAndreas Gohr        $index->addEntity('wiki:start', ['wiki:banner.jpg', 'wiki:icon.svg']);
76ede46466SAndreas Gohr        $index->unlock();
77ede46466SAndreas Gohr
78ede46466SAndreas Gohr        // logo should be removed from frequency index
79ede46466SAndreas Gohr        $idxFreq = new MemoryIndex('c_freq');
80ede46466SAndreas Gohr        $this->assertEquals('', $idxFreq->retrieveRow(0)); // logo removed
81ede46466SAndreas Gohr        $this->assertEquals('0', $idxFreq->retrieveRow(1)); // banner still on entity 0
82ede46466SAndreas Gohr        $this->assertEquals('0', $idxFreq->retrieveRow(2)); // icon added on entity 0
83ede46466SAndreas Gohr
84ede46466SAndreas Gohr        // reverse index should only have banner and icon
85ede46466SAndreas Gohr        $idxRev = new MemoryIndex('c_reverse');
86ede46466SAndreas Gohr        $this->assertEquals('1:2', $idxRev->retrieveRow(0));
87ede46466SAndreas Gohr    }
88ede46466SAndreas Gohr
89ede46466SAndreas Gohr    /**
90ede46466SAndreas Gohr     * Test reverse assignments returns two-level structure with empty group key
91ede46466SAndreas Gohr     */
92ede46466SAndreas Gohr    public function testReverseAssignments()
93ede46466SAndreas Gohr    {
94ede46466SAndreas Gohr        $index = new MockLookupCollection('d_entity', 'd_token', 'd_freq', 'd_reverse');
95ede46466SAndreas Gohr        $index->lock();
96ede46466SAndreas Gohr        $index->addEntity('wiki:start', ['wiki:logo.png', 'wiki:banner.jpg']);
97ede46466SAndreas Gohr        $index->unlock();
98ede46466SAndreas Gohr
99ede46466SAndreas Gohr        $result = $index->getReverseAssignments('wiki:start');
1006734bb8cSAndreas Gohr        $this->assertEquals([0 => [0 => 0, 1 => 0]], $result);
101ede46466SAndreas Gohr    }
102ede46466SAndreas Gohr
103ede46466SAndreas Gohr    /**
104ede46466SAndreas Gohr     * Adding entity without lock should throw exception
105ede46466SAndreas Gohr     */
106ede46466SAndreas Gohr    public function testAddEntityWithoutLock()
107ede46466SAndreas Gohr    {
108ede46466SAndreas Gohr        $this->expectException(IndexLockException::class);
109ede46466SAndreas Gohr
110ede46466SAndreas Gohr        $index = new MockLookupCollection();
111ede46466SAndreas Gohr        $index->addEntity('wiki:start', ['wiki:logo.png']);
112ede46466SAndreas Gohr    }
113ede46466SAndreas Gohr
114ede46466SAndreas Gohr    /**
115ede46466SAndreas Gohr     * Adding empty token list should clear entity from indexes
116ede46466SAndreas Gohr     */
117ede46466SAndreas Gohr    public function testEmptyTokens()
118ede46466SAndreas Gohr    {
119ede46466SAndreas Gohr        $index = new MockLookupCollection('f_entity', 'f_token', 'f_freq', 'f_reverse');
120ede46466SAndreas Gohr
121ede46466SAndreas Gohr        // add some tokens first
122ede46466SAndreas Gohr        $index->lock();
123ede46466SAndreas Gohr        $index->addEntity('wiki:start', ['wiki:logo.png']);
124ede46466SAndreas Gohr        $index->unlock();
125ede46466SAndreas Gohr
126ede46466SAndreas Gohr        // now clear
127ede46466SAndreas Gohr        $index->lock();
128ede46466SAndreas Gohr        $index->addEntity('wiki:start', []);
129ede46466SAndreas Gohr        $index->unlock();
130ede46466SAndreas Gohr
131ede46466SAndreas Gohr        // frequency index should be empty for this token
132ede46466SAndreas Gohr        $idxFreq = new MemoryIndex('f_freq');
133ede46466SAndreas Gohr        $this->assertEquals('', $idxFreq->retrieveRow(0));
134ede46466SAndreas Gohr
135ede46466SAndreas Gohr        // reverse index should be empty
136ede46466SAndreas Gohr        $idxRev = new MemoryIndex('f_reverse');
137ede46466SAndreas Gohr        $this->assertEquals('', $idxRev->retrieveRow(0));
138ede46466SAndreas Gohr    }
139ede46466SAndreas Gohr
140ede46466SAndreas Gohr    /**
141ede46466SAndreas Gohr     * Test that PageMetaCollection('relation_media') uses correct index names
142ede46466SAndreas Gohr     */
143ede46466SAndreas Gohr    public function testMediaCollection()
144ede46466SAndreas Gohr    {
145ede46466SAndreas Gohr        $index = new PageMetaCollection('relation_media');
146ede46466SAndreas Gohr        $index->lock();
147ede46466SAndreas Gohr        $index->addEntity('wiki:start', ['wiki:logo.png', 'wiki:banner.jpg']);
148ede46466SAndreas Gohr        $index->unlock();
149ede46466SAndreas Gohr
150ede46466SAndreas Gohr        $idxToken = new MemoryIndex('relation_media_w');
151ede46466SAndreas Gohr        $this->assertEquals('wiki:logo.png', $idxToken->retrieveRow(0));
152ede46466SAndreas Gohr        $this->assertEquals('wiki:banner.jpg', $idxToken->retrieveRow(1));
153ede46466SAndreas Gohr
154ede46466SAndreas Gohr        $idxRev = new MemoryIndex('relation_media_p');
155ede46466SAndreas Gohr        $this->assertEquals('0:1', $idxRev->retrieveRow(0));
156ede46466SAndreas Gohr    }
157ede46466SAndreas Gohr
158ede46466SAndreas Gohr    /**
159ede46466SAndreas Gohr     * Test that PageMetaCollection('relation_references') uses correct index names
160ede46466SAndreas Gohr     */
161ede46466SAndreas Gohr    public function testReferencesCollection()
162ede46466SAndreas Gohr    {
163ede46466SAndreas Gohr        $index = new PageMetaCollection('relation_references');
164ede46466SAndreas Gohr        $index->lock();
165ede46466SAndreas Gohr        $index->addEntity('wiki:start', ['wiki:syntax', 'wiki:welcome']);
166ede46466SAndreas Gohr        $index->unlock();
167ede46466SAndreas Gohr
168ede46466SAndreas Gohr        $idxToken = new MemoryIndex('relation_references_w');
169ede46466SAndreas Gohr        $this->assertEquals('wiki:syntax', $idxToken->retrieveRow(0));
170ede46466SAndreas Gohr        $this->assertEquals('wiki:welcome', $idxToken->retrieveRow(1));
171ede46466SAndreas Gohr
172ede46466SAndreas Gohr        $idxRev = new MemoryIndex('relation_references_p');
173ede46466SAndreas Gohr        $this->assertEquals('0:1', $idxRev->retrieveRow(0));
174ede46466SAndreas Gohr
175ede46466SAndreas Gohr        $result = $index->getReverseAssignments('wiki:start');
1766734bb8cSAndreas Gohr        $this->assertEquals([0 => [0 => 0, 1 => 0]], $result);
177ede46466SAndreas Gohr    }
178ede46466SAndreas Gohr
179ede46466SAndreas Gohr    /**
1806734bb8cSAndreas Gohr     * resolveTokens should deduplicate and assign frequency 1 under group 0
181ede46466SAndreas Gohr     */
182ede46466SAndreas Gohr    public function testResolveTokens()
183ede46466SAndreas Gohr    {
184ede46466SAndreas Gohr        $index = new MockLookupCollection('rt_entity', 'rt_token', 'rt_freq', 'rt_reverse');
185ede46466SAndreas Gohr        $index->lock();
186ede46466SAndreas Gohr
187ede46466SAndreas Gohr        $result = $this->callInaccessibleMethod($index, 'resolveTokens', [
188ede46466SAndreas Gohr            ['wiki:logo.png', 'wiki:banner.jpg', 'wiki:logo.png'],
189ede46466SAndreas Gohr        ]);
190ede46466SAndreas Gohr
1916734bb8cSAndreas Gohr        // all tokens under group 0 (non-split)
1926734bb8cSAndreas Gohr        $this->assertArrayHasKey(0, $result);
1936734bb8cSAndreas Gohr        $this->assertCount(2, $result[0]); // deduplicated
194ede46466SAndreas Gohr
195ede46466SAndreas Gohr        // token IDs are sequential: logo=0, banner=1
1966734bb8cSAndreas Gohr        $this->assertEquals(1, $result[0][0]); // logo freq=1
1976734bb8cSAndreas Gohr        $this->assertEquals(1, $result[0][1]); // banner freq=1
198ede46466SAndreas Gohr    }
199ede46466SAndreas Gohr
200ede46466SAndreas Gohr    /**
201ede46466SAndreas Gohr     * resolveTokens with empty input should return empty array
202ede46466SAndreas Gohr     */
203ede46466SAndreas Gohr    public function testResolveTokensEmpty()
204ede46466SAndreas Gohr    {
205ede46466SAndreas Gohr        $index = new MockLookupCollection('rte_entity', 'rte_token', 'rte_freq', 'rte_reverse');
206ede46466SAndreas Gohr        $index->lock();
207ede46466SAndreas Gohr
208ede46466SAndreas Gohr        $result = $this->callInaccessibleMethod($index, 'resolveTokens', [[]]);
209ede46466SAndreas Gohr
210ede46466SAndreas Gohr        $this->assertEmpty($result);
211ede46466SAndreas Gohr    }
212ede46466SAndreas Gohr
213ede46466SAndreas Gohr    /**
214ede46466SAndreas Gohr     * countTokens should deduplicate and assign frequency 1
215ede46466SAndreas Gohr     */
216ede46466SAndreas Gohr    public function testCountTokens()
217ede46466SAndreas Gohr    {
218ede46466SAndreas Gohr        $index = new MockLookupCollection();
219ede46466SAndreas Gohr
220ede46466SAndreas Gohr        $result = $this->callInaccessibleMethod($index, 'countTokens', [
221ede46466SAndreas Gohr            ['wiki:logo.png', 'wiki:banner.jpg', 'wiki:logo.png'],
222ede46466SAndreas Gohr        ]);
223ede46466SAndreas Gohr
224ede46466SAndreas Gohr        $this->assertEquals([
225ede46466SAndreas Gohr            'wiki:logo.png' => 1,
226ede46466SAndreas Gohr            'wiki:banner.jpg' => 1,
227ede46466SAndreas Gohr        ], $result);
228ede46466SAndreas Gohr    }
2296734bb8cSAndreas Gohr
2306734bb8cSAndreas Gohr    /**
2316734bb8cSAndreas Gohr     * getEntitiesWithData returns entities that have frequency data
2326734bb8cSAndreas Gohr     */
2336734bb8cSAndreas Gohr    public function testGetEntitiesWithData()
2346734bb8cSAndreas Gohr    {
2356734bb8cSAndreas Gohr        $index = new MockLookupCollection('ewd_entity', 'ewd_token', 'ewd_freq', 'ewd_reverse');
2366734bb8cSAndreas Gohr        $index->lock();
2376734bb8cSAndreas Gohr        $index->addEntity('wiki:start', ['wiki:syntax', 'wiki:welcome']);
2386734bb8cSAndreas Gohr        $index->addEntity('wiki:other', ['wiki:syntax']);
2396734bb8cSAndreas Gohr        $index->addEntity('wiki:empty', []);
2406734bb8cSAndreas Gohr        $index->unlock();
2416734bb8cSAndreas Gohr
2426734bb8cSAndreas Gohr        $result = $index->getEntitiesWithData();
2436734bb8cSAndreas Gohr        sort($result);
2446734bb8cSAndreas Gohr        $this->assertEquals(['wiki:other', 'wiki:start'], $result);
2456734bb8cSAndreas Gohr    }
2466734bb8cSAndreas Gohr
2476734bb8cSAndreas Gohr    /**
2486734bb8cSAndreas Gohr     * resolveTokenFrequencies returns entity frequencies for given token IDs
2496734bb8cSAndreas Gohr     */
2506734bb8cSAndreas Gohr    public function testResolveTokenFrequencies()
2516734bb8cSAndreas Gohr    {
2526734bb8cSAndreas Gohr        $index = new MockLookupCollection('rtf_entity', 'rtf_token', 'rtf_freq', 'rtf_reverse');
2536734bb8cSAndreas Gohr        $index->lock();
2546734bb8cSAndreas Gohr        $index->addEntity('wiki:start', ['wiki:syntax', 'wiki:welcome']);
2556734bb8cSAndreas Gohr        $index->addEntity('wiki:other', ['wiki:syntax']);
2566734bb8cSAndreas Gohr        $index->unlock();
2576734bb8cSAndreas Gohr
2586734bb8cSAndreas Gohr        // token ID 0 = wiki:syntax, referenced by both entities
2596734bb8cSAndreas Gohr        $result = $index->resolveTokenFrequencies(0, [0]);
2606734bb8cSAndreas Gohr        $this->assertArrayHasKey(0, $result);
2616734bb8cSAndreas Gohr        $this->assertCount(2, $result[0]); // two entities have this token
2626734bb8cSAndreas Gohr    }
2636734bb8cSAndreas Gohr
2646734bb8cSAndreas Gohr    /**
265*21fbd01bSAndreas Gohr     * checkIntegrity passes on a healthy non-split collection
266*21fbd01bSAndreas Gohr     */
267*21fbd01bSAndreas Gohr    public function testCheckIntegrityHealthy()
268*21fbd01bSAndreas Gohr    {
269*21fbd01bSAndreas Gohr        $index = new MockLookupCollection('cih_entity', 'cih_token', 'cih_freq', 'cih_reverse');
270*21fbd01bSAndreas Gohr        $index->lock();
271*21fbd01bSAndreas Gohr        $index->addEntity('wiki:start', ['wiki:syntax']);
272*21fbd01bSAndreas Gohr        $index->unlock();
273*21fbd01bSAndreas Gohr
274*21fbd01bSAndreas Gohr        $index->checkIntegrity(); // should not throw
275*21fbd01bSAndreas Gohr        $this->assertTrue(true);
276*21fbd01bSAndreas Gohr    }
277*21fbd01bSAndreas Gohr
278*21fbd01bSAndreas Gohr    /**
279*21fbd01bSAndreas Gohr     * checkIntegrity passes on an empty non-split collection
280*21fbd01bSAndreas Gohr     */
281*21fbd01bSAndreas Gohr    public function testCheckIntegrityEmpty()
282*21fbd01bSAndreas Gohr    {
283*21fbd01bSAndreas Gohr        $index = new MockLookupCollection('cie_entity', 'cie_token', 'cie_freq', 'cie_reverse');
284*21fbd01bSAndreas Gohr        $index->checkIntegrity(); // should not throw
285*21fbd01bSAndreas Gohr        $this->assertTrue(true);
286*21fbd01bSAndreas Gohr    }
287*21fbd01bSAndreas Gohr
288*21fbd01bSAndreas Gohr    /**
289*21fbd01bSAndreas Gohr     * checkIntegrity detects token/frequency mismatch on non-split collection
290*21fbd01bSAndreas Gohr     */
291*21fbd01bSAndreas Gohr    public function testCheckIntegrityTokenFreqMismatch()
292*21fbd01bSAndreas Gohr    {
293*21fbd01bSAndreas Gohr        global $conf;
294*21fbd01bSAndreas Gohr        $index = new MockLookupCollection('cim_entity', 'cim_token', 'cim_freq', 'cim_reverse');
295*21fbd01bSAndreas Gohr        $index->lock();
296*21fbd01bSAndreas Gohr        $index->addEntity('wiki:start', ['wiki:syntax']);
297*21fbd01bSAndreas Gohr        $index->unlock();
298*21fbd01bSAndreas Gohr
299*21fbd01bSAndreas Gohr        // corrupt: add extra line to token index
300*21fbd01bSAndreas Gohr        file_put_contents($conf['indexdir'] . '/cim_token.idx', "extra\n", FILE_APPEND);
301*21fbd01bSAndreas Gohr
302*21fbd01bSAndreas Gohr        $this->expectException(IndexIntegrityException::class);
303*21fbd01bSAndreas Gohr        (new MockLookupCollection('cim_entity', 'cim_token', 'cim_freq', 'cim_reverse'))->checkIntegrity();
304*21fbd01bSAndreas Gohr    }
305*21fbd01bSAndreas Gohr
306*21fbd01bSAndreas Gohr    /**
307*21fbd01bSAndreas Gohr     * checkIntegrity detects entity/reverse mismatch on non-split collection
308*21fbd01bSAndreas Gohr     */
309*21fbd01bSAndreas Gohr    public function testCheckIntegrityEntityReverseMismatch()
310*21fbd01bSAndreas Gohr    {
311*21fbd01bSAndreas Gohr        global $conf;
312*21fbd01bSAndreas Gohr        $index = new MockLookupCollection('cir_entity', 'cir_token', 'cir_freq', 'cir_reverse');
313*21fbd01bSAndreas Gohr        $index->lock();
314*21fbd01bSAndreas Gohr        $index->addEntity('wiki:start', ['wiki:syntax']);
315*21fbd01bSAndreas Gohr        $index->unlock();
316*21fbd01bSAndreas Gohr
317*21fbd01bSAndreas Gohr        // corrupt: add extra line to reverse index
318*21fbd01bSAndreas Gohr        file_put_contents($conf['indexdir'] . '/cir_reverse.idx', "0\n", FILE_APPEND);
319*21fbd01bSAndreas Gohr
320*21fbd01bSAndreas Gohr        $this->expectException(IndexIntegrityException::class);
321*21fbd01bSAndreas Gohr        (new MockLookupCollection('cir_entity', 'cir_token', 'cir_freq', 'cir_reverse'))->checkIntegrity();
322*21fbd01bSAndreas Gohr    }
323*21fbd01bSAndreas Gohr
324*21fbd01bSAndreas Gohr    /**
325*21fbd01bSAndreas Gohr     * checkIntegrity detects missing frequency index when token index exists
326*21fbd01bSAndreas Gohr     */
327*21fbd01bSAndreas Gohr    public function testCheckIntegrityMissingFreqIndex()
328*21fbd01bSAndreas Gohr    {
329*21fbd01bSAndreas Gohr        global $conf;
330*21fbd01bSAndreas Gohr        $index = new MockLookupCollection('cimf_entity', 'cimf_token', 'cimf_freq', 'cimf_reverse');
331*21fbd01bSAndreas Gohr        $index->lock();
332*21fbd01bSAndreas Gohr        $index->addEntity('wiki:start', ['wiki:syntax']);
333*21fbd01bSAndreas Gohr        $index->unlock();
334*21fbd01bSAndreas Gohr
335*21fbd01bSAndreas Gohr        // corrupt: delete frequency index
336*21fbd01bSAndreas Gohr        @unlink($conf['indexdir'] . '/cimf_freq.idx');
337*21fbd01bSAndreas Gohr
338*21fbd01bSAndreas Gohr        $this->expectException(IndexIntegrityException::class);
339*21fbd01bSAndreas Gohr        (new MockLookupCollection('cimf_entity', 'cimf_token', 'cimf_freq', 'cimf_reverse'))->checkIntegrity();
340*21fbd01bSAndreas Gohr    }
341*21fbd01bSAndreas Gohr
342*21fbd01bSAndreas Gohr    /**
3436734bb8cSAndreas Gohr     * groupToSuffix throws on non-0 group for non-split collection
3446734bb8cSAndreas Gohr     */
3456734bb8cSAndreas Gohr    public function testGroupToSuffixValidation()
3466734bb8cSAndreas Gohr    {
3476734bb8cSAndreas Gohr        $this->expectException(\dokuwiki\Search\Exception\IndexUsageException::class);
3486734bb8cSAndreas Gohr
3496734bb8cSAndreas Gohr        $index = new MockLookupCollection('gs_entity', 'gs_token', 'gs_freq', 'gs_reverse');
3506734bb8cSAndreas Gohr        // non-split collection should reject group 5
3516734bb8cSAndreas Gohr        $index->getTokenIndex(5);
3526734bb8cSAndreas Gohr    }
353ede46466SAndreas Gohr}
354