Passed
Push — master ( e6d102...7dc300 )
by Eric
12:39
created

FilesystemTest::tearDownAfterClass()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 8
nc 1
nop 0
dl 0
loc 11
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Utility - Collection of various PHP utility functions.
7
 *
8
 * @author    Eric Sizemore <[email protected]>
9
 * @version   2.0.0
10
 * @copyright (C) 2017 - 2024 Eric Sizemore
11
 * @license   The MIT License (MIT)
12
 *
13
 * Copyright (C) 2017 - 2024 Eric Sizemore <https://www.secondversion.com>.
14
 *
15
 * Permission is hereby granted, free of charge, to any person obtaining a copy
16
 * of this software and associated documentation files (the "Software"), to
17
 * deal in the Software without restriction, including without limitation the
18
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
19
 * sell copies of the Software, and to permit persons to whom the Software is
20
 * furnished to do so, subject to the following conditions:
21
 *
22
 * The above copyright notice and this permission notice shall be included in
23
 * all copies or substantial portions of the Software.
24
 *
25
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
31
 * THE SOFTWARE.
32
 */
33
34
namespace Esi\Utility\Tests;
35
36
use Esi\Utility\Filesystem;
37
use PHPUnit\Framework\TestCase;
38
use PHPUnit\Framework\Attributes\CoversClass;
39
40
use InvalidArgumentException;
41
use RuntimeException;
42
43
use function array_diff;
44
use function array_sum;
45
use function chmod;
46
use function count;
47
use function dirname;
48
use function file_exists;
49
use function implode;
50
use function is_dir;
51
use function mkdir;
52
use function natsort;
53
use function range;
54
use function rmdir;
55
use function str_replace;
56
use function touch;
57
use function trim;
58
use function unlink;
59
use function usleep;
60
61
use const DIRECTORY_SEPARATOR;
62
63
/**
64
 * File system utility tests.
65
 */
66
#[CoversClass(Filesystem::class)]
67
class FilesystemTest extends TestCase
68
{
69
    /**
70
     * @var string
71
     */
72
    protected static string $testDir;
73
74
    /**
75
     * @var array<string>
76
     */
77
    protected static array $testFiles;
78
79
    #[\Override]
80
    public static function setUpBeforeClass(): void
81
    {
82
        self::$testDir = __DIR__ . DIRECTORY_SEPARATOR . 'dir1';
83
        self::$testFiles = [
84
            'file1' => self::$testDir . DIRECTORY_SEPARATOR . 'file1',
85
            'file2' => self::$testDir . DIRECTORY_SEPARATOR . 'file2',
86
            'file3' => self::$testDir . DIRECTORY_SEPARATOR . 'file3.txt',
87
        ];
88
89
        if (!is_dir(self::$testDir)) {
90
            mkdir(self::$testDir);
91
        }
92
93
        if (!file_exists(self::$testFiles['file1'])) {
94
            touch(self::$testFiles['file1']);
95
        }
96
97
        if (!file_exists(self::$testFiles['file2'])) {
98
            touch(self::$testFiles['file2']);
99
        }
100
101
        if (!file_exists(self::$testFiles['file3'])) {
102
            touch(self::$testFiles['file3']);
103
        }
104
    }
105
106
    #[\Override]
107
    public static function tearDownAfterClass(): void
108
    {
109
        unlink(self::$testFiles['file1']);
110
        unlink(self::$testFiles['file2']);
111
        unlink(self::$testFiles['file3']);
112
        usleep(90000);
113
        rmdir(self::$testDir);
114
115
        self::$testDir = '';
116
        self::$testFiles = [];
117
    }
118
119
    /**
120
     * Test Filesystem::lineCounter().
121
     */
122
    public function testLineCounter(): void
123
    {
124
        Filesystem::fileWrite(self::$testFiles['file1'], "This\nis\na\nnew\nline.\n");
125
        self::assertSame(5, array_sum(Filesystem::lineCounter(directory: self::$testDir, onlyLineCount: true)));
126
        self::assertSame(0, array_sum(Filesystem::lineCounter(directory: self::$testDir, ignore: ['dir1'], onlyLineCount: true)));
127
        self::assertSame(0, array_sum(Filesystem::lineCounter(self::$testDir, extensions: ['.txt'], onlyLineCount: true)));
128
129
        self::assertSame([
130
            self::$testDir => [
131
                'file1' => 5,
132
                'file2' => 0,
133
                'file3.txt' => 0,
134
            ],
135
        ], Filesystem::lineCounter(directory: self::$testDir));
136
137
        self::assertSame([], Filesystem::lineCounter(directory: self::$testDir, ignore: ['dir1']));
138
        self::assertSame([], Filesystem::lineCounter(self::$testDir, extensions: ['.txt']));
139
140
        Filesystem::fileWrite(self::$testFiles['file1']);
141
142
        self::expectException(InvalidArgumentException::class);
1 ignored issue
show
Bug Best Practice introduced by
The method PHPUnit\Framework\TestCase::expectException() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

142
        self::/** @scrutinizer ignore-call */ 
143
              expectException(InvalidArgumentException::class);
Loading history...
143
        $count = array_sum(Filesystem::lineCounter('/this/should/not/exist', onlyLineCount: true));
0 ignored issues
show
Unused Code introduced by
The assignment to $count is dead and can be removed.
Loading history...
144
        $count = count(Filesystem::lineCounter('/this/should/not/exist'));
145
146
        $count = array_sum(Filesystem::lineCounter('/this/should/not/exist', ignore: ['dir1'], onlyLineCount: true));
147
        $count = count(Filesystem::lineCounter('/this/should/not/exist', ignore: ['dir1']));
148
    }
149
150
    /**
151
     * Test Filesystem::directorySize().
152
     */
153
    public function testDirectorySize(): void
154
    {
155
        Filesystem::fileWrite(self::$testFiles['file1'], '1234567890');
156
        Filesystem::fileWrite(self::$testFiles['file2'], implode('', range('a', 'z')));
157
158
        self::assertSame(10 + 26, Filesystem::directorySize(self::$testDir));
159
        self::assertSame(0, Filesystem::directorySize(self::$testDir, ['dir1']));
160
161
        Filesystem::fileWrite(self::$testFiles['file1']);
162
        Filesystem::fileWrite(self::$testFiles['file2']);
163
164
        self::expectException(InvalidArgumentException::class);
1 ignored issue
show
Bug Best Practice introduced by
The method PHPUnit\Framework\TestCase::expectException() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

164
        self::/** @scrutinizer ignore-call */ 
165
              expectException(InvalidArgumentException::class);
Loading history...
165
        $count = Filesystem::directorySize('/this/should/not/exist');
0 ignored issues
show
Unused Code introduced by
The assignment to $count is dead and can be removed.
Loading history...
166
    }
167
168
    /**
169
     * Test Filesystem::directoryList().
170
     */
171
    public function testDirectoryList(): void
172
    {
173
        Filesystem::fileWrite(self::$testFiles['file1'], '1234567890');
174
        Filesystem::fileWrite(self::$testFiles['file2'], implode('', range('a', 'z')));
175
176
        $expected = [
177
            0 => self::$testFiles['file1'],
178
            1 => self::$testFiles['file2'],
179
        ];
180
        natsort($expected);
181
182
        $actual = Filesystem::directoryList(self::$testDir);
183
        natsort($actual);
184
185
        self::assertSame([], array_diff($expected, $actual));
186
        self::assertSame([], Filesystem::directoryList(self::$testDir, ['dir1']));
187
188
        Filesystem::fileWrite(self::$testFiles['file1']);
189
        Filesystem::fileWrite(self::$testFiles['file2']);
190
191
        self::expectException(InvalidArgumentException::class);
1 ignored issue
show
Bug Best Practice introduced by
The method PHPUnit\Framework\TestCase::expectException() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

191
        self::/** @scrutinizer ignore-call */ 
192
              expectException(InvalidArgumentException::class);
Loading history...
192
        $count = Filesystem::directoryList('/this/should/not/exist');
0 ignored issues
show
Unused Code introduced by
The assignment to $count is dead and can be removed.
Loading history...
193
    }
194
195
    /**
196
     * Test Filesystem::normalizeFilePath().
197
     */
198
    public function testNormalizeFilePath(): void
199
    {
200
        $separator = DIRECTORY_SEPARATOR;
201
202
        $path1 = __DIR__ . $separator . 'dir1' . $separator . 'file1';
203
        self::assertSame($path1, Filesystem::normalizeFilePath($path1));
204
205
        $path2 = $path1 . $separator;
206
        self::assertSame($path1, Filesystem::normalizeFilePath($path2));
207
208
        $path3 = str_replace($separator, '\\//', $path2);
209
        self::assertSame($path1, Filesystem::normalizeFilePath($path3));
210
211
        $path4 = $path2 . '..' . $separator;
212
        self::assertSame(str_replace($separator . 'file1', '', $path1), Filesystem::normalizeFilePath($path4));
213
214
        $path5 = $path4 . '..';
215
        self::assertSame(str_replace($separator . 'dir1' . $separator . 'file1', '', $path1), Filesystem::normalizeFilePath($path5));
216
    }
217
218
    /**
219
     * Test Filesystem::fileRead().
220
     */
221
    public function testFileRead(): void
222
    {
223
        Filesystem::fileWrite(self::$testFiles['file1'], "This is a test.");
224
225
        /** @var string $data */
226
        $data = Filesystem::fileRead(self::$testFiles['file1']);
227
        $data = trim($data);
228
229
        self::assertSame('This is a test.', $data);
230
231
        Filesystem::fileWrite(self::$testFiles['file1']);
232
233
        self::expectException(InvalidArgumentException::class);
1 ignored issue
show
Bug Best Practice introduced by
The method PHPUnit\Framework\TestCase::expectException() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

233
        self::/** @scrutinizer ignore-call */ 
234
              expectException(InvalidArgumentException::class);
Loading history...
234
        $read = Filesystem::fileRead(self::$testFiles['file1'] . '.php');
0 ignored issues
show
Unused Code introduced by
The assignment to $read is dead and can be removed.
Loading history...
235
    }
236
237
    /**
238
     * Test Filesystem::fileWrite().
239
     */
240
    public function testFileWrite(): void
241
    {
242
        self::assertSame(15, Filesystem::fileWrite(self::$testFiles['file1'], "This is a test."));
243
244
        Filesystem::fileWrite(self::$testFiles['file1']);
245
246
        self::assertSame(15, Filesystem::fileWrite(self::$testFiles['file1'], "This is a test.", -1));
247
248
        self::expectException(InvalidArgumentException::class);
1 ignored issue
show
Bug Best Practice introduced by
The method PHPUnit\Framework\TestCase::expectException() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

248
        self::/** @scrutinizer ignore-call */ 
249
              expectException(InvalidArgumentException::class);
Loading history...
249
        $read = Filesystem::fileWrite(self::$testFiles['file1'] . '.php');
0 ignored issues
show
Unused Code introduced by
The assignment to $read is dead and can be removed.
Loading history...
250
251
        chmod(self::$testFiles['file1'], 0o644);
252
        $read = Filesystem::fileWrite(self::$testFiles['file1']);
253
    }
254
255
    /**
256
     * Test Filesystem::isReallyWritable().
257
     */
258
    public function testIsReallyWritable(): void
259
    {
260
        self::assertTrue(Filesystem::isReallyWritable(self::$testDir));
261
        self::assertTrue(Filesystem::isReallyWritable(self::$testFiles['file1']));
262
        self::assertTrue(Filesystem::isReallyWritable(self::$testFiles['file2']));
263
264
        self::expectException(RuntimeException::class);
1 ignored issue
show
Bug Best Practice introduced by
The method PHPUnit\Framework\TestCase::expectException() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

264
        self::/** @scrutinizer ignore-call */ 
265
              expectException(RuntimeException::class);
Loading history...
265
        self::assertFalse(Filesystem::isReallyWritable('/this/should/not/exist'));
266
        self::assertFalse(Filesystem::isReallyWritable('/this/should/not/exist/file'));
267
    }
268
}
269