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