Temp files should be deleted when an exception is thrown (#327)

If an exception is thrown while writing data, instead of letting the developer handle this situation gracefully, Spout can attempt to delete all the temporary files that were created so far, as well as the output file as it won't be completed and therefore corrupted.
This commit is contained in:
Adrien Loison authored and GitHub committed 2016-10-11 15:08:37 -07:00
1 parent 442a9837f1
commit 23f8cc4f05
5 files changed
+157 -1

No files matched your search

+45
View File
@@ -18,6 +18,9 @@ trait TestUsingResource
/** @var string Path to the test resources folder, that does not have writing permissions */
private $generatedUnwritableResourcesPath = 'tests/resources/generated/unwritable';
/** @var string Path to the test temp folder */
private $tempFolderPath = 'tests/resources/generated/temp';
/**
* @param string $resourceName
* @return string|null Path of the resource who matches the given name or null if resource not found
@@ -86,6 +89,48 @@ trait TestUsingResource
}
}
/**
* @return string Path of the temp folder
*/
protected function getTempFolderPath()
{
return realpath($this->tempFolderPath);
}
/**
* @return void
*/
protected function recreateTempFolder()
{
if (file_exists($this->tempFolderPath)) {
$this->deleteFolderRecursively($this->tempFolderPath);
}
mkdir($this->tempFolderPath, 0777, true);
}
/**
* @param string $folderPath
* @return void
*/
private function deleteFolderRecursively($folderPath)
{
$itemIterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($folderPath, \RecursiveDirectoryIterator::SKIP_DOTS),
\RecursiveIteratorIterator::CHILD_FIRST
);
foreach ($itemIterator as $item) {
if ($item->isDir()) {
rmdir($item->getPathname());
} else {
unlink($item->getPathname());
}
}
rmdir($folderPath);
}
/**
* @return bool Whether the OS on which PHP is installed is Windows
*/
+34
View File
@@ -2,6 +2,7 @@
namespace Box\Spout\Writer\ODS;
use Box\Spout\Common\Exception\SpoutException;
use Box\Spout\Common\Type;
use Box\Spout\Reader\Wrapper\XMLReader;
use Box\Spout\TestUsingResource;
@@ -91,6 +92,39 @@ class WriterTest extends \PHPUnit_Framework_TestCase
$this->writeToODSFile($dataRows, $fileName);
}
/**
* @return void
*/
public function testAddRowShouldCleanupAllFilesIfExceptionIsThrown()
{
$fileName = 'test_add_row_should_cleanup_all_files_if_exception_thrown.ods';
$dataRows = [
['wrong'],
[new \stdClass()],
];
$this->createGeneratedFolderIfNeeded($fileName);
$resourcePath = $this->getGeneratedResourcePath($fileName);
$this->recreateTempFolder();
$tempFolderPath = $this->getTempFolderPath();
/** @var \Box\Spout\Writer\ODS\Writer $writer */
$writer = WriterFactory::create(Type::ODS);
$writer->setTempFolder($tempFolderPath);
$writer->openToFile($resourcePath);
try {
$writer->addRows($dataRows);
$this->fail('Exception should have been thrown');
} catch (SpoutException $e) {
$this->assertFalse(file_exists($fileName), 'Output file should have been deleted');
$numFiles = iterator_count(new \FilesystemIterator($tempFolderPath, \FilesystemIterator::SKIP_DOTS));
$this->assertEquals(0, $numFiles, 'All temp files should have been deleted');
}
}
/**
* @return void
*/
+34
View File
@@ -2,6 +2,7 @@
namespace Box\Spout\Writer\XLSX;
use Box\Spout\Common\Exception\SpoutException;
use Box\Spout\Common\Type;
use Box\Spout\TestUsingResource;
use Box\Spout\Writer\WriterFactory;
@@ -104,6 +105,39 @@ class WriterTest extends \PHPUnit_Framework_TestCase
$this->writeToXLSXFile($dataRows, $fileName);
}
/**
* @return void
*/
public function testAddRowShouldCleanupAllFilesIfExceptionIsThrown2()
{
$fileName = 'test_add_row_should_cleanup_all_files_if_exception_thrown.xlsx';
$dataRows = [
['wrong'],
[new \stdClass()],
];
$this->createGeneratedFolderIfNeeded($fileName);
$resourcePath = $this->getGeneratedResourcePath($fileName);
$this->recreateTempFolder();
$tempFolderPath = $this->getTempFolderPath();
/** @var \Box\Spout\Writer\XLSX\Writer $writer */
$writer = WriterFactory::create(Type::XLSX);
$writer->setTempFolder($tempFolderPath);
$writer->openToFile($resourcePath);
try {
$writer->addRows($dataRows);
$this->fail('Exception should have been thrown');
} catch (SpoutException $e) {
$this->assertFalse(file_exists($fileName), 'Output file should have been deleted');
$numFiles = iterator_count(new \FilesystemIterator($tempFolderPath, \FilesystemIterator::SKIP_DOTS));
$this->assertEquals(0, $numFiles, 'All temp files should have been deleted');
}
}
/**
* @return void
*/