init
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright © Magento, Inc. All rights reserved.
|
||||
* See COPYING.txt for license details.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Magento\MessageQueue\Model;
|
||||
|
||||
use Magento\Framework\MessageQueue\Consumer;
|
||||
use Magento\Framework\MessageQueue\ConsumerFactory;
|
||||
use Magento\Framework\MessageQueue\EnvelopeFactory;
|
||||
use Magento\Framework\MessageQueue\QueueInterface;
|
||||
use Magento\MysqlMq\Model\QueueManagement;
|
||||
use Magento\MysqlMq\Model\ResourceModel\Queue;
|
||||
use Magento\TestFramework\ObjectManager;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Tests the different cases of consumers running by Consumer processor
|
||||
*/
|
||||
class ConsumerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var ObjectManager
|
||||
*/
|
||||
private $objectManager;
|
||||
|
||||
/**
|
||||
* @var Consumer
|
||||
*/
|
||||
private $model;
|
||||
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
private $queueResource;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->objectManager = ObjectManager::getInstance();
|
||||
/** @var ConsumerFactory $factory */
|
||||
$factory = $this->objectManager->get(ConsumerFactory::class);
|
||||
$this->model = $factory->get('demoConsumerWithConnectionException');
|
||||
$this->queueResource = $this->objectManager->get(Queue::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if after connection exception and retry
|
||||
* message doesn't have success status but still has status in progress
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testRunWithException(): void
|
||||
{
|
||||
/** @var EnvelopeFactory $envelopFactory */
|
||||
$envelopFactory = $this->objectManager->get(EnvelopeFactory::class);
|
||||
$messageBody = '{"name":"test"}';
|
||||
$topicName = 'demo.connection.exception';
|
||||
$queueName = 'queue-connection-exception';
|
||||
$envelope = $envelopFactory->create(['body' => $messageBody, 'properties' => ['topic_name' => $topicName]]);
|
||||
/** @var QueueInterface $queue */
|
||||
$queue = $this->objectManager->create(
|
||||
\Magento\MysqlMq\Model\Driver\Queue::class,
|
||||
['queueName' => $queueName]
|
||||
);
|
||||
$queue->push($envelope);
|
||||
$messages = $this->queueResource->getMessages($queueName, 1);
|
||||
$envelope = $envelopFactory->create(['body' => $messageBody, 'properties' => $messages[0]]);
|
||||
$this->model->process(1);
|
||||
$queue->reject($envelope);
|
||||
$this->model->process(1);
|
||||
$message = $this->getLastMessage($queueName);
|
||||
$this->assertEquals(QueueManagement::MESSAGE_STATUS_IN_PROGRESS, $message['status']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return last message by queue name
|
||||
*
|
||||
* @param string $queueName
|
||||
* @return array
|
||||
*/
|
||||
private function getLastMessage(string $queueName)
|
||||
{
|
||||
$connection = $this->queueResource->getConnection();
|
||||
$select = $connection->select()
|
||||
->from(
|
||||
['queue_message' => $this->queueResource->getTable('queue_message')],
|
||||
[]
|
||||
)->join(
|
||||
['queue_message_status' => $this->queueResource->getTable('queue_message_status')],
|
||||
'queue_message.id = queue_message_status.message_id',
|
||||
[
|
||||
QueueManagement::MESSAGE_QUEUE_RELATION_ID => 'id',
|
||||
QueueManagement::MESSAGE_STATUS => 'status',
|
||||
]
|
||||
)->join(
|
||||
['queue' => $this->queueResource->getTable('queue')],
|
||||
'queue.id = queue_message_status.queue_id',
|
||||
[QueueManagement::MESSAGE_QUEUE_NAME => 'name']
|
||||
)->where('queue.name = ?', $queueName)
|
||||
->order(['queue_message_status.id DESC']);
|
||||
|
||||
return $connection->fetchRow($select);
|
||||
}
|
||||
}
|
||||
+280
@@ -0,0 +1,280 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright © Magento, Inc. All rights reserved.
|
||||
* See COPYING.txt for license details.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Magento\MessageQueue\Model\Cron;
|
||||
|
||||
use Magento\Framework\App\Config\ReinitableConfigInterface;
|
||||
use Magento\Framework\App\DeploymentConfig;
|
||||
use Magento\Framework\App\DeploymentConfig\FileReader;
|
||||
use Magento\Framework\App\DeploymentConfig\Writer;
|
||||
use Magento\Framework\App\Filesystem\DirectoryList;
|
||||
use Magento\Framework\App\ResourceConnection;
|
||||
use Magento\Framework\Config\File\ConfigFilePool;
|
||||
use Magento\Framework\Filesystem;
|
||||
use Magento\Framework\Lock\Backend\Database;
|
||||
use Magento\Framework\Lock\LockManagerInterface;
|
||||
use Magento\Framework\MessageQueue\Consumer\ConfigInterface as ConsumerConfigInterface;
|
||||
use Magento\Framework\ObjectManagerInterface;
|
||||
use Magento\Framework\ShellInterface;
|
||||
use Magento\TestFramework\Helper\Bootstrap;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Tests the different cases of consumers running by ConsumersRunner
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class ConsumersRunnerTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var ObjectManagerInterface
|
||||
*/
|
||||
private $objectManager;
|
||||
|
||||
/**
|
||||
* Consumer config provider
|
||||
*
|
||||
* @var ConsumerConfigInterface
|
||||
*/
|
||||
private $consumerConfig;
|
||||
|
||||
/**
|
||||
* @var LockManagerInterface
|
||||
*/
|
||||
private $lockManager;
|
||||
|
||||
/**
|
||||
* @var FileReader
|
||||
*/
|
||||
private $reader;
|
||||
|
||||
/**
|
||||
* @var ConsumersRunner
|
||||
*/
|
||||
private $consumersRunner;
|
||||
|
||||
/**
|
||||
* @var Filesystem
|
||||
*/
|
||||
private $filesystem;
|
||||
|
||||
/**
|
||||
* @var ConfigFilePool
|
||||
*/
|
||||
private $configFilePool;
|
||||
|
||||
/**
|
||||
* @var ReinitableConfigInterface
|
||||
*/
|
||||
private $appConfig;
|
||||
|
||||
/**
|
||||
* @var ShellInterface|MockObject
|
||||
*/
|
||||
private $shellMock;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->objectManager = Bootstrap::getObjectManager();
|
||||
$this->shellMock = $this->getMockBuilder(ShellInterface::class)
|
||||
->getMockForAbstractClass();
|
||||
$resourceConnection = $this->objectManager->create(ResourceConnection::class);
|
||||
$deploymentConfig = $this->objectManager->create(DeploymentConfig::class);
|
||||
// create object with new otherwise dummy locker is created because of di.xml preference for integration tests
|
||||
$this->lockManager = new Database($resourceConnection, $deploymentConfig);
|
||||
$this->consumerConfig = $this->objectManager->get(ConsumerConfigInterface::class);
|
||||
$this->reader = $this->objectManager->get(FileReader::class);
|
||||
$this->filesystem = $this->objectManager->get(Filesystem::class);
|
||||
$this->configFilePool = $this->objectManager->get(ConfigFilePool::class);
|
||||
$this->appConfig = $this->objectManager->get(ReinitableConfigInterface::class);
|
||||
$this->consumersRunner = $this->objectManager->create(
|
||||
ConsumersRunner::class,
|
||||
['shellBackground' => $this->shellMock]
|
||||
);
|
||||
$this->config = $this->loadConfig();
|
||||
|
||||
$this->shellMock->expects($this->any())
|
||||
->method('execute')
|
||||
->willReturnCallback(
|
||||
function ($command, $arguments) {
|
||||
$command = vsprintf($command, $arguments);
|
||||
$params = Bootstrap::getInstance()->getAppInitParams();
|
||||
$params['MAGE_DIRS']['base']['path'] = BP;
|
||||
$params = 'INTEGRATION_TEST_PARAMS="' . urldecode(http_build_query($params)) . '"';
|
||||
$command = str_replace('bin/magento', 'dev/tests/integration/bin/magento', $command);
|
||||
$command = $params . ' ' . $command;
|
||||
|
||||
return exec("{$command} >/dev/null &"); //phpcs:ignore
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $specificConsumer
|
||||
* @param int $maxMessage
|
||||
* @param string $command
|
||||
* @param array $expectedArguments
|
||||
*
|
||||
* @return void
|
||||
* @dataProvider runDataProvider
|
||||
*/
|
||||
public function testArgumentMaxMessages(
|
||||
string $specificConsumer,
|
||||
int $maxMessage,
|
||||
string $command,
|
||||
array $expectedArguments
|
||||
) {
|
||||
$config = $this->config;
|
||||
$config['cron_consumers_runner'] = ['consumers' => [$specificConsumer], 'max_messages' => $maxMessage];
|
||||
$this->writeConfig($config);
|
||||
$this->shellMock->expects($this->any())
|
||||
->method('execute')
|
||||
->with($command, $expectedArguments);
|
||||
|
||||
$this->consumersRunner->run();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function runDataProvider()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'specificConsumer' => 'exportProcessor',
|
||||
'max_messages' => 10,
|
||||
'command' => PHP_BINARY . ' ' . BP . '/bin/magento queue:consumers:start %s %s %s',
|
||||
'expectedArguments' => ['exportProcessor', '--single-thread', '--max-messages=10'],
|
||||
],
|
||||
[
|
||||
'specificConsumer' => 'exportProcessor',
|
||||
'max_messages' => 5000,
|
||||
'command' => PHP_BINARY . ' ' . BP . '/bin/magento queue:consumers:start %s %s %s',
|
||||
'expectedArguments' => ['exportProcessor', '--single-thread', '--max-messages=100'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests running of specific consumer and his re-running when it is working
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSpecificConsumerAndRerun()
|
||||
{
|
||||
$specificConsumer = 'exportProcessor';
|
||||
$config = $this->config;
|
||||
$config['cron_consumers_runner'] = ['consumers' => [$specificConsumer], 'max_messages' => 0];
|
||||
$config['queue'] = ['only_spawn_when_message_available' => 0];
|
||||
$this->writeConfig($config);
|
||||
$this->reRunConsumersAndCheckLocks($specificConsumer);
|
||||
$this->reRunConsumersAndCheckLocks($specificConsumer);
|
||||
$this->assertTrue($this->lockManager->isLocked(md5($specificConsumer))); //phpcs:ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $specificConsumer
|
||||
* @return void
|
||||
*/
|
||||
private function reRunConsumersAndCheckLocks($specificConsumer)
|
||||
{
|
||||
$this->consumersRunner->run();
|
||||
|
||||
sleep(20);
|
||||
|
||||
foreach ($this->consumerConfig->getConsumers() as $consumer) {
|
||||
$consumerName = $consumer->getName();
|
||||
|
||||
if ($consumerName === $specificConsumer) {
|
||||
$this->assertTrue($this->lockManager->isLocked(md5($consumerName))); //phpcs:ignore
|
||||
} else {
|
||||
$this->assertFalse($this->lockManager->isLocked(md5($consumerName))); //phpcs:ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests disabling cron job which runs consumers
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCronJobDisabled()
|
||||
{
|
||||
$config = $this->config;
|
||||
$config['cron_consumers_runner'] = ['cron_run' => false];
|
||||
|
||||
$this->writeConfig($config);
|
||||
|
||||
$this->consumersRunner->run();
|
||||
|
||||
sleep(20);
|
||||
|
||||
foreach ($this->consumerConfig->getConsumers() as $consumer) {
|
||||
$this->assertFalse($this->lockManager->isLocked(md5($consumer->getName()))); //phpcs:ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function loadConfig()
|
||||
{
|
||||
return $this->reader->load(ConfigFilePool::APP_ENV);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
private function writeConfig(array $config)
|
||||
{
|
||||
/** @var Writer $writer */
|
||||
$writer = $this->objectManager->get(Writer::class);
|
||||
$writer->saveConfig([ConfigFilePool::APP_ENV => $config]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function tearDown(): void
|
||||
{
|
||||
foreach ($this->consumerConfig->getConsumers() as $consumer) {
|
||||
foreach ($this->getConsumerProcessIds($consumer->getName()) as $consumerProcessId) {
|
||||
exec("kill {$consumerProcessId}"); //phpcs:ignore
|
||||
}
|
||||
}
|
||||
|
||||
$this->filesystem->getDirectoryWrite(DirectoryList::CONFIG)->writeFile(
|
||||
$this->configFilePool->getPath(ConfigFilePool::APP_ENV),
|
||||
"<?php\n return array();\n"
|
||||
);
|
||||
$this->writeConfig($this->config);
|
||||
$this->appConfig->reinit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Consumer ProcessIds
|
||||
*
|
||||
* @param string $consumer
|
||||
* @return string[]
|
||||
*/
|
||||
private function getConsumerProcessIds($consumer)
|
||||
{
|
||||
//phpcs:ignore
|
||||
exec("ps ax | grep -v grep | grep 'queue:consumers:start {$consumer}' | awk '{print $1}'", $output);
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright © Magento, Inc. All rights reserved.
|
||||
* See COPYING.txt for license details.
|
||||
*/
|
||||
|
||||
namespace Magento\MessageQueue\Model\Plugin\ResourceModel;
|
||||
|
||||
use Magento\TestFramework\Event\Magento;
|
||||
|
||||
class LockTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
/**
|
||||
* @var \Magento\Framework\ObjectManagerInterface
|
||||
*/
|
||||
protected $objectManager;
|
||||
|
||||
/**
|
||||
* @var \Magento\Framework\MessageQueue\LockInterface
|
||||
*/
|
||||
protected $lock;
|
||||
|
||||
/**
|
||||
* @var \Magento\Framework\MessageQueue\Lock\WriterInterface
|
||||
*/
|
||||
protected $writer;
|
||||
|
||||
/**
|
||||
* @var \Magento\Framework\MessageQueue\Lock\ReaderInterface
|
||||
*/
|
||||
protected $reader;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
|
||||
|
||||
$this->lock = $this->objectManager->get(\Magento\Framework\MessageQueue\LockInterface::class);
|
||||
$this->writer = $this->objectManager->get(\Magento\Framework\MessageQueue\Lock\WriterInterface::class);
|
||||
$this->reader = $this->objectManager->get(\Magento\Framework\MessageQueue\Lock\ReaderInterface::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to ensure Queue Lock Table is cleared when maintenance mode transitions from on to off.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testLockClearedByMaintenanceModeOff()
|
||||
{
|
||||
/** @var $maintenanceMode \Magento\Framework\App\MaintenanceMode */
|
||||
$maintenanceMode = $this->objectManager->get(\Magento\Framework\App\MaintenanceMode::class);
|
||||
// md5() here is not for cryptographic use.
|
||||
// phpcs:ignore Magento2.Security.InsecureFunction
|
||||
$code = md5('consumer.name-1');
|
||||
$this->lock->setMessageCode($code);
|
||||
$this->writer->saveLock($this->lock);
|
||||
$this->reader->read($this->lock, $code);
|
||||
$id = $this->lock->getId();
|
||||
$maintenanceMode->set(true);
|
||||
$maintenanceMode->set(false);
|
||||
$this->reader->read($this->lock, $code);
|
||||
$emptyId = $this->lock->getId();
|
||||
|
||||
$this->assertGreaterThanOrEqual('1', $id);
|
||||
$this->assertEmpty($emptyId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright © Magento, Inc. All rights reserved.
|
||||
* See COPYING.txt for license details.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Magento\MessageQueue\Model\ResourceModel;
|
||||
|
||||
use Magento\Framework\MessageQueue\LockInterface;
|
||||
use Magento\TestFramework\ObjectManager;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Covers Lock resource model test cases
|
||||
*/
|
||||
class LockTest extends TestCase
|
||||
{
|
||||
public function testSaveLock()
|
||||
{
|
||||
$objectManager = ObjectManager::getInstance();
|
||||
/** @var Lock $resourceModel */
|
||||
$resourceModel = $objectManager->get(Lock::class);
|
||||
$lock = $objectManager->create(LockInterface::class);
|
||||
$resourceModel->saveLock($lock);
|
||||
self::assertNotEquals(null, $lock->getId());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user