assertEquals($expected, $uploadedFile);
    }
    /**
     * @param array $input The input array to parse.
     *
     * @dataProvider providerCreateFromGlobals
     */
    public function testCreateFromGlobalsFromUserData(array $input)
    {
        //If slim.files provided - it will return what was provided
        $userData['slim.files'] = $input;
        $uploadedFile = UploadedFile::createFromGlobals(Environment::mock($userData));
        $this->assertEquals($input, $uploadedFile);
    }
    public function testCreateFromGlobalsWithoutFile()
    {
        unset($_FILES);
        $uploadedFile = UploadedFile::createFromGlobals(Environment::mock());
        $this->assertEquals([], $uploadedFile);
    }
    public function testConstructor(): UploadedFile
    {
        $attr = [
            'tmp_name' => self::$filename,
            'name' => 'my-avatar.txt',
            'size' => 8,
            'type' => 'text/plain',
            'error' => 0,
        ];
        $uploadedFile = new UploadedFile(
            $attr['tmp_name'],
            $attr['name'],
            $attr['type'],
            $attr['size'],
            $attr['error'],
            false
        );
        $this->assertEquals($attr['name'], $uploadedFile->getClientFilename());
        $this->assertEquals($attr['type'], $uploadedFile->getClientMediaType());
        $this->assertEquals($attr['size'], $uploadedFile->getSize());
        $this->assertEquals($attr['error'], $uploadedFile->getError());
        $this->assertEquals($attr['tmp_name'], $uploadedFile->getFilePath());
        return $uploadedFile;
    }
    public function testConstructorSapi(): UploadedFile
    {
        $attr = [
            'tmp_name' => self::$filename,
            'name' => 'my-avatar.txt',
            'size' => 8,
            'type' => 'text/plain',
            'error' => 0,
        ];
        $uploadedFile = new UploadedFile(
            $attr['tmp_name'],
            $attr['name'],
            $attr['type'],
            $attr['size'],
            $attr['error'],
            true
        );
        $this->assertEquals($attr['name'], $uploadedFile->getClientFilename());
        $this->assertEquals($attr['type'], $uploadedFile->getClientMediaType());
        $this->assertEquals($attr['size'], $uploadedFile->getSize());
        $this->assertEquals($attr['error'], $uploadedFile->getError());
        $this->assertEquals($attr['tmp_name'], $uploadedFile->getFilePath());
        return $uploadedFile;
    }
    /**
     * @depends testConstructor
     *
     * @param UploadedFile $uploadedFile
     *
     * @return UploadedFile
     */
    public function testGetStream(UploadedFile $uploadedFile): UploadedFile
    {
        $stream = $uploadedFile->getStream();
        $this->assertEquals(true, $uploadedFile->getStream() instanceof Stream);
        $stream->close();
        return $uploadedFile;
    }
    /**
     * @depends testConstructor
     *
     * @param UploadedFile $uploadedFile
     *
     */
    public function testMoveToNotWritable(UploadedFile $uploadedFile)
    {
        $this->expectException(InvalidArgumentException::class);
        $tempName = uniqid('file-');
        $path = 'some_random_dir' . DIRECTORY_SEPARATOR . $tempName;
        $uploadedFile->moveTo($path);
    }
    /**
     * @depends testConstructor
     *
     * @param UploadedFile $uploadedFile
     *
     * @return UploadedFile
     */
    public function testMoveTo(UploadedFile $uploadedFile): UploadedFile
    {
        $tempName = uniqid('file-');
        $path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $tempName;
        $uploadedFile->moveTo($path);
        $this->assertFileExists($path);
        unlink($path);
        return $uploadedFile;
    }
    public function testMoveToRenameFailure()
    {
        $this->expectException(RuntimeException::class);
        $this->expectExceptionMessageMatches('/^Error moving uploaded file .* to .*$/');
        $uploadedFile = $this->generateNewTmpFile();
        $tempName = uniqid('file-');
        $path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $tempName;
        $GLOBALS['rename_return'] = false;
        $uploadedFile->moveTo($path);
    }
    /**
     * @depends testConstructorSapi
     *
     * @param UploadedFile $uploadedFile
     *
     */
    public function testMoveToSapiNonUploadedFile(UploadedFile $uploadedFile)
    {
        $this->expectException(RuntimeException::class);
        $tempName = uniqid('file-');
        $path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $tempName;
        $uploadedFile->moveTo($path);
    }
    /**
     * @depends testConstructorSapi
     *
     * @param UploadedFile $uploadedFile
     *
     */
    public function testMoveToSapiMoveUploadedFileFails(UploadedFile $uploadedFile)
    {
        $this->expectException(RuntimeException::class);
        $this->expectExceptionMessageMatches('~Error moving uploaded file.*~');
        $GLOBALS['is_uploaded_file_return'] = true;
        $tempName = uniqid('file-');
        $path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $tempName;
        $uploadedFile->moveTo($path);
    }
    /**
     * @depends testMoveTo
     *
     * @param UploadedFile $uploadedFile
     *
     */
    public function testMoveToCannotBeDoneTwice(UploadedFile $uploadedFile)
    {
        $this->expectException(RuntimeException::class);
        $tempName = uniqid('file-');
        $path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $tempName;
        $uploadedFile->moveTo($path);
        $this->assertFileExists($path);
        unlink($path);
        $uploadedFile->moveTo($path);
    }
    /**
     * This test must run after testMoveTo
     *
     * @depends testConstructor
     *
     * @param UploadedFile $uploadedFile
     *
     */
    public function testMoveToAgain(UploadedFile $uploadedFile)
    {
        $this->expectException(RuntimeException::class);
        $tempName = uniqid('file-');
        $path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $tempName;
        $uploadedFile->moveTo($path);
    }
    /**
     * This test must run after testMoveTo
     *
     * @depends testConstructor
     *
     * @param UploadedFile $uploadedFile
     *
     */
    public function testMovedStream(UploadedFile $uploadedFile)
    {
        $this->expectException(RuntimeException::class);
        $uploadedFile->getStream();
    }
    public function testMoveToStream()
    {
        $uploadedFile = $this->generateNewTmpFile();
        $fileProperty = new ReflectionProperty($uploadedFile, 'file');
        $fileProperty->setAccessible(true);
        $fileName = $fileProperty->getValue($uploadedFile);
        $contents = file_get_contents($fileName);
        ob_start();
        $uploadedFile->moveTo('php://output');
        $movedFileContents = ob_get_clean();
        $this->assertEquals($contents, $movedFileContents);
        $this->assertFileDoesNotExist($fileName);
    }
    public function testMoveToStreamCopyFailure()
    {
        $this->expectException(RuntimeException::class);
        $this->expectExceptionMessage('Error moving uploaded file  to php://output');
        $uploadedFile = $this->generateNewTmpFile();
        $GLOBALS['copy_return'] = false;
        $uploadedFile->moveTo('php://output');
    }
    public function testFileUploadWithTempStream()
    {
        $streamFactory = function (...$args) {
            return (new StreamFactory())->createStream(...$args);
        };
        $uploadedFileFactory = function (...$args) {
            return (new UploadedFileFactory())->createUploadedFile(...$args);
        };
        $this->runFileUploadWithTempStreamTest($streamFactory, $uploadedFileFactory);
    }
    /**
     * This test sequence has been inspired by UploadedFileFactoryTestCase from http-interop/http-factory-tests package.
     *
     * @param callable $streamFactory
     * @param callable $uploadedFileFactory
     */
    private function runFileUploadWithTempStreamTest(callable $streamFactory, callable $uploadedFileFactory)
    {
        $content = 'this is your capitan speaking';
        $error = UPLOAD_ERR_OK;
        $clientFilename = 'test.txt';
        $clientMediaType = 'text/plain';
        $stream = call_user_func($streamFactory, $content);
        $file = call_user_func(
            $uploadedFileFactory,
            $stream,
            strlen($content),
            $error,
            $clientFilename,
            $clientMediaType
        );
        $this->assertInstanceOf(UploadedFileInterface::class, $file);
        $this->assertSame($content, (string)$file->getStream());
        $this->assertSame(strlen($content), $file->getSize());
        $this->assertSame($error, $file->getError());
        $this->assertSame($clientFilename, $file->getClientFilename());
        $this->assertSame($clientMediaType, $file->getClientMediaType());
        $this->assertSame($stream->getMetadata('uri'), $file->getFilePath());
    }
    public function testCreateUploadedFileWithInvalidArguments()
    {
        $this->expectException(InvalidArgumentException::class);
        new UploadedFile(42); // a random value that is neither a string nor an instance of StreamInterface
    }
    public function testCreateUploadedFileWithInvalidUri()
    {
        $this->expectException(InvalidArgumentException::class);
        $streamProphecy = $this->prophesize(StreamInterface::class);
        /** @noinspection PhpUndefinedMethodInspection */
        $streamProphecy
            ->getMetadata('uri')
            ->willReturn(null)
            ->shouldBeCalled();
        $stream = $streamProphecy->reveal();
        // Test with a StreamInterface that returns `null`
        // when `$stream->getMetadata('uri')` is called (which is an invalid case).
        new UploadedFile($stream);
    }
    public static function providerCreateFromGlobals(): array
    {
        return [
            // no nest: 
            [
                // $_FILES array
                [
                    'avatar' => [
                        'tmp_name' => 'phpUxcOty',
                        'name' => 'my-avatar.png',
                        'size' => 90996,
                        'type' => 'image/png',
                        'error' => 0,
                    ],
                ],
                // expected format of array
                [
                    'avatar' => new UploadedFile('phpUxcOty', 'my-avatar.png', 'image/png', 90996, UPLOAD_ERR_OK, true)
                ]
            ],
            // no nest, with error: 
            [
                // $_FILES array
                [
                    'avatar' => [
                        'tmp_name' => 'phpUxcOty',
                        'name' => 'my-avatar.png',
                        'size' => 90996,
                        'type' => 'image/png',
                        'error' => 7,
                    ],
                ],
                // expected format of array
                [
                    'avatar' => new UploadedFile(
                        'phpUxcOty',
                        'my-avatar.png',
                        'image/png',
                        90996,
                        UPLOAD_ERR_CANT_WRITE,
                        true
                    )
                ]
            ],
            // array of files: 
            [
                // $_FILES array
                [
                    'avatars' => [
                        'tmp_name' => [
                            0 => __DIR__ . DIRECTORY_SEPARATOR . 'file0.txt',
                            1 => __DIR__ . DIRECTORY_SEPARATOR . 'file1.html',
                        ],
                        'name' => [
                            0 => 'file0.txt',
                            1 => 'file1.html',
                        ],
                        'type' => [
                            0 => 'text/plain',
                            1 => 'text/html',
                        ],
                        'error' => [
                            0 => 0,
                            1 => 0
                        ],
                        'size' => [
                            0 => 0,
                            1 => 0
                        ]
                    ],
                ],
                // expected format of array
                [
                    'avatars' => [
                        0 => new UploadedFile(
                            __DIR__ . DIRECTORY_SEPARATOR . 'file0.txt',
                            'file0.txt',
                            'text/plain',
                            null,
                            UPLOAD_ERR_OK,
                            true
                        ),
                        1 => new UploadedFile(
                            __DIR__ . DIRECTORY_SEPARATOR . 'file1.html',
                            'file1.html',
                            'text/html',
                            null,
                            UPLOAD_ERR_OK,
                            true
                        ),
                    ],
                ]
            ],
            // array of files as multidimensional array: 
            [
                // $_FILES array
                [
                    [
                        'avatars' => [
                            'tmp_name' => [
                                0 => __DIR__ . DIRECTORY_SEPARATOR . 'file0.txt',
                                1 => __DIR__ . DIRECTORY_SEPARATOR . 'file1.html',
                            ],
                            'name' => [
                                0 => 'file0.txt',
                                1 => 'file1.html',
                            ],
                            'type' => [
                                0 => 'text/plain',
                                1 => 'text/html',
                            ],
                            'size' => [
                                0 => 0,
                                1 => 0,
                            ],
                        ],
                    ],
                ],
                // expected format of array
                [
                    0 =>
                        [
                            'avatars' =>
                                [
                                    'tmp_name' => [],
                                    'name' => [],
                                    'type' => [],
                                    'size' => [],
                                ],
                        ],
                ],
            ],
            // single nested file: 
            [
                // $_FILES array
                [
                    'details' => [
                        'tmp_name' => [
                            'avatar' => __DIR__ . DIRECTORY_SEPARATOR . 'file0.txt',
                        ],
                        'name' => [
                            'avatar' => 'file0.txt',
                        ],
                        'type' => [
                            'avatar' => 'text/plain',
                        ],
                        'error' => [
                            'avatar' => 0,
                        ],
                        'size' => [
                            'avatar' => 0,
                        ],
                    ],
                ],
                // expected format of array
                [
                    'details' => [
                        'avatar' => new UploadedFile(
                            __DIR__ . DIRECTORY_SEPARATOR . 'file0.txt',
                            'file0.txt',
                            'text/plain',
                            null,
                            UPLOAD_ERR_OK,
                            true
                        ),
                    ],
                ]
            ],
            // nested array of files: 
            [
                [
                    'files' => [
                        'tmp_name' => [
                            'details' => [
                                'avatar' => [
                                    0 => __DIR__ . DIRECTORY_SEPARATOR . 'file0.txt',
                                    1 => __DIR__ . DIRECTORY_SEPARATOR . 'file1.html',
                                ],
                            ],
                        ],
                        'name' => [
                            'details' => [
                                'avatar' => [
                                    0 => 'file0.txt',
                                    1 => 'file1.html',
                                ],
                            ],
                        ],
                        'type' => [
                            'details' => [
                                'avatar' => [
                                    0 => 'text/plain',
                                    1 => 'text/html',
                                ],
                            ],
                        ],
                        'error' => [
                            'details' => [
                                'avatar' => [
                                    0 => 0,
                                    1 => 0
                                ],
                            ],
                        ],
                        'size' => [
                            'details' => [
                                'avatar' => [
                                    0 => 0,
                                    1 => 0
                                ],
                            ],
                        ],
                    ],
                ],
                // expected format of array
                [
                    'files' => [
                        'details' => [
                            'avatar' => [
                                0 => new UploadedFile(
                                    __DIR__ . DIRECTORY_SEPARATOR . 'file0.txt',
                                    'file0.txt',
                                    'text/plain',
                                    null,
                                    UPLOAD_ERR_OK,
                                    true
                                ),
                                1 => new UploadedFile(
                                    __DIR__ . DIRECTORY_SEPARATOR . 'file1.html',
                                    'file1.html',
                                    'text/html',
                                    null,
                                    UPLOAD_ERR_OK,
                                    true
                                ),
                            ],
                        ],
                    ],
                ]
            ],
        ];
    }
}