<commit_before><?php

declare(strict_types=1);

namespace League\Flysystem\Local;

use League\Flysystem\AdapterTestUtilities\FilesystemAdapterTestCase;
use League\Flysystem\Config;
use League\Flysystem\FilesystemAdapter;
use League\Flysystem\StorageAttributes;
use League\Flysystem\SymbolicLinkEncountered;
use League\Flysystem\UnableToCopyFile;
use League\Flysystem\UnableToCreateDirectory;
use League\Flysystem\UnableToDeleteDirectory;
use League\Flysystem\UnableToDeleteFile;
use League\Flysystem\UnableToMoveFile;
use League\Flysystem\UnableToReadFile;
use League\Flysystem\UnableToRetrieveMetadata;
use League\Flysystem\UnableToSetVisibility;
use League\Flysystem\UnableToWriteFile;
use League\Flysystem\UnixVisibility\PortableVisibilityConverter;
use League\Flysystem\Visibility;

use Traversable;

use function file_get_contents;
use function file_put_contents;
use function fileperms;
use function iterator_to_array;
use function mkdir;
use function symlink;

use const LOCK_EX;

/**
 * @group local
 */
class LocalFilesystemAdapterTest extends FilesystemAdapterTestCase
{
    private const ROOT = __DIR__ . '/test-root';

    protected function setUp(): void
    {
        reset_function_mocks();
        delete_directory(static::ROOT);
    }

    protected function tearDown(): void
    {
        reset_function_mocks();
        delete_directory(static::ROOT);
    }

    /**
     * @test
     */
    public function creating_a_local_filesystem_creates_a_root_directory(): void
    {
        new LocalFilesystemAdapter(static::ROOT);
        $this->assertDirectoryExists(static::ROOT);
    }

    /**
     * @test
     */
    public function not_being_able_to_create_a_root_directory_results_in_an_exception(): void
    {
        $this->expectException(UnableToCreateDirectory::class);
        new LocalFilesystemAdapter('/cannot-create/this-directory/');
    }

    /**
     * @test
     */
    public function writing_a_file(): void
    {
        $adapter = new LocalFilesystemAdapter(static::ROOT);

        $adapter->write('/file.txt', 'contents', new Config());

        $this->assertFileExists(static::ROOT . '/file.txt');
        $contents = file_get_contents(static::ROOT . '/file.txt');
        $this->assertEquals('contents', $contents);
    }

    /**
     * @test
     */
    public function writing_a_file_with_a_stream(): void
    {
        $adapter = new LocalFilesystemAdapter(static::ROOT);
        $stream = stream_with_contents('contents');

        $adapter->writeStream('/file.txt', $stream, new Config());
        fclose($stream);

        $this->assertFileExists(static::ROOT . '/file.txt');
        $contents = file_get_contents(static::ROOT . '/file.txt');
        $this->assertEquals('contents', $contents);
    }

    /**
     * @test
     */
    public function writing_a_file_with_a_stream_and_visibility(): void
    {
        $adapter = new LocalFilesystemAdapter(static::ROOT);
        $stream = stream_with_contents('something');

        $adapter->writeStream('/file.txt', $stream, new Config(['visibility' => Visibility::PRIVATE]));
        fclose($stream);

        $this->assertFileContains(static::ROOT . '/file.txt', 'something');
        $this->assertFileHasPermissions(static::ROOT . '/file.txt', 0600);
    }

    /**
     * @test
     */
    public function writing_a_file_with_visibility(): void
    {
        $adapter = new LocalFilesystemAdapter(static::ROOT, new PortableVisibilityConverter());
        $adapter->write('/file.txt', 'contents', new Config(['visibility' => 'private']));
        $this->assertFileContains(static::ROOT . '/file.txt', 'contents');
        $this->assertFileHasPermissions(static::ROOT . '/file.txt', 0600);
    }

    /**
     * @test
     */
    public function failing_to_set_visibility(): void
    {<commit_msg>Add test for empty stream<commit_after><?php

declare(strict_types=1);

namespace League\Flysystem\Local;

use League\Flysystem\AdapterTestUtilities\FilesystemAdapterTestCase;
use League\Flysystem\Config;
use League\Flysystem\FilesystemAdapter;
use League\Flysystem\StorageAttributes;
use League\Flysystem\SymbolicLinkEncountered;
use League\Flysystem\UnableToCopyFile;
use League\Flysystem\UnableToCreateDirectory;
use League\Flysystem\UnableToDeleteDirectory;
use League\Flysystem\UnableToDeleteFile;
use League\Flysystem\UnableToMoveFile;
use League\Flysystem\UnableToReadFile;
use League\Flysystem\UnableToRetrieveMetadata;
use League\Flysystem\UnableToSetVisibility;
use League\Flysystem\UnableToWriteFile;
use League\Flysystem\UnixVisibility\PortableVisibilityConverter;
use League\Flysystem\Visibility;

use Traversable;

use function file_get_contents;
use function file_put_contents;
use function fileperms;
use function iterator_to_array;
use function mkdir;
use function symlink;

use const LOCK_EX;

/**
 * @group local
 */
class LocalFilesystemAdapterTest extends FilesystemAdapterTestCase
{
    private const ROOT = __DIR__ . '/test-root';

    protected function setUp(): void
    {
        reset_function_mocks();
        delete_directory(static::ROOT);
    }

    protected function tearDown(): void
    {
        reset_function_mocks();
        delete_directory(static::ROOT);
    }

    /**
     * @test
     */
    public function creating_a_local_filesystem_creates_a_root_directory(): void
    {
        new LocalFilesystemAdapter(static::ROOT);
        $this->assertDirectoryExists(static::ROOT);
    }

    /**
     * @test
     */
    public function not_being_able_to_create_a_root_directory_results_in_an_exception(): void
    {
        $this->expectException(UnableToCreateDirectory::class);
        new LocalFilesystemAdapter('/cannot-create/this-directory/');
    }

    /**
     * @test
     */
    public function writing_a_file(): void
    {
        $adapter = new LocalFilesystemAdapter(static::ROOT);

        $adapter->write('/file.txt', 'contents', new Config());

        $this->assertFileExists(static::ROOT . '/file.txt');
        $contents = file_get_contents(static::ROOT . '/file.txt');
        $this->assertEquals('contents', $contents);
    }

    /**
     * @test
     */
    public function writing_a_file_with_a_stream(): void
    {
        $adapter = new LocalFilesystemAdapter(static::ROOT);
        $stream = stream_with_contents('contents');

        $adapter->writeStream('/file.txt', $stream, new Config());
        fclose($stream);

        $this->assertFileExists(static::ROOT . '/file.txt');
        $contents = file_get_contents(static::ROOT . '/file.txt');
        $this->assertEquals('contents', $contents);
    }

    /**
     * @test
     */
    public function writing_a_file_with_an_empty_stream(): void
    {
        $adapter = new LocalFilesystemAdapter(static::ROOT);
        $stream = stream_with_contents('');

        $adapter->writeStream('/file.txt', $stream, new Config());
        fclose($stream);

        $this->assertFileExists(static::ROOT . '/file.txt');
        $contents = file_get_contents(static::ROOT . '/file.txt');
        $this->assertEquals('', $contents);
    }

    /**
     * @test
     */
    public function writing_a_file_with_a_stream_and_visibility(): void
    {
        $adapter = new LocalFilesystemAdapter(static::ROOT);
        $stream = stream_with_contents('something');

        $adapter->writeStream('/file.txt', $stream, new Config(['visibility' => Visibility::PRIVATE]));
        fclose($stream);

        $this->assertFileContains(static::ROOT . '/file.txt', 'something');
        $this->assertFileHasPermissions(static::ROOT . '/file.txt', 0600);
    }

    /**
     * @test
     */
    public function writing_a_file_with_visibility(): void
    {
        $adapter = new LocalFilesystemAdapter(static::ROOT, new PortableVisibilityConverter());
        $adapter->write('/file.txt', 'contents', new Config(['visibility' => 'private']));
        $this->assertFileContains(static::ROOT . '/file.txt', 'contents');
        $this->assertFileHasPermissions(static::ROOT . '/file.txt', 0600);
    }

    /**
     * @test
     */
    public function failing_to_set_visibility(): void
    {
{'fraction_non_alphanumeric': 0.13008532212192409, 'fraction_numerical': 0.0022257944849758873, 'mean_word_length': 3.5361749859786875, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 38, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3506980', 'n_tokens_mistral': 2381, 'n_tokens_neox': 2298, 'n_words': 400}