Skip to content

Commit 04d76cb

Browse files
author
Yu Tang
committed
Merge remote-tracking branch 'mainline/develop' into FearlessKiwis-MAGETWO-35278-Random-Integration-Test-Failure
2 parents ed1f1b5 + 9050a27 commit 04d76cb

File tree

6 files changed

+159
-298
lines changed

6 files changed

+159
-298
lines changed

lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/EntityChildTestAbstract.php

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -84,41 +84,34 @@ public function testGenerate()
8484
//Mocking _validateData call
8585
$this->mockDefinedClassesCall();
8686

87-
$this->ioObjectMock->expects($this->once())
88-
->method('makeGenerationDirectory')
89-
->will($this->returnValue(true));
9087
$this->ioObjectMock->expects($this->once())
9188
->method('makeResultFileDirectory')
9289
->with($this->getResultClassName())
93-
->will($this->returnValue(true));
94-
$this->ioObjectMock->expects($this->once())
95-
->method('fileExists')
96-
->with($resultFileName)
97-
->will($this->returnValue(false));
90+
->willReturn(true);
9891

9992
//Mocking _generateCode call
10093
$this->classGenerator->expects($this->once())
10194
->method('setName')
10295
->with($this->getResultClassName())
103-
->will($this->returnSelf());
96+
->willReturnSelf();
10497
$this->classGenerator->expects($this->once())
10598
->method('addProperties')
106-
->will($this->returnSelf());
99+
->willReturnSelf();
107100
$this->classGenerator->expects($this->once())
108101
->method('addMethods')
109-
->will($this->returnSelf());
102+
->willReturnSelf();
110103
$this->classGenerator->expects($this->once())
111104
->method('setClassDocBlock')
112-
->will($this->returnSelf());
105+
->willReturnSelf();
113106
$this->classGenerator->expects($this->once())
114107
->method('generate')
115-
->will($this->returnValue($generatedCode));
108+
->willReturn($generatedCode);
116109

117110
//Mocking generation
118111
$this->ioObjectMock->expects($this->any())
119112
->method('getResultFileName')
120113
->with($this->getResultClassName())
121-
->will($this->returnValue($resultFileName));
114+
->willReturn($resultFileName);
122115
$this->ioObjectMock->expects($this->once())
123116
->method('writeResultFile')
124117
->with($resultFileName, $generatedCode);

lib/internal/Magento/Framework/Code/Generator/EntityAbstract.php

Lines changed: 11 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -247,52 +247,23 @@ protected function _validateData()
247247
{
248248
$sourceClassName = $this->getSourceClassName();
249249
$resultClassName = $this->_getResultClassName();
250-
$resultFileName = $this->_ioObject->getResultFileName($resultClassName);
251-
252-
// @todo the controller handling logic below must be removed when controllers become PSR-0 compliant
253-
$controllerSuffix = 'Controller';
254-
$pathParts = explode('_', $sourceClassName);
255-
if (strrpos(
256-
$sourceClassName,
257-
$controllerSuffix
258-
) === strlen(
259-
$sourceClassName
260-
) - strlen(
261-
$controllerSuffix
262-
) && isset(
263-
$pathParts[2]
264-
) && !in_array(
265-
$pathParts[2],
266-
['Block', 'Helper', 'Model']
267-
)
268-
) {
269-
$controllerPath = preg_replace(
270-
'/^([0-9A-Za-z]*)_([0-9A-Za-z]*)/',
271-
'\\1_\\2_controllers',
272-
$sourceClassName
273-
);
274-
$filePath = stream_resolve_include_path(str_replace('_', '/', $controllerPath) . '.php');
275-
$isSourceClassValid = !empty($filePath);
276-
} else {
277-
$isSourceClassValid = $this->definedClasses->classLoadable($sourceClassName);
278-
}
250+
$resultDir = $this->_ioObject->getResultFileDirectory($resultClassName);
279251

280-
if (!$isSourceClassValid) {
252+
if (!$this->definedClasses->classLoadable($sourceClassName)) {
281253
$this->_addError('Source class ' . $sourceClassName . ' doesn\'t exist.');
282254
return false;
283255
} elseif ($this->definedClasses->classLoadable($resultClassName)) {
284256
$this->_addError('Result class ' . $resultClassName . ' already exists.');
285257
return false;
286-
} elseif (!$this->_ioObject->makeGenerationDirectory()) {
287-
$this->_addError('Can\'t create directory ' . $this->_ioObject->getGenerationDirectory() . '.');
288-
return false;
289-
} elseif (!$this->_ioObject->makeResultFileDirectory($resultClassName)) {
290-
$this->_addError(
291-
'Can\'t create directory ' . $this->_ioObject->getResultFileDirectory($resultClassName) . '.'
292-
);
293-
return false;
294-
} elseif ($this->_ioObject->fileExists($resultFileName)) {
295-
$this->_addError('Result file ' . $resultFileName . ' already exists.');
258+
} elseif (
259+
/**
260+
* If makeResultFileDirectory only fails because the file is already created,
261+
* a competing process has generated the file, no exception should be thrown.
262+
*/
263+
!$this->_ioObject->makeResultFileDirectory($resultClassName)
264+
&& !$this->_ioObject->fileExists($resultDir)
265+
) {
266+
$this->_addError('Can\'t create directory ' . $resultDir . '.');
296267
return false;
297268
}
298269
return true;

lib/internal/Magento/Framework/Code/Generator/Io.php

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
*/
66
namespace Magento\Framework\Code\Generator;
77

8+
use Magento\Framework\Filesystem\FilesystemException;
9+
810
class Io
911
{
1012
/**
@@ -82,12 +84,36 @@ public function getResultFileName($className)
8284
/**
8385
* @param string $fileName
8486
* @param string $content
87+
* @throws FilesystemException
8588
* @return bool
8689
*/
8790
public function writeResultFile($fileName, $content)
8891
{
92+
/**
93+
* Rename is atomic on *nix systems, while file_put_contents is not. Writing to a
94+
* temporary file whose name is process-unique and renaming to the real location helps
95+
* avoid race conditions. Race condition can occur if the compiler has not been run, when
96+
* multiple processes are attempting to access the generated file simultaneously.
97+
*/
8998
$content = "<?php\n" . $content;
90-
return $this->filesystemDriver->filePutContents($fileName, $content);
99+
$tmpFile = $fileName . "." . getmypid();
100+
$this->filesystemDriver->filePutContents($tmpFile, $content);
101+
102+
try {
103+
$success = $this->filesystemDriver->rename($tmpFile, $fileName);
104+
} catch (FilesystemException $e) {
105+
if (!file_exists($fileName)) {
106+
throw $e;
107+
} else {
108+
/**
109+
* Due to race conditions, file may have already been written, causing rename to fail. As long as
110+
* the file exists, everything is okay.
111+
*/
112+
$success = true;
113+
}
114+
}
115+
116+
return $success;
91117
}
92118

93119
/**
@@ -138,7 +164,7 @@ private function _makeDirectory($directory)
138164
$this->filesystemDriver->createDirectory($directory, self::DIRECTORY_PERMISSION);
139165
}
140166
return true;
141-
} catch (\Magento\Framework\Filesystem\FilesystemException $e) {
167+
} catch (FilesystemException $e) {
142168
return false;
143169
}
144170
}

0 commit comments

Comments
 (0)