#!/usr/bin/expect -f
#
# Usage: testing.exp <path to arping> <ifname> <ip address> <mac address>
#
# Test all cases against a "normal" machine:
# * Responds to ARP
# * Responds to ping
# * Doesn't respond to broadcast pings.
#
# Abnormal machines, to be tested elsewhere:
# * Proxy ARP
# * Respond to broadcast pings
# * Lost packets
# * Duplicated replies
#
# Tested here:
# * -a
# * -c
# * -d (minimally)
# * -D
# * -e
# * -h
# * -q (soon)
# * -r
# * -R
# * -s (soon)
# * -S (soon)
# * -t
# * -T
# * -u (soon)
# * -v (soon)
# * -w (soon)
# * -W (soon)
#
# Not tested here:
# * -0
# * -A (forced on with mac ping)
# * -b
# * -B
# * -p
# * -P
# * -U
# * -V
# * Mac ping without -T.
#
set bin [lindex $argv 0]
set ifname [lindex $argv 1]
set ip [lindex $argv 2]
set mac [lindex $argv 3]
set bad_ip "1.2.4.3"
set bad_mac "00:11:22:33:44:55"

# Check if "stty -oxtabs" is a thing.
# It is on OpenBSD, but not Linux.
spawn tty
expect eof
spawn "stty" "-oxtabs"
catch wait result
if {[lindex $result 3] == 0} {
    set stty_init "-oxtabs"
}

# Helper functions.
proc want_err {code} {
    lassign [wait] pid spawnid os_error_flag value
    if {$os_error_flag != 0} {
        puts "No error code provided"
        exit 1
    }
    if {$value != $code} {
        puts "Wrong error code. Want $code, got $value"
        exit 1
    }
}


send_user -- "--------------- No options ------------------\n"
spawn $bin
expect -re "ARPing 2\.\d+, by Thomas Habets <thomas@habets.se>\r
usage: arping \\\[ -0aAbdDeFpqrRuUv \\\] \\\[ -w <us> \\\] \\\[ -S <host/ip> \\\]\r
\\\[ -T <host/ip \\\] \\\[ -s <MAC> \\\] \\\[ -t <MAC> \\\] \\\[ -c <count> \\\]\r
\\\[ -i <interface> \\\] <host/ip/MAC | -B>\r
For complete usage info, use --help or check the manpage.\r
"
expect eof
want_err 1

send_user -- "--------------- -h ------------------\n"
spawn $bin -h
expect -re "ARPing 2\.\d+, by Thomas Habets <thomas@habets.se>\r
usage: arping \\\[ -0aAbdDeFpqrRuUv \\\] \\\[ -w <us> \\\] \\\[ -S <host/ip> \\\]\r
\\\[ -T <host/ip \\\] \\\[ -s <MAC> \\\] \\\[ -t <MAC> \\\] \\\[ -c <count> \\\]\r
\\\[ -i <interface> \\\] <host/ip/MAC | -B>\r
For complete usage info, use --help or check the manpage.\r
"
expect eof
want_err 0

send_user -- "--------------- --help ------------------\n"
spawn $bin --help
expect -re "ARPing 2\.\d+, by Thomas Habets <thomas@habets.se>\r
usage: arping \\\[ -0aAbdDeFpqrRuUv \\\] \\\[ -w <us> \\\] \\\[ -S <host/ip> \\\]\r
\\\[ -T <host/ip \\\] \\\[ -s <MAC> \\\] \\\[ -t <MAC> \\\] \\\[ -c <count> \\\]\r
\\\[ -i <interface> \\\] <host/ip/MAC | -B>\r
\r
"
expect "Report bugs to: thomas@habets.se\r
Arping home page: <http://www.habets.pp.se/synscan/>\r
Development repo: http://github.com/ThomasHabets/arping\r
"
expect eof
want_err 0

send_user -- "--------------- Bad interface ------------------\n"
spawn $bin -i uhtaonuhoes $ip
expect -re "arping: libnet_init.*\r"
expect "\r" {
    # Make sure double-endline is stripped.
    exit 1
}
want_err 1

send_user -- "--------------- Ping IP Simple ------------------\n"
spawn $bin -c 1 $ip
expect -re "ARPING $ip\r
\(42|60\) bytes from $mac \\($ip\\): index=0 time=(.*)sec\r
\r
--- $ip statistics ---\r
1 packets transmitted, 1 packets received,   0% unanswered \\(0 extra\\)\r
rtt min/avg/max/std-dev = \[0-9.\]+/\[0-9.\]+/\[0-9.\]+/0.000 ms\r
"
expect eof
want_err 0

send_user -- "--------------- Ping IP Raw (-r) ------------------\n"
spawn $bin -c 2 -r $ip
expect -re "$mac\r
$mac\r
"
expect eof
want_err 0

send_user -- "--------------- Ping IP Raw audio (-r -a) ------------------\n"
spawn $bin -c 2 -r -a $ip
expect -re "\a$mac\r
\a$mac\r
"
expect eof
want_err 0

send_user -- "--------------- Ping IP Raw audio bad dest (-r -e) ------------------\n"
spawn $bin -c 2 -r -i "$ifname" -e $bad_ip
expect -re "\a\a"
expect eof
want_err 1

send_user -- "--------------- Ping IP reverse raw (-R) ------------------\n"
spawn $bin -c 2 -R $ip
expect -re "$ip\r
$ip\r
"
expect eof
want_err 0

send_user -- "--------------- Ping IP double raw (-R) ------------------\n"
spawn $bin -c 2 -R -r $ip
expect -re "$mac $ip\r
$mac $ip\r
"
expect eof
want_err 0

send_user -- "--------------- Ping IP max 2 (-C) ------------------\n"
spawn $bin -C 2 -c 10 $ip
expect -re "ARPING $ip\r
\(42|60\) bytes from $mac \\($ip\\): index=0 time=(.*)sec\r
\(42|60\) bytes from $mac \\($ip\\): index=1 time=(.*)sec\r
\r
--- $ip statistics ---\r
2 packets transmitted, 2 packets received,   0% unanswered \\(0 extra\\)\r
rtt min/avg/max/std-dev = \[0-9.\]+/\[0-9.\]+/\[0-9.\]+/\[0-9.\]+ ms\r
"
expect eof
want_err 0

send_user -- "--------------- Ping IP x 3 (-c) ------------------\n"
spawn $bin -c 3 $ip
expect -re "ARPING $ip\r
\(42|60\) bytes from $mac \\($ip\\): index=0 time=\[0-9.\]+ \[mu\]?sec\r
\(42|60\) bytes from $mac \\($ip\\): index=1 time=\[0-9.\]+ \[mu\]?sec\r
\(42|60\) bytes from $mac \\($ip\\): index=2 time=\[0-9.\]+ \[mu\]?sec\r
\r
--- $ip statistics ---\r
3 packets transmitted, 3 packets received,   0% unanswered \\(0 extra\\)\r
rtt min/avg/max/std-dev = \[0-9.\]+/\[0-9.\]+/\[0-9.\]+/\[0-9.\]+ ms\r
"
expect eof
want_err 0

send_user -- "--------------- Ping IP x 3 with audio (-a)  ------------------\n"
spawn $bin -c 3 -a $ip
expect -re "ARPING $ip\r
\a\(42|60\) bytes from $mac \\($ip\\): index=0 time=\[0-9.\]+ \[mu\]?sec\r
\a\(42|60\) bytes from $mac \\($ip\\): index=1 time=\[0-9.\]+ \[mu\]?sec\r
\a\(42|60\) bytes from $mac \\($ip\\): index=2 time=\[0-9.\]+ \[mu\]?sec\r
\r
--- $ip statistics ---\r
3 packets transmitted, 3 packets received,   0% unanswered \\(0 extra\\)\r
rtt min/avg/max/std-dev = \[0-9.\]+/\[0-9.\]+/\[0-9.\]+/\[0-9.\]+ ms\r
"
expect eof
want_err 0

send_user -- "--------- Ping IP x 2 with inverted audio (-e)  ------------\n"
spawn $bin -c 2 -e $ip
expect -re "ARPING $ip\r
\(42|60\) bytes from $mac \\($ip\\): index=0 time=\[0-9.\]+ \[mu\]?sec\r
\(42|60\) bytes from $mac \\($ip\\): index=1 time=\[0-9.\]+ \[mu\]?sec\r
\r
--- $ip statistics ---\r
2 packets transmitted, 2 packets received,   0% unanswered \\(0 extra\\)\r
rtt min/avg/max/std-dev = \[0-9.\]+/\[0-9.\]+/\[0-9.\]+/\[0-9.\]+ ms\r
"
expect eof
want_err 0

send_user -- "--------- Ping IP x 2 with inverted audio, bad IP (-e)  ------------\n"
spawn $bin -c 2 -i "$ifname" -e "$bad_ip"
expect -re "ARPING $bad_ip\r
\aTimeout\r
\aTimeout\r
\r
--- $bad_ip statistics ---\r
2 packets transmitted, 0 packets received, 100% unanswered \\(0 extra\\)\r
\r
"
expect eof
want_err 1

send_user -- "--------- Ping IP x 2 with inverted audio (-e -D)  ------------\n"
spawn $bin -c 2 -e -D $ip
expect "!!\t  0% packet loss (0 extra)\r\n"
expect eof
want_err 0

send_user -- "--------- Ping IP x 2 with inverted audio, bad IP (-e -D)  ------------\n"
spawn $bin -c 2 -e -i $ifname -D "$bad_ip"
expect "\a.\a.\t100% packet loss (0 extra)\r\n"
expect eof
want_err 1

send_user -- "--------------- Ping IP cisco style (-D) ------------------\n"
spawn $bin -c 3 -D $ip
expect "!!!\t  0% packet loss (0 extra)\r\n"
expect eof
want_err 0

send_user -- "--------------- Ping IP cisco style with audio (-D -a) -----------\n"
spawn $bin -c 3 -D -a $ip
expect "\a!\a!\a!\t  0% packet loss (0 extra)\r\n"
expect eof
want_err 0

send_user -- "--------------- Ping IP Targeted (-t) ------------------\n"
spawn $bin -c 1 -t $mac $ip
expect -re "ARPING $ip\r
\(42|60\) bytes from $mac \\($ip\\): index=0 time=(.*)sec\r
\r
--- $ip statistics ---\r
1 packets transmitted, 1 packets received,   0% unanswered \\(0 extra\\)\r
rtt min/avg/max/std-dev = \[0-9.\]+/\[0-9.\]+/\[0-9.\]+/0.000 ms\r
"
expect eof
want_err 0

send_user -- "--------------- Ping IP Mistargeted (-t) ------------------\n"
spawn $bin -c 1 -t $bad_mac $ip
expect "ARPING $ip\r
Timeout\r
\r
--- $ip statistics ---\r
1 packets transmitted, 0 packets received, 100% unanswered \\(0 extra\\)\r
"
expect eof
want_err 1

send_user -- "--------------- Ping MAC with IP destination ------------------\n"
spawn $bin -A -c 1 -T $ip $mac
expect -re "ARPING $mac\r
\(42|60\) bytes from $ip \\($mac\\): icmp_seq=0 time=(.*)sec\r
\r
--- $mac statistics ---\r
1 packets transmitted, 1 packets received,   0% unanswered \\(0 extra\\)\r
rtt min/avg/max/std-dev = \[0-9.\]+/\[0-9.\]+/\[0-9.\]+/0.000 ms\r
"
expect eof
want_err 0

send_user -- "--------------- Ping MAC Raw (-r) ------------------\n"
spawn $bin -c 2 -r -T $ip $mac
expect -re "$ip\r
$ip\r
"
expect eof
want_err 0

send_user -- "--------------- Ping MAC Raw audio (-r -a) ------------------\n"
spawn $bin -c 2 -a -r -T $ip $mac
expect -re "\a$ip\r
\a$ip\r
"
expect eof
want_err 0

send_user -- "--------------- Ping MAC Raw audio bad dest (-r -e) ------------------\n"
spawn $bin -c 2 -r -e -T $ip $bad_mac
expect -re "\a\a"
expect eof
want_err 1

send_user -- "--------------- Ping MAC reverse raw (-R) ------------------\n"
spawn $bin -c 2 -R -T $ip $mac
expect -re "$mac\r
$mac\r
"
expect eof
want_err 0

send_user -- "--------------- Ping MAC double raw (-a -R) ------------------\n"
spawn $bin -c 2 -R -r -T $ip $mac
expect -re "$mac $ip\r
$mac $ip\r
"
expect eof
want_err 0


send_user -- "--------------- Ping MAC max 2 (-C) ------------------\n"
spawn $bin -A -C 2 -c 10 -T $ip $mac
expect -re "ARPING $mac\r
\(42|60\) bytes from $ip \\($mac\\): icmp_seq=0 time=(.*)sec\r
\(42|60\) bytes from $ip \\($mac\\): icmp_seq=1 time=(.*)sec\r
\r
--- $mac statistics ---\r
2 packets transmitted, 2 packets received,   0% unanswered \\(0 extra\\)\r
rtt min/avg/max/std-dev = \[0-9.\]+/\[0-9.\]+/\[0-9.\]+/\[0-9.\]+ ms\r
"
expect eof
want_err 0

send_user -- "--------------- Ping MAC cisco style (-D) ------------------\n"
spawn $bin -A -c 3 -D -T $ip $mac
expect "!!!\t  0% packet loss (0 extra)\r\n"
expect eof
want_err 0

send_user -- "--------------- Ping MAC cisco style with audio (-D -a) -----------\n"
spawn $bin -A -c 3 -D -a -T $ip $mac
expect "\a!\a!\a!\t  0% packet loss (0 extra)\r\n"
expect eof
want_err 0

send_user -- "--------- Ping MAC x 2 with inverted audio (-e)  ------------\n"
spawn $bin -c 2 -T $ip "$mac"
expect -re "ARPING $mac\r
\(42|60\) bytes from $ip \\($mac\\): icmp_seq=0 time=(.*)sec\r
\(42|60\) bytes from $ip \\($mac\\): icmp_seq=1 time=(.*)sec\r
\r
--- $mac statistics ---\r
2 packets transmitted, 2 packets received,   0% unanswered \\(0 extra\\)\r
rtt min/avg/max/std-dev = \[0-9.\]+/\[0-9.\]+/\[0-9.\]+/\[0-9.\]+ ms\r
"
expect eof
want_err 0

send_user -- "--------- Ping MAC x 2 with inverted audio, bad dest (-e)  ------------\n"
spawn $bin -e -c 2 -T $ip "$bad_mac"
expect -re "ARPING $bad_mac\r
\aTimeout\r
\aTimeout\r
\r
--- $bad_mac statistics ---\r
2 packets transmitted, 0 packets received, 100% unanswered \\(0 extra\\)\r
\r
"
expect eof
want_err 1

send_user -- "--------- Ping MAC x 2 with inverted audio (-e -D)  ------------\n"
spawn $bin -A -e -c 2 -D -T $ip $mac
expect "!!\t  0% packet loss (0 extra)\r\n"
expect eof
want_err 0

send_user -- "--------- Ping MAC x 2 with inverted audio, bad dest (-e -D)  ------------\n"
spawn $bin -A -c 2 -e -i $ifname -D -T $ip $bad_mac
expect "\a.\a.\t100% packet loss (0 extra)\r\n"
expect eof
want_err 1

send_user -- "--------- Detect duplicate  ------------\n"
spawn $bin -c 2 -d $ip
expect eof
want_err 0

send_user -- "--------- Detect duplicate of self  ------------\n"
spawn $bin -c 2 -d
expect eof
want_err 0

send_user -- "--------- Too many args  ------------\n"
spawn $bin -c 2 1.1.1.1 1.1.1.1
expect eof
want_err 1

send_user -- "---------------------------------------------------------\n"
send_user -- "All tests passed\n"
