1#!/usr/bin/perl
2# 2.2.2010, Sampo Kellomaki (sampo@iki.fi)
3# 18.11.2010, greatly enchanced --Sampo
4# 28.8.2012, added some features from hitest.pl, added zxbusd tests --Sampo
5#
6# Test suite for ZXID
7
8$usage = <<USAGE;
9Test driver for ZXID
10Usage: http://localhost:8081/zxtest.pl?tst=XML1  # Run as CGI with HTML putput
11       ./zxtest.pl -a [-a] [-x] [-dx] tst=XML1   # Run specific test
12       ./zxtest.pl -a [-a] [-x] [-dx] ntst=XML   # Run all tests except specified
13         -a  Ascii mode (give twice for colored ascii)
14         -x  Print exec(2) command lines to stderr
15         -dx Proprietary per character color diff (default: system diff -u)
16         N.B. Positional order of even optional arguments is significant.
17USAGE
18    ;
19
20$cvsid = '$Id$';
21($rev) = (split /\s+/, $cvsid)[2];
22
23# See https://wiki.archlinux.org/index.php/Color_Bash_Prompt
24#sub red   { $ascii > 1 ? "\e[1;31m$_[0]\e[0m" : $_[0]; }  # red text
25#sub green { $ascii > 1 ? "\e[1;32m$_[0]\e[0m" : $_[0]; }
26sub red    { $ascii > 1 ? "\e[1;41m$_[0]\e[0m" : $_[0]; }  # red background, black bold text
27sub green  { $ascii > 1 ? "\e[1;42m$_[0]\e[0m" : $_[0]; }
28sub redy   { $ascii > 1 ? "\e[41m$_[0]\e[0m" : $_[0]; }    # red background, black text (no bold)
29sub greeny { $ascii > 1 ? "\e[42m$_[0]\e[0m" : $_[0]; }
30
31use Encode;
32use Digest::MD5;
33use Digest::SHA;  # apt-get install libdigest-sha-perl
34use Net::SSLeay qw(get_httpx post_httpx make_headers make_form);  # Need Net::SSLeay-1.24
35use WWW::Curl::Easy;    # HTTP client library, see curl.haxx.se. apt-get install libwww-curl-perl
36use WWW::Curl::Multi;
37use XML::Simple;   # apt-get install libxml-simple-perl
38#use Net::SMTP;
39#use MIME::Base64;  # plain=decode_base64(b64)   # RFC3548
40#sub decode_safe_base64 { my ($x) = @_; $x=~tr[-_][+/]; return decode_base64 $x; }
41#sub encode_safe_base64 { my ($x) = @_; $x = encode_base64 $x, ''; $x=~tr[+/][-_]; return $x; }
42use Data::Dumper;
43use Time::HiRes;
44
45die $usage if $ARGV[0] =~ /^--?[hH?]/;
46$trace = 0;
47
48if ($ARGV[0] eq '-t') {
49    warn "Test: ".check_diff("ZXBUSM64", 60, 10, '10x10x20');
50    exit;
51}
52
53# Where error log goes tail -f zxtest.err
54#open STDERR, ">>zxtest.err";
55
56select STDERR; $| = 1; select STDOUT; $| = 1;
57$ascii = 1,shift if $ARGV[0] eq '-a';
58$ascii = 2,shift if $ARGV[0] eq '-a';
59$show_exec = shift if $ARGV[0] eq '-x';
60$diffx = shift if $ARGV[0] eq '-dx';
61
62$ENV{'LD_LIBRARY_PATH'} = '/apps/lib';  # *** Specific to Sampo's environment
63warn "START pid=$$ $cvsid qs($ENV{'QUERY_STRING'}) LD($ENV{'LD_LIBRARY_PATH'})";
64syswrite STDOUT, "Content-Type: text/html\r\n\r\n" if !$ascii;
65
66### N.B. Ignoring SIGCHLD breaks return value of system() and $?
67#$x=system "false"; warn "x($x) q($?) $!";
68#$SIG{CHLD} = 'IGNORE';  # No zombies, please (subprocesses for delayed ops).
69#$x=system "false"; warn "x($x) q($?) $!";
70
71$uname_minus_s = `uname -s`;
72chop $uname_minus_s;
73
74###
75### Library Functions
76###
77
78sub writeall {
79    my ($f,$d) = @_;
80    open F, ">$f" or die "Cant write($f): $!";
81    binmode F;
82    flock F, 2;    # Exclusive
83    print F $d;
84    flock F, 8;
85    close F;
86}
87
88sub readall {
89    my ($f,$silent) = @_;
90    my ($pkg, $srcfile, $line) = caller;
91    undef $/;         # Read all in, without breaking on lines
92    if (open F, "<$f") {
93	binmode F;
94	#flock F, 1;
95	my $x = <F>;
96	#flock F, 8;
97	close F;
98	return $x;
99    } else {
100	return undef if $silent;
101	warn "$srcfile:$line: Cant read($f): $!";
102	warn "pwd(".`pwd`.")";
103	return undef;
104    }
105}
106
107sub cgiout {
108    my ($hdr, $mime, $body, $isbin) = @_;
109    warn "Len body preenc=".length($body);
110    $body = encode_utf8($body);
111    warn "Len body postenc=".length($body);
112    syswrite STDOUT, "${hdr}Content-Type: $mime\r\nContent-Length: ".length($body)."\r\n\r\n$body";
113
114    if ($isbin > 0) {  # 0 = proto, 1 = html, 2 = true binary
115	#warn "cgiout(${hdr}Content-Type: $mime\r\nContent-Length: ".length($body)."\r\n\r\n(binary($isbin) body omitted from log)";
116	warn "-- cgiout $$ hdr(${hdr}) mime($mime) len=".length($body)." bin($isbin)";
117    } else {
118	#warn "cgiout(${hdr}Content-Type: $mime\r\nContent-Length: ".length($body)."\r\n\r\n$body)";
119	warn "-- cgiout $$ hdr(${hdr}) mime($mime) len=".length($body)." body($body)";
120    }
121}
122
123sub cgidec {
124    my ($d) = @_;
125    my %qs;
126    for $nv (split '&', $d) {
127	($n, $v) = split '=', $nv, 2;
128	$qs{$n} = $v;
129    }
130    return \%qs;
131}
132
133sub uridec {
134    my ($val) = @_;
135    $val =~ s/\+/ /g;
136    $val =~ s/%([0-9a-f]{2})/chr(hex($1))/gsex;  # URI decode
137    return $val;
138}
139
140sub urienc {
141    my ($val) = @_;
142    $val =~ s/([^A-Za-z0-9.,_-])/sprintf("%%%02x",ord($1))/gsex; # URI enc
143    return $val;
144}
145
146###
147### Custome diff package
148###
149
150# Erase some common innocent differences
151
152sub blot_out_std_diffs {
153    my ($x) = @_;
154    #warn "len=".length($x);
155    $x =~ s/(ID)=".*?"/$1=""/g;
156    $x =~ s/(IssueInstant)=".*?"/$1=""/g;
157
158    $x =~ s/0\.\d+ 12\d+ libzxid \(zxid\.org\)/0./g;
159    $x =~ s/R0\.\d+ \(\d+\)/R0./g;
160    $x =~ s/R0\.\d+/R0./g;
161
162    $x =~ s/^(msgid: ).+/$1/gm;
163    $x =~ s/^(sespath: ).+/$1/gm;
164    $x =~ s/^(sesid: ).+/$1/gm;
165    $x =~ s/^(tgta7npath: ).+/$1/gm;
166    $x =~ s/^(ssoa7npath: ).+/$1/gm;
167    $x =~ s/^(zxididp: 0\.).+/$1/gm;
168
169    $x =~ s%<wsu:Created>.*?</wsu:Created>%CREATED_TS%g;
170    $x =~ s%<a:MessageID[^>]*>.*?</a:MessageID>%MessageID%g;
171    $x =~ s%<a:InReplyTo[^>]*>.*?</a:InReplyTo>%InReplyTo%g;
172    $x =~ s%<ds:DigestValue>.*?</ds:DigestValue>%DIGESTVAL%g;
173    $x =~ s%<ds:SignatureValue>.*?</ds:SignatureValue>%SIGVAL%g;
174    $x =~ s%<xenc:CipherValue>.*?</xenc:CipherValue>%CIPHERVALUE%g;
175
176    # zxbusd hiiosdump related
177
178    #warn "len=".length($x);
179    $x =~ s%(shf_0x)[0-9a-f]+%$1%g;
180    $x =~ s%(io_0x)[0-9a-f]+%$1%g;
181    $x =~ s%(hit_0x)[0-9a-f]+%$1%g;
182    $x =~ s%(tid_)[0-9a-f]+%$1%g;
183    $x =~ s%(pdu_0x)[0-9a-f]+%$1%g;
184    $x =~ s%(-> pdu_0x  // \()[A-Z]+\)%$1)%g;
185    $x =~ s%(// fd=0x)[0-9a-f]+%$1%g;
186
187    #warn "len=".length($x);
188    $x =~ s%test\(-?\d+,\d+,\d+\)%test(,,)%g;
189    $x =~ s%RECEIPT \d+%RECEIPT %g;
190    #warn "len=".length($x);
191    return $x;
192}
193
194sub ediffy {   # The main diff algo
195    my ($a,$b) = @_;
196    return 0 if $a eq $b;
197
198    # Ignore some common innocent differences
199
200    $a = blot_out_std_diffs($a);
201    $b = blot_out_std_diffs($b);
202    return 0 if $a eq $b;
203
204    warn "enter heavy diff -u tmp/a tmp/b; len1=".length($a)." len2=".length($b);
205    writeall("tmp/a", $a);
206    writeall("tmp/b", $b);
207
208    my $ret = 0;
209
210    eval {
211	local $SIG{ALRM} = sub { die "TIMEOUT\n"; };
212	alarm 60;   # The ediff algorithm seems exponential time, so lets not wait forever.
213	require Algorithm::Diff;
214	my @seq1 = split //, $a;
215	my @seq2 = split //, $b;
216	my $diff = Algorithm::Diff->new( \@seq1, \@seq2 );
217
218	$diff->Base(1);   # Return line numbers, not indices
219	while(  $diff->Next()  ) {
220	    if (@sames = $diff->Same()) {
221		print @sames;
222		next;
223	    }
224	    if (@dels = $diff->Items(1)) {
225		print redy(join '', @dels);
226		++$ret;;
227	    }
228	    if (@adds = $diff->Items(2)) {
229		print greeny(join '', @adds);
230		++$ret;
231	    }
232	}
233    };
234    alarm 0;
235    print "\n" if $ret;
236    return $ret;
237}
238
239sub ediffy_read {
240    my ($file1,$file2) = @_;
241    my $data1 = readall $file1;
242    my $data2 = readall $file2;
243    return ediffy($data1,$data2);
244}
245
246sub isdiff_read {
247    my ($file1,$file2,$silent) = @_;
248    my $data1 = readall($file1,$silent);
249    my $data2 = readall($file2,$silent);
250    #warn "len1($file1)=".length($data1)." def1=".defined($data1)." len2($file2)=".length($data2)." def2=".defined($data2).".";
251    return -6 if !defined($data1) || !defined($data2);
252    #warn "data1($data1)\ndata2($data2)" if $data1 && $data2;
253    $data1 = blot_out_std_diffs($data1);
254    $data2 = blot_out_std_diffs($data2);
255    return 0 if $data1 eq $data2;
256    return (length($data1)-length($data2)) || -5;
257}
258
259sub check_diff {
260    my ($tsti, $latency, $slow, $test) = @_;
261    my $ret;
262    $ok_lvl = '';
263    return 0 if !($ret = isdiff_read("t/$tsti.out", "tmp/$tsti.out"));
264    $ok_lvl = 2;
265    return 0 if !isdiff_read("t/$tsti.out2", "tmp/$tsti.out", 1);  # second truth matches
266    $ok_lvl = 3;
267    return 0 if !isdiff_read("t/$tsti.out3", "tmp/$tsti.out", 1);  # third truth
268    if ($diffx) {
269	if ($ret = ediffy_read("t/$tsti.out", "tmp/$tsti.out")) {
270	    tst_print('col1r', 'Diff ERR', $latency, $slow, $test, "$ret lines of diff");
271	    return 1;
272	}
273    } elsif ($diffmeth eq 'diffu') {
274	if (system "/usr/bin/diff t/$tsti.out tmp/$tsti.out") {
275	    tst_print('col1r', 'Diff Err', $latency, $slow, $test, '');
276	    return 1;
277	}
278    } else {
279	tst_print('col1r', (abs($ret)>5)?'Size ERR':'Diff ERR', $latency, $slow, $test, ($ret==-5?'':"Difference in size: $ret"));
280	return 1;
281    }
282    $ok_lvl = 4;
283    return 0;
284}
285
286### HTTP clients
287
288if (1) {
289sub resp_cb {
290    my ($chunk,$curl_id) = @_;
291    #warn "resp_cb curl_id($curl_id) chunk($chunk) len=".length($chunk);
292    $resp{$curl_id} .= $chunk;
293    return length $chunk; # OK
294}
295
296sub curl_reset_all {
297    my ($curl) = @_;
298    $curl->reset();
299    sleep 5;
300}
301
302sub test_http {
303    my ($curl, $cmd, $tsti, $expl, $url, $timeout, $slow) = @_;
304    return unless $tst eq 'all' || $tst eq substr($tsti,0,length $tst);
305    return if $ntst && $ntst eq substr($tsti,0,length $ntst);
306    #warn "\n======= $tsti =======";
307
308    $slow ||= 0.5;
309    $timeout ||= 15;
310    my $test = tst_link($tsti, $expl, $url);
311    my $send_ts = Time::HiRes::time();
312    $cmd{$curl_id} = $cmd;
313    $key{$curl_id} = $koerkki;
314    $qs{$curl_id} = '';
315    $sesid{$curl_id} = '';
316    warn "HERE1 ".Time::HiRes::time() if $timeout_trace;
317    eval {
318	warn "HERE2 ".Time::HiRes::time() if $timeout_trace;
319	local $SIG{ALRM} = sub { die "TIMEOUT\n"; };
320	warn "HERE3 ".Time::HiRes::time() if $timeout_trace;
321	alarm $timeout;
322	warn "HERE4 ".Time::HiRes::time() if $timeout_trace;
323	send_http($curl, $url, 0);
324	warn "HERE5 ".Time::HiRes::time() if $timeout_trace;
325	wait_response();
326	warn "HERE6 ".Time::HiRes::time() if $timeout_trace;
327    };
328    warn "HERE7 ".Time::HiRes::time() if $timeout_trace;
329    alarm 0;
330    warn "HERE8 ".Time::HiRes::time() if $timeout_trace;
331    my $status = $@;
332    warn "HERE9 ".Time::HiRes::time() if $timeout_trace;
333    my $latency = substr(Time::HiRes::time() - $send_ts, 0, 5);
334    if ($status eq "TIMEOUT\n") {
335	tst_print('col1r', 'Timeout', $latency, $slow, $test, '');
336	$@ = 0;
337	warn "Timeout ($@) ".Time::HiRes::time();
338	#$timeout_trace = 1;
339	curl_reset_all($curl);
340    } elsif ($status) {
341	tst_print('col1r', 'Conn. Err', $latency, $slow, $test, $status);
342    } elsif ($laststatus ne 'OK') {
343	tst_print('col1r', 'App Err', $latency, $slow, $test, $lasterror);
344    } else {
345	tst_ok($latency, $slow, $test);
346    }
347}
348
349sub test_http_post {
350    my ($curl, $cmd, $tsti, $expl, $url, $body, $timeout, $slow) = @_;
351    return unless $tst eq 'all' || $tst eq substr($tsti,0,length $tst);
352    return if $ntst && $ntst eq substr($tsti,0,length $ntst);
353    #warn "\n======= $tsti =======";
354
355    $slow ||= 0.5;
356    $timeout ||= 15;
357    my $test = tst_link($tsti, $expl, $url);
358    my $send_ts = Time::HiRes::time();
359    $cmd{$curl_id} = $cmd;
360    $key{$curl_id} = $koerkki;
361    $qs{$curl_id} = '';
362    $sesid{$curl_id} = '';
363    eval {
364	local $SIG{ALRM} = sub { die "TIMEOUT\n"; };
365	alarm $timeout;
366	send_http_post($curl, $url, $body, 1);
367	wait_response();
368    };
369    alarm 0;
370    my $status = $@;
371    my $latency = substr(Time::HiRes::time() - $send_ts, 0, 5);
372    if ($status eq "TIMEOUT\n") {
373	tst_print('col1r', 'Timeout', $latency, $slow, $test, '');
374	$@ = 0;
375	curl_reset_all($curl);
376    } elsif ($status) {
377	tst_print('col1r', 'Conn. Err', $latency, $slow, $test, $status);
378    } elsif ($laststatus ne 'OK') {
379	tst_print('col1r', 'App Err', $latency, $slow, $test, $lasterror);
380    } else {
381	tst_ok($latency, $slow, $test);
382    }
383}
384
385### Create http connection handles. Each will correspnd to one session, i.e. set of cookies
386
387$curl_id = 1;
388$curlm = WWW::Curl::Multi->new;  # Multihandle, technically needed
389
390$curlA = new WWW::Curl::Easy;  # Share curl handle so that cookies are shared
391
392sub tA { test_http($curlA, @_); }
393sub pA { test_http_post($curlA, @_); }
394
395sub send_req {
396    my ($what, $send_trace) = @_;
397    my ($pkg, $srcfile, $line) = caller;
398    $send_ts{$curl_id} = Time::HiRes::time();
399    #my $curl = new WWW::Curl::Easy; # Globally created to preserve cookies
400    my $curl = $curlP;
401    $curl->setopt(CURLOPT_FOLLOWLOCATION, 1);
402    $curl->setopt(CURLOPT_MAXREDIRS, 5);
403    #$curl->setopt(CURLOPT_SSL_VERIFYHOST, 2);  # 2=verify (default, 0=disable check
404    $curl->setopt(CURLOPT_SSL_VERIFYPEER, 0);  # 1=verify (default, 0=disable check
405    $curl->setopt(CURLOPT_UNRESTRICTED_AUTH, 1);
406    #$curl->setopt(CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
407    #$curl->setopt(CURLOPT_USERPWD, "sampo:12345678");  # ***
408    $curl->setopt(CURLOPT_COOKIEFILE, '');  # Empty file enables tracking cookies
409    #open (my $fileb, ">", \$resp);            # Read into inmemory file
410    #$curl->setopt(CURLOPT_WRITEDATA,$fileb);
411    $curl->setopt(CURLOPT_WRITEFUNCTION, \&resp_cb);
412    $curl->setopt(CURLOPT_FILE, $curl_id);
413    $resp{$curl_id} = '';
414    $curl->setopt(CURLOPT_HTTPGET, 1);
415    my @hdr = ("User-Agent: wrevd-0.2-$rev");
416    $curl->setopt(CURLOPT_HTTPHEADER, \@hdr);
417    $easy_url{$curl_id} = "$dom$soap_endpoint/$what";  # Curl will reference mem so make sure it will not be garbage collected until the handle is
418    $curl->setopt(CURLOPT_URL, $easy_url{$curl_id});
419    warn "  $srcfile:$line: WS GET($easy_url{$curl_id}) curl_id($curl_id)" if $send_trace;
420    $curl->setopt(CURLOPT_PRIVATE, $curl_id);
421    $easy{$curl_id} = $curl;
422    $curlm->add_handle($curl);
423    ++$curl_id;
424    ++$active_handles;
425}
426
427sub send_req_post_soap {
428    my ($body) = @_;
429    my ($pkg, $srcfile, $line) = caller;
430    $send_ts{$curl_id} = Time::HiRes::time();
431    #my $curl = new WWW::Curl::Easy; # Globally created to preserve cookies
432    my $curl = $curlP;
433    $curl->setopt(CURLOPT_FOLLOWLOCATION, 1);
434    $curl->setopt(CURLOPT_MAXREDIRS, 5);
435    #$curl->setopt(CURLOPT_SSL_VERIFYHOST, 2);  # 2=verify (default, 0=disable check
436    $curl->setopt(CURLOPT_SSL_VERIFYPEER, 0);  # 1=verify (default, 0=disable check
437    $curl->setopt(CURLOPT_UNRESTRICTED_AUTH, 1);
438    #$curl->setopt(CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
439    #$curl->setopt(CURLOPT_USERPWD, "sampo:12345678");  # ***
440    $curl->setopt(CURLOPT_COOKIEFILE, '');  # Empty file enables tracking cookies
441    #open (my $fileb, ">", \$resp);         # Read into inmemory file
442    #$curl->setopt(CURLOPT_WRITEDATA,$fileb);
443    $curl->setopt(CURLOPT_WRITEFUNCTION, \&resp_cb);
444    $curl->setopt(CURLOPT_FILE, $curl_id);
445    $resp{$curl_id} = '';
446
447    #$curl->setopt(CURLOPT_POSTFIELDS, qq(<?xml version="1.0" encoding="utf-8"?><soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"><soap12:Body>$body</soap12:Body></soap12:Envelope>));
448    # Curl will reference mem so make sure it will not be garbage collected until the handle is
449    $easy_post{$curl_id} = qq(<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body>$body</soap:Body></soap:Envelope>);
450    $curl->setopt(CURLOPT_POSTFIELDS, $easy_post{$curl_id});  # implies CURLOPT_POST
451
452    #my @hdr = ("Content-Type: application/soap+xml","User-Agent: wrevd-0.2");
453    my @hdr = ("Content-Type: text/xml","User-Agent: wrevd-0.2-$rev",'SOAPAction: "http://timebi.com/UpdatePositions"');
454    $curl->setopt(CURLOPT_HTTPHEADER, \@hdr);
455    $easy_url{$curl_id} = "$dom$soap_endpoint";  # Curl will reference mem so make sure it will not be garbage collected until the handle is
456    $curl->setopt(CURLOPT_URL, $easy_url{$curl_id});
457    warn "$srcfile:$line: WS SOAP($body)" if $wstrace;
458    $curl->setopt(CURLOPT_PRIVATE,$curl_id);
459    $easy{$curl_id} = $curl;
460    $curlm->add_handle($curl);
461    ++$curl_id;
462    ++$active_handles;
463}
464
465sub send_http {
466    my ($curl, $url, $send_trace) = @_;
467    my ($pkg, $srcfile, $line) = caller;
468    $send_ts{$curl_id} = Time::HiRes::time();
469    #my $curl = new WWW::Curl::Easy;   # see 1st arg
470    $curl->setopt(CURLOPT_FOLLOWLOCATION, 1);
471    $curl->setopt(CURLOPT_MAXREDIRS, 5);
472    #$curl->setopt(CURLOPT_SSL_VERIFYHOST, 2);  # 2=verify (default, 0=disable check
473    $curl->setopt(CURLOPT_SSL_VERIFYPEER, 0);  # 1=verify (default, 0=disable check
474    $curl->setopt(CURLOPT_UNRESTRICTED_AUTH, 1);
475    $curl->setopt(CURLOPT_COOKIEFILE, ''); # Empty file enables cookie tracking
476    $curl->setopt(CURLOPT_WRITEFUNCTION, \&resp_cb);
477    $curl->setopt(CURLOPT_FILE, $curl_id);
478    $resp{$curl_id} = '';
479    $curl->setopt(CURLOPT_HTTPGET, 1);
480    my @hdr = ("User-Agent: wrevd-0.2-$rev");
481    $curl->setopt(CURLOPT_HTTPHEADER, \@hdr);
482    $easy_url{$curl_id} = $url;  # Curl will reference mem so make sure it will not be garbage collected until the handle is
483    $curl->setopt(CURLOPT_URL, $easy_url{$curl_id});
484    warn "  $srcfile:$line: WS GET($easy_url{$curl_id}) curl_id($curl_id)" if $send_trace;
485    $curl->setopt(CURLOPT_PRIVATE, $curl_id);
486    $easy{$curl_id} = $curl;
487    $curlm->add_handle($curl);
488    ++$curl_id;
489    ++$active_handles;
490}
491
492sub send_http_post {
493    my ($curl, $url, $body, $send_trace) = @_;
494    my ($pkg, $srcfile, $line) = caller;
495    $send_ts{$curl_id} = Time::HiRes::time();
496    #my $curl = new WWW::Curl::Easy;  # see 1st arg
497    $curl->setopt(CURLOPT_FOLLOWLOCATION, 1);
498    $curl->setopt(CURLOPT_MAXREDIRS, 5);
499    #$curl->setopt(CURLOPT_SSL_VERIFYHOST, 2);  # 2=verify (default, 0=disable check
500    $curl->setopt(CURLOPT_SSL_VERIFYPEER, 0);  # 1=verify (default, 0=disable check
501    $curl->setopt(CURLOPT_UNRESTRICTED_AUTH, 1);
502    $curl->setopt(CURLOPT_COOKIEFILE, ''); # Empty file enables cookie tracking
503    $curl->setopt(CURLOPT_WRITEFUNCTION, \&resp_cb);
504    $curl->setopt(CURLOPT_FILE, $curl_id);
505
506    #             1 1    234     4 5     53 2
507    #$url =~ s%http(s)?://((([^:]+):([^@]+))@)?%%si;
508    #if ($3) {  # inline specified username and password
509    #warn "Basic-Auth($3) url($url)";
510    #$curl->setopt(CURLOPT_USERPWD, $1);
511    #}
512
513    $resp{$curl_id} = '';
514    $easy_post{$curl_id} = $body;
515    $curl->setopt(CURLOPT_POSTFIELDS, $easy_post{$curl_id});  # implies CURLOPT_POST
516    my @hdr = ("User-Agent: wrevd-0.2-$rev");
517    $curl->setopt(CURLOPT_HTTPHEADER, \@hdr);
518    $easy_url{$curl_id} = $url;  # Curl will reference mem so make sure it will not be garbage collected until the handle is
519    $curl->setopt(CURLOPT_URL, $easy_url{$curl_id});
520    warn "  $srcfile:$line: WS POST($easy_url{$curl_id}) BODY($body) curl_id($curl_id)" if $send_trace;
521    $curl->setopt(CURLOPT_PRIVATE, $curl_id);
522    $easy{$curl_id} = $curl;
523    $curlm->add_handle($curl);
524    ++$curl_id;
525    ++$active_handles;
526}
527
528sub wait_response {
529    $laststatus = $lasterror = '';
530    while ($active_handles) {
531	warn "  curlm->perform loop active($active_handles) n=$n_resp vol=$v_resp avg_lat=".($n_resp?($tot_latency / $n_resp):0) if $trace;
532	$tcid = $curl_id - 1;
533	warn "  url($easy_url{$tcid}) curl_id($tcid)" if $trace;
534	my $active_transfers = $curlm->perform;
535	if ($active_transfers == $active_handles) {
536	    #warn "  url($easy_url{$curl_id})";
537	    select(undef, undef, undef, 0.1);   # transfers incomplete, wait a little and try again
538	    next;
539	}
540	warn "  url($easy_url{$tcid}) at=$active_transfers ah=$active_handles" if $trace;
541	while (my ($id, $ret) = $curlm->info_read) {
542	    next if !$id;
543	    --$active_handles;
544	    my $curle = $easy{$id};
545	    delete $easy{$id}; # let curl handle get garbage collected, or we leak memory
546	    delete $easy_post{$id};
547	    $latency = Time::HiRes::time() - $send_ts{$id};
548	    if ($ret) {
549		warn "HTTP layer failed: ".$curle->errbuf."\nid=$id qs($qs{$id})\nurl($easy_url{$id})\nret($ret) id=$id latency=$latency";
550		delete $easy_url{$id};
551		next;
552	    }
553	    #warn "HTTP complete $id URL($easy_url{$id})";
554	    $qs = cgidec $qs{$id};
555	    $rsp = decode_utf8($resp{$id});  # http response
556	    delete $resp{$id};
557	    #warn "resp($rsp) id=$id latency=$latency ($send_ts{$id})" if $wstrace>1;
558	    warn "resp($rsp) id=$id qsid($qs{$id}) latency=$latency\n\n" if $wstrace>1 && $$qs{'id'} ne 'intupd';
559	    ++$n_resp;
560	    $tot_latency += $latency;
561	    $v_resp += length $rsp;
562	    if (length $rsp) {
563		if ($cmd{$id} eq 'PING'
564		    || $cmd{$id} eq 'LOGOUT') {
565		    #warn "Non XML cmd($cmd{$id}) url($easy_url{$id}) response($rsp)";
566		} elsif ($cmd{$id} eq 'ST') {
567		    #warn "static response len=".length($rsp);
568		} else {
569		    # Wrapped in eval {} to avoid death when web service sends non XML errors
570		    eval {
571			$xx = XMLin $rsp, ForceArray => 1, KeyAttr => [];   # <== Decode XML
572		    };
573		    if ($@) {
574			if (($lasterror) = $rsp =~ /^(.*?Exception.*?)\n/s) {
575			    $cmd{$id} = 'exception';
576			}
577			#warn "XMLin: $@";
578			#warn "cmd($cmd{$id}) resp($id)=($rsp)";
579			$xx = undef;
580		    }
581		}
582	    } else {
583		#warn "Empty response (possibly OK)";
584		$xx = undef;
585	    }
586	    #warn "XML::Simple: " . Dumper($xx);
587
588	    $user = $ses{$sesid{$id}}{'user'};
589	    #warn "user($user) qs($qs{$id})" . Dumper($xx) if $wstrace && $$qs{'id'} ne 'intupd';
590	    #printf WS_LOG "%.3f %2.3f %5d %4d %s %s %s\n", $send_ts{$id}, $latency, length($rsp), $id, $user, $key{$id}, $qs{$id}; #substr($qs{$id},0,30);
591
592	    if ($cmd{$id} eq 'PING'
593		|| $cmd{$id} eq 'WRSEND') {
594		$lasterror = $rsp;
595		eval { $rr = $jsonobj->decode($rsp); };
596		if ($$rr[0]{'err'} && $$rr[0]{'err'} ne 'OK' && $$rr[0]{'err'} ne 'LAST') {
597		    warn "err($$rr[0]{'err'})";
598		    $laststatus = $$rr[0]{'err'};
599		} else {
600		    warn "OK err($$rr[0]{'err'})";
601		    $laststatus = 'OK';
602		}
603	    } elsif ($cmd{$id} eq 'NOT') {
604		$lasterror = $rsp;
605		eval { $rr = $jsonobj->decode($rsp); };
606		if ($$rr[0]{'err'} ne 'NA') {
607		    $laststatus = "E=".$$rr[0]{'err'};
608		} else {
609		    $laststatus = 'OK';
610		}
611	    } elsif ($cmd{$id} eq 'NOP') {
612		$lasterror = $rsp;
613		eval { $rr = $jsonobj->decode($rsp); };
614		if ($$rr[0]{'err'} ne 'NP') {
615		    $laststatus = "E=".$$rr[0]{'err'};
616		} else {
617		    $laststatus = 'OK';
618		}
619	    } elsif ($cmd{$id} eq 'AR') {
620		# Extract from the POST binding page form fields to pass on
621		($AR) = $rsp =~ /<input name="ar" value="(.*?)"/;
622		$laststatus = 'OK';
623		$lasterror = "len=".length($rsp);
624	    } elsif ($cmd{$id} eq 'SP') {
625		# Extract from the POST binding page form fields to pass on
626		($SAMLResponse) = $rsp =~ /<input name="SAMLResponse" value="(.*?)"/;
627		$laststatus = 'OK';
628		$lasterror = "len=".length($rsp);
629	    } elsif ($cmd{$id} eq 'ST') {
630		$laststatus = 'OK';
631		$lasterror = "len=".length($rsp);
632	    }
633	    delete $easy_url{$id};
634	    delete $cmd{$id};
635	    delete $key{$id};
636	    delete $sesid{$id};
637	    delete $send_ts{$id};
638	}
639    }
640}
641
642### N.B. Runs in context of inquiring user and only sends messages (such
643### as diffs or end result) to the inquiring user's sessions.
644
645sub process_timetag_response {
646    my ($xx, $user, $sesid, $qs) = @_;
647
648    if (length $$xx{'Name'}[0]) {
649	$laststatus = 'OK';
650    } else {
651	$laststatus = 'ERRTT';
652    }
653}
654
655sub process_simple_response {
656    my ($xx, $user, $sesid, $qs) = @_;
657    $laststatus = 'OK';
658}
659
660sub process_error_response {
661    my ($erro, $user, $sesid, $qs) = @_;
662    warn "error($erro) user($user) sesid($sesid) qs(".Dumper($qs).")";
663    $laststatus = $erro;
664}
665
666sub process_sent_response {
667    my ($xx, $user, $sesid, $qs) = @_;
668    $lasterror = 'OK'; # Need better check to verify if message really was sent
669}
670} # Close if (0) several pages above
671
672###
673### Daemon management routines
674###
675
676### Persist in killing a child process
677
678sub kill_child {
679    my ($pid,$sig) = @_;
680    return 1 unless $pid;
681    $sig ||= USR1;  # 1 = SIGHUP, 10 = SIGUSR1 (which cause gcov friendly exit(3))
682    #warn "KILL CHILD $pid";
683    kill $sig, $pid;
684    eval {
685	local $SIG{ALRM} = sub { die "timeout\n"; };
686	alarm 5;
687	waitpid $pid,0;
688	alarm 0;
689    };
690    if ($@) {
691	die "waitpid $pid failed: $@ / $!" unless $@ eq "timeout\n";
692	warn "Die hard process $pid refuses to die. Trying kill -9";
693	kill 9, $pid for (1..3);
694	alarm 5;       # If it won't die, its an error so do not catch the timeout
695	waitpid $pid,0;
696	alarm 0;
697    }
698    return 1;
699}
700
701### Check that the port numbers and take them out of the message (because
702### port numbers could be variable and cause test log comparison to fail).
703
704sub check_ports {
705   my ($m) = @_;
706   my @a=split (/\n/,$m);
707   my %port;
708   my $cont=0;
709   my $fin='';
710   for my $m (@a) {
711       my @aux = split (/:/,$m);
712       if ($aux[0] eq "search_port"){
713	  if ($cont == 0){    #The first port is used to compare
714	     $cont=$aux[1];
715	  }else{
716       	     $port{$aux[1]}++;
717	  }
718       }else{
719           $fin .= "$m\n";
720       }
721   }
722
723   $fin .= "\n";
724
725   my $number = keys(%port);
726   $fin.= "There are $number ports\n";
727   $fin.="\n";
728   for my $p (keys(%port)){
729	if ($p < $cont){
730	   $fin.= "One port minor than first port \n";
731	   $fin.="\n";
732	}else {  #It should not be the same port
733	   $fin.= "One port mayor than first port \n";
734	   $fin.="\n";
735	}
736   }
737   return $fin;
738}
739
740sub check_nums {
741   my ($m) = @_;
742   my @a=split (/\n/,$m);
743   my %nums;
744   my $cont=0;
745   my $fin='';
746   for my $m (@a) {
747       my @aux = split (/:/,$m);
748       if ($aux[0] eq "numorder"){
749       	     $nums{$aux[1]}++;
750       }
751   }
752
753   $fin .= "\n";
754
755   my $number = keys(%nums);
756   $fin.= "There are $number nums\n";
757   $fin.="\n";
758   for my $p (keys(%nums)){
759	   $fin.= "$p,";
760   }
761   $fin.="\n";
762   return $fin;
763}
764
765sub check_for_listener {
766    my $port = shift @_;
767    return 1 if $always_external_test_servers;  # avoid netstat because it oopes Linux 2.5.74
768    if ($uname_minus_s eq "SunOS" || $uname_minus_s eq "Darwin" || $uname_minus_s eq "AIX" || $uname_minus_s eq "Interix") {
769	if (`netstat -an` =~ /\.$port\s+.+LISTEN$/m) {
770	    return 1;
771	}
772    } elsif ($uname_minus_s eq "Linux") {
773	my $netstat = `netstat -ln --inet`;
774	if ($netstat =~ /(\:$port\s+.+LISTEN\s*)/) {
775	    #warn "MATCH netstat($netstat)";
776	    #warn "matched($1)";
777	    return 1;
778	}
779	#warn "NO MATCH netstat($netstat)";
780    } elsif (substr($uname_minus_s, 0, 9) eq "CYGWIN_NT" || $uname_minus_s eq "Windows") {
781	if (`netstat -an` =~ /\:$port\s+.+LISTENING\s*/) {
782	    return 1;
783	}
784    } else {
785	die "Can't determine system type($uname_minus_s)";
786    }
787    return 0;
788}
789
790sub check_for_udp {
791    my $port = shift @_;
792    return 1 if $always_external_test_servers;  # avoid netstat 'cause it oopes Linux 2.5.74
793    if ($uname_minus_s eq "SunOS") {         # Solaris8
794	if (`netstat -an -P udp` =~ /^\s+\*.$port\s+Idle\s*$/m) {
795	    return 1;
796	}
797    } elsif ($uname_minus_s eq "Darwin") {   # this probably works for SunOS 2.6, too
798	if (`netstat -an` =~ /^udp[\d\s.]+\.$port\s+/m) {
799	    return 1;
800	}
801    } elsif ($uname_minus_s eq "Linux") {
802	my $x = `netstat -an`;
803	#warn ">>$x<<";
804	if ($x =~ /^udp[0-9. \t]+\:$port\s+/m) {
805	    return 1;
806	}
807    } else {
808	die "Unknown system type($uname_minus_s)";
809    }
810    return 0;
811}
812
813### Wait for a network service to ramp up and start listening for a port
814
815$port_wait_secs = 10;
816
817sub wait_for_port {
818    my ($p) = @_;
819    #return 1 if $host ne 'localhost';
820    my $ret;
821    my $iter = 0;
822    my $sleep = 0.05;
823    # sleep 10; return;
824    eval {
825	local $SIG{ALRM} = sub { die "timeout\n"; };
826	alarm $port_wait_secs;
827	while (1) {
828	    last if $ret = check_for_listener($p);
829	    #warn "Waiting for exe to come up on TCP port $p" if $iter++>6;
830	    warn "Waiting for exe to come up on TCP port $p" if $iter++>1;
831	    select(undef, undef, undef, $sleep);
832	    $sleep += 0.05;
833	}
834	alarm 0;
835	#warn "out of check_for_listener($ret)";
836    };
837    if ($@) {
838	die "wait for port $p failed: $@ / $!" unless $@ eq "timeout\n";
839	warn "Port number $p did not come up LISTENing in reasonable time";
840	#success_report();
841	return undef;
842    }
843    return 1;
844}
845
846sub wait_for_udp {
847    my ($p) = @_;
848    #return 1 if $host ne 'localhost';
849    my $iter = 0;
850    my $sleep = 0.05;
851    # sleep 10; return;
852    eval {
853	local $SIG{ALRM} = sub { die "timeout\n"; };
854	alarm $port_wait_secs;
855	while (1) {
856	    last if (&check_for_udp($p));
857	    warn "Waiting for exe to come up on UDP port $p" if $iter++>6;
858	    select(undef, undef, undef, $sleep);
859	    $sleep += 0.05;
860	}
861	alarm 0;
862    };
863    if ($@) {
864	die "wait for port $p failed: $@ / $!" unless $@ eq "timeout\n";
865	warn "Port number $p did not come up LISTENing in reasonable time";
866	#success_report();
867	return undef;
868    }
869    #warn "udp $p came up";
870    return 1;
871}
872
873# Launches a server, unless one is already listening on the targeted port,
874# and arranges for logs to go to the right place.
875
876sub launch_server {
877#    for some tests to work with -e flag
878#    my ($port, $log_file, @cmd_line, $file) = @_;
879#    @cmd_line = "@cmd_line" . "$file";
880    my ($port, $log_file, @cmd_line) = @_;
881    my $pid;
882    my $devnull = "</dev/null";
883    if (substr($uname_minus_s, 0, 9) eq "CYGWIN_NT" || $uname_minus_s eq "Windows") {
884    	$devnull = "<:NUL";
885    }
886    return if $host ne 'localhost';   # Presumably it was set up somewhere else
887    return if check_for_listener($port);
888    die "Test server (port $port) died. Tried to relaunch"
889	if $relaunch_testserver{$port}++;
890    #warn "Launching @cmd_line";
891    if ($pid = fork) {
892        #warn "launched server $pid:: @cmd_line\n";
893	wait_for_port($port) or kill_child($pid) and exit 1;
894	return $pid;
895    }
896    die "fork($port) failed: $!" unless defined $pid;
897    open STDIN, $devnull;  # Keep fd 0 occupied as it has special meaning
898    warn "\nEXEC @cmd_line (>$log_file pid=$$)\n" if $show_exec;
899    open STDOUT, ">>$log_file"
900	or die "Redirect of STDOUT to $log_file failed: $!";
901    open STDERR, ">&STDOUT" or die "Redirect of STDERR failed: $!";
902    exec @cmd_line;
903    die "exec($port) failed: $!";
904}
905
906sub launch_udp_server {
907#   for some tests to work with -e flag
908#   my ($port, $log_file, @cmd_line,$file) = @_;
909#   @cmd_line = "@cmd_line" . "$file";
910    my ($port, $log_file, @cmd_line) = @_;
911    my $pid;
912    return if $host ne 'localhost';   # Presumably it was set up somewhere else
913    return if check_for_udp($port);
914    die "Test server died (port $port). Tried to relaunch"
915	if $relaunch_testserver{$port}++;
916    #warn "Launching @cmd_line";
917    if ($pid = fork) {
918	wait_for_udp($port) or kill_child($pid) and exit 1;
919	return $pid;
920    }
921    die "fork($port) failed: $!" unless defined $pid;
922    open STDIN, "</dev/null";  # Keep fd 0 occupied as it has special meaning
923    warn "\nEXEC @cmd_line (>$log_file pid=$$)\n" if $show_exec;
924    open STDOUT, ">>$log_file"
925	or die "Redirect of STDOUT to $log_file failed: $!";
926    open STDERR, ">&STDOUT" or die "Redirect of STDERR failed: $!";
927    exec @cmd_line;
928    die "exec($port) failed: $!";
929}
930
931#only kill the zxbusd that runs foo
932sub kill_server {
933    my @process=split ' ',`ps -efa | grep zxbusd | grep foo | grep -v "ps -efa"`;
934    my $proc=$process[1];
935    if ($proc){
936	kill_child($proc);
937	#The next line initialize the relaunch counter
938	$relaunch_testserver{$testserver_port}=0;
939    }
940}
941
942sub G {
943    my ($cmd, $tsti, $expl, $timeout, $slow, $url) = @_;
944    return unless $tst eq 'all' || $tst eq substr("$tsti ",0,length $tst);
945    return if $ntst && $ntst eq substr("$tsti ",0,length $ntst);
946    warn "\n======= $tsti =======";
947
948    #my ($page, $result, %headers);  Let these be global!
949    my ($proto, $host, $port, $localurl)
950	= $url =~ m%^(https?)://([^:/]+)(?:(\d+))?(/.*?)$%i;
951    my $usessl = ($proto =~ /^https$/i ? 1 : 0);
952    $port ||= $usessl?443:80;
953
954    my $test = tst_link($tsti, $expl, $url);
955    my $send_ts = Time::HiRes::time();
956    warn "HERE1 ".Time::HiRes::time() if $timeout_trace;
957    eval {
958	warn "HERE2 ".Time::HiRes::time() if $timeout_trace;
959	local $SIG{ALRM} = sub { die "TIMEOUT\n"; };
960	warn "HERE3 ".Time::HiRes::time() if $timeout_trace;
961	alarm $timeout;
962	warn "HERE4 ".Time::HiRes::time() if $timeout_trace;
963
964	($page, $result, %headers)
965	    = get_httpx($usessl, $host, $port, $localurl, $headers);
966
967	warn "HERE6 ".Time::HiRes::time() if $timeout_trace;
968    };
969    warn "HERE7 ".Time::HiRes::time() if $timeout_trace;
970    alarm 0;
971    warn "HERE8 ".Time::HiRes::time() if $timeout_trace;
972    my $status = $@;
973    warn "HERE9 ".Time::HiRes::time() if $timeout_trace;
974    my $latency = substr(Time::HiRes::time() - $send_ts, 0, 5);
975    if ($status eq "TIMEOUT\n") {
976	tst_print('col1r', 'Timeout', $latency, $slow, $test, '');
977	$@ = 0;
978	warn "Timeout ($@) ".Time::HiRes::time();
979	$timeout_trace = 1;
980    } elsif ($status) {
981	tst_print('col1r', 'Conn. Err', $latency, $slow, $test, $status);
982    } elsif ($result !~ m%^HTTP/1\.[01] 200%) {
983	tst_print('col1r', 'App Err', $latency, $slow, $test, $result);
984    } else {
985	$lasterror = 'len='.length($page);
986	tst_ok($latency, $slow, $test);
987    }
988}
989
990sub call_system {
991    my ($test, $timeout, $slow, $command_line, $exitval) = @_;
992    my $send_ts = Time::HiRes::time();
993    $? = 0;
994    warn "HERE1 ".Time::HiRes::time() if $timeout_trace;
995    eval {
996	warn "HERE2 ".Time::HiRes::time() if $timeout_trace;
997	local $SIG{ALRM} = sub { die "TIMEOUT\n"; };
998	warn "HERE3 ".Time::HiRes::time() if $timeout_trace;
999	alarm $timeout;
1000	warn "HERE4 ".Time::HiRes::time() if $timeout_trace;
1001
1002	warn "EXEC($command_line)\n" if $show_exec;
1003	system $command_line;
1004	#warn "ret($ret) exit($?): $!";
1005	warn "HERE6 ".Time::HiRes::time() if $timeout_trace;
1006    };
1007    warn "HERE7 ".Time::HiRes::time() if $timeout_trace;
1008    alarm 0;
1009    warn "HERE8 ".Time::HiRes::time() if $timeout_trace;
1010    my $latency = substr(Time::HiRes::time() - $send_ts, 0, 5);
1011    if ($@ eq "TIMEOUT\n") {
1012	tst_print('col1r', 'Timeout', $latency, $slow, $test, '');
1013	$@ = 0;
1014	warn "Timeout ($@) ".Time::HiRes::time();
1015	#$timeout_trace = 1;
1016	return -1;
1017    } elsif ($@) {
1018	tst_print('col1r', 'Conn. Err', $latency, $slow, $test, $@);
1019	return -1;
1020    } elsif ($? != $exitval) {
1021	tst_print('col1r', 'App Err', $latency, $slow, $test, "exit=$?" . ($?==-1?"$!":""));
1022	return -1;
1023    }
1024    return $latency;
1025}
1026
1027sub C { # simple command
1028    my ($tsti, $expl, $timeout, $slow, $command_line) = @_;
1029    return unless $tst eq 'all' || $tst eq substr("$tsti ",0,length $tst);
1030    return if $ntst && $ntst eq substr("$tsti ",0,length $ntst);
1031    warn "\n======= $tsti =======\n";
1032
1033    my $test = tst_link($tsti, $expl, $url);
1034    my $latency = call_system($test, $timeout, $slow, $command_line);
1035    return if $latency == -1;
1036    tst_ok($latency, $slow, $test);
1037}
1038
1039sub ED {  # enc-dec command with diff
1040    my ($tsti, $expl, $n_iter, $file, $exitval, $timeout) = @_;
1041    return unless $tst eq 'all' || $tst eq substr("$tsti ",0,length $tst);
1042    return if $ntst && $ntst eq substr("$tsti ",0,length $ntst);
1043    my $test = tst_link($tsti, $expl, '');
1044    my $slow = 0.01 * $n_iter;
1045    $timeout ||= 60;
1046
1047    unlink "tmp/$tsti.out";
1048
1049    my $latency = call_system($test, $timeout, $slow, "./zxencdectest -i $n_iter <$file >tmp/$tsti.out 2>tmp/$tsti.err", $exitval);
1050    return if $latency == -1;
1051    return if check_diff($tsti, $latency, $slow, $test);
1052    tst_ok($latency, $slow, $test);
1053}
1054
1055sub ZXC {  # zxcall
1056    my ($tsti, $expl, $n_iter, $arg, $file) = @_;
1057    return unless $tst eq 'all' || $tst eq substr("$tsti ",0,length $tst);
1058    return if $ntst && $ntst eq substr("$tsti ",0,length $ntst);
1059    my $test = tst_link($tsti, $expl, '');
1060    my $slow = 0.03 * $n_iter;
1061
1062    unlink "tmp/$tsti.out";
1063
1064    #my $latency = call_system($test, 60, $slow, "./zxcall -a http://idp.tas3.pt:8081/zxididp?o=B tastest:tas123 $arg <$file >tmp/$tsti.out 2>tmp/tst.err");
1065    my $latency = call_system($test, 60, $slow, "./zxcall -a http://idp.tas3.pt:8081/zxididp tastest:tas123 $arg <$file >tmp/$tsti.out 2>tmp/$tsti.err");
1066    return if $latency == -1;
1067
1068    #if (system "/usr/bin/diff -u t/$tsti.out tmp/$tsti.out") {
1069    #	tst_print('col1r', 'Diff Err', $latency, $slow, $test, '');
1070    #	return;
1071    #}
1072    tst_ok($latency, $slow, $test);
1073}
1074
1075sub CMD {  # command with diff
1076    my ($tsti, $expl, $cmd, $exitval, $timeout, $slow) = @_;
1077    return unless $tst eq 'all' || $tst eq substr("$tsti ",0,length $tst);
1078    return if $ntst && $ntst eq substr("$tsti ",0,length $ntst);
1079    my $test = tst_link($tsti, $expl, '');
1080    $slow ||= 0.1;
1081    $timeout ||= 60;
1082
1083    unlink "tmp/$tsti.out";
1084
1085    my $latency = call_system($test,$timeout,$slow, "$cmd >tmp/$tsti.out 2>tmp/$tsti.err", $exitval);
1086    return if $latency == -1;
1087    return if check_diff($tsti, $latency, $slow, $test);
1088    tst_ok($latency, $slow, $test);
1089}
1090
1091sub DAEMON {  # launch a daemon that can be used as test target by clients. See also KILLD.
1092    my ($tsti, $expl, $port, $cmd, $exitval, $timeout, $slow) = @_;
1093    return unless $tst eq 'all' || $tst eq substr("$tsti ",0,length $tst);
1094    return if $ntst && $ntst eq substr("$tsti ",0,length $ntst);
1095    my $test = tst_link($tsti, $expl, '');
1096    $slow ||= 0.1;
1097    $timeout ||= 60;
1098
1099    unlink "tmp/$tsti.out";
1100    unlink "tmp/$tsti.pid";
1101
1102    if ($port != -1) {
1103	if (check_for_listener($port)) {
1104	    warn "Some on is already using the port($port). Waiting a bit...";
1105	    sleep 1;
1106	    if (check_for_listener($port)) {
1107		die "Some on is already using the port($port). Test can not continue. killall...";
1108	    }
1109	}
1110    }
1111    $send_ts{$tsti} = Time::HiRes::time();
1112    my $latency = call_system($test,$timeout,$slow, "$cmd >tmp/$tsti.out 2>tmp/$tsti.err &", $exitval);
1113    return if $latency == -1;
1114
1115    if ($port != -1) {
1116	#warn "port($port)";
1117	die "Daemon not up in time" unless wait_for_port($port);
1118    }
1119    tst_ok($latency, $slow, $test);
1120}
1121
1122sub STILL {  # Check that daemon is still alive, but do not reap its results
1123    my ($tsti, $expl) = @_;
1124    return unless $tst eq 'all' || $tst eq substr("$tsti ",0,length $tst);
1125    return if $ntst && $ntst eq substr("$tsti ",0,length $ntst);
1126    my $test = tst_link($tsti, $expl, '');
1127
1128    $pid = readall("tmp/$tsti.pid");
1129    if (!kill(0, $pid)) {
1130	tst_print('col1r', 'Daemon dead', 0, 0, $test, '');
1131	return;
1132    }
1133    tst_ok(0,0, $test);
1134}
1135
1136sub KILLD {  # Collect results of a daemon (see DAEMON) after client tests.
1137    my ($tsti, $expl, $cmd, $exitval, $timeout, $slow) = @_;
1138    return unless $tst eq 'all' || $tst eq substr("$tsti ",0,length $tst);
1139    return if $ntst && $ntst eq substr("$tsti ",0,length $ntst);
1140    my $test = tst_link($tsti, $expl, '');
1141    $slow ||= 60;
1142    $timeout ||= 600;
1143    my $latency = substr(Time::HiRes::time() - $send_ts{$tsti}, 0, 5);
1144
1145    $pid = readall("tmp/$tsti.pid");
1146    if (!kill(0, $pid)) {
1147	tst_print('col1r', 'Daemon dead', $latency, $slow, $test, '');
1148	return;
1149    }
1150    kill_child($pid);
1151    return if check_diff($tsti, $latency, $slow, $test);
1152    tst_ok($latency, $slow, $test);
1153}
1154
1155##################################################################
1156### START
1157###
1158
1159$cgi = cgidec($ENV{'QUERY_STRING'} || shift);
1160$tst = $$cgi{'tst'} || 'all';
1161$ntst = $$cgi{'ntst'};
1162$diffmeth = $$cgi{'diffmeth'} || 'nodiff';
1163
1164my ($ss, $mm, $hh, $day, $mon, $year) = gmtime();
1165$ts = sprintf "%04d%02d%02d-%02d%02d%02d", $year+1900,$mon+1,$day,$hh,$mm,$ss;
1166
1167# N.B. It appears that it is very important for the table-layout: fixed
1168#      to be complemented with width: specification at table and th/td level.
1169#
1170#     <table class=line width=980><tr><td class=$class1 width=80>$status</td><td class=col2 width=50>$latency</td><td class=col3 width=50>$slow</td><td class=col4 width=300>$test</td><td class=col5>$lasterror&nbsp;</td></tr></table>
1171
1172
1173#$out =
1174syswrite STDOUT, <<HTML if !$ascii;
1175<title>ZXTEST</title>
1176<style type="text/css" media="screen, projection">
1177table.line  {  table-layout: fixed; width: 980px;  }
1178table       {  table-layout: fixed; width: 980px;  }
1179td  {  vertical-align: top;  white-space: nowrap; }
1180td.col1  {  width=80px;  padding-left: 3px; padding-right: 7px; border-right: 1px dotted #066;  }
1181td.col1r {  width=60px;  padding-left: 3px; padding-right: 7px; border-right: 1px dotted #066;  background-color: red;  }
1182td.col1g {  width=80px;  padding-left: 3px; padding-right: 7px; border-right: 1px dotted #066;  background-color: green;  }
1183td.col1y {  width=80px;  padding-left: 3px; padding-right: 7px; border-right: 1px dotted #066;  background-color: yellow;  }
1184td.col2  {  width=50px;  padding-left: 3px; padding-right: 7px; border-right: 1px dotted #066;  }
1185td.col3  {  width=50px;  padding-left: 3px; padding-right: 7px; border-right: 1px dotted #066;  }
1186td.col4  {  width=300px; padding-left: 3px; padding-right: 7px; border-right: 1px dotted #066;  }
1187td.col5  {  width=500px; padding-left: 3px; padding-right: 3px; border-right: 0px;  white-space: normal; }
1188</style>
1189<body bgcolor=white>
1190<h1>ZXID Testing Tool $ts $diffmeth</h1>
1191<a href="zxtest.pl">zxtest.pl</a>
1192<p>
1193HTML
1194    ;
1195
1196sub tst_link {
1197    my ($tsti, $expl, $url) = @_;
1198    ++$n_tst;
1199    return "$tsti $expl" if $ascii;
1200    return qq(<a href="zxtest.pl?tst=$tsti">$tsti</a> <a href="$url">*</a> $expl);
1201}
1202
1203sub tst_ok {
1204    my ($latency, $slow, $test) = @_;
1205    ++$n_tst_ok;
1206    if ($latency > $slow) {
1207	tst_print('col1y', "OK slow$ok_lvl", $latency, $slow, $test, $lasterror);
1208    } else {
1209	tst_print('col1g', "OK $ok_lvl", $latency, $slow, $test, $lasterror);
1210    }
1211}
1212
1213sub tst_print {
1214    my ($class1, $status, $latency, $slow, $test, $lasterror) = @_;
1215    if ($ascii) {
1216	$status = sprintf "%-8s", $status;
1217	$status = $class1 eq 'col1r' ? red($status) : green($status);
1218	printf "%s %-5s %-5s %-50s %s\n", $status, $latency, $slow, $test, $lasterror;
1219    } else {
1220	syswrite STDOUT, "<table class=line><tr><td class=$class1>$status</td><td class=col2>$latency</td><td class=col3>$slow</td><td class=col4>$test</td><td class=col5>$lasterror&nbsp;</td></tr></table>\n";
1221    }
1222    $tst_nl_called = 0;
1223}
1224
1225sub tst_nl {
1226    return if $tst_nl_called++;
1227    if ($ascii) {
1228	print "\n";
1229    } else {
1230	syswrite STDOUT, "<hr>\n";
1231    }
1232}
1233
1234if ($ascii) {
1235    tst_print('col1', 'STATUS', 'SECS', 'GOAL', 'TEST NAME', 'MESSAGES');
1236} else {
1237    tst_print('col1', '<b>Status</b>', '<b>Secs</b>', '<b>Goal</b>', '<b>Test name</b>', '<b>Messages</b>');
1238}
1239
1240### Service testing
1241
1242CMD('HELP1', 'zxcall -h',    "./zxcall -v -h");
1243CMD('HELP2', 'zxpasswd -h',  "./zxpasswd -v -h");
1244CMD('HELP3', 'zxcot -h',     "./zxcot -v -h");
1245CMD('HELP4', 'zxdecode -h',  "./zxdecode -v -h");
1246CMD('HELP5', 'zxlogview -h', "./zxlogview -v -h");
1247CMD('HELP6', 'zxumacall -h', "./zxumacall -v -h");
1248
1249CMD('SOENC1', 'EncDec Status',     "./zxencdectest -r 3");
1250CMD('ATORD1', 'Attribute sorting', "./zxencdectest -r 4");
1251CMD('ATCERT1', 'Attribute certificate', "./zxencdectest -r 7|wc -l");
1252CMD('TIMEGM1', 'zx_timegm leaps', "./zxencdectest -r 8");
1253
1254CMD('CONF1', 'zxcall -dc dump config',       "./zxcall -v -v -c PATH=/var/zxid/ -dc");
1255CMD('CONF2', 'zxidhlo o=d dump config',      "QUERY_STRING=o=d ./zxidhlo");
1256CMD('CONF3', 'zxidhlo o=c dump carml',       "QUERY_STRING=o=c ./zxidhlo");
1257CMD('CONF4', 'zxidhlo o=B dump metadata',    "QUERY_STRING=o=B ./zxidhlo");
1258CMD('CONF5', 'zxididp o=B dump metadata',    "QUERY_STRING=o=B ./zxididp");
1259
1260CMD('HLO1', 'zxidhlo o=M LECP check',        "QUERY_STRING=o=M ./zxidhlo");
1261CMD('HLO2', 'zxidhlo o=C CDC',               "QUERY_STRING=o=C ./zxidhlo");
1262CMD('HLO3', 'zxidhlo o=E idp select page',   "QUERY_STRING=o=E ./zxidhlo");
1263CMD('HLO4', 'zxidhlo o=L start sso failure', "QUERY_STRING=o=L ./zxidhlo");
1264CMD('HLO5', 'zxidhlo o=A artifact failure',  "QUERY_STRING=o=A ./zxidhlo");
1265CMD('HLO6', 'zxidhlo o=P POST failure',      "QUERY_STRING=o=P ./zxidhlo");
1266CMD('HLO7', 'zxidhlo o=D deleg invite fail', "QUERY_STRING=o=D ./zxidhlo");
1267CMD('HLO8', 'zxidhlo o=F not an idp fail',   "QUERY_STRING=o=F ./zxidhlo");
1268
1269CMD('IDP1', 'zxididp o=R fail', "QUERY_STRING=o=R ./zxididp");
1270CMD('IDP2', 'zxididp o=F fail', "QUERY_STRING=o=F ./zxididp");
1271CMD('IDP3', 'zxididp o=N new user fail', "QUERY_STRING=o=N ./zxididp");
1272CMD('IDP4', 'zxididp o=W pwreset fail',  "QUERY_STRING=o=W ./zxididp");
1273CMD('IDP5', 'zxididp o=S SASL Req',  "QUERY_STRING=o=S CONTENT_LENGTH=222 ./zxididp <t/sasl_req.xml");
1274
1275system 'rm -rf /var/zxid/uid/tastest';  # Delete user so we can test again
1276CMD('PW0', 'zxpasswd list user fail',   "./zxpasswd -l tastest",1024);  # no user
1277CMD('PW01', 'zxpasswd new user',    "echo tas123 | ./zxpasswd -v -new tastest");
1278CMD('PW1', 'zxpasswd list user',   "./zxpasswd -l tastest");
1279CMD('PW2', 'zxpasswd pw an ok',    "echo tas123 | ./zxpasswd -v -a tastest");
1280CMD('PW3', 'zxpasswd pw an fail',  "echo tas124 | ./zxpasswd -v -a tastest",1792);
1281
1282system 'rm -rf /var/zxid/uid/pwtest';  # Delete user so we can test again
1283CMD('PW4', 'zxpasswd create user', "echo tas125 | ./zxpasswd -t y -at 'cn: pw test user\$o: test corp' -new pwtest");
1284CMD('PW5', 'zxpasswd change pw y',   "echo tas126 | ./zxpasswd -t y pwtest");
1285CMD('PW6', 'zxpasswd list user',   "./zxpasswd -l pwtest");
1286CMD('PW7', 'zxpasswd change pw plain',   "echo tas126 | ./zxpasswd -t 0 pwtest");
1287CMD('PW8', 'zxpasswd plain an ok',   "echo tas126 | ./zxpasswd -v -a pwtest");
1288CMD('PW9', 'zxpasswd plain an fail', "echo tas127 | ./zxpasswd -v -a pwtest",1792);
1289
1290# ./zxid_httpd -p 8081 -c 'zxid*' &
1291CMD('META1', 'Java LEAF Meta', "curl 'http://sp.tas3.pt:8080/zxidservlet/wspleaf?o=B'");
1292
1293CMD('COT1', 'zxcot list',          "./zxcot");
1294CMD('COT2', 'zxcot list swap',     "./zxcot -s");
1295CMD('COT3', 'zxcot list s2',       "./zxcot -s -s");
1296CMD('COT4', 'zxcot get idp meta dry', "./zxcot -g http://idp.tas3.pt:8081/zxididp?o=B -n -v");
1297CMD('COT5', 'zxcot get sp meta dry',"./zxcot -g http://sp.tas3.pt:8080/zxidservlet/sso?o=B -n -v");
1298CMD('COT6', 'zxcot my meta',       "./zxcot -m");
1299CMD('COT7', 'zxcot my meta add',   "./zxcot -m | ./zxcot -a");
1300CMD('COT8', 'zxcot gen epr',       "./zxcot -e http://localhost:1234/ testabstract http://localhost:1234/?o=B x-impossible");
1301CMD('COT9', 'zxcot gen epr add',   "./zxcot -e http://localhost:1234/ testabstract http://localhost:1234/?o=B x-impossible | ./zxcot -b -bs");
1302CMD('COT10', 'zxcot my meta',      "./zxcot -p http://localhost:1234/?o=B");
1303CMD('COT11', 'zxcot list s2',      "./zxcot -s /var/zxid/cot");
1304
1305# ~/zxid/zxcot -c CPATH=/var/zxid/bus/ -dirs
1306# ~/zxid/zxcot -c 'CPATH=/var/zxid/bus/&NON_STANDARD_ENTITYID=stomp://localhost:2229/' -m | ~/zxid/zxcot -a
1307# ~/zxid/zxcot -c 'CPATH=/var/zxid/bus/&NON_STANDARD_ENTITYID=stomp://localhost:2229/' -m | ~/zxid/zxcot -c CPATH=/var/zxid/bus/ -a
1308
1309CMD('LOG1', 'zxlogview list',      "./zxlogview /var/zxid/pem/logsign-nopw-cert.pem /var/zxid/pem/logenc-nopw-cert.pem <t/act");
1310CMD('LOG2', 'zxlogview test',      "./zxlogview -t /var/zxid/pem/logsign-nopw-cert.pem /var/zxid/pem/logenc-nopw-cert.pem");
1311CMD('LOG3', 'zxlogview receipt',   "./zxlogview -t1");
1312
1313# See also README.smime for tutorial of these commands
1314CMD('SMIME1', 'smime key gen ca',  "echo 'commonName=TestCA|emailAddress=test\@test.com' | ./smime -kg 'description=CA' passwd tmp/careq.pem >tmp/capriv_ss.pem; wc -l tmp/capriv_ss.pem");
1315CMD('SMIME2', 'smime key gen joe', "echo 'commonName=Joe Smith|emailAddress=joe\@test.com' | ./smime -kg 'description=foo' passwd tmp/req.pem >tmp/priv_ss.pem; wc -l tmp/priv_ss.pem");
1316CMD('SMIME3', 'smime ca',          "./smime -ca tmp/capriv_ss.pem passwd 1 <tmp/req.pem >tmp/cert.pem; wc -l tmp/cert.pem");
1317CMD('SMIME4', 'smime code sig',    "./smime -ds tmp/priv_ss.pem passwd <t/XML1.out >tmp/XML1.sig; wc -l tmp/XML1.sig");
1318CMD('SMIME5', 'smime code vfy',    "cat tmp/priv_ss.pem tmp/XML1.sig |./smime -dv t/XML1.out");
1319CMD('SMIME6', 'smime sig',          "echo foo|./smime -mime text/plain|./smime -s tmp/priv_ss.pem passwd >tmp/foo.p7m; wc -l tmp/foo.p7m");
1320CMD('SMIME7', 'smime clear sig',    "echo foo|./smime -mime text/plain|./smime -cs tmp/priv_ss.pem passwd >tmp/foo.clear.smime; wc -l tmp/foo.clear.smime");
1321CMD('SMIME8', 'smime pubenc',       "echo foo|./smime -mime text/plain|./smime -e tmp/priv_ss.pem|wc -l");
1322CMD('SMIME8b', 'smime pubencdec',   "echo foo|./smime -mime text/plain|./smime -e tmp/priv_ss.pem|./smime -d tmp/priv_ss.pem passwd");
1323CMD('SMIME9', 'smime sigenc',       "echo foo|./smime -mime text/plain|./smime -cs tmp/priv_ss.pem passwd|./smime -e tmp/priv_ss.pem");
1324CMD('SMIME10', 'smime encsig',      "echo foo|./smime -mime text/plain|./smime -e tmp/priv_ss.pem|./smime -cs tmp/priv_ss.pem passwd");
1325CMD('SMIME11', 'smime multi sigenc', "echo bar|./smime -m image/gif t/XML1.out|./smime -cs tmp/priv_ss.pem passwd|./smime -e tmp/priv_ss.pem");
1326CMD('SMIME12', 'smime query sig',   "./smime -qs <tmp/foo.p7m");
1327CMD('SMIME13', 'smime verify',      "./smime -v tmp/priv_ss.pem <tmp/foo.p7m");
1328CMD('SMIME14', 'smime query cert',  "./smime -qc <tmp/cert.pem");
1329CMD('SMIME15', 'smime verify cert', "./smime -vc tmp/capriv_ss.pem <tmp/req.pem");
1330CMD('SMIME16', 'smime mime ent',    "./smime -mime text/plain <tmp/XML1.out");
1331CMD('SMIME17', 'smime mime ent b64',"./smime -mime_base64 image/gif <tmp/XML1.out");
1332CMD('SMIME18', 'smime pkcs12 exp',  "./smime -pem-p12 you\@test.com passwd pw-for-p12 <tmp/priv_ss.pem >tmp/me.p12; wc -l tmp/me.p12");
1333CMD('SMIME19', 'smime pkcs12 imp',  "./smime -p12-pem pw-for-p12 passwd <tmp/me.p12 >tmp/me.pem; wc -l tmp/me.pem");
1334CMD('SMIME20', 'smime query req',   "./smime -qr <tmp/req.pem");
1335CMD('SMIME21', 'smime covimp',      "echo foo|./smime -base64|./smime -cat|./smime -unbase64");
1336
1337#CMD('SIG1',  'sig vry shib resp',  "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <cal-private/shib-resp.xml");
1338#CMD('SIG2',  'sig vry shib post',  "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <cal-private/shib-resp.qs");
1339
1340CMD('SIG3',  'sig vry zxid resp',  "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/anrs1.xml");
1341CMD('SIG4',  'sig vry zxid post',  "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/anrs1.post");
1342
1343#CMD('SIG5',  'sig vry sm resp',    "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/siteminder-resp.xml");
1344#CMD('SIG6',  'sig vry sm post',    "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/siteminder-resp.b64");
1345
1346CMD('SIG7',  '* sig vry shib resp undecl prefix deep', "./zxdecode -v -s -s <t/shib-a7n2.xml");  # fail due to inclusive ns prefix that is declared only deep in the document
1347CMD('SIG8',  '* sig vry ping resp', "./zxdecode -v -s -s <t/ping-resp.xml");  # Ping miscanonicalizes. Fail due to lack of InclusiveNamespace/@PrefixList="xs" (and declares namespace deep in the document)
1348CMD('SIG9',  'sig vry ping post',  "./zxdecode -v -s -s <t/ping-resp.qs");
1349CMD('SIG10', 'sig vry hp a7n',     "./zxdecode -v -s -s <t/hp-a7n.xml");
1350CMD('SIG11', 'sig vry hp post',    "./zxdecode -v -s -s <t/hp-idp-post-resp.cgi");
1351CMD('SIG12', 'sig vry hp resp',    "./zxdecode -v -s -s <t/hp-idp-post-resp.xml");
1352CMD('SIG13', 'sig vry hp resp2',   "./zxdecode -v -s -s <t/hp-idp-post-resp2.xml");
1353#CMD('SIG14', 'sig vry saml artifact request',  "./zxdecode -v -s -s <t/se-req2.xml"); # no a7n
1354CMD('SIG15', 'sig vry saml artifact response', "./zxdecode -v -s -s <t/se-resp.xml");
1355CMD('SIG16', 'sig vry saml artifact response', "./zxdecode -v -s -s <t/se-req.xml");
1356CMD('SIG17', 'sig vry saml artifact response', "./zxdecode -v -s -s <t/se-artif-resp.xml");
1357#CMD('SIG18', 'sig vry prstnt-a7n',  "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/prstnt-a7n.xml");  # RSA padding check fail (wrong private key)
1358CMD('SIG18b', 'sig vry prstnt-a7n',  "./zxdecode -v -s -s <t/prstnt-a7n.xml");
1359
1360#CMD('SIG19', 'sig vry rsa-slo-req', "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/rsa-slo-req.xml");
1361#CMD('SIG20', 'sig vry rsa-a7n', "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/rsa-a7n.xml");  # RSA padding check fail (wrong private key)
1362CMD('SIG20b', 'sig vry rsa-a7n', "./zxdecode -v -s -s <t/rsa-a7n.xml");
1363#CMD('SIG21', 'sig vry rsa-a7n2', "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/rsa-a7n2.xml");  # RSA padding check fail (wrong private key)
1364CMD('SIG21b', 'sig vry rsa-a7n2', "./zxdecode -v -s -s <t/rsa-a7n2.xml");
1365#CMD('SIG22', 'sig vry rsa-idp-post',  "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/rsa-idp-post-resp.cgi");  # RSA padding check fail (wrong private key)
1366CMD('SIG22b', 'sig vry rsa-idp-post',  "./zxdecode -v -s -s <t/rsa-idp-post-resp.cgi");
1367
1368#CMD('SIG23', 'sig vry rsa-idp-post-enc-a7n', "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/rsa-idp-post-resp2.cgi");  # RSA padding check fail (wrong private key)
1369
1370#CMD('SIG24', 'sig vry protectednet-post-enc-a7n', "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/protectednet-encrypted.txt");
1371#CMD('SIG25', 'sig vry protectednet-resp-enc-a7n', "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/protectednet-encrypted.xml");
1372
1373#CMD('SIG26', 'sig vry orange simple sign', "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/orange1.post-simple-sign");  # No metadata
1374#CMD('SIG27', 'sig vry orange simple sign2', "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/orange2-sig-data.b64");  # No metadata
1375
1376#CMD('SIG28', 'sig vry ibm-enc-a7n', "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/ibm-enc-a7n.xml");
1377#CMD('SIG29', 'sig vry ibm-resp-extra-ns', "./zxdecode -v encdec-s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/ibm-resp-extra-ns.xml");  # No a7n, no metadata
1378
1379#CMD('SIG30', 'sig vry simplesamlphp enc a7n', "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/encrypted-simplesamlphp.xml"); # Messed up by whitespace
1380#CMD('SIG31', 'sig vry simplesamlphp enc post', "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/encrypted-simplesamlphp.txt"); # Messed up by whitespace
1381
1382#CMD('SIG32', 'sig vry enc-nid-enc-attr', "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/enc-nid-enc-attr.xml");  # wrong private key
1383CMD('SIG32b', 'sig vry enc-nid-enc-attr', "./zxdecode -v -s -s <t/enc-nid-enc-attr.xml");
1384#CMD('SIG33', 'sig vry a7n stijn', "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/assertion-stijn-20100108.xml");  # Corrupt with non-printable chars
1385#CMD('SIG34', 'sig vry symsp-ibmidp-slo',     "./zxdecode -v -s -s <t/symsp-ibmidp-slo.xml");
1386#CMD('SIG35', 'sig vry symsp-symidp-slo',     "./zxdecode -v -s -s <t/symsp-symidp-slo-soap.xml");
1387#CMD('SIG36', 'sig vry zxidp-ki-old',     "./zxdecode -v -s -s <t/zxidp-ki-a7n-20100906.xml"); # ***fail canon
1388CMD('SIG37', 'sig vry', "./zxdecode -v -s -s <t/enve-sigval-err.xml", 2560);
1389CMD('SIG38', 'sig vry', "./zxdecode -v -s -s <t/default-ns-req-simple.xml");
1390CMD('SIG39', 'sig vry', "./zxdecode -v -s -s <t/default-ns-req-simple-nons.xml", 2560);
1391CMD('SIG40', 'sig vry', "./zxdecode -v -s -s <t/default-ns-req.xml");
1392CMD('SIG41', 'sig vry', "./zxdecode -v -s -s <t/soag-namespace-issue.xml");
1393CMD('SIG42', 'sig vry shib a7n art',  "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/shib-a7n-art.xml");
1394CMD('SIG43', 'sig vry shib a7n art2',  "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/shib-a7n-art2.xml");
1395CMD('SIG44', 'sig vry shib a7n art3',  "./zxdecode -v -s -c AUDIENCE_FATAL=0 -c TIMEOUT_FATAL=0 -c DUP_A7N_FATAL=0 -c DUP_MSG_FATAL=0 <t/shib-a7n-art3.xml");
1396
1397ED('XML1',  'Decode-Encode SO and WO: ns-bug',  1000, 't/default-ns-bug.xml');
1398ED('XML2',  'Decode-Encode SO and WO: azrq1',   1000, 't/azrq1.xml');
1399ED('XML3',  'Decode-Encode SO and WO: azrs1',   1000, 't/azrs1.xml');
1400ED('XML4',  '* Decode-Encode RIS malformed 1',  1,    't/risaris-bad.xml');  # Order of unknown elements gets inverted
1401ED('XML5',  'Decode-Encode SO and WO: ana7n1',  1000, 't/ana7n1.xml');
1402ED('XML6',  'Decode-Encode SO and WO: anrq1',   1000, 't/anrq1.xml');
1403ED('XML7',  'Decode-Encode SO and WO: anrs1',   1000, 't/anrs1.xml');
1404ED('XML8',  'Decode-Encode SO and WO: dirq1',   1000, 't/dirq1.xml');
1405ED('XML9',  'Decode-Encode SO and WO: dirs1',   1000, 't/dirs1.xml');
1406ED('XML10', 'Decode-Encode SO and WO: dirq2',   1000, 't/dirq2.xml');
1407ED('XML11', 'Decode-Encode SO and WO: dia7n1',  1000, 't/dia7n1.xml');
1408ED('XML12', 'Decode-Encode SO and WO: epr1',    1000, 't/epr1.xml');
1409ED('XML13', 'Decode-Encode SO and WO: wsrq1',   1000, 't/wsrq1.xml');
1410ED('XML14', 'Decode-Encode SO and WO: wsrs1',   1000, 't/wsrs1.xml');
1411ED('XML15', 'Decode-Encode SO and WO: wsrq2',   1000, 't/wsrq2.xml');
1412ED('XML16', 'Decode-Encode SO and WO: wsrs2',   1000, 't/wsrs2.xml');
1413ED('XML17', 'Decode-Encode SO and WO: as-req',  1000, 't/as-req.xml');
1414ED('XML18', 'Decode-Encode SO and WO: as-resp', 1000, 't/as-resp.xml');
1415ED('XML19', 'Decode-Encode SO and WO: authnreq',1000, 't/authnreq.xml');
1416ED('XML20', 'Decode-Encode SO and WO: sun-md',  10, 't/sun-md.xml');
1417ED('XML21', 'Decode-Encode SO and WO: provisioning-req',  10, 't/pmdreg-req.xml');
1418ED('XML22', 'Decode-Encode SO and WO: provisioning-resp', 10, 't/pmdreg-resp.xml');
1419ED('XML23', 'Decode-Encode SO and WO: pds-create-uc1',    10, 't/pds-create-uc1.xml');
1420ED('XML24', 'Decode-Encode SO and WO: pds-query-uc1',     10, 't/pds-query-uc1.xml');
1421ED('XML25', 'Decode-Encode SO and WO: AdvClient hoard-trnsnt', 10, 't/ac-hoard-trnsnt.xml');
1422ED('XML26', 'Decode-Encode SO and WO: AdvClient ming-trnsnt',  10, 't/ac-ming-trnsnt.xml');
1423ED('XML27', 'Decode-Encode SO and WO: AdvClient ming-prstnt',  10, 't/ac-ming-prstnt.xml');
1424ED('XML28', 'Decode-Encode SO and WO: AdvClient ming-ntt',     10, 't/ac-ming-ntt.xml');
1425ED('XML29', 'Decode-Encode SO and WO: AdvClient ntt-fixed',    10, 't/ac-ming-ntt-fixed.xml');
1426ED('XML30', 'Decode-Encode SO and WO: zx a7n',    10, 't/a7n-len-err.xml');
1427ED('XML31', 'Decode-Encode SO and WO: covimp',    10, 't/covimp.xml');
1428ED('XML32', 'Decode-Encode SO and WO: bad-body malformed close',  10, 't/bad-body.xml');
1429ED('XML33', 'Decode-Encode SO and WO: bad-body2 malformed close', 10, 't/bad-body2.xml');
1430
1431# *** TODO: add EncDec for all other types of protocol messages
1432# *** TODO: add specific SSO signature validation tests
1433
1434# *** TODO: benchmark raw RSA performance using logging w/ zxlogview
1435
1436# /apps/bin/mini_httpd -p 8081 -c 'zxid*' &   # IdP
1437# /apps/bin/mini_httpd -p 8082 -c 'zxid*' &   # SP
1438
1439# *** TODO: set up test IdP using zxcot (for disco registrations and bootstrap) and zxpasswd
1440# *** TODO: set up test SP
1441# *** TODO: set up test WSP
1442
1443
1444ZXC('ZXC-AS1', 'Authentication Service call: SSO + AZ', 1000, "-az ''", '/dev/null');
1445CMD('ZXC-AS2', 'Authentication Service call: An Fail', "./zxcall -d -a http://idp.tas3.pt:8081/zxididp test:tas -t urn:x-foobar -e '<foobar>Hello</foobar>' -b", 256);
1446
1447ZXC('ZXC-IM1', 'Identity Mapping Service call', 1000, "-im http://sp.tas3.pt:8081/zxidhrxmlwsp?o=B", '/dev/null');
1448ZXC('ZXC-IM2', '* SAML NID Map call', 1000, "-nidmap http://sp.tas3.pt:8081/zxidhrxmlwsp?o=B", '/dev/null');  # SEGV
1449ZXC('ZXC-IM3', 'SSOS call', 1000, "-t urn:liberty:ims:2006-08", 't/ssos-req.xml');
1450
1451ZXC('ZXC-DI1', 'Discovery Service call', 1000, "-di '' -t urn:x-foobar -nd", '/dev/null');
1452ZXC('ZXC-DI2', 'List EPR cache', 1, "-l", '/dev/null');
1453
1454ZXC('ZXC-WS1', 'AS + WSF call: idhrxml',  1000, "-t urn:id-sis-idhrxml:2007-06:dst-2.1", 't/id-hrxml-rq.xml');
1455ZXC('ZXC-WS2', 'AS + WSF call: x-foobar', 1000, "-t urn:x-foobar", 't/x-foobar-rq.xml');
1456
1457CMD('ZXC-WS3', 'AS + WSF call leaf (x-recurs)', "./zxcall -d -a http://idp.tas3.pt:8081/zxididp test:foo -t x-recurs -e '<foobar>Hello</foobar>' -b");
1458CMD('ZXC-WS4', 'AS + WSF call EPR not found', "./zxcall -d -a http://idp.tas3.pt:8081/zxididp test:foo -t x-none -e '<foobar>Hello</foobar>' -b",512);
1459CMD('ZXC-WS5', 'AS + WSF call bad pw', "./zxcall -d -a http://idp.tas3.pt:8081/zxididp test:bad -t x-none -e '<foobar>Hello</foobar>' -b",256);
1460
1461CMD('ZXC-WS6', 'AS + WSF call hr-xml bad', "./zxcall -d -a http://idp.tas3.pt:8081/zxididp test:foo -t urn:id-sis-idhrxml:2007-06:dst-2.1 -e '<foobar>Hello</foobar>' -b");
1462
1463CMD('ZXC-WS7', 'AS + WSF call hr-xml create', "./zxcall -d -a http://idp.tas3.pt:8081/zxididp test:foo -t urn:id-sis-idhrxml:2007-06:dst-2.1 -e '<idhrxml:Create xmlns:idhrxml=\"urn:id-sis-idhrxml:2007-06:dst-2.1\"><idhrxml:CreateItem><idhrxml:NewData><hrxml:Candidate xmlns:hrxml=\"http://ns.hr-xml.org/2007-04-15\">test candidate</hrxml:Candidate></idhrxml:NewData></idhrxml:CreateItem></idhrxml:Create>' -b");
1464CMD('ZXC-WS8', 'AS + WSF call hr-xml query', "./zxcall -d -a http://idp.tas3.pt:8081/zxididp test:foo -t urn:id-sis-idhrxml:2007-06:dst-2.1 -e '<idhrxml:Query xmlns:idhrxml=\"urn:id-sis-idhrxml:2007-06:dst-2.1\"><idhrxml:QueryItem><idhrxml:Select>test query</idhrxml:Select></idhrxml:QueryItem></idhrxml:Query>' -b");
1465CMD('ZXC-WS9', 'AS + WSF call hr-xml mod', "./zxcall -d -a http://idp.tas3.pt:8081/zxididp test:foo -t urn:id-sis-idhrxml:2007-06:dst-2.1 -e '<idhrxml:Modify xmlns:idhrxml=\"urn:id-sis-idhrxml:2007-06:dst-2.1\"><idhrxml:ModifyItem><idhrxml:Select>test query</idhrxml:Select><idhrxml:NewData><hrxml:Candidate xmlns:hrxml=\"http://ns.hr-xml.org/2007-04-15\">test mod</hrxml:Candidate></idhrxml:NewData></idhrxml:ModifyItem></idhrxml:Modify>' -b");
1466CMD('ZXC-WS10', 'AS + WSF call hr-xml mod', "./zxcall -d -a http://idp.tas3.pt:8081/zxididp test:foo -t urn:id-sis-idhrxml:2007-06:dst-2.1 -e '<idhrxml:Delete xmlns:idhrxml=\"urn:id-sis-idhrxml:2007-06:dst-2.1\"><idhrxml:DeleteItem><idhrxml:Select>test query</idhrxml:Select></idhrxml:DeleteItem></idhrxml:Delete>' -b");
1467
1468### Simulated browsing tests (a bit fragile)
1469
1470#$idpurl='http://idp.tas3.pt:8081/zxididp';
1471
1472# sudo ./zxid_httpd -S /var/zxid/pem/enc-nopw-cert.pem -u sampo -c 'zxid*' &
1473#$idpurl='https://yourhost.example.com/zxididp';
1474#$spurl='https://yourhost.example.com/zxidhlo';
1475
1476# ./zxid_httpd -S /var/zxid/pem/enc-nopw-cert.pem -p 8443 -u sampo -c 'zxid*' &
1477$idpurl='https://yourhost.example.com:8443/zxididp';
1478$spurl='https://yourhost.example.com:8443/zxidhlo';
1479
1480CMD('META2', 'IdP meta', "curl -k $idpurl?o=B");
1481CMD('META3', 'SP meta',  "curl -k $spurl?o=B");
1482CMD('META4', 'IdP conf', "curl -k $idpurl?o=d");
1483CMD('META5', 'SP conf',  "curl -k $spurl?o=d");
1484
1485tA('ST','LOGIN-IDP1', 'IdP Login screen',  "$idpurl?o=F");
1486tA('ST','LOGIN-IDP2', 'IdP Give password', "$idpurl?au=&alp=+Login+&au=test&ap=foo&fc=1&fn=prstnt&fq=&fy=&fa=&fm=&fp=0&ff=0&ar=&zxapp=");
1487tA('ST','LOGIN-IDP3', 'IdP Local Logout',  "$idpurl?gl=+Local+Logout+");
1488
1489tA('ST','SSOHLO1', 'IdP selection screen', "$spurl?o=E");
1490tA('AR','SSOHLO2', 'Selected IdP', "$spurl?e=&l0http%3A%2F%2Fidp.tas3.pt%3A8081%2Fzxididp=+Login+with+TAS3+Demo+IdP+%28http%3A%2F%2Fidp.tas3.pt%3A8081%2Fzxididp%29+&fc=1&fn=prstnt&fr=&fq=&fy=&fa=&fm=&fp=0&ff=0");
1491
1492tA('SP','SSOHLO3', 'Login to IdP', "$idpurl?au=&alp=+Login+&au=test&ap=foo&fc=1&fn=prstnt&fq=&fy=&fa=&fm=&fp=0&ff=0&ar=$AR&zxapp=");
1493
1494pA('ST','SSOHLO4', 'POST to SP',      "$spurl?o=P", "SAMLResponse=$SAMLResponse");
1495tA('ST','SSOHLO5', 'SP SOAP Az',      "$spurl?gv=1");
1496tA('ST','SSOHLO6', 'SP SOAP defed',   "$spurl?gu=1");
1497tA('ST','SSOHLO7', 'SP SOAP defed',   "$spurl?gt=1");
1498tA('ST','SSOHLO8', 'SP SOAP logout',  "$spurl?gs=1");
1499tA('ST','SSOHLO9', 'SP local logout', "$spurl?gl=+Local+Logout+");
1500
1501#tA('ST','javaexit', 'http://sp1.zxidsp.org:8080/appdemo?exit');
1502
1503# *** TODO: add through GUI testing for SSO
1504# *** TODO: via zxidhlo
1505# *** TODO: via mod_auth_saml
1506# *** TODO: via zxidhlo.php
1507# *** TODO: via Net::SAML
1508# *** TODO: via SSO servlet
1509# http://sp1.zxidsp.org:8081/zxidhlo?o=E
1510# http://sp1.zxidsp.org:8080/zxidservlet/zxidHLO?o=E
1511# http://sp.tas3.pt:8080/zxidservlet/appdemo
1512# http://sp.tas3.pt:8080/zxidservlet/wscprepdemo
1513
1514###
1515### UMA and OAUTH2 tests
1516###
1517# ./zxid_httpd -p 8081 -c 'zxid*' &
1518
1519tA('ST','OAZ-JWKS1', 'Java Web Key Set test',  'http://idp.tas3.pt:8081/zxididp?o=j');
1520CMD('OAZ-DCR1', 'Dynamic CLient Registration', "./zxumacall -u 'http://sp.tas3.pt:8081/zxididp?o=J' -iat foobar-iat -dynclireg");
1521
1522###
1523### Audit bus tests
1524###
1525
1526# N.B. Although the nonSSL port should be 2228, we use 2229 so we can use same metadata
1527$busd_conf = "CPATH=/var/zxid/bus/&NON_STANDARD_ENTITYID=stomp://localhost:2229/";
1528$bus_cli_conf = "CPATH=/var/zxid/buscli/&BUS_URL=stomp://localhost:2229/&BUS_PW=pw123&BURL=https://buscli.zxid.org/";
1529$bus_cli_conf_badpw = "CPATH=/var/zxid/buscli/&BUS_URL=stomp://localhost:2229/&BUS_PW=pw124&BURL=https://buscli.zxid.org/";
1530$bus_list_conf = "CPATH=/var/zxid/buslist/&BUS_URL=stomp://localhost:2229/&BUS_PW=pw123&BURL=https://buslist.zxid.org/";
1531$bus_list2_conf = "CPATH=/var/zxid/buslist2/&BUS_URL=stomp://localhost:2229/&BUS_PW=pw123&BURL=https://buslist2.zxid.org/";
1532
1533# For SSL tests it is important to NOT supply BUS_PW so that ClientTLS takes precedence.
1534$bussd_conf = "CPATH=/var/zxid/bus/&NON_STANDARD_ENTITYID=stomps://localhost:2229/";
1535$buss_cli_conf = "CPATH=/var/zxid/buscli/&BUS_URL=stomps://localhost:2229/&BURL=https://buscli.zxid.org/";
1536$buss_list_conf = "CPATH=/var/zxid/buslist/&BUS_URL=stomps://localhost:2229/&BURL=https://buslist.zxid.org/";
1537$buss_list2_conf = "CPATH=/var/zxid/buslist2/&BUS_URL=stomps://localhost:2229/&BURL=https://buslist2.zxid.org/";
1538
1539# Metadata exchange
1540#./zxcot -c 'CPATH=/var/zxid/buscli/&BUS_URL=stomp://localhost:2229/&BUS_PW=pw123&BURL=https://buscli.zxid.org/' -dirs
1541#./zxcot -c 'CPATH=/var/zxid/buslist/&BUS_URL=stomp://localhost:2229/&BUS_PW=pw123&BURL=https://buslist.zxid.org/' -dirs
1542#./zxcot -c 'CPATH=/var/zxid/buslist2/&BUS_URL=stomp://localhost:2229/&BUS_PW=pw123&BURL=https://buslist2.zxid.org/' -dirs
1543
1544# Metadata from clients to server
1545# ./zxcot -c 'CPATH=/var/zxid/buscli/&BUS_URL=stomp://localhost:2229/&BUS_PW=pw123&BURL=https://buscli.zxid.org/' -m | ./zxcot -c 'CPATH=/var/zxid/bus/&NON_STANDARD_ENTITYID=stomp://localhost:2229/' -a
1546# ./zxcot -c 'CPATH=/var/zxid/buslist/&BUS_URL=stomp://localhost:2229/&BUS_PW=pw123&BURL=https://buslist.zxid.org/' -m | ./zxcot -c 'CPATH=/var/zxid/bus/&NON_STANDARD_ENTITYID=stomp://localhost:2229/' -a
1547# ./zxcot -c "CPATH=/var/zxid/buslist2/&BUS_URL=stomp://localhost:2229/&BUS_PW=pw123&BURL=https://buslist2.zxid.org/" -m | ./zxcot -c 'CPATH=/var/zxid/bus/&NON_STANDARD_ENTITYID=stomp://localhost:2229/' -a
1548
1549# Metadata from server to clients
1550# ./zxcot -c 'CPATH=/var/zxid/bus/&NON_STANDARD_ENTITYID=stomp://localhost:2229/' -m | ./zxcot -c 'CPATH=/var/zxid/buscli/&BUS_URL=stomp://localhost:2229/&BUS_PW=pw123&BURL=https://buscli.zxid.org/' -a
1551# ./zxcot -c 'CPATH=/var/zxid/bus/&NON_STANDARD_ENTITYID=stomp://localhost:2229/' -m | ./zxcot -c 'CPATH=/var/zxid/buslist/&BUS_URL=stomp://localhost:2229/&BUS_PW=pw123&BURL=https://buslist.zxid.org/' -a
1552# ./zxcot -c 'CPATH=/var/zxid/bus/&NON_STANDARD_ENTITYID=stomp://localhost:2229/' -m | ./zxcot -c 'CPATH=/var/zxid/buslist2/&BUS_URL=stomp://localhost:2229/&BUS_PW=pw123&BURL=https://buslist2.zxid.org/' -a
1553
1554# Provision bus users
1555# echo -n 'pw123' | ./zxpasswd -new 2E_uLovDu748vn9dWEM6tqVzqUQ /var/zxid/bus/uid/  # buslist
1556# echo -n 'pw123' | ./zxpasswd -new YJCLRHKIxyjlbnwT3bJrjgphlDA /var/zxid/bus/uid/  # buslist2
1557# echo -n 'pw123' | ./zxpasswd -new RjZmauuglW8TSTZjfGQ5zldszZM /var/zxid/bus/uid/  # buscli
1558
1559# To create bus users, you should follow these steps
1560# 0. Create dir: ./zxmkdirs.sh /var/zxid/buslist2/
1561# 1. Run ./zxbuslist -c 'URL=https://sp.foo.com/' -dc to determine the entity ID
1562# 2. Convert entity ID to SHA1 hash: ./zxcot -p 'http://sp.foo.com?o=B'
1563# 3. Create the user: ./zxpasswd -at 'eid: http://sp.foo.com?o=B' -new G2JpTSX_dbdJ7frhYNpKWGiMdTs /var/zxid/bus/uid/ <passwd  # N.B. the default password is pw123
1564# 4. To enable ClientTLS authentication, determine the subject_hash of
1565#    the encryption certificate and symlink that to the main account:
1566#      > openssl x509 -subject_hash -noout </var/zxid/buscli/pem/enc-nopw-cert.pem
1567#      162553b8
1568#      > ln -s /var/zxid/bus/uid/G2JpTSX_dbdJ7frhYNpKWGiMdTs /var/zxid/bus/uid/162553b8
1569
1570### Single client, various numbers of threads at zxbusd
1571
1572CMD('ZXBUS00', 'Clean', "rm -f /var/zxid/bus/ch/default/*  /var/zxid/bus/ch/default/.del/*  /var/zxid/bus/ch/default/.ack/*");
1573CMD('ZXBUS01', 'Fail connect tailf', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'failbar'", 256);
1574CMD('ZXBUS02', 'Fail connect list',  "./zxbuslist -d -d -c '$bus_list_conf'", 256);
1575
1576tst_nl();
1577DAEMON('ZXBUS10', 'zxbusd 1', 2229, "./zxbusd -pid tmp/ZXBUS10.pid -c '$busd_conf' -d -d -nthr 1 -nfd 11 -npdu 500 -p stomp:0.0.0.0:2229");
1578DAEMON('ZXBUS10b', 'zxbuslist 1', -1, "./zxbuslist -pid tmp/ZXBUS10b.pid -d -d -c '$bus_list_conf'");
1579CMD('ZXBUS11a', 'Bad pw', "./zxbustailf -d -d -c '$bus_cli_conf_badpw' -e 'foo bar'", 256);
1580CMD('ZXBUS11', 'One shot', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'foo bar'");
1581STILL('ZXBUS10b', 'zxbuslist 1 still there');
1582CMD('ZXBUS12', 'zero len', "./zxbustailf -d -d -c '$bus_cli_conf' -e ''");
1583CMD('ZXBUS13', 'len1',     "./zxbustailf -d -d -c '$bus_cli_conf' -e 'F'");
1584CMD('ZXBUS14', '10x20 battery', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'foo bar' -i 10 -is 20", 0, 60, 10);
1585CMD('ZXBUS15', 'len2',     "./zxbustailf -d -d -c '$bus_cli_conf' -e 'F'");
1586CMD('ZXBUS19', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1587KILLD('ZXBUS10b', 'collect zxbuslist 1');
1588KILLD('ZXBUS10', 'collect zxbusd 1');
1589
1590# 20 two thread debug
1591
1592tst_nl();
1593DAEMON('ZXBUS20', 'zxbusd 2', 2229, "./zxbusd -pid tmp/ZXBUS20.pid -c '$busd_conf' -d -d -nthr 2 -nfd 11 -npdu 700 -p stomp:0.0.0.0:2229");
1594DAEMON('ZXBUS20b', 'zxbuslist 1', -1, "./zxbuslist -pid tmp/ZXBUS20b.pid -d -d -c '$bus_list_conf'");
1595CMD('ZXBUS21', 'One shot', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'foo bar'");
1596CMD('ZXBUS21b','zxbuslist 2 one shot', "./zxbuslist -o 1 -d -d -c '$bus_list2_conf'");
1597CMD('ZXBUS22', 'zero len', "./zxbustailf -d -d -c '$bus_cli_conf' -e ''");
1598CMD('ZXBUS23', 'len1',     "./zxbustailf -d -d -c '$bus_cli_conf' -e 'F'");
1599CMD('ZXBUS24', '10x20 battery', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'foo bar' -i 10 -is 20", 0, 40, 10);
1600CMD('ZXBUS25', 'len2',     "./zxbustailf -d -d -c '$bus_cli_conf' -e 'F'");
1601CMD('ZXBUS29', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1602KILLD('ZXBUS20b', 'collect zxbuslist 1');
1603KILLD('ZXBUS20', 'collect zxbusd 2');
1604
1605# 30 single thread nodebug, two listeners
1606
1607tst_nl();
1608DAEMON('ZXBUS30', 'zxbusd 3', 2229, "./zxbusd -pid tmp/ZXBUS30.pid -c '$busd_conf' -nthr 1 -nfd 1000 -npdu 5000 -p stomp:0.0.0.0:2229");
1609DAEMON('ZXBUS30b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUS30b.pid -c '$bus_list_conf'");
1610CMD('ZXBUS31', 'One shot', "./zxbustailf -c '$bus_cli_conf' -e 'foo bar'");
1611DAEMON('ZXBUS31b','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUS31b.pid -c '$bus_list2_conf'");
1612CMD('ZXBUS32', 'zero len', "./zxbustailf -c '$bus_cli_conf' -e ''");
1613CMD('ZXBUS33', 'len1',     "./zxbustailf -c '$bus_cli_conf' -e 'F'");
1614CMD('ZXBUS34', '10x20 battery', "./zxbustailf -c '$bus_cli_conf' -e 'foo bar' -i 10 -is 20", 0, 40, 10);
1615CMD('ZXBUS35', 'len2',     "./zxbustailf -c '$bus_cli_conf' -e 'F'");
1616CMD('ZXBUS39', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1617KILLD('ZXBUS30b', 'collect zxbuslist 1');
1618KILLD('ZXBUS31b', 'collect zxbuslist 2');
1619KILLD('ZXBUS30', 'collect zxbusd 3');
1620
1621# 40 two thread nodebug, two listeners
1622
1623tst_nl();
1624DAEMON('ZXBUS40', 'zxbusd 4', 2229, "./zxbusd -pid tmp/ZXBUS40.pid -c '$busd_conf' -nthr 2 -nfd 1000 -npdu 5000 -p stomp:0.0.0.0:2229");
1625DAEMON('ZXBUS40b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUS40b.pid -c '$bus_list_conf'");
1626CMD('ZXBUS41', 'One shot', "./zxbustailf -c '$bus_cli_conf' -e 'foo bar'");
1627sleep(1);
1628CMD('ZXBUS41b','zxbuslist 2 one shot', "./zxbuslist -o 1 -d -d -c '$bus_list2_conf'", 0, 10, 1);
1629CMD('ZXBUS42', 'zero len', "./zxbustailf -c '$bus_cli_conf' -e ''");
1630DAEMON('ZXBUS42b','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUS42b.pid -c '$bus_list2_conf'");
1631CMD('ZXBUS43', 'len1',     "./zxbustailf -c '$bus_cli_conf' -e 'F'");
1632CMD('ZXBUS44', '10x20 battery', "./zxbustailf -c '$bus_cli_conf' -e 'foo bar' -i 10 -is 20", 0, 60, 10);
1633CMD('ZXBUS45', 'len2',     "./zxbustailf -c '$bus_cli_conf' -e 'F'");
1634CMD('ZXBUS49', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1635KILLD('ZXBUS40b', 'collect zxbuslist 1');
1636KILLD('ZXBUS42b', 'collect zxbuslist 2');
1637KILLD('ZXBUS40', 'collect zxbusd 4');
1638
1639# *** add tests with some listeners offline and coming back online later
1640
1641# 50 three thread debug
1642
1643tst_nl();
1644DAEMON('ZXBUS50', 'zxbusd 5', 2229, "./zxbusd -pid tmp/ZXBUS50.pid -c '$busd_conf' -d -d -nthr 3 -nfd 1000 -npdu 5000 -p stomp:0.0.0.0:2229");
1645DAEMON('ZXBUS50b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUS50b.pid -d -d -c '$bus_list_conf'");
1646CMD('ZXBUS51', 'One shot', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'foo bar'");
1647CMD('ZXBUS52', 'zero len', "./zxbustailf -d -d -c '$bus_cli_conf' -e ''");
1648CMD('ZXBUS52b','zxbuslist 2 one shot',  "./zxbuslist -o 1 -d -d -c '$bus_list2_conf'", 0, 10, 1);
1649CMD('ZXBUS52c','zxbuslist 2 one shot2', "./zxbuslist -o -1 -d -d -c '$bus_list2_conf'", 0, 10, 1);
1650CMD('ZXBUS53', 'len1',     "./zxbustailf -d -d -c '$bus_cli_conf' -e 'F'");
1651DAEMON('ZXBUS53b','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUS53b.pid -d -d -c '$bus_list2_conf'");
1652CMD('ZXBUS54', '10x20 battery', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'foo bar' -i 10 -is 20", 0, 40, 10);
1653CMD('ZXBUS55', 'len2',     "./zxbustailf -d -d -c '$bus_cli_conf' -e 'F'");
1654CMD('ZXBUS59', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1655KILLD('ZXBUS50b', 'collect zxbuslist 1');
1656KILLD('ZXBUS53b', 'collect zxbuslist 2');
1657KILLD('ZXBUS50', 'collect zxbusd 5');
1658
1659# 60 three thread nodebug
1660
1661tst_nl();
1662DAEMON('ZXBUS60', 'zxbusd 6', 2229, "./zxbusd -pid tmp/ZXBUS60.pid -c '$busd_conf' -nthr 3 -nfd 1000 -npdu 5000 -p stomp:0.0.0.0:2229");
1663DAEMON('ZXBUS60b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUS60b.pid -d -d -c '$bus_list_conf'");
1664CMD('ZXBUS61', 'One shot', "./zxbustailf -c '$bus_cli_conf' -e 'foo bar'");
1665CMD('ZXBUS62', 'zero len', "./zxbustailf -c '$bus_cli_conf' -e ''");
1666CMD('ZXBUS62b','zxbuslist 2 one shot',  "./zxbuslist -o 1 -d -d -c '$bus_list2_conf'", 0, 10, 1);
1667CMD('ZXBUS63', 'len1',     "./zxbustailf -c '$bus_cli_conf' -e 'F'");
1668DAEMON('ZXBUS63b','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUS63b.pid -d -d -c '$bus_list2_conf'");
1669CMD('ZXBUS64', '10x20 battery', "./zxbustailf -c '$bus_cli_conf' -e 'foo bar' -i 10 -is 20", 0, 40, 10);
1670CMD('ZXBUS65', 'len2',     "./zxbustailf -c '$bus_cli_conf' -e 'F'");
1671CMD('ZXBUS69', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1672KILLD('ZXBUS60b', 'collect zxbuslist 1');
1673KILLD('ZXBUS63b', 'collect zxbuslist 2');
1674KILLD('ZXBUS60', 'collect zxbusd 6');
1675
1676# 70 ten thread debug
1677
1678tst_nl();
1679DAEMON('ZXBUS70', 'zxbusd 7', 2229, "./zxbusd -pid tmp/ZXBUS70.pid -c '$busd_conf' -d -d -nthr 10 -nfd 1000 -npdu 5000 -p stomp:0.0.0.0:2229");
1680DAEMON('ZXBUS70b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUS70b.pid -d -d -c '$bus_list_conf'");
1681CMD('ZXBUS71', 'One shot', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'foo bar'");
1682CMD('ZXBUS72', 'zero len', "./zxbustailf -d -d -c '$bus_cli_conf' -e ''");
1683CMD('ZXBUS72b','zxbuslist 2 one shot',  "./zxbuslist -o 1 -d -d -c '$bus_list2_conf'", 0, 10, 1);
1684CMD('ZXBUS73', 'len1',     "./zxbustailf -d -d -c '$bus_cli_conf' -e 'F'");
1685DAEMON('ZXBUS73b','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUS73b.pid -d -d -c '$bus_list2_conf'");
1686CMD('ZXBUS74', '10x20 battery', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'foo bar' -i 10 -is 20", 0, 40, 10);
1687CMD('ZXBUS75', 'len2',     "./zxbustailf -d -d -c '$bus_cli_conf' -e 'F'");
1688CMD('ZXBUS79', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1689KILLD('ZXBUS70b', 'collect zxbuslist 1');
1690KILLD('ZXBUS73b', 'collect zxbuslist 2');
1691KILLD('ZXBUS70', 'collect zxbusd 7');
1692
1693# 80 ten thread nodebug
1694
1695tst_nl();
1696DAEMON('ZXBUS80', 'zxbusd 8', 2229, "./zxbusd -pid tmp/ZXBUS80.pid -c '$busd_conf' -nthr 10 -nfd 1000 -npdu 5000 -p stomp:0.0.0.0:2229");
1697DAEMON('ZXBUS80b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUS80b.pid -d -d -c '$bus_list_conf'");
1698CMD('ZXBUS81', 'One shot', "./zxbustailf -c '$bus_cli_conf' -e 'foo bar'");
1699CMD('ZXBUS82', 'zero len', "./zxbustailf -c '$bus_cli_conf' -e ''");
1700CMD('ZXBUS82b','zxbuslist 2 one shot',  "./zxbuslist -o 1 -d -d -c '$bus_list2_conf'", 0, 10, 1);
1701CMD('ZXBUS83', 'len1',     "./zxbustailf -c '$bus_cli_conf' -e 'F'");
1702DAEMON('ZXBUS83b','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUS83b.pid -d -d -c '$bus_list2_conf'");
1703CMD('ZXBUS84', '10x20 battery', "./zxbustailf -c '$bus_cli_conf' -e 'foo bar' -i 10 -is 20", 0, 40, 10);
1704CMD('ZXBUS85', 'len2',     "./zxbustailf -c '$bus_cli_conf' -e 'F'");
1705CMD('ZXBUS89', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1706KILLD('ZXBUS80b', 'collect zxbuslist 1');
1707KILLD('ZXBUS83b', 'collect zxbuslist 2');
1708KILLD('ZXBUS80', 'collect zxbusd 8');
1709
1710### Single client using SSL, various numbers of threads at zxbusd
1711
1712tst_nl();
1713CMD('ZXBUSS00', 'Clean', "rm -f /var/zxid/bus/ch/default/*  /var/zxid/bus/ch/default/.del/*  /var/zxid/bus/ch/default/.ack/*");
1714CMD('ZXBUSS01', 'Fail connect tailf', "./zxbustailf -d -d -c '$buss_cli_conf' -e 'failbar'", 256);
1715CMD('ZXBUSS02', 'Fail connect list',  "./zxbuslist -d -d -c '$buss_list_conf'", 256);
1716
1717DAEMON('ZXBUSS10', 'zxbusd 1', 2229, "./zxbusd -pid tmp/ZXBUSS10.pid -c '$bussd_conf' -d -d -nthr 1 -nfd 13 -npdu 500 -p stomps:0.0.0.0:2229");
1718# *** The current version (20120911) has a bug in that first SSL connection fails.
1719# *** Thus we send this priming connection to enable all the rest work.
1720#CMD('ZXBUSS10a','zxbuslist 1 prime-bug', "./zxbuslist -o -1 -d -d -c '$buss_list_conf'", 36096);
1721DAEMON('ZXBUSS10b', 'zxbuslist 1', -1, "./zxbuslist -pid tmp/ZXBUSS10b.pid -d -d -c '$buss_list_conf'");
1722CMD('ZXBUSS11', 'One shot', "./zxbustailf -d -d -c '$buss_cli_conf' -e 'foo bar'");
1723STILL('ZXBUSS10b', 'zxbuslist 1 still there');
1724CMD('ZXBUSS12', 'zero len', "./zxbustailf -d -d -c '$buss_cli_conf' -e ''");
1725CMD('ZXBUSS13', 'len1',     "./zxbustailf -d -d -c '$buss_cli_conf' -e 'F'");
1726CMD('ZXBUSS14', '10x20 battery', "./zxbustailf -d -d -c '$buss_cli_conf' -e 'foo bar' -i 10 -is 20", 0, 60, 10);
1727CMD('ZXBUSS15', 'len2',     "./zxbustailf -d -d -c '$buss_cli_conf' -e 'F'");
1728CMD('ZXBUSS19', 'dump',     "./zxbustailf -c '$buss_cli_conf' -ctl 'dump'");
1729KILLD('ZXBUSS10b', 'collect zxbuslist 1');
1730KILLD('ZXBUSS10', 'collect zxbusd 1');
1731
1732# 20 two thread debug
1733
1734tst_nl();
1735DAEMON('ZXBUSS20', 'zxbusd 2', 2229, "./zxbusd -pid tmp/ZXBUSS20.pid -c '$bussd_conf' -d -d -nthr 2 -nfd 13 -npdu 900 -p stomps:0.0.0.0:2229");
1736#CMD('ZXBUSS20a','zxbuslist 1 prime-bug', "./zxbuslist -o -1 -d -d -c '$buss_list_conf'", 36096);
1737DAEMON('ZXBUSS20b', 'zxbuslist 1', -1, "./zxbuslist -pid tmp/ZXBUSS20b.pid -d -d -c '$buss_list_conf'");
1738CMD('ZXBUSS21', 'One shot', "./zxbustailf -d -d -c '$buss_cli_conf' -e 'foo bar'");
1739CMD('ZXBUSS21b','zxbuslist 2 one shot', "./zxbuslist -o 1 -d -d -c '$buss_list2_conf'");
1740CMD('ZXBUSS22', 'zero len', "./zxbustailf -d -d -c '$buss_cli_conf' -e ''");
1741CMD('ZXBUSS23', 'len1',     "./zxbustailf -d -d -c '$buss_cli_conf' -e 'F'");
1742CMD('ZXBUSS24', '10x20 battery', "./zxbustailf -d -d -c '$buss_cli_conf' -e 'foo bar' -i 10 -is 20", 0, 60, 10);
1743CMD('ZXBUSS25', 'len2',     "./zxbustailf -d -d -c '$buss_cli_conf' -e 'F'");
1744CMD('ZXBUSS29', 'dump',     "./zxbustailf -c '$buss_cli_conf' -ctl 'dump'");
1745KILLD('ZXBUSS20b', 'collect zxbuslist 1');
1746KILLD('ZXBUSS20', 'collect zxbusd 2');
1747
1748# 30 single thread nodebug, two listener clients
1749
1750tst_nl();
1751DAEMON('ZXBUSS30', 'zxbusd 3', 2229, "./zxbusd -pid tmp/ZXBUSS30.pid -c '$bussd_conf' -nthr 1 -nfd 1000 -npdu 5000 -p stomps:0.0.0.0:2229");
1752#CMD('ZXBUSS30a','zxbuslist 1 prime-bug', "./zxbuslist -o -1 -d -d -c '$buss_list_conf'", 36096);
1753DAEMON('ZXBUSS30b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSS30b.pid -c '$buss_list_conf'");
1754CMD('ZXBUSS31', 'One shot', "./zxbustailf -c '$buss_cli_conf' -e 'foo bar'");
1755DAEMON('ZXBUSS31b','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSS31b.pid -c '$buss_list2_conf'");
1756CMD('ZXBUSS32', 'zero len', "./zxbustailf -c '$buss_cli_conf' -e ''");
1757CMD('ZXBUSS33', 'len1',     "./zxbustailf -c '$buss_cli_conf' -e 'F'");
1758CMD('ZXBUSS34', '10x20 battery', "./zxbustailf -c '$buss_cli_conf' -e 'foo bar' -i 10 -is 20", 0, 60, 10);
1759CMD('ZXBUSS35', 'len2',     "./zxbustailf -c '$buss_cli_conf' -e 'F'");
1760CMD('ZXBUSS39', 'dump',     "./zxbustailf -c '$buss_cli_conf' -ctl 'dump'");
1761KILLD('ZXBUSS30b', 'collect zxbuslist 1');
1762KILLD('ZXBUSS31b', 'collect zxbuslist 2');
1763KILLD('ZXBUSS30', 'collect zxbusd 3');
1764
1765# 40 two thread nodebug, two listeners
1766
1767tst_nl();
1768DAEMON('ZXBUSS40', 'zxbusd 4', 2229, "./zxbusd -pid tmp/ZXBUSS40.pid -c '$bussd_conf' -nthr 2 -nfd 1000 -npdu 5000 -p stomps:0.0.0.0:2229");
1769#CMD('ZXBUSS40a','zxbuslist 1 prime-bug', "./zxbuslist -o -1 -d -d -c '$buss_list_conf'", 36096);
1770DAEMON('ZXBUSS40b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSS40b.pid -c '$buss_list_conf'");
1771CMD('ZXBUSS41', 'One shot', "./zxbustailf -c '$buss_cli_conf' -e 'foo bar'");
1772sleep(1);
1773CMD('ZXBUSS41b','zxbuslist 2 one shot', "./zxbuslist -o 1 -d -d -c '$buss_list2_conf'", 0, 10, 1);
1774CMD('ZXBUSS42', 'zero len', "./zxbustailf -c '$buss_cli_conf' -e ''");
1775DAEMON('ZXBUSS42b','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSS42b.pid -c '$buss_list2_conf'");
1776CMD('ZXBUSS43', 'len1',     "./zxbustailf -c '$buss_cli_conf' -e 'F'");
1777CMD('ZXBUSS44', '10x20 battery', "./zxbustailf -c '$buss_cli_conf' -e 'foo bar' -i 10 -is 20", 0, 60, 10);
1778CMD('ZXBUSS45', 'len2',     "./zxbustailf -c '$buss_cli_conf' -e 'F'");
1779CMD('ZXBUSS49', 'dump',     "./zxbustailf -c '$buss_cli_conf' -ctl 'dump'");
1780KILLD('ZXBUSS40b', 'collect zxbuslist 1');
1781KILLD('ZXBUSS42b', 'collect zxbuslist 2');
1782KILLD('ZXBUSS40', 'collect zxbusd 4');
1783
1784# *** add tests with some listeners offline and coming back online later
1785
1786# 50 three thread debug
1787
1788tst_nl();
1789DAEMON('ZXBUSS50', 'zxbusd 5', 2229, "./zxbusd -pid tmp/ZXBUSS50.pid -c '$bussd_conf' -d -d -nthr 3 -nfd 1000 -npdu 5000 -p stomps:0.0.0.0:2229");
1790#CMD('ZXBUSS50a','zxbuslist 1 prime-bug', "./zxbuslist -o -1 -d -d -c '$buss_list_conf'", 36096);
1791DAEMON('ZXBUSS50b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSS50b.pid -d -d -c '$buss_list_conf'");
1792CMD('ZXBUSS51', 'One shot', "./zxbustailf -d -d -c '$buss_cli_conf' -e 'foo bar'");
1793CMD('ZXBUSS52', 'zero len', "./zxbustailf -d -d -c '$buss_cli_conf' -e ''");
1794CMD('ZXBUSS52b','zxbuslist 2 one shot',  "./zxbuslist -o 1 -d -d -c '$buss_list2_conf'", 0, 10, 1);
1795CMD('ZXBUSS52c','zxbuslist 2 one shot2', "./zxbuslist -o -1 -d -d -c '$buss_list2_conf'", 0, 10, 1);
1796CMD('ZXBUSS53', 'len1',     "./zxbustailf -d -d -c '$buss_cli_conf' -e 'F'");
1797DAEMON('ZXBUSS53b','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSS53b.pid -d -d -c '$buss_list2_conf'");
1798CMD('ZXBUSS54', '10x20 battery', "./zxbustailf -d -d -c '$buss_cli_conf' -e 'foo bar' -i 10 -is 20", 0, 60, 10);
1799CMD('ZXBUSS55', 'len2',     "./zxbustailf -d -d -c '$buss_cli_conf' -e 'F'");
1800CMD('ZXBUSS59', 'dump',     "./zxbustailf -c '$buss_cli_conf' -ctl 'dump'");
1801KILLD('ZXBUSS50b', 'collect zxbuslist 1');
1802KILLD('ZXBUSS53b', 'collect zxbuslist 2');
1803KILLD('ZXBUSS50', 'collect zxbusd 5');
1804
1805# 60 three thread nodebug
1806
1807tst_nl();
1808DAEMON('ZXBUSS60', 'zxbusd 6', 2229, "./zxbusd -pid tmp/ZXBUSS60.pid -c '$bussd_conf' -nthr 3 -nfd 1000 -npdu 5000 -p stomps:0.0.0.0:2229");
1809#CMD('ZXBUSS60a','zxbuslist 1 prime-bug', "./zxbuslist -o -1 -d -d -c '$buss_list_conf'", 36096);
1810DAEMON('ZXBUSS60b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSS60b.pid -d -d -c '$buss_list_conf'");
1811CMD('ZXBUSS61', 'One shot', "./zxbustailf -c '$buss_cli_conf' -e 'foo bar'");
1812CMD('ZXBUSS62', 'zero len', "./zxbustailf -c '$buss_cli_conf' -e ''");
1813CMD('ZXBUSS62b','zxbuslist 2 one shot',  "./zxbuslist -o 1 -d -d -c '$buss_list2_conf'", 0, 10, 1);
1814CMD('ZXBUSS63', 'len1',     "./zxbustailf -c '$buss_cli_conf' -e 'F'");
1815DAEMON('ZXBUSS63b','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSS63b.pid -d -d -c '$buss_list2_conf'");
1816CMD('ZXBUSS64', '10x20 battery', "./zxbustailf -c '$buss_cli_conf' -e 'foo bar' -i 10 -is 20", 0, 60, 10);
1817CMD('ZXBUSS65', 'len2',     "./zxbustailf -c '$buss_cli_conf' -e 'F'");
1818CMD('ZXBUSS69', 'dump',     "./zxbustailf -c '$buss_cli_conf' -ctl 'dump'");
1819KILLD('ZXBUSS60b', 'collect zxbuslist 1');
1820KILLD('ZXBUSS63b', 'collect zxbuslist 2');
1821KILLD('ZXBUSS60', 'collect zxbusd 6');
1822
1823# 70 ten thread debug
1824
1825tst_nl();
1826DAEMON('ZXBUSS70', 'zxbusd 7', 2229, "./zxbusd -pid tmp/ZXBUSS70.pid -c '$bussd_conf' -d -d -nthr 10 -nfd 1000 -npdu 5000 -p stomps:0.0.0.0:2229");
1827#CMD('ZXBUSS70a','zxbuslist 1 prime-bug', "./zxbuslist -o -1 -d -d -c '$buss_list_conf'", 36096);
1828DAEMON('ZXBUSS70b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSS70b.pid -d -d -c '$buss_list_conf'");
1829CMD('ZXBUSS71', 'One shot', "./zxbustailf -d -d -c '$buss_cli_conf' -e 'foo bar'");
1830CMD('ZXBUSS72', 'zero len', "./zxbustailf -d -d -c '$buss_cli_conf' -e ''");
1831CMD('ZXBUSS72b','zxbuslist 2 one shot',  "./zxbuslist -o 1 -d -d -c '$buss_list2_conf'", 0, 10, 1);
1832CMD('ZXBUSS73', 'len1',     "./zxbustailf -d -d -c '$buss_cli_conf' -e 'F'");
1833DAEMON('ZXBUSS73b','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSS73b.pid -d -d -c '$buss_list2_conf'");
1834CMD('ZXBUSS74', '10x20 battery', "./zxbustailf -d -d -c '$buss_cli_conf' -e 'foo bar' -i 10 -is 20", 0, 60, 10);
1835CMD('ZXBUSS75', 'len2',     "./zxbustailf -d -d -c '$buss_cli_conf' -e 'F'");
1836CMD('ZXBUSS79', 'dump',     "./zxbustailf -c '$buss_cli_conf' -ctl 'dump'");
1837KILLD('ZXBUSS70b', 'collect zxbuslist 1');
1838KILLD('ZXBUSS73b', 'collect zxbuslist 2');
1839KILLD('ZXBUSS70', 'collect zxbusd 7');
1840
1841# 80 ten thread nodebug
1842
1843tst_nl();
1844DAEMON('ZXBUSS80', 'zxbusd 8', 2229, "./zxbusd -pid tmp/ZXBUSS80.pid -c '$bussd_conf' -nthr 10 -nfd 1000 -npdu 5000 -p stomps:0.0.0.0:2229");
1845#CMD('ZXBUSS80a','zxbuslist 1 prime-bug', "./zxbuslist -o -1 -d -d -c '$buss_list_conf'", 36096);
1846DAEMON('ZXBUSS80b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSS80b.pid -d -d -c '$buss_list_conf'");
1847CMD('ZXBUSS81', 'One shot', "./zxbustailf -c '$buss_cli_conf' -e 'foo bar'");
1848CMD('ZXBUSS82', 'zero len', "./zxbustailf -c '$buss_cli_conf' -e ''");
1849CMD('ZXBUSS82b','zxbuslist 2 one shot',  "./zxbuslist -o 1 -d -d -c '$buss_list2_conf'", 0, 10, 1);
1850CMD('ZXBUSS83', 'len1',     "./zxbustailf -c '$buss_cli_conf' -e 'F'");
1851DAEMON('ZXBUSS83b','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSS83b.pid -d -d -c '$buss_list2_conf'");
1852CMD('ZXBUSS84', '10x20 battery', "./zxbustailf -c '$buss_cli_conf' -e 'foo bar' -i 10 -is 20", 0, 60, 10);
1853CMD('ZXBUSS85', 'len2',     "./zxbustailf -c '$buss_cli_conf' -e 'F'");
1854CMD('ZXBUSS89', 'dump',     "./zxbustailf -c '$buss_cli_conf' -ctl 'dump'");
1855KILLD('ZXBUSS80b', 'collect zxbuslist 1');
1856KILLD('ZXBUSS83b', 'collect zxbuslist 2');
1857KILLD('ZXBUSS80', 'collect zxbusd 8');
1858
1859### Dual threaded client, various numbers of threads at zxbusd
1860
1861tst_nl();
1862CMD('ZXBUSD00', 'Clean', "rm -f /var/zxid/bus/ch/default/*  /var/zxid/bus/ch/default/.del/*  /var/zxid/bus/ch/default/.ack/*");
1863
1864tst_nl();
1865DAEMON('ZXBUSD10', 'zxbusd 1', 2229, "./zxbusd -pid tmp/ZXBUSD10.pid -c '$busd_conf' -d -d -nthr 1 -nfd 30 -npdu 1000 -p stomp:0.0.0.0:2229");
1866DAEMON('ZXBUSD10b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSD10b.pid -d -d -c '$bus_list_conf'");
1867DAEMON('ZXBUSD10c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSD10c.pid -d -d -c '$bus_list2_conf'");
1868CMD('ZXBUSD12', 'zxbuslist 2 fail one shot',  "./zxbuslist -o 1 -d -d -c '$buss_list2_conf'", 256, 10, 1);
1869CMD('ZXBUSD14', '2x10x20 battery', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'foo bar' -it 2 -i 10 -is 20", 0, 90, 10);
1870CMD('ZXBUSD19', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1871KILLD('ZXBUSD10b', 'collect zxbuslist 1');
1872KILLD('ZXBUSD10c', 'collect zxbuslist 2');
1873KILLD('ZXBUSD10',  'collect zxbusd 1');
1874
1875tst_nl();
1876DAEMON('ZXBUSD20', 'zxbusd 2', 2229, "./zxbusd -pid tmp/ZXBUSD20.pid -c '$busd_conf' -d -d -nthr 2 -nfd 30 -npdu 1000 -p stomp:0.0.0.0:2229");
1877DAEMON('ZXBUSD20b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSD20b.pid -d -d -c '$bus_list_conf'");
1878DAEMON('ZXBUSD20c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSD20c.pid -d -d -c '$bus_list2_conf'");
1879CMD('ZXBUSD24', '2x10x20 battery', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'foo bar' -it 2 -i 10 -is 20", 0, 180, 10);
1880CMD('ZXBUSD29', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1881KILLD('ZXBUSD20b', 'collect zxbuslist 1');
1882KILLD('ZXBUSD20c', 'collect zxbuslist 2');
1883KILLD('ZXBUSD20', 'collect zxbusd 2');
1884
1885tst_nl();
1886DAEMON('ZXBUSD30', 'zxbusd 3', 2229, "./zxbusd -pid tmp/ZXBUSD30.pid -c '$busd_conf' -nthr 1 -nfd 30 -npdu 1000 -p stomp:0.0.0.0:2229");
1887DAEMON('ZXBUSD30b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSD30b.pid -d -d -c '$bus_list_conf'");
1888DAEMON('ZXBUSD30c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSD30c.pid -d -d -c '$bus_list2_conf'");
1889CMD('ZXBUSD34', '2x10x20 battery', "./zxbustailf -c '$bus_cli_conf' -e 'foo bar' -it 2 -i 10 -is 20", 0, 120, 10);
1890CMD('ZXBUSD39', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1891KILLD('ZXBUSD30b', 'collect zxbuslist 1');
1892KILLD('ZXBUSD30c', 'collect zxbuslist 2');
1893KILLD('ZXBUSD30', 'collect zxbusd 3');
1894
1895tst_nl();
1896DAEMON('ZXBUSD40', 'zxbusd 4', 2229, "./zxbusd -pid tmp/ZXBUSD40.pid -c '$busd_conf' -nthr 2 -nfd 30 -npdu 1000 -p stomp:0.0.0.0:2229");
1897DAEMON('ZXBUSD40b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSD40b.pid -d -d -c '$bus_list_conf'");
1898DAEMON('ZXBUSD40c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSD40c.pid -d -d -c '$bus_list2_conf'");
1899CMD('ZXBUSD44', '2x10x20 battery', "./zxbustailf -c '$bus_cli_conf' -e 'foo bar' -it 2 -i 10 -is 20", 0, 120, 10);
1900CMD('ZXBUSD49', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1901KILLD('ZXBUSD40b', 'collect zxbuslist 1');
1902KILLD('ZXBUSD40c', 'collect zxbuslist 2');
1903KILLD('ZXBUSD40', 'collect zxbusd 4');
1904
1905tst_nl();
1906DAEMON('ZXBUSD50', 'zxbusd 5', 2229, "./zxbusd -pid tmp/ZXBUSD50.pid -c '$busd_conf' -d -d -nthr 3 -nfd 30 -npdu 1000 -p stomp:0.0.0.0:2229");
1907DAEMON('ZXBUSD50b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSD50b.pid -d -d -c '$bus_list_conf'");
1908DAEMON('ZXBUSD50c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSD50c.pid -d -d -c '$bus_list2_conf'");
1909CMD('ZXBUSD54', '2x10x20 battery', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'foo bar' -it 2 -i 10 -is 20", 0, 120, 10);
1910CMD('ZXBUSD59', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1911KILLD('ZXBUSD50b', 'collect zxbuslist 1');
1912KILLD('ZXBUSD50c', 'collect zxbuslist 2');
1913KILLD('ZXBUSD50', 'collect zxbusd 5');
1914
1915tst_nl();
1916DAEMON('ZXBUSD60', 'zxbusd 6', 2229, "./zxbusd -pid tmp/ZXBUSD60.pid -c '$busd_conf' -nthr 3 -nfd 30 -npdu 1000 -p stomp:0.0.0.0:2229");
1917DAEMON('ZXBUSD60b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSD60b.pid -d -d -c '$bus_list_conf'");
1918DAEMON('ZXBUSD60c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSD60c.pid -d -d -c '$bus_list2_conf'");
1919CMD('ZXBUSD64', '2x10x20 battery', "./zxbustailf -c '$bus_cli_conf' -e 'foo bar' -it 2 -i 10 -is 20", 0, 120, 10);
1920CMD('ZXBUSD69', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1921KILLD('ZXBUSD60b', 'collect zxbuslist 1');
1922KILLD('ZXBUSD60c', 'collect zxbuslist 2');
1923KILLD('ZXBUSD60', 'collect zxbusd 6');
1924
1925tst_nl();
1926DAEMON('ZXBUSD70', 'zxbusd 7', 2229, "./zxbusd -pid tmp/ZXBUSD70.pid -c '$busd_conf' -d -d -nthr 10 -nfd 30 -npdu 1000 -p stomp:0.0.0.0:2229");
1927DAEMON('ZXBUSD70b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSD70b.pid -d -d -c '$bus_list_conf'");
1928DAEMON('ZXBUSD70c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSD70c.pid -d -d -c '$bus_list2_conf'");
1929CMD('ZXBUSD74', '2x10x20 battery', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'foo bar' -it 2 -i 10 -is 20", 0, 120, 10);
1930CMD('ZXBUSD79', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1931KILLD('ZXBUSD70b', 'collect zxbuslist 1');
1932KILLD('ZXBUSD70c', 'collect zxbuslist 2');
1933KILLD('ZXBUSD70', 'collect zxbusd 7');
1934
1935tst_nl();
1936DAEMON('ZXBUSD80', 'zxbusd 8', 2229, "./zxbusd -pid tmp/ZXBUSD80.pid -c '$busd_conf' -nthr 10 -nfd 30 -npdu 1000 -p stomp:0.0.0.0:2229");
1937DAEMON('ZXBUSD80b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSD80b.pid -d -d -c '$bus_list_conf'");
1938DAEMON('ZXBUSD80c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSD80c.pid -d -d -c '$bus_list2_conf'");
1939CMD('ZXBUSD84', '2x10x20 battery', "./zxbustailf -c '$bus_cli_conf' -e 'foo bar' -it 2 -i 10 -is 20", 0, 120, 10);
1940CMD('ZXBUSD89', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1941KILLD('ZXBUSD80b', 'collect zxbuslist 1');
1942KILLD('ZXBUSD80c', 'collect zxbuslist 2');
1943KILLD('ZXBUSD80', 'collect zxbusd 8');
1944
1945### Triple threaded client, various numbers of threads at zxbusd
1946
1947tst_nl();
1948CMD('ZXBUST00', 'Clean', "rm -f /var/zxid/bus/ch/default/*  /var/zxid/bus/ch/default/.del/*  /var/zxid/bus/ch/default/.ack/*");
1949
1950tst_nl();
1951DAEMON('ZXBUST10', 'zxbusd 1', 2229, "./zxbusd -pid tmp/ZXBUST10.pid -c '$busd_conf' -d -d -nthr 1 -nfd 30 -npdu 1500 -p stomp:0.0.0.0:2229");
1952DAEMON('ZXBUST10b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUST10b.pid -d -d -c '$bus_list_conf'");
1953DAEMON('ZXBUST10c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUST10c.pid -d -d -c '$bus_list2_conf'");
1954CMD('ZXBUST12', 'zxbuslist 2 fail one shot',  "./zxbuslist -o 1 -d -d -c '$buss_list2_conf'", 256, 10, 1);
1955CMD('ZXBUST14', '3x10x20 battery', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'foo bar' -it 3 -i 10 -is 20", 0, 240, 10);
1956CMD('ZXBUST19', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1957KILLD('ZXBUST10b', 'collect zxbuslist 1');
1958KILLD('ZXBUST10c', 'collect zxbuslist 2');
1959KILLD('ZXBUST10',  'collect zxbusd 1');
1960
1961tst_nl();
1962DAEMON('ZXBUST20', 'zxbusd 2', 2229, "./zxbusd -pid tmp/ZXBUST20.pid -c '$busd_conf' -d -d -nthr 2 -nfd 30 -npdu 1500 -p stomp:0.0.0.0:2229");
1963DAEMON('ZXBUST20b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUST20b.pid -d -d -c '$bus_list_conf'");
1964DAEMON('ZXBUST20c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUST20c.pid -d -d -c '$bus_list2_conf'");
1965CMD('ZXBUST24', '3x10x20 battery', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'foo bar' -it 3 -i 10 -is 20", 0, 240, 10);
1966CMD('ZXBUST29', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1967KILLD('ZXBUST20b', 'collect zxbuslist 1');
1968KILLD('ZXBUST20c', 'collect zxbuslist 2');
1969KILLD('ZXBUST20', 'collect zxbusd 2');
1970
1971tst_nl();
1972DAEMON('ZXBUST30', 'zxbusd 3', 2229, "./zxbusd -pid tmp/ZXBUST30.pid -c '$busd_conf' -nthr 1 -nfd 30 -npdu 1500 -p stomp:0.0.0.0:2229");
1973DAEMON('ZXBUST30b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUST30b.pid -d -d -c '$bus_list_conf'");
1974DAEMON('ZXBUST30c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUST30c.pid -d -d -c '$bus_list2_conf'");
1975CMD('ZXBUST34', '3x10x20 battery', "./zxbustailf -c '$bus_cli_conf' -e 'foo bar' -it 3 -i 10 -is 20", 0, 240, 10);
1976CMD('ZXBUST39', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1977KILLD('ZXBUST30b', 'collect zxbuslist 1');
1978KILLD('ZXBUST30c', 'collect zxbuslist 2');
1979KILLD('ZXBUST30', 'collect zxbusd 3');
1980
1981tst_nl();
1982DAEMON('ZXBUST40', 'zxbusd 4', 2229, "./zxbusd -pid tmp/ZXBUST40.pid -c '$busd_conf' -nthr 2 -nfd 30 -npdu 1500 -p stomp:0.0.0.0:2229");
1983DAEMON('ZXBUST40b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUST40b.pid -d -d -c '$bus_list_conf'");
1984DAEMON('ZXBUST40c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUST40c.pid -d -d -c '$bus_list2_conf'");
1985CMD('ZXBUST44', '3x10x20 battery', "./zxbustailf -c '$bus_cli_conf' -e 'foo bar' -it 3 -i 10 -is 20", 0, 240, 10);
1986CMD('ZXBUST49', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1987KILLD('ZXBUST40b', 'collect zxbuslist 1');
1988KILLD('ZXBUST40c', 'collect zxbuslist 2');
1989KILLD('ZXBUST40', 'collect zxbusd 4');
1990
1991tst_nl();
1992DAEMON('ZXBUST50', 'zxbusd 5', 2229, "./zxbusd -pid tmp/ZXBUST50.pid -c '$busd_conf' -d -d -nthr 3 -nfd 30 -npdu 1500 -p stomp:0.0.0.0:2229");
1993DAEMON('ZXBUST50b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUST50b.pid -d -d -c '$bus_list_conf'");
1994DAEMON('ZXBUST50c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUST50c.pid -d -d -c '$bus_list2_conf'");
1995CMD('ZXBUST54', '3x10x20 battery', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'foo bar' -it 3 -i 10 -is 20", 0, 240, 10);
1996CMD('ZXBUST59', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
1997KILLD('ZXBUST50b', 'collect zxbuslist 1');
1998KILLD('ZXBUST50c', 'collect zxbuslist 2');
1999KILLD('ZXBUST50', 'collect zxbusd 5');
2000
2001tst_nl();
2002DAEMON('ZXBUST60', 'zxbusd 6', 2229, "./zxbusd -pid tmp/ZXBUST60.pid -c '$busd_conf' -nthr 3 -nfd 30 -npdu 1500 -p stomp:0.0.0.0:2229");
2003DAEMON('ZXBUST60b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUST60b.pid -d -d -c '$bus_list_conf'");
2004DAEMON('ZXBUST60c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUST60c.pid -d -d -c '$bus_list2_conf'");
2005CMD('ZXBUST64', '3x10x20 battery', "./zxbustailf -c '$bus_cli_conf' -e 'foo bar' -it 3 -i 10 -is 20", 0, 240, 10);
2006CMD('ZXBUST69', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
2007KILLD('ZXBUST60b', 'collect zxbuslist 1');
2008KILLD('ZXBUST60c', 'collect zxbuslist 2');
2009KILLD('ZXBUST60', 'collect zxbusd 6');
2010
2011tst_nl();
2012DAEMON('ZXBUST70', 'zxbusd 7', 2229, "./zxbusd -pid tmp/ZXBUST70.pid -c '$busd_conf' -d -d -nthr 10 -nfd 30 -npdu 1500 -p stomp:0.0.0.0:2229");
2013DAEMON('ZXBUST70b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUST70b.pid -d -d -c '$bus_list_conf'");
2014DAEMON('ZXBUST70c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUST70c.pid -d -d -c '$bus_list2_conf'");
2015CMD('ZXBUST74', '3x10x20 battery', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'foo bar' -it 3 -i 10 -is 20", 0, 240, 10);
2016CMD('ZXBUST79', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
2017KILLD('ZXBUST70b', 'collect zxbuslist 1');
2018KILLD('ZXBUST70c', 'collect zxbuslist 2');
2019KILLD('ZXBUST70', 'collect zxbusd 7');
2020
2021tst_nl();
2022DAEMON('ZXBUST80', 'zxbusd 8', 2229, "./zxbusd -pid tmp/ZXBUST80.pid -c '$busd_conf' -nthr 10 -nfd 30 -npdu 1500 -p stomp:0.0.0.0:2229");
2023DAEMON('ZXBUST80b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUST80b.pid -d -d -c '$bus_list_conf'");
2024DAEMON('ZXBUST80c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUST80c.pid -d -d -c '$bus_list2_conf'");
2025CMD('ZXBUST84', '3x10x20 battery', "./zxbustailf -c '$bus_cli_conf' -e 'foo bar' -it 3 -i 10 -is 20", 0, 240, 10);
2026CMD('ZXBUST89', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
2027KILLD('ZXBUST80b', 'collect zxbuslist 1');
2028KILLD('ZXBUST80c', 'collect zxbuslist 2');
2029KILLD('ZXBUST80', 'collect zxbusd 8');
2030
2031### Multi threaded (10) client, various numbers of threads at zxbusd
2032
2033tst_nl();
2034CMD('ZXBUSM00', 'Clean', "rm -f /var/zxid/bus/ch/default/*  /var/zxid/bus/ch/default/.del/*  /var/zxid/bus/ch/default/.ack/*");
2035
2036tst_nl();
2037DAEMON('ZXBUSM10', 'zxbusd 1', 2229, "./zxbusd -pid tmp/ZXBUSM10.pid -c '$busd_conf' -d -d -nthr 1 -nfd 50 -npdu 5000 -p stomp:0.0.0.0:2229");
2038DAEMON('ZXBUSM10b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSM10b.pid -d -d -c '$bus_list_conf'");
2039DAEMON('ZXBUSM10c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSM10c.pid -d -d -c '$bus_list2_conf'");
2040CMD('ZXBUSM12', 'zxbuslist 2 fail one shot',  "./zxbuslist -o 1 -d -d -c '$buss_list2_conf'", 256, 10, 1);
2041CMD('ZXBUSM14', '10x10x20 battery', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'foo bar' -it 10 -i 10 -is 20", 0, 3600, 10);
2042CMD('ZXBUSM19', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
2043KILLD('ZXBUSM10b', 'collect zxbuslist 1');
2044KILLD('ZXBUSM10c', 'collect zxbuslist 2');
2045KILLD('ZXBUSM10',  'collect zxbusd 1');
2046
2047tst_nl();
2048DAEMON('ZXBUSM20', 'zxbusd 2', 2229, "./zxbusd -pid tmp/ZXBUSM20.pid -c '$busd_conf' -d -d -nthr 2 -nfd 50 -npdu 5000 -p stomp:0.0.0.0:2229");
2049DAEMON('ZXBUSM20b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSM20b.pid -d -d -c '$bus_list_conf'");
2050DAEMON('ZXBUSM20c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSM20c.pid -d -d -c '$bus_list2_conf'");
2051CMD('ZXBUSM24', '10x10x20 battery', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'foo bar' -it 10 -i 10 -is 20", 0, 3600, 10);
2052CMD('ZXBUSM29', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
2053KILLD('ZXBUSM20b', 'collect zxbuslist 1');
2054KILLD('ZXBUSM20c', 'collect zxbuslist 2');
2055KILLD('ZXBUSM20', 'collect zxbusd 2');
2056
2057tst_nl();
2058DAEMON('ZXBUSM30', 'zxbusd 3', 2229, "./zxbusd -pid tmp/ZXBUSM30.pid -c '$busd_conf' -nthr 1 -nfd 50 -npdu 5000 -p stomp:0.0.0.0:2229");
2059DAEMON('ZXBUSM30b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSM30b.pid -d -d -c '$bus_list_conf'");
2060DAEMON('ZXBUSM30c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSM30c.pid -d -d -c '$bus_list2_conf'");
2061CMD('ZXBUSM34', '10x10x20 battery', "./zxbustailf -c '$bus_cli_conf' -e 'foo bar' -it 10 -i 10 -is 20", 0, 3600, 10);
2062CMD('ZXBUSM39', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
2063KILLD('ZXBUSM30b', 'collect zxbuslist 1');
2064KILLD('ZXBUSM30c', 'collect zxbuslist 2');
2065KILLD('ZXBUSM30', 'collect zxbusd 3');
2066
2067tst_nl();
2068DAEMON('ZXBUSM40', 'zxbusd 4', 2229, "./zxbusd -pid tmp/ZXBUSM40.pid -c '$busd_conf' -nthr 2 -nfd 50 -npdu 5000 -p stomp:0.0.0.0:2229");
2069DAEMON('ZXBUSM40b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSM40b.pid -d -d -c '$bus_list_conf'");
2070DAEMON('ZXBUSM40c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSM40c.pid -d -d -c '$bus_list2_conf'");
2071CMD('ZXBUSM44', '10x10x20 battery', "./zxbustailf -c '$bus_cli_conf' -e 'foo bar' -it 10 -i 10 -is 20", 0, 3600, 10);
2072CMD('ZXBUSM49', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
2073KILLD('ZXBUSM40b', 'collect zxbuslist 1');
2074KILLD('ZXBUSM40c', 'collect zxbuslist 2');
2075KILLD('ZXBUSM40', 'collect zxbusd 4');
2076
2077tst_nl();
2078DAEMON('ZXBUSM50', 'zxbusd 5', 2229, "./zxbusd -pid tmp/ZXBUSM50.pid -c '$busd_conf' -d -d -nthr 3 -nfd 50 -npdu 5000 -p stomp:0.0.0.0:2229");
2079DAEMON('ZXBUSM50b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSM50b.pid -d -d -c '$bus_list_conf'");
2080DAEMON('ZXBUSM50c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSM50c.pid -d -d -c '$bus_list2_conf'");
2081CMD('ZXBUSM54', '10x10x20 battery', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'foo bar' -it 10 -i 10 -is 20", 0, 3600, 10);
2082CMD('ZXBUSM59', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
2083KILLD('ZXBUSM50b', 'collect zxbuslist 1');
2084KILLD('ZXBUSM50c', 'collect zxbuslist 2');
2085KILLD('ZXBUSM50', 'collect zxbusd 5');
2086
2087tst_nl();
2088DAEMON('ZXBUSM60', 'zxbusd 6', 2229, "./zxbusd -pid tmp/ZXBUSM60.pid -c '$busd_conf' -nthr 3 -nfd 50 -npdu 5000 -p stomp:0.0.0.0:2229");
2089DAEMON('ZXBUSM60b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSM60b.pid -d -d -c '$bus_list_conf'");
2090DAEMON('ZXBUSM60c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSM60c.pid -d -d -c '$bus_list2_conf'");
2091CMD('ZXBUSM64', '10x10x20 battery', "./zxbustailf -c '$bus_cli_conf' -e 'foo bar' -it 10 -i 10 -is 20", 0, 3600, 10);
2092CMD('ZXBUSM69', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
2093KILLD('ZXBUSM60b', 'collect zxbuslist 1');
2094KILLD('ZXBUSM60c', 'collect zxbuslist 2');
2095KILLD('ZXBUSM60', 'collect zxbusd 6');
2096
2097tst_nl();
2098DAEMON('ZXBUSM70', 'zxbusd 7', 2229, "./zxbusd -pid tmp/ZXBUSM70.pid -c '$busd_conf' -d -d -nthr 10 -nfd 50 -npdu 5000 -p stomp:0.0.0.0:2229");
2099DAEMON('ZXBUSM70b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSM70b.pid -d -d -c '$bus_list_conf'");
2100DAEMON('ZXBUSM70c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSM70c.pid -d -d -c '$bus_list2_conf'");
2101CMD('ZXBUSM74', '10x10x20 battery', "./zxbustailf -d -d -c '$bus_cli_conf' -e 'foo bar' -it 10 -i 10 -is 20", 0, 3600, 10);
2102CMD('ZXBUSM79', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
2103KILLD('ZXBUSM70b', 'collect zxbuslist 1');
2104KILLD('ZXBUSM70c', 'collect zxbuslist 2');
2105KILLD('ZXBUSM70', 'collect zxbusd 7');
2106
2107tst_nl();
2108DAEMON('ZXBUSM80', 'zxbusd 8', 2229, "./zxbusd -pid tmp/ZXBUSM80.pid -c '$busd_conf' -nthr 10 -nfd 1000 -npdu 7000 -p stomp:0.0.0.0:2229");
2109DAEMON('ZXBUSM80b','zxbuslist 1',-1,"./zxbuslist -pid tmp/ZXBUSM80b.pid -d -d -c '$bus_list_conf'");
2110DAEMON('ZXBUSM80c','zxbuslist 2',-1,"./zxbuslist -pid tmp/ZXBUSM80c.pid -d -d -c '$bus_list2_conf'");
2111CMD('ZXBUSM84', '10x10x20 battery', "./zxbustailf -c '$bus_cli_conf' -e 'foo bar' -it 10 -i 10 -is 20", 0, 3600, 10);
2112CMD('ZXBUSM89', 'dump',     "./zxbustailf -c '$bus_cli_conf' -ctl 'dump'");
2113KILLD('ZXBUSM80b', 'collect zxbuslist 1');
2114KILLD('ZXBUSM80c', 'collect zxbuslist 2');
2115KILLD('ZXBUSM80', 'collect zxbusd 8');
2116
2117### Unit test code that did not get tested otherwise
2118
2119tst_nl();
2120CMD('COVIMP1', 'Silly tests just to improve test coverage', "./zxcovimp.sh", 0, 60, 10);
2121
2122if (0) {
2123#C('DBG1', 'Test exit value', 0.5, 0.1, "echo foo");
2124C('SRV1', 'mini_http -p 2301 idp', 5, 0.5, "");
2125
2126tA('ST', 'ST1', 'static content bypass svn.zxid.org', 5, 0.5, "http://svn.zxid.org/wr/redx.png");
2127tP('ST', 'ST2', 'static content bypass zxid.org', 5, 0.5, "http://zxid.org/favicon.ico");
2128}
2129
2130$success_ratio = $n_tst ? sprintf("=== Test success %d/%d (%.1f%%) ===\n", $n_tst_ok, $n_tst, $n_tst_ok*100.0/$n_tst) : "No tests run.\n";
2131
2132print $success_ratio if $ascii;
2133
2134syswrite STDOUT, <<HTML if !$ascii;
2135</table>
2136<p><i>Hint: Click on test name to run just that test.</i>
2137
2138<p><b>$success_ratio</b>
2139
2140[ <a href="zxtest.pl">zxtest.pl</a>
2141| <a href="zxtest.pl?tst=XML">XML Encoding and Decoding</a>
2142| <a href="zxtest.pl?tst=ZXC-WS">Web Service calls</a> ]
2143
2144<hr>
2145<i>$cvsid</i>
2146HTML
2147    ;
2148
2149__END__
2150#EOF
2151