1<?php 2 3namespace Drupal\Tests\migrate\Unit; 4 5/** 6 * Tests the \Drupal\migrate\MigrateExecutable::memoryExceeded() method. 7 * 8 * @group migrate 9 */ 10class MigrateExecutableMemoryExceededTest extends MigrateTestCase { 11 12 /** 13 * The mocked migration entity. 14 * 15 * @var \Drupal\migrate\Plugin\MigrationInterface|\PHPUnit\Framework\MockObject\MockObject 16 */ 17 protected $migration; 18 19 /** 20 * The mocked migrate message. 21 * 22 * @var \Drupal\migrate\MigrateMessageInterface|\PHPUnit\Framework\MockObject\MockObject 23 */ 24 protected $message; 25 26 /** 27 * The tested migrate executable. 28 * 29 * @var \Drupal\Tests\migrate\Unit\TestMigrateExecutable 30 */ 31 protected $executable; 32 33 /** 34 * The migration configuration, initialized to set the ID to test. 35 * 36 * @var array 37 */ 38 protected $migrationConfiguration = [ 39 'id' => 'test', 40 ]; 41 42 /** 43 * The php.ini memory_limit value. 44 * 45 * @var int 46 */ 47 protected $memoryLimit = 10000000; 48 49 /** 50 * {@inheritdoc} 51 */ 52 protected function setUp(): void { 53 parent::setUp(); 54 $this->migration = $this->getMigration(); 55 $this->message = $this->createMock('Drupal\migrate\MigrateMessageInterface'); 56 57 $this->executable = new TestMigrateExecutable($this->migration, $this->message); 58 $this->executable->setStringTranslation($this->getStringTranslationStub()); 59 } 60 61 /** 62 * Runs the actual test. 63 * 64 * @param string $message 65 * The second message to assert. 66 * @param bool $memory_exceeded 67 * Whether to test the memory exceeded case. 68 * @param int|null $memory_usage_first 69 * (optional) The first memory usage value. Defaults to NULL. 70 * @param int|null $memory_usage_second 71 * (optional) The fake amount of memory usage reported after memory reclaim. 72 * Defaults to NULL. 73 * @param int|null $memory_limit 74 * (optional) The memory limit. Defaults to NULL. 75 */ 76 protected function runMemoryExceededTest($message, $memory_exceeded, $memory_usage_first = NULL, $memory_usage_second = NULL, $memory_limit = NULL) { 77 $this->executable->setMemoryLimit($memory_limit ?: $this->memoryLimit); 78 $this->executable->setMemoryUsage($memory_usage_first ?: $this->memoryLimit, $memory_usage_second ?: $this->memoryLimit); 79 $this->executable->setMemoryThreshold(0.85); 80 if ($message) { 81 $this->executable->message->expects($this->exactly(2)) 82 ->method('display') 83 ->withConsecutive( 84 [ 85 $this->callback(function ($subject) { 86 return mb_stripos((string) $subject, 'reclaiming memory') !== FALSE; 87 }), 88 ], 89 [ 90 $this->callback(function ($subject) use ($message) { 91 return mb_stripos((string) $subject, $message) !== FALSE; 92 }), 93 ], 94 ); 95 } 96 else { 97 $this->executable->message->expects($this->never()) 98 ->method($this->anything()); 99 } 100 $result = $this->executable->memoryExceeded(); 101 $this->assertEquals($memory_exceeded, $result); 102 } 103 104 /** 105 * Tests memoryExceeded method when a new batch is needed. 106 */ 107 public function testMemoryExceededNewBatch() { 108 // First case try reset and then start new batch. 109 $this->runMemoryExceededTest('starting new batch', TRUE); 110 } 111 112 /** 113 * Tests memoryExceeded method when enough is cleared. 114 */ 115 public function testMemoryExceededClearedEnough() { 116 $this->runMemoryExceededTest('reclaimed enough', FALSE, $this->memoryLimit, $this->memoryLimit * 0.75); 117 } 118 119 /** 120 * Tests memoryExceeded when memory usage is not exceeded. 121 */ 122 public function testMemoryNotExceeded() { 123 $this->runMemoryExceededTest('', FALSE, floor($this->memoryLimit * 0.85) - 1); 124 } 125 126} 127