AT_BANNER([appctl bashcomp unit tests])

m4_define([GET_FORMAT], [
echo "$@" | grep -A 1 -- "Command format" | tail -n+2
])

m4_define([GET_EXPAN], [
echo "$@" | grep -- "available completions for keyword" \
     | sed -e 's/^[ ]*//g;s/[ ]*$//g'
])

m4_define([GET_AVAIL], [
echo "$@" | sed -e '1,/Available/d' | tail -n+2
])

m4_define([GET_COMP_STR], [
echo "available completions for keyword \"$1\": $2" \
     | sed -e 's/[ ]*$//g'
])

AT_SETUP([appctl-bashcomp - basic verification])
AT_SKIP_IF([test -z ${BASH_VERSION+x}])
OVS_VSWITCHD_START

# complete ovs-appctl [TAB]
# complete ovs-dpctl  [TAB]
# complete ovs-ofctl  [TAB]
# complete ovsdb-tool [TAB]
m4_foreach(
[test_command],
[[ovs-appctl],
[ovs-dpctl],
[ovs-ofctl],
[ovsdb-tool]],
[
INPUT="$(bash ovs-appctl-bashcomp.bash debug test_command TAB 2>&1)"
MATCH="$(test_command --option | sort | sed -n '/^--.*/p' | cut -d '=' -f1)
$(test_command list-commands | tail -n +2 | cut -c3- | cut -d ' ' -f1 | sort)"
AT_CHECK_UNQUOTED([GET_AVAIL(${INPUT})],
[0], [dnl
${MATCH}
])])


# complete ovs-appctl --tar[TAB]
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl --tar 2>&1)"
AT_CHECK_UNQUOTED([GET_AVAIL(${INPUT})],
[0], [dnl
--target
])


# complete ovs-appctl --target [TAB]
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl --target TAB 2>&1)"
AT_CHECK_UNQUOTED([GET_AVAIL(${INPUT})],
[0], [dnl
ovs-ofctl
ovs-vswitchd
ovsdb-server
])


# complete ovs-appctl --target ovs-vswitchd [TAB]
# complete ovs-appctl --target ovsdb-server [TAB]
# complete ovs-appctl --target ovs-ofctl    [TAB]
AT_CHECK([ovs-ofctl monitor br0 --detach --no-chdir --pidfile])
m4_foreach(
[target_daemon],
[[ovs-vswitchd],
[ovsdb-server],
[ovs-ofctl]],
[
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl --target target_daemon TAB 2>&1)"
MATCH="$(ovs-appctl --option | sort | sed -n '/^--.*/p' | cut -d '=' -f1)
$(ovs-appctl --target target_daemon list-commands | tail -n +2 | cut -c3- | cut -d ' ' -f1 | sort)"
AT_CHECK_UNQUOTED([GET_AVAIL(${INPUT})],
[0], [dnl
${MATCH}
])])
OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
OVS_VSWITCHD_STOP
AT_CLEANUP


# complex completion check - bfd/set-forwarding
# bfd/set-forwarding [interface] normal|false|true
# test expansion of 'interface'
AT_SETUP([appctl-bashcomp - complex completion check 1])
AT_SKIP_IF([test -z ${BASH_VERSION+x}])
OVS_VSWITCHD_START(add-port br0 p0 -- set Interface p0 type=dummy)

# check the top level completion.
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl bfd/set-forwarding TAB 2>&1)"
MATCH="$(GET_COMP_STR([normal], [])
GET_COMP_STR([false], [])
GET_COMP_STR([true], [])
GET_COMP_STR([interface], [p0]))"
AT_CHECK_UNQUOTED([GET_EXPAN(${INPUT})],
[0], [dnl
${MATCH}
])
# check the available completions.
AT_CHECK_UNQUOTED([GET_AVAIL(${INPUT})],
[0], [dnl
p0
])


# set argument to 'true', there should be no more completions.
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl bfd/set-forwarding true TAB 2>&1)"
AT_CHECK_UNQUOTED([echo "$INPUT" | sed -e '/./,$!d'],
[0], [dnl
])


# set argument to 'p1', there should still be the completion for booleans.
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl bfd/set-forwarding p1 TAB 2>&1)"
MATCH="$(GET_COMP_STR([normal], [])
GET_COMP_STR([false], [])
GET_COMP_STR([true], []))"
AT_CHECK_UNQUOTED([GET_EXPAN(${INPUT})],
[0], [dnl
${MATCH}
])
# check the available completions.
AT_CHECK_UNQUOTED([GET_AVAIL(${INPUT})], [0])


# set argument to 'p1 false', there should still no more completions.
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl bfd/set-forwarding p1 false TAB 2>&1)"
AT_CHECK_UNQUOTED([echo "$INPUT" | sed -e '/./,$!d'],
[0], [dnl
])

OVS_VSWITCHD_STOP
AT_CLEANUP


# complex completion check - lacp/show
# lacp/show [port]
# test expansion on 'port'
AT_SETUP([appctl-bashcomp - complex completion check 2])
AT_SKIP_IF([test -z ${BASH_VERSION+x}])
OVS_VSWITCHD_START(add-port br0 p0 -- set Interface p0 type=dummy \
                   -- add-port br0 p1 -- set Interface p1 type=dummy)

# check the top level completion.
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl lacp/show TAB 2>&1)"
MATCH="$(GET_COMP_STR([port], [br0 p0 p1]))"
AT_CHECK_UNQUOTED([GET_EXPAN(${INPUT})],
[0], [dnl
${MATCH}
])
# check the available completions.
AT_CHECK_UNQUOTED([GET_AVAIL(${INPUT})],
[0], [dnl
br0
p0
p1
])


# set argument to 'p1', there should be no more completions.
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl lacp/show p1 TAB 2>&1)"
AT_CHECK_UNQUOTED([echo "$INPUT" | sed -e '/./,$!d'],
[0], [dnl
])

OVS_VSWITCHD_STOP
AT_CLEANUP


# complex completion check - ofproto/trace
# ofproto/trace {[dp_name] odp_flow | bridge br_flow} [OPTIONS] [-generate|packet]
# test expansion on 'dp|dp_name' and 'bridge'
AT_SETUP([appctl-bashcomp - complex completion check 3])
AT_SKIP_IF([test -z ${BASH_VERSION+x}])
OVS_VSWITCHD_START(add-port br0 p0 -- set Interface p0 type=dummy \
                   -- add-port br0 p1 -- set Interface p1 type=dummy)

# check the top level completion.
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl ofproto/trace TAB 2>&1)"
MATCH="$(GET_COMP_STR([bridge], [br0])
GET_COMP_STR([odp_flow], [])
GET_COMP_STR([dp_name], [ovs-dummy]))"
AT_CHECK_UNQUOTED([GET_EXPAN(${INPUT})],
[0], [dnl
${MATCH}
])
# check the available completions.
AT_CHECK_UNQUOTED([GET_AVAIL(${INPUT})],
[0], [dnl
br0
ovs-dummy
])


# set argument to 'ovs-dummy', should go to the dp-name path.
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl ofproto/trace ovs-dummy TAB 2>&1)"
MATCH="$(GET_COMP_STR([odp_flow], []))"
AT_CHECK_UNQUOTED([GET_EXPAN(${INPUT})],
[0], [dnl
${MATCH}
])
# check the available completions.
AT_CHECK_UNQUOTED([GET_AVAIL(${INPUT})], [0])


# set odp_flow to some random string, should go to the next level.
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl ofproto/trace ovs-dummy "in_port(123),mac(),ip,tcp" TAB 2>&1)"
MATCH="$(GET_COMP_STR([-generate], [-generate])
GET_COMP_STR([packet], [])
GET_COMP_STR([OPTIONS...], []))"
AT_CHECK_UNQUOTED([GET_EXPAN(${INPUT})],
[0], [dnl
${MATCH}
])
# check the available completions.
AT_CHECK_UNQUOTED([GET_AVAIL(${INPUT})],
[0], [dnl
-generate
])


# set packet to some random string, there should be no more completions.
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl ofproto/trace ovs-dummy "in_port(123),mac(),ip,tcp" "ABSJDFLSDJFOIWEQR" TAB 2>&1)"
AT_CHECK_UNQUOTED([echo "$INPUT" | sed -e '/./,$!d'],
[0], [dnl
])


# set argument to 'br0', should go to the bridge path.
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl ofproto/trace br0 TAB 2>&1)"
MATCH="$(GET_COMP_STR([br_flow], []))"
AT_CHECK_UNQUOTED([GET_EXPAN(${INPUT})],
[0], [dnl
${MATCH}
])
# check the available completions.
AT_CHECK_UNQUOTED([GET_AVAIL(${INPUT})], [0])


# set argument to some random string, should go to the odp_flow path.
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl ofproto/trace "in_port(123),mac(),ip,tcp" TAB 2>&1)"
MATCH="$(GET_COMP_STR([-generate], [-generate])
GET_COMP_STR([packet], [])
GET_COMP_STR([OPTIONS...], []))"
AT_CHECK_UNQUOTED([GET_EXPAN(${INPUT})],
[0], [dnl
${MATCH}
])
# check the available completions.
AT_CHECK_UNQUOTED([GET_AVAIL(${INPUT})],
[0], [dnl
-generate
])

OVS_VSWITCHD_STOP
AT_CLEANUP


# complex completion check - vlog/set
# vlog/set {spec | PATTERN:destination:pattern}
# test non expandable arguments
AT_SETUP([appctl-bashcomp - complex completion check 4])
AT_SKIP_IF([test -z ${BASH_VERSION+x}])
OVS_VSWITCHD_START

# check the top level completion.
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl vlog/set TAB 2>&1)"
MATCH="$(GET_COMP_STR([PATTERN:destination:pattern], [])
GET_COMP_STR([spec], []))"
AT_CHECK_UNQUOTED([GET_EXPAN(${INPUT})],
[0], [dnl
${MATCH}
])
# check the available completions.
AT_CHECK_UNQUOTED([GET_AVAIL(${INPUT})], [0])


# set argument to random 'abcd', there should be no more completions.
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl vlog/set abcd TAB 2>&1)"
AT_CHECK_UNQUOTED([echo "$INPUT" | sed -e '/./,$!d'],
[0], [dnl
])

OVS_VSWITCHD_STOP
AT_CLEANUP


AT_SETUP([appctl-bashcomp - negative test])
AT_SKIP_IF([test -z ${BASH_VERSION+x}])
OVS_VSWITCHD_START(add-port br0 p0 -- set Interface p0 type=dummy)

# negative test - incorrect subcommand
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl ERROR 2>&1)"
AT_CHECK_UNQUOTED([echo "$INPUT" | sed -e 's/[ \t]*$//' | sed -e '/./,$!d'], [0])
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl ERROR TAB 2>&1)"
AT_CHECK_UNQUOTED([echo "$INPUT" | sed -e 's/[ \t]*$//' | sed -e '/./!d'],
[0], [dnl
])


# negative test - no ovs-vswitchd
# negative test - no ovsdb-server
# negative test - no ovs-ofctl
# should not see any error.
OVS_VSWITCHD_STOP
m4_foreach(
[target_daemon],
[[ovs-vswitchd],
[ovsdb-server],
[ovs-ofctl]],
[
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl --target target_daemon TAB 2>&1)"
MATCH="$(ovs-appctl --option | sort | sed -n '/^--.*/p' | cut -d '=' -f1)"
AT_CHECK_UNQUOTED([GET_AVAIL(${INPUT})],
[0], [dnl
${MATCH}
])
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovs-appctl --target target_daemon ERROR SUBCMD TAB 2>&1)"
AT_CHECK_UNQUOTED([echo "$INPUT" | sed -e 's/[ \t]*$//' | sed -e '/./!d'],
[0], [dnl
])])


# negative test - do not match on nested option
INPUT="$(bash ovs-appctl-bashcomp.bash debug ovsdb-tool create TAB 2>&1)"
AT_CHECK_UNQUOTED([GET_AVAIL(${INPUT})], [0])

AT_CLEANUP


dnl ----------------------------------------------------------------------
AT_BANNER([vsctl bashcomp unit tests])

m4_define([PREPARE_MATCH_NOSPACE], [
echo "$@" | tr ' ' '\n' | sed -e '/^$/d' | sort -u
])

m4_define([PREPARE_MATCH_SPACE], [
echo "$@" | tr ' ' '\n' | sed -e '/^$/d' | sed -e 's/$/ /g' | sort -u
])

AT_SETUP([vsctl-bashcomp - basic verification])
AT_SKIP_IF([test -z ${BASH_VERSION+x}])
AT_SKIP_IF([eval 'test ${BASH_VERSINFO[[0]]} -lt 4'])
OVS_VSWITCHD_START

# complete ovs-vsctl --db=* [TAB]
TMP="$(ovs-vsctl --commands | cut -d',' -f1-2 | tr -d ',[[]]' | tr -s ' ' '\n')
$(ovs-vsctl --options | grep -- '--' | sed -e 's/=.*$/=/g')"
MATCH="$(PREPARE_MATCH_NOSPACE(${TMP}))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "--db=unix:$OVS_RUNDIR/db.sock "],
[0], [dnl
${MATCH}
])
# complete ovs-vsctl [TAB]
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test ""],
[0], [dnl
${MATCH}
])

# complete on global options.
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "--dry-run "],
[0], [dnl
${MATCH}
])
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "--dry-run --pretty "],
[0], [dnl
${MATCH}
])

# complete on local options.
TMP="$(ovs-vsctl --commands | grep -- '--may-exist' | cut -d',' -f1-2 | tr -d ',[[]]' | tr -s ' ' '\n' | grep -v -- '--may-exist')"
MATCH="$(PREPARE_MATCH_SPACE(${TMP}))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "--may-exist "],
[0], [dnl
${MATCH}
])

#
# test !, +, ?, *.
#
# test !.  no following arguments are expanded.
TMP="$(ovsdb-client --no-heading list-tables)"
MATCH="$(PREPARE_MATCH_SPACE(${TMP}))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set "],
[0], [dnl
${MATCH}
])
# test ?.  will show completions for both current and following arguments.
ovs-vsctl br-set-external-id br0 bridge-id br0
MATCH="$(PREPARE_MATCH_SPACE(bridge-id --))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "br-get-external-id br0 "],
[0], [dnl
${MATCH}
])
# test *.  argument with this prefix could be completed for zero or more times.
TMP="$(ovs-vsctl --no-heading --columns=_uuid,name list Bridge | tr -d '\"')"
MATCH="$(PREPARE_MATCH_SPACE(${TMP} --))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "destroy Bridge "],
[0], [dnl
${MATCH}
])
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "destroy Bridge br0 "],
[0], [dnl
${MATCH}
])
# test +.  the first time, an argument is required, after that, it becomes '*'.
TMP="$(ovsdb-client --no-heading list-columns Open_vSwitch Bridge | awk '/key.*value/ { print $1":"; next } { print $1; next }')"
MATCH="$(PREPARE_MATCH_NOSPACE(${TMP}))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set Bridge br0 "],
[0], [dnl
${MATCH}
])
MATCH="$(PREPARE_MATCH_NOSPACE(${TMP} --))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set Bridge br0 other_config:random_key=123 "],
[0], [dnl
${MATCH}
])

OVS_VSWITCHD_STOP
AT_CLEANUP


AT_SETUP([vsctl-bashcomp - argument completion])
AT_SKIP_IF([test -z ${BASH_VERSION+x}])
AT_SKIP_IF([eval 'test ${BASH_VERSINFO[[0]]} -lt 4'])
OVS_VSWITCHD_START(
   [add-br br1 -- \
       set bridge br1 datapath-type=dummy -- \
    add-br foo -- \
       set bridge foo datapath-type=dummy -- \
    add-br --weird-br_name -- \
       set bridge --weird-br_name datapath-type=dummy -- \
    add-port br0 br0p0 -- set Interface br0p0 type=dummy -- \
    add-port br0 br0p1 -- set Interface br0p1 type=dummy -- \
    add-port br1 br1p0 -- set Interface br1p0 type=dummy -- \
    add-port br1 br1p1 -- set Interface br1p1 type=dummy -- \
    add-port foo bar -- set Interface bar type=dummy ])
#
# test completion functions defined in '_OVS_VSCTL_ARG_COMPLETION_FUNCS'.
# therein, the different argument prefixes are also tested at the same time.
#
# A space is appended to each output if completion is configured without
# 'nospace' option.
#


#
# test: _ovs_vsctl_complete_table
#
TMP="$(ovsdb-client --no-heading list-tables)"
MATCH="$(PREPARE_MATCH_SPACE(${TMP}))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set "],
[0], [dnl
${MATCH}
])
MATCH="$(PREPARE_MATCH_SPACE(Open_vSwitch))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set Open"],
[0], [dnl
${MATCH}
])


#
# test: _ovs_vsctl_complete_record
#
TMP="$(ovs-vsctl --no-heading --columns=_uuid list Open_vSwitch | tr -d '\"')"
MATCH="$(PREPARE_MATCH_SPACE(${TMP}))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set Open_vSwitch "],
[0], [dnl
${MATCH}
])
TMP="$(ovs-vsctl --no-heading --columns=_uuid,name list Bridge | tr -d '\"')"
MATCH="$(PREPARE_MATCH_SPACE(${TMP}))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set Bridge "],
[0], [dnl
${MATCH}
])


#
# test: _ovs_vsctl_complete_bridge
#
TMP="$(ovs-vsctl list-br)"
MATCH="$(PREPARE_MATCH_SPACE(${TMP}))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "br-to-vlan "],
[0], [dnl
${MATCH}
])
# this also helps check the '_ovs_vsctl_check_startswith_string'.
MATCH="$(PREPARE_MATCH_SPACE(--weird-br_name))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "br-to-vlan --"],
[0], [dnl
${MATCH}
])


#
# test: _ovs_vsctl_complete_port
#
TMP="$(ovs-vsctl --no-heading --columns=name list Port | tr -d '\"')"
MATCH="$(PREPARE_MATCH_SPACE(${TMP}))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "port-to-br "],
[0], [dnl
${MATCH}
])
# complete on ports in particular bridge.
TMP="$(ovs-vsctl list-ports br0)"
MATCH="$(PREPARE_MATCH_SPACE(${TMP}))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "del-port br0 "],
[0], [dnl
${MATCH}
])


#
# test: _ovs_vsctl_complete_iface
#
for br in `ovs-vsctl list-br`; do
    TMP="${TMP} $(ovs-vsctl list-ifaces $br)"
done
MATCH="$(PREPARE_MATCH_SPACE(${TMP}))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "iface-to-br "],
[0], [dnl
${MATCH}
])


#
# test: _ovs_vsctl_complete_bridge_fail_mode
#
MATCH="$(PREPARE_MATCH_SPACE(standalone secure))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set-fail-mode br0 "],
[0], [dnl
${MATCH}
])


#
# test: _ovs_vsctl_complete_key
#
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "br-set-external-id br0 "],
[0], [dnl

])
# since there is no key added yet, we will only get our own input.
MATCH="$(PREPARE_MATCH_SPACE(test_key))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "br-set-external-id br0 test_key"],
[0], [dnl
${MATCH}
])
# now add a key, as we should see it.
ovs-vsctl br-set-external-id br0 bridge-id br0
MATCH="$(PREPARE_MATCH_SPACE(bridge-id))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "br-set-external-id br0 "],
[0], [dnl
${MATCH}
])
MATCH="$(PREPARE_MATCH_SPACE(bridge-id --))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "br-get-external-id br0 "],
[0], [dnl
${MATCH}
])


#
# test: _ovs_vsctl_complete_value
#
# should just return the user input.
MATCH="$(PREPARE_MATCH_SPACE(test_value --))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "br-set-external-id br0 bridge-id test_value"],
[0], [dnl
${MATCH}
])


#
# test: _ovs_vsctl_complete_column
#
TMP="$(ovsdb-client --no-heading list-columns Open_vSwitch Open_vSwitch | tr -d ':' | cut -d' ' -f1)"
UUID="$(ovs-vsctl --no-heading --columns=_uuid list Open_vSwitch | tr -d ' ')"
MATCH="$(PREPARE_MATCH_SPACE(${TMP}))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "clear Open_vSwitch $UUID "],
[0], [dnl
${MATCH}
])
TMP="$(ovsdb-client --no-heading list-columns Open_vSwitch Bridge | tr -d ':' | cut -d' ' -f1)"
MATCH="$(PREPARE_MATCH_SPACE(${TMP}))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "clear Bridge br0 "],
[0], [dnl
${MATCH}
])
# the 'clear' command requires one or more (+) COLUMN.
# so, with one specified COLUMN 'other_config', it should still complete on
# COLUMNs, plus '--'.
MATCH="$(PREPARE_MATCH_SPACE(${TMP} --))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "clear Bridge br0 other_config "],
[0], [dnl
${MATCH}
])


#
# test: _ovs_vsctl_complete_key_value
#
# with no key available, should always get user input.
MATCH="$(PREPARE_MATCH_NOSPACE(random_key))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "add Bridge br0 other_config random_key"],
[0], [dnl
${MATCH}
])
MATCH="$(PREPARE_MATCH_NOSPACE(abc))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "add Bridge br0 other_config random_key=abc"],
[0], [dnl
${MATCH}
])
# now add two random keys.
ovs-vsctl set Bridge br0 other_config:random_key1=abc other_config:random_val1=xyz
MATCH="$(PREPARE_MATCH_NOSPACE(random_key1= random_val1=))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "add Bridge br0 other_config ran"],
[0], [dnl
${MATCH}
])


#
# test: _ovs_vsctl_complete_column_optkey_value
#
# at first, we should complete on column.
TMP="$(ovsdb-client --no-heading list-columns Open_vSwitch Bridge | awk '/key.*value/ { print $1":"; next } { print $1; next }')"
MATCH="$(PREPARE_MATCH_NOSPACE(${TMP}))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set Bridge br0 "],
[0], [dnl
${MATCH}
])
MATCH="$(PREPARE_MATCH_NOSPACE(other_config:))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set Bridge br0 other"],
[0], [dnl
${MATCH}
])
# then, with the ':' we should complete on key.
TMP="$(ovs-vsctl --no-heading --columns=other_config list Bridge br0 | tr -d '{\"}' | tr -s ', ' '\n' | cut -d'=' -f1)"
MATCH="$(PREPARE_MATCH_NOSPACE(${TMP}))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set Bridge br0 other_config:"],
[0], [dnl
${MATCH}
])
# finally, if user fill in some value, we should just complete on user input.
MATCH="$(PREPARE_MATCH_NOSPACE(random_val1))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set Bridge br0 other_config:random_val1=12345"],
[0], [dnl
${MATCH}
])


#
# test: _ovs_vsctl_complete_filename
#
touch private_key certificate
MATCH="$(PREPARE_MATCH_SPACE(private_key))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set-ssl priva"],
[0], [dnl
${MATCH}
])
MATCH="$(PREPARE_MATCH_SPACE(certificate))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set-ssl private_key cer"],
[0], [dnl
${MATCH}
])


#
# test: _ovs_vsctl_complete_target
#
MATCH="$(PREPARE_MATCH_NOSPACE(pssl: ptcp: punix: ssl: tcp: unix:))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set-manager "],
[0], [dnl
${MATCH}
])
# filename completion on unix, punix.
MATCH="$(PREPARE_MATCH_NOSPACE(testsuite.log))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set-manager unix:test"],
[0], [dnl
${MATCH}
])
# no completion on other type, just return available types.
# in real environment, bash will not complete on anything.
MATCH="$(PREPARE_MATCH_NOSPACE(pssl: ptcp: punix: tcp: unix:))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set-manager ssl:something"],
[0], [dnl
${MATCH}
])


#
# test: _ovs_vsctl_complete_new
#
# test 'add-br'
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "add-br "],
[0], [dnl
--- BEGIN MESSAGE
Enter a new bridge:
> ovs-vsctl add-br --- END MESSAGE
])
# user input does not change the output.
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "add-br new-br"],
[0], [dnl
--- BEGIN MESSAGE
Enter a new bridge:
> ovs-vsctl add-br new-br--- END MESSAGE
])
# after specifying the new bridge name, we should complete on parent bridge.
TMP="$(ovs-vsctl list-br)"
MATCH="$(PREPARE_MATCH_SPACE(${TMP}))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "add-br new-br "],
[0], [dnl
${MATCH}
])
# test 'add-port'
# after specifying the new port name, we should complete on the column part
# of '*COLUMN?:KEY=VALUE'.
TMP="$(ovsdb-client --no-heading list-columns Open_vSwitch Port | awk '/key.*value/ { print $1":"; next } { print $1; next }')"
MATCH="$(PREPARE_MATCH_NOSPACE(${TMP} --))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "add-port br0 new-port "],
[0], [dnl
${MATCH}
])


#
# test: _ovs_vsctl_complete_dashdash
#
# after '--', there should be no global options available for completion.
TMP="$(ovs-vsctl --commands | cut -d',' -f1-2 | tr -d ',[[]]' | tr -s ' ' '\n')"
MATCH="$(PREPARE_MATCH_NOSPACE(${TMP}))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "init -- "],
[0], [dnl
${MATCH}
])
TMP="$(ovs-vsctl --no-heading --columns=name,_uuid list Port | tr -d '\"')"
MATCH="$(PREPARE_MATCH_SPACE(${TMP} newp1 newp2))"
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "add-port br0 newp1 -- add-port br1 newp2 -- set Port "],
[0], [dnl
${MATCH}
])

OVS_VSWITCHD_STOP
AT_CLEANUP


AT_SETUP([vsctl-bashcomp - negative test])
AT_SKIP_IF([test -z ${BASH_VERSION+x}])
AT_SKIP_IF([eval 'test ${BASH_VERSINFO[[0]]} -lt 4'])
OVS_VSWITCHD_START

# complete non-matching command.
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "invalid"],
[0], [dnl

])

# complete after invalid command.
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "invalid argu"],
[0], [dnl

])

# complete non-matching end argument.
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set INVALID_"],
[0], [dnl

])

# complete after invalid intermediate argument.
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "set INVALID_TBL "],
[1], [dnl
--- BEGIN MESSAGE
Cannot complete 'INVALID_TBL' at index 3:
> ovs-vsctl set INVALID_TBL --- END MESSAGE])

# complete ovs-vsctl --db=wrongdb [TAB]
# should return 1 and show nothing.
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test "--db=wrongdb"],
[1], [])

OVS_VSWITCHD_STOP
# delete ovsdb-server and try again.
AT_CHECK_UNQUOTED([ovs-vsctl-bashcomp.bash test ""],
[1], [])

AT_CLEANUP
