Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX for issue #21916 - Elasticsearch6 generation does not exist #22046

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions lib/internal/Magento/Framework/Code/Generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Magento\Framework\Code\Generator\DefinedClasses;
use Magento\Framework\Code\Generator\EntityAbstract;
use Magento\Framework\Code\Generator\Io;
use Magento\Framework\ObjectManager\ConfigInterface;
use Magento\Framework\ObjectManagerInterface;
use Magento\Framework\Phrase;
use Magento\Framework\Filesystem\Driver\File;
Expand Down Expand Up @@ -232,7 +233,21 @@ protected function shouldSkipGeneration($resultEntityType, $sourceClassName, $re
{
if (!$resultEntityType || !$sourceClassName) {
return self::GENERATION_ERROR;
} elseif ($this->definedClasses->isClassLoadableFromDisk($resultClass)) {
}

/** @var ConfigInterface $omConfig */
$omConfig = $this->objectManager->get(ConfigInterface::class);
$virtualTypes = $omConfig->getVirtualTypes();

/**
* Do not try to autogenerate virtual types
* For example virtual types with names overlapping autogenerated suffixes
*/
if (isset($virtualTypes[$resultClass])) {
return self::GENERATION_SKIP;
}

if ($this->definedClasses->isClassLoadableFromDisk($resultClass)) {
$generatedFileName = $this->_ioObject->generateResultFileName($resultClass);
/**
* Must handle two edge cases: a competing process has generated the class and written it to disc already,
Expand All @@ -244,9 +259,12 @@ protected function shouldSkipGeneration($resultEntityType, $sourceClassName, $re
$this->_ioObject->includeFile($generatedFileName);
}
return self::GENERATION_SKIP;
} elseif (!isset($this->_generatedEntities[$resultEntityType])) {
}

if (!isset($this->_generatedEntities[$resultEntityType])) {
throw new \InvalidArgumentException('Unknown generation entity.');
}

return false;
}
}
169 changes: 140 additions & 29 deletions lib/internal/Magento/Framework/Code/Test/Unit/GeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\Framework\Code\Test\Unit;

use Magento\Framework\Code\Generator;
use Magento\Framework\Code\Generator\DefinedClasses;
use Magento\Framework\Code\Generator\Io;
use Magento\Framework\ObjectManager\ConfigInterface;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Magento\Framework\ObjectManager\Code\Generator\Factory;
use Magento\Framework\ObjectManager\Code\Generator\Proxy;
Expand All @@ -17,13 +21,14 @@
use Magento\Framework\ObjectManagerInterface;
use Magento\Framework\Code\Generator\EntityAbstract;
use Magento\GeneratedClass\Factory as GeneratedClassFactory;
use RuntimeException;

class GeneratorTest extends TestCase
{
/**
* Class name parameter value
*/
const SOURCE_CLASS = 'testClassName';
private const SOURCE_CLASS = 'testClassName';

/**
* Expected generated entities
Expand Down Expand Up @@ -58,13 +63,32 @@ class GeneratorTest extends TestCase
*/
private $loggerMock;

/**
* @var ObjectManagerInterface|MockObject
*/
private $objectManagerMock;

/**
* @var ConfigInterface|MockObject
*/
private $objectManagerConfigMock;

/**
* @inheritDoc
*/
protected function setUp()
{
$this->definedClassesMock = $this->createMock(DefinedClasses::class);
$this->ioObjectMock = $this->getMockBuilder(Io::class)
->disableOriginalConstructor()
->getMock();
$this->loggerMock = $this->getMockForAbstractClass(LoggerInterface::class);
$this->objectManagerMock = $this->getMockBuilder(ObjectManagerInterface::class)
->disableOriginalConstructor()
->getMock();
$this->objectManagerConfigMock = $this->getMockBuilder(ConfigInterface::class)
->disableOriginalConstructor()
->getMock();

$this->model = new Generator(
$this->ioObjectMock,
Expand All @@ -78,7 +102,7 @@ protected function setUp()
);
}

public function testGetGeneratedEntities()
public function testGetGeneratedEntities(): void
{
$this->model = new Generator(
$this->ioObjectMock,
Expand All @@ -91,22 +115,58 @@ public function testGetGeneratedEntities()
/**
* @param string $className
* @param string $entityType
* @expectedException \RuntimeException
* @expectedException RuntimeException
* @dataProvider generateValidClassDataProvider
*/
public function testGenerateClass($className, $entityType)
public function testGenerateClass($className, $entityType): void
{
$objectManagerMock = $this->createMock(ObjectManagerInterface::class);
$fullClassName = $className . $entityType;

$entityGeneratorMock = $this->getMockBuilder(EntityAbstract::class)
->disableOriginalConstructor()
->getMock();
$objectManagerMock->expects($this->once())->method('create')->willReturn($entityGeneratorMock);
$this->model->setObjectManager($objectManagerMock);
$this->model->generateClass($fullClassName);
$this->objectManagerMock
->expects($this->once())
->method('create')
->willReturn($entityGeneratorMock);

$this->objectManagerConfigMock
->expects($this->once())
->method('getVirtualTypes')
->willReturn([]);
$this->objectManagerMock
->expects($this->once())
->method('get')
->with(ConfigInterface::class)
->willReturn($this->objectManagerConfigMock);
$this->model->setObjectManager($this->objectManagerMock);

$this->assertSame(
Generator::GENERATION_SUCCESS,
$this->model->generateClass(GeneratedClassFactory::class)
);
}

public function testGenerateClassWithWrongName()
public function testShouldNotGenerateVirtualType(): void
{
$this->objectManagerConfigMock
->expects($this->once())
->method('getVirtualTypes')
->willReturn([GeneratedClassFactory::class => GeneratedClassFactory::class]);
$this->objectManagerMock
->expects($this->once())
->method('get')
->with(ConfigInterface::class)
->willReturn($this->objectManagerConfigMock);
$this->model->setObjectManager($this->objectManagerMock);

$this->assertSame(
Generator::GENERATION_SKIP,
$this->model->generateClass(GeneratedClassFactory::class)
);
}

public function testGenerateClassWithWrongName(): void
{
$this->assertEquals(
Generator::GENERATION_ERROR,
Expand All @@ -115,25 +175,42 @@ public function testGenerateClassWithWrongName()
}

/**
* @expectedException \RuntimeException
* @expectedException RuntimeException
*/
public function testGenerateClassWhenClassIsNotGenerationSuccess()
public function testGenerateClassWhenClassIsNotGenerationSuccess(): void
{
$expectedEntities = array_values($this->expectedEntities);
$resultClassName = self::SOURCE_CLASS . ucfirst(array_shift($expectedEntities));
$objectManagerMock = $this->createMock(ObjectManagerInterface::class);

$entityGeneratorMock = $this->getMockBuilder(EntityAbstract::class)
->disableOriginalConstructor()
->getMock();
$objectManagerMock->expects($this->once())->method('create')->willReturn($entityGeneratorMock);
$this->model->setObjectManager($objectManagerMock);
$this->model->generateClass($resultClassName);
$this->objectManagerMock
->expects($this->once())
->method('create')
->willReturn($entityGeneratorMock);

$this->objectManagerConfigMock
->expects($this->once())
->method('getVirtualTypes')
->willReturn([]);
$this->objectManagerMock
->expects($this->once())
->method('get')
->with(ConfigInterface::class)
->willReturn($this->objectManagerConfigMock);
$this->model->setObjectManager($this->objectManagerMock);

$this->assertSame(
Generator::GENERATION_SUCCESS,
$this->model->generateClass($resultClassName)
);
}

/**
* @inheritdoc
*/
public function testGenerateClassWithErrors()
public function testGenerateClassWithErrors(): void
{
$expectedEntities = array_values($this->expectedEntities);
$resultClassName = self::SOURCE_CLASS . ucfirst(array_shift($expectedEntities));
Expand All @@ -148,17 +225,15 @@ public function testGenerateClassWithErrors()
. 'directory permission is set to write --- the requested class did not generate properly, then '
. 'you must add the generated class object to the signature of the related construct method, only.';
$FinalErrorMessage = implode(PHP_EOL, $errorMessages) . "\n" . $mainErrorMessage;
$this->expectException(\RuntimeException::class);
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage($FinalErrorMessage);

/** @var ObjectManagerInterface|Mock $objectManagerMock */
$objectManagerMock = $this->createMock(ObjectManagerInterface::class);
/** @var EntityAbstract|Mock $entityGeneratorMock */
$entityGeneratorMock = $this->getMockBuilder(EntityAbstract::class)
->disableOriginalConstructor()
->getMock();

$objectManagerMock->expects($this->once())
$this->objectManagerMock->expects($this->once())
->method('create')
->willReturn($entityGeneratorMock);
$entityGeneratorMock->expects($this->once())
Expand All @@ -177,26 +252,62 @@ public function testGenerateClassWithErrors()
$this->loggerMock->expects($this->once())
->method('critical')
->with($FinalErrorMessage);
$this->model->setObjectManager($objectManagerMock);
$this->model->generateClass($resultClassName);

$this->objectManagerConfigMock
->expects($this->once())
->method('getVirtualTypes')
->willReturn([]);
$this->objectManagerMock
->expects($this->once())
->method('get')
->with(ConfigInterface::class)
->willReturn($this->objectManagerConfigMock);
$this->model->setObjectManager($this->objectManagerMock);

$this->assertSame(
Generator::GENERATION_SUCCESS,
$this->model->generateClass($resultClassName)
);
}

/**
* @dataProvider trueFalseDataProvider
* @param $fileExists
*/
public function testGenerateClassWithExistName($fileExists)
public function testGenerateClassWithExistName($fileExists): void
{
$this->definedClassesMock->expects($this->any())
->method('isClassLoadableFromDisk')
->willReturn(true);

$resultClassFileName = '/Magento/Path/To/Class.php';
$this->ioObjectMock->expects($this->once())->method('generateResultFileName')->willReturn($resultClassFileName);
$this->ioObjectMock->expects($this->once())->method('fileExists')->willReturn($fileExists);

$this->objectManagerConfigMock
->expects($this->once())
->method('getVirtualTypes')
->willReturn([]);
$this->objectManagerMock
->expects($this->once())
->method('get')
->with(ConfigInterface::class)
->willReturn($this->objectManagerConfigMock);
$this->model->setObjectManager($this->objectManagerMock);

$this->ioObjectMock
->expects($this->once())
->method('generateResultFileName')
->willReturn($resultClassFileName);
$this->ioObjectMock
->expects($this->once())
->method('fileExists')
->willReturn($fileExists);

$includeFileInvokeCount = $fileExists ? 1 : 0;
$this->ioObjectMock->expects($this->exactly($includeFileInvokeCount))->method('includeFile');
$this->ioObjectMock
->expects($this->exactly($includeFileInvokeCount))
->method('includeFile');

$this->assertEquals(
$this->assertSame(
Generator::GENERATION_SKIP,
$this->model->generateClass(GeneratedClassFactory::class)
);
Expand All @@ -205,7 +316,7 @@ public function testGenerateClassWithExistName($fileExists)
/**
* @return array
*/
public function trueFalseDataProvider()
public function trueFalseDataProvider(): array
{
return [[true], [false]];
}
Expand All @@ -215,7 +326,7 @@ public function trueFalseDataProvider()
*
* @return array
*/
public function generateValidClassDataProvider()
public function generateValidClassDataProvider(): array
{
$data = [];
foreach ($this->expectedEntities as $generatedEntity) {
Expand Down