diff -u b/core/modules/migrate/src/MemoryManagerInterface.php b/core/modules/migrate/src/MemoryManagerInterface.php --- b/core/modules/migrate/src/MemoryManagerInterface.php +++ b/core/modules/migrate/src/MemoryManagerInterface.php @@ -31,8 +31,8 @@ * whether enough memory was reclaimed. * * @return bool - * TRUE if memory usage is low enough, or if enough memory can be reclaimed. - * FALSE if memory usage is too high and not enough can be reclaimed. + * TRUE if memory usage is low enough, or if enough memory can be reclaimed. + * FALSE if memory usage is too high and not enough can be reclaimed. */ public function ensureMemory(); diff -u b/core/modules/migrate/tests/src/Unit/MigrateExecutableMemoryExceededTest.php /dev/null --- b/core/modules/migrate/tests/src/Unit/MigrateExecutableMemoryExceededTest.php +++ /dev/null @@ -1,144 +0,0 @@ - 'test', - ]; - - /** - * The php.ini memory_limit value. - * - * @var int - */ - protected $memoryLimit = 10000000; - - /** - * {@inheritdoc} - */ - protected function setUp(): void { - parent::setUp(); - $this->migration = $this->getMigration(); - $this->message = $this->createMock('Drupal\migrate\MigrateMessageInterface'); - $this->eventDispatcher = $this->createMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); - } - - /** - * Test the memory manager. - * - * @param string $message - * The second message to assert. - * @param bool $memory_exceeded - * Whether to test the memory exceeded case. - * @param float $reclaim_threshold - * The ratio of the memory limit which will trigger a failed reclaim. - * @param float $memory_threshold - * The ratio of the memory limit at which an operation will be interrupted. - * @param int|null $memory_usage_first - * (optional) The first memory usage value. Defaults to NULL. - * @param int|null $memory_usage_second - * (optional) The fake amount of memory usage reported after memory reclaim. - * Defaults to NULL. - * @param int|null $memory_limit - * (optional) The memory limit. Defaults to NULL. - * - * @dataProvider memoryExceededProvider - * - * @throws \Drupal\migrate\MigrateException - */ - public function testMemoryExceeded($message, $memory_exceeded, $reclaim_threshold, $memory_threshold, $memory_usage_first, $memory_usage_second, $memory_limit ) { - $this->executable = new TestMigrateExecutable($this->migration, $this->message, $this->eventDispatcher, NULL); - - // Get the memory and set parameters. - $memory_manager = $this->executable->getMemoryManager(); - $memory_manager->setMemoryReclaimThreshold($reclaim_threshold); - $memory_manager->setMemoryThreshold($memory_threshold); - $memory_manager->setMemoryUsage($memory_usage_first ?: $this->memoryLimit, $memory_usage_second ?: $this->memoryLimit); - $memory_manager->setMemoryLimit($memory_limit); - - if ($memory_usage_second) { - $memory_manager->reclaim(); - } - $result = $memory_manager->isLimitExceeded(1); - $this->assertEquals($memory_exceeded, $result); - } - - /** - * Memory manager test data provider. - */ - public function memoryExceededProvider() { - return [ - // Tests memoryExceeded method when a new batch is needed. - 'MemoryExceededNewBatch' => [ - 'message' => 'starting new batch', - 'memory_limit' => $this->memoryLimit, - 'reclaim_threshold' => 0.9, - 'memory_threshold' => 0.85, - 'memory_usage_first' => NULL, - 'memory_usage_second' => NULL, - 'memory_exceeded' => TRUE, - ], - // Tests memoryExceeded method when enough is cleared. - 'testMemoryExceededClearedEnough' => [ - 'message' => 'reclaimed enough', - 'memory_limit' => $this->memoryLimit, - 'reclaim_threshold' => 0.9, - 'memory_threshold' => 0.85, - 'memory_usage_first' => $this->memoryLimit, - 'memory_usage_second' => $this->memoryLimit * 0.75, - 'memory_exceeded' => FALSE, - ], - // Tests memoryExceeded when memory usage is not exceeded. - 'testMemoryNotExceeded' => [ - 'message' => 'starting new batch', - 'memory_limit' => $this->memoryLimit, - 'reclaim_threshold' => 0.9, - 'memory_threshold' => 0.85, - 'memory_usage_first' => floor($this->memoryLimit * 0.85) - 1, - 'memory_usage_second' => NULL, - 'memory_exceeded' => FALSE, - ], - ]; - } - -} diff -u b/core/modules/migrate/tests/src/Unit/MigrateExecutableTest.php b/core/modules/migrate/tests/src/Unit/MigrateExecutableTest.php --- b/core/modules/migrate/tests/src/Unit/MigrateExecutableTest.php +++ b/core/modules/migrate/tests/src/Unit/MigrateExecutableTest.php @@ -495,4 +495,17 @@ /** + * Tests the checkStatus method. + */ + public function testCheckStatus() { + $this->memoryManager->expects($this->any()) + ->method('ensureMemory') + ->will($this->onConsecutiveCalls(TRUE, FALSE)); + $result = $this->executable->checkStatus(); + $this->assertEquals($result, MigrationInterface::RESULT_COMPLETED); + $result = $this->executable->checkStatus(); + $this->assertEquals($result, MigrationInterface::RESULT_INCOMPLETE); + } + + /** * Returns a mock migration source instance. * diff -u b/core/modules/migrate/tests/src/Unit/TestMigrateExecutable.php b/core/modules/migrate/tests/src/Unit/TestMigrateExecutable.php --- b/core/modules/migrate/tests/src/Unit/TestMigrateExecutable.php +++ b/core/modules/migrate/tests/src/Unit/TestMigrateExecutable.php @@ -2,12 +2,8 @@ namespace Drupal\Tests\migrate\Unit; -use Drupal\migrate\MemoryManager; -use Drupal\migrate\MemoryManagerInterface; +use Drupal\Core\StringTranslation\TranslationInterface; use Drupal\migrate\MigrateExecutable; -use Drupal\migrate\MigrateMessageInterface; -use Drupal\migrate\Plugin\MigrationInterface; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * Tests MigrateExecutable. @@ -15,25 +11,13 @@ class TestMigrateExecutable extends MigrateExecutable { /** - * Constructs a TestMigrateExecutable and verifies and sets the memory limit. + * Sets the string translation service. * - * @param \Drupal\migrate\Plugin\MigrationInterface $migration - * The migration to run. - * @param \Drupal\migrate\MigrateMessageInterface $message - * (optional) The migrate message service. - * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher - * (optional) The event dispatcher. - * @param \Drupal\Migrate\MemoryManagerInterface $memory_manager - * (optional) The memory manager. - * - * @throws \Drupal\migrate\MigrateException + * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation + * The translation manager. */ - public function __construct(MigrationInterface $migration, MigrateMessageInterface $message = NULL, EventDispatcherInterface $event_dispatcher = NULL, MemoryManagerInterface $memory_manager = NULL) { - parent::__construct($migration, $message, $event_dispatcher); - $this->memoryManager = $memory_manager; - if (!$memory_manager) { - $this->memoryManager = new TestMemoryManager($this->eventDispatcher, NULL, NULL, NULL); - } + public function setStringTranslation(TranslationInterface $string_translation) { + $this->stringTranslation = $string_translation; } /** @@ -70,97 +54,21 @@ /** - * Allows access to the protected memory manager. - * - * @return \Drupal\Tests\migrate\Unit\TestMemoryManager - * The test memory manager. - */ - public function getMemoryManager() { - return $this->memoryManager; - } - -} - -/** - * Class TestMemoryManager. - */ -class TestMemoryManager extends MemoryManager { - - /** - * The fake memory usage in bytes. - * - * @var int - */ - protected $memoryUsage; - - /** - * The cleared memory usage. - * - * @var int - */ - protected $clearedMemoryUsage; - - /** * {@inheritdoc} */ - public function getUsageInBytes() { - return $this->memoryUsage; + protected function formatSize($size) { + return $size; } /** * {@inheritdoc} */ - public function isLimitExceeded($multiplier = 1.0) { - return parent::isLimitExceeded($multiplier); - } - - /** - * Reclaim memory. - */ - public function reclaim() { - $this->memoryUsage = $this->clearedMemoryUsage; - return $this; - } - - /** - * Sets the memory limit. - * - * @param int $memory_limit - * The memory limit. - */ - public function setMemoryLimit($memory_limit) { - $this->memoryLimit = $memory_limit; - } - - /** - * Sets the memory threshold. - * - * @param float $threshold - * The new threshold. - */ - public function setMemoryReclaimThreshold($threshold) { - $this->memoryReclaimThreshold = $threshold; - } - - /** - * Sets the memory threshold. - * - * @param float $threshold - * The new threshold. - */ - public function setMemoryThreshold($threshold) { - $this->memoryThreshold = $threshold; + public function getMemoryManager() { + return parent::getMemoryManager(); } /** - * Sets the fake memory usage. - * - * @param int $memory_usage - * The fake memory usage value. - * @param int $cleared_memory_usage - * (optional) The fake cleared memory value. Defaults to NULL. + * {@inheritdoc} */ - public function setMemoryUsage($memory_usage, $cleared_memory_usage = NULL) { - $this->memoryUsage = $memory_usage; - $this->clearedMemoryUsage = $cleared_memory_usage; + public function checkStatus() { + return parent::checkStatus(); } - } only in patch2: unchanged: --- /dev/null +++ b/core/modules/migrate/tests/src/Unit/MemoryManagerTest.php @@ -0,0 +1,300 @@ +message = $this->createMock('Drupal\migrate\MigrateMessageInterface'); + $this->eventDispatcher = $this->createMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + } + + /** + * Tests ensureMemory. + * + * @param float $reclaim_threshold + * The ratio of the memory limit which will trigger a failed reclaim. + * @param float $memory_threshold + * The ratio of the memory limit at which an operation will be interrupted. + * @param int|null $memory_limit + * The memory limit. Defaults to NULL. + * @param int|null $memory_usage + * The first memory usage value. Defaults to NULL. + * @param int|null $cleared_memory_usage + * The fake amount of memory usage reported after memory reclaim. + * Defaults to NULL. + * @param bool $expected_ensure_memory + * Indicated that the desired memory threshold was exceeded. + * + * @dataProvider providerTestEnsureMemory + */ + public function testEnsureMemory($reclaim_threshold, $memory_threshold, $memory_limit, $memory_usage, $cleared_memory_usage, $expected_ensure_memory) { + $memory_manager = new TestMemoryManager($this->eventDispatcher, $reclaim_threshold, $memory_threshold, $memory_limit); + $memory_manager->setMemoryUsage($memory_usage, $cleared_memory_usage); + if ($cleared_memory_usage) { + $memory_manager->reclaim(); + } + $result = $memory_manager->ensureMemory(); + $this->assertEquals($expected_ensure_memory, $result); + } + + /** + * Provides data for testEnsureMemory. + */ + public function providerTestEnsureMemory() { + return [ + // Tests memoryExceeded method when a new batch is needed. + 'MemoryExceededNewBatch' => [ + 'reclaim_threshold' => 0.9, + 'memory_threshold' => 0.85, + 'memory_limit' => 10000000, + 'memory_usage' => NULL, + 'cleared_memory_usage' => NULL, + 'expected_ensure_memory' => TRUE, + ], + // Tests memoryExceeded method when enough is cleared. + 'testMemoryExceededClearedEnough' => [ + 'reclaim_threshold' => 0.9, + 'memory_threshold' => 0.85, + 'memory_limit' => 10000000, + 'memory_usage' => 10000000, + 'cleared_memory_usage' => 10000000 * 0.75, + 'expected_ensure_memory' => TRUE, + ], + // Tests memoryExceeded when memory usage is not exceeded. + 'testMemoryNotExceeded' => [ + 'reclaim_threshold' => 0.9, + 'memory_threshold' => 0.85, + 'memory_limit' => 10000000, + 'memory_usage' => floor(10000000 * 0.85) - 1, + 'cleared_memory_usage' => NULL, + 'expected_ensure_memory' => TRUE, + ], + ]; + } + + /** + * Test getUsageInBytes. + * + * @param int|null $memory_usage + * The memory usage in bytes. Defaults to NULL. + * @param int|null $expected_usage + * The expected memory usage in bytes. + * + * @dataProvider providerTestGetUsageInBytes + */ + public function testGetUsageInBytes($memory_usage, $expected_usage) { + $memory_manager = new TestMemoryManager($this->eventDispatcher, 0.9, 0.85, 1000000); + $memory_manager->setMemoryUsage($memory_usage); + $result = $memory_manager->getUsageInBytes(); + $this->assertEquals($expected_usage, $result); + } + + /** + * Provides data for testGetUsageInBytes. + */ + public function providerTestGetUsageInBytes() { + return [ + 'Null' => [ + 'memory_usage' => NULL, + 'expected_usage' => NULL, + ], + 'Integer' => [ + 'memory_usage' => 12345, + 'expected_usage' => 12345, + ], + ]; + } + + /** + * Tests getUsageRatio. + * + * @param int $memory_limit + * The memory limit. + * @param int|null $memory_usage + * The memory usage in bytes. Defaults to NULL. + * @param int $expected_ratio + * The expected memory usage in bytes. + * + * @dataProvider providerTestGeRatio + */ + public function testGetUsageRatio($memory_limit, $memory_usage, $expected_ratio) { + $memory_manager = new TestMemoryManager($this->eventDispatcher, 0.9, 0.85, $memory_limit); + $memory_manager->setMemoryUsage($memory_usage); + $result = $memory_manager->getUsageRatio(); + $this->assertEquals($expected_ratio, $result); + } + + /** + * Provides data for testGetUsageRatio. + */ + public function providerTestGeRatio() { + return [ + 'Null' => [ + 'memory_limit' => 10000000, + 'memory_usage' => NULL, + 'expected_ratio' => NULL, + ], + 'Current limit' => [ + 'memory_limit' => 10000000, + 'memory_usage' => 10000000, + 'expected_ratio' => 1, + ], + 'ten percent' => [ + 'memory_limit' => 100000, + 'memory_usage' => 10000, + 'expected_ratio' => .1, + ], + 'exceed ten times' => [ + 'memory_limit' => 100000, + 'memory_usage' => 1000000, + 'expected_ratio' => 10, + ], + ]; + } + + /** + * Tests isLimitExceeded. + * + * @param float $reclaim_threshold + * The ratio of the memory limit which will trigger a failed reclaim. + * @param float $memory_threshold + * The ratio of the memory limit at which an operation will be interrupted. + * @param int $memory_limit + * The memory limit. + * @param int|null $memory_usage + * The memory usage in bytes. Defaults to NULL. + * @param float $multiplier + * A percentage of the threshold. + * @param bool $memory_exceeded + * A boolean indicating if memory was exceeded. + * + * @dataProvider providerIsLimitExceeded + */ + public function testIsLimitExceeded($reclaim_threshold, $memory_threshold, $memory_limit, $memory_usage, $multiplier, $memory_exceeded) { + $memory_manager = new TestMemoryManager($this->eventDispatcher, $reclaim_threshold, $memory_threshold, $memory_limit); + $memory_manager->setMemoryUsage($memory_usage); + $result = $memory_manager->isLimitExceeded($multiplier); + $this->assertEquals($memory_exceeded, $result); + } + + /** + * Provides data for testIsLimitExceeded. + */ + public function providerIsLimitExceeded() { + return [ + 'Not exceeded' => [ + 'reclaim_threshold' => 0.9, + 'memory_threshold' => 0.85, + 'memory_limit' => 1000000, + 'memory_usage' => 1000000 * .85, + 'multiplier' => 1.0, + 'memory_exceeded' => FALSE, + ], + 'exceeded' => [ + 'reclaim_threshold' => 0.9, + 'memory_threshold' => 0.85, + 'memory_limit' => 1000000, + 'memory_usage' => 10000001, + 'multiplier' => 1.0, + 'memory_exceeded' => TRUE, + ], + ]; + } + +} + +/** + * Class TestMemoryManager. + */ +class TestMemoryManager extends MemoryManager { + + /** + * The fake memory usage in bytes. + * + * @var int + */ + protected $memoryUsage; + + /** + * The cleared memory usage. + * + * @var int + */ + protected $clearedMemoryUsage; + + /** + * {@inheritdoc} + */ + public function dispatchEvent($phase) { + return parent::dispatchEvent($phase); + } + + /** + * {@inheritdoc} + */ + public function getUsageInBytes() { + return $this->memoryUsage; + } + + /** + * {@inheritdoc} + */ + public function getUsageRatio() { + return parent::getUsageRatio(); + } + + /** + * {@inheritdoc} + */ + public function isLimitExceeded($multiplier = 1.0) { + return parent::isLimitExceeded($multiplier); + } + + /** + * Reclaim memory. + */ + public function reclaim() { + $this->memoryUsage = $this->clearedMemoryUsage; + return $this; + } + + /** + * Sets the fake memory usage. + * + * @param int $memory_usage + * The fake memory usage value. + * @param int $cleared_memory_usage + * (optional) The fake cleared memory value. Defaults to NULL. + */ + public function setMemoryUsage($memory_usage, $cleared_memory_usage = NULL) { + $this->memoryUsage = $memory_usage; + $this->clearedMemoryUsage = $cleared_memory_usage; + } + +}