1<?php
2
3namespace Sabre\VObject;
4
5/**
6 * Tests the cli.
7 *
8 * Warning: these tests are very rudimentary.
9 */
10class CliTest extends \PHPUnit_Framework_TestCase {
11
12    function setUp() {
13
14        $this->cli = new CliMock();
15        $this->cli->stderr = fopen('php://memory', 'r+');
16        $this->cli->stdout = fopen('php://memory', 'r+');
17
18    }
19
20    function testInvalidArg() {
21
22        $this->assertEquals(
23            1,
24            $this->cli->main(['vobject', '--hi'])
25        );
26        rewind($this->cli->stderr);
27        $this->assertTrue(strlen(stream_get_contents($this->cli->stderr)) > 100);
28
29    }
30
31    function testQuiet() {
32
33        $this->assertEquals(
34            1,
35            $this->cli->main(['vobject', '-q'])
36        );
37        $this->assertTrue($this->cli->quiet);
38
39        rewind($this->cli->stderr);
40        $this->assertEquals(0, strlen(stream_get_contents($this->cli->stderr)));
41
42    }
43
44    function testHelp() {
45
46        $this->assertEquals(
47            0,
48            $this->cli->main(['vobject', '-h'])
49        );
50        rewind($this->cli->stderr);
51        $this->assertTrue(strlen(stream_get_contents($this->cli->stderr)) > 100);
52
53    }
54
55    function testFormat() {
56
57        $this->assertEquals(
58            1,
59            $this->cli->main(['vobject', '--format=jcard'])
60        );
61
62        rewind($this->cli->stderr);
63        $this->assertTrue(strlen(stream_get_contents($this->cli->stderr)) > 100);
64
65        $this->assertEquals('jcard', $this->cli->format);
66
67    }
68
69    function testFormatInvalid() {
70
71        $this->assertEquals(
72            1,
73            $this->cli->main(['vobject', '--format=foo'])
74        );
75
76        rewind($this->cli->stderr);
77        $this->assertTrue(strlen(stream_get_contents($this->cli->stderr)) > 100);
78
79        $this->assertNull($this->cli->format);
80
81    }
82
83    function testInputFormatInvalid() {
84
85        $this->assertEquals(
86            1,
87            $this->cli->main(['vobject', '--inputformat=foo'])
88        );
89
90        rewind($this->cli->stderr);
91        $this->assertTrue(strlen(stream_get_contents($this->cli->stderr)) > 100);
92
93        $this->assertNull($this->cli->format);
94
95    }
96
97
98    function testNoInputFile() {
99
100        $this->assertEquals(
101            1,
102            $this->cli->main(['vobject', 'color'])
103        );
104
105        rewind($this->cli->stderr);
106        $this->assertTrue(strlen(stream_get_contents($this->cli->stderr)) > 100);
107
108    }
109
110    function testTooManyArgs() {
111
112        $this->assertEquals(
113            1,
114            $this->cli->main(['vobject', 'color', 'a', 'b', 'c'])
115        );
116
117    }
118
119    function testUnknownCommand() {
120
121        $this->assertEquals(
122            1,
123            $this->cli->main(['vobject', 'foo', '-'])
124        );
125
126    }
127
128    function testConvertJson() {
129
130        $inputStream = fopen('php://memory', 'r+');
131
132        fwrite($inputStream, <<<ICS
133BEGIN:VCARD
134VERSION:3.0
135FN:Cowboy Henk
136END:VCARD
137ICS
138    );
139        rewind($inputStream);
140        $this->cli->stdin = $inputStream;
141
142        $this->assertEquals(
143            0,
144            $this->cli->main(['vobject', 'convert', '--format=json', '-'])
145        );
146
147        rewind($this->cli->stdout);
148        $version = Version::VERSION;
149        $this->assertEquals(
150            '["vcard",[["version",{},"text","4.0"],["prodid",{},"text","-\/\/Sabre\/\/Sabre VObject ' . $version . '\/\/EN"],["fn",{},"text","Cowboy Henk"]]]',
151            stream_get_contents($this->cli->stdout)
152        );
153
154    }
155
156    function testConvertJCardPretty() {
157
158        if (version_compare(PHP_VERSION, '5.4.0') < 0) {
159            $this->markTestSkipped('This test required PHP 5.4.0');
160        }
161
162        $inputStream = fopen('php://memory', 'r+');
163
164        fwrite($inputStream, <<<ICS
165BEGIN:VCARD
166VERSION:3.0
167FN:Cowboy Henk
168END:VCARD
169ICS
170    );
171        rewind($inputStream);
172        $this->cli->stdin = $inputStream;
173
174        $this->assertEquals(
175            0,
176            $this->cli->main(['vobject', 'convert', '--format=jcard', '--pretty', '-'])
177        );
178
179        rewind($this->cli->stdout);
180
181        // PHP 5.5.12 changed the output
182
183        $expected = <<<JCARD
184[
185    "vcard",
186    [
187        [
188            "versi
189JCARD;
190
191          $this->assertStringStartsWith(
192            $expected,
193            stream_get_contents($this->cli->stdout)
194        );
195
196    }
197
198    function testConvertJCalFail() {
199
200        $inputStream = fopen('php://memory', 'r+');
201
202        fwrite($inputStream, <<<ICS
203BEGIN:VCARD
204VERSION:3.0
205FN:Cowboy Henk
206END:VCARD
207ICS
208    );
209        rewind($inputStream);
210        $this->cli->stdin = $inputStream;
211
212        $this->assertEquals(
213            2,
214            $this->cli->main(['vobject', 'convert', '--format=jcal', '--inputformat=mimedir', '-'])
215        );
216
217    }
218
219    function testConvertMimeDir() {
220
221        $inputStream = fopen('php://memory', 'r+');
222
223        fwrite($inputStream, <<<JCARD
224[
225    "vcard",
226    [
227        [
228            "version",
229            {
230
231            },
232            "text",
233            "4.0"
234        ],
235        [
236            "prodid",
237            {
238
239            },
240            "text",
241            "-\/\/Sabre\/\/Sabre VObject 3.1.0\/\/EN"
242        ],
243        [
244            "fn",
245            {
246
247            },
248            "text",
249            "Cowboy Henk"
250        ]
251    ]
252]
253JCARD
254    );
255        rewind($inputStream);
256        $this->cli->stdin = $inputStream;
257
258        $this->assertEquals(
259            0,
260            $this->cli->main(['vobject', 'convert', '--format=mimedir', '--inputformat=json', '--pretty', '-'])
261        );
262
263        rewind($this->cli->stdout);
264        $expected = <<<VCF
265BEGIN:VCARD
266VERSION:4.0
267PRODID:-//Sabre//Sabre VObject 3.1.0//EN
268FN:Cowboy Henk
269END:VCARD
270
271VCF;
272
273          $this->assertEquals(
274            strtr($expected, ["\n" => "\r\n"]),
275            stream_get_contents($this->cli->stdout)
276        );
277
278    }
279
280    function testConvertDefaultFormats() {
281
282        $outputFile = SABRE_TEMPDIR . 'bar.json';
283
284        $this->assertEquals(
285            2,
286            $this->cli->main(['vobject', 'convert', 'foo.json', $outputFile])
287        );
288
289        $this->assertEquals('json', $this->cli->inputFormat);
290        $this->assertEquals('json', $this->cli->format);
291
292    }
293
294    function testConvertDefaultFormats2() {
295
296        $outputFile = SABRE_TEMPDIR . 'bar.ics';
297
298        $this->assertEquals(
299            2,
300            $this->cli->main(['vobject', 'convert', 'foo.ics', $outputFile])
301        );
302
303        $this->assertEquals('mimedir', $this->cli->inputFormat);
304        $this->assertEquals('mimedir', $this->cli->format);
305
306    }
307
308    function testVCard3040() {
309
310        $inputStream = fopen('php://memory', 'r+');
311
312        fwrite($inputStream, <<<VCARD
313BEGIN:VCARD
314VERSION:3.0
315PRODID:-//Sabre//Sabre VObject 3.1.0//EN
316FN:Cowboy Henk
317END:VCARD
318
319VCARD
320    );
321        rewind($inputStream);
322        $this->cli->stdin = $inputStream;
323
324        $this->assertEquals(
325            0,
326            $this->cli->main(['vobject', 'convert', '--format=vcard40', '--pretty', '-'])
327        );
328
329        rewind($this->cli->stdout);
330
331        $version = Version::VERSION;
332        $expected = <<<VCF
333BEGIN:VCARD
334VERSION:4.0
335PRODID:-//Sabre//Sabre VObject $version//EN
336FN:Cowboy Henk
337END:VCARD
338
339VCF;
340
341          $this->assertEquals(
342            strtr($expected, ["\n" => "\r\n"]),
343            stream_get_contents($this->cli->stdout)
344        );
345
346    }
347
348    function testVCard4030() {
349
350        $inputStream = fopen('php://memory', 'r+');
351
352        fwrite($inputStream, <<<VCARD
353BEGIN:VCARD
354VERSION:4.0
355PRODID:-//Sabre//Sabre VObject 3.1.0//EN
356FN:Cowboy Henk
357END:VCARD
358
359VCARD
360    );
361        rewind($inputStream);
362        $this->cli->stdin = $inputStream;
363
364        $this->assertEquals(
365            0,
366            $this->cli->main(['vobject', 'convert', '--format=vcard30', '--pretty', '-'])
367        );
368
369        $version = Version::VERSION;
370
371        rewind($this->cli->stdout);
372        $expected = <<<VCF
373BEGIN:VCARD
374VERSION:3.0
375PRODID:-//Sabre//Sabre VObject $version//EN
376FN:Cowboy Henk
377END:VCARD
378
379VCF;
380
381          $this->assertEquals(
382            strtr($expected, ["\n" => "\r\n"]),
383            stream_get_contents($this->cli->stdout)
384        );
385
386    }
387
388    function testVCard4021() {
389
390        $inputStream = fopen('php://memory', 'r+');
391
392        fwrite($inputStream, <<<VCARD
393BEGIN:VCARD
394VERSION:4.0
395PRODID:-//Sabre//Sabre VObject 3.1.0//EN
396FN:Cowboy Henk
397END:VCARD
398
399VCARD
400    );
401        rewind($inputStream);
402        $this->cli->stdin = $inputStream;
403
404        $this->assertEquals(
405            2,
406            $this->cli->main(['vobject', 'convert', '--format=vcard21', '--pretty', '-'])
407        );
408
409    }
410
411    function testValidate() {
412
413        $inputStream = fopen('php://memory', 'r+');
414
415        fwrite($inputStream, <<<VCARD
416BEGIN:VCARD
417VERSION:4.0
418PRODID:-//Sabre//Sabre VObject 3.1.0//EN
419UID:foo
420FN:Cowboy Henk
421END:VCARD
422
423VCARD
424    );
425        rewind($inputStream);
426        $this->cli->stdin = $inputStream;
427        $result = $this->cli->main(['vobject', 'validate', '-']);
428
429        $this->assertEquals(
430            0,
431            $result
432        );
433
434    }
435
436    function testValidateFail() {
437
438        $inputStream = fopen('php://memory', 'r+');
439
440        fwrite($inputStream, <<<VCARD
441BEGIN:VCALENDAR
442VERSION:2.0
443END:VCARD
444
445VCARD
446    );
447        rewind($inputStream);
448        $this->cli->stdin = $inputStream;
449        // vCard 2.0 is not supported yet, so this returns a failure.
450        $this->assertEquals(
451            2,
452            $this->cli->main(['vobject', 'validate', '-'])
453        );
454
455    }
456
457    function testValidateFail2() {
458
459        $inputStream = fopen('php://memory', 'r+');
460
461        fwrite($inputStream, <<<VCARD
462BEGIN:VCALENDAR
463VERSION:5.0
464END:VCALENDAR
465
466VCARD
467    );
468        rewind($inputStream);
469        $this->cli->stdin = $inputStream;
470
471        $this->assertEquals(
472            2,
473            $this->cli->main(['vobject', 'validate', '-'])
474        );
475
476    }
477
478    function testRepair() {
479
480        $inputStream = fopen('php://memory', 'r+');
481
482        fwrite($inputStream, <<<VCARD
483BEGIN:VCARD
484VERSION:5.0
485END:VCARD
486
487VCARD
488    );
489        rewind($inputStream);
490        $this->cli->stdin = $inputStream;
491
492        $this->assertEquals(
493            2,
494            $this->cli->main(['vobject', 'repair', '-'])
495        );
496
497        rewind($this->cli->stdout);
498        $this->assertRegExp("/^BEGIN:VCARD\r\nVERSION:2.1\r\nUID:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\r\nEND:VCARD\r\n$/", stream_get_contents($this->cli->stdout));
499    }
500
501    function testRepairNothing() {
502
503        $inputStream = fopen('php://memory', 'r+');
504
505        fwrite($inputStream, <<<VCARD
506BEGIN:VCALENDAR
507VERSION:2.0
508PRODID:-//Sabre//Sabre VObject 3.1.0//EN
509BEGIN:VEVENT
510UID:foo
511DTSTAMP:20140122T233226Z
512DTSTART:20140101T120000Z
513END:VEVENT
514END:VCALENDAR
515
516VCARD
517    );
518        rewind($inputStream);
519        $this->cli->stdin = $inputStream;
520
521        $result = $this->cli->main(['vobject', 'repair', '-']);
522
523        rewind($this->cli->stderr);
524        $error = stream_get_contents($this->cli->stderr);
525
526        $this->assertEquals(
527            0,
528            $result,
529            "This should have been error free. stderr output:\n" . $error
530        );
531
532    }
533
534    /**
535     * Note: this is a very shallow test, doesn't dig into the actual output,
536     * but just makes sure there's no errors thrown.
537     *
538     * The colorizer is not a critical component, it's mostly a debugging tool.
539     */
540    function testColorCalendar() {
541
542        $inputStream = fopen('php://memory', 'r+');
543
544        $version = Version::VERSION;
545
546        /**
547         * This object is not valid, but it's designed to hit every part of the
548         * colorizer source.
549         */
550        fwrite($inputStream, <<<VCARD
551BEGIN:VCALENDAR
552VERSION:2.0
553PRODID:-//Sabre//Sabre VObject {$version}//EN
554BEGIN:VTIMEZONE
555END:VTIMEZONE
556BEGIN:VEVENT
557ATTENDEE;RSVP=TRUE:mailto:foo@example.org
558REQUEST-STATUS:5;foo
559ATTACH:blabla
560END:VEVENT
561END:VCALENDAR
562
563VCARD
564    );
565        rewind($inputStream);
566        $this->cli->stdin = $inputStream;
567
568        $result = $this->cli->main(['vobject', 'color', '-']);
569
570        rewind($this->cli->stderr);
571        $error = stream_get_contents($this->cli->stderr);
572
573        $this->assertEquals(
574            0,
575            $result,
576            "This should have been error free. stderr output:\n" . $error
577        );
578
579    }
580
581    /**
582     * Note: this is a very shallow test, doesn't dig into the actual output,
583     * but just makes sure there's no errors thrown.
584     *
585     * The colorizer is not a critical component, it's mostly a debugging tool.
586     */
587    function testColorVCard() {
588
589        $inputStream = fopen('php://memory', 'r+');
590
591        $version = Version::VERSION;
592
593        /**
594         * This object is not valid, but it's designed to hit every part of the
595         * colorizer source.
596         */
597        fwrite($inputStream, <<<VCARD
598BEGIN:VCARD
599VERSION:4.0
600PRODID:-//Sabre//Sabre VObject {$version}//EN
601ADR:1;2;3;4a,4b;5;6
602group.TEL:123454768
603END:VCARD
604
605VCARD
606    );
607        rewind($inputStream);
608        $this->cli->stdin = $inputStream;
609
610        $result = $this->cli->main(['vobject', 'color', '-']);
611
612        rewind($this->cli->stderr);
613        $error = stream_get_contents($this->cli->stderr);
614
615        $this->assertEquals(
616            0,
617            $result,
618            "This should have been error free. stderr output:\n" . $error
619        );
620
621    }
622}
623
624class CliMock extends Cli {
625
626    public $quiet = false;
627
628    public $format;
629
630    public $pretty;
631
632    public $stdin;
633
634    public $stdout;
635
636    public $stderr;
637
638    public $inputFormat;
639
640    public $outputFormat;
641
642}
643