Completed
Push — master ( 0b9e95...0208b2 )
by Damian
42s queued 20s
created

ConvertTest::testUpperCamelToLowerCamel()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 36
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 28
nc 1
nop 0
dl 0
loc 36
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\Core\Tests;
4
5
use SilverStripe\Core\Convert;
6
use SilverStripe\Dev\SapphireTest;
7
use SilverStripe\View\Parsers\URLSegmentFilter;
8
use stdClass;
9
use Exception;
10
use InvalidArgumentException;
11
12
/**
13
 * Test various functions on the {@link Convert} class.
14
 */
15
class ConvertTest extends SapphireTest
16
{
17
18
    protected $usesDatabase = false;
19
20
    private $previousLocaleSetting = null;
21
22
    public function setUp()
23
    {
24
        parent::setUp();
25
        // clear the previous locale setting
26
        $this->previousLocaleSetting = null;
27
    }
28
29
    public function tearDown()
30
    {
31
        parent::tearDown();
32
        // If a test sets the locale, reset it on teardown
33
        if ($this->previousLocaleSetting) {
34
            setlocale(LC_CTYPE, $this->previousLocaleSetting);
35
        }
36
    }
37
38
    /**
39
     * Tests {@link Convert::raw2att()}
40
     */
41
    public function testRaw2Att()
42
    {
43
        $val1 = '<input type="text">';
44
        $this->assertEquals(
45
            '&lt;input type=&quot;text&quot;&gt;',
46
            Convert::raw2att($val1),
47
            'Special characters are escaped'
48
        );
49
50
        $val2 = 'This is some normal text.';
51
        $this->assertEquals(
52
            'This is some normal text.',
53
            Convert::raw2att($val2),
54
            'Normal text is not escaped'
55
        );
56
    }
57
58
    /**
59
     * Tests {@link Convert::raw2htmlatt()}
60
     */
61
    public function testRaw2HtmlAtt()
62
    {
63
        $val1 = '<input type="text">';
64
        $this->assertEquals(
65
            '&lt;input type=&quot;text&quot;&gt;',
66
            Convert::raw2htmlatt($val1),
67
            'Special characters are escaped'
68
        );
69
70
        $val2 = 'This is some normal text.';
71
        $this->assertEquals(
72
            'This is some normal text.',
73
            Convert::raw2htmlatt($val2),
74
            'Normal text is not escaped'
75
        );
76
    }
77
78
    /**
79
     * Tests {@link Convert::html2raw()}
80
     */
81
    public function testHtml2raw()
82
    {
83
        $val1 = 'This has a <strong>strong tag</strong>.';
84
        $this->assertEquals(
85
            'This has a *strong tag*.',
86
            Convert::html2raw($val1),
87
            'Strong tags are replaced with asterisks'
88
        );
89
90
        $val1 = 'This has a <b class="test" style="font-weight: bold">b tag with attributes</b>.';
91
        $this->assertEquals(
92
            'This has a *b tag with attributes*.',
93
            Convert::html2raw($val1),
94
            'B tags with attributes are replaced with asterisks'
95
        );
96
97
        $val2 = 'This has a <strong class="test" style="font-weight: bold">strong tag with attributes</STRONG>.';
98
        $this->assertEquals(
99
            'This has a *strong tag with attributes*.',
100
            Convert::html2raw($val2),
101
            'Strong tags with attributes are replaced with asterisks'
102
        );
103
104
        $val3 = '<script type="application/javascript">Some really nasty javascript here</script>';
105
        $this->assertEquals(
106
            '',
107
            Convert::html2raw($val3),
108
            'Script tags are completely removed'
109
        );
110
111
        $val4 = '<style type="text/css">Some really nasty CSS here</style>';
112
        $this->assertEquals(
113
            '',
114
            Convert::html2raw($val4),
115
            'Style tags are completely removed'
116
        );
117
118
        $val5 = "<script type=\"application/javascript\">Some really nasty\nmultiline javascript here</script>";
119
        $this->assertEquals(
120
            '',
121
            Convert::html2raw($val5),
122
            'Multiline script tags are completely removed'
123
        );
124
125
        $val6 = "<style type=\"text/css\">Some really nasty\nmultiline CSS here</style>";
126
        $this->assertEquals(
127
            '',
128
            Convert::html2raw($val6),
129
            'Multiline style tags are completely removed'
130
        );
131
132
        $val7 = '<p>That&#39;s absolutely correct</p>';
133
        $this->assertEquals(
134
            "That's absolutely correct",
135
            Convert::html2raw($val7),
136
            "Single quotes are decoded correctly"
137
        );
138
139
        $val8 = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor '
140
            . 'incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud '
141
            . 'exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute '
142
            . 'irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla '
143
            . 'pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia '
144
            . 'deserunt mollit anim id est laborum.';
145
        $this->assertEquals($val8, Convert::html2raw($val8), 'Test long text is unwrapped');
146
        $this->assertEquals(
147
            <<<PHP
148
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed
149
do eiusmod tempor incididunt ut labore et dolore magna
150
aliqua. Ut enim ad minim veniam, quis nostrud exercitation
151
ullamco laboris nisi ut aliquip ex ea commodo consequat.
152
Duis aute irure dolor in reprehenderit in voluptate velit
153
esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
154
occaecat cupidatat non proident, sunt in culpa qui officia
155
deserunt mollit anim id est laborum.
156
PHP
157
            ,
158
            Convert::html2raw($val8, false, 60),
159
            'Test long text is wrapped'
160
        );
161
    }
162
163
    /**
164
     * Tests {@link Convert::raw2xml()}
165
     */
166
    public function testRaw2Xml()
167
    {
168
        $val1 = '<input type="text">';
169
        $this->assertEquals(
170
            '&lt;input type=&quot;text&quot;&gt;',
171
            Convert::raw2xml($val1),
172
            'Special characters are escaped'
173
        );
174
175
        $val2 = 'This is some normal text.';
176
        $this->assertEquals(
177
            'This is some normal text.',
178
            Convert::raw2xml($val2),
179
            'Normal text is not escaped'
180
        );
181
182
        $val3 = "This is test\nNow on a new line.";
183
        $this->assertEquals(
184
            "This is test\nNow on a new line.",
185
            Convert::raw2xml($val3),
186
            'Newlines are retained. They should not be replaced with <br /> as it is not XML valid'
187
        );
188
    }
189
190
    /**
191
     * Tests {@link Convert::raw2htmlid()}
192
     */
193
    public function testRaw2HtmlID()
194
    {
195
        $val1 = 'test test 123';
196
        $this->assertEquals('test_test_123', Convert::raw2htmlid($val1));
197
198
        $val2 = 'test[test][123]';
199
        $this->assertEquals('test_test_123', Convert::raw2htmlid($val2));
200
201
        $val3 = '[test[[test]][123]]';
202
        $this->assertEquals('test_test_123', Convert::raw2htmlid($val3));
203
204
        $val4 = 'A\\Namespaced\\Class';
205
        $this->assertEquals('A_Namespaced_Class', Convert::raw2htmlid($val4));
206
    }
207
208
    /**
209
     * Tests {@link Convert::xml2raw()}
210
     */
211
    public function testXml2Raw()
212
    {
213
        $val1 = '&lt;input type=&quot;text&quot;&gt;';
214
        $this->assertEquals('<input type="text">', Convert::xml2raw($val1), 'Special characters are escaped');
215
216
        $val2 = 'This is some normal text.';
217
        $this->assertEquals('This is some normal text.', Convert::xml2raw($val2), 'Normal text is not escaped');
218
    }
219
220
    /**
221
     * Tests {@link Convert::xml2raw()}
222
     */
223
    public function testArray2JSON()
224
    {
225
        $val = array(
226
         'Joe' => 'Bloggs',
227
         'Tom' => 'Jones',
228
         'My' => array(
229
          'Complicated' => 'Structure'
230
         )
231
        );
232
        $encoded = Convert::array2json($val);
233
        $this->assertEquals(
234
            '{"Joe":"Bloggs","Tom":"Jones","My":{"Complicated":"Structure"}}',
235
            $encoded,
236
            'Array is encoded in JSON'
237
        );
238
    }
239
240
    /**
241
     * Tests {@link Convert::json2array()}
242
     */
243
    public function testJSON2Array()
244
    {
245
        $val = '{"Joe":"Bloggs","Tom":"Jones","My":{"Complicated":"Structure"}}';
246
        $decoded = Convert::json2array($val);
247
        $this->assertEquals(3, count($decoded), '3 items in the decoded array');
0 ignored issues
show
Bug introduced by
It seems like $decoded can also be of type boolean; however, parameter $var of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

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

247
        $this->assertEquals(3, count(/** @scrutinizer ignore-type */ $decoded), '3 items in the decoded array');
Loading history...
248
        $this->assertContains('Bloggs', $decoded, 'Contains "Bloggs" value in decoded array');
249
        $this->assertContains('Jones', $decoded, 'Contains "Jones" value in decoded array');
250
        $this->assertContains('Structure', $decoded['My']['Complicated']);
251
    }
252
253
    /**
254
     * Tests {@link Convert::testJSON2Obj()}
255
     */
256
    public function testJSON2Obj()
257
    {
258
        $val = '{"Joe":"Bloggs","Tom":"Jones","My":{"Complicated":"Structure"}}';
259
        $obj = Convert::json2obj($val);
260
        $this->assertEquals('Bloggs', $obj->Joe);
261
        $this->assertEquals('Jones', $obj->Tom);
262
        $this->assertEquals('Structure', $obj->My->Complicated);
263
    }
264
265
    /**
266
     * Tests {@link Convert::testRaw2URL()}
267
     *
268
     * @todo test toASCII()
269
     */
270
    public function testRaw2URL()
271
    {
272
        URLSegmentFilter::config()->update('default_allow_multibyte', false);
273
        $this->assertEquals('foo', Convert::raw2url('foo'));
274
        $this->assertEquals('foo-and-bar', Convert::raw2url('foo & bar'));
275
        $this->assertEquals('foo-and-bar', Convert::raw2url('foo &amp; bar!'));
276
        $this->assertEquals('foos-bar-2', Convert::raw2url('foo\'s [bar] (2)'));
277
    }
278
279
    /**
280
     * Helper function for comparing characters with significant whitespaces
281
     *
282
     * @param string $expected
283
     * @param string $actual
284
     */
285
    protected function assertEqualsQuoted($expected, $actual)
286
    {
287
        $message = sprintf(
288
            "Expected \"%s\" but given \"%s\"",
289
            addcslashes($expected, "\r\n"),
290
            addcslashes($actual, "\r\n")
291
        );
292
        $this->assertEquals($expected, $actual, $message);
293
    }
294
295
    /**
296
     * Tests {@link Convert::nl2os()}
297
     */
298
    public function testNL2OS()
299
    {
300
301
        foreach (array("\r\n", "\r", "\n") as $nl) {
302
            // Base case: no action
303
            $this->assertEqualsQuoted(
304
                "Base case",
305
                Convert::nl2os("Base case", $nl)
306
            );
307
308
            // Mixed formats
309
            $this->assertEqualsQuoted(
310
                "Test{$nl}Text{$nl}Is{$nl}{$nl}Here{$nl}.",
311
                Convert::nl2os("Test\rText\r\nIs\n\rHere\r\n.", $nl)
312
            );
313
314
            // Test that multiple runs are non-destructive
315
            $expected = "Test{$nl}Text{$nl}Is{$nl}{$nl}Here{$nl}.";
316
            $this->assertEqualsQuoted(
317
                $expected,
318
                Convert::nl2os($expected, $nl)
319
            );
320
321
            // Check repeated sequence behaves correctly
322
            $expected = "{$nl}{$nl}{$nl}{$nl}{$nl}{$nl}{$nl}{$nl}";
323
            $input = "\r\r\n\r\r\n\n\n\n\r";
324
            $this->assertEqualsQuoted(
325
                $expected,
326
                Convert::nl2os($input, $nl)
327
            );
328
        }
329
    }
330
331
    /**
332
     * Tests {@link Convert::raw2js()}
333
     */
334
    public function testRaw2JS()
335
    {
336
        // Test attempt to break out of string
337
        $this->assertEquals(
338
            '\\"; window.location=\\"http://www.google.com',
339
            Convert::raw2js('"; window.location="http://www.google.com')
340
        );
341
        $this->assertEquals(
342
            '\\\'; window.location=\\\'http://www.google.com',
343
            Convert::raw2js('\'; window.location=\'http://www.google.com')
344
        );
345
        // Test attempt to close script tag
346
        $this->assertEquals(
347
            '\\"; \\x3c/script\\x3e\\x3ch1\\x3eHa \\x26amp; Ha\\x3c/h1\\x3e\\x3cscript\\x3e',
348
            Convert::raw2js('"; </script><h1>Ha &amp; Ha</h1><script>')
349
        );
350
        // Test newlines are properly escaped
351
        $this->assertEquals(
352
            'New\\nLine\\rReturn',
353
            Convert::raw2js("New\nLine\rReturn")
354
        );
355
        // Check escape of slashes
356
        $this->assertEquals(
357
            '\\\\\\"\\x3eClick here',
358
            Convert::raw2js('\\">Click here')
359
        );
360
    }
361
362
    /**
363
     * Tests {@link Convert::raw2json()}
364
     */
365
    public function testRaw2JSON()
366
    {
367
368
        // Test object
369
        $input = new stdClass();
370
        $input->Title = 'My Object';
371
        $input->Content = '<p>Data</p>';
372
        $this->assertEquals(
373
            '{"Title":"My Object","Content":"<p>Data<\/p>"}',
374
            Convert::raw2json($input)
375
        );
376
377
        // Array
378
        $array = array('One' => 'Apple', 'Two' => 'Banana');
379
        $this->assertEquals(
380
            '{"One":"Apple","Two":"Banana"}',
381
            Convert::raw2json($array)
382
        );
383
384
        // String value with already encoded data. Result should be quoted.
385
        $value = '{"Left": "Value"}';
386
        $this->assertEquals(
387
            '"{\\"Left\\": \\"Value\\"}"',
388
            Convert::raw2json($value)
389
        );
390
    }
391
392
    /**
393
     * Test that a context bitmask can be passed through to the json_encode method in {@link Convert::raw2json()}
394
     * and in {@link Convert::array2json()}
395
     */
396
    public function testRaw2JsonWithContext()
397
    {
398
        $data = array('foo' => 'b"ar');
399
        $expected = '{"foo":"b\u0022ar"}';
400
        $result = Convert::raw2json($data, JSON_HEX_QUOT);
401
        $this->assertSame($expected, $result);
402
        $wrapperResult = Convert::array2json($data, JSON_HEX_QUOT);
403
        $this->assertSame($expected, $wrapperResult);
404
    }
405
406
    /**
407
     * Tests {@link Convert::xml2array()}
408
     */
409
    public function testXML2Array()
410
    {
411
        // Ensure an XML file at risk of entity expansion can be avoided safely
412
        $inputXML = <<<XML
413
<?xml version="1.0"?>
414
<!DOCTYPE results [<!ENTITY long "SOME_SUPER_LONG_STRING">]>
415
<results>
416
    <result>Now include &long; lots of times to expand the in-memory size of this XML structure</result>
417
    <result>&long;&long;&long;</result>
418
</results>
419
XML
420
         ;
421
        try {
422
            Convert::xml2array($inputXML, true);
423
        } catch (Exception $ex) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
424
        }
425
        $this->assertTrue(
426
            isset($ex)
427
            && $ex instanceof InvalidArgumentException
428
            && $ex->getMessage() === 'XML Doctype parsing disabled'
429
        );
430
431
        // Test without doctype validation
432
        $expected = array(
433
         'result' => array(
434
          "Now include SOME_SUPER_LONG_STRING lots of times to expand the in-memory size of this XML structure",
435
          array(
436
        'long' => array(
437
         array(
438
          'long' => 'SOME_SUPER_LONG_STRING'
439
         ),
440
         array(
441
          'long' => 'SOME_SUPER_LONG_STRING'
442
         ),
443
         array(
444
          'long' => 'SOME_SUPER_LONG_STRING'
445
         )
446
           )
447
          )
448
         )
449
        );
450
        $result = Convert::xml2array($inputXML, false, true);
451
        $this->assertEquals(
452
            $expected,
453
            $result
454
        );
455
        $result = Convert::xml2array($inputXML, false, false);
456
        $this->assertEquals(
457
            $expected,
458
            $result
459
        );
460
    }
461
462
    /**
463
     * Tests {@link Convert::base64url_encode()} and {@link Convert::base64url_decode()}
464
     */
465
    public function testBase64url()
466
    {
467
        $data = 'Wëīrð characters ☺ such as ¤Ø¶÷╬';
468
        // This requires this test file to have UTF-8 character encoding
469
        $this->assertEquals(
470
            $data,
471
            Convert::base64url_decode(Convert::base64url_encode($data))
472
        );
473
474
        $data = 654.423;
475
        $this->assertEquals(
476
            $data,
477
            Convert::base64url_decode(Convert::base64url_encode($data))
478
        );
479
480
        $data = true;
481
        $this->assertEquals(
482
            $data,
483
            Convert::base64url_decode(Convert::base64url_encode($data))
484
        );
485
486
        $data = array('simple','array','¤Ø¶÷╬');
487
        $this->assertEquals(
488
            $data,
489
            Convert::base64url_decode(Convert::base64url_encode($data))
490
        );
491
492
        $data = array(
493
         'a'  => 'associative',
494
         4    => 'array',
495
         '☺' => '¤Ø¶÷╬'
496
        );
497
        $this->assertEquals(
498
            $data,
499
            Convert::base64url_decode(Convert::base64url_encode($data))
500
        );
501
    }
502
503
    public function testValidUtf8()
504
    {
505
        // Install a UTF-8 locale
506
        $this->previousLocaleSetting = setlocale(LC_CTYPE, 0);
507
508
        $locales = array('en_US.UTF-8', 'en_NZ.UTF-8', 'de_DE.UTF-8');
509
        $localeInstalled = false;
510
        foreach ($locales as $locale) {
511
            if ($localeInstalled = setlocale(LC_CTYPE, $locale)) {
512
                break;
513
            }
514
        }
515
516
        // If the system doesn't have any of the UTF-8 locales, exit early
517
        if ($localeInstalled === false) {
518
            $this->markTestIncomplete('Unable to run this test because of missing locale!');
519
            return;
520
        }
521
522
        $problematicText = html_entity_decode(
523
            '<p>This is a&nbsp;Test with non-breaking&nbsp;space!</p>',
524
            ENT_COMPAT,
525
            'UTF-8'
526
        );
527
528
        $this->assertTrue(mb_check_encoding(Convert::html2raw($problematicText), 'UTF-8'));
529
    }
530
531
    public function testUpperCamelToLowerCamel()
532
    {
533
        $this->assertEquals(
534
            'd',
535
            Convert::upperCamelToLowerCamel('D'),
536
            'Single character'
537
        );
538
        $this->assertEquals(
539
            'id',
540
            Convert::upperCamelToLowerCamel('ID'),
541
            'Multi leading upper without trailing lower'
542
        );
543
        $this->assertEquals(
544
            'id',
545
            Convert::upperCamelToLowerCamel('Id'),
546
            'Single leading upper with trailing lower'
547
        );
548
        $this->assertEquals(
549
            'idField',
550
            Convert::upperCamelToLowerCamel('IdField'),
551
            'Single leading upper with trailing upper camel'
552
        );
553
        $this->assertEquals(
554
            'idField',
555
            Convert::upperCamelToLowerCamel('IDField'),
556
            'Multi leading upper with trailing upper camel'
557
        );
558
        $this->assertEquals(
559
            'iDField',
560
            Convert::upperCamelToLowerCamel('iDField'),
561
            'Single leading lower with trailing upper camel'
562
        );
563
        $this->assertEquals(
564
            '_IDField',
565
            Convert::upperCamelToLowerCamel('_IDField'),
566
            'Non-alpha leading  with trailing upper camel'
567
        );
568
    }
569
570
    /**
571
     * Test that memstring2bytes returns the number of bytes for a PHP ini style size declaration
572
     *
573
     * @param string $memString
574
     * @param int    $expected
575
     * @dataProvider memString2BytesProvider
576
     */
577
    public function testMemString2Bytes($memString, $expected)
578
    {
579
        $this->assertSame($expected, Convert::memstring2bytes($memString));
580
    }
581
582
    /**
583
     * @return array
584
     */
585
    public function memString2BytesProvider()
586
    {
587
        return [
588
            ['2048', (float)(2 * 1024)],
589
            ['2k', (float)(2 * 1024)],
590
            ['512M', (float)(512 * 1024 * 1024)],
591
            ['512MiB', (float)(512 * 1024 * 1024)],
592
            ['512 mbytes', (float)(512 * 1024 * 1024)],
593
            ['512 megabytes', (float)(512 * 1024 * 1024)],
594
            ['1024g', (float)(1024 * 1024 * 1024 * 1024)],
595
            ['1024G', (float)(1024 * 1024 * 1024 * 1024)]
596
        ];
597
    }
598
599
    /**
600
     * Test that bytes2memstring returns a binary prefixed string representing the number of bytes
601
     *
602
     * @param string $bytes
603
     * @param int    $expected
604
     * @dataProvider bytes2MemStringProvider
605
     */
606
    public function testBytes2MemString($bytes, $expected)
607
    {
608
        $this->assertSame($expected, Convert::bytes2memstring($bytes));
0 ignored issues
show
Bug introduced by
$bytes of type string is incompatible with the type double expected by parameter $bytes of SilverStripe\Core\Convert::bytes2memstring(). ( Ignorable by Annotation )

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

608
        $this->assertSame($expected, Convert::bytes2memstring(/** @scrutinizer ignore-type */ $bytes));
Loading history...
609
    }
610
611
    /**
612
     * @return array
613
     */
614
    public function bytes2MemStringProvider()
615
    {
616
        return [
617
            [200, '200B'],
618
            [(2 * 1024), '2K'],
619
            [(512 * 1024 * 1024), '512M'],
620
            [(512 * 1024 * 1024 * 1024), '512G'],
621
            [(512 * 1024 * 1024 * 1024 * 1024), '512T'],
622
            [(512 * 1024 * 1024 * 1024 * 1024 * 1024), '512P']
623
        ];
624
    }
625
626
    public function providerTestSlashes()
627
    {
628
        return [
629
            ['bob/bob', '/', true, 'bob/bob'],
630
            ['\\bob/bob\\', '/', true, '/bob/bob/'],
631
            ['\\bob////bob\\/', '/', true, '/bob/bob/'],
632
            ['bob/bob', '\\', true, 'bob\\bob'],
633
            ['\\bob/bob\\', '\\', true, '\\bob\\bob\\'],
634
            ['\\bob////bob\\/', '\\', true, '\\bob\\bob\\'],
635
            ['bob/bob', '#', true, 'bob#bob'],
636
            ['\\bob/bob\\', '#', true, '#bob#bob#'],
637
            ['\\bob////bob\\/', '#', true, '#bob#bob#'],
638
            ['bob/bob', '/', false, 'bob/bob'],
639
            ['\\bob/bob\\', '/', false, '/bob/bob/'],
640
            ['\\bob////bob\\/', '/', false, '/bob////bob//'],
641
            ['bob/bob', '\\', false, 'bob\\bob'],
642
            ['\\bob/bob\\', '\\', false, '\\bob\\bob\\'],
643
            ['\\bob////bob\\/', '\\', false, '\\bob\\\\\\\\bob\\\\'],
644
            ['bob/bob', '#', false, 'bob#bob'],
645
            ['\\bob/bob\\', '#', false, '#bob#bob#'],
646
            ['\\bob////bob\\/', '#', false, '#bob####bob##'],
647
        ];
648
    }
649
650
    /**
651
     * @dataProvider providerTestSlashes
652
     * @param string $path
653
     * @param string $separator
654
     * @param bool $multiple
655
     * @param string $expected
656
     */
657
    public function testSlashes($path, $separator, $multiple, $expected)
658
    {
659
        $this->assertEquals($expected, Convert::slashes($path, $separator, $multiple));
660
    }
661
}
662