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]); } }