Skip to content

Commit 55d61b4

Browse files
committed
ACPT-1751: Enable Suspension of Cron-Triggered Indexer Operations
- Add unit test that covers mview update with suspended indexer status;
1 parent 93081f1 commit 55d61b4

File tree

1 file changed

+208
-0
lines changed

1 file changed

+208
-0
lines changed
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Indexer\Test\Unit\Plugin\Mview;
9+
10+
use Magento\Framework\Indexer\ConfigInterface;
11+
use Magento\Framework\Indexer\IndexerInterface;
12+
use Magento\Framework\Indexer\IndexerRegistry;
13+
use Magento\Framework\Indexer\StateInterface;
14+
use Magento\Framework\Mview\ViewInterface;
15+
use Magento\Indexer\Plugin\Mview\ViewUpdatePlugin;
16+
use PHPUnit\Framework\MockObject\MockObject;
17+
use PHPUnit\Framework\TestCase;
18+
use Psr\Log\LoggerInterface;
19+
20+
class ViewUpdatePluginTest extends TestCase
21+
{
22+
/**
23+
* @var ViewUpdatePlugin|MockObject
24+
*/
25+
private $plugin;
26+
27+
/**
28+
* @var IndexerRegistry|MockObject
29+
*/
30+
private $indexerRegistryMock;
31+
32+
/**
33+
* @var ConfigInterface|MockObject
34+
*/
35+
private $configMock;
36+
37+
/**
38+
* @var LoggerInterface|MockObject
39+
*/
40+
private $loggerMock;
41+
42+
/**
43+
* @inheritDoc
44+
*/
45+
protected function setUp(): void
46+
{
47+
$this->indexerRegistryMock = $this->createMock(IndexerRegistry::class);
48+
$this->configMock = $this->createMock(ConfigInterface::class);
49+
$this->loggerMock = $this->createMock(LoggerInterface::class);
50+
51+
$this->plugin = new ViewUpdatePlugin(
52+
$this->indexerRegistryMock,
53+
$this->configMock,
54+
$this->loggerMock
55+
);
56+
}
57+
58+
/**
59+
* Tests the behavior when the associated indexer is suspended.
60+
*/
61+
public function testAroundUpdateWithSuspendedIndexer(): void
62+
{
63+
$viewId = 'test_view';
64+
$indexerId = 'test_indexer';
65+
$viewMock = $this->createMock(ViewInterface::class);
66+
$indexerMock = $this->createMock(IndexerInterface::class);
67+
68+
$viewMock->expects($this->once())->method('getId')->willReturn($viewId);
69+
$this->configMock->expects($this->once())
70+
->method('getIndexers')
71+
->willReturn([$indexerId => ['view_id' => $viewId]]);
72+
73+
$this->indexerRegistryMock->expects($this->once())
74+
->method('get')
75+
->with($indexerId)
76+
->willReturn($indexerMock);
77+
78+
$indexerMock->expects($this->once())
79+
->method('getStatus')
80+
->willReturn(StateInterface::STATUS_SUSPENDED);
81+
82+
$this->loggerMock->expects($this->once())
83+
->method('info')
84+
->with($this->stringContains("Suspended status detected for indexer"));
85+
86+
$proceed = function () {
87+
// This should not be called
88+
$this->fail('Proceed should not be called when indexer is suspended');
89+
};
90+
91+
$this->plugin->aroundUpdate($viewMock, $proceed);
92+
}
93+
94+
/**
95+
* Tests the behavior when the associated indexer is not suspended.
96+
*/
97+
public function testAroundUpdateWithNonSuspendedIndexer(): void
98+
{
99+
$viewId = 'test_view';
100+
$indexerId = 'test_indexer';
101+
$viewMock = $this->createMock(ViewInterface::class);
102+
$indexerMock = $this->createMock(IndexerInterface::class);
103+
104+
$viewMock->expects($this->once())->method('getId')->willReturn($viewId);
105+
$this->configMock->expects($this->once())
106+
->method('getIndexers')
107+
->willReturn([$indexerId => ['view_id' => $viewId]]);
108+
109+
$this->indexerRegistryMock->expects($this->once())
110+
->method('get')
111+
->with($indexerId)
112+
->willReturn($indexerMock);
113+
114+
$indexerMock->expects($this->once())
115+
->method('getStatus')
116+
->willReturn(StateInterface::STATUS_VALID);
117+
118+
$proceedCalled = false;
119+
$proceed = function () use (&$proceedCalled) {
120+
$proceedCalled = true;
121+
};
122+
123+
$this->plugin->aroundUpdate($viewMock, $proceed);
124+
125+
$this->assertTrue($proceedCalled, 'Proceed should be called when indexer is not suspended');
126+
}
127+
128+
/**
129+
* Tests the behavior when an indexer sharing the same shared_index is suspended.
130+
*/
131+
public function testAroundUpdateWithSharedIndexSuspended(): void
132+
{
133+
$viewId = 'test_view';
134+
$indexerId = 'test_indexer';
135+
$sharedIndexId = 'shared_index';
136+
$viewMock = $this->createMock(ViewInterface::class);
137+
138+
$viewMock->expects($this->once())->method('getId')->willReturn($viewId);
139+
140+
$this->configMock->method('getIndexers')->willReturnOnConsecutiveCalls(
141+
[
142+
$indexerId => ['view_id' => $viewId]
143+
],
144+
[
145+
'test_indexer' => [
146+
'view_id' => 'test_view',
147+
'shared_index' => 'shared_index'
148+
],
149+
'another_test_indexer' => [
150+
'view_id' => 'another_view_id',
151+
'shared_index' => 'shared_index',
152+
]
153+
]
154+
);
155+
156+
$this->configMock->expects($this->once())
157+
->method('getIndexer')
158+
->willReturn(['view_id' => $viewId, 'shared_index' => $sharedIndexId]);
159+
160+
$indexerMock1 = $this->createMock(IndexerInterface::class);
161+
$indexerMock2 = $this->createMock(IndexerInterface::class);
162+
$indexerMock3 = $this->createMock(IndexerInterface::class);
163+
$this->indexerRegistryMock->expects($this->exactly(3))
164+
->method('get')
165+
->willReturnOnConsecutiveCalls($indexerMock1, $indexerMock2, $indexerMock3);
166+
$indexerMock1->expects($this->once())
167+
->method('getStatus')
168+
->willReturn(StateInterface::STATUS_INVALID);
169+
$indexerMock2->expects($this->once())
170+
->method('getStatus')
171+
->willReturn(StateInterface::STATUS_INVALID);
172+
$indexerMock3->expects($this->once())
173+
->method('getStatus')
174+
->willReturn(StateInterface::STATUS_SUSPENDED);
175+
176+
$this->loggerMock->expects($this->once())
177+
->method('info')
178+
->with($this->stringContains("Suspended status detected for indexer"));
179+
180+
$proceed = function () {
181+
// This should not be called
182+
$this->fail('Proceed should not be called when any indexer with the same shared_index is suspended');
183+
};
184+
185+
$this->plugin->aroundUpdate($viewMock, $proceed);
186+
}
187+
188+
/**
189+
* Tests that the proceed function is called when there's no matching indexer ID for the given view ID.
190+
*/
191+
public function testAroundUpdateProceedsWhenIndexerIdIsNull()
192+
{
193+
$viewMock = $this->createMock(ViewInterface::class);
194+
$viewMock->method('getId')->willReturn('nonexistent_view_id');
195+
196+
$this->configMock->method('getIndexers')->willReturn([]);
197+
198+
// The proceed function should be called since no matching indexer ID was found
199+
$proceedCalled = false;
200+
$proceed = function () use (&$proceedCalled) {
201+
$proceedCalled = true;
202+
};
203+
204+
$this->plugin->aroundUpdate($viewMock, $proceed);
205+
206+
$this->assertTrue($proceedCalled, 'Proceed should have been called when no matching indexer ID is found.');
207+
}
208+
}

0 commit comments

Comments
 (0)