tests: Add RunCmdViaExpect function

Improves test readability.
This commit is contained in:
Jiri Kucera 2020-05-28 14:04:03 +02:00
parent e7e88210b1
commit d58a399a9e
4 changed files with 240 additions and 31 deletions

View File

@ -43,6 +43,8 @@ _TESTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
exit 1
}
TEST="${TEST:-/CoreOS/volume_key/tests/Sanity/basic-sanity}"
TESTVERSION="${TESTVERSION:-1.0}"
PACKAGES="${PACKAGES:-volume_key}"
REQUIRES="${REQUIRES:-cryptsetup nss-tools expect tcllib}"
@ -77,6 +79,7 @@ _VOLUME=""
function Setup() {
LANG=C
LC_ALL=C
export EXPECT_SCRIPTS_PATH="${SCRIPTDIR}"
rlAssertRpm --all || return $?
@ -131,28 +134,31 @@ function Cleanup_DestroyVolume() {
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function TestVolumeKeySave() {
RunCmdX 0 \
"volume_key --save ${_VOLUME} --output-format=passphrase -o ${_PACKET}" \
${SCRIPTDIR}/volume_key.exp -- \
--password1 "${_LUKS_PASS}" --password2 "${_PACKET_PASS}" \
${USING_PINENTRY:+--pinentry} -- \
--save "${_VOLUME}" --output-format=passphrase -o "${_PACKET}"
RunCmdViaExpect
Command volume_key
Command --save "${_VOLUME}" --output-format=passphrase -o "${_PACKET}"
Input --lukspass "${_LUKS_PASS}"
Input --packetpass "${_PACKET_PASS}"
Input ${USING_PINENTRY:+--pinentry}
FinishRun
}
AddTest TestVolumeKeySave "save"
function TestVolumeKeyRestore() {
ClearGpgAgentsCache
RunCmdX 0 "volume_key --restore ${_VOLUME} ${_PACKET}" \
${SCRIPTDIR}/volume_key.exp -- \
--password1 "${_PACKET_PASS}" --password2 "${_NEW_LUKS_PASS}" \
${USING_PINENTRY:+--pinentry} -- \
--restore "${_VOLUME}" "${_PACKET}" \
|| return $?
rlAssertExists "${_PACKET}" || return $?
RunCmdX 0 "cryptsetup luksOpen ${_VOLUME} ${_IMAGE}" \
${SCRIPTDIR}/cryptsetup.exp -- --password "${_NEW_LUKS_PASS}" -- \
luksOpen "${_VOLUME}" "${_IMAGE}" \
|| return $?
ClearGpgAgentsCache
RunCmdViaExpect
Command volume_key --restore "${_VOLUME}" "${_PACKET}"
Input --lukspass "${_LUKS_PASS}"
Input --packetpass "${_PACKET_PASS}"
Input ${USING_PINENTRY:+--pinentry}
FinishRun || return $?
RunCmdViaExpect
Command cryptsetup luksOpen "${_VOLUME}" "${_IMAGE}"
Input --password "${_NEW_LUKS_PASS}"
FinishRun || return $?
RunCmd ls -la /dev/mapper
rlAssertExists "/dev/mapper/${_IMAGE}"

View File

@ -31,6 +31,18 @@ Result=""
ResultA=""
ResultB=""
# Internal variables used by RunCmdViaExpect family of functions.
_rlwrap_expect_script_path=""
declare -ag _rlwrap_rlRun_options=()
declare -ag _rlwrap_expect_options=()
_rlwrap_expect_script=""
_rlwrap_expect_script_scommand=""
declare -ag _rlwrap_expect_script_command_args=()
declare -ag _rlwrap_expect_script_input_args=()
_rlwrap_rlRun_status="0"
_rlwrap_rlRun_comment=""
# Internal variables used by RunTest family of functions.
declare -ag _CleanupActions=()
declare -ag _Tests=()
@ -178,6 +190,197 @@ function RunCmdX() {
"${__command}" "${__status}" "${__comment}"
}
##
# RunCmdViaExpect
#
# Starts a specification of command that should be run via expect. This is
# handy for interactive commands. General usage is
#
# RunCmdViaExpect
# Path ${ScriptsDir}
# rlRunOptions -s
# ExpectOptions -f
# Command cryptsetup luksFormat ${VOLUME}
# Input --password ${PASSWD}
# Status 0
# Comment "Format ${VOLUME}"
# FinishRun || return $?
#
# In the example above, Path specifies the directory where the expect script
# is located. If it is omitted, EXPECT_SCRIPTS_PATH environment variable is
# read. If EXPECT_SCRIPTS_PATH is not set, `.` is used.
#
# rlRunOptions are options for rlRun, like -s and -t (see beakerlib manual).
#
# ExpectOptions are options for expect tool or Tcl interpreter, not for the
# script.
#
# Command is a command together with its arguments that will be run via expect.
# The first command argument, the command itself, is used as a name of expect
# script so in the example above the name of expect script will be
# cryptsetup.exp. This script must exist in directory specified by Path. The
# rest of Command arguments will be passed to the end of this script's command
# line and it is up to script's implementation what happen to them.
#
# Input gather arguments that specify input data that are feed to command by
# expect tool when they are asked for.
#
# Input, Command, ExpectOptions, and rlRunOptions work in accumulative way.
# That is, you can write `Command cryptsetup luksFormat ${VOLUME}` as a two
# Command calls, e.g. `Command cryptsetup` and `luksFormat ${VOLUME}`. This
# allow to split long commands accross multiple lines without using backslash
# character, which has the benefit of writing comments for particular command
# options.
#
# Status is the expected status/return code (default is 0).
#
# Comment is the comment as described in rlRun documentation. The default
# comment is a string made from arguments of Command separated by spaces.
#
# FinishRun makes a final arguments for rlRun and execute it. In our case, the
# rlRun call will look like this
#
# rlRun -s "${ScriptsDir}/cryptsetup.exp -f -- --password ${PASSWD} --
# luksFormat ${VOLUME}" 0 "Format ${VOLUME}"
#
# The return code of rlRun is the return code of FinishRun. To parse its
# command line, cryptsetup.exp uses cmdline package from tcllib.
function RunCmdViaExpect() {
_rlwrap_expect_script_path="${EXPECT_SCRIPTS_PATH:-.}"
_rlwrap_rlRun_options=()
_rlwrap_expect_options=()
_rlwrap_expect_script=""
_rlwrap_expect_script_scommand=""
_rlwrap_expect_script_command_args=()
_rlwrap_expect_script_input_args=()
_rlwrap_rlRun_status="0"
_rlwrap_rlRun_comment=""
}
##
# Path [PATH]
#
# PATH
# PATH to script directory
#
# See RunCmdViaExpect.
function Path() {
if [[ $# -gt 0 ]]; then
_rlwrap_expect_script_path="${1}"
fi
}
##
# rlRunOptions [OPTIONS]
#
# OPTIONS
# options for rlRun
#
# See RunCmdViaExpect.
function rlRunOptions() {
_rlwrap_rlRun_options+=( "$@" )
}
##
# ExpectOptions [OPTIONS]
#
# OPTIONS
# options for expect tool
#
# See RunCmdViaExpect.
function ExpectOptions() {
_rlwrap_expect_options+=( "$@" )
}
##
# Command [COMMAND_OR_OPTION] [COMMAND_OPTIONS]
#
# COMMAND_OR_OPTION
# command name or option (depending on a number of Command invocations)
# COMMAND_OPTIONS
# command options
#
# See RunCmdViaExpect.
function Command() {
if [[ -z "${_rlwrap_expect_script}" ]]; then
if [[ -n "${1:-}" ]]; then
_rlwrap_expect_script="${1}.exp"
_rlwrap_expect_script_scommand="${1}"
shift
fi
fi
if [[ $# -gt 0 ]]; then
_rlwrap_expect_script_command_args+=( "$@" )
_rlwrap_expect_script_scommand="${_rlwrap_expect_script_scommand} $*"
fi
}
##
# Input [OPTIONS]
#
# OPTIONS
# options for expect script that are used for passing input values to
# commands that are run from within the script
#
# See RunCmdViaExpect.
function Input() {
_rlwrap_expect_script_input_args+=( "$@" )
}
##
# Status [STATUS_CODE]
#
# STATUS_CODE
# expected status/return code of expect script
#
# See RunCmdViaExpect.
function Status() {
if [[ $# -gt 0 ]]; then
_rlwrap_rlRun_status="${1}"
fi
}
##
# Comment [COMMENT]
#
# COMMENT
# comment to be passed to rlRun
#
# See RunCmdViaExpect.
function Comment() {
if [[ $# -gt 0 ]]; then
_rlwrap_rlRun_comment="${1}"
fi
}
##
# FinishRun
#
# See RunCmdViaExpect.
function FinishRun() {
local __command=""
if [[ -z "${_rlwrap_expect_script}" ]]; then
errmsg "RunCmdViaExpect: Missing name of expect script!"
errmsg "| The name of expect script is deduced from the first"
errmsg "| argument given to Command."
return 1
fi
if [[ -z "${_rlwrap_rlRun_comment}" ]]; then
_rlwrap_rlRun_comment="${_rlwrap_expect_script_scommand}"
fi
__command="${_rlwrap_expect_script_path}/${_rlwrap_expect_script}"
__command="${__command} ${_rlwrap_expect_options[*]} --"
__command="${__command} ${_rlwrap_expect_script_input_args[*]} --"
__command="${__command} ${_rlwrap_expect_script_command_args[*]}"
rlRun "${_rlwrap_rlRun_options[@]}" "${__command}" \
"${_rlwrap_rlRun_status}" "${_rlwrap_rlRun_comment}"
}
##
# CreateTemporaryDirectory
#

View File

@ -91,10 +91,10 @@ function CreateEncryptedVolume() {
)" || return $?
fi
RunCmdX 0 "cryptsetup luksFormat ${__volume}" \
${SCRIPTDIR}/cryptsetup.exp -- --password "${__password}" -- \
luksFormat "${__volume}" \
|| return $?
RunCmdViaExpect
Command cryptsetup luksFormat "${__volume}"
Input --password "${__password}"
FinishRun || return $?
Result="${__volume}"
}

View File

@ -29,8 +29,8 @@ package require cmdline
source [file join [file dirname [info script]] "common.tcl"]
set options {
{password1.arg "" "Password that volume_key may ask for"}
{password2.arg "" "Second password that volume_key may ask for"}
{lukspass.arg "" "Password for LUKS encryption/decryption"}
{packetpass.arg "" "Password for escrow packet encryption/decryption"}
{pinentry "gpg-agent may ask for password via pinentry"}
}
@ -48,18 +48,18 @@ if {[catch {
exit 1
}
set password1 $params(password1)
set password2 $params(password2)
set lukspass $params(lukspass)
set packetpass $params(packetpass)
set pinentry $params(pinentry)
proc prompt_volume_password {password} {
proc prompt_luks_password {password} {
verify_password $password
expect -re "Passphrase for.*"
sleep 1
send -- "$password\r"
}
proc prompt_new_volume_password {password} {
proc prompt_new_luks_password {password} {
verify_password $password
expect -re "New passphrase for.*"
sleep 1
@ -101,11 +101,11 @@ proc prompt_new_packet_password {password pinentry} {
eval spawn volume_key $::argv
if {"--save" in $::argv} {
prompt_volume_password $password1
prompt_new_packet_password $password2 $pinentry
prompt_luks_password $lukspass
prompt_new_packet_password $packetpass $pinentry
expect eof
} elseif {"--restore" in $::argv} {
prompt_packet_password $password1 $pinentry
prompt_new_volume_password $password2
prompt_packet_password $packetpass $pinentry
prompt_new_volume_password $lukspass
expect eof
}