]> Pileus Git - ~andy/lamechat/blob - test.sh
10d5057189476e920cb5666d84c7c26e2b08d149
[~andy/lamechat] / test.sh
1 #!/bin/bash
2
3 # Test View
4 test_view_empty() {
5         setup
6         output <<-EOF
7                 | No Topic
8                 |
9                 |00:00 *** Welcome to lamechat!
10                 | Windows: [system]
11                 |[system]
12         EOF
13 }
14
15 test_view_wrap() {
16         setup
17         resize 5 24
18         output <<-EOF
19                 | No Topic
20                 |00:00 *** Welcome to
21                 |          lamechat!
22                 | Windows: [system]
23                 |[system]
24         EOF
25         resize 5 80
26         output <<-EOF
27                 | No Topic
28                 |
29                 |00:00 *** Welcome to lamechat!
30                 | Windows: [system]
31                 |[system]
32         EOF
33 }
34
35 test_view_scroll() {
36         setup -c -s 6667 <<-EOF
37                 [server "localhost"]
38                     protocol = irc
39                     connect  = true
40                 [window "localhost"]
41                     server   = "localhost"
42         EOF
43         resize 7 50
44         server 6667 <<-EOF
45                 < NOTICE andy :one
46                 < NOTICE andy :two
47                 < NOTICE andy :three
48                 < NOTICE andy :four
49                 < NOTICE andy :five
50                 < NOTICE andy :six
51         EOF
52         sleep 0.05
53         output <<-EOF
54                 | No Topic
55                 |00:00 [localhost] *** three
56                 |00:00 [localhost] *** four
57                 |00:00 [localhost] *** five
58                 |00:00 [localhost] *** six
59                 | Windows: [localhost]
60                 |[system]
61         EOF
62         input -c y
63         output -i <<-EOF
64                 |00:00 [localhost] *** two
65                 |00:00 [localhost] *** five
66         EOF
67         input -c e
68         output -i <<-EOF
69                 |00:00 [localhost] *** three
70                 |00:00 [localhost] *** six
71         EOF
72         input -c u
73         output -i <<-EOF
74                 |00:00 [localhost] *** one
75                 |00:00 [localhost] *** four
76         EOF
77         input -c d
78         output -i <<-EOF
79                 |00:00 [localhost] *** three
80                 |00:00 [localhost] *** six
81         EOF
82 }
83
84 test_view_color() {
85         setup -c -s 6667 <<-EOF
86                 [server "local"]
87                     protocol = irc
88                     connect  = true
89                     host     = "localhost"
90                 [window "system"]
91                     filter   = "local|#.*"
92         EOF
93         server 6667 <<-EOF
94                 < NOTICE andy :Welcome to lame server!
95
96                 < NOTICE andy :$(color 002)bold$(color 017)
97                 < NOTICE andy :$(color 011)italic$(color 017)
98                 < NOTICE andy :$(color 023)uline$(color 017)
99                 < NOTICE andy :$(color 025)uline$(color 017)
100                 < NOTICE andy :$(color 037)uline$(color 017)
101                 < NOTICE andy :$(color 026)rev$(color 017)
102
103                 < NOTICE andy :$(color 003)01 fg,--$(color 017)
104                 < NOTICE andy :$(color 003)2 fg,--$(color 017)
105                 < NOTICE andy :$(color 003)3,fg,--$(color 017)
106                 < NOTICE andy :$(color 003),4 --,bg$(color 017)
107                 < NOTICE andy :$(color 003)5,6 fg,bg$(color 017)
108         EOF
109
110         input /theme dark   && sleep 0.01
111         input /theme light  && sleep 0.01
112         input /theme normal && sleep 0.01
113
114         output -i <<-EOF
115                 |00:00 [local] *** Welcome to lame server!
116                 |00:00 [local] *** bold
117                 |00:00 [local] *** italic
118                 |00:00 [local] *** uline
119                 |00:00 [local] *** uline
120                 |00:00 [local] *** uline
121                 |00:00 [local] *** rev
122                 |00:00 [local] ***  fg,--
123                 |00:00 [local] ***  fg,--
124                 |00:00 [local] *** ,fg,--
125                 |00:00 [local] ***  --,bg
126                 |00:00 [local] ***  fg,bg
127         EOF
128 }
129
130 test_view_window() {
131         setup -c -s 6667 <<-EOF
132                 [server "local"]
133                     protocol = irc
134                     connect  = true
135                     host     = "localhost"
136                 [window "local"]
137                     filter   = "local"
138                 [window "users"]
139                     filter   = "user.*"
140         EOF
141         server 6667 <<-EOF
142                 > CAP REQ *
143                 < CAP NAK
144                 < :lamechat 001 andy :Welcome to lame server!
145                 < :user1 PRIVMSG andy :hello 1
146                 < :user2 PRIVMSG andy :hello 2
147         EOF
148         sleep 0.05
149         input -c n
150         input -c n
151         input -c x
152         input -c x
153         output -i <<-EOF
154                 |00:00 [user1] user1: hello 1
155                 |00:00 [user2] user2: hello 2
156                 | Windows: [local] [users]
157                 |[user2]
158         EOF
159
160         input -c x
161         input -c p
162         input -c p
163         input -c l
164         input -c g
165         output -i <<-EOF
166                 |[system]
167         EOF
168 }
169
170 # Test IRC
171 test_irc_basic() {
172         setup -c -s 6667 <<-EOF
173                 [server "local"]
174                     protocol = irc
175                     connect  = true
176                     host     = "localhost"
177                     nick     = "andy"
178                 [channel "#test"]
179                     server   = "local"
180                     join     = true
181                 [window "system"]
182                     filter   = "local|#.*"
183         EOF
184         server 6667 <<-EOF
185                 > CAP REQ :tls
186                 < CAP NAK
187                 > CAP END
188                 > USER *
189                 > NICK *
190                 < :lamechat 001 andy :Welcome to lamechat!
191                 > JOIN #test
192                 > TOPIC #test
193                 > WHO #test
194         EOF
195 }
196
197 test_irc_connect() {
198         test_irc_basic
199         output -i <<-EOF
200                 |00:00 [local] *** Joining Server: local
201                 |00:00 [local] *** Start TLS unsupported
202                 |00:00 [#test] *** Joining Channel: #test
203                 |00:00 [local] *** Welcome to lamechat!
204         EOF
205 }
206
207 test_irc_unauth() {
208         setup -c -x 6697 <<-EOF
209                 [server "serv"]
210                     protocol = irc
211                     connect  = true
212                     noverify = true
213                     host     = "localhost"
214                     tls      = true
215                     nick     = "andy"
216                 [window "system"]
217                     filter   = "serv"
218         EOF
219         server 6697 <<-EOF
220                 > CAP REQ :sasl
221                 < CAP ACK
222                 > AUTHENTICATE PLAIN
223                 > AUTHENTICATE *
224                 < 904 :Authentication Failed.
225         EOF
226         output -i <<-EOF
227                 |00:00 [serv] *** SASL auth proceeding
228                 |00:00 [serv] *** SASL auth failed
229         EOF
230 }
231
232 test_irc_dropped() {
233         test_irc_basic
234         kill -INT ${PIDS[0]}
235         PIDS=("${PIDS[1]}")
236         output -i <<-EOF
237                 |00:00 [local] *** Welcome to lamechat!
238                 |00:00 [local] *** Server disconnected
239         EOF
240 }
241
242 test_irc_reconnect() {
243         setup -c -s 6667 <<-EOF
244                 [server "local"]
245                     protocol  = irc
246                     connect   = true
247                     reconnect = -10000000
248                     host      = "localhost"
249                     nick      = "andy"
250                 [window "system"]
251                     filter   = "local|#.*"
252         EOF
253         server 6667 <<-EOF
254                 > CAP REQ :tls
255                 < CAP NAK
256                 > CAP END
257                 > USER *
258                 > NICK *
259                 < :lamechat 001 andy :Welcome to lamechat!
260                 < PING
261                 > PING
262         EOF
263         kill -INT ${PIDS[0]}
264         PIDS=("${PIDS[1]}")
265         listen tcp 6667
266         server 6667 <<-EOF
267                 > CAP REQ :tls
268         EOF
269         output -i <<-EOF
270                 |00:00 [local] *** Joining Server: local
271                 |00:00 [local] *** Welcome to lamechat!
272                 |00:00 [local] *** Server disconnected
273                 |00:00 [local] *** Reconnecting: local
274                 |00:00 [local] *** Joining Server: local
275         EOF
276 }
277
278 test_irc_servers() {
279         setup -c -s 6001 -s 6002 <<-EOF
280                 [server "xmpp"]
281                     protocol = xmpp
282                     jid      = "andy@local/lame"
283                 [server "serv1"]
284                     protocol = irc
285                     connect  = true
286                     host     = "localhost"
287                     port     = 6001
288                     nick     = "andy1"
289                 [server "serv2"]
290                     protocol = irc
291                     connect  = true
292                     host     = "localhost"
293                     port     = 6002
294                     nick     = "andy2"
295                 [channel "#xmpp"]
296                     server   = "xmpp"
297                 [channel "#chan1"]
298                     server   = "serv1"
299                     join     = true
300                 [channel "#chan2"]
301                     server   = "serv2"
302                     join     = true
303                 [window "system"]
304                     filter   = "serv.|#chan."
305         EOF
306         server 6001 <<-EOF
307                 > CAP REQ :tls
308                 < CAP NAK
309                 > CAP END
310                 > USER *
311                 > NICK andy1
312                 < :lamechat 001 andy1 :Welcome to lamechat 1!
313                 > JOIN #chan1
314                 > TOPIC #chan1
315                 > WHO #chan1
316         EOF
317         server 6002 <<-EOF
318                 > CAP REQ :tls
319                 < CAP NAK
320                 > CAP END
321                 > USER *
322                 > NICK andy2
323                 < :lamechat 001 andy2 :Welcome to lamechat 2!
324                 > JOIN #chan2
325                 > TOPIC #chan2
326                 > WHO #chan2
327         EOF
328         server 6001 <<-EOF
329                 < :alice1 PRIVMSG #chan1 :hello, here 1!
330                 < :bob1 PRIVMSG #other1 :hello, there 1!
331         EOF
332         server 6002 <<-EOF
333                 < :alice2 PRIVMSG #chan2 :hello, here 2!
334                 < :bob2 PRIVMSG #other2 :hello, there 2!
335         EOF
336         output -i <<-EOF
337                 |00:00 [serv1] *** Joining Server: serv1
338                 |00:00 [serv2] *** Joining Server: serv2
339                 |00:00 [serv1] *** Welcome to lamechat 1!
340                 |00:00 [serv2] *** Welcome to lamechat 2!
341                 |00:00 [#chan1] alice1: hello, here 1!
342                 |00:00 [#chan2] alice2: hello, here 2!
343                 | Windows: [system] [#other1] [#other2]
344         EOF
345 }
346
347 test_irc_openssl() {
348         setup -c -x 6697 <<-EOF
349                 [server "local"]
350                     protocol = irc
351                     connect  = true
352                     noverify = true
353                     host     = "localhost"
354                     tls      = true
355                     nick     = "andy"
356                 [window "system"]
357                     filter   = "local"
358         EOF
359         server 6697 <<-EOF
360                 > CAP REQ :sasl
361                 < CAP NAK
362                 > CAP END
363                 > USER *
364                 > NICK *
365                 < :lamechat 001 andy :Welcome to lamechat!
366         EOF
367         output -i <<-EOF
368                 |00:00 [local] *** SASL auth unsupported
369                 |00:00 [local] *** Welcome to lamechat!
370         EOF
371 }
372
373 test_irc_startls() {
374         setup -c -s 6667 <<-EOF
375                 [server "local"]
376                     protocol = irc
377                     connect  = true
378                     noverify = true
379                     host     = "localhost"
380                     nick     = "andy"
381                 [window "system"]
382                     filter   = "local"
383         EOF
384         server 6667 <<-EOF
385                 > CAP REQ :tls
386                 < CAP ACK
387                 > STARTTLS
388                 < :lamechat 607 andy :STARTTLS successful
389         EOF
390         output -i <<-EOF
391                 |00:00 [local] *** Start TLS proceeding
392         EOF
393 }
394
395 test_irc_timeout() {
396         setup -c -s 6667 <<-EOF
397                 [server "local"]
398                     protocol = irc
399                     connect  = true
400                     timeout  = -10000000
401                     host     = "localhost"
402                     nick     = "andy"
403         EOF
404         server 6667 <<-EOF
405                 > CAP REQ :tls
406                 < CAP NAK
407                 > CAP END
408                 > USER *
409                 > NICK *
410                 < :lamechat 001 andy :Welcome to lamechat!
411                 > PING localhost
412         EOF
413 }
414
415 test_irc_options() {
416         unset USER
417         setup -c -x 12345 <<-EOF
418                 [server "serv"]
419                     protocol = irc
420                     connect  = true
421                     noverify = true
422                     host     = "localhost"
423                     port     = 12345
424                     tls      = true
425                     auth     = "ali"
426                     pass     = "opensesame"
427                 [channel "chan"]
428                     server   = "serv"
429                     dest     = "#test"
430                     join     = true
431                 [window "system"]
432                     filter   = "serv|chan"
433         EOF
434         server 12345 <<-EOF
435                 > CAP REQ :sasl
436                 < CAP ACK
437                 > AUTHENTICATE PLAIN
438                 > AUTHENTICATE $(echo -n ali ali opensesame |
439                                  tr ' ' '\0' | base64)
440                 < 903 :Authentication Successful.
441                 > CAP END
442                 > USER *
443                 > NICK lameuser
444                 < :lamechat 001 andy :Welcome to lamechat!
445                 < :bob PRIVMSG #test :hello, there!
446         EOF
447         output -i <<-EOF
448                 |00:00 [serv] *** Joining Server: serv
449                 |00:00 [serv] *** SASL auth proceeding
450                 |00:00 [serv] *** SASL auth succeeded
451                 |00:00 [chan] bob: hello, there!
452         EOF
453 }
454
455 test_irc_message() {
456         test_irc_basic
457
458         input /filter "system"
459         server 6667 <<-EOF
460                 < :alice PRIVMSG #test :hello, here!
461                 < :bob PRIVMSG #other :hello, there!
462                 < :eve PRIVMSG andy :hello, where?
463                 < :eve PRIVMSG andy :hello, everywhere
464         EOF
465         input /filter "#.*|eve"
466
467         output -i <<-EOF
468                 |00:00 [#test] alice: hello, here!
469                 |00:00 [#other] bob: hello, there!
470                 |00:00 [eve] eve: hello, where?
471                 |00:00 [eve] eve: hello, everywhere
472                 | Windows: [system] [#test] [#other] [eve:1]
473         EOF
474 }
475
476 test_irc_topic() {
477         test_irc_basic
478         input -c x
479         input -c x
480
481         server 6667 <<-EOF
482                 < :bob 353 andy @ #test :alice bob
483                 < :bob 331 #test #test :First Topic!
484                 < :bob 332 #test #test :Second Topic!
485                 < :bob TOPIC #test #test :Third Topic!
486         EOF
487         output -i <<-EOF
488                 | Third Topic!
489                 |00:00 [#test] *** Members: alice bob
490                 |00:00 [#test] *** Topic: First Topic!
491                 |00:00 [#test] *** Topic: Second Topic!
492                 |00:00 [#test] *** Topic changed to Third Topic!
493         EOF
494 }
495
496 test_irc_send() {
497         test_irc_basic
498         input /filter '#test'
499         input -c x
500         input -c x
501         input -n "hello bob!\n"
502         input -n "hello ali"
503
504         server 6667 <<-EOF
505                 > PRIVMSG #test :hello bob!
506                 < PING
507                 > PING
508         EOF
509         output -i <<-EOF
510                 |00:00 [#test] *** Joining Channel: #test
511                 |00:00 [#test] andy: hello bob!
512                 | Windows: [system]
513                 |[#test] hello ali
514         EOF
515 }
516
517 test_irc_commands() {
518         setup -c -s 6667 <<-EOF
519                 [server "local"]
520                     protocol = irc
521                     connect  = true
522                     host     = "localhost"
523                     nick     = "andy"
524                 [window "system"]
525                     filter   = "local|alice|#.*"
526         EOF
527         server 6667 <<-EOF
528                 > CAP REQ :tls
529                 < CAP NAK
530                 > CAP END
531                 > USER *
532                 > NICK *
533                 < :lamechat 001 andy :Welcome to lamechat!
534         EOF
535
536         input -c x
537         input hello local
538
539         input /join
540         input /join '#test'
541         input -c x
542         input hello '#test'
543         input /part '#test'
544         input /join
545         input /part
546
547         input /query
548         input /query alice
549         input -c x
550         input hello alice
551
552         input /kill_all_humans
553
554         output -i <<-EOF
555                 |00:00 [local] *** Cannot send to server
556                 |00:00 [#test] *** Joining Channel: #test
557                 |00:00 [#test] andy: hello #test
558                 |00:00 [#test] *** Leaving Channel: #test
559                 |00:00 [#test] *** Joining Channel: #test
560                 |00:00 [#test] *** usage: /query <user>
561                 |00:00 [alice] *** User: alice
562                 |00:00 [alice] andy: hello alice
563                 |00:00 [alice] *** Unknown command /kill_all_humans
564         EOF
565 }
566
567 # Test XMPP
568 test_xmpp_basic() {
569         setup -c -s 5222 <<-EOF
570                 [server "local"]
571                     protocol = xmpp
572                     connect  = true
573                     jid      = "andy@localhost/lamechat"
574                     muc      = "conf.local"
575                 [channel "test"]
576                     server   = "local"
577                     join     = true
578                 [window "system"]
579                     filter   = "local|info|test|other|alice|bob|Adelais|Robert"
580         EOF
581         server 5222 <<-EOF
582                 > <?xml version='1.0'?>
583                 > <stream:stream from='andy@localhost/lamechat'*>
584                 < <stream:stream to="andy@localhost/lamechat" from="localhost">
585         EOF
586 }
587
588 test_xmpp_dropped() {
589         test_xmpp_basic
590         server 5222 <<-EOF
591                 < <stream:error>
592                 <     <text>We don't serve your kind here!</text>
593                 < </stream:error>
594         EOF
595         sleep 0.01
596         kill -INT ${PIDS[0]}
597         PIDS=("${PIDS[1]}")
598         output -i <<-EOF
599                 |00:00 [local] *** XMPP Server: local
600                 |00:00 [local] *** error: We don't serve your kind here!
601                 |00:00 [local] *** Server disconnected
602         EOF
603 }
604
605 test_xmpp_errors() {
606         setup -c <<-EOF
607                 [server "local"]
608                     protocol = xmpp
609                     connect  = true
610         EOF
611         output -e -i <<-EOF
612                 |0.000: error: jid is required
613         EOF
614         quit
615
616         preload <<-EOF
617                 int timerfd_create() { return -1; }
618         EOF
619         setup -c <<-EOF
620                 [server "local"]
621                     protocol = xmpp
622                     connect  = true
623                     jid      = "andy@localhost/lamechat"
624         EOF
625         output -e -i <<-EOF
626                 |0.000: error: creating timer fd
627         EOF
628         quit
629
630         preload <<-EOF
631                 void *XML_ParserCreate() { return 0; }
632         EOF
633         setup -c <<-EOF
634                 [server "local"]
635                     protocol = xmpp
636                     connect  = true
637                     jid      = "andy@localhost/lamechat"
638         EOF
639         output -e -i <<-EOF
640                 |0.000: error: creating XML parser
641         EOF
642         quit
643
644         preload <<-EOF
645                 int XML_ParserReset() { return 0; }
646         EOF
647         test_xmpp_starttls
648         output -e -i <<-EOF
649                 |0.000: error: resetting XML parser
650         EOF
651         quit
652
653         preload <<-EOF
654                 int XML_ParserReset() { return 0; }
655         EOF
656         test_xmpp_basic
657         server 5222 <<-EOF
658                 < <stream:features>
659                 <     <mechanisms/>
660                 < </stream:features>
661                 > <auth xmlns='*:xmpp-sasl' mechanism='PLAIN'>*</auth>
662                 < <success/>
663         EOF
664         output -e -i <<-EOF
665                 |0.000: error: resetting XML parser
666         EOF
667 }
668
669 test_xmpp_timeout() {
670         setup -c -s 5222 <<-EOF
671                 [server "local"]
672                     protocol = xmpp
673                     connect  = true
674                     timeout  = -10000000
675                     jid      = "andy@localhost/lamechat"
676         EOF
677         server 5222 <<-EOF
678                 > <?xml*?>
679                 > <stream:stream*>
680                 > $(echo -ne " ")
681         EOF
682 }
683
684 test_xmpp_options() {
685         setup -c -s 5000 <<-EOF
686                 [server "local"]
687                     protocol = xmpp
688                     connect  = true
689                     timeout  = 10
690                     noverify = true
691                     host     = localhost
692                     port     = 5000
693                     srv      = "srv@local"
694                     nick     = "Andy"
695                     jid      = "andy@local.host/lamechat"
696                     user     = "ali"
697                     pass     = "opensesame"
698                     quiet    = true
699                 [channel "test"]
700                     server   = "local"
701                     room     = "test@local"
702                     join     = true
703                 [channel "other"]
704                     server   = "local"
705                     join     = false
706                 [window "system"]
707                     filter   = "local|test"
708         EOF
709         server 5000 <<-EOF
710                 > <?xml*?>
711                 > <stream:stream*>
712                 < <stream:stream>
713                 < <stream:features><bind/></stream:features>
714
715                 > <iq*><bind*><resource>lamechat</resource></bind></iq>
716                 < <jid>foo</jid>
717
718                 > <iq*><session*/></iq>
719                 > <presence/>
720                 > <presence*><*/></presence>
721                 < <presence id="join" from="test@localhost/andy"/>
722                 < <presence id="join" from="test@localhost/bob"/>
723         EOF
724         output <<-EOF
725                 | No Topic
726                 |
727                 | Windows: [system]
728                 |[system]
729         EOF
730 }
731
732 test_xmpp_starttls() {
733         test_xmpp_basic
734         server 5222 <<-EOF
735                 < <stream:features>
736                 <     <starttls/>
737                 < </stream:features>
738                 > <starttls xmlns='*:xmpp-tls'/>
739                 < <proceed/>
740         EOF
741 }
742
743 test_xmpp_auth() {
744         test_xmpp_basic
745         server 5222 <<-EOF
746                 < <stream:features>
747                 <     <mechanisms/>
748                 < </stream:features>
749                 > <auth xmlns='*:xmpp-sasl' mechanism='PLAIN'>*</auth>
750                 < <success/>
751
752                 > <?xml version='1.0'?>
753                 > <stream:stream from='andy@localhost/lamechat'*>
754                 < <stream:stream to="andy@localhost/lamechat" from="localhost">
755         EOF
756         output -i <<-EOF
757                 |00:00 [local] *** Authentication success
758         EOF
759 }
760
761 test_xmpp_unauth() {
762         test_xmpp_basic
763         server 5222 <<-EOF
764                 < <stream:features>
765                 <     <mechanisms/>
766                 < </stream:features>
767                 > <auth xmlns='*:xmpp-sasl' mechanism='PLAIN'>*</auth>
768                 < <failure/>
769         EOF
770         output -i <<-EOF
771                 |00:00 [local] *** Authentication failure
772         EOF
773 }
774
775 test_xmpp_bind() {
776         test_xmpp_basic
777         server 5222 <<-EOF
778                 < <stream:features>
779                 <     <bind/>
780                 < </stream:features>
781                 > <iq id='bind' type='set'>
782                 >     <bind xmlns='*:xmpp-bind'>
783                 >         <resource>lamechat</resource>
784                 >     </bind>
785                 > </iq>
786                 < <iq id="bind" type="result">
787                 <     <bind>
788                 <         <jid>andy@localhost/lamechat</jid>
789                 <     </bind>
790                 < </iq>
791         EOF
792 }
793
794 test_xmpp_join() {
795         test_xmpp_bind
796
797         server 5222 <<-EOF
798                 > <iq id='session' type='set' to='localhost'>
799                 >     <session xmlns='*:xmpp-session'/>
800                 > </iq>
801                 > <presence/>
802                 > <presence id='join' from='andy@localhost/lamechat' to='*'>
803                 >     <x xmlns='http://jabber.org/protocol/muc'/>
804                 > </presence>
805                 < <iq to="localhost" type="result" id="session"/>
806                 < <presence id="join" from="test@conf.local/andy"/>
807                 < <presence id="join" from="test@conf.local/bob">
808                 <     <item jid="bob1@local"/>
809                 < </presence>
810         EOF
811         output -i <<-EOF
812                 |00:00 [test] *** XMPP Channel: test
813                 |00:00 [test] *** andy entered room.
814                 |00:00 [test] *** bob (bob1) entered room.
815         EOF
816 }
817
818 test_xmpp_topic() {
819         test_xmpp_join
820         input -c x
821         input -c x
822
823         server 5222 <<-EOF
824                 < <message type="groupchat" from="test@conf.local/bob">
825                 <     <subject>Some Topic</subject>
826                 < </message>
827         EOF
828         output -i <<-EOF
829                 | Some Topic
830                 |
831                 |00:00 [test] *** Topic: Some Topic
832         EOF
833 }
834
835 test_xmpp_message() {
836         test_xmpp_join
837
838         input -c x
839         input -c x
840         server 5222 <<-EOF
841                 < <iq from="info@local">
842                 <     <item jid="test@conf.local" name="Test Chat"/>
843                 < </iq>
844                 < <message type="error">
845                 <     <body>Server says goodbye!</body>
846                 < </message>
847         EOF
848         output -i <<-EOF
849                 |00:00 [info] *** item: [test@conf.local] Test Chat
850         EOF
851
852         server 5222 <<-EOF
853                 < <message type="groupchat" from="test@conf.local/bob">
854                 <     <body>Hello, again!</body>
855                 < </message>
856                 < <message type="groupchat" from="test@conf.local/bob">
857                 <     <delay stamp="2017-01-01T00:00:00"/>
858                 <     <body>Goodbye!</body>
859                 < </message>
860                 < <message type="groupchat" from="test@conf.local/bob">
861                 <     <html>I <i>said</i> <b>HELLO!</b></html>
862                 < </message>
863         EOF
864         input /sort
865         output -i <<-EOF
866                 |00:00 [test] bob: Goodbye!
867                 |00:00 [test] bob: Hello, again!
868                 |00:00 [test] bob: I said HELLO!
869         EOF
870
871         server 5222 <<-EOF
872                 < <presence id="join" from="test@conf.local/bob">
873                 <     <item jid="2@local"/>
874                 < </presence>
875                 < <message from="1@local">
876                 <     <body>I'm Andy!</body>
877                 < </message>
878                 > <iq id='auto-vcard' * to='1@local'>
879                 >     <vCard xmlns='vcard-temp'/>
880                 > </iq>
881                 < <iq id='auto-vcard' from='1@local'>
882                 <     <vCard>
883                 <         <FN>Andy Spencer</FN>
884                 <     </vCard>
885                 < </iq>
886         EOF
887         input -c n
888         output -i <<-EOF
889                 |00:00 Andy Spencer: I'm Andy!
890                 | Windows: [system] [Andy Spencer]
891                 |[Andy Spencer]
892         EOF
893
894         input /abbrev first && 
895         output -i <<-EOF
896                 | Windows: [system] [andy]
897         EOF
898
899         input /abbrev last
900         output -i <<-EOF
901                 | Windows: [system] [spencer]
902         EOF
903
904         input /abbrev flast
905         output -i <<-EOF
906                 | Windows: [system] [aspencer]
907         EOF
908
909         input /abbrev initials
910         output -i <<-EOF
911                 | Windows: [system] [as]
912         EOF
913 }
914
915 test_xmpp_servers() {
916         setup -c -s 6001 -s 6002 <<-EOF
917                 [server "irc"]
918                     protocol = irc
919                 [server "serv1"]
920                     protocol = xmpp
921                     connect  = true
922                     host     = "localhost"
923                     port     = 6001
924                     jid      = "andy@serv1/lame"
925                     muc      = "conf.serv1"
926                 [server "serv2"]
927                     protocol = xmpp
928                     connect  = true
929                     host     = "localhost"
930                     port     = 6002
931                     jid      = "andy@sevr2/lame"
932                     muc      = "conf.serv2"
933                 [channel "irc"]
934                     server   = "irc"
935                 [channel "chan1"]
936                     server   = "serv1"
937                     join     = true
938                 [channel "chan2"]
939                     server   = "serv2"
940                     join     = true
941                 [window "system"]
942                     filter   = "serv.|chan.|other.|irc"
943         EOF
944         server 6001 <<-EOF
945                 > <?xml*?>
946                 > <stream:stream*>
947                 < <stream:stream>
948                 < <stream:features><bind/></stream:features>
949
950                 > <iq*><bind*><resource>lame</resource></bind></iq>
951                 < <jid>foo</jid>
952
953                 > <iq*><session*/></iq>
954                 > <presence/>
955                 > <presence*><*/></presence>
956                 < <presence from="chan1@conf.serv1/alice1"/>
957                 < <presence from="other1@conf.serv1/bob1"/>
958         EOF
959         server 6002 <<-EOF
960                 > <?xml*?>
961                 > <stream:stream*>
962                 < <stream:stream>
963                 < <stream:features><bind/></stream:features>
964
965                 > <iq*><bind*><resource>lame</resource></bind></iq>
966                 < <jid>foo</jid>
967
968                 > <iq*><session*/></iq>
969                 > <presence/>
970                 > <presence*><*/></presence>
971                 < <presence from="chan2@conf.serv2/alice2"/>
972                 < <presence from="other2@conf.serv2/bob2"/>
973         EOF
974         output -i <<-EOF
975                 |00:00 [serv1] *** XMPP Server: serv1
976                 |00:00 [serv2] *** XMPP Server: serv2
977                 |00:00 [chan1] *** XMPP Channel: chan1
978                 |00:00 [chan1] *** alice1 entered room.
979                 |00:00 [other1] *** bob1 entered room.
980                 |00:00 [chan2] *** XMPP Channel: chan2
981                 |00:00 [chan2] *** alice2 entered room.
982                 |00:00 [other2] *** bob2 entered room.
983         EOF
984 }
985
986 test_xmpp_commands() {
987         test_xmpp_join
988
989         input -c x
990         input /join
991         input /query
992         input /config more_magic
993         input /kill_all_humans
994         output -i <<-EOF
995                 |00:00 [local] *** usage: /join <channel>
996                 |00:00 [local] *** usage: /query <user>
997                 |00:00 [local] *** Unimplemented: /config <arg>
998                 |00:00 [local] *** Unknown command /kill_all_humans
999         EOF
1000
1001         input hello local
1002         input /names
1003         input /config
1004         output -i <<-EOF
1005                 |00:00 [local] *** Cannot send to server
1006                 |00:00 [local] *** Cannot get names from server
1007                 |00:00 [local] *** Cannot get config from server
1008         EOF
1009
1010         input /items
1011         input /info
1012         server 5222 <<-EOF
1013                 > <iq id='items' * to='localhost'><query xmlns='*/disco#items'/></iq>
1014                 < <iq id='items'><item name='Public Chatrooms' jid='conf.localhost'/></iq>
1015                 > <iq id='info' * to='localhost'><query xmlns='*/disco#info'/></iq>
1016                 < <iq id='info'><identity name='chatrooms'/><feature var='vcard-temp'/></iq>
1017         EOF
1018         output -i <<-EOF
1019                 |00:00 [local] *** item: [conf.localhost] Public Chatrooms
1020                 |00:00 [local] *** identity: chatrooms
1021                 |00:00 [local] *** feature: vcard-temp
1022         EOF
1023
1024         input -c x
1025         input /names
1026         input /names other
1027         input /join other
1028         server 5222 <<-EOF
1029                 > <iq id='names' * to='test@conf.local'><query xmlns='*/disco#items'/></iq>
1030                 < <iq id='names' from='test@conf.local'><item jid='test@conf.local/Alice'/></iq>
1031                 > <iq id='names' * to='other@conf.local'><query xmlns='*/disco#items'/></iq>
1032                 < <iq id='names' from='other@conf.local'><item jid='other@conf.local/Bob'/></iq>
1033                 > <presence id='join' * to='other@conf.local/andy'><x xmlns='*/muc'/></presence>
1034         EOF
1035         output -i <<-EOF
1036                 |00:00 [test] *** User: Alice (test@conf.local/Alice)
1037                 |00:00 [other] *** User: Bob (other@conf.local/Bob)
1038         EOF
1039
1040         input -c x
1041         input hello other
1042         input /config
1043         input /query alice
1044         server 5222 <<-EOF
1045                 > <message id='chat0' * to='other@conf.local' type='groupchat'><body>hello other</body></message>
1046                 < <message from='other@conf.local/andy' type='groupchat'><body>hello other</body></message>
1047                 > <iq id='config' * to='other@conf.local'><query xmlns='*/muc#owner'/></iq>
1048                 < <iq from='other@conf.local'>
1049                 <     <title>Channel Setup</title>
1050                 <     <instructions>Fill out the form, yo!</instructions>
1051                 <     <field var='magic' type='hidden'/>
1052                 <     <field var='topic' type='string' label='Room Topic'/>
1053                 < </iq>
1054                 EOF
1055         output -i <<-EOF
1056                 |00:00 [other] andy: hello other
1057                 |00:00 [other] *** Title: Channel Setup
1058                 |00:00 [other] *** Fill out the form, yo!
1059                 |00:00 [other] *** topic                                -- Room Topic (string)
1060         EOF
1061
1062         input -c x
1063         input hello alice
1064         input /vcard
1065         input /vcard bob
1066         server 5222 <<-EOF
1067                 > <message id='chat1' * to='alice@localhost' type='chat'><body>hello alice</body></message>
1068                 > <iq id='vcard' * to='alice@localhost'><vCard xmlns='vcard-temp'/></iq>
1069                 < <iq id='vcard' from='alice@localhost'><vCard><FN>Adelais</FN></vCard></iq>
1070                 > <iq id='vcard' * to='bob@localhost'><vCard xmlns='vcard-temp'/></iq>
1071                 < <iq id='vcard' from='bob@localhost'><vCard><FN>Robert</FN></vCard></iq>
1072         EOF
1073         output -i <<-EOF
1074                 |00:00 [Adelais] andy: hello alice
1075                 |00:00 [Adelais] *** Begin vCard (alice)
1076                 |00:00 [Adelais] ***   FN -> Adelais
1077                 |00:00 [Adelais] *** End vCard
1078                 |00:00 [Robert] *** Begin vCard (bob)
1079                 |00:00 [Robert] ***   FN -> Robert
1080                 |00:00 [Robert] *** End vCard
1081         EOF
1082 }
1083
1084 # Utility functions
1085 wait_pid() {
1086         for i in `seq 10 -1 0`; do
1087                 if [ -f "$TMPDIR/pid.txt" ]; then
1088                         return
1089                 fi
1090                 if [ "$i" -eq 0 ]; then
1091                         fail -v "Process failed to start"
1092                 fi
1093                 sleep 0.01
1094         done
1095 }
1096 wait_idle() {
1097         debug "wait_idle"
1098         for i in `seq 50 -1 0`; do
1099                 idle=true
1100                 for p in "${PIDS[@]}"; do
1101                         if [ ! -f "/proc/$p/status" ]; then
1102                                 if [ "$1" != '-e' ]; then
1103                                         fail -v "Process exited early: $p"
1104                                 else
1105                                         PIDS=()
1106                                 fi
1107                                 continue
1108                         fi
1109                         if /bin/grep -q '^State:.*S' "/proc/$p/status" 2>/dev/null; then
1110                                 continue
1111                         fi
1112                         if [ "$i" -eq 0 ]; then
1113                                 fail -v "Process failed to sleep: $p"         \
1114                                      "-- $(grep "State:" /proc/$p/status)" \
1115                                      "-- $(sed 's/\x0/ /' "/proc/$p/cmdline")"
1116                         fi
1117                         idle=false
1118                 done
1119                 if $idle; then
1120                         debug "wait_idle ok"
1121                         return 0
1122                 fi
1123                 sleep 0.01
1124         done
1125 }
1126 listen() {
1127         debug "listen $1 $2"
1128         coproc=false
1129         proto=$1
1130         port=$2
1131         if [ "$proto" = ssl ] && [ ! -f "test.key" -o ! -f "test.crt" ]; then
1132                 openssl req -newkey rsa:2048 -nodes -x509      \
1133                             -days 7 -subj "/CN=example.com"    \
1134                             -keyout "test.key" -out "test.crt" \
1135                             2>/dev/null
1136         fi
1137         if [ "$proto" = ssl ]; then
1138                 addr="OPENSSL-LISTEN:$port"
1139                 addr="$addr,reuseaddr,nodelay"
1140                 addr="$addr,key=test.key,cert=test.crt,verify=0"
1141         else
1142                 addr="TCP-LISTEN:$port"
1143                 addr="$addr,reuseaddr,nodelay"
1144         fi
1145         if $coproc; then
1146                 coproc socat "STDIO" "$addr"
1147                 RECV[$port]=${COPROC[0]}
1148                 SEND[$port]=${COPROC[1]}
1149                 PIDS+=("$COPROC_PID")
1150         else
1151                 if [ ! -e "$TMPDIR/send_$port" ] ||
1152                    [ ! -e "$TMPDIR/recv_$port" ]; then
1153                         mkfifo "$TMPDIR/send_$port"
1154                         mkfifo "$TMPDIR/recv_$port"
1155                 fi
1156                 socat "STDIO" "$addr"          \
1157                         < "$TMPDIR/send_$port" \
1158                         > "$TMPDIR/recv_$port" &
1159                 exec {SEND[$port]}> "$TMPDIR/send_$port"
1160                 exec {RECV[$port]}< "$TMPDIR/recv_$port"
1161                 PIDS+=("$!")
1162         fi
1163         debug "${PIDS[@]} | >${SEND[$port]} <${RECV[$port]}"
1164 }
1165 preload() {
1166         debug "preload"
1167         txt="$(cat -)"
1168         id="$(cksum <<<"$txt")"
1169         id="${id% *}"
1170         if [ ! -f "$TMPDIR/libpreload-$id.so" ]; then
1171                 debug "compiling"
1172                 echo "$txt" > "$TMPDIR/preload-$id.c"
1173                 gcc -Wall -fPIC -shared -o      \
1174                     "$TMPDIR/libpreload-$id.so" \
1175                     "$TMPDIR/preload-$id.c"
1176         fi
1177         cp "$TMPDIR/libpreload-$id.so" \
1178            "$TMPDIR/libpreload.so"
1179 }
1180 setup() {
1181         debug "setup"
1182         mkdir -p "$TMPDIR"
1183         rm -f  "$TMPDIR/.lamechatrc" \
1184                "$TMPDIR/pid.txt"     \
1185                "$TMPDIR/send_"*      \
1186                "$TMPDIR/recv_"*
1187
1188         while [ "$1" ]; do
1189                 case "$1" in
1190                         -x) listen ssl $2; shift ;;
1191                         -s) listen tcp $2; shift ;;
1192                         -c) cat > "$TMPDIR/.lamechatrc" ;;
1193                         *)  error "Invalid setup" ;;
1194                 esac
1195                 shift
1196         done
1197
1198         cat >"$TMPDIR/start.sh" <<-EOF
1199                 echo \$\$ > "$TMPDIR/pid.txt"
1200                 ulimit -c unlimited
1201                 $([ -f "$TMPDIR/libpreload.so" ] &&
1202                   echo export LD_PRELOAD=\"$TMPDIR/libpreload.so\")
1203                 export HOME="$TMPDIR"
1204                 exec ./lamechat
1205         EOF
1206
1207         screen -S "$SESSION-p" -d -m -- \
1208         screen -S "$SESSION" /bin/sh
1209         screen -S "$SESSION" -X stuff "/bin/sh $TMPDIR/start.sh\n"
1210
1211         wait_pid
1212         pid=$(cat "$TMPDIR/pid.txt")
1213         PIDS+=("$pid")
1214         debug "pid $pid -- lamechat"
1215 }
1216 resize() {
1217         debug "resize"
1218         screen -S "$SESSION-p" -X height -w $1 $2
1219         screen -S "$SESSION"   -X height -w $1 $2
1220 }
1221 color() {
1222         debug "color"
1223         echo -ne "\\$1"
1224 }
1225 input() {
1226         debug "input"
1227         case "$1" in
1228                 -n) keys="$2"   ;;
1229                 -c) keys="^$2"  ;;
1230                 *)  keys="$*\n" ;;
1231         esac
1232         screen -S "$SESSION" -X stuff "$keys"
1233 }
1234 server() {
1235         debug "server"
1236         send_fd="${SEND[$1]}"
1237         recv_fd="${RECV[$1]}"
1238         if [ -z "$send_fd" -o -z "$recv_fd" ]; then
1239                 error "Invalid server port: $1"
1240         fi
1241         while IFS= read line; do
1242                 debug "line: [$line]"
1243                 send=""
1244                 recv=""
1245                 case "$line" in
1246                         "> "*) recv="${line#> }" ;;
1247                         "< "*) send="${line#< }" ;;
1248                 esac
1249                 if [ "$recv" ]; then
1250                         if [[ "$recv" == *'<'* ]]; then
1251                                 line=""
1252                                 recv=${recv##+( )}
1253                                 for i in ${recv//[^>]/ }; do
1254                                         if ! read -u"$recv_fd" -d'>' -t0.5 tag; then
1255                                                 fail "Timeout receiving '$recv'"
1256                                         fi
1257                                         line="$line$tag>"
1258                                 done
1259                         elif [[ "$recv" == ' ' ]]; then
1260                                 if ! IFS= read -n1 -u"$recv_fd" -t0.5 line; then
1261                                         fail "Timeout receiving '$recv'"
1262                                 fi
1263                         else
1264                                 if ! read -u"$recv_fd" -t0.5 line; then
1265                                         fail "Timeout receiving '$recv'"
1266                                 fi
1267                         fi
1268                         if [[ "$line" != $recv ]]; then
1269                                 fail "Received incorrect data\n" \
1270                                      " Expect: $recv\n" \
1271                                      " Actual: $line\n"
1272                         fi
1273                         debug "recv: $recv -> $line"
1274                 fi
1275                 if [ "$send" ]; then
1276                         debug "send: $send"
1277                         echo "$send" >&"$send_fd"
1278                 fi
1279         done
1280 }
1281 output() {
1282         debug "output"
1283         wait_idle "$1"
1284         if [ "$1" == "-e" ]; then
1285                 shift
1286         fi
1287         screen -S "$SESSION" -X hardcopy "$TMPDIR/output.txt"
1288         awk '
1289                 /^$/ { i++ }
1290                 /./  { i=0 }
1291                 //   { sub(/^[0-2][0-9]:[0-5][0-9]/,     "00:00") }
1292                 //   { sub(/^[0-9]+\.[0-9][0-9][0-9]: /, "0.000: ") }
1293                 //   { sub(/^/, "|") }
1294                 i<2  { print }
1295         ' < "$TMPDIR/output.txt" > "$TMPDIR/actual.txt"
1296         cat > "${TMPDIR}/expect.txt"
1297         out=$(diff -u99999 "$TMPDIR"/{expect,actual}.txt || true)
1298         if [ "$out" ]; then
1299                 out=$(echo "$out" | tail -n+4)
1300                 case "$1" in
1301                         -i) check=$(echo "$out" | sed '/^+|/d') ;;
1302                         -x) check=$(echo "$out" | sed '/^-|/d') ;;
1303                         *)  check=$(echo "$out")                ;;
1304                 esac
1305                 if [ "$(echo "$check" | sed '/^ /d')" ]; then
1306                         fail "$out"
1307                 fi
1308         fi
1309 }
1310 fail() {
1311         verbose=false
1312         if [ "$1" == "-v" ]; then
1313                 verbose=true
1314                 shift
1315         fi
1316         debug "fail"
1317         screen -S "$SESSION" -X hardcopy "$TMPDIR/fail.txt"
1318         echo -e "$*"
1319         if $verbose; then
1320                 sed '/^$/d; s/^/| /' "$TMPDIR/fail.txt"
1321         fi
1322         exit 1
1323 }
1324 quit() {
1325         debug "quit"
1326         if [ "${#PIDS}" -gt 0 ]; then
1327                 kill -INT "${PIDS[@]}" 2>&1
1328                 PIDS=()
1329         fi
1330         rm -f "$TMPDIR/libpreload.so"
1331         screen -S "$SESSION" -X quit
1332 }
1333 run() {
1334         for name; do
1335                 t0=$(date +%s.%N)
1336                 if out=$(trap quit EXIT; eval "$name"); then
1337                         result="pass"
1338                 else
1339                         result="fail"
1340                 fi
1341                 t1=$(date +%s.%N)
1342                 dt=$(dc -e "$t1 $t0 - p")
1343                 printf "%s -- %-20s -- %0.2fs\n" \
1344                         "$result" "$name" "$dt"
1345                 if [ "$out" ]; then
1346                         echo "$out" | sed 's/^/     /'
1347                 fi
1348                 if [ -f "core" ]; then
1349                         echo "  Found core file"
1350                         gdb -batch -q -ex bt -ex quit ./lamechat core |
1351                                 sed 's/^/      | /'
1352                         mv "core" "core-$name"
1353                 fi
1354         done
1355 }
1356
1357
1358
1359 # Main functions
1360 info() {
1361         echo "# $*" 1>&2
1362 }
1363
1364 error() {
1365         info "$*"
1366         exit 1
1367 }
1368
1369 debug() {
1370         if $debug; then
1371                 info "$(date +%s.%N) $*"
1372         fi
1373 }
1374
1375 usage() {
1376         echo "usage: ./test.sh [-dh] [test_case]"
1377         echo ""
1378         echo "Options:"
1379         echo "  -d,--debug  Print debug information"
1380         echo "  -h,--help   Print usage information"
1381         echo ""
1382         echo "Test Cases:"
1383         echo "$avail" | sed 's/^/  /'
1384         exit
1385 }
1386
1387 parse() {
1388         avail=$(grep -o '^test_[a-z0-9_]*' "${BASH_SOURCE}")
1389         opts=$(getopt -n "$0" -o dh -l debug,help -- "$@")
1390         eval set -- "${opts[@]}"
1391         while true; do
1392                 case "$1" in
1393                         -d|--debug)
1394                                 debug=true
1395                                 ;;
1396                         -h|--help)
1397                                 usage
1398                                 ;;
1399                         --)
1400                                 ;;
1401                         test_*)
1402                                 if these=$(echo "$avail" | grep -F "$1"); then
1403                                         tests+=($these)
1404                                 else
1405                                         error "Unknown test: $1"
1406                                 fi
1407                                 ;;
1408                         "")
1409                                 if [ "${#tests}" -eq 0 ]; then
1410                                         tests=($avail)
1411                                 fi
1412                                 break
1413                                 ;;
1414                         *)
1415                                 usage
1416                                 ;;
1417                 esac
1418                 shift
1419         done
1420 }
1421
1422 # Main
1423 PIDS=()
1424 SEND=()
1425 RECV=()
1426 TMPDIR=/tmp/lamechat-test
1427 SESSION=lamechat-test
1428
1429 debug=false
1430 tests=()
1431
1432 set -e
1433 shopt -s extglob
1434
1435 parse "$@"
1436 run "${tests[@]}"