diff --git a/Makefile.am b/Makefile.am index 5ec9cf772b223ef858f84f7c296dd7cb045f351f..7ae24ef8830e1e58599fcda53b1435e347069853 100644 --- a/Makefile.am +++ b/Makefile.am @@ -934,6 +934,7 @@ dist_TESTS = \ test/ganeti-cleaner_unittest.bash \ test/import-export_unittest.bash \ test/cli-test.bash \ + test/bash_completion.bash \ $(python_tests) nodist_TESTS = @@ -986,6 +987,7 @@ srclink_files = \ test/ganeti-cleaner_unittest.bash \ test/import-export_unittest.bash \ test/cli-test.bash \ + test/bash_completion.bash \ htest/offline-test.sh \ htest/cli-tests-defs.sh \ $(all_python_code) \ @@ -1030,6 +1032,8 @@ test/daemon-util_unittest.bash: daemons/daemon-util test/ganeti-cleaner_unittest.bash: daemons/ganeti-cleaner +test/bash_completion.bash: doc/examples/bash_completion-debug + tools/kvm-ifup: tools/kvm-ifup.in $(REPLACE_VARS_SED) sed -f $(REPLACE_VARS_SED) < $< > $@ chmod +x $@ diff --git a/test/bash_completion.bash b/test/bash_completion.bash new file mode 100755 index 0000000000000000000000000000000000000000..012ec27968339a9e479e5a7701e438e82b8b6f48 --- /dev/null +++ b/test/bash_completion.bash @@ -0,0 +1,235 @@ +#!/bin/bash +# + +# Copyright (C) 2012 Google Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +set -e -u -o pipefail + +# Disable any locales +export LC_ALL=C + +readonly bash_completion=${TOP_BUILDDIR:-.}/doc/examples/bash_completion-debug +readonly default_wordbreaks=$' \t\n"'\''@><=;|&(:' + +err() { + echo "$@" + echo 'Aborting' + exit 1 +} + +contains() { + local -r needle="$1"; shift + + for value; do + if [[ "$value" = "$needle" ]]; then + return 0 + fi + done + + return 1 +} + +# Prepares a subshell for testing bash completion functions +setup() { + local -r unused=UNUSED + + set +e +u -o pipefail + + . $bash_completion + + COMP_KEY=$unused + COMP_LINE=$unused + COMP_POINT=$unused + COMP_TYPE=$unused + COMP_WORDBREAKS="$default_wordbreaks" + + GANETI_COMPL_LOG= + + unset COMP_CWORD + unset COMP_WORDS +} + +# Check if default wordbreaks are still valid (this detects cases where Bash +# were to change its built-in default value) +# TODO: May need an update for older Bash versions; some didn't include the +# colon character (':') in COMP_WORDBREAKS +( + bashdef=$(env - bash --noprofile --norc -c 'echo -n "$COMP_WORDBREAKS"') + case "$bashdef" in + $default_wordbreaks) ;; + *) + err 'Bash uses unknown value for COMP_WORDBREAKS' + ;; + esac +) + +# Check for --help +for cmd in gnt-{instance,node,group,job}; do + ( + setup + COMP_CWORD=2 + COMP_WORDS=( $cmd list - ) + _${cmd/-/_} + contains --help "${COMPREPLY[@]}" || \ + err "'$cmd list' did not list --help as an option" + ) +done + +# Completing a yes/no option +( + setup + COMP_CWORD=3 + COMP_WORDS=( gnt-node modify --drained ) + _gnt_node + if [[ "${COMPREPLY[*]}" != 'no yes' ]]; then + err "Completing '${COMP_WORDS[@]}' did not give correct result" + fi +) + +# Completing a multiple-choice option +( + setup + COMP_CWORD=2 + COMP_WORDS=( gnt-debug allocator --disk-template=sh foo ) + _gnt_debug + if [[ "${COMPREPLY[*]}" != sharedfile ]]; then + err "Completing '${COMP_WORDS[*]}' did not give correct result" + fi +) + +# Completing a node name +( + setup + + # Override built-in function + _ganeti_nodes() { + echo aanode1 bbnode2 aanode3 + } + + COMP_CWORD=4 + COMP_WORDS=( gnt-node modify --drained yes aa ) + _gnt_node + if [[ "${COMPREPLY[*]}" != 'aanode1 aanode3' ]]; then + err 'Completing node names failed' + fi +) + +# Completing an option when it's not at the end +( + setup + + # Override built-in function + _ganeti_instances() { + echo inst{1..5} + } + + # Completing word in the middle + COMP_CWORD=2 + COMP_WORDS=( gnt-instance list --o inst3 inst inst5 ) + _gnt_node + contains --output "${COMPREPLY[@]}" || err 'Did not complete parameter' +) + +# Completing an instance name +( + setup + + # Override built-in function + _ganeti_instances() { + echo inst{1..5} + } + + # Completing word in the middle + COMP_CWORD=5 + COMP_WORDS=( gnt-instance list -o foobar inst1 inst inst5 ) + _gnt_instance + if [[ "${COMPREPLY[*]}" != "$(echo inst{1..5})" ]]; then + err "Completing '${COMP_WORDS[*]}' did not give correct result" + fi +) + +# Need to test node expansion with different wordbreak settings +[[ "$default_wordbreaks" == *:* ]] || \ + err 'No colon in default wordbreak characters' +for wb in "$default_wordbreaks" "${default_wordbreaks/:/}"; do + ( + setup + + # Override built-in function + _ganeti_nodes() { + echo node{A..C} + } + + COMP_WORDBREAKS="$wb" + + # Completing nodes + COMP_CWORD=3 + COMP_WORDS=( gnt-instance add -n ) + _gnt_instance + if [[ "${COMPREPLY[*]}" != 'nodeA nodeA: nodeB nodeB: nodeC nodeC:' ]]; then + err 'Got wrong node list' + fi + + COMP_CWORD=3 + COMP_WORDS=( gnt-instance add -n nodeB ) + _gnt_instance + if [[ "${COMPREPLY[*]}" != 'nodeB nodeB:' ]]; then + err 'Got wrong node list' + fi + + COMP_CWORD=3 + COMP_WORDS=( gnt-instance add -n nodeC: ) + _gnt_instance + if [[ "$COMP_WORDBREAKS" == *:* ]]; then + expected='nodeA nodeB' + else + expected='nodeC:nodeA nodeC:nodeB' + fi + if [[ "${COMPREPLY[*]}" != "$expected" ]]; then + err 'Got wrong node list' + fi + ) +done + +# Need to test different settings for the extglob shell option +for opt in -u -s; do + verify_extglob() { + if [[ "$(shopt -p extglob)" != "shopt $opt extglob" ]]; then + err 'The "extglob" shell option has an unexpected value' + fi + } + + ( + shopt $opt extglob + + verify_extglob + setup + verify_extglob + + # Completing nodes + COMP_CWORD=4 + COMP_WORDS=( gnt-instance add --os-type busybox --no-n ) + _gnt_instance + if [[ "${COMPREPLY[*]}" != '--no-name-check --no-nics' ]]; then + err "Completing '${COMP_WORDS[*]}' did not give correct result" + fi + verify_extglob + ) +done + +exit 0