Issues (308)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/utils/tests/FuncTest.php (17 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php namespace nyx\utils\tests;
2
3
// Internal dependencies
4
use nyx\utils\Func;
5
6
/**
7
 * Func Tests
8
 *
9
 * @package     Nyx\Utils\Tests
10
 * @version     0.0.1
11
 * @author      Michal Chojnacki <[email protected]>
12
 * @copyright   2012-2016 Nyx Dev Team
13
 * @link        http://docs.muyo.io/nyx/utils/index.html
14
 */
15
class FuncTest extends \PHPUnit\Framework\TestCase
16
{
17
    // Used by the when/unless tests.
18
    private $whenExists;
19
20
    // Func::after()
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
21
    public function testAfter()
22
    {
23
        $times = 5;
24
        $runs  = 11;
25
26
        // Let's create a simple helper.
27
        $test = function (callable $wrapper, callable $function, $value) use ($times, $runs) {
28
29
            // Invoke the function once to determine the expected value.
30
            $expected = $function($value);
31
32
            for ($i = 1; $i <= $runs; $i++) {
33
                if ($i < $times) {
34
                    $this->assertNull($wrapper($value));
35
                } else {
36
                    $this->assertEquals($expected, $wrapper($value));
37
                }
38
            }
39
        };
40
41
        // Prepare our functions.
42
        $func1 = function ($value) {return 'foo'.$value;};
43
        $func2 = function ($value) {return $value.'bar';};
44
45
        // Run a few loops.
46
        $wrapper = Func::after($times, $func1);
47
        $test($wrapper, $func1, 'bar');
48
49
        $wrapper = Func::after($times, $func2);
50
        $test($wrapper, $func2, 'foo');
51
    }
52
53
    /**
54
     * @see Func::compose()
55
     * ----------------------------------------------------------------------------------------------------------------
56
     */
57
58
    public function testCompose()
59
    {
60
        $countFiltered = Func::compose('count', 'array_filter');
61
        $data = [1, 'foo', 2, 'bar', 3, [1, 2, 3]];
62
63
        static::assertEquals(3, $countFiltered($data, 'is_int'));
64
        static::assertEquals(1, $countFiltered($data, 'is_array'));
65
        static::assertEquals(2, $countFiltered($data, 'is_string'));
66
    }
67
68
    /**
69
     * @see Func::hash()
70
     * ----------------------------------------------------------------------------------------------------------------
71
     */
72
73
    public function testHash()
74
    {
75
        // Prepare our functions.
76
        $func1 = function ($arg1, $arg2) {return true;};
0 ignored issues
show
The parameter $arg1 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $arg2 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
77
78
        // Run some tests.
79
        $this->assertEquals('8bdb4ed5e8d60590121851789f7c5366', Func::hash($func1, ['arg1', 'arg2']));
80
        $this->assertEquals('d18a838748b014d758771d5dc497f78f', Func::hash($func1, ['arg1', ['arg2', 'arg3']]));
81
82
        // Same callable, different arguments.
83
        $this->assertEquals('0322135bc1a0c8e574fc5c3d380eb8d7', Func::hash([$this, 'compute'], ['arg1', ['arg2', 'arg3']]));
84
        $this->assertEquals('bd1d96a1996666394149e71b1f18352c', Func::hash([$this, 'compute'], ['arg1']));
85
86
        // Both should boil down to the same hash - same arguments, just a different callable notation.
87
        $this->assertEquals('2edbc7fd908ff5a29f88330640479c08', Func::hash(['\nyx\utils\tests\FuncTest', 'staticCompute'], ['arg1', ['arg2', 'arg3']]));
88
        $this->assertEquals('2edbc7fd908ff5a29f88330640479c08', Func::hash('\nyx\utils\tests\FuncTest::staticCompute', ['arg1', ['arg2', 'arg3']]));
89
90
        // Same callable notation, different arguments though.
91
        $this->assertEquals('2e287dc68fecd9998c0fcc8e15dbe3aa', Func::hash(['\nyx\utils\tests\FuncTest', 'staticCompute'], ['arg1']));
92
        $this->assertEquals('95d485a14f7431598b81c70e92999745', Func::hash('\nyx\utils\tests\FuncTest::staticCompute', ['arg2']));
93
    }
94
95
    // Func::memoize()
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
96
    public function testMemoize()
97
    {
98
        // Prepare our functions.
99
        $func = function ($arg1, $arg2) {return $arg1.$arg2;};
100
101
        // Without resolver (automatic cache key).
102
        $memoized = Func::memoize($func);
103
104
        $this->assertEquals('foobar', $memoized('foo', 'bar'));
105
        $this->assertNotEquals('barfoo', $memoized('foo', 'bar'));
106
        $this->assertEquals('barfoo', $memoized('bar', 'foo'));
107
        $this->assertNotEquals('foobar', $memoized('bar', 'foo'));
108
109
        // With resolver (key depends on args).
110
        $resolver = function (callable $func, $args) {
111
            return 'key_'.$args[0].$args[1];
112
        };
113
        $memoized = Func::memoize($func, $resolver);
114
115
        $this->assertEquals('foobar', $memoized('foo', 'bar'));
116
        $this->assertNotEquals('barfoo', $memoized('foo', 'bar'));
117
        $this->assertEquals('barfoo', $memoized('bar', 'foo'));
118
        $this->assertNotEquals('foobar', $memoized('bar', 'foo'));
119
120
        // With resolver (fixed key) - all calls should return the first result, regardless of the arguments
121
        // passed, since the result will be fetched from the fixed key.
122
        $resolver = function (callable $func, $args) {return 'key';};
0 ignored issues
show
The parameter $func is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
123
        $memoized = Func::memoize($func, $resolver);
124
125
        $this->assertEquals('foobar', $memoized('foo', 'bar'));
126
        $this->assertEquals('foobar', $memoized('bar', 'foo'));
127
        $this->assertEquals('foobar', $memoized('test', 'omnomnom'));
128
129
        // Same as above but external resolver callable.
130
        $memoized = Func::memoize($func, [$this, 'compute']);
131
132
        $this->assertEquals('foobar', $memoized('foo', 'bar'));
133
        $this->assertEquals('foobar', $memoized('bar', 'foo'));
134
        $this->assertEquals('foobar', $memoized('test', 'omnomnom'));
135
    }
136
137
    // Func::once()
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
138
    public function testOnce()
139
    {
140
        // Prepare our functions.
141
        $func1 = function ($value) {return 'foo'.$value;};
142
        $func2 = function ($value) {return $value.'bar';};
143
144
        // Run some tests.
145
        $wrapper = Func::once($func1);
146
        $this->assertEquals('foobar', $wrapper('bar'));
147
        $this->assertNull($wrapper('bar'));
148
        $this->assertNull($wrapper('baz'));
149
150
        $wrapper = Func::once($func2);
151
        $this->assertEquals('foobar', $wrapper('foo'));
152
        $this->assertNull($wrapper('bar'));
153
        $this->assertNull($wrapper('baz'));
154
    }
155
156
    // Func::once()
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
157
    public function testOnly()
158
    {
159
        // Prepare our functions.
160
        $func1 = function ($value) {return 'foo'.$value;};
161
        $func2 = function ($value) {return $value.'bar';};
162
163
        // Run some tests.
164
        $wrapper = Func::only(3, $func1);
165
        $this->assertEquals('foobar', $wrapper('bar'));
166
        $this->assertEquals('foobaz', $wrapper('baz'));
167
        $this->assertEquals('fooxyz', $wrapper('xyz'));
168
        $this->assertNull($wrapper('bar'));
169
        $this->assertNull($wrapper('baz'));
170
171
        $wrapper = Func::only(2, $func2);
172
        $this->assertEquals('foobar', $wrapper('foo'));
173
        $this->assertEquals('bazbar', $wrapper('baz'));
174
        $this->assertNull($wrapper('bar'));
175
        $this->assertNull($wrapper('baz'));
176
    }
177
178
    // Func::partial()
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
179 View Code Duplication
    public function testPartial()
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
180
    {
181
        // Prepare our function.
182
        $func = function ($val1, $val2, $val3) {return $val1.$val2.$val3;};
183
184
        // Run some tests.
185
        $wrapper = Func::partial($func, 'foo', 'bar');
186
        $this->assertEquals('foobarbaz', $wrapper('baz'));
187
        $this->assertEquals('foobarzeta', $wrapper('zeta'));
188
189
        $wrapper = Func::partial($func, 'hello', ' world');
190
        $this->assertEquals('hello world of doom.', $wrapper(' of doom.'));
191
        $this->assertEquals('hello world of mine.', $wrapper(' of mine.'));
192
    }
193
194
    // Func::partial()
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
195 View Code Duplication
    public function testPartialRight()
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
196
    {
197
        // Prepare our function.
198
        $func = function ($val1, $val2, $val3) {return $val1.$val2.$val3;};
199
200
        // Run some tests.
201
        $wrapper = Func::partialRight($func, 'foo', 'bar');
202
        $this->assertEquals('bazfoobar', $wrapper('baz'));
203
        $this->assertEquals('zetafoobar', $wrapper('zeta'));
204
205
        $wrapper = Func::partialRight($func, 'hello', ' world');
206
        $this->assertEquals(' of doom.hello world', $wrapper(' of doom.'));
207
        $this->assertEquals(' of mine.hello world', $wrapper(' of mine.'));
208
    }
209
210
    // Func::throttle()
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
211
    public function testThrottle()
212
    {
213
        $counter  = 0;
214
        $function = function () use (&$counter) { $counter++; };
215
        $wrapper  = Func::throttle($function, 100);
216
217
        // Time it to invoke the function 5 times at most, even though we call the wrapper 7 times.
218
        $wrapper();
219
        $wrapper();
220
        $wrapper();
221
        usleep(120 * 1000);
222
        $wrapper();
223
        usleep(140 * 1000);
224
        $wrapper();
225
        usleep(220 * 1000);
226
        $wrapper();
227
        usleep(240 * 1000);
228
        $wrapper();
229
        $this->assertEquals(5, $counter, 'function was throttled');
230
231
        usleep(500 * 1000);
232
233
        // Single call.
234
        $counter  = 0;
235
        $function = function () use (&$counter) { $counter++; };
236
        $wrapper  = Func::throttle($function, 100);
237
238
        $wrapper();
239
        usleep(220 * 1000);
240
        $this->assertEquals(1, $counter, 'function called once');
241
242
        usleep(500 * 1000);
243
244
        // Double call.
245
        $counter  = 0;
246
        $function = function () use (&$counter) { $counter++; };
247
        $wrapper  = Func::throttle($function, 100);
248
249
        $wrapper();
250
        $wrapper();
251
        usleep(220 * 1000);
252
        $this->assertEquals(1, $counter, 'function called twice');
253
    }
254
255
    /**
256
     * @see Func::retry()
257
     * ----------------------------------------------------------------------------------------------------------------
258
     */
259
260
    public function testRetryAlwaysSuccessful()
261
    {
262
        $expected = 'foo';
263
        $result   = Func::retry(function () use ($expected) {
264
            return $expected;
265
        });
266
267
        static::assertEquals('foo', $result);
268
    }
269
270
    public function testRetryAlwaysFailing()
271
    {
272
        $this->expectException('InvalidArgumentException');
273
274
        Func::retry(function () {
275
            throw new \InvalidArgumentException;
276
        });
277
    }
278
279
    public function testRetryWithSingleException()
280
    {
281
        $shouldThrow = true;
282
        $result = Func::retry(function () use (&$shouldThrow) {
283
            if ($shouldThrow) {
284
                $shouldThrow = false;
285
                throw new \Exception;
286
            }
287
288
            return 'foo';
289
        });
290
291
        static::assertEquals('foo', $result);
292
    }
293
294
    public function testRetryAttemptsCount()
295
    {
296
        $count = 0;
297
        try {
298
            Func::retry(function () use (&$count) {
299
                $count++;
300
                throw new \Exception;
301
            }, 5);
302
        } catch (\Exception $e) { }
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
303
304
        // We expect to have counted to 6, since we requested 5 retries (+1 initial attempt).
305
        static::assertEquals(6, $count);
306
    }
307
308
    public function testRetryWithDelay()
309
    {
310
        $startTime = microtime(true);
311
312
        try {
313
            Func::retry(function () use (&$count) {
314
                throw new \Exception;
315
            }, 4, 0.25);
316
        } catch (\Exception $e) {
317
            // We expect at least 1 second to have passed (1 initial attempt + 4 retries after 0.25 seconds each).
318
            static::assertGreaterThan(1, (microtime(true) - $startTime));
319
        }
320
    }
321
322
    /**
323
     * @see Func::unless()
324
     * ----------------------------------------------------------------------------------------------------------------
325
     */
326
327 View Code Duplication
    public function testUnless()
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
328
    {
329
        // -- Basic test. No params for the test nor the callable.
330
        $test = function () {
331
            return true === $this->getWhenExists();
332
        };
333
334
        $callable = function () {return 1;};
335
336
        $unless = Func::unless($test, $callable);
337
        $this->setWhenExists(true);
338
        $this->assertNull($unless());
339
        $this->setWhenExists(false);
340
        $this->assertEquals(1, $unless());
341
342
        // -- Params for the callable.
343
        $callable = function ($val) {return $val;};
344
        $unless = Func::unless($test, $callable);
345
        $this->setWhenExists(true);
346
        $this->assertNull($unless('foo'));
347
        $this->setWhenExists(false);
348
        $this->assertEquals('foo', $unless('foo'));
349
350
        // -- Same params for the callable and the test.
351
        $test = function ($bool) {
352
            return $bool === $this->getWhenExists();
353
        };
354
355
        $unless = Func::unless($test, $callable, Func::PASSTHROUGH);
356
        $this->setWhenExists(true);
357
        $this->assertNull($unless(true));
358
        $this->assertFalse($unless(false));
359
        $this->assertEquals('foo', $unless('foo'));
360
        $this->setWhenExists(false);
361
        $this->assertTrue($unless(true));
362
363
        // -- Different params for the callable and the test.
364
        $test = function ($bool) {
365
            return $bool === $this->getWhenExists();
366
        };
367
368
        // Pass 'true' to the test.
369
        $unless = Func::unless($test, $callable, true);
370
        $this->setWhenExists(true);
371
        $this->assertNull($unless('foo'));
372
        $this->assertNull($unless(false));
373
        $this->setWhenExists(false);
374
        $this->assertEquals('foo', $unless('foo'));
375
        $this->assertTrue($unless(true));
376
    }
377
378
    // Func::when()
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
379 View Code Duplication
    public function testWhen()
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
380
    {
381
        // -- Basic test. No params for the test nor the callable.
382
        $test = function () {
383
            return true === $this->getWhenExists();
384
        };
385
386
        $callable = function () {return 1;};
387
        $when = Func::when($test, $callable);
388
        $this->setWhenExists(true);
389
        $this->assertEquals(1, $when());
390
        $this->setWhenExists(false);
391
        $this->assertNull($when());
392
393
        // -- Params for the callable.
394
        $callable = function ($val) {return $val;};
395
        $when = Func::when($test, $callable);
396
        $this->setWhenExists(true);
397
        $this->assertEquals('foo', $when('foo'));
398
        $this->setWhenExists(false);
399
        $this->assertNull($when('foo'));
400
401
        // -- Same params for the callable and the test.
402
        $test = function ($bool) {
403
            return $bool === $this->getWhenExists();
404
        };
405
406
        $when = Func::when($test, $callable, Func::PASSTHROUGH);
407
        $this->setWhenExists(true);
408
        $this->assertTrue($when(true));
409
        $this->assertNull($when(false));
410
        $this->assertNull($when('foo'));
411
        $this->setWhenExists(false);
412
        $this->assertFalse($when(false));
413
414
        // -- Different params for the callable and the test.
415
        $test = function ($bool) {
416
            return $bool === $this->getWhenExists();
417
        };
418
419
        // Pass 'true' to the test.
420
        $when = Func::when($test, $callable, true);
421
        $this->setWhenExists(true);
422
        $this->assertEquals('foo', $when('foo'));
423
        $this->assertFalse($when(false));
424
        $this->setWhenExists(false);
425
        $this->assertNull($when('foo'));
426
        $this->assertNull($when(false));
427
    }
428
429
    // Used by the when/unless tests.
430
    protected function getWhenExists()
431
    {
432
        return $this->whenExists;
433
    }
434
435
    // Used by the when/unless tests.
436
    protected function setWhenExists($exists)
437
    {
438
        $this->whenExists = (bool) $exists;
439
    }
440
441
    // Used by the memoize and hash tests.
442
    public function compute()
443
    {
444
        return 'foobar';
445
    }
446
447
    // Used by the hash tests.
448
    public static function staticCompute()
449
    {
450
        return 'foobar';
451
    }
452
}
453