1
|
|
|
<?php |
2
|
|
|
namespace Mezon\Security\Tests; |
3
|
|
|
|
4
|
|
|
use PHPUnit\Framework\TestCase; |
5
|
|
|
use Mezon\Security\SecurityRules; |
6
|
|
|
use Mezon\Security\Validators\File\Size; |
7
|
|
|
use Mezon\Security\Validators\File\MimeType; |
8
|
|
|
use Mezon\Security\Validators\File\ImageMaximumWidthHeight; |
9
|
|
|
use Mezon\Security\Validators\File\ImageMinimumWidthHeight; |
10
|
|
|
|
11
|
|
|
class SecurityRulesUnitTest extends TestCase |
12
|
|
|
{ |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* Path to the directory where all files are stored |
16
|
|
|
* |
17
|
|
|
* @var string |
18
|
|
|
*/ |
19
|
|
|
public const PATH_TO_FILE_STORAGE = '/data/files/'; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Field name of the testing file |
23
|
|
|
* |
24
|
|
|
* @var string |
25
|
|
|
*/ |
26
|
|
|
public const TEST_FILE_FIELD_NAME = 'test-file'; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Testing image |
30
|
|
|
* |
31
|
|
|
* @var string |
32
|
|
|
*/ |
33
|
|
|
public const TEST_PNG_IMAGE_PATH = __DIR__ . '/res/test.png'; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* List of methods wich provides file system access and need to be mocked |
37
|
|
|
* |
38
|
|
|
* @var array |
39
|
|
|
*/ |
40
|
|
|
public const FILE_SYSTEM_ACCESS_METHODS = [ |
41
|
|
|
'_prepareFs', |
42
|
|
|
'filePutContents', |
43
|
|
|
'moveUploadedFile', |
44
|
|
|
'fileGetContents' |
45
|
|
|
]; |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* Method returns path to storage |
49
|
|
|
* |
50
|
|
|
* @return string path to storage |
51
|
|
|
*/ |
52
|
|
|
protected function getPathToStorage(): string |
53
|
|
|
{ |
54
|
|
|
return SecurityRulesUnitTest::PATH_TO_FILE_STORAGE . date('Y/m/d/'); |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* Testing edge cases of getFileValue |
59
|
|
|
*/ |
60
|
|
|
public function testGetEmptyFileValue(): void |
61
|
|
|
{ |
62
|
|
|
// setup |
63
|
|
|
$_FILES = [ |
64
|
|
|
'empty-file' => [ |
65
|
|
|
'size' => 0 |
66
|
|
|
] |
67
|
|
|
]; |
68
|
|
|
$securityRules = $this->getMockBuilder(SecurityRules::class) |
|
|
|
|
69
|
|
|
->setMethods(SecurityRulesUnitTest::FILE_SYSTEM_ACCESS_METHODS) |
70
|
|
|
->setConstructorArgs([]) |
71
|
|
|
->getMock(); |
72
|
|
|
|
73
|
|
|
// test body |
74
|
|
|
$result = $securityRules->getFileValue('empty-file', false); |
75
|
|
|
|
76
|
|
|
// assertions |
77
|
|
|
$this->assertEquals('', $result); |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* Method constructs element of the $_FILES array |
82
|
|
|
* |
83
|
|
|
* @param int $size |
84
|
|
|
* size of the file |
85
|
|
|
* @param string $file |
86
|
|
|
* file path |
87
|
|
|
* @param string $name |
88
|
|
|
* file name |
89
|
|
|
* @return array element of the $_FILES array |
90
|
|
|
*/ |
91
|
|
|
protected function constructUploadedFile(int $size, string $file, string $name, string $tmpName = ''): array |
92
|
|
|
{ |
93
|
|
|
$return = [ |
94
|
|
|
'size' => $size, |
95
|
|
|
'name' => $name |
96
|
|
|
]; |
97
|
|
|
|
98
|
|
|
if ($file !== '') { |
99
|
|
|
$return['file'] = $file; |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
if ($tmpName !== '') { |
103
|
|
|
$return['tmp_' . 'name'] = $tmpName; |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
return $return; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
/** |
110
|
|
|
* Method constructs $_FILES array with one element |
111
|
|
|
* |
112
|
|
|
* @param int $size |
113
|
|
|
* size of the file |
114
|
|
|
* @param string $file |
115
|
|
|
* file path |
116
|
|
|
* @param string $name |
117
|
|
|
* file name |
118
|
|
|
* @return array element of the $_FILES array |
119
|
|
|
*/ |
120
|
|
|
protected function constructTestFiles(int $size, string $file, string $name, string $tmpName = ''): array |
121
|
|
|
{ |
122
|
|
|
return [ |
123
|
|
|
SecurityRulesUnitTest::TEST_FILE_FIELD_NAME => $this->constructUploadedFile($size, $file, $name, $tmpName) |
124
|
|
|
]; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* Data provider for the testGetFileValue test |
129
|
|
|
* |
130
|
|
|
* @return array data for test testGetFileValue |
131
|
|
|
*/ |
132
|
|
|
public function getFileValueProvider(): array |
133
|
|
|
{ |
134
|
|
|
return [ |
135
|
|
|
[ |
136
|
|
|
true, |
137
|
|
|
$this->constructTestFiles(2000, '1', '1') |
138
|
|
|
], |
139
|
|
|
[ |
140
|
|
|
false, |
141
|
|
|
$this->constructTestFiles(1, '1', '1') |
142
|
|
|
], |
143
|
|
|
[ |
144
|
|
|
true, |
145
|
|
|
$this->constructTestFiles(1, '', '1', '1') |
146
|
|
|
] |
147
|
|
|
]; |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* Method returns true if the field tmp_name is set |
152
|
|
|
* |
153
|
|
|
* @param array $file |
154
|
|
|
* validating file description |
155
|
|
|
* @return bool true if the field tmp_name is set, false otherwise |
156
|
|
|
*/ |
157
|
|
|
protected function tmpNameSet(array $file): bool |
158
|
|
|
{ |
159
|
|
|
return isset($file['tmp_name']); |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
/** |
163
|
|
|
* Testing edge cases of getFileValue |
164
|
|
|
* |
165
|
|
|
* @param bool $storeFile |
166
|
|
|
* do we need to store file |
167
|
|
|
* @param array $files |
168
|
|
|
* file ddescription |
169
|
|
|
* @dataProvider getFileValueProvider |
170
|
|
|
*/ |
171
|
|
|
public function testGetFileValue(bool $storeFile, array $files): void |
172
|
|
|
{ |
173
|
|
|
// setup |
174
|
|
|
$_FILES = $files; |
175
|
|
|
$securityRules = $this->getMockBuilder(SecurityRules::class) |
|
|
|
|
176
|
|
|
->setMethods(SecurityRulesUnitTest::FILE_SYSTEM_ACCESS_METHODS) |
177
|
|
|
->setConstructorArgs([]) |
178
|
|
|
->getMock(); |
179
|
|
|
|
180
|
|
|
if ($storeFile) { |
181
|
|
|
if ($this->tmpNameSet($files[SecurityRulesUnitTest::TEST_FILE_FIELD_NAME])) { |
182
|
|
|
$securityRules->expects($this->once()) |
183
|
|
|
->method('moveUploadedFile'); |
184
|
|
|
} else { |
185
|
|
|
$securityRules->expects($this->once()) |
186
|
|
|
->method('filePutContents'); |
187
|
|
|
} |
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
// test body |
191
|
|
|
$result = $securityRules->getFileValue(SecurityRulesUnitTest::TEST_FILE_FIELD_NAME, $storeFile); |
192
|
|
|
|
193
|
|
|
// assertions |
194
|
|
|
if ($storeFile) { |
195
|
|
|
$this->assertStringContainsString($this->getPathToStorage(), $result); |
196
|
|
|
} else { |
197
|
|
|
$this->assertEquals(1, $result['size']); |
198
|
|
|
|
199
|
|
|
$this->assertEquals('1', $result['name']); |
200
|
|
|
if ($this->tmpNameSet($files[SecurityRulesUnitTest::TEST_FILE_FIELD_NAME])) { |
201
|
|
|
$this->assertEquals('1', $result['tmp_name']); |
202
|
|
|
} else { |
203
|
|
|
$this->assertEquals('1', $result['file']); |
204
|
|
|
} |
205
|
|
|
} |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
/** |
209
|
|
|
* Data provider for the testStoreFileContent |
210
|
|
|
* |
211
|
|
|
* @return array data for the testStoreFileContent test |
212
|
|
|
*/ |
213
|
|
|
public function storeFileContentProvider(): array |
214
|
|
|
{ |
215
|
|
|
return [ |
216
|
|
|
[ |
217
|
|
|
true |
218
|
|
|
], |
219
|
|
|
[ |
220
|
|
|
false |
221
|
|
|
] |
222
|
|
|
]; |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
/** |
226
|
|
|
* Testing storeFileContent method |
227
|
|
|
* |
228
|
|
|
* @dataProvider storeFileContentProvider |
229
|
|
|
*/ |
230
|
|
|
public function testStoreFileContent(bool $decoded): void |
231
|
|
|
{ |
232
|
|
|
// setup |
233
|
|
|
$securityRules = $this->getMockBuilder(SecurityRules::class) |
|
|
|
|
234
|
|
|
->setMethods(SecurityRulesUnitTest::FILE_SYSTEM_ACCESS_METHODS) |
235
|
|
|
->setConstructorArgs([]) |
236
|
|
|
->getMock(); |
237
|
|
|
$securityRules->method('_prepareFs')->willReturn('prepared'); |
238
|
|
|
$securityRules->expects($this->once()) |
239
|
|
|
->method('filePutContents'); |
240
|
|
|
|
241
|
|
|
// test body |
242
|
|
|
$result = $securityRules->storeFileContent('content', 'file-prefix', $decoded); |
243
|
|
|
|
244
|
|
|
// assertions |
245
|
|
|
$this->assertStringContainsString($this->getPathToStorage(), $result); |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
/** |
249
|
|
|
* Mock creation function |
250
|
|
|
* |
251
|
|
|
* @param mixed $returnValue |
252
|
|
|
* return value of the fileGetContents method |
253
|
|
|
* @return object mock |
254
|
|
|
*/ |
255
|
|
|
protected function getStoreFileMock($returnValue): object |
256
|
|
|
{ |
257
|
|
|
$securityRules = $this->getMockBuilder(SecurityRules::class) |
|
|
|
|
258
|
|
|
->setMethods(SecurityRulesUnitTest::FILE_SYSTEM_ACCESS_METHODS) |
259
|
|
|
->setConstructorArgs([]) |
260
|
|
|
->getMock(); |
261
|
|
|
$securityRules->expects($this->once()) |
262
|
|
|
->method('fileGetContents') |
263
|
|
|
->willReturn($returnValue); |
264
|
|
|
$securityRules->method('_prepareFs')->willReturn('prepared'); |
265
|
|
|
|
266
|
|
|
return $securityRules; |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
/** |
270
|
|
|
* Testing 'storeFile' method |
271
|
|
|
*/ |
272
|
|
|
public function testStoreFile(): void |
273
|
|
|
{ |
274
|
|
|
// setup |
275
|
|
|
$securityRules = $this->getStoreFileMock('content'); |
276
|
|
|
|
277
|
|
|
// test body |
278
|
|
|
$result = $securityRules->storeFile('c://file', 'prefix'); |
279
|
|
|
|
280
|
|
|
// assertions |
281
|
|
|
$this->assertStringContainsString($this->getPathToStorage(), $result); |
282
|
|
|
} |
283
|
|
|
|
284
|
|
|
/** |
285
|
|
|
* Testing 'storeFile' method for unexisting file |
286
|
|
|
*/ |
287
|
|
|
public function testStoreUnexistingFile(): void |
288
|
|
|
{ |
289
|
|
|
// setup |
290
|
|
|
$securityRules = $this->getStoreFileMock(false); |
291
|
|
|
|
292
|
|
|
// test body |
293
|
|
|
$result = $securityRules->storeFile('c://file', 'prefix'); |
294
|
|
|
|
295
|
|
|
// assertions |
296
|
|
|
$this->assertNull($result); |
297
|
|
|
} |
298
|
|
|
|
299
|
|
|
/** |
300
|
|
|
* Data provider for the test testIsUploadedFileValid |
301
|
|
|
* |
302
|
|
|
* @return array testing data |
303
|
|
|
*/ |
304
|
|
|
public function isUploadFileValidProvider(): array |
305
|
|
|
{ |
306
|
|
|
return [ |
307
|
|
|
[ |
308
|
|
|
$this->constructUploadedFile(2000, '1', '1'), |
309
|
|
|
[], |
310
|
|
|
true |
311
|
|
|
], |
312
|
|
|
[ |
313
|
|
|
$this->constructUploadedFile(2000, '1', '1'), |
314
|
|
|
[ |
315
|
|
|
new Size(2000) |
316
|
|
|
], |
317
|
|
|
true |
318
|
|
|
], |
319
|
|
|
[ |
320
|
|
|
$this->constructUploadedFile(2000, '1', '1'), |
321
|
|
|
[ |
322
|
|
|
new Size(1500) |
323
|
|
|
], |
324
|
|
|
false |
325
|
|
|
], |
326
|
|
|
[ |
327
|
|
|
$this->constructUploadedFile(2000, '1', '1', __DIR__ . '/SecurityRulesUnitTest.php'), |
328
|
|
|
[ |
329
|
|
|
new MimeType([ |
330
|
|
|
'text/x-php' |
331
|
|
|
]) |
332
|
|
|
], |
333
|
|
|
true |
334
|
|
|
], |
335
|
|
|
[ |
336
|
|
|
$this->constructUploadedFile(2000, '1', '1', __DIR__ . '/SecurityRulesUnitTest.php'), |
337
|
|
|
[ |
338
|
|
|
new MimeType([ |
339
|
|
|
'image/png' |
340
|
|
|
]) |
341
|
|
|
], |
342
|
|
|
false |
343
|
|
|
], |
344
|
|
|
[ |
345
|
|
|
$this->constructUploadedFile(6912, '1', '1', SecurityRulesUnitTest::TEST_PNG_IMAGE_PATH), |
346
|
|
|
[ |
347
|
|
|
new MimeType([ |
348
|
|
|
'image/png' |
349
|
|
|
]) |
350
|
|
|
], |
351
|
|
|
true |
352
|
|
|
], |
353
|
|
|
[ |
354
|
|
|
$this->constructUploadedFile(6912, '1', '1', SecurityRulesUnitTest::TEST_PNG_IMAGE_PATH), |
355
|
|
|
[ |
356
|
|
|
new ImageMaximumWidthHeight(500, 500) |
357
|
|
|
], |
358
|
|
|
false |
359
|
|
|
], |
360
|
|
|
[ |
361
|
|
|
$this->constructUploadedFile(6912, '1', '1', SecurityRulesUnitTest::TEST_PNG_IMAGE_PATH), |
362
|
|
|
[ |
363
|
|
|
new ImageMaximumWidthHeight(500, 600) |
364
|
|
|
], |
365
|
|
|
false |
366
|
|
|
], |
367
|
|
|
[ |
368
|
|
|
$this->constructUploadedFile(6912, '1', '1', SecurityRulesUnitTest::TEST_PNG_IMAGE_PATH), |
369
|
|
|
[ |
370
|
|
|
new ImageMaximumWidthHeight(500, 500) |
371
|
|
|
], |
372
|
|
|
false |
373
|
|
|
], |
374
|
|
|
[ |
375
|
|
|
$this->constructUploadedFile(6912, '1', '1', SecurityRulesUnitTest::TEST_PNG_IMAGE_PATH), |
376
|
|
|
[ |
377
|
|
|
new ImageMaximumWidthHeight(600, 600) |
378
|
|
|
], |
379
|
|
|
true |
380
|
|
|
], |
381
|
|
|
[ |
382
|
|
|
$this->constructUploadedFile(6912, '1', '1', SecurityRulesUnitTest::TEST_PNG_IMAGE_PATH), |
383
|
|
|
[ |
384
|
|
|
new ImageMinimumWidthHeight(500, 500) |
385
|
|
|
], |
386
|
|
|
true |
387
|
|
|
], |
388
|
|
|
[ |
389
|
|
|
$this->constructUploadedFile(6912, '1', '1', SecurityRulesUnitTest::TEST_PNG_IMAGE_PATH), |
390
|
|
|
[ |
391
|
|
|
new ImageMinimumWidthHeight(600, 500) |
392
|
|
|
], |
393
|
|
|
false |
394
|
|
|
], |
395
|
|
|
[ |
396
|
|
|
$this->constructUploadedFile(6912, '1', '1', SecurityRulesUnitTest::TEST_PNG_IMAGE_PATH), |
397
|
|
|
[ |
398
|
|
|
new ImageMinimumWidthHeight(500, 600) |
399
|
|
|
], |
400
|
|
|
false |
401
|
|
|
], |
402
|
|
|
[ |
403
|
|
|
$this->constructUploadedFile(6912, '1', '1', SecurityRulesUnitTest::TEST_PNG_IMAGE_PATH), |
404
|
|
|
[ |
405
|
|
|
new ImageMinimumWidthHeight(600, 600) |
406
|
|
|
], |
407
|
|
|
false |
408
|
|
|
] |
409
|
|
|
]; |
410
|
|
|
} |
411
|
|
|
|
412
|
|
|
/** |
413
|
|
|
* Testing that uploaded file is valid |
414
|
|
|
* |
415
|
|
|
* @param array $file |
416
|
|
|
* uploaded file |
417
|
|
|
* @param array $validators |
418
|
|
|
* validators |
419
|
|
|
* @param bool $requiredResult |
420
|
|
|
* required result |
421
|
|
|
* @dataProvider isUploadFileValidProvider |
422
|
|
|
*/ |
423
|
|
|
public function testIsUploadedFileValid(array $file, array $validators, bool $requiredResult): void |
424
|
|
|
{ |
425
|
|
|
// setup |
426
|
|
|
$security = new SecurityRules(); |
427
|
|
|
$_FILES['is-valid-file'] = $file; |
428
|
|
|
|
429
|
|
|
// test body |
430
|
|
|
$result = $security->isUploadedFileValid('is-valid-file', $validators); |
431
|
|
|
|
432
|
|
|
// assertions |
433
|
|
|
$this->assertEquals($requiredResult, $result); |
434
|
|
|
} |
435
|
|
|
|
436
|
|
|
/** |
437
|
|
|
* Data provider for the test testValidatingUnexistingFile |
438
|
|
|
* |
439
|
|
|
* @return array testing data |
440
|
|
|
*/ |
441
|
|
|
public function validatingUnexistingFileProvider(): array |
442
|
|
|
{ |
443
|
|
|
return [ |
444
|
|
|
[ |
445
|
|
|
new Size(2000) |
446
|
|
|
], |
447
|
|
|
[ |
448
|
|
|
new MimeType([ |
449
|
|
|
'image/jpeg' |
450
|
|
|
]) |
451
|
|
|
] |
452
|
|
|
]; |
453
|
|
|
} |
454
|
|
|
|
455
|
|
|
/** |
456
|
|
|
* Trying to validate size of the unexisting file |
457
|
|
|
* |
458
|
|
|
* @param object $validator |
459
|
|
|
* validator |
460
|
|
|
* @dataProvider validatingUnexistingFileProvider |
461
|
|
|
*/ |
462
|
|
|
public function testValidatingUnexistingFile(object $validator): void |
463
|
|
|
{ |
464
|
|
|
// assertions |
465
|
|
|
$this->expectException(\Exception::class); |
466
|
|
|
|
467
|
|
|
// setup |
468
|
|
|
$security = new SecurityRules(); |
469
|
|
|
|
470
|
|
|
// test body |
471
|
|
|
$security->isUploadedFileValid('unexisting-file', [ |
472
|
|
|
$validator |
473
|
|
|
]); |
474
|
|
|
} |
475
|
|
|
|
476
|
|
|
/** |
477
|
|
|
* Testing getIntValue method |
478
|
|
|
*/ |
479
|
|
|
public function testGetIntValue(): void |
480
|
|
|
{ |
481
|
|
|
// setup |
482
|
|
|
$security = new SecurityRules(); |
483
|
|
|
|
484
|
|
|
// test body and assertions |
485
|
|
|
$this->assertEquals(1, $security->getIntValue('1')); |
486
|
|
|
$this->assertEquals(2, $security->getIntValue(2)); |
487
|
|
|
$this->assertEquals(0, $security->getIntValue('abc')); |
488
|
|
|
$this->assertEquals(1, $security->getIntValue(1.1)); |
489
|
|
|
} |
490
|
|
|
|
491
|
|
|
/** |
492
|
|
|
* Testing getStringValue |
493
|
|
|
*/ |
494
|
|
|
public function testGetStringValue(): void |
495
|
|
|
{ |
496
|
|
|
// setup |
497
|
|
|
$security = new SecurityRules(); |
498
|
|
|
|
499
|
|
|
// test body and assertions |
500
|
|
|
$this->assertEquals('1', $security->getStringValue('1')); |
501
|
|
|
$this->assertEquals('1', $security->getStringValue(1)); |
502
|
|
|
$this->assertEquals('2.1', $security->getStringValue(2.1)); |
503
|
|
|
$this->assertEquals('&', $security->getStringValue('&')); |
504
|
|
|
$this->assertEquals('<', $security->getStringValue('<')); |
505
|
|
|
$this->assertEquals('>', $security->getStringValue('>')); |
506
|
|
|
} |
507
|
|
|
} |
508
|
|
|
|
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.