You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
303 lines
10 KiB
303 lines
10 KiB
<?php |
|
|
|
namespace yiiunit\framework\validators; |
|
|
|
|
|
use yii\validators\FileValidator; |
|
use yii\web\UploadedFile; |
|
use Yii; |
|
use yiiunit\data\validators\models\FakedValidationModel; |
|
use yiiunit\TestCase; |
|
|
|
class FileValidatorTest extends TestCase |
|
{ |
|
public function setUp() |
|
{ |
|
$this->mockApplication(); |
|
} |
|
|
|
public function testAssureMessagesSetOnInit() |
|
{ |
|
$val = new FileValidator(); |
|
foreach (['message', 'uploadRequired', 'tooMany', 'wrongType', 'tooBig', 'tooSmall'] as $attr) { |
|
$this->assertTrue(is_string($val->$attr)); |
|
} |
|
} |
|
|
|
public function testTypeSplitOnInit() |
|
{ |
|
$val = new FileValidator(['types' => 'jpeg, jpg, gif']); |
|
$this->assertEquals(['jpeg', 'jpg', 'gif'], $val->types); |
|
$val = new FileValidator(['types' => 'jpeg']); |
|
$this->assertEquals(['jpeg'], $val->types); |
|
$val = new FileValidator(['types' => '']); |
|
$this->assertEquals([], $val->types); |
|
$val = new FileValidator(['types' => []]); |
|
$this->assertEquals([], $val->types); |
|
$val = new FileValidator(); |
|
$this->assertEquals([], $val->types); |
|
$val = new FileValidator(['types' => ['jpeg', 'exe']]); |
|
$this->assertEquals(['jpeg', 'exe'], $val->types); |
|
} |
|
|
|
public function testGetSizeLimit() |
|
{ |
|
$size = $this->sizeToBytes(ini_get('upload_max_filesize')); |
|
$val = new FileValidator(); |
|
$this->assertEquals($size, $val->getSizeLimit()); |
|
$val->maxSize = $size + 1; // set and test if value is overridden |
|
$this->assertEquals($size, $val->getSizeLimit()); |
|
$val->maxSize = abs($size - 1); |
|
$this->assertEquals($size - 1, $val->getSizeLimit()); |
|
$_POST['MAX_FILE_SIZE'] = $size + 1; |
|
$this->assertEquals($size - 1, $val->getSizeLimit()); |
|
$_POST['MAX_FILE_SIZE'] = abs($size - 2); |
|
$this->assertSame($_POST['MAX_FILE_SIZE'], $val->getSizeLimit()); |
|
} |
|
|
|
protected function sizeToBytes($sizeStr) |
|
{ |
|
switch (substr($sizeStr, -1)) { |
|
case 'M': |
|
case 'm': |
|
return (int)$sizeStr * 1048576; |
|
case 'K': |
|
case 'k': |
|
return (int)$sizeStr * 1024; |
|
case 'G': |
|
case 'g': |
|
return (int)$sizeStr * 1073741824; |
|
default: |
|
return (int)$sizeStr; |
|
} |
|
} |
|
|
|
public function testValidateAttributeMultiple() |
|
{ |
|
$val = new FileValidator(['maxFiles' => 2]); |
|
$m = FakedValidationModel::createWithAttributes(['attr_files' => 'path']); |
|
$val->validateAttribute($m, 'attr_files'); |
|
$this->assertTrue($m->hasErrors('attr_files')); |
|
$m = FakedValidationModel::createWithAttributes(['attr_files' => []]); |
|
$val->validateAttribute($m, 'attr_files'); |
|
$this->assertTrue($m->hasErrors('attr_files')); |
|
$this->assertSame($val->uploadRequired, current($m->getErrors('attr_files'))); |
|
$m = FakedValidationModel::createWithAttributes( |
|
[ |
|
'attr_files' => $this->createTestFiles( |
|
[ |
|
[ |
|
'name' => 'test_up_1.txt', |
|
'size' => 1024, |
|
], |
|
[ |
|
'error' => UPLOAD_ERR_NO_FILE, |
|
], |
|
] |
|
) |
|
] |
|
); |
|
$val->validateAttribute($m, 'attr_files'); |
|
$this->assertFalse($m->hasErrors('attr_files')); |
|
$m = FakedValidationModel::createWithAttributes([ |
|
'attr_files' => $this->createTestFiles([ |
|
[''], [''], [''] |
|
]) |
|
]); |
|
$val->validateAttribute($m, 'attr_files'); |
|
$this->assertTrue($m->hasErrors()); |
|
$this->assertTrue(stripos(current($m->getErrors('attr_files')), 'you can upload at most') !== false); |
|
} |
|
|
|
/** |
|
* @param array $params |
|
* @return UploadedFile[] |
|
*/ |
|
protected function createTestFiles($params = []) |
|
{ |
|
$rndString = function ($len = 10) { |
|
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; |
|
$randomString = ''; |
|
for ($i = 0; $i < $len; $i++) { |
|
$randomString .= $characters[rand(0, strlen($characters) - 1)]; |
|
} |
|
return $randomString; |
|
}; |
|
$files = []; |
|
foreach ($params as $param) { |
|
if (empty($param) && count($params) != 1) { |
|
$files[] = ['no instance of UploadedFile']; |
|
continue; |
|
} |
|
$name = isset($param['name']) ? $param['name'] : $rndString(); |
|
$tempName = \Yii::getAlias('@yiiunit/runtime/validators/file/tmp') . $name; |
|
if (is_readable($tempName)) { |
|
$size = filesize($tempName); |
|
} else { |
|
$size = isset($param['size']) ? $param['size'] : rand( |
|
1, |
|
$this->sizeToBytes(ini_get('upload_max_filesize')) |
|
); |
|
} |
|
$type = isset($param['type']) ? $param['type'] : 'text/plain'; |
|
$error = isset($param['error']) ? $param['error'] : UPLOAD_ERR_OK; |
|
if (count($params) == 1) { |
|
$error = empty($param) ? UPLOAD_ERR_NO_FILE : $error; |
|
return new UploadedFile([ |
|
'name' => $name, |
|
'tempName' => $tempName, |
|
'type' => $type, |
|
'size' => $size, |
|
'error' => $error |
|
]); |
|
} |
|
$files[] = new UploadedFile([ |
|
'name' => $name, |
|
'tempName' => $tempName, |
|
'type' => $type, |
|
'size' => $size, |
|
'error' => $error |
|
]); |
|
} |
|
return $files; |
|
} |
|
|
|
public function testValidateAttribute() |
|
{ |
|
// single File |
|
$val = new FileValidator(); |
|
$m = $this->createModelForAttributeTest(); |
|
$val->validateAttribute($m, 'attr_files'); |
|
$this->assertFalse($m->hasErrors()); |
|
$val->validateAttribute($m, 'attr_files_empty'); |
|
$this->assertTrue($m->hasErrors('attr_files_empty')); |
|
$this->assertSame($val->uploadRequired, current($m->getErrors('attr_files_empty'))); |
|
$m = $this->createModelForAttributeTest(); |
|
// too big |
|
$val = new FileValidator(['maxSize' => 128]); |
|
$val->validateAttribute($m, 'attr_files'); |
|
$this->assertTrue($m->hasErrors('attr_files')); |
|
$this->assertTrue( |
|
stripos( |
|
current($m->getErrors('attr_files')), |
|
str_ireplace(['{file}', '{limit}'], [$m->attr_files->name, 128], $val->tooBig) |
|
) !== false |
|
); |
|
// to Small |
|
$m = $this->createModelForAttributeTest(); |
|
$val = new FileValidator(['minSize' => 2048]); |
|
$val->validateAttribute($m, 'attr_files'); |
|
$this->assertTrue($m->hasErrors('attr_files')); |
|
$this->assertTrue( |
|
stripos( |
|
current($m->getErrors('attr_files')), |
|
str_ireplace(['{file}', '{limit}'], [$m->attr_files->name, 2048], $val->tooSmall) |
|
) !== false |
|
); |
|
// UPLOAD_ERR_INI_SIZE/UPLOAD_ERR_FORM_SIZE |
|
$m = $this->createModelForAttributeTest(); |
|
$val = new FileValidator(); |
|
$val->validateAttribute($m, 'attr_err_ini'); |
|
$this->assertTrue($m->hasErrors('attr_err_ini')); |
|
$this->assertTrue( |
|
stripos( |
|
current($m->getErrors('attr_err_ini')), |
|
str_ireplace( |
|
['{file}', '{limit}'], |
|
[$m->attr_err_ini->name, $val->getSizeLimit()], |
|
$val->tooBig |
|
) |
|
) !== false |
|
); |
|
// UPLOAD_ERR_PARTIAL |
|
$m = $this->createModelForAttributeTest(); |
|
$val = new FileValidator(); |
|
$val->validateAttribute($m, 'attr_err_part'); |
|
$this->assertTrue($m->hasErrors('attr_err_part')); |
|
$this->assertSame(Yii::t('yii', 'File upload failed.'), current($m->getErrors('attr_err_part'))); |
|
$log = Yii::$app->getLog()->toArray(); |
|
$this->assertSame(FileValidator::className() . '::validateFile', $log['messages'][0][2]); |
|
} |
|
|
|
public function testValidateAttributeType() |
|
{ |
|
$val = new FileValidator(['types' => 'jpeg, jpg']); |
|
$m = FakedValidationModel::createWithAttributes( |
|
[ |
|
'attr_jpg' => $this->createTestFiles([['name' => 'one.jpeg']]), |
|
'attr_exe' => $this->createTestFiles([['name' => 'bad.exe']]), |
|
] |
|
); |
|
$val->validateAttribute($m, 'attr_jpg'); |
|
$this->assertFalse($m->hasErrors('attr_jpg')); |
|
$val->validateAttribute($m, 'attr_exe'); |
|
$this->assertTrue($m->hasErrors('attr_exe')); |
|
$this->assertTrue(stripos(current($m->getErrors('attr_exe')), 'Only files with these extensions ') !== false); |
|
} |
|
|
|
|
|
protected function createModelForAttributeTest() |
|
{ |
|
return FakedValidationModel::createWithAttributes( |
|
[ |
|
'attr_files' => $this->createTestFiles([ |
|
['name' => 'abc.jpg', 'size' => 1024, 'type' => 'image/jpeg'], |
|
]), |
|
'attr_files_empty' => $this->createTestFiles([[]]), |
|
'attr_err_ini' => $this->createTestFiles([['error' => UPLOAD_ERR_INI_SIZE]]), |
|
'attr_err_part' => $this->createTestFiles([['error' => UPLOAD_ERR_PARTIAL]]), |
|
'attr_err_tmp' => $this->createTestFiles([['error' => UPLOAD_ERR_NO_TMP_DIR]]), |
|
'attr_err_write' => $this->createTestFiles([['error' => UPLOAD_ERR_CANT_WRITE]]), |
|
'attr_err_ext' => $this->createTestFiles([['error' => UPLOAD_ERR_EXTENSION]]), |
|
] |
|
); |
|
} |
|
|
|
public function testValidateAttributeErrPartial() |
|
{ |
|
$m = $this->createModelForAttributeTest(); |
|
$val = new FileValidator(); |
|
$val->validateAttribute($m, 'attr_err_part'); |
|
$this->assertTrue($m->hasErrors('attr_err_part')); |
|
$this->assertSame(Yii::t('yii', 'File upload failed.'), current($m->getErrors('attr_err_part'))); |
|
$log = Yii::$app->getLog()->toArray(); |
|
$this->assertSame(FileValidator::className() . '::validateFile', $log['messages'][0][2]); |
|
$this->assertContains('File was only', $log['messages'][0][0]); |
|
} |
|
|
|
public function testValidateAttributeErrCantWrite() |
|
{ |
|
$m = $this->createModelForAttributeTest(); |
|
$val = new FileValidator(); |
|
$val->validateAttribute($m, 'attr_err_write'); |
|
$this->assertTrue($m->hasErrors('attr_err_write')); |
|
$this->assertSame(Yii::t('yii', 'File upload failed.'), current($m->getErrors('attr_err_write'))); |
|
$log = Yii::$app->getLog()->toArray(); |
|
$this->assertSame(FileValidator::className() . '::validateFile', $log['messages'][0][2]); |
|
$this->assertContains('Failed to write', $log['messages'][0][0]); |
|
} |
|
|
|
public function testValidateAttributeErrExtension() |
|
{ |
|
$m = $this->createModelForAttributeTest(); |
|
$val = new FileValidator(); |
|
$val->validateAttribute($m, 'attr_err_ext'); |
|
$this->assertTrue($m->hasErrors('attr_err_ext')); |
|
$this->assertSame(Yii::t('yii', 'File upload failed.'), current($m->getErrors('attr_err_ext'))); |
|
$log = Yii::$app->getLog()->toArray(); |
|
$this->assertSame(FileValidator::className() . '::validateFile', $log['messages'][0][2]); |
|
$this->assertContains('PHP extension', $log['messages'][0][0]); |
|
} |
|
|
|
public function testValidateAttributeErrNoTmpDir() |
|
{ |
|
$m = $this->createModelForAttributeTest(); |
|
$val = new FileValidator(); |
|
$val->validateAttribute($m, 'attr_err_tmp'); |
|
$this->assertTrue($m->hasErrors('attr_err_tmp')); |
|
$this->assertSame(Yii::t('yii', 'File upload failed.'), current($m->getErrors('attr_err_tmp'))); |
|
$log = Yii::$app->getLog()->toArray(); |
|
$this->assertSame(FileValidator::className() . '::validateFile', $log['messages'][0][2]); |
|
$this->assertContains('Missing the temporary folder', $log['messages'][0][0]); |
|
} |
|
} |