RHEL 9.0.0 Alpha bootstrap

The content of this branch was automatically imported from Fedora ELN
with the following as its source:
https://src.fedoraproject.org/rpms/sudo#68203ed1a2fac7aff1b57189e8c217db89e5fe4a
This commit is contained in:
Troy Dawson 2020-10-15 10:06:29 -07:00
parent f86c836b96
commit 864ea2c24c
49 changed files with 8309 additions and 0 deletions

27
.gitignore vendored
View File

@ -0,0 +1,27 @@
/sudo-1.8.16.tar.gz
/sudo-1.8.17p1.tar.gz
/sudo-1.8.18b2.tar.gz
/sudo-1.8.18rc2.tar.gz
/sudo-1.8.18rc4.tar.gz
/sudo-1.8.18.tar.gz
/sudo-90e4538c001fbe1b791a11d6a2c37607472fafe5.tar.gz
/sudo-738c3cbf3e8400bf4a5aeab8966427ff6d630cd2.tar.gz
/sudo-1.8.19p2.tar.gz
/sudo-1.8.20b1.tar.gz
/sudo-1.8.20p1.tar.gz
/sudo-1.8.20p2.tar.gz
/sudo-1.8.21p2.tar.gz
/sudo-1.8.22b1.tar.gz
/sudo-1.8.23b3.tar.gz
/sudo-1.8.23.tar.gz
/sudo-1.8.25.tar.gz
/sudo-1.8.25p1.tar.gz
/sudo-1.8.27.tar.gz
/sudo-1.8.28.tar.gz
/sudo-1.8.28p1.tar.gz
/sudo-1.8.29.tar.gz
/sudo-1.9.0b1.tar.gz
/sudo-1.9.0b4.tar.gz
/sudo-1.9.1.tar.gz
/sudo-1.9.2.tar.gz
/sudo-1.9.3p1.tar.gz

1
sources Normal file
View File

@ -0,0 +1 @@
SHA512 (sudo-1.9.3p1.tar.gz) = 3ad13fd03e5b371fd6bf7909731ffc11431d2182a744b654f7e5d4b810e47955d49bc78f551afe13ec56acbce694139c33a15bc022cea41b17af5496b8b7f89f

11
sudo-1.6.7p5-strip.patch Normal file
View File

@ -0,0 +1,11 @@
--- sudo-1.6.7p5/install-sh.strip 2005-07-21 14:28:25.000000000 +0200
+++ sudo-1.6.7p5/install-sh 2005-07-21 14:29:18.000000000 +0200
@@ -138,7 +138,7 @@
fi
;;
X-s)
- STRIPIT=true
+ #STRIPIT=true
;;
X--)
shift

16
sudo.rpmlintrc Normal file
View File

@ -0,0 +1,16 @@
# Sudo allows restricted root access for specified users. In other words,
# it is a special package, which requires special permissions on on some
# of the installed files.
addFilter("missing-call-to-setgroups-before-setuid (/usr/bin/sudo|/usr/bin/sudoreplay|/usr/sbin/sudo_logsrvd|/usr/sbin/sudo_sendlog|/usr/libexec/sudo/sudoers.so|)$")
addFilter("non-readable (/etc/sudo.conf|/etc/sudo_logsrvd.conf|/etc/sudoers|/usr/bin/sudoreplay) .*$")
addFilter("non-standard-dir-perm (/etc/sudoers.d|/var/db/sudo|/var/db/sudo/lectured) .*$")
addFilter("setuid-binary /usr/bin/sudo .*$")
addFilter("non-standard-executable-perm (/usr/bin/sudo|/usr/bin/sudoreplay) .*$")
addFilter("wrong-file-end-of-line-encoding /usr/share/doc/sudo/schema.ActiveDirectory$")
addFilter("non-standard-dir-in-var db$")

1016
sudo.spec Normal file

File diff suppressed because it is too large Load Diff

120
sudoers Normal file
View File

@ -0,0 +1,120 @@
## Sudoers allows particular users to run various commands as
## the root user, without needing the root password.
##
## Examples are provided at the bottom of the file for collections
## of related commands, which can then be delegated out to particular
## users or groups.
##
## This file must be edited with the 'visudo' command.
## Host Aliases
## Groups of machines. You may prefer to use hostnames (perhaps using
## wildcards for entire domains) or IP addresses instead.
# Host_Alias FILESERVERS = fs1, fs2
# Host_Alias MAILSERVERS = smtp, smtp2
## User Aliases
## These aren't often necessary, as you can use regular groups
## (ie, from files, LDAP, NIS, etc) in this file - just use %groupname
## rather than USERALIAS
# User_Alias ADMINS = jsmith, mikem
## Command Aliases
## These are groups of related commands...
## Networking
# Cmnd_Alias NETWORKING = /sbin/route, /sbin/ifconfig, /bin/ping, /sbin/dhclient, /usr/bin/net, /sbin/iptables, /usr/bin/rfcomm, /usr/bin/wvdial, /sbin/iwconfig, /sbin/mii-tool
## Installation and management of software
# Cmnd_Alias SOFTWARE = /bin/rpm, /usr/bin/up2date, /usr/bin/yum
## Services
# Cmnd_Alias SERVICES = /sbin/service, /sbin/chkconfig, /usr/bin/systemctl start, /usr/bin/systemctl stop, /usr/bin/systemctl reload, /usr/bin/systemctl restart, /usr/bin/systemctl status, /usr/bin/systemctl enable, /usr/bin/systemctl disable
## Updating the locate database
# Cmnd_Alias LOCATE = /usr/bin/updatedb
## Storage
# Cmnd_Alias STORAGE = /sbin/fdisk, /sbin/sfdisk, /sbin/parted, /sbin/partprobe, /bin/mount, /bin/umount
## Delegating permissions
# Cmnd_Alias DELEGATING = /usr/sbin/visudo, /bin/chown, /bin/chmod, /bin/chgrp
## Processes
# Cmnd_Alias PROCESSES = /bin/nice, /bin/kill, /usr/bin/kill, /usr/bin/killall
## Drivers
# Cmnd_Alias DRIVERS = /sbin/modprobe
# Defaults specification
#
# Refuse to run if unable to disable echo on the tty.
#
Defaults !visiblepw
#
# Preserving HOME has security implications since many programs
# use it when searching for configuration files. Note that HOME
# is already set when the the env_reset option is enabled, so
# this option is only effective for configurations where either
# env_reset is disabled or HOME is present in the env_keep list.
#
Defaults always_set_home
Defaults match_group_by_gid
# Prior to version 1.8.15, groups listed in sudoers that were not
# found in the system group database were passed to the group
# plugin, if any. Starting with 1.8.15, only groups of the form
# %:group are resolved via the group plugin by default.
# We enable always_query_group_plugin to restore old behavior.
# Disable this option for new behavior.
Defaults always_query_group_plugin
Defaults env_reset
Defaults env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS"
Defaults env_keep += "MAIL QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
Defaults env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
Defaults env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
Defaults env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"
#
# Adding HOME to env_keep may enable a user to run unrestricted
# commands via sudo.
#
# Defaults env_keep += "HOME"
Defaults secure_path = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/var/lib/snapd/snap/bin
## Next comes the main part: which users can run what software on
## which machines (the sudoers file can be shared between multiple
## systems).
## Syntax:
##
## user MACHINE=COMMANDS
##
## The COMMANDS section may have other options added to it.
##
## Allow root to run any commands anywhere
root ALL=(ALL) ALL
## Allows members of the 'sys' group to run networking, software,
## service management apps and more.
# %sys ALL = NETWORKING, SOFTWARE, SERVICES, STORAGE, DELEGATING, PROCESSES, LOCATE, DRIVERS
## Allows people in group wheel to run all commands
%wheel ALL=(ALL) ALL
## Same thing without a password
# %wheel ALL=(ALL) NOPASSWD: ALL
## Allows members of the users group to mount and unmount the
## cdrom as root
# %users ALL=/sbin/mount /mnt/cdrom, /sbin/umount /mnt/cdrom
## Allows members of the users group to shutdown this system
# %users localhost=/sbin/shutdown -h now
## Read drop-in files from /etc/sudoers.d (the # here does not mean a comment)
#includedir /etc/sudoers.d

View File

@ -0,0 +1,71 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Makefile of /CoreOS/sudo/Sanity/fully-qualified-hostnames
# Description: checks if sudo works correctly when FQDN is used in /etc/sudoers
# Author: Milos Malik <mmalik@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2011 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export TEST=/CoreOS/sudo/Sanity/fully-qualified-hostnames
export TESTVERSION=1.0
BUILT_FILES=
FILES=$(METADATA) runtest.sh Makefile PURPOSE ssh-sudo.exp
.PHONY: all install download clean
run: $(FILES) build
./runtest.sh
build: $(BUILT_FILES)
chmod a+x runtest.sh
chmod a+x ssh-sudo.exp
clean:
rm -f *~ $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@echo "Owner: Milos Malik <mmalik@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "Description: checks if sudo works correctly when FQDN is used in /etc/sudoers" >> $(METADATA)
@echo "Type: Sanity" >> $(METADATA)
@echo "TestTime: 10m" >> $(METADATA)
@echo "RunFor: sudo" >> $(METADATA)
@echo "Requires: sudo" >> $(METADATA)
@echo "Requires: sed" >> $(METADATA)
@echo "Requires: grep" >> $(METADATA)
@echo "Requires: mktemp" >> $(METADATA)
@echo "Requires: openssh-server" >> $(METADATA)
@echo "Requires: openssh-clients" >> $(METADATA)
@echo "Requires: expect" >> $(METADATA)
@echo "Requires: shadow-utils" >> $(METADATA)
@echo "Priority: Normal" >> $(METADATA)
@echo "License: GPLv2" >> $(METADATA)
@echo "Confidential: no" >> $(METADATA)
@echo "Destructive: no" >> $(METADATA)
rhts-lint $(METADATA)

View File

@ -0,0 +1,3 @@
PURPOSE of /CoreOS/sudo/Sanity/fully-qualified-hostnames
Description: checks if sudo works correctly when FQDN is used in /etc/sudoers
Author: Milos Malik <mmalik@redhat.com>

View File

@ -0,0 +1,106 @@
#!/bin/bash
# vim: dict=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# runtest.sh of /CoreOS/sudo/Sanity/fully-qualified-hostnames
# Description: checks if sudo works correctly when FQDN is used in /etc/sudoers
# Author: Milos Malik <mmalik@redhat.com>
# Edit: Ales "alich" Marecek <amarecek@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2011 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Include rhts environment
. /usr/bin/rhts-environment.sh
. /usr/share/beakerlib/beakerlib.sh
PACKAGE="sudo"
USER_NAME="user${RANDOM}"
USER_SECRET="s3kr3T${RANDOM}"
CONFIG_FILE="/etc/sudoers"
OUTPUT_FILE="sudo.log"
rlJournalStart
rlPhaseStartSetup
rlAssertRpm ${PACKAGE}
rlRun "TmpDir=\$(mktemp -d)" 0 "Creating tmp directory"
rlRun "cp ssh-sudo.exp ${TmpDir}" 0 "Copying expect file"
rlRun "pushd $TmpDir"
OUTPUT_FILE="${TmpDir}/${OUTPUT_FILE}"
rlFileBackup ${CONFIG_FILE} ~/.ssh
id ${USER_NAME} && userdel -r ${USER_NAME}
rlRun "useradd ${USER_NAME}"
rlRun "echo ${USER_SECRET} | passwd --stdin ${USER_NAME}"
rlRun "sed -i 's/^.*requiretty.*$//' ${CONFIG_FILE}"
rlRun "sed -i 's/^.*lecture.*$//' ${CONFIG_FILE}"
rlRun "echo \"Defaults !requiretty, !lecture\" >> ${CONFIG_FILE}"
rlRun "echo \"${USER_NAME} ${HOSTNAME} = (root) `which id`\" >> ${CONFIG_FILE}"
rlRun "> ~/.ssh/known_hosts"
rlPhaseEnd
if rlIsRHEL 5; then
rlPhaseStartTest
rlRun "strings `which sudo` | grep fqdn"
rlPhaseEnd
fi
if echo ${HOSTNAME} | grep -q '^localhost'; then
rlPhaseStartTest
rlLogInfo "skipping fqdn option enabled tests, cannot run with local-only host name ${HOSTNAME}"
rlPhaseEnd
else
rlPhaseStartTest "fqdn option is enabled, command is valid"
rlRun "sed -i 's/^.*fqdn.*$//' ${CONFIG_FILE}"
rlRun "echo \"Defaults fqdn\" >> ${CONFIG_FILE}"
rlRun "./ssh-sudo.exp ${USER_NAME} ${USER_SECRET} localhost id 2>&1 | tee ${OUTPUT_FILE}"
rlAssertGrep "uid=0.*gid=0.*groups=0" ${OUTPUT_FILE}
rlPhaseEnd
rlPhaseStartTest "fqdn option is enabled, command is invalid"
rlRun "sed -i 's/^.*fqdn.*$//' ${CONFIG_FILE}"
rlRun "echo \"Defaults fqdn\" >> ${CONFIG_FILE}"
rlRun "./ssh-sudo.exp ${USER_NAME} ${USER_SECRET} localhost w 2>&1 | tee ${OUTPUT_FILE}"
rlAssertGrep "user.*is not allowed to execute" ${OUTPUT_FILE}
rlPhaseEnd
fi
rlPhaseStartTest "fqdn option is disabled, command is valid"
rlRun "sed -i 's/^.*fqdn.*$//' ${CONFIG_FILE}"
rlRun "echo \"Defaults !fqdn\" >> ${CONFIG_FILE}"
rlRun "./ssh-sudo.exp ${USER_NAME} ${USER_SECRET} localhost id 2>&1 | tee ${OUTPUT_FILE}"
rlAssertGrep "uid=0.*gid=0.*groups=0" ${OUTPUT_FILE}
rlPhaseEnd
rlPhaseStartTest "fqdn option is disabled, command is invalid"
rlRun "sed -i 's/^.*fqdn.*$//' ${CONFIG_FILE}"
rlRun "echo \"Defaults !fqdn\" >> ${CONFIG_FILE}"
rlRun "./ssh-sudo.exp ${USER_NAME} ${USER_SECRET} localhost w 2>&1 | tee ${OUTPUT_FILE}"
rlAssertGrep "user.*is not allowed to execute" ${OUTPUT_FILE}
rlPhaseEnd
rlPhaseStartCleanup
rlRun "userdel -rf ${USER_NAME}"
rlFileRestore
rlRun "popd"
rlRun "rm -r $TmpDir" 0 "Removing tmp directory"
rlPhaseEnd
rlJournalPrintText
rlJournalEnd

View File

@ -0,0 +1,20 @@
#!/usr/bin/expect -f
# usage:
# ./ssh-sudo.exp username password hostname command
set username [lrange $argv 0 0]
set password [lrange $argv 1 1]
set hostname [lrange $argv 2 2]
set command [lrange $argv 3 3]
set timeout 5
spawn ssh -t $username@$hostname sudo $command
expect "*yes/no*" {
send -- "yes\r"
}
expect "*assword*" {
send -- "$password\r"
}
expect "*assword*" {
send -- "$password\r"
}
expect eof

68
tests/run-as/Makefile Normal file
View File

@ -0,0 +1,68 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Makefile of /CoreOS/sudo/Sanity/run-as
# Description: Test feature 'run as'. This means -u, -g options.
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2017 Red Hat, Inc.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export TEST=/CoreOS/sudo/Sanity/run-as
export TESTVERSION=1.0
BUILT_FILES=
FILES=$(METADATA) runtest.sh Makefile PURPOSE
.PHONY: all install download clean
run: $(FILES) build
./runtest.sh
build: $(BUILT_FILES)
test -x runtest.sh || chmod a+x runtest.sh
clean:
rm -f *~ $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@echo "Owner: Dalibor Pospisil <dapospis@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "Description: Test feature 'run as'. This means -u, -g options." >> $(METADATA)
@echo "Type: Sanity" >> $(METADATA)
@echo "TestTime: 5m" >> $(METADATA)
@echo "RunFor: sudo" >> $(METADATA)
@echo "Requires: sudo" >> $(METADATA)
@echo "RhtsRequires: library(distribution/tcf)" >> $(METADATA)
@echo "RhtsRequires: library(distribution/Cleanup)" >> $(METADATA)
@echo "RhtsRequires: library(distribution/testUser)" >> $(METADATA)
@echo "RhtsRequires: library(distribution/ConditionalPhases)" >> $(METADATA)
@echo "Priority: Normal" >> $(METADATA)
@echo "License: GPLv2" >> $(METADATA)
@echo "Confidential: no" >> $(METADATA)
@echo "Destructive: no" >> $(METADATA)
@echo "Releases: -RHEL4 -RHELClient5 -RHELServer5" >> $(METADATA)
rhts-lint $(METADATA)

3
tests/run-as/PURPOSE Normal file
View File

@ -0,0 +1,3 @@
PURPOSE of /CoreOS/sudo/Sanity/run-as
Description: Test feature 'run as'. This means -u, -g options.
Author: Dalibor Pospisil <dapospis@redhat.com>

View File

@ -0,0 +1,59 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Makefile of /distribution/Library/Cleanup
# Description: Block style coding with ability of skipping parts.
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export TEST=/distribution/Library/Cleanup
export TESTVERSION=1.0
BUILT_FILES=
FILES=$(METADATA) lib.sh Makefile
.PHONY: all install download clean
run: $(FILES) build
./runtest.sh
build: $(BUILT_FILES)
test -x runtest.sh || chmod a+x runtest.sh
clean:
rm -f *~ $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@echo "Owner: Dalibor Pospisil <dapospis@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "Description: Provides function to define cleanup stack which can do its work at any time of the test run." >> $(METADATA)
@echo "Type: Library" >> $(METADATA)
@echo "TestTime: 5m" >> $(METADATA)
@echo "Provides: library(distribution/Cleanup)" >> $(METADATA)
@echo "License: GPLv2" >> $(METADATA)
rhts-lint $(METADATA)

View File

@ -0,0 +1,314 @@
#!/bin/bash
# Authors: Dalibor Pospíšil <dapospis@redhat.com>
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# library-prefix = Cleanup
# library-version = 9
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__INTERNAL_Cleanup_LIB_VERSION=9
: <<'=cut'
=pod
=head1 NAME
BeakerLib library Cleanup
=head1 DESCRIPTION
This file contains functions which provides cleanup stack functionality.
=head1 USAGE
To use this functionality you need to import library distribution/Cleanup and add
following line to Makefile.
@echo "RhtsRequires: library(distribution/Cleanup)" >> $(METADATA)
B<Code example>
rlJournalStart
rlPhaseStartSetup
rlImport 'distribution/Cleanup'
tmp=$(mktemp)
CleanupRegister "
rlLog 'Removing data'
rlRun \"rm -f ${tmp}\"
"
rlLog 'Creating some data'
rlRun "echo 'asdfalkjh' > $tmp"
CleanupRegister "
rlLog 'just something to demonstrate unregistering'
"
ID1=$CleanupRegisterID
CleanupUnregister $ID1
CleanupRegister "
rlLog 'just something to demonstrate partial cleanup'
"
ID2=$CleanupRegisterID
CleanupRegister "rlLog 'cleanup some more things'"
# cleanup everything upto ID2
CleanupDo $ID2
CleanupRegister --mark "
rlLog 'yet another something to demonstrate partial cleanup using internal ID saving'
"
CleanupRegister "rlLog 'cleanup some more things'"
# cleanup everything upto last mark
CleanupDo --mark
rlPhaseEnd
rlPhaseStartCleanup
CleanupDo
rlPhaseEnd
rlJournalPrintText
rlJournalEnd
=head1 FUNCTIONS
=cut
echo -n "loading library Cleanup v$__INTERNAL_Cleanup_LIB_VERSION... "
__INTERNAL_Cleanup_stack_file="$BEAKERLIB_DIR/Cleanup_stack"
touch "$__INTERNAL_Cleanup_stack_file"
chmod ug+rw "$__INTERNAL_Cleanup_stack_file"
# CleanupRegister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
# CleanupRegister [--mark] CLEANUP_CODE
# --mark - also mark this position
CleanupRegister() {
local mark=0
[[ "$1" == "--mark" ]] && {
mark=1
shift
}
if ! CleanupGetStack; then
rlLogError "cannot continue, could not get cleanup stack"
return 1
fi
CleanupRegisterID="${RANDOM}$(date +"%s%N")"
echo -n "Registering cleanup ID=$CleanupRegisterID" >&2
if [[ $mark -eq 1 ]]; then
__INTERNAL_CleanupMark=( "$CleanupRegisterID" "${__INTERNAL_CleanupMark[@]}" )
echo -n " with mark" >&2
fi
echo " '$1'" >&2
rlLogDebug "prepending '$1'"
local ID_tag="# ID='$CleanupRegisterID'"
__INTERNAL_Cleanup_stack="$ID_tag
$1
$ID_tag
$__INTERNAL_Cleanup_stack"
if ! CleanupSetStack "$__INTERNAL_Cleanup_stack"; then
rlLogError "an error occured while registering the cleanup '$1'"
return 1
fi
return 0
}; # end of CleanupRegister }}}
# __INTERNAL_Cleanup_get_stack_part ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
# 1: ID
# -ID - everything upto the ID
# 2: '' - return ID only
# 'rest' - return exact oposit
__INTERNAL_Cleanup_get_stack_part() {
rlLogDebug "__INTERNAL_Cleanup_get_stack_part(): $* begin"
local ID="$1"
local n='1 0 1'
local stack=''
[[ "${ID:0:1}" == "-" ]] && {
ID="${ID:1}"
n='0 0 1'
}
[[ "$2" == "rest" ]] && {
n="$(echo "${n//0/2}")"
n="$(echo "${n//1/0}")"
n="$(echo "${n//2/1}")"
}
n=($n)
[[ -n "$DEBUG" ]] && rlLogDebug "$(set | grep ^n=)"
local ID_tag="# ID='$ID'"
while IFS= read -r line; do
[[ "$line" == "$ID_tag" ]] && {
n=( "${n[@]:1}" )
continue
}
if [[ $n -eq 0 ]]; then
stack="$stack
$line"
fi
done < <(echo "$__INTERNAL_Cleanup_stack")
rlLogDebug "__INTERNAL_Cleanup_get_stack_part(): cleanup stack part is '${stack:1}'"
echo "${stack:1}"
rlLogDebug "__INTERNAL_Cleanup_get_stack_part(): $* end"
}; # end of __INTERNAL_Cleanup_get_stack_part }}}
# CleanupUnregister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
CleanupUnregister() {
local ID="$1"
rlLog "Unregistering cleanup ID='$ID'"
if ! CleanupGetStack; then
rlLogError "cannot continue, could not get cleanup stack"
return 1
fi
rlLogDebug "removing ID='$ID'"
if ! CleanupSetStack "$(__INTERNAL_Cleanup_get_stack_part "$ID" 'rest')"; then
rlLogError "an error occured while registering the cleanup '$1'"
return 1
fi
return 0
}; # end of CleanupUnregister }}}
# CleanupMark ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_CleanupMark=()
CleanupMark() {
echo -n "Setting cleanup mark" >&2
CleanupRegister --mark '' 2>/dev/null
local res=$?
echo " ID='$CleanupRegisterID'" >&2
return $res
}; # end of CleanupMark }}}
# CleanupDo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
# 1: '' - cleanup all
# ID - cleanup ID only
# -ID - cleanup all upto ID, including
# mark - cleanup all unto last mark, including
CleanupDo() {
local ID="$1"
if ! CleanupGetStack; then
rlLogError "cannot continue, could not get cleanup stack"
return 1
fi
local res tmp newstack=''
tmp="$(mktemp)"
if [[ "$ID" == "mark" || "$ID" == "--mark" ]]; then
echo "execute cleanup upto mark='$__INTERNAL_CleanupMark'" >&2
__INTERNAL_Cleanup_get_stack_part "-$__INTERNAL_CleanupMark" | grep -v "^# ID='" > "$tmp"
newstack="$(__INTERNAL_Cleanup_get_stack_part "-$__INTERNAL_CleanupMark" 'rest')"
__INTERNAL_CleanupMark=("${__INTERNAL_CleanupMark[@]:1}")
elif [[ -n "$ID" ]]; then
echo "execute cleanup for ID='$ID'" >&2
__INTERNAL_Cleanup_get_stack_part "$ID" | grep -v "^# ID='" > "$tmp"
newstack="$(__INTERNAL_Cleanup_get_stack_part "$ID" 'rest')"
else
CleanupTrapUnhook
trap "echo 'temporarily blocking ctrl+c until cleanup is done' >&2" SIGINT
cat "$__INTERNAL_Cleanup_stack_file" | grep -v "^# ID='" > "$tmp"
echo "execute whole cleanup stack" >&2
fi
. "$tmp"
res=$?
[[ $res -ne 0 ]] && {
echo "cleanup code:" >&2
cat -n "$tmp" >&2
}
rm -f "$tmp"
echo "cleanup execution done" >&2
if [[ -z "$ID" ]]; then
trap - SIGINT
fi
if ! CleanupSetStack "$newstack"; then
rlLogError "an error occured while cleaning the stack"
return 1
fi
return $res
}; # end of CleanupDo }}}
# CleanupGetStack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
CleanupGetStack() {
rlLogDebug "getting cleanup stack"
if [[ -r "$__INTERNAL_Cleanup_stack_file" ]]; then
if __INTERNAL_Cleanup_stack="$(cat "$__INTERNAL_Cleanup_stack_file")"; then
rlLogDebug "cleanup stack is '$__INTERNAL_Cleanup_stack'"
return 0
fi
fi
rlLogError "could not load cleanup stack"
return 1
}; # end of CleanupGetStack }}}
# CleanupSetStack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
CleanupSetStack() {
rlLogDebug "setting cleanup stack to '$1'"
__INTERNAL_Cleanup_stack="$1"
if echo "$__INTERNAL_Cleanup_stack" > "$__INTERNAL_Cleanup_stack_file"; then
rlLogDebug "cleanup stack is now '$__INTERNAL_Cleanup_stack'"
return 0
fi
rlLogError "could not set cleanup stack"
return 1
}; # end of CleanupSetStack }}}
__INTERNAL_Cleanup_signals=''
__INTERNAL_Cleanup_trap_code='rlJournalStart; rlPhaseStartCleanup; CleanupDo; rlPhaseEnd; rlJournalPrintText; rlJournalEnd; exit'
# CleanupTrapHook ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
CleanupTrapHook() {
rlLog "register cleanup trap"
__INTERNAL_Cleanup_signals="${1:-"SIGHUP SIGINT SIGTERM EXIT"}"
eval "trap \"${__INTERNAL_Cleanup_trap_code}\" $__INTERNAL_Cleanup_signals"
}; # end of CleanupTrapHook }}}
# CleanupTrapUnhook ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
CleanupTrapUnhook() {
if [[ -n "$__INTERNAL_Cleanup_signals" ]]; then
rlLog "unregister cleanup trap"
eval trap - $__INTERNAL_Cleanup_signals
__INTERNAL_Cleanup_signals=''
fi
}; # end of CleanupTrapUnhook }}}
# CleanupLibraryLoaded ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
CleanupLibraryLoaded() {
CleanupTrapHook
}; # end of CleanupLibraryLoaded }}}
echo "done."
: <<'=cut'
=pod
=head1 AUTHORS
=over
=item *
Dalibor Pospisil <dapospis@redhat.com>
=back
=cut

View File

@ -0,0 +1,59 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Makefile of /distribution/Library/ConditionalPhases
# Description: Implements conditional phases.
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export TEST=/distribution/Library/ConditionalPhases
export TESTVERSION=1.0
BUILT_FILES=
FILES=$(METADATA) lib.sh Makefile
.PHONY: all install download clean
run: $(FILES) build
./runtest.sh
build: $(BUILT_FILES)
test -x runtest.sh || chmod a+x runtest.sh
clean:
rm -f *~ $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@echo "Owner: Dalibor Pospisil <dapospis@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "Description: Implements conditional phases." >> $(METADATA)
@echo "Type: Library" >> $(METADATA)
@echo "Provides: library(distribution/ConditionalPhases)" >> $(METADATA)
@echo "TestTime: 5m" >> $(METADATA)
@echo "License: GPLv2" >> $(METADATA)
rhts-lint $(METADATA)

View File

@ -0,0 +1,166 @@
#!/bin/bash
# Authors: Dalibor Pospíšil <dapospis@redhat.com>
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# library-prefix = ConditionalPhases
# library-version = 2
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__INTERNAL_ConditionalPhases_LIB_VERSION=2
__INTERNAL_ConditionalPhases_LIB_NAME='distribution/ConditionalPhases'
: <<'=cut'
=pod
=head1 NAME
BeakerLib library distribution/condpahses
=head1 DESCRIPTION
Implements conditional phases to eficiently select test phases to be execute
using white and black lists.
To use this functionality you need to import library
distribution/ConditionalPhases and add following line to Makefile.
@echo "RhtsRequires: library(distribution/ConditionalPhases)" >> $(METADATA)
=head1 USAGE
=head2 Conditional phases
Each test phase can be conditionally skipped based on a bash regular expression
given in CONDITIONAL_PHASES_BL and/or CONDITIONAL_PHASES_WL variables.
=over
=item CONDITIONAL_PHASES_BL
It is a black list. If match phase name the respective phase should be skipped.
=item CONDITIONAL_PHASES_WL
It is a white list. If does B<not> match phase name the respective phase should
be skipped excluding phases contatning 'setup' or 'cleanup' in its name. Names
'setup' and 'cleanup' are matched case insenitively.
=back
Actual skipping has to be done in the test case itself by using return code of
functions I<rlPhaseStart>, I<rlPhaseStartSetup>, I<rlPhaseStartTest>, and
I<rlPhaseStartCleanup>.
Example:
rlPhaseStartTest "phase name" && {
...
rlPhaseEnd; }
Evaluation of the phase relevancy works as follows:
1. If CONDITIONAL_PHASES_BL is non-empty and matches phase name => return 2.
2. If phase name contains word 'setup' or 'cleanup' or CONDITIONAL_PHASES_WL
is empty => return 0.
3. If CONDITIONAL_PHASES_WL is non-empty and matches phase name => return 0
otherwise return 1.
Normaly Setup and Cleanup phases are not skipped unless hey are B<explicitly>
black-listed.
To make the test work properly with conditional phases it is necessary to
surround phase code with curly brackets and make it conditionally executed
based on rlPhaseStart* function's exit code the same way as it is demostrated in
the example above. To make the process easy you can use following command:
sed 's/rlPhaseStart[^{]*$/& \&\& {/;s/rlPhaseEnd[^}]*$/&; }/'
This code can be embedded in Makefile by modifying build target to following
form:
build: $(BUILT_FILES)
grep -Eq 'rlPhase(Start[^{]*|End[^}]*)$' runtest.sh && sed -i 's/rlPhaseStart[^{]*$/& \&\& {/;s/rlPhaseEnd[^}]*$/&; }/' testrun.sh
test -x runtest.sh || chmod a+x runtest.sh
=cut
#'
echo -n "loading library $__INTERNAL_ConditionalPhases_LIB_NAME v$__INTERNAL_ConditionalPhases_LIB_VERSION... "
# ConditionalPhasesLibraryLoaded ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
ConditionalPhasesLibraryLoaded() {
if [[ -n "$CONDITIONAL_PHASES_BL" || -n "$CONDITIONAL_PHASES_WL" ]]; then
__INTERNAL_ConditionalPhases_eval() {
# check phases black-list
[[ -n "$CONDITIONAL_PHASES_BL" && "$1" =~ $CONDITIONAL_PHASES_BL ]] && {
rlLogWarning "phase '$1' should be skipped as it is defined in \$CONDITIONAL_PHASES_BL='$CONDITIONAL_PHASES_BL'"
return 2
}
# always execute Setup, Cleanup and if no PHASES (white-list) specified
[[ "$1" =~ $(echo "\<[Ss][Ee][Tt][Uu][Pp]\>") || "$1" =~ $(echo "\<[Cc][Ll][Ee][Aa][Nn][Uu][Pp]\>") ]] && {
rlLogInfo "phase '$1' will be executed as 'setup' and 'cleanup' phases are allowed by default, these can be black-listed"
return 0
}
[[ -z "$CONDITIONAL_PHASES_WL" ]] && {
rlLogInfo "phase '$1' will be executed as there is no rule for it"
return 0
}
[[ "$1" =~ $CONDITIONAL_PHASES_WL ]] && {
rlLogInfo "phase '$1' will be executed as it is defined in \$CONDITIONAL_PHASES_WL='$CONDITIONAL_PHASES_WL'"
return 0
} || {
rlLogWarning "phase '$1' should be skipped as it is not defined in \$CONDITIONAL_PHASES_WL='$CONDITIONAL_PHASES_WL'"
return 1
}
}
rlLogInfo "replacing rlPhaseStart by modified function with conditional phases implemented"
:; rlPhaseStart() {
if [ "x$1" = "xFAIL" -o "x$1" = "xWARN" ] ; then
__INTERNAL_ConditionalPhases_eval "$2" && \
rljAddPhase "$1" "$2"
return $?
else
rlLogError "rlPhaseStart: Unknown phase type: $1"
return 1
fi
}
else
rlLogInfo "Neither CONDITIONAL_PHASES_WL nor CONDITIONAL_PHASES_BL is defined, not applying modifications"
fi
}; # end of ConditionalPhasesLibraryLoaded }}}
: <<'=cut'
=pod
=head1 AUTHORS
=over
=item *
Dalibor Pospisil <dapospis@redhat.com>
=back
=cut
echo 'done.'

View File

@ -0,0 +1,48 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Makefile of /distribution/Library/Log
# Description: Block style coding with ability of skipping parts.
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export TEST=/distribution/Library/Log
export TESTVERSION=1.0
BUILT_FILES=
FILES=$(METADATA) lib.sh Makefile
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@echo "Owner: Dalibor Pospisil <dapospis@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "Description: Provides yet another logging facility that does not rely on beakerlib while it can integrate with it." >> $(METADATA)
@echo "Type: Library" >> $(METADATA)
@echo "TestTime: 5m" >> $(METADATA)
@echo "RhtsRequires: library(distribution/opts)" >> $(METADATA)
@echo "Provides: library(distribution/Log)" >> $(METADATA)
@echo "License: GPLv2" >> $(METADATA)
rhts-lint $(METADATA)

View File

@ -0,0 +1,637 @@
#!/bin/bash
# Authors: Dalibor Pospíšil <dapospis@redhat.com>
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2013 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# library-prefix = Log
# library-version = 11
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__INTERNAL_Log_LIB_VERSION=11
: <<'=cut'
=pod
=head1 NAME
BeakerLib library Log
=head1 DESCRIPTION
This library provide logging capability which does not rely on beakerlib so it
can be used standalone.
If it is used within beakerlib it automatically bypass all messages to the
beakerlib.
Also this library provide journaling feature so the summary can be printed out
at the end.
=head1 USAGE
To use this functionality you need to import library distribution/Log and add
following line to Makefile.
@echo "RhtsRequires: library(distribution/Log)" >> $(METADATA)
=head1 FUNCTIONS
=cut
echo -n "loading library Log v$__INTERNAL_Log_LIB_VERSION... "
__INTERNAL_Log_prefix=''
__INTERNAL_Log_prefix2=''
__INTERNAL_Log_postfix=''
__INTERNAL_Log_default_level=3
__INTERNAL_Log_level=$__INTERNAL_Log_default_level
LogSetDebugLevel() {
if [[ -n "$1" ]]; then
if [[ "$1" =~ ^[0-9]+$ ]]; then
let __INTERNAL_Log_level=$__INTERNAL_Log_default_level+$1;
else
__INTERNAL_Log_level=255
fi
else
__INTERNAL_Log_level=$__INTERNAL_Log_default_level
fi
}
LogSetDebugLevel "$DEBUG"
let __INTERNAL_Log_level_LOG=0
let __INTERNAL_Log_level_FATAL=0
let __INTERNAL_Log_level_ERROR=1
let __INTERNAL_Log_level_WARNING=2
let __INTERNAL_Log_level_INFO=3
let __INTERNAL_Log_level_DEBUG=4
let __INTERNAL_Log_level_MORE=5
let __INTERNAL_Log_level_MORE_=$__INTERNAL_Log_level_MORE+1
let __INTERNAL_Log_level_MORE__=$__INTERNAL_Log_level_MORE_+1
let __INTERNAL_Log_level_MORE___=$__INTERNAL_Log_level_MORE__+1
# Log ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
Log() {
LogMore___ -f "begin '$*'"
local pri=$2 message="${__INTERNAL_Log_prefix}${__INTERNAL_Log_prefix2}${1}${__INTERNAL_Log_postfix}"
if [[ -n "$pri" ]]; then
LogPrintMessage "$pri" "$message"
LogjAddMessage "$pri" "$message"
else
LogPrintMessage "$(date +%H:%M:%S)" "$message"
LogjAddMessage "INFO" "$message"
fi
LogMore___ -f "end"
return 0
}; # end of Log }}}
__INTERNAL_Log_condition() {
cat <<EOF
__INTERNAL_Log_level_do=$1
if [[ \$__INTERNAL_Log_level -ge \$__INTERNAL_Log_level_do ]]; then
[[ -z "$2" ]] && return 1
else
return 0
fi
EOF
}
# LogInfo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogInfo() {
__INTERNAL_LogPrio='INFO'
eval "$(__INTERNAL_Log_condition \$__INTERNAL_Log_level_INFO \"\$1\")"
LogMore___ -f "begin '$*'"
__INTERNAL_LogPrio='INFO'
Log "$1" $__INTERNAL_LogPrio
LogMore___ -f "end"
return 0
}; # end of LogInfo }}}
# LogWarn ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogWarn() {
__INTERNAL_LogPrio='WARNING'
eval "$(__INTERNAL_Log_condition \$__INTERNAL_Log_level_WARNING \"\$1\")"
LogMore___ -f "begin '$*'"
__INTERNAL_LogPrio='WARNING'
Log "$1" $__INTERNAL_LogPrio
LogMore___ -f "end"
return 0
}; # end of LogWarn }}}
# LogWarning ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogWarning() {
__INTERNAL_LogPrio='WARNING'
eval "$(__INTERNAL_Log_condition \$__INTERNAL_Log_level_WARNING \"\$1\")"
LogMore___ -f "begin '$*'"
__INTERNAL_LogPrio='WARNING'
Log "$1" $__INTERNAL_LogPrio
LogMore___ -f "end"
return 0
}; # end of LogWarning }}}
# LogError ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogError() {
__INTERNAL_LogPrio='ERROR'
eval "$(__INTERNAL_Log_condition \$__INTERNAL_Log_level_ERROR \"\$1\")"
LogMore___ -f "begin '$*'"
__INTERNAL_LogPrio='ERROR'
Log "$1" $__INTERNAL_LogPrio
LogMore___ -f "end"
return 0
}; # end of LogError }}}
# LogFatal ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogFatal() {
__INTERNAL_LogPrio='FATAL'
eval "$(__INTERNAL_Log_condition \$__INTERNAL_Log_level_FATAL \"\$1\")"
LogMore___ -f "begin '$*'"
__INTERNAL_LogPrio='FATAL'
Log "$1" $__INTERNAL_LogPrio
exit 255
LogMore___ -f "end"
}; # end of LogFatal }}}
# LogPASS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogPASS() {
LogMore___ -f "begin '$*'"
Log "$1" PASS
LogMore___ -f "end"
return 0
}
LogPass() {
LogPASS "$@"
}; # end of LogPASS }}}
# LogFAIL ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogFAIL() {
LogMore___ -f "begin '$*'"
Log "$1" FAIL
LogMore___ -f "end"
return 0
}
LogFail() {
LogFAIL "$@"
}; # end of LogFAIL }}}
# LogDo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogDo() {
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
local tmp=${BASH_REMATCH[1]:-1}
pref="${FUNCNAME[$tmp]}(): "
}
LogPrintMessage "$__INTERNAL_LogPrio" "${__INTERNAL_Log_prefix}${pref}${__INTERNAL_Log_prefix2}${1}${__INTERNAL_Log_postfix}"
return 0
}; # end of LogDo }}}
# LogDebug ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogDebug() {
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}+1))"
}
__INTERNAL_Log_level_do=${2:-$__INTERNAL_Log_level_DEBUG}
__INTERNAL_LogPrio='DEBUG'
[[ $__INTERNAL_Log_level_do -ge $__INTERNAL_Log_level_MORE ]] && __INTERNAL_LogPrio="${__INTERNAL_LogPrio}:$(($__INTERNAL_Log_level_do-$__INTERNAL_Log_level_DEBUG+1))"
eval "$(__INTERNAL_Log_condition \${2:-\$__INTERNAL_Log_level_DEBUG} \"\$1\")"
LogDo $pref "$1"
return 0
}; # end of LogDebug }}}
# LogMore ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogMore() {
# log if DEBUG does not containg a number
# or the number is greater or equal to 2
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}+1))"
}
LogDebug $pref "$1" ${2:-$__INTERNAL_Log_level_MORE}
}; # end of LogMore }}}
# LogMore_ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogMore_() {
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}+1))"
}
LogDebug $pref "$1" $__INTERNAL_Log_level_MORE_
}; # end of LogMore_ }}}
# LogMore__ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogMore__() {
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}+1))"
}
LogDebug $pref "$1" $__INTERNAL_Log_level_MORE__
}; # end of LogMore__ }}}
# LogMore___ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogMore___() {
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}+1))"
}
LogDebug $pref "$1" $__INTERNAL_Log_level_MORE___
}; # end of LogMore___ }}}
# LogMoreLow ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_LogMoreLow_Obs=''
LogMoreLow() {
[[ -z "$__INTERNAL_LogMoreLow_Obs" ]] && {
LogMore_ -f "LogMoreLow is obsoleted by LogMore_"
__INTERNAL_LogMoreLow_Obs=1
}
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}+1))"
}
LogDebug $pref "$1" $__INTERNAL_Log_level_MORE_
}; # end of LogMoreLow }}}
# LogMoreMed ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_LogMoreMed_Obs=''
LogMoreMed() {
[[ -z "$__INTERNAL_LogMoreMed_Obs" ]] && {
LogMore__ -f "LogMoreMed is obsoleted by LogMore__"
__INTERNAL_LogMoreMed_Obs=1
}
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}+1))"
}
LogDebug $pref "$1" $__INTERNAL_Log_level_MORE__
}; # end of LogMoreMed }}}
# LogMoreHigh ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_LogMoreHigh_Obs=''
LogMoreHigh() {
[[ -z "$__INTERNAL_LogMoreHigh_Obs" ]] && {
LogMore___ -f "LogMoreHigh is obsoleted by LogMore___"
__INTERNAL_LogMoreHigh_Obs=1
}
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}+1))"
}
LogDebug $pref "$1" $__INTERNAL_Log_level_MORE___
}; # end of LogMoreHigh }}}
# LogjAddMessage ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogjAddMessage() {
LogMore__ -f "begin '$*'"
__INTERNAL_Log_journal=("${__INTERNAL_Log_journal[@]}" "$1" "$2")
LogMore__ -f "end"
true;
}; # end of LogjAddMessage }}}
# __INTERNAL_LogCenterText ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_LogCenterText() {
local spaces=' '
# strip colors
local log_pri_strip=$(echo -en "$1" | sed -r "s:\x1B\[[0-9;]*[mK]::g")
local log_pri_strip_count=${#log_pri_strip}
local left_spaces=$(( ($2 - $log_pri_strip_count) / 2 ))
local right_spaces=$(( $2 - $log_pri_strip_count - $left_spaces ))
echo -en "${spaces:0:$left_spaces}${1}${spaces:0:$right_spaces}"
}; # end of __INTERNAL_LogCenterText }}}
# LogPrintMessage ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogPrintMessage() {
echo -e ":: [$(__INTERNAL_LogCenterText "$1" 10)] :: $2" >&2
return 0
}; # end of LogPrintMessage }}}
# LogReport ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 LogReport
Prints final report similar to breakerlib's rlJournalPrintText. This is useful
mainly if you use TCF without beakerlib.
LogReport
=cut
#'
LogReport() {
echo -e "\n ====== Summary report begin ======"
local a p l i
for i in $(seq 0 2 $((${#__INTERNAL_Log_journal[@]}-1)) ); do
LogPrintMessage "${__INTERNAL_Log_journal[$i]}" "${__INTERNAL_Log_journal[$((++i))]}"
done
echo " ======= Summary report end ======="
__INTERNAL_Log_journal=()
}; # end of LogReport }}}
# LogFile ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogFile() {
LogMore__ -f "begin '$*'"
local prio=''
[[ $# -ge 3 ]] && {
optsBegin
optsAdd 'prio|tag|p|t' --mandatory
optsDone; eval "${optsCode}"
}
cat $1 | while IFS= read line; do
Log "$line" "${prio:-$2}"
done
LogMore__ -f "end"
}; #}}}
# LogText ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogText() {
LogMore__ -f "begin '$*'"
local prio=''
[[ $# -ge 3 ]] && {
optsBegin
optsAdd 'prio|tag|p|t' --mandatory
optsDone; eval "${optsCode}"
}
{
if [[ "$1" == "-" ]]; then
cat -
else
echo "$1"
fi
} | while IFS= read line; do
Log "$line" "${prio:-$2}"
done
LogMore__ -f "end"
}; #}}}
# LogStrippedDiff ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogStrippedDiff() {
LogMore__ -f "begin '$*'"
local prio=''
[[ $# -ge 3 ]] && {
optsBegin
optsAdd 'prio|tag|p|t' --mandatory
optsDone; eval "${optsCode}"
}
{
if [[ -n "$2" ]]; then
diff -U0 "$1" "$2"
else
cat $1
fi
} | grep -v -e '^@@ ' -e '^--- ' -e '^+++ ' | while IFS= read line; do
Log "$line" "$prio"
done
LogMore__ -f "end"
}; #}}}
# LogRun ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
# log info about execution to Debug level
LogRun() {
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}+1))"
}
LogMore
local dolog=$?
[[ $dolog -eq 0 ]] || {
local param params blacklist="[[:space:]]|>|<|\|"
[[ "${#@}" -eq 1 ]] && params="$1" || {
for param in "$@"; do
if [[ "$param" =~ $blacklist ]]; then
params="$params \"${param//\"/\\\"}\""
else
params="$params $param"
fi
done
params="${params:1}"
}
LogDo $pref "executing >>>>> ${params} <<<<<"
}
eval "$@"
ret=$?
[[ $dolog -eq 0 ]] || LogMore $pref "execution >>>>> ${params} <<<<< returned '$ret'"
return $ret
}; # end of LogRun }}}
# LogDebugNext ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
# log info about execution to Debug level
LogDebugNext() {
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}))"
}
LogDebug '' ${1:-$__INTERNAL_Log_level_DEBUG} || {
__INTERNAL_Log_DEBUGING=0
trap "
__INTERNAL_Log_DEBUGING_res=\$?
let __INTERNAL_Log_DEBUGING++
if [[ \$__INTERNAL_Log_DEBUGING -eq 1 ]]; then
__INTERNAL_Log_DEBUGING_cmd=\"\$BASH_COMMAND\"
LogDebug $pref \"executing >>>>> \$__INTERNAL_Log_DEBUGING_cmd <<<<<\" ${1:-$__INTERNAL_Log_level_DEBUG}
else
trap - DEBUG
LogDebug $pref \"execution >>>>> \$__INTERNAL_Log_DEBUGING_cmd <<<<< returned \$__INTERNAL_Log_DEBUGING_res\" ${1:-$__INTERNAL_Log_level_DEBUG}
fi" DEBUG
}
}; # end of LogDebugNext }}}
# LogMoreNext ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
# log info about execution to Debug level
LogMoreNext() {
LogMore || {
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}))"
}
LogDebugNext $pref ${1:-$__INTERNAL_Log_level_MORE}
}
}; # end of LogMoreNext }}}
LogNext() {
LogMoreNext "$@"
}
# LogDebugOn ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
# log info about execution to Debug level
LogDebugOn() {
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}))"
}
LogDebug '' ${1:-$__INTERNAL_Log_level_DEBUG} || {
trap "
__INTERNAL_Log_DEBUGING_res=\$?
let __INTERNAL_Log_DEBUGING++
if [[ -z \"\$__INTERNAL_Log_DEBUGING_cmd\" ]]; then
__INTERNAL_Log_DEBUGING_cmd=\"\$BASH_COMMAND\"
LogDebug $pref \"executing >>>>> \$__INTERNAL_Log_DEBUGING_cmd <<<<<\" ${1:-$__INTERNAL_Log_level_DEBUG}
else
LogDebug $pref \"execution >>>>> \$__INTERNAL_Log_DEBUGING_cmd <<<<< returned \$__INTERNAL_Log_DEBUGING_res\" ${1:-$__INTERNAL_Log_level_DEBUG}
__INTERNAL_Log_DEBUGING_cmd=\"\$BASH_COMMAND\"
if [[ \"\$__INTERNAL_Log_DEBUGING_cmd\" =~ LogDebugOff ]]; then
trap - DEBUG
else
LogDebug $pref \"executing >>>>> \$__INTERNAL_Log_DEBUGING_cmd <<<<<\" ${1:-$__INTERNAL_Log_level_DEBUG}
fi
fi" DEBUG
}
}; # end of LogDebugOn }}}
# LogMoreOn ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
# log info about execution to Debug level
LogMoreOn() {
LogMore || {
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}))"
}
LogDebugOn $pref ${1:-$__INTERNAL_Log_level_MORE}
}
}; # end of LogMoreOn }}}
# LogDebugOff ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
# log info about execution to Debug level
LogDebugOff() {
__INTERNAL_Log_DEBUGING_cmd=''
}; # end of LogDebugOff }}}
# LogVar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogVar() {
[[ -n "$DEBUG" ]] && {
echo -n 'eval '
while [[ -n "$1" ]]; do
echo -n "LogDebug -f \"\$(set | grep -P '^$1=')\";"
shift
done
}
}; # end of LogVar }}}
# __INTERNAL_LogRedirectToBeakerlib ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_LogRedirectToBeakerlib() {
echo -e "\nrunning inside the beakerlib - redirect own logging functions to beakerlib ones"
true; LogjAddMessage() {
LogMore___ -f "begin $*"
rljAddMessage "$2" "$1"
LogMore___ -f "end $*"
}
true; Log() {
LogMore___ -f "begin $*"
case ${2} in
INFO)
LogjAddMessage "INFO" "$1"
LogPrintMessage "$2" "${__INTERNAL_Log_prefix}${__INTERNAL_Log_prefix2}${1}${__INTERNAL_Log_postfix}"
;;
BEGIN)
LogjAddMessage "INFO" "$*:"
LogPrintMessage "$2" "${__INTERNAL_Log_prefix}${__INTERNAL_Log_prefix2}${1}${__INTERNAL_Log_postfix}"
;;
WARNING|WARN|ERROR|FATAL)
LogjAddMessage "WARNING" "$1"
LogPrintMessage "$2" "${__INTERNAL_Log_prefix}${__INTERNAL_Log_prefix2}${1}${__INTERNAL_Log_postfix}"
;;
SKIP|SKIPPING)
LogjAddMessage "WARNING" "$*:"
LogPrintMessage "$2" "${__INTERNAL_Log_prefix}${__INTERNAL_Log_prefix2}${1}${__INTERNAL_Log_postfix}"
;;
FAIL)
rlFail "$*"
return $?
;;
PASS)
rlPass "$*"
return $?
;;
*)
rlLog "$*"
;;
esac
LogMore___ -f "end $*"
return 0;
}
}
# end of __INTERNAL_LogRedirectToBeakerlib }}}
# LogLibraryLoaded ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogLibraryLoaded() {
declare -F rlDie > /dev/null && __INTERNAL_LogRedirectToBeakerlib
return 0
}; # end of LogLibraryLoaded }}}
echo "done."
: <<'=cut'
=pod
=head1 AUTHORS
=over
=item *
Dalibor Pospisil <dapospis@redhat.com>
=back
=cut

View File

@ -0,0 +1,48 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Makefile of /distribution/Library/opts
# Description: Block style coding with ability of skipping parts.
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export TEST=/distribution/Library/opts
export TESTVERSION=1.0
BUILT_FILES=
FILES=$(METADATA) lib.sh Makefile
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@echo "Owner: Dalibor Pospisil <dapospis@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "Description: Provides simple way for defining script's or function's options including help" >> $(METADATA)
@echo "Type: Library" >> $(METADATA)
@echo "TestTime: 5m" >> $(METADATA)
@echo "RhtsRequires: library(distribution/Log)" >> $(METADATA)
@echo "Provides: library(distribution/opts)" >> $(METADATA)
@echo "License: GPLv2" >> $(METADATA)
rhts-lint $(METADATA)

View File

@ -0,0 +1,338 @@
#!/bin/bash
# Authors: Dalibor Pospíšil <dapospis@redhat.com>
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2013 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# library-prefix = opts
# library-version = 4
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__INTERNAL_opts_LIB_VERSION=4
: <<'=cut'
=pod
=head1 NAME
BeakerLib library opts
=head1 DESCRIPTION
This library provides simple way for defining script's or function's option
agruments including help.
=head1 USAGE
To use this functionality you need to import library distribution/opts and add
following line to Makefile.
@echo "RhtsRequires: library(distribution/opts)" >> $(METADATA)
B<Code example>
testfunction() {
optsBegin -h "Usage: $0 [options]
options:
"
optsAdd 'flag1' --flag
optsAdd 'optional1|o' --optional
optsAdd 'Optional2|O' "echo opt \$1" --optional --long --var-name opt
optsAdd 'mandatory1|m' "echo man \$1" --mandatory
optsDone; eval "${optsCode}"
echo "$optional1"
echo "$opt"
echo "$mandatory1"
}
=head1 FUNCTIONS
=cut
echo -n "loading library opts v$__INTERNAL_opts_LIB_VERSION... "
# optsAdd ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
optsAdd() {
LogMoreMed -f "begin '$*'"
local GETOPT=$(getopt -q -o fomv:d:lh:l -l flag,opt,optional,mandatory,varname:,default:,local,help:,long -- "$@")
eval set -- "$GETOPT"
local type='f' var_name var_name_set default help long
while [[ -n "$@" ]]; do
case $1 in
--)
shift; break
;;
-h|--help)
shift
help="$1"
;;
-l|--long)
long=1
;;
-d|--default)
shift
default="$1"
;;
-v|--varname|--var-name)
shift
var_name="$1"
var_name_set=1
;;
-f|--flag)
type='f'
;;
-o|--opt|--optional)
type='o'
;;
-m|--mandatory)
type='m'
;;
*)
echo "unknown option '$1'"
return 1
;;
esac
shift;
done
[ -z "$var_name" ] && {
var_name=$(echo -n "$1" | cut -d '|' -f 1 | sed -e 's/-//g;s/^[0-9]/_\0/')
LogMoreHigh -f "constructing variable name '$var_name'"
}
local opts='' opts_help='' optsi=''
for optsi in $(echo -n "$1" | tr '|' ' '); do
if [[ ${#optsi} -ge 2 || $long -eq 1 ]]; then
opts="$opts|--$optsi"
opts_help="$opts_help|--$optsi[=ARG]"
__INTERNAL_opts_long="${__INTERNAL_opts_long},${optsi}"
LogMoreHigh -f "adding long option '$optsi'"
case $type in
m)
__INTERNAL_opts_long="${__INTERNAL_opts_long}:"
;;
o)
__INTERNAL_opts_long="${__INTERNAL_opts_long}::"
;;
esac
else
opts="$opts|-$optsi"
opts_help="$opts_help|-${optsi}[ARG]"
__INTERNAL_opts_short="${__INTERNAL_opts_short}${optsi}"
LogMoreHigh -f "adding short option '$optsi'"
case $type in
m)
__INTERNAL_opts_short="${__INTERNAL_opts_short}:"
;;
o)
__INTERNAL_opts_short="${__INTERNAL_opts_short}::"
;;
esac
fi
done
optsCode="${optsCode}
${opts:1})
optsPresent=\"\${optsPresent}$var_name \""
LogMoreHigh -f "adding code for processing option '${opts:1}'"
__INTERNAL_opts_init_var="$__INTERNAL_opts_init_var
${__INTERNAL_opts_local}$var_name=()"
__INTERNAL_opts_default="$__INTERNAL_opts_default
[[ \"\$optsPresent\" =~ \$(echo \"\<${var_name}\>\") ]] || ${__INTERNAL_opts_local}$var_name='$default'"
case $type in
f)
[[ -z "$2" || -n "$var_name_set" ]] && {
local val=1
[[ -n "$default" ]] && val=''
optsCode="$optsCode
$var_name+=( '$val' )"
}
__INTERNAL_opts_help="${__INTERNAL_opts_help}
${opts:1}"
;;
o|m)
optsCode="$optsCode
shift"
[[ -z "$2" || -n "$var_name_set" ]] && optsCode="$optsCode
$var_name+=( \"\$1\" )"
if [[ "$type" == "o" ]]; then
__INTERNAL_opts_help="${__INTERNAL_opts_help}
${opts_help:1}"
else
__INTERNAL_opts_help="${__INTERNAL_opts_help}
${opts:1} ARG"
fi
;;
esac
[[ -n "$2" ]] && {
optsCode="$optsCode
$2"
}
optsCode="$optsCode
;;"
__INTERNAL_opts_help="${__INTERNAL_opts_help}${help:+
$help
}"
LogMoreMed -f "end"
}; # end of optsAdd }}}
# optsBegin ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
optsBegin() {
LogMoreMed -f "begin '$*'"
optsCode=''
optsPresent=' '
__INTERNAL_opts_short='.'
__INTERNAL_opts_long='help'
__INTERNAL_opts_help=''
__INTERNAL_opts_local=''
__INTERNAL_opts_default=''
__INTERNAL_opts_init_var=''
[[ "${FUNCNAME[1]}" != "main" ]] && __INTERNAL_opts_local='local '
while [[ -n "$1" ]]; do
case $1 in
--)
shift; break
;;
-h|--help)
shift
__INTERNAL_opts_help="$1"
;;
*)
echo "unknown option '$1'"
return 1
;;
esac
shift;
done
LogMoreMed -f "end"
}; # end of optsBegin }}}
# optsDone ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
optsDone() {
LogMoreMed -f "begin '$*'"
optsCode="${__INTERNAL_opts_local}GETOPT=\$(getopt -o ${__INTERNAL_opts_short} -l ${__INTERNAL_opts_long} -- \"\$@\")
[[ \$? -ne 0 ]] && {
echo 'Exiting'
return 1 >& /dev/null
exit 1
}
eval set -- \"\$GETOPT\"
${__INTERNAL_opts_init_var:1}
while [[ -n \"\$1\" ]]; do
case \$1 in
--)
shift; break
;;
${optsCode}
--help)
echo \"\$__INTERNAL_opts_help\"
return >& /dev/null
exit
;;
*)
echo \"unknown option '\$1'\"
return 1 >& /dev/null
exit 1
;;
esac
shift
done
${__INTERNAL_opts_default:1}
unset optsCode __INTERNAL_opts_help __INTERNAL_opts_short __INTERNAL_opts_long __INTERNAL_opts_default __INTERNAL_opts_init_var __INTERNAL_opts_local
"
if ! echo "$optsCode" | grep -q -- '--help$'; then
__INTERNAL_opts_help="$__INTERNAL_opts_help
--help
Show this help."
fi
LogMoreHigh -f "optsCode:\n$optsCode"
LogMoreMed -f "end"
}; # end of optsDone }}}
# optsSelfCheck ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
optsSelfCheck() {
optsBegin -h "Usage: $0 [options]
options:
"
# optsAdd 'help' -f 'echo help'
optsAdd 'flag' -f 'echo f'
optsAdd 'optional|o' -o "echo opt \$1"
optsAdd 'Optional|O' -o "echo opt \$1" --long
optsAdd 'mandatory|m' -m "echo man \$1"
optsDone
echo "${optsCode}"
echo ...
eval "${optsCode}"
echo ...
fce() {
optsBegin -h "Usage: $0 [options]
options:
"
# optsAdd 'help' -f 'echo help'
optsAdd 'flag' -f
optsAdd 'optional|o' -o "echo opt \$1"
optsAdd 'Optional|O' -o "echo opt \$1" --long
optsAdd 'mandatory|m' -m "echo man \$1"
optsDone
echo "${optsCode}"
echo ...
eval "${optsCode}"
echo ...
}
echo -e 'test for opts in function\n========================='
fce --help
}; # end of optsSelfCheck }}}
# optsLibraryLoaded ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
optsLibraryLoaded() {
return 0
}; # end of LogLibraryLoaded }}}
echo "done."
: <<'=cut'
=pod
=head1 AUTHORS
=over
=item *
Dalibor Pospisil <dapospis@redhat.com>
=back
=cut

View File

@ -0,0 +1,60 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Makefile of /distribution/Library/tcf
# Description: Block style coding with ability of skipping parts.
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export TEST=/distribution/Library/tcf
export TESTVERSION=1.0
BUILT_FILES=
FILES=$(METADATA) lib.sh Makefile
.PHONY: all install download clean
run: $(FILES) build
./runtest.sh
build: $(BUILT_FILES)
test -x runtest.sh || chmod a+x runtest.sh
clean:
rm -f *~ $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@echo "Owner: Dalibor Pospisil <dapospis@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "Description: Block style coding with ability of skipping parts." >> $(METADATA)
@echo "Type: Library" >> $(METADATA)
@echo "TestTime: 5m" >> $(METADATA)
@echo "RhtsRequires: library(distribution/Log)" >> $(METADATA)
@echo "Provides: library(distribution/tcf)" >> $(METADATA)
@echo "License: GPLv2" >> $(METADATA)
rhts-lint $(METADATA)

View File

@ -0,0 +1,903 @@
#!/bin/bash
# try-check-final.sh
# Authors: Dalibor Pospíšil <dapospis@redhat.com>
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# library-prefix = tcf
# library-version = 14
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__INTERNAL_tcf_LIB_VERSION=14
: <<'=cut'
=pod
=head1 NAME
BeakerLib library Try-Check-Final
=head1 DESCRIPTION
This file contains functions which gives user the ability to define blocks of
code where some of the blocks can be automatically skipped if some of preceeding
blocks failed.
ATTENTION
This plugin modifies some beakerlib functions! If you suspect that it breakes
some functionality set the environment variable TCF_NOHACK to nonempty value.
=head1 USAGE
To use this functionality you need to import library distribution/tcf and add
following line to Makefile.
@echo "RhtsRequires: library(distribution/tcf)" >> $(METADATA)
=head1 FUNCTIONS
=cut
echo -n "loading library try-check-final v$__INTERNAL_tcf_LIB_VERSION... "
let __INTERNAL_tcf_DEBUG_LEVEL_LOW=3
let __INTERNAL_tcf_DEBUG_LEVEL_MED=$__INTERNAL_tcf_DEBUG_LEVEL_LOW+1
let __INTERNAL_tcf_DEBUG_LEVEL_HIGH=$__INTERNAL_tcf_DEBUG_LEVEL_LOW+2
# global variables {{{
__INTERNAL_tcf_result=0
__INTERNAL_tcf_result_file="${BEAKERLIB_DIR:-"/var/tmp"}/tcf.result"
echo -n "$__INTERNAL_tcf_result" > "$__INTERNAL_tcf_result_file"
__INTERNAL_tcf_current_level_data=()
__INTERNAL_tcf_current_level_val=0
__INTERNAL_tcf_journal=()
#}}}
# __INTERNAL_tcf_colorize ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_colorize() {
local a
case $1 in
PASS)
a="${__INTERNAL_tcf_color_green}${1}${__INTERNAL_tcf_color_reset}"
;;
FAIL)
a="${__INTERNAL_tcf_color_red}${1}${__INTERNAL_tcf_color_reset}"
;;
SKIPPING|WARNING)
a="${__INTERNAL_tcf_color_yellow}${1}${__INTERNAL_tcf_color_reset}"
;;
BEGIN|INFO)
a="${__INTERNAL_tcf_color_blue}${1}${__INTERNAL_tcf_color_reset}"
;;
*)
a=$1
esac
echo -n "$a"
}; # end of __INTERNAL_tcf_colorize }}}
# __INTERNAL_tcf_colors_setup ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_colors_setup(){
T="$TERM"
[[ -t 1 ]] || T=""
[[ -t 2 ]] || T=""
[[ "$1" == "--force" ]] && T="xterm"
case $T in
xterm|screen)
__INTERNAL_tcf_color_black="\e[0;30m"
__INTERNAL_tcf_color_dark_gray="\e[1;30m"
__INTERNAL_tcf_color_blue="\e[0;34m"
__INTERNAL_tcf_color_light_blue="\e[1;34m"
__INTERNAL_tcf_color_green="\e[0;32m"
__INTERNAL_tcf_color_light_green="\e[1;32m"
__INTERNAL_tcf_color_cyan="\e[0;36m"
__INTERNAL_tcf_color_light_cyan="\e[1;36m"
__INTERNAL_tcf_color_red="\e[0;31m"
__INTERNAL_tcf_color_light_red="\e[1;31m"
__INTERNAL_tcf_color_purple="\e[0;35m"
__INTERNAL_tcf_color_light_purple="\e[1;35m"
__INTERNAL_tcf_color_brown="\e[0;33m"
__INTERNAL_tcf_color_yellow="\e[1;33m"
__INTERNAL_tcf_color_light_gray="\e[0;37m"
__INTERNAL_tcf_color_white="\e[1;37m"
__INTERNAL_tcf_color_reset="\e[00m"
;;
* )
__INTERNAL_tcf_color_black=""
__INTERNAL_tcf_color_dark_gray=""
__INTERNAL_tcf_color_blue=""
__INTERNAL_tcf_color_light_blue=""
__INTERNAL_tcf_color_green=""
__INTERNAL_tcf_color_light_green=""
__INTERNAL_tcf_color_cyan=""
__INTERNAL_tcf_color_light_cyan=""
__INTERNAL_tcf_color_red=""
__INTERNAL_tcf_color_light_red=""
__INTERNAL_tcf_color_purple=""
__INTERNAL_tcf_color_light_purple=""
__INTERNAL_tcf_color_brown=""
__INTERNAL_tcf_color_yellow=""
__INTERNAL_tcf_color_light_gray=""
__INTERNAL_tcf_color_white=""
__INTERNAL_tcf_color_reset=""
;;
esac
}; # end of __INTERNAL_tcf_colors_setup
__INTERNAL_tcf_colors_setup; # }}}
# __INTERNAL_tcf_copy_function ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_copy_function() {
declare -F $1 > /dev/null || return 1
eval "$(echo -n "${2}() "; declare -f ${1} | tail -n +2)"
}; # end of __INTERNAL_tcf_copy_function }}}
# __INTERNAL_tcf_addE2R ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_addE2R() {
__INTERNAL_tcf_copy_function $1 TCF_orig_$1
eval "${1}() { TCF_orig_${1} \"\$@\"; tcfE2R; }"
}; # end of __INTERNAL_tcf_addE2R }}}
# __INTERNAL_tcf_insertE2R ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_insertE2R() {
__INTERNAL_tcf_copy_function $1 TCF_orig_$1
eval "$(echo -n "${1}() "; declare -f ${1} | tail -n +2 | sed -e 's/\(.*__INTERNAL_ConditionalAssert.*\)/\1\ntcfE2R;/')"
}; # end of __INTERNAL_tcf_insertE2R }}}
# __INTERNAL_tcf_get_current_level ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_get_current_level() {
local l=$__INTERNAL_tcf_current_level_val
if [[ $1 ]]; then
l=$(($l+$1))
fi
local i
for i in $(seq 1 $(($l*2)) ); do echo -n " "; done
return $l
}; # end of __INTERNAL_tcf_get_current_level }}}
# __INTERNAL_tcf_incr_current_level ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_incr_current_level() {
let __INTERNAL_tcf_current_level_val++
__INTERNAL_Log_prefix=$(__INTERNAL_tcf_get_current_level)
}; # end of __INTERNAL_tcf_incr_current_level }}}
# __INTERNAL_tcf_decr_current_level ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_decr_current_level() {
let __INTERNAL_tcf_current_level_val--
__INTERNAL_Log_prefix=$(__INTERNAL_tcf_get_current_level)
}; # end of __INTERNAL_tcf_decr_current_level }}}
# __INTERNAL_tcf_do_hack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_do_hack() {
LogDebug "TCF_NOHACK='$TCF_NOHACK'"
if [[ -z "$TCF_NOHACK" ]]; then
tcfChk "Apply TCF beakerlib hacks" && {
rlLog " injecting tcf hacks into the beakerlib functions"
echo -n "patching rlLog"
local rlL=$(declare -f rlLog | sed -e 's|\] ::|\0${__INTERNAL_Log_prefix}|;s|$3 $1"|${3:+"$3 "}$1"|')
eval "$rlL"
echo -n ", rljAddTest"
__INTERNAL_tcf_copy_function rljAddTest __INTERNAL_tcf_orig_rljAddTest
true; rljAddTest() {
local a="${__INTERNAL_Log_prefix}$1"; shift
[[ "$1" != "FAIL" ]]; tcfE2R
__INTERNAL_tcf_journal=("${__INTERNAL_tcf_journal[@]}" "$1" "$a")
__INTERNAL_tcf_orig_rljAddTest "$a" "$@"
}
echo -n ", rljAddMessage"
__INTERNAL_tcf_copy_function rljAddMessage __INTERNAL_tcf_orig_rljAddMessage
true; rljAddMessage() {
local a="${__INTERNAL_Log_prefix}$1"; shift
__INTERNAL_tcf_journal=("${__INTERNAL_tcf_journal[@]}" "$1" "$a")
__INTERNAL_tcf_orig_rljAddMessage "$a" "$@"
}
echo -n ", __INTERNAL_LogAndJournalFail"
__INTERNAL_tcf_copy_function __INTERNAL_LogAndJournalFail __INTERNAL_tcf_orig___INTERNAL_LogAndJournalFail
true; __INTERNAL_LogAndJournalFail() {
tcfNOK
__INTERNAL_tcf_orig___INTERNAL_LogAndJournalFail "$@"
}
echo "."
tcfFin --no-assert --ignore; }
else
Log "skip hacking beakerlib functions"
fi
}; # end of __INTERNAL_tcf_do_hack }}}
# __INTERNAL_tcf_kill_old_plugin ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_kill_old_plugin() {
tcfChk "Get rid of the old TCF implementation. removing" && {
local comma='' i
for i in Try Chk Fin E2R RES OK NOK NEG TCFcheckFinal TCFreport; do
echo -n "${comma}rl$i"
unset -f rl$i
comma=', '
done
echo '.'
tcfFin --no-assert; }
}; # end of __INTERNAL_tcf_kill_old_plugin }}}
: <<'=cut'
=pod
=head2 Block functions
=cut
# __INTERNAL_tcf_parse_params ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_parse_params() {
local GETOPT=$(getopt -q -o if: -l ignore,no-assert,fail-tag: -- "$@")
eval set -- "$GETOPT"
echo "local ignore noass title fail_tag"
echo "[ -z \"\$ignore\" ] && ignore=0"
echo "[ -z \"\$noass\" ] && noass=0"
echo "[ -z \"\$fail_tag\" ] && fail_tag='FAIL'"
while [[ -n "$@" ]]; do
case $1 in
--)
shift; break
;;
--ignore|-i)
echo "ignore=1"
echo "noass=1"
;;
--no-assert|-n)
echo "noass=1"
;;
--fail-tag|-f)
shift
echo "fail_tag='$1'"
;;
*)
echo "unknown option $1"
return 1
;;
esac
shift;
done
[[ -n "$1" ]] && echo "title=\"${1}\""
echo "eval set -- \"$(echo "$GETOPT" | sed -e 's/.*-- //')\""
}; # end of __INTERNAL_tcf_parse_params }}}
# tcfTry ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 tcfTry
Starting function of block which will be skipped if an error has been detected
by tcfFin function occurent before.
tcfTry ["title"] [-i|--ignore] [--no-assert] [--fail-tag TAG] && {
<some code>
tcfFin; }
If title is omitted than noting is printed out so no error will be reported (no
Assert is executed) thus at least the very top level tcfTry should have title.
tcfTry and tcfChk blocks are stackable so you can organize them into a hierarchy
structure.
Note that tcfFin has to be used otherwise the overall result will not be
accurate.
=over
=item title
Text which will be displayed and logged at the beginning and the end (in tcfFin
function) of the block.
=item -i, --ignore
Do not propagate the actual result to the higher level result.
=item -n, --no-assert
Do not log error into the journal.
=item -f, --fail-tag TAG
If the result of the block is FAIL, use TAG instead ie. INFO or WARNING.
=back
Returns 1 if and error occured before, otherwise returns 0.
=cut
tcfTry() {
LogMoreLow -f "begin '$*'"
local vars=$(__INTERNAL_tcf_parse_params "$@") || { Log "$vars" FAIL; return 1; }
LogMoreMed -f "vars:\n$vars"
LogMoreLow -f "evaluating options start"
eval "$vars"
LogMoreLow -f "evaluating options end"
local incr=
local pp="SKIPPING"
tcfRES; # to set __INTERNAL_tcf_result
LogMoreLow -f "result was $__INTERNAL_tcf_result"
if [[ $__INTERNAL_tcf_result -eq 0 ]]; then
__INTERNAL_tcf_current_level_data=("$__INTERNAL_tcf_result" "$vars" "${__INTERNAL_tcf_current_level_data[@]}")
pp="BEGIN"
incr=1
fi
if [[ -n "$title" ]]; then
Log "$title" "$pp"
[[ -n "$incr" ]] && {
LogMoreLow -f "increment indentation level"
__INTERNAL_tcf_incr_current_level
}
fi
LogMoreLow -f "end"
return $__INTERNAL_tcf_result
}; # end of tcfTry }}}
# tcfChk ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 tcfChk
Starting function of block which will be always executed.
tcfChk ["title"] [-i|--ignore] [--no-assert] [--fail-tag TAG] && {
<some code>
tcfFin; }
If title is omitted than noting is printed out so no error will be reported (no
Assert is executed) thus at least the very top level tcfChk should have title.
tcfTry and tcfChk blocks are stackable so you can organize them into a hierarchy
structure.
Note that tcfFin has to be used otherwise the overall result will not be
accurate.
For details about arguments see tcfTry.
Returns 0.
=cut
tcfChk() {
LogMoreLow -f "begin '$*'"
tcfRES; # to set __INTERNAL_tcf_result
local res=$__INTERNAL_tcf_result
tcfRES 0
tcfTry "$@"
__INTERNAL_tcf_current_level_data[0]=$res
LogMoreLow -f "end"
return $__INTERNAL_tcf_result
}; # end of tcfChk }}}
# tcfFin ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 tcfFin
Ending function of block. It does some evaluation of previous local and global
results and puts it into the global result.
tcfTry ["title"] && {
<some code>
tcfFin [-i|--ignore] [--no-assert] [--fail-tag TAG]; }
Local result is actualy exit code of the last command int the body.
Global result is an internal varibale hodning previous local results.
Respectively last error or 0.
For details about arguments see tcfTry.
Returns local result of the preceeding block.
=cut
tcfFin() {
local RES=$?
LogMoreLow -f "begin '$*'"
LogMoreMed -f "previous exit code was '$RES'"
local vars=$(__INTERNAL_tcf_parse_params "$@") || { Log "$vars" FAIL; return 1; }
LogMoreMed -f "vars:\n$vars"
LogMoreLow -f "evaluating options start"
eval "$vars"
LogMoreLow -f "evaluating options end"
tcfRES; # to set __INTERNAL_tcf_result
[[ $RES -ne 0 ]] && tcfRES $RES
RES=$__INTERNAL_tcf_result
LogMoreMed -f "overall result is '$RES'"
LogMoreMed -f "data:\n${__INTERNAL_tcf_current_level_data[1]}"
LogMoreLow -f "evaluating data start"
eval "${__INTERNAL_tcf_current_level_data[1]}"
LogMoreLow -f "evaluating data end"
if [[ -n "$title" ]]; then
__INTERNAL_tcf_decr_current_level
if [[ $ignore -eq 1 ]]; then
RES=0
[[ $__INTERNAL_tcf_result -ne 0 ]] && title="$title - ignored"
fi
if [[ $noass -eq 0 ]]; then
tcfAssert0 "$title" $__INTERNAL_tcf_result "$fail_tag"
else
if [[ $__INTERNAL_tcf_result -eq 0 ]]; then
local pp="PASS"
LogInfo "$title - $pp"
else
local pp="${fail_tag:-FAIL}"
LogWarn "$title - $pp"
fi
fi
fi
if [[ $__INTERNAL_tcf_result -eq 0 || $ignore -eq 1 ]]; then
tcfRES ${__INTERNAL_tcf_current_level_data[0]}
fi
local i
for i in 0 1; do unset __INTERNAL_tcf_current_level_data[$i]; done
__INTERNAL_tcf_current_level_data=("${__INTERNAL_tcf_current_level_data[@]}")
LogMoreLow -f "end"
return $RES
}; # end of tcfFin }}}
: <<'=cut'
=pod
=head2 Functions for manipulation with the results
=cut
# tcfRES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 tcfRES
Sets and return the global result.
tcfRES [-p|--print] [number]
=over
=item -p --print
Also print the result value.
=item number
If present the global result is set to this value.
=back
Returns global result.
=cut
tcfRES() {
local p=0
while [[ -n "$1" ]]; do
case $1 in
--print|-p)
p=1
;;
*)
break
;;
esac
shift
done
if [[ -n "$1" ]]; then
__INTERNAL_tcf_result=$1
echo -n "$__INTERNAL_tcf_result" > "$__INTERNAL_tcf_result_file"
else
__INTERNAL_tcf_result="$(cat "$__INTERNAL_tcf_result_file")"
fi
[[ $p -eq 1 ]] && echo $__INTERNAL_tcf_result
return $__INTERNAL_tcf_result
}; # end of tcfRES }}}
# tcfOK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 tcfOK
Sets the global result to 0.
tcfOK
Returns global result.
=cut
tcfOK() {
tcfRES 0
}; # end of tcfOK }}}
# tcfNOK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 tcfNOK
Sets the global result to 1 or given number.
tcfNOK [number]
=over
=item number
If present the global result is set to this value.
=back
Returns global result.
=cut
tcfNOK() {
if [[ -n "$1" ]]; then
[[ $1 -eq 0 ]] && echo "You have requested result '0'. You should use tcfOK instead."
tcfRES $1
else
tcfRES 1
fi
}; # end of tcfNOK }}}
# tcfE2R ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 tcfE2R
Converts exit code of previous command to local result if the exit code is not 0
(zero).
<some command>
tcfE2R [number]
=over
=item number
If present use it instead of exit code.
=back
Returns original exit code or given number.
=cut
tcfE2R() {
local res=$?
[[ -n "$1" ]] && res=$1
[[ $res -ne 0 ]] && tcfRES $res
return $res
}; # end of tcfE2R }}}
: <<'=cut'
=pod
=head2 Functions for manipulation with the exit codes
=cut
# tcfNEG ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 tcfNEG
Negates exit code of previous command.
<some command>
tcfNEG
Returns 1 if original exit code was 0, otherwise returns 0.
=cut
tcfNEG() {
[[ $? -eq 0 ]] && return 1 || return 0
}; # end of tcfNEG }}}
# tcfRun ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 tcfRun
Simmilar to rlRun but it also annouces the beginnign of the command.
tcfRun [--fail-tag|-f TAG] command [exp_result [title]]
Moreover if 'command not found' appears on STDERR it should produce WARNING.
=over
=item command
Command to execute.
=item exp_result
Specification of expect resutl.
It can be a list of values or intervals or * for any result. Also negation (!) can be used.
Example:
<=2,7,10-12,>252,!254 means following values 0,1,2,7,10,11,12,253,255
=item title
Text which will be displayed and logged at the beginning and the end of command execution.
=item --fail-tag | -f
If the command fails use TAG instead of FAIL.
=back
Returns exit code of the executed command.
=cut
tcfRun() {
LogMore_ -f "begin $*"
optsBegin
optsAdd 'fail-tag|f' --mandatory
optsAdd 'timeout' --optional 'timeout="${1:-10}"'
optsAdd 'kill-timeout|kt' --mandatory --default 5
optsAdd 'signal' --mandatory --default TERM
optsAdd 'check-code' --mandatory --default 'kill -0 $cmdpid >&/dev/null'
optsAdd 'kill-code' --mandatory --default '/bin/kill -$signal -- $cmdpid'
optsAdd 'allow-skip|as' --flag
optsAdd 'no-assert|n' --flag
optsDone; eval "${optsCode}"
LogMore_ -f "after opts $*"
[[ -z "$allowskip" ]] && tcfChk
local orig_expecode="${2:-0}"
local expecode="$orig_expecode"
[[ "$expecode" == "*" ]] && expecode="0-255"
local command="$1"
local comment="Running command '$command'"
[[ -n "$3" ]] && comment="$3"
[[ -n "$expecode" ]] && {
expecode=$(echo "$expecode" | tr ',-' '\n ' | sed -e 's/^!=/!/;s/^=//;s/^<=\(.\+\)$/0 \1/;s/^>=\(.\+\)$/\1 255/;s/^<\(.\+\)$/0 \$(( \1 - 1 ))/;s/^>\(.\+\)$/\$(( \1 + 1 )) 255/' | while read line; do [[ "$line" =~ ^[^\ ]+$ ]] && echo "$line" || eval seq $line; done; )
tcfE2R
LogMoreLow -f "orig_expecode='$orig_expecode'"
LogMoreLow -f "expecode='$expecode'"
}
tcfTry ${noassert:+--no-assert} "$comment" && {
local errout=$(mktemp)
LogMoreLow -f "executing '$command'"
if [[ "$optsPresent" =~ $(echo "\<timeout\>") ]]; then
LogDebug -f "using watchdog feature"
local ec="$(mktemp)"
eval "$command; echo $? > $ec 2> >(tee $errout)" &
local cmdpid=$!
local time_start=$(date +%s)
local timeout_t=$(( $time_start + $timeout ))
while true; do
if ! eval "$checkcode"; then
Log "command finished in $(($(date +%s) - $time_start )) seconds"
local res="$(cat $ec)"
break
elif [[ $(date +%s) -ge $timeout_t ]]; then
echo
Log "command is still running, sending $signal signal"
eval "$killcode"
tcfNOK 255
echo 255 > $ec
let timeout_t+=killtimeout
signal=KILL
fi
sleep 0.1
done
rm -f $ec
else
eval "$command" 2> >(tee $errout)
local res=$?
fi
LogMoreLow -f "got '$res'"
local resmatch=$(echo "$expecode" | grep "^\!\?${res}$")
LogMoreLow -f "resmatch='$resmatch'"
[[ -n "$resmatch" && ! "$resmatch" =~ '!' ]]
if tcfE2R; then
! grep -iq "command not found" $errout || { failtag='WARNING'; tcfNOK; }
else
Log "Expected result was '$orig_expecode', got '$res'!"
fi
tcfFin ${failtag:+--fail-tag "$failtag"}; }
rm -f $errout
[[ -z "$allowskip" ]] && tcfFin
LogMore_ -f "end $*"
return $res
}; # end of tcfRun }}}
: <<'=cut'
=pod
=head2 Functions for logging
=cut
# tcfAssert0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
tcfAssert0() {
LogMoreLow -f "begin '$*'"
local RES="${3:-FAIL}"
[[ $2 -eq 0 ]] && RES='PASS'
Log "$1" $RES
LogMoreLow -f "end"
}; # end of tcfAssert0 }}}
# tcfCheckFinal ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 tcfCheckFinal
Check that all tcfTry / tcfChk functions have been close by tcfFin.
tcfCheckFinal
=cut
tcfCheckFinal() {
tcfAssert0 "Check that TCF block cache is empty" ${#__INTERNAL_tcf_current_level_data[@]}
tcfAssert0 "Check that TCF current level is 0" $__INTERNAL_tcf_current_level_val
}; # end of tcfCheckFinal }}}
echo "done."
: <<'=cut'
=pod
=head2 Self check functions
=cut
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# tcfSelfCheck {{{
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
: <<'=cut'
=pod
=head3 tcfSelfCheck
Does some basic functionality tests.
tcfSelfCheck
The function is called also by the following command:
./lib.sh selfcheck
=cut
tcfSelfCheck() {
tcfChk "check 1" &&{
tcfTry "try 1.1 - true" &&{
true
tcfFin;}
tcfTry "try 1.2 - false" &&{
false
tcfFin;}
tcfTry "try 1.3 - true" &&{
true
tcfFin;}
tcfFin;}
tcfChk "check 2" &&{
tcfTry "try 2.1 - true" &&{
true
tcfFin;}
tcfTry "try 2.2 - true - ignore" &&{
true
tcfFin -i;}
tcfTry "try 2.3 - true" &&{
true
tcfFin;}
tcfFin;}
tcfChk "check 3" &&{
tcfTry "try 3.1 - true" &&{
true
tcfFin;}
tcfTry "try 3.2 - false - ignore" &&{
false
tcfFin -i;}
tcfTry "try 3.3 - true" &&{
true
tcfFin;}
tcfFin;}
tcfCheckFinal
tcfAssert0 "Overall result" $(tcfRES -p)
LogReport
}
if [[ "$1" == "selfcheck" ]]; then
tcfSelfCheck
fi; # end of tcfSelfCheck }}}
# tcfLibraryLoaded ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
tcfLibraryLoaded() {
rlImport distribution/Log
declare -F rlDie > /dev/null && {
#rlJournalStart
#rlPhaseStartSetup "TCF"
echo -e "\nrunning inside the beakerlib - using rlAssert0"
true; tcfAssert0() {
local text="$1"
[[ "$3" != "FAIL" && "$3" != "PASS" ]] && text="$text - $3"
__INTERNAL_ConditionalAssert "$text" "$2"
}
__INTERNAL_tcf_do_hack
#rlPhaseEnd
#rlJournalEnd
};
if declare -F rlE2R >& /dev/null; then
__INTERNAL_tcf_kill_old_plugin
fi
true
}; # end of tcfLibraryLoaded }}}
: <<'=cut'
=pod
=head1 AUTHORS
=over
=item *
Dalibor Pospisil <dapospis@redhat.com>
=back
=cut

View File

@ -0,0 +1,60 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Makefile of /distribution/Library/testUser
# Description: Block style coding with ability of skipping parts.
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export TEST=/distribution/Library/testUser
export TESTVERSION=1.0
BUILT_FILES=
FILES=$(METADATA) lib.sh Makefile
.PHONY: all install download clean
run: $(FILES) build
./runtest.sh
build: $(BUILT_FILES)
test -x runtest.sh || chmod a+x runtest.sh
clean:
rm -f *~ $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@echo "Owner: Dalibor Pospisil <dapospis@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "Description: Setup/cleanup standard testing user." >> $(METADATA)
@echo "Type: Library" >> $(METADATA)
@echo "TestTime: 5m" >> $(METADATA)
@echo "RhtsRequires: library(distribution/Log)" >> $(METADATA)
@echo "Provides: library(distribution/testUser)" >> $(METADATA)
@echo "License: GPLv2" >> $(METADATA)
rhts-lint $(METADATA)

View File

@ -0,0 +1,234 @@
#!/bin/bash
# try-check-final.sh
# Authors: Dalibor Pospíšil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# library-prefix = testUser
# library-version = 7
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
: <<'=cut'
=pod
=head1 NAME
BeakerLib library testUser
=head1 DESCRIPTION
This library provide s function for maintaining testing users.
=head1 USAGE
To use this functionality you need to import library distribution/testUser and add
following line to Makefile.
@echo "RhtsRequires: library(distribution/testUser)" >> $(METADATA)
=head1 VARIABLES
=over
=item testUser
Array of testing user login names.
=item testUserPasswd
Array of testing users passwords.
=item testUserUID
Array of testing users UIDs.
=item testUserGID
Array of testing users primary GIDs.
=item testUserGroup
Array of testing users primary group names.
=item testUserGIDs
Array of space separated testing users all GIDs.
=item testUserGroups
Array of space separated testing users all group names.
=item testUserGecos
Array of testing users gecos fields.
=item testUserHomeDir
Array of testing users home directories.
=item testUserShell
Array of testing users default shells.
=back
=head1 FUNCTIONS
=cut
echo -n "loading library testUser... "
: <<'=cut'
=pod
=head3 testUserSetup, testUserCleanup
Creates/removes testing user(s).
rlPhaseStartSetup
testUserSetup [NUM]
rlPhaseEnd
rlPhaseStartCleanup
testUserCleanup
rlPhaseEnd
=over
=item NUM
Optional number of user to be created. If not specified one user is created.
=back
Returns 0 if success.
=cut
testUserSetup() {
# parameter dictates how many users should be created, defaults to 1
local res=0
local count_created=0
local count_wanted=${1:-"1"}
local index=0
(( $count_wanted < 1 )) && return 1
while (( $count_created != $count_wanted ));do
let index++
local newUser="testuser${index}"
local newUserPasswd="redhat"
id "$newUser" &> /dev/null && continue # if user with the name exists, try again
# create
useradd -m $newUser >&2 || ((res++))
echo "$newUserPasswd" | passwd --stdin $newUser || ((res++))
# save the users array
testUser+=($newUser)
testUserPasswd+=($newUserPasswd)
set | grep "^testUser=" > $__INTERNAL_testUser_users_file
set | grep "^testUserPasswd=" >> $__INTERNAL_testUser_users_file
((count_created++))
done
__INTERNAL_testUserRefillInfo || ((res++))
echo ${res}
[[ $res -eq 0 ]]
}
__INTERNAL_testUserRefillInfo() {
local res=0
local user
testUserUID=()
testUserGID=()
testUserGroup=()
testUserGIDs=()
testUserGroups=()
testUserGecos=()
testUserHomeDir=()
testUserShell=()
for user in ${testUser[@]}; do
local ent_passwd=$(getent passwd ${user}) || ((res++))
local users_id="$(id ${user})" || ((res++))
# testUser is filled during user creation - already present
# testUserPasswd is saved same way as testUser - already present
testUserUID+=("$(echo "$ent_passwd" | cut -d ':' -f 3)")
testUserGID+=("$(echo "$ent_passwd" | cut -d ':' -f 4)")
testUserGroup+=("$(echo "$users_id" | sed -r 's/.*gid=(\S+).*/\1/;s/[[:digit:]]+\(//g;s/\)//g;s/,/ /g')")
testUserGIDs+=("$(echo "$users_id" | sed -r 's/.*groups=(\S+).*/\1/;s/\([^\)]+\)//g;s/\)//g;s/,/ /g')")
testUserGroups+=("$(echo "$users_id" | sed -r 's/.*groups=(\S+).*/\1/;s/[[:digit:]]+\(//g;s/\)//g;s/,/ /g')")
testUserGecos+=("$(echo "$ent_passwd" | cut -d ':' -f 5)")
testUserHomeDir+=("$(echo "$ent_passwd" | cut -d ':' -f 6)")
testUserShell+=("$(echo "$ent_passwd" | cut -d ':' -f 7)")
done
echo ${res}
[[ $res -eq 0 ]]
}
testUserCleanup() {
local res=0
for user in ${testUser[@]}; do
userdel -rf "$user" >&2 || ((res++))
done
unset testUser
__INTERNAL_testUserRefillInfo
rm -f $__INTERNAL_testUser_users_file >&2 || ((res++))
echo ${res}
[[ $res -eq 0 ]]
}
# testUserLibraryLoaded ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
testUserLibraryLoaded() {
local res=0
# necessary init steps
__INTERNAL_testUser_users_file="$BEAKERLIB_DIR/users"
# try to fill in users array with previous data
[[ -f ${__INTERNAL_testUser_users_file} ]] && . ${__INTERNAL_testUser_users_file} >&2
__INTERNAL_testUserRefillInfo >&2 || ((res++))
[[ $res -eq 0 ]]
}; # end of testUserLibraryLoaded }}}
: <<'=cut'
=pod
=head1 AUTHORS
=over
=item *
Dalibor Pospisil <dapospis@redhat.com>
=back
=cut
echo "done."

163
tests/run-as/runtest.sh Executable file
View File

@ -0,0 +1,163 @@
#!/bin/bash
# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# runtest.sh of /CoreOS/sudo/Sanity/run-as
# Description: Test feature 'run as'. This means -u, -g options.
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2017 Red Hat, Inc.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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-1151, USA.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Include Beaker environment
. /usr/bin/rhts-environment.sh || exit 1
. /usr/share/beakerlib/beakerlib.sh || exit 1
PACKAGE="sudo"
rlJournalStart && {
rlPhaseStartSetup && {
[[ -z "$BEAKERLIB_LIBRARY_PATH" ]] && BEAKERLIB_LIBRARY_PATH="`dirname "$(readlink -f "$0")"`"
rlRun "rlImport --all" 0 "Import libraries" || rlDie "cannot continue"
tcfRun "rlCheckMakefileRequires"
rlRun "TmpDir=\$(mktemp -d)" 0 "Creating tmp directory"
CleanupRegister "rlRun 'rm -r $TmpDir' 0 'Removing tmp directory'"
CleanupRegister 'rlRun "popd"'
rlRun "pushd $TmpDir"
CleanupRegister 'tcfRun "testUserCleanup"'
tcfRun "testUserSetup 5"
CleanupRegister 'rlRun "rlFileRestore"'
rlRun "rlFileBackup --clean /etc/sudoers.d"
cat > /etc/sudoers.d/testing << EOF
Defaults !requiretty
$testUser ALL = (ALL:ALL) NOPASSWD: ALL
${testUser[1]} ALL = ( ${testUser[0]} ) NOPASSWD: ALL
${testUser[2]} ALL = ( ${testUser[0]}, ${testUser[1]} ) NOPASSWD: ALL
${testUser[3]} ALL = ( : ${testUserGroup[1]}, ${testUser[0]} ) NOPASSWD: ALL
${testUser[4]} ALL = ( ${testUser[0]} : ${testUserGroup[2]} ) NOPASSWD: ALL
EOF
rlRun "cat /etc/sudoers.d/testing"
rlPhaseEnd; }
CMD='bash -c "ps -o user:15,group:15,ruser:15,rgroup:15,args --ppid $$"'
tcfTry "Tests" --no-assert && {
test() {
local who="$1" as="$2" as_grp="$3" exp_res="$4"
if [[ -z "$exp_res" || "$exp_res" == "0" ]]; then
rlRun -s "su -l $who -c 'sudo ${as:+-u $as} ${as_grp:+-g $as_grp} $CMD'"
[[ -n "$as_grp" && -z "$as" ]] && as="$who"
as="${as:-root}"
as_grp="${as_grp:-$as}"
rlAssertGrep "$as\s+$as_grp\s+$as\s+$as_grp\s+" $rlRun_LOG -Eq
rm -f $rlRun_LOG
else
rlRun -s "su -l $who -c 'sudo ${as:+-u $as} ${as_grp:+-g $as_grp} $CMD'" 1
[[ -n "$as_grp" && -z "$as" ]] && as="$who"
as="${as:-root}"
as_grp="${as_grp:-$as}"
rlAssertNotGrep "$as\s+$as_grp\s+$as\s+$as_grp\s+" $rlRun_LOG -Eq
rm -f $rlRun_LOG
fi
}
rlPhaseStartTest "run as a default user" && {
tcfChk "Test phase" && {
tcfChk "$testUser can run as all" && {
test $testUser "" "" "" 0
tcfFin; }
tcfChk "${testUser[1]} cannot run as anyone" && {
test ${testUser[1]} "" "" 1
tcfFin; }
tcfChk "${testUser[2]} cannot run as anyone" && {
test ${testUser[2]} "" "" 1
tcfFin; }
tcfFin; }
rlPhaseEnd; }
rlPhaseStartTest "run as a user (-u)" && {
tcfChk "Test phase" && {
tcfChk "$testUser can run as all" && {
test $testUser "root" "" 0
test $testUser "${testUser[1]}" "" 0
test $testUser "${testUser[2]}" "" 0
tcfFin; }
tcfChk "${testUser[1]} can run as $testUser" && {
test ${testUser[1]} "root" "" 1
test ${testUser[1]} "${testUser[0]}" "" 0
test ${testUser[1]} "${testUser[2]}" "" 1
tcfFin; }
tcfChk "${testUser[2]} can run as $testUser and ${testUser[1]}" && {
test ${testUser[2]} "root" "" 1
test ${testUser[2]} "${testUser[0]}" "" 0
test ${testUser[2]} "${testUser[1]}" "" 0
tcfFin; }
tcfFin; }
rlPhaseEnd; }
rlPhaseStartTest "run as a group (-g)" && {
tcfChk "Test phase" && {
tcfChk "$testUser can run as all" && {
test $testUser "" "root" 0
test $testUser "" "${testUserGroup[1]}" 0
test $testUser "" "${testUserGroup[2]}" 0
tcfFin; }
tcfChk "${testUser[4]} can run as ${testUserGroup[2]}" && {
test ${testUser[4]} "" "root" 1
test ${testUser[4]} "" "${testUserGroup[0]}" 1
test ${testUser[4]} "" "${testUserGroup[2]}" 0
tcfFin; }
#tcfChk "${testUser[2]} can run as ${testUserGroup[1]}" && {
# test ${testUser[2]} "" "root" 1
# test ${testUser[2]} "" "${testUserGroup[1]}" 1
# test ${testUser[2]} "" "${testUserGroup[2]}" 1
#tcfFin; }
#tcfChk "${testUser[3]}" && {
# test ${testUser[2]} "" "root" 1
# test ${testUser[2]} "" "${testUserGroup[1]}" 0
# test ${testUser[2]} "" "${testUserGroup[2]}" 0
#tcfFin; }
tcfFin; }
rlPhaseEnd; }
rlPhaseStartTest "run as both user (-u) and group (-g)" && {
tcfChk "Test phase" && {
tcfChk "$testUser can run as all" && {
test $testUser "${testUser[1]}" "root" 0
test $testUser "${testUser[2]}" "${testUserGroup[1]}" 0
test $testUser "${testUser[1]}" "${testUserGroup[2]}" 0
tcfFin; }
tcfChk "${testUser[4]} can run as ${testUser[0]} ${testUserGroup[2]}" && {
test ${testUser[4]} "${testUser[0]}" "root" 1
test ${testUser[4]} "${testUser[0]}" "${testUserGroup[0]}" 0
#test ${testUser[4]} "${testUser[0]}" "${testUserGroup[4]}" 0
test ${testUser[4]} "${testUser[4]}" "${testUserGroup[4]}" 0
test ${testUser[4]} "${testUser[0]}" "${testUserGroup[3]}" 1
test ${testUser[4]} "${testUser[0]}" "${testUserGroup[2]}" 0
tcfFin; }
tcfFin; }
rlPhaseEnd; }
tcfFin; }
rlPhaseStartCleanup && {
CleanupDo
tcfCheckFinal
rlPhaseEnd; }
rlJournalPrintText
rlJournalEnd; }

View File

@ -0,0 +1,67 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Makefile of /CoreOS/sudo/Sanity/sudoers-options-sanity-test
# Description: This sanity test checks pre-defined (some are commented) options (examples) in sudoers file.
# Author: Ales Marecek <amarecek@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2013 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export TEST=/CoreOS/sudo/Sanity/sudoers-options-sanity-test
export TESTVERSION=1.0
BUILT_FILES=
FILES=$(METADATA) runtest.sh Makefile PURPOSE
.PHONY: all install download clean
run: $(FILES) build
./runtest.sh
build: $(BUILT_FILES)
test -x runtest.sh || chmod a+x runtest.sh
clean:
rm -f *~ $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@echo "Owner: Ales Marecek <amarecek@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "RhtsRequires: library(distribution/tcf)" >> $(METADATA)
@echo "RhtsRequires: library(distribution/Cleanup)" >> $(METADATA)
@echo "RhtsRequires: library(distribution/ConditionalPhases)" >> $(METADATA)
@echo "RhtsRequires: library(distribution/testUser)" >> $(METADATA)
@echo "Description: This sanity test checks pre-defined (some are commented) options (examples) in sudoers file." >> $(METADATA)
@echo "Type: Sanity" >> $(METADATA)
@echo "TestTime: 30m" >> $(METADATA)
@echo "RunFor: sudo" >> $(METADATA)
@echo "Requires: sudo grep coreutils" >> $(METADATA)
@echo "Priority: Normal" >> $(METADATA)
@echo "License: GPLv2" >> $(METADATA)
@echo "Confidential: no" >> $(METADATA)
@echo "Destructive: no" >> $(METADATA)
rhts-lint $(METADATA)

View File

@ -0,0 +1,3 @@
PURPOSE of /CoreOS/sudo/Sanity/sudoers-options-sanity-test
Description: This sanity test checks pre-defined (some are commented) options (examples) in sudoers file.
Author: Ales Marecek <amarecek@redhat.com>

View File

@ -0,0 +1,59 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Makefile of /distribution/Library/Cleanup
# Description: Block style coding with ability of skipping parts.
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export TEST=/distribution/Library/Cleanup
export TESTVERSION=1.0
BUILT_FILES=
FILES=$(METADATA) lib.sh Makefile
.PHONY: all install download clean
run: $(FILES) build
./runtest.sh
build: $(BUILT_FILES)
test -x runtest.sh || chmod a+x runtest.sh
clean:
rm -f *~ $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@echo "Owner: Dalibor Pospisil <dapospis@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "Description: Provides function to define cleanup stack which can do its work at any time of the test run." >> $(METADATA)
@echo "Type: Library" >> $(METADATA)
@echo "TestTime: 5m" >> $(METADATA)
@echo "Provides: library(distribution/Cleanup)" >> $(METADATA)
@echo "License: GPLv2" >> $(METADATA)
rhts-lint $(METADATA)

View File

@ -0,0 +1,314 @@
#!/bin/bash
# Authors: Dalibor Pospíšil <dapospis@redhat.com>
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# library-prefix = Cleanup
# library-version = 9
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__INTERNAL_Cleanup_LIB_VERSION=9
: <<'=cut'
=pod
=head1 NAME
BeakerLib library Cleanup
=head1 DESCRIPTION
This file contains functions which provides cleanup stack functionality.
=head1 USAGE
To use this functionality you need to import library distribution/Cleanup and add
following line to Makefile.
@echo "RhtsRequires: library(distribution/Cleanup)" >> $(METADATA)
B<Code example>
rlJournalStart
rlPhaseStartSetup
rlImport 'distribution/Cleanup'
tmp=$(mktemp)
CleanupRegister "
rlLog 'Removing data'
rlRun \"rm -f ${tmp}\"
"
rlLog 'Creating some data'
rlRun "echo 'asdfalkjh' > $tmp"
CleanupRegister "
rlLog 'just something to demonstrate unregistering'
"
ID1=$CleanupRegisterID
CleanupUnregister $ID1
CleanupRegister "
rlLog 'just something to demonstrate partial cleanup'
"
ID2=$CleanupRegisterID
CleanupRegister "rlLog 'cleanup some more things'"
# cleanup everything upto ID2
CleanupDo $ID2
CleanupRegister --mark "
rlLog 'yet another something to demonstrate partial cleanup using internal ID saving'
"
CleanupRegister "rlLog 'cleanup some more things'"
# cleanup everything upto last mark
CleanupDo --mark
rlPhaseEnd
rlPhaseStartCleanup
CleanupDo
rlPhaseEnd
rlJournalPrintText
rlJournalEnd
=head1 FUNCTIONS
=cut
echo -n "loading library Cleanup v$__INTERNAL_Cleanup_LIB_VERSION... "
__INTERNAL_Cleanup_stack_file="$BEAKERLIB_DIR/Cleanup_stack"
touch "$__INTERNAL_Cleanup_stack_file"
chmod ug+rw "$__INTERNAL_Cleanup_stack_file"
# CleanupRegister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
# CleanupRegister [--mark] CLEANUP_CODE
# --mark - also mark this position
CleanupRegister() {
local mark=0
[[ "$1" == "--mark" ]] && {
mark=1
shift
}
if ! CleanupGetStack; then
rlLogError "cannot continue, could not get cleanup stack"
return 1
fi
CleanupRegisterID="${RANDOM}$(date +"%s%N")"
echo -n "Registering cleanup ID=$CleanupRegisterID" >&2
if [[ $mark -eq 1 ]]; then
__INTERNAL_CleanupMark=( "$CleanupRegisterID" "${__INTERNAL_CleanupMark[@]}" )
echo -n " with mark" >&2
fi
echo " '$1'" >&2
rlLogDebug "prepending '$1'"
local ID_tag="# ID='$CleanupRegisterID'"
__INTERNAL_Cleanup_stack="$ID_tag
$1
$ID_tag
$__INTERNAL_Cleanup_stack"
if ! CleanupSetStack "$__INTERNAL_Cleanup_stack"; then
rlLogError "an error occured while registering the cleanup '$1'"
return 1
fi
return 0
}; # end of CleanupRegister }}}
# __INTERNAL_Cleanup_get_stack_part ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
# 1: ID
# -ID - everything upto the ID
# 2: '' - return ID only
# 'rest' - return exact oposit
__INTERNAL_Cleanup_get_stack_part() {
rlLogDebug "__INTERNAL_Cleanup_get_stack_part(): $* begin"
local ID="$1"
local n='1 0 1'
local stack=''
[[ "${ID:0:1}" == "-" ]] && {
ID="${ID:1}"
n='0 0 1'
}
[[ "$2" == "rest" ]] && {
n="$(echo "${n//0/2}")"
n="$(echo "${n//1/0}")"
n="$(echo "${n//2/1}")"
}
n=($n)
[[ -n "$DEBUG" ]] && rlLogDebug "$(set | grep ^n=)"
local ID_tag="# ID='$ID'"
while IFS= read -r line; do
[[ "$line" == "$ID_tag" ]] && {
n=( "${n[@]:1}" )
continue
}
if [[ $n -eq 0 ]]; then
stack="$stack
$line"
fi
done < <(echo "$__INTERNAL_Cleanup_stack")
rlLogDebug "__INTERNAL_Cleanup_get_stack_part(): cleanup stack part is '${stack:1}'"
echo "${stack:1}"
rlLogDebug "__INTERNAL_Cleanup_get_stack_part(): $* end"
}; # end of __INTERNAL_Cleanup_get_stack_part }}}
# CleanupUnregister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
CleanupUnregister() {
local ID="$1"
rlLog "Unregistering cleanup ID='$ID'"
if ! CleanupGetStack; then
rlLogError "cannot continue, could not get cleanup stack"
return 1
fi
rlLogDebug "removing ID='$ID'"
if ! CleanupSetStack "$(__INTERNAL_Cleanup_get_stack_part "$ID" 'rest')"; then
rlLogError "an error occured while registering the cleanup '$1'"
return 1
fi
return 0
}; # end of CleanupUnregister }}}
# CleanupMark ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_CleanupMark=()
CleanupMark() {
echo -n "Setting cleanup mark" >&2
CleanupRegister --mark '' 2>/dev/null
local res=$?
echo " ID='$CleanupRegisterID'" >&2
return $res
}; # end of CleanupMark }}}
# CleanupDo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
# 1: '' - cleanup all
# ID - cleanup ID only
# -ID - cleanup all upto ID, including
# mark - cleanup all unto last mark, including
CleanupDo() {
local ID="$1"
if ! CleanupGetStack; then
rlLogError "cannot continue, could not get cleanup stack"
return 1
fi
local res tmp newstack=''
tmp="$(mktemp)"
if [[ "$ID" == "mark" || "$ID" == "--mark" ]]; then
echo "execute cleanup upto mark='$__INTERNAL_CleanupMark'" >&2
__INTERNAL_Cleanup_get_stack_part "-$__INTERNAL_CleanupMark" | grep -v "^# ID='" > "$tmp"
newstack="$(__INTERNAL_Cleanup_get_stack_part "-$__INTERNAL_CleanupMark" 'rest')"
__INTERNAL_CleanupMark=("${__INTERNAL_CleanupMark[@]:1}")
elif [[ -n "$ID" ]]; then
echo "execute cleanup for ID='$ID'" >&2
__INTERNAL_Cleanup_get_stack_part "$ID" | grep -v "^# ID='" > "$tmp"
newstack="$(__INTERNAL_Cleanup_get_stack_part "$ID" 'rest')"
else
CleanupTrapUnhook
trap "echo 'temporarily blocking ctrl+c until cleanup is done' >&2" SIGINT
cat "$__INTERNAL_Cleanup_stack_file" | grep -v "^# ID='" > "$tmp"
echo "execute whole cleanup stack" >&2
fi
. "$tmp"
res=$?
[[ $res -ne 0 ]] && {
echo "cleanup code:" >&2
cat -n "$tmp" >&2
}
rm -f "$tmp"
echo "cleanup execution done" >&2
if [[ -z "$ID" ]]; then
trap - SIGINT
fi
if ! CleanupSetStack "$newstack"; then
rlLogError "an error occured while cleaning the stack"
return 1
fi
return $res
}; # end of CleanupDo }}}
# CleanupGetStack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
CleanupGetStack() {
rlLogDebug "getting cleanup stack"
if [[ -r "$__INTERNAL_Cleanup_stack_file" ]]; then
if __INTERNAL_Cleanup_stack="$(cat "$__INTERNAL_Cleanup_stack_file")"; then
rlLogDebug "cleanup stack is '$__INTERNAL_Cleanup_stack'"
return 0
fi
fi
rlLogError "could not load cleanup stack"
return 1
}; # end of CleanupGetStack }}}
# CleanupSetStack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
CleanupSetStack() {
rlLogDebug "setting cleanup stack to '$1'"
__INTERNAL_Cleanup_stack="$1"
if echo "$__INTERNAL_Cleanup_stack" > "$__INTERNAL_Cleanup_stack_file"; then
rlLogDebug "cleanup stack is now '$__INTERNAL_Cleanup_stack'"
return 0
fi
rlLogError "could not set cleanup stack"
return 1
}; # end of CleanupSetStack }}}
__INTERNAL_Cleanup_signals=''
__INTERNAL_Cleanup_trap_code='rlJournalStart; rlPhaseStartCleanup; CleanupDo; rlPhaseEnd; rlJournalPrintText; rlJournalEnd; exit'
# CleanupTrapHook ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
CleanupTrapHook() {
rlLog "register cleanup trap"
__INTERNAL_Cleanup_signals="${1:-"SIGHUP SIGINT SIGTERM EXIT"}"
eval "trap \"${__INTERNAL_Cleanup_trap_code}\" $__INTERNAL_Cleanup_signals"
}; # end of CleanupTrapHook }}}
# CleanupTrapUnhook ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
CleanupTrapUnhook() {
if [[ -n "$__INTERNAL_Cleanup_signals" ]]; then
rlLog "unregister cleanup trap"
eval trap - $__INTERNAL_Cleanup_signals
__INTERNAL_Cleanup_signals=''
fi
}; # end of CleanupTrapUnhook }}}
# CleanupLibraryLoaded ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
CleanupLibraryLoaded() {
CleanupTrapHook
}; # end of CleanupLibraryLoaded }}}
echo "done."
: <<'=cut'
=pod
=head1 AUTHORS
=over
=item *
Dalibor Pospisil <dapospis@redhat.com>
=back
=cut

View File

@ -0,0 +1,59 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Makefile of /distribution/Library/ConditionalPhases
# Description: Implements conditional phases.
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export TEST=/distribution/Library/ConditionalPhases
export TESTVERSION=1.0
BUILT_FILES=
FILES=$(METADATA) lib.sh Makefile
.PHONY: all install download clean
run: $(FILES) build
./runtest.sh
build: $(BUILT_FILES)
test -x runtest.sh || chmod a+x runtest.sh
clean:
rm -f *~ $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@echo "Owner: Dalibor Pospisil <dapospis@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "Description: Implements conditional phases." >> $(METADATA)
@echo "Type: Library" >> $(METADATA)
@echo "Provides: library(distribution/ConditionalPhases)" >> $(METADATA)
@echo "TestTime: 5m" >> $(METADATA)
@echo "License: GPLv2" >> $(METADATA)
rhts-lint $(METADATA)

View File

@ -0,0 +1,166 @@
#!/bin/bash
# Authors: Dalibor Pospíšil <dapospis@redhat.com>
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# library-prefix = ConditionalPhases
# library-version = 2
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__INTERNAL_ConditionalPhases_LIB_VERSION=2
__INTERNAL_ConditionalPhases_LIB_NAME='distribution/ConditionalPhases'
: <<'=cut'
=pod
=head1 NAME
BeakerLib library distribution/condpahses
=head1 DESCRIPTION
Implements conditional phases to eficiently select test phases to be execute
using white and black lists.
To use this functionality you need to import library
distribution/ConditionalPhases and add following line to Makefile.
@echo "RhtsRequires: library(distribution/ConditionalPhases)" >> $(METADATA)
=head1 USAGE
=head2 Conditional phases
Each test phase can be conditionally skipped based on a bash regular expression
given in CONDITIONAL_PHASES_BL and/or CONDITIONAL_PHASES_WL variables.
=over
=item CONDITIONAL_PHASES_BL
It is a black list. If match phase name the respective phase should be skipped.
=item CONDITIONAL_PHASES_WL
It is a white list. If does B<not> match phase name the respective phase should
be skipped excluding phases contatning 'setup' or 'cleanup' in its name. Names
'setup' and 'cleanup' are matched case insenitively.
=back
Actual skipping has to be done in the test case itself by using return code of
functions I<rlPhaseStart>, I<rlPhaseStartSetup>, I<rlPhaseStartTest>, and
I<rlPhaseStartCleanup>.
Example:
rlPhaseStartTest "phase name" && {
...
rlPhaseEnd; }
Evaluation of the phase relevancy works as follows:
1. If CONDITIONAL_PHASES_BL is non-empty and matches phase name => return 2.
2. If phase name contains word 'setup' or 'cleanup' or CONDITIONAL_PHASES_WL
is empty => return 0.
3. If CONDITIONAL_PHASES_WL is non-empty and matches phase name => return 0
otherwise return 1.
Normaly Setup and Cleanup phases are not skipped unless hey are B<explicitly>
black-listed.
To make the test work properly with conditional phases it is necessary to
surround phase code with curly brackets and make it conditionally executed
based on rlPhaseStart* function's exit code the same way as it is demostrated in
the example above. To make the process easy you can use following command:
sed 's/rlPhaseStart[^{]*$/& \&\& {/;s/rlPhaseEnd[^}]*$/&; }/'
This code can be embedded in Makefile by modifying build target to following
form:
build: $(BUILT_FILES)
grep -Eq 'rlPhase(Start[^{]*|End[^}]*)$' runtest.sh && sed -i 's/rlPhaseStart[^{]*$/& \&\& {/;s/rlPhaseEnd[^}]*$/&; }/' testrun.sh
test -x runtest.sh || chmod a+x runtest.sh
=cut
#'
echo -n "loading library $__INTERNAL_ConditionalPhases_LIB_NAME v$__INTERNAL_ConditionalPhases_LIB_VERSION... "
# ConditionalPhasesLibraryLoaded ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
ConditionalPhasesLibraryLoaded() {
if [[ -n "$CONDITIONAL_PHASES_BL" || -n "$CONDITIONAL_PHASES_WL" ]]; then
__INTERNAL_ConditionalPhases_eval() {
# check phases black-list
[[ -n "$CONDITIONAL_PHASES_BL" && "$1" =~ $CONDITIONAL_PHASES_BL ]] && {
rlLogWarning "phase '$1' should be skipped as it is defined in \$CONDITIONAL_PHASES_BL='$CONDITIONAL_PHASES_BL'"
return 2
}
# always execute Setup, Cleanup and if no PHASES (white-list) specified
[[ "$1" =~ $(echo "\<[Ss][Ee][Tt][Uu][Pp]\>") || "$1" =~ $(echo "\<[Cc][Ll][Ee][Aa][Nn][Uu][Pp]\>") ]] && {
rlLogInfo "phase '$1' will be executed as 'setup' and 'cleanup' phases are allowed by default, these can be black-listed"
return 0
}
[[ -z "$CONDITIONAL_PHASES_WL" ]] && {
rlLogInfo "phase '$1' will be executed as there is no rule for it"
return 0
}
[[ "$1" =~ $CONDITIONAL_PHASES_WL ]] && {
rlLogInfo "phase '$1' will be executed as it is defined in \$CONDITIONAL_PHASES_WL='$CONDITIONAL_PHASES_WL'"
return 0
} || {
rlLogWarning "phase '$1' should be skipped as it is not defined in \$CONDITIONAL_PHASES_WL='$CONDITIONAL_PHASES_WL'"
return 1
}
}
rlLogInfo "replacing rlPhaseStart by modified function with conditional phases implemented"
:; rlPhaseStart() {
if [ "x$1" = "xFAIL" -o "x$1" = "xWARN" ] ; then
__INTERNAL_ConditionalPhases_eval "$2" && \
rljAddPhase "$1" "$2"
return $?
else
rlLogError "rlPhaseStart: Unknown phase type: $1"
return 1
fi
}
else
rlLogInfo "Neither CONDITIONAL_PHASES_WL nor CONDITIONAL_PHASES_BL is defined, not applying modifications"
fi
}; # end of ConditionalPhasesLibraryLoaded }}}
: <<'=cut'
=pod
=head1 AUTHORS
=over
=item *
Dalibor Pospisil <dapospis@redhat.com>
=back
=cut
echo 'done.'

View File

@ -0,0 +1,48 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Makefile of /distribution/Library/Log
# Description: Block style coding with ability of skipping parts.
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export TEST=/distribution/Library/Log
export TESTVERSION=1.0
BUILT_FILES=
FILES=$(METADATA) lib.sh Makefile
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@echo "Owner: Dalibor Pospisil <dapospis@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "Description: Provides yet another logging facility that does not rely on beakerlib while it can integrate with it." >> $(METADATA)
@echo "Type: Library" >> $(METADATA)
@echo "TestTime: 5m" >> $(METADATA)
@echo "RhtsRequires: library(distribution/opts)" >> $(METADATA)
@echo "Provides: library(distribution/Log)" >> $(METADATA)
@echo "License: GPLv2" >> $(METADATA)
rhts-lint $(METADATA)

View File

@ -0,0 +1,637 @@
#!/bin/bash
# Authors: Dalibor Pospíšil <dapospis@redhat.com>
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2013 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# library-prefix = Log
# library-version = 11
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__INTERNAL_Log_LIB_VERSION=11
: <<'=cut'
=pod
=head1 NAME
BeakerLib library Log
=head1 DESCRIPTION
This library provide logging capability which does not rely on beakerlib so it
can be used standalone.
If it is used within beakerlib it automatically bypass all messages to the
beakerlib.
Also this library provide journaling feature so the summary can be printed out
at the end.
=head1 USAGE
To use this functionality you need to import library distribution/Log and add
following line to Makefile.
@echo "RhtsRequires: library(distribution/Log)" >> $(METADATA)
=head1 FUNCTIONS
=cut
echo -n "loading library Log v$__INTERNAL_Log_LIB_VERSION... "
__INTERNAL_Log_prefix=''
__INTERNAL_Log_prefix2=''
__INTERNAL_Log_postfix=''
__INTERNAL_Log_default_level=3
__INTERNAL_Log_level=$__INTERNAL_Log_default_level
LogSetDebugLevel() {
if [[ -n "$1" ]]; then
if [[ "$1" =~ ^[0-9]+$ ]]; then
let __INTERNAL_Log_level=$__INTERNAL_Log_default_level+$1;
else
__INTERNAL_Log_level=255
fi
else
__INTERNAL_Log_level=$__INTERNAL_Log_default_level
fi
}
LogSetDebugLevel "$DEBUG"
let __INTERNAL_Log_level_LOG=0
let __INTERNAL_Log_level_FATAL=0
let __INTERNAL_Log_level_ERROR=1
let __INTERNAL_Log_level_WARNING=2
let __INTERNAL_Log_level_INFO=3
let __INTERNAL_Log_level_DEBUG=4
let __INTERNAL_Log_level_MORE=5
let __INTERNAL_Log_level_MORE_=$__INTERNAL_Log_level_MORE+1
let __INTERNAL_Log_level_MORE__=$__INTERNAL_Log_level_MORE_+1
let __INTERNAL_Log_level_MORE___=$__INTERNAL_Log_level_MORE__+1
# Log ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
Log() {
LogMore___ -f "begin '$*'"
local pri=$2 message="${__INTERNAL_Log_prefix}${__INTERNAL_Log_prefix2}${1}${__INTERNAL_Log_postfix}"
if [[ -n "$pri" ]]; then
LogPrintMessage "$pri" "$message"
LogjAddMessage "$pri" "$message"
else
LogPrintMessage "$(date +%H:%M:%S)" "$message"
LogjAddMessage "INFO" "$message"
fi
LogMore___ -f "end"
return 0
}; # end of Log }}}
__INTERNAL_Log_condition() {
cat <<EOF
__INTERNAL_Log_level_do=$1
if [[ \$__INTERNAL_Log_level -ge \$__INTERNAL_Log_level_do ]]; then
[[ -z "$2" ]] && return 1
else
return 0
fi
EOF
}
# LogInfo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogInfo() {
__INTERNAL_LogPrio='INFO'
eval "$(__INTERNAL_Log_condition \$__INTERNAL_Log_level_INFO \"\$1\")"
LogMore___ -f "begin '$*'"
__INTERNAL_LogPrio='INFO'
Log "$1" $__INTERNAL_LogPrio
LogMore___ -f "end"
return 0
}; # end of LogInfo }}}
# LogWarn ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogWarn() {
__INTERNAL_LogPrio='WARNING'
eval "$(__INTERNAL_Log_condition \$__INTERNAL_Log_level_WARNING \"\$1\")"
LogMore___ -f "begin '$*'"
__INTERNAL_LogPrio='WARNING'
Log "$1" $__INTERNAL_LogPrio
LogMore___ -f "end"
return 0
}; # end of LogWarn }}}
# LogWarning ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogWarning() {
__INTERNAL_LogPrio='WARNING'
eval "$(__INTERNAL_Log_condition \$__INTERNAL_Log_level_WARNING \"\$1\")"
LogMore___ -f "begin '$*'"
__INTERNAL_LogPrio='WARNING'
Log "$1" $__INTERNAL_LogPrio
LogMore___ -f "end"
return 0
}; # end of LogWarning }}}
# LogError ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogError() {
__INTERNAL_LogPrio='ERROR'
eval "$(__INTERNAL_Log_condition \$__INTERNAL_Log_level_ERROR \"\$1\")"
LogMore___ -f "begin '$*'"
__INTERNAL_LogPrio='ERROR'
Log "$1" $__INTERNAL_LogPrio
LogMore___ -f "end"
return 0
}; # end of LogError }}}
# LogFatal ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogFatal() {
__INTERNAL_LogPrio='FATAL'
eval "$(__INTERNAL_Log_condition \$__INTERNAL_Log_level_FATAL \"\$1\")"
LogMore___ -f "begin '$*'"
__INTERNAL_LogPrio='FATAL'
Log "$1" $__INTERNAL_LogPrio
exit 255
LogMore___ -f "end"
}; # end of LogFatal }}}
# LogPASS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogPASS() {
LogMore___ -f "begin '$*'"
Log "$1" PASS
LogMore___ -f "end"
return 0
}
LogPass() {
LogPASS "$@"
}; # end of LogPASS }}}
# LogFAIL ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogFAIL() {
LogMore___ -f "begin '$*'"
Log "$1" FAIL
LogMore___ -f "end"
return 0
}
LogFail() {
LogFAIL "$@"
}; # end of LogFAIL }}}
# LogDo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogDo() {
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
local tmp=${BASH_REMATCH[1]:-1}
pref="${FUNCNAME[$tmp]}(): "
}
LogPrintMessage "$__INTERNAL_LogPrio" "${__INTERNAL_Log_prefix}${pref}${__INTERNAL_Log_prefix2}${1}${__INTERNAL_Log_postfix}"
return 0
}; # end of LogDo }}}
# LogDebug ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogDebug() {
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}+1))"
}
__INTERNAL_Log_level_do=${2:-$__INTERNAL_Log_level_DEBUG}
__INTERNAL_LogPrio='DEBUG'
[[ $__INTERNAL_Log_level_do -ge $__INTERNAL_Log_level_MORE ]] && __INTERNAL_LogPrio="${__INTERNAL_LogPrio}:$(($__INTERNAL_Log_level_do-$__INTERNAL_Log_level_DEBUG+1))"
eval "$(__INTERNAL_Log_condition \${2:-\$__INTERNAL_Log_level_DEBUG} \"\$1\")"
LogDo $pref "$1"
return 0
}; # end of LogDebug }}}
# LogMore ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogMore() {
# log if DEBUG does not containg a number
# or the number is greater or equal to 2
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}+1))"
}
LogDebug $pref "$1" ${2:-$__INTERNAL_Log_level_MORE}
}; # end of LogMore }}}
# LogMore_ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogMore_() {
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}+1))"
}
LogDebug $pref "$1" $__INTERNAL_Log_level_MORE_
}; # end of LogMore_ }}}
# LogMore__ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogMore__() {
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}+1))"
}
LogDebug $pref "$1" $__INTERNAL_Log_level_MORE__
}; # end of LogMore__ }}}
# LogMore___ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogMore___() {
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}+1))"
}
LogDebug $pref "$1" $__INTERNAL_Log_level_MORE___
}; # end of LogMore___ }}}
# LogMoreLow ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_LogMoreLow_Obs=''
LogMoreLow() {
[[ -z "$__INTERNAL_LogMoreLow_Obs" ]] && {
LogMore_ -f "LogMoreLow is obsoleted by LogMore_"
__INTERNAL_LogMoreLow_Obs=1
}
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}+1))"
}
LogDebug $pref "$1" $__INTERNAL_Log_level_MORE_
}; # end of LogMoreLow }}}
# LogMoreMed ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_LogMoreMed_Obs=''
LogMoreMed() {
[[ -z "$__INTERNAL_LogMoreMed_Obs" ]] && {
LogMore__ -f "LogMoreMed is obsoleted by LogMore__"
__INTERNAL_LogMoreMed_Obs=1
}
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}+1))"
}
LogDebug $pref "$1" $__INTERNAL_Log_level_MORE__
}; # end of LogMoreMed }}}
# LogMoreHigh ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_LogMoreHigh_Obs=''
LogMoreHigh() {
[[ -z "$__INTERNAL_LogMoreHigh_Obs" ]] && {
LogMore___ -f "LogMoreHigh is obsoleted by LogMore___"
__INTERNAL_LogMoreHigh_Obs=1
}
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}+1))"
}
LogDebug $pref "$1" $__INTERNAL_Log_level_MORE___
}; # end of LogMoreHigh }}}
# LogjAddMessage ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogjAddMessage() {
LogMore__ -f "begin '$*'"
__INTERNAL_Log_journal=("${__INTERNAL_Log_journal[@]}" "$1" "$2")
LogMore__ -f "end"
true;
}; # end of LogjAddMessage }}}
# __INTERNAL_LogCenterText ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_LogCenterText() {
local spaces=' '
# strip colors
local log_pri_strip=$(echo -en "$1" | sed -r "s:\x1B\[[0-9;]*[mK]::g")
local log_pri_strip_count=${#log_pri_strip}
local left_spaces=$(( ($2 - $log_pri_strip_count) / 2 ))
local right_spaces=$(( $2 - $log_pri_strip_count - $left_spaces ))
echo -en "${spaces:0:$left_spaces}${1}${spaces:0:$right_spaces}"
}; # end of __INTERNAL_LogCenterText }}}
# LogPrintMessage ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogPrintMessage() {
echo -e ":: [$(__INTERNAL_LogCenterText "$1" 10)] :: $2" >&2
return 0
}; # end of LogPrintMessage }}}
# LogReport ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 LogReport
Prints final report similar to breakerlib's rlJournalPrintText. This is useful
mainly if you use TCF without beakerlib.
LogReport
=cut
#'
LogReport() {
echo -e "\n ====== Summary report begin ======"
local a p l i
for i in $(seq 0 2 $((${#__INTERNAL_Log_journal[@]}-1)) ); do
LogPrintMessage "${__INTERNAL_Log_journal[$i]}" "${__INTERNAL_Log_journal[$((++i))]}"
done
echo " ======= Summary report end ======="
__INTERNAL_Log_journal=()
}; # end of LogReport }}}
# LogFile ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogFile() {
LogMore__ -f "begin '$*'"
local prio=''
[[ $# -ge 3 ]] && {
optsBegin
optsAdd 'prio|tag|p|t' --mandatory
optsDone; eval "${optsCode}"
}
cat $1 | while IFS= read line; do
Log "$line" "${prio:-$2}"
done
LogMore__ -f "end"
}; #}}}
# LogText ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogText() {
LogMore__ -f "begin '$*'"
local prio=''
[[ $# -ge 3 ]] && {
optsBegin
optsAdd 'prio|tag|p|t' --mandatory
optsDone; eval "${optsCode}"
}
{
if [[ "$1" == "-" ]]; then
cat -
else
echo "$1"
fi
} | while IFS= read line; do
Log "$line" "${prio:-$2}"
done
LogMore__ -f "end"
}; #}}}
# LogStrippedDiff ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogStrippedDiff() {
LogMore__ -f "begin '$*'"
local prio=''
[[ $# -ge 3 ]] && {
optsBegin
optsAdd 'prio|tag|p|t' --mandatory
optsDone; eval "${optsCode}"
}
{
if [[ -n "$2" ]]; then
diff -U0 "$1" "$2"
else
cat $1
fi
} | grep -v -e '^@@ ' -e '^--- ' -e '^+++ ' | while IFS= read line; do
Log "$line" "$prio"
done
LogMore__ -f "end"
}; #}}}
# LogRun ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
# log info about execution to Debug level
LogRun() {
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}+1))"
}
LogMore
local dolog=$?
[[ $dolog -eq 0 ]] || {
local param params blacklist="[[:space:]]|>|<|\|"
[[ "${#@}" -eq 1 ]] && params="$1" || {
for param in "$@"; do
if [[ "$param" =~ $blacklist ]]; then
params="$params \"${param//\"/\\\"}\""
else
params="$params $param"
fi
done
params="${params:1}"
}
LogDo $pref "executing >>>>> ${params} <<<<<"
}
eval "$@"
ret=$?
[[ $dolog -eq 0 ]] || LogMore $pref "execution >>>>> ${params} <<<<< returned '$ret'"
return $ret
}; # end of LogRun }}}
# LogDebugNext ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
# log info about execution to Debug level
LogDebugNext() {
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}))"
}
LogDebug '' ${1:-$__INTERNAL_Log_level_DEBUG} || {
__INTERNAL_Log_DEBUGING=0
trap "
__INTERNAL_Log_DEBUGING_res=\$?
let __INTERNAL_Log_DEBUGING++
if [[ \$__INTERNAL_Log_DEBUGING -eq 1 ]]; then
__INTERNAL_Log_DEBUGING_cmd=\"\$BASH_COMMAND\"
LogDebug $pref \"executing >>>>> \$__INTERNAL_Log_DEBUGING_cmd <<<<<\" ${1:-$__INTERNAL_Log_level_DEBUG}
else
trap - DEBUG
LogDebug $pref \"execution >>>>> \$__INTERNAL_Log_DEBUGING_cmd <<<<< returned \$__INTERNAL_Log_DEBUGING_res\" ${1:-$__INTERNAL_Log_level_DEBUG}
fi" DEBUG
}
}; # end of LogDebugNext }}}
# LogMoreNext ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
# log info about execution to Debug level
LogMoreNext() {
LogMore || {
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}))"
}
LogDebugNext $pref ${1:-$__INTERNAL_Log_level_MORE}
}
}; # end of LogMoreNext }}}
LogNext() {
LogMoreNext "$@"
}
# LogDebugOn ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
# log info about execution to Debug level
LogDebugOn() {
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}))"
}
LogDebug '' ${1:-$__INTERNAL_Log_level_DEBUG} || {
trap "
__INTERNAL_Log_DEBUGING_res=\$?
let __INTERNAL_Log_DEBUGING++
if [[ -z \"\$__INTERNAL_Log_DEBUGING_cmd\" ]]; then
__INTERNAL_Log_DEBUGING_cmd=\"\$BASH_COMMAND\"
LogDebug $pref \"executing >>>>> \$__INTERNAL_Log_DEBUGING_cmd <<<<<\" ${1:-$__INTERNAL_Log_level_DEBUG}
else
LogDebug $pref \"execution >>>>> \$__INTERNAL_Log_DEBUGING_cmd <<<<< returned \$__INTERNAL_Log_DEBUGING_res\" ${1:-$__INTERNAL_Log_level_DEBUG}
__INTERNAL_Log_DEBUGING_cmd=\"\$BASH_COMMAND\"
if [[ \"\$__INTERNAL_Log_DEBUGING_cmd\" =~ LogDebugOff ]]; then
trap - DEBUG
else
LogDebug $pref \"executing >>>>> \$__INTERNAL_Log_DEBUGING_cmd <<<<<\" ${1:-$__INTERNAL_Log_level_DEBUG}
fi
fi" DEBUG
}
}; # end of LogDebugOn }}}
# LogMoreOn ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
# log info about execution to Debug level
LogMoreOn() {
LogMore || {
local pref=''
[[ "$1" =~ ^-f([0-9]*) ]] && {
shift
pref="-f$((${BASH_REMATCH[1]:-1}))"
}
LogDebugOn $pref ${1:-$__INTERNAL_Log_level_MORE}
}
}; # end of LogMoreOn }}}
# LogDebugOff ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
# log info about execution to Debug level
LogDebugOff() {
__INTERNAL_Log_DEBUGING_cmd=''
}; # end of LogDebugOff }}}
# LogVar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogVar() {
[[ -n "$DEBUG" ]] && {
echo -n 'eval '
while [[ -n "$1" ]]; do
echo -n "LogDebug -f \"\$(set | grep -P '^$1=')\";"
shift
done
}
}; # end of LogVar }}}
# __INTERNAL_LogRedirectToBeakerlib ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_LogRedirectToBeakerlib() {
echo -e "\nrunning inside the beakerlib - redirect own logging functions to beakerlib ones"
true; LogjAddMessage() {
LogMore___ -f "begin $*"
rljAddMessage "$2" "$1"
LogMore___ -f "end $*"
}
true; Log() {
LogMore___ -f "begin $*"
case ${2} in
INFO)
LogjAddMessage "INFO" "$1"
LogPrintMessage "$2" "${__INTERNAL_Log_prefix}${__INTERNAL_Log_prefix2}${1}${__INTERNAL_Log_postfix}"
;;
BEGIN)
LogjAddMessage "INFO" "$*:"
LogPrintMessage "$2" "${__INTERNAL_Log_prefix}${__INTERNAL_Log_prefix2}${1}${__INTERNAL_Log_postfix}"
;;
WARNING|WARN|ERROR|FATAL)
LogjAddMessage "WARNING" "$1"
LogPrintMessage "$2" "${__INTERNAL_Log_prefix}${__INTERNAL_Log_prefix2}${1}${__INTERNAL_Log_postfix}"
;;
SKIP|SKIPPING)
LogjAddMessage "WARNING" "$*:"
LogPrintMessage "$2" "${__INTERNAL_Log_prefix}${__INTERNAL_Log_prefix2}${1}${__INTERNAL_Log_postfix}"
;;
FAIL)
rlFail "$*"
return $?
;;
PASS)
rlPass "$*"
return $?
;;
*)
rlLog "$*"
;;
esac
LogMore___ -f "end $*"
return 0;
}
}
# end of __INTERNAL_LogRedirectToBeakerlib }}}
# LogLibraryLoaded ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
LogLibraryLoaded() {
declare -F rlDie > /dev/null && __INTERNAL_LogRedirectToBeakerlib
return 0
}; # end of LogLibraryLoaded }}}
echo "done."
: <<'=cut'
=pod
=head1 AUTHORS
=over
=item *
Dalibor Pospisil <dapospis@redhat.com>
=back
=cut

View File

@ -0,0 +1,48 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Makefile of /distribution/Library/opts
# Description: Block style coding with ability of skipping parts.
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export TEST=/distribution/Library/opts
export TESTVERSION=1.0
BUILT_FILES=
FILES=$(METADATA) lib.sh Makefile
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@echo "Owner: Dalibor Pospisil <dapospis@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "Description: Provides simple way for defining script's or function's options including help" >> $(METADATA)
@echo "Type: Library" >> $(METADATA)
@echo "TestTime: 5m" >> $(METADATA)
@echo "RhtsRequires: library(distribution/Log)" >> $(METADATA)
@echo "Provides: library(distribution/opts)" >> $(METADATA)
@echo "License: GPLv2" >> $(METADATA)
rhts-lint $(METADATA)

View File

@ -0,0 +1,338 @@
#!/bin/bash
# Authors: Dalibor Pospíšil <dapospis@redhat.com>
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2013 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# library-prefix = opts
# library-version = 4
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__INTERNAL_opts_LIB_VERSION=4
: <<'=cut'
=pod
=head1 NAME
BeakerLib library opts
=head1 DESCRIPTION
This library provides simple way for defining script's or function's option
agruments including help.
=head1 USAGE
To use this functionality you need to import library distribution/opts and add
following line to Makefile.
@echo "RhtsRequires: library(distribution/opts)" >> $(METADATA)
B<Code example>
testfunction() {
optsBegin -h "Usage: $0 [options]
options:
"
optsAdd 'flag1' --flag
optsAdd 'optional1|o' --optional
optsAdd 'Optional2|O' "echo opt \$1" --optional --long --var-name opt
optsAdd 'mandatory1|m' "echo man \$1" --mandatory
optsDone; eval "${optsCode}"
echo "$optional1"
echo "$opt"
echo "$mandatory1"
}
=head1 FUNCTIONS
=cut
echo -n "loading library opts v$__INTERNAL_opts_LIB_VERSION... "
# optsAdd ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
optsAdd() {
LogMoreMed -f "begin '$*'"
local GETOPT=$(getopt -q -o fomv:d:lh:l -l flag,opt,optional,mandatory,varname:,default:,local,help:,long -- "$@")
eval set -- "$GETOPT"
local type='f' var_name var_name_set default help long
while [[ -n "$@" ]]; do
case $1 in
--)
shift; break
;;
-h|--help)
shift
help="$1"
;;
-l|--long)
long=1
;;
-d|--default)
shift
default="$1"
;;
-v|--varname|--var-name)
shift
var_name="$1"
var_name_set=1
;;
-f|--flag)
type='f'
;;
-o|--opt|--optional)
type='o'
;;
-m|--mandatory)
type='m'
;;
*)
echo "unknown option '$1'"
return 1
;;
esac
shift;
done
[ -z "$var_name" ] && {
var_name=$(echo -n "$1" | cut -d '|' -f 1 | sed -e 's/-//g;s/^[0-9]/_\0/')
LogMoreHigh -f "constructing variable name '$var_name'"
}
local opts='' opts_help='' optsi=''
for optsi in $(echo -n "$1" | tr '|' ' '); do
if [[ ${#optsi} -ge 2 || $long -eq 1 ]]; then
opts="$opts|--$optsi"
opts_help="$opts_help|--$optsi[=ARG]"
__INTERNAL_opts_long="${__INTERNAL_opts_long},${optsi}"
LogMoreHigh -f "adding long option '$optsi'"
case $type in
m)
__INTERNAL_opts_long="${__INTERNAL_opts_long}:"
;;
o)
__INTERNAL_opts_long="${__INTERNAL_opts_long}::"
;;
esac
else
opts="$opts|-$optsi"
opts_help="$opts_help|-${optsi}[ARG]"
__INTERNAL_opts_short="${__INTERNAL_opts_short}${optsi}"
LogMoreHigh -f "adding short option '$optsi'"
case $type in
m)
__INTERNAL_opts_short="${__INTERNAL_opts_short}:"
;;
o)
__INTERNAL_opts_short="${__INTERNAL_opts_short}::"
;;
esac
fi
done
optsCode="${optsCode}
${opts:1})
optsPresent=\"\${optsPresent}$var_name \""
LogMoreHigh -f "adding code for processing option '${opts:1}'"
__INTERNAL_opts_init_var="$__INTERNAL_opts_init_var
${__INTERNAL_opts_local}$var_name=()"
__INTERNAL_opts_default="$__INTERNAL_opts_default
[[ \"\$optsPresent\" =~ \$(echo \"\<${var_name}\>\") ]] || ${__INTERNAL_opts_local}$var_name='$default'"
case $type in
f)
[[ -z "$2" || -n "$var_name_set" ]] && {
local val=1
[[ -n "$default" ]] && val=''
optsCode="$optsCode
$var_name+=( '$val' )"
}
__INTERNAL_opts_help="${__INTERNAL_opts_help}
${opts:1}"
;;
o|m)
optsCode="$optsCode
shift"
[[ -z "$2" || -n "$var_name_set" ]] && optsCode="$optsCode
$var_name+=( \"\$1\" )"
if [[ "$type" == "o" ]]; then
__INTERNAL_opts_help="${__INTERNAL_opts_help}
${opts_help:1}"
else
__INTERNAL_opts_help="${__INTERNAL_opts_help}
${opts:1} ARG"
fi
;;
esac
[[ -n "$2" ]] && {
optsCode="$optsCode
$2"
}
optsCode="$optsCode
;;"
__INTERNAL_opts_help="${__INTERNAL_opts_help}${help:+
$help
}"
LogMoreMed -f "end"
}; # end of optsAdd }}}
# optsBegin ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
optsBegin() {
LogMoreMed -f "begin '$*'"
optsCode=''
optsPresent=' '
__INTERNAL_opts_short='.'
__INTERNAL_opts_long='help'
__INTERNAL_opts_help=''
__INTERNAL_opts_local=''
__INTERNAL_opts_default=''
__INTERNAL_opts_init_var=''
[[ "${FUNCNAME[1]}" != "main" ]] && __INTERNAL_opts_local='local '
while [[ -n "$1" ]]; do
case $1 in
--)
shift; break
;;
-h|--help)
shift
__INTERNAL_opts_help="$1"
;;
*)
echo "unknown option '$1'"
return 1
;;
esac
shift;
done
LogMoreMed -f "end"
}; # end of optsBegin }}}
# optsDone ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
optsDone() {
LogMoreMed -f "begin '$*'"
optsCode="${__INTERNAL_opts_local}GETOPT=\$(getopt -o ${__INTERNAL_opts_short} -l ${__INTERNAL_opts_long} -- \"\$@\")
[[ \$? -ne 0 ]] && {
echo 'Exiting'
return 1 >& /dev/null
exit 1
}
eval set -- \"\$GETOPT\"
${__INTERNAL_opts_init_var:1}
while [[ -n \"\$1\" ]]; do
case \$1 in
--)
shift; break
;;
${optsCode}
--help)
echo \"\$__INTERNAL_opts_help\"
return >& /dev/null
exit
;;
*)
echo \"unknown option '\$1'\"
return 1 >& /dev/null
exit 1
;;
esac
shift
done
${__INTERNAL_opts_default:1}
unset optsCode __INTERNAL_opts_help __INTERNAL_opts_short __INTERNAL_opts_long __INTERNAL_opts_default __INTERNAL_opts_init_var __INTERNAL_opts_local
"
if ! echo "$optsCode" | grep -q -- '--help$'; then
__INTERNAL_opts_help="$__INTERNAL_opts_help
--help
Show this help."
fi
LogMoreHigh -f "optsCode:\n$optsCode"
LogMoreMed -f "end"
}; # end of optsDone }}}
# optsSelfCheck ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
optsSelfCheck() {
optsBegin -h "Usage: $0 [options]
options:
"
# optsAdd 'help' -f 'echo help'
optsAdd 'flag' -f 'echo f'
optsAdd 'optional|o' -o "echo opt \$1"
optsAdd 'Optional|O' -o "echo opt \$1" --long
optsAdd 'mandatory|m' -m "echo man \$1"
optsDone
echo "${optsCode}"
echo ...
eval "${optsCode}"
echo ...
fce() {
optsBegin -h "Usage: $0 [options]
options:
"
# optsAdd 'help' -f 'echo help'
optsAdd 'flag' -f
optsAdd 'optional|o' -o "echo opt \$1"
optsAdd 'Optional|O' -o "echo opt \$1" --long
optsAdd 'mandatory|m' -m "echo man \$1"
optsDone
echo "${optsCode}"
echo ...
eval "${optsCode}"
echo ...
}
echo -e 'test for opts in function\n========================='
fce --help
}; # end of optsSelfCheck }}}
# optsLibraryLoaded ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
optsLibraryLoaded() {
return 0
}; # end of LogLibraryLoaded }}}
echo "done."
: <<'=cut'
=pod
=head1 AUTHORS
=over
=item *
Dalibor Pospisil <dapospis@redhat.com>
=back
=cut

View File

@ -0,0 +1,60 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Makefile of /distribution/Library/tcf
# Description: Block style coding with ability of skipping parts.
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export TEST=/distribution/Library/tcf
export TESTVERSION=1.0
BUILT_FILES=
FILES=$(METADATA) lib.sh Makefile
.PHONY: all install download clean
run: $(FILES) build
./runtest.sh
build: $(BUILT_FILES)
test -x runtest.sh || chmod a+x runtest.sh
clean:
rm -f *~ $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@echo "Owner: Dalibor Pospisil <dapospis@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "Description: Block style coding with ability of skipping parts." >> $(METADATA)
@echo "Type: Library" >> $(METADATA)
@echo "TestTime: 5m" >> $(METADATA)
@echo "RhtsRequires: library(distribution/Log)" >> $(METADATA)
@echo "Provides: library(distribution/tcf)" >> $(METADATA)
@echo "License: GPLv2" >> $(METADATA)
rhts-lint $(METADATA)

View File

@ -0,0 +1,903 @@
#!/bin/bash
# try-check-final.sh
# Authors: Dalibor Pospíšil <dapospis@redhat.com>
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# library-prefix = tcf
# library-version = 14
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
__INTERNAL_tcf_LIB_VERSION=14
: <<'=cut'
=pod
=head1 NAME
BeakerLib library Try-Check-Final
=head1 DESCRIPTION
This file contains functions which gives user the ability to define blocks of
code where some of the blocks can be automatically skipped if some of preceeding
blocks failed.
ATTENTION
This plugin modifies some beakerlib functions! If you suspect that it breakes
some functionality set the environment variable TCF_NOHACK to nonempty value.
=head1 USAGE
To use this functionality you need to import library distribution/tcf and add
following line to Makefile.
@echo "RhtsRequires: library(distribution/tcf)" >> $(METADATA)
=head1 FUNCTIONS
=cut
echo -n "loading library try-check-final v$__INTERNAL_tcf_LIB_VERSION... "
let __INTERNAL_tcf_DEBUG_LEVEL_LOW=3
let __INTERNAL_tcf_DEBUG_LEVEL_MED=$__INTERNAL_tcf_DEBUG_LEVEL_LOW+1
let __INTERNAL_tcf_DEBUG_LEVEL_HIGH=$__INTERNAL_tcf_DEBUG_LEVEL_LOW+2
# global variables {{{
__INTERNAL_tcf_result=0
__INTERNAL_tcf_result_file="${BEAKERLIB_DIR:-"/var/tmp"}/tcf.result"
echo -n "$__INTERNAL_tcf_result" > "$__INTERNAL_tcf_result_file"
__INTERNAL_tcf_current_level_data=()
__INTERNAL_tcf_current_level_val=0
__INTERNAL_tcf_journal=()
#}}}
# __INTERNAL_tcf_colorize ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_colorize() {
local a
case $1 in
PASS)
a="${__INTERNAL_tcf_color_green}${1}${__INTERNAL_tcf_color_reset}"
;;
FAIL)
a="${__INTERNAL_tcf_color_red}${1}${__INTERNAL_tcf_color_reset}"
;;
SKIPPING|WARNING)
a="${__INTERNAL_tcf_color_yellow}${1}${__INTERNAL_tcf_color_reset}"
;;
BEGIN|INFO)
a="${__INTERNAL_tcf_color_blue}${1}${__INTERNAL_tcf_color_reset}"
;;
*)
a=$1
esac
echo -n "$a"
}; # end of __INTERNAL_tcf_colorize }}}
# __INTERNAL_tcf_colors_setup ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_colors_setup(){
T="$TERM"
[[ -t 1 ]] || T=""
[[ -t 2 ]] || T=""
[[ "$1" == "--force" ]] && T="xterm"
case $T in
xterm|screen)
__INTERNAL_tcf_color_black="\e[0;30m"
__INTERNAL_tcf_color_dark_gray="\e[1;30m"
__INTERNAL_tcf_color_blue="\e[0;34m"
__INTERNAL_tcf_color_light_blue="\e[1;34m"
__INTERNAL_tcf_color_green="\e[0;32m"
__INTERNAL_tcf_color_light_green="\e[1;32m"
__INTERNAL_tcf_color_cyan="\e[0;36m"
__INTERNAL_tcf_color_light_cyan="\e[1;36m"
__INTERNAL_tcf_color_red="\e[0;31m"
__INTERNAL_tcf_color_light_red="\e[1;31m"
__INTERNAL_tcf_color_purple="\e[0;35m"
__INTERNAL_tcf_color_light_purple="\e[1;35m"
__INTERNAL_tcf_color_brown="\e[0;33m"
__INTERNAL_tcf_color_yellow="\e[1;33m"
__INTERNAL_tcf_color_light_gray="\e[0;37m"
__INTERNAL_tcf_color_white="\e[1;37m"
__INTERNAL_tcf_color_reset="\e[00m"
;;
* )
__INTERNAL_tcf_color_black=""
__INTERNAL_tcf_color_dark_gray=""
__INTERNAL_tcf_color_blue=""
__INTERNAL_tcf_color_light_blue=""
__INTERNAL_tcf_color_green=""
__INTERNAL_tcf_color_light_green=""
__INTERNAL_tcf_color_cyan=""
__INTERNAL_tcf_color_light_cyan=""
__INTERNAL_tcf_color_red=""
__INTERNAL_tcf_color_light_red=""
__INTERNAL_tcf_color_purple=""
__INTERNAL_tcf_color_light_purple=""
__INTERNAL_tcf_color_brown=""
__INTERNAL_tcf_color_yellow=""
__INTERNAL_tcf_color_light_gray=""
__INTERNAL_tcf_color_white=""
__INTERNAL_tcf_color_reset=""
;;
esac
}; # end of __INTERNAL_tcf_colors_setup
__INTERNAL_tcf_colors_setup; # }}}
# __INTERNAL_tcf_copy_function ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_copy_function() {
declare -F $1 > /dev/null || return 1
eval "$(echo -n "${2}() "; declare -f ${1} | tail -n +2)"
}; # end of __INTERNAL_tcf_copy_function }}}
# __INTERNAL_tcf_addE2R ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_addE2R() {
__INTERNAL_tcf_copy_function $1 TCF_orig_$1
eval "${1}() { TCF_orig_${1} \"\$@\"; tcfE2R; }"
}; # end of __INTERNAL_tcf_addE2R }}}
# __INTERNAL_tcf_insertE2R ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_insertE2R() {
__INTERNAL_tcf_copy_function $1 TCF_orig_$1
eval "$(echo -n "${1}() "; declare -f ${1} | tail -n +2 | sed -e 's/\(.*__INTERNAL_ConditionalAssert.*\)/\1\ntcfE2R;/')"
}; # end of __INTERNAL_tcf_insertE2R }}}
# __INTERNAL_tcf_get_current_level ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_get_current_level() {
local l=$__INTERNAL_tcf_current_level_val
if [[ $1 ]]; then
l=$(($l+$1))
fi
local i
for i in $(seq 1 $(($l*2)) ); do echo -n " "; done
return $l
}; # end of __INTERNAL_tcf_get_current_level }}}
# __INTERNAL_tcf_incr_current_level ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_incr_current_level() {
let __INTERNAL_tcf_current_level_val++
__INTERNAL_Log_prefix=$(__INTERNAL_tcf_get_current_level)
}; # end of __INTERNAL_tcf_incr_current_level }}}
# __INTERNAL_tcf_decr_current_level ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_decr_current_level() {
let __INTERNAL_tcf_current_level_val--
__INTERNAL_Log_prefix=$(__INTERNAL_tcf_get_current_level)
}; # end of __INTERNAL_tcf_decr_current_level }}}
# __INTERNAL_tcf_do_hack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_do_hack() {
LogDebug "TCF_NOHACK='$TCF_NOHACK'"
if [[ -z "$TCF_NOHACK" ]]; then
tcfChk "Apply TCF beakerlib hacks" && {
rlLog " injecting tcf hacks into the beakerlib functions"
echo -n "patching rlLog"
local rlL=$(declare -f rlLog | sed -e 's|\] ::|\0${__INTERNAL_Log_prefix}|;s|$3 $1"|${3:+"$3 "}$1"|')
eval "$rlL"
echo -n ", rljAddTest"
__INTERNAL_tcf_copy_function rljAddTest __INTERNAL_tcf_orig_rljAddTest
true; rljAddTest() {
local a="${__INTERNAL_Log_prefix}$1"; shift
[[ "$1" != "FAIL" ]]; tcfE2R
__INTERNAL_tcf_journal=("${__INTERNAL_tcf_journal[@]}" "$1" "$a")
__INTERNAL_tcf_orig_rljAddTest "$a" "$@"
}
echo -n ", rljAddMessage"
__INTERNAL_tcf_copy_function rljAddMessage __INTERNAL_tcf_orig_rljAddMessage
true; rljAddMessage() {
local a="${__INTERNAL_Log_prefix}$1"; shift
__INTERNAL_tcf_journal=("${__INTERNAL_tcf_journal[@]}" "$1" "$a")
__INTERNAL_tcf_orig_rljAddMessage "$a" "$@"
}
echo -n ", __INTERNAL_LogAndJournalFail"
__INTERNAL_tcf_copy_function __INTERNAL_LogAndJournalFail __INTERNAL_tcf_orig___INTERNAL_LogAndJournalFail
true; __INTERNAL_LogAndJournalFail() {
tcfNOK
__INTERNAL_tcf_orig___INTERNAL_LogAndJournalFail "$@"
}
echo "."
tcfFin --no-assert --ignore; }
else
Log "skip hacking beakerlib functions"
fi
}; # end of __INTERNAL_tcf_do_hack }}}
# __INTERNAL_tcf_kill_old_plugin ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_kill_old_plugin() {
tcfChk "Get rid of the old TCF implementation. removing" && {
local comma='' i
for i in Try Chk Fin E2R RES OK NOK NEG TCFcheckFinal TCFreport; do
echo -n "${comma}rl$i"
unset -f rl$i
comma=', '
done
echo '.'
tcfFin --no-assert; }
}; # end of __INTERNAL_tcf_kill_old_plugin }}}
: <<'=cut'
=pod
=head2 Block functions
=cut
# __INTERNAL_tcf_parse_params ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
__INTERNAL_tcf_parse_params() {
local GETOPT=$(getopt -q -o if: -l ignore,no-assert,fail-tag: -- "$@")
eval set -- "$GETOPT"
echo "local ignore noass title fail_tag"
echo "[ -z \"\$ignore\" ] && ignore=0"
echo "[ -z \"\$noass\" ] && noass=0"
echo "[ -z \"\$fail_tag\" ] && fail_tag='FAIL'"
while [[ -n "$@" ]]; do
case $1 in
--)
shift; break
;;
--ignore|-i)
echo "ignore=1"
echo "noass=1"
;;
--no-assert|-n)
echo "noass=1"
;;
--fail-tag|-f)
shift
echo "fail_tag='$1'"
;;
*)
echo "unknown option $1"
return 1
;;
esac
shift;
done
[[ -n "$1" ]] && echo "title=\"${1}\""
echo "eval set -- \"$(echo "$GETOPT" | sed -e 's/.*-- //')\""
}; # end of __INTERNAL_tcf_parse_params }}}
# tcfTry ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 tcfTry
Starting function of block which will be skipped if an error has been detected
by tcfFin function occurent before.
tcfTry ["title"] [-i|--ignore] [--no-assert] [--fail-tag TAG] && {
<some code>
tcfFin; }
If title is omitted than noting is printed out so no error will be reported (no
Assert is executed) thus at least the very top level tcfTry should have title.
tcfTry and tcfChk blocks are stackable so you can organize them into a hierarchy
structure.
Note that tcfFin has to be used otherwise the overall result will not be
accurate.
=over
=item title
Text which will be displayed and logged at the beginning and the end (in tcfFin
function) of the block.
=item -i, --ignore
Do not propagate the actual result to the higher level result.
=item -n, --no-assert
Do not log error into the journal.
=item -f, --fail-tag TAG
If the result of the block is FAIL, use TAG instead ie. INFO or WARNING.
=back
Returns 1 if and error occured before, otherwise returns 0.
=cut
tcfTry() {
LogMoreLow -f "begin '$*'"
local vars=$(__INTERNAL_tcf_parse_params "$@") || { Log "$vars" FAIL; return 1; }
LogMoreMed -f "vars:\n$vars"
LogMoreLow -f "evaluating options start"
eval "$vars"
LogMoreLow -f "evaluating options end"
local incr=
local pp="SKIPPING"
tcfRES; # to set __INTERNAL_tcf_result
LogMoreLow -f "result was $__INTERNAL_tcf_result"
if [[ $__INTERNAL_tcf_result -eq 0 ]]; then
__INTERNAL_tcf_current_level_data=("$__INTERNAL_tcf_result" "$vars" "${__INTERNAL_tcf_current_level_data[@]}")
pp="BEGIN"
incr=1
fi
if [[ -n "$title" ]]; then
Log "$title" "$pp"
[[ -n "$incr" ]] && {
LogMoreLow -f "increment indentation level"
__INTERNAL_tcf_incr_current_level
}
fi
LogMoreLow -f "end"
return $__INTERNAL_tcf_result
}; # end of tcfTry }}}
# tcfChk ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 tcfChk
Starting function of block which will be always executed.
tcfChk ["title"] [-i|--ignore] [--no-assert] [--fail-tag TAG] && {
<some code>
tcfFin; }
If title is omitted than noting is printed out so no error will be reported (no
Assert is executed) thus at least the very top level tcfChk should have title.
tcfTry and tcfChk blocks are stackable so you can organize them into a hierarchy
structure.
Note that tcfFin has to be used otherwise the overall result will not be
accurate.
For details about arguments see tcfTry.
Returns 0.
=cut
tcfChk() {
LogMoreLow -f "begin '$*'"
tcfRES; # to set __INTERNAL_tcf_result
local res=$__INTERNAL_tcf_result
tcfRES 0
tcfTry "$@"
__INTERNAL_tcf_current_level_data[0]=$res
LogMoreLow -f "end"
return $__INTERNAL_tcf_result
}; # end of tcfChk }}}
# tcfFin ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 tcfFin
Ending function of block. It does some evaluation of previous local and global
results and puts it into the global result.
tcfTry ["title"] && {
<some code>
tcfFin [-i|--ignore] [--no-assert] [--fail-tag TAG]; }
Local result is actualy exit code of the last command int the body.
Global result is an internal varibale hodning previous local results.
Respectively last error or 0.
For details about arguments see tcfTry.
Returns local result of the preceeding block.
=cut
tcfFin() {
local RES=$?
LogMoreLow -f "begin '$*'"
LogMoreMed -f "previous exit code was '$RES'"
local vars=$(__INTERNAL_tcf_parse_params "$@") || { Log "$vars" FAIL; return 1; }
LogMoreMed -f "vars:\n$vars"
LogMoreLow -f "evaluating options start"
eval "$vars"
LogMoreLow -f "evaluating options end"
tcfRES; # to set __INTERNAL_tcf_result
[[ $RES -ne 0 ]] && tcfRES $RES
RES=$__INTERNAL_tcf_result
LogMoreMed -f "overall result is '$RES'"
LogMoreMed -f "data:\n${__INTERNAL_tcf_current_level_data[1]}"
LogMoreLow -f "evaluating data start"
eval "${__INTERNAL_tcf_current_level_data[1]}"
LogMoreLow -f "evaluating data end"
if [[ -n "$title" ]]; then
__INTERNAL_tcf_decr_current_level
if [[ $ignore -eq 1 ]]; then
RES=0
[[ $__INTERNAL_tcf_result -ne 0 ]] && title="$title - ignored"
fi
if [[ $noass -eq 0 ]]; then
tcfAssert0 "$title" $__INTERNAL_tcf_result "$fail_tag"
else
if [[ $__INTERNAL_tcf_result -eq 0 ]]; then
local pp="PASS"
LogInfo "$title - $pp"
else
local pp="${fail_tag:-FAIL}"
LogWarn "$title - $pp"
fi
fi
fi
if [[ $__INTERNAL_tcf_result -eq 0 || $ignore -eq 1 ]]; then
tcfRES ${__INTERNAL_tcf_current_level_data[0]}
fi
local i
for i in 0 1; do unset __INTERNAL_tcf_current_level_data[$i]; done
__INTERNAL_tcf_current_level_data=("${__INTERNAL_tcf_current_level_data[@]}")
LogMoreLow -f "end"
return $RES
}; # end of tcfFin }}}
: <<'=cut'
=pod
=head2 Functions for manipulation with the results
=cut
# tcfRES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 tcfRES
Sets and return the global result.
tcfRES [-p|--print] [number]
=over
=item -p --print
Also print the result value.
=item number
If present the global result is set to this value.
=back
Returns global result.
=cut
tcfRES() {
local p=0
while [[ -n "$1" ]]; do
case $1 in
--print|-p)
p=1
;;
*)
break
;;
esac
shift
done
if [[ -n "$1" ]]; then
__INTERNAL_tcf_result=$1
echo -n "$__INTERNAL_tcf_result" > "$__INTERNAL_tcf_result_file"
else
__INTERNAL_tcf_result="$(cat "$__INTERNAL_tcf_result_file")"
fi
[[ $p -eq 1 ]] && echo $__INTERNAL_tcf_result
return $__INTERNAL_tcf_result
}; # end of tcfRES }}}
# tcfOK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 tcfOK
Sets the global result to 0.
tcfOK
Returns global result.
=cut
tcfOK() {
tcfRES 0
}; # end of tcfOK }}}
# tcfNOK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 tcfNOK
Sets the global result to 1 or given number.
tcfNOK [number]
=over
=item number
If present the global result is set to this value.
=back
Returns global result.
=cut
tcfNOK() {
if [[ -n "$1" ]]; then
[[ $1 -eq 0 ]] && echo "You have requested result '0'. You should use tcfOK instead."
tcfRES $1
else
tcfRES 1
fi
}; # end of tcfNOK }}}
# tcfE2R ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 tcfE2R
Converts exit code of previous command to local result if the exit code is not 0
(zero).
<some command>
tcfE2R [number]
=over
=item number
If present use it instead of exit code.
=back
Returns original exit code or given number.
=cut
tcfE2R() {
local res=$?
[[ -n "$1" ]] && res=$1
[[ $res -ne 0 ]] && tcfRES $res
return $res
}; # end of tcfE2R }}}
: <<'=cut'
=pod
=head2 Functions for manipulation with the exit codes
=cut
# tcfNEG ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 tcfNEG
Negates exit code of previous command.
<some command>
tcfNEG
Returns 1 if original exit code was 0, otherwise returns 0.
=cut
tcfNEG() {
[[ $? -eq 0 ]] && return 1 || return 0
}; # end of tcfNEG }}}
# tcfRun ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 tcfRun
Simmilar to rlRun but it also annouces the beginnign of the command.
tcfRun [--fail-tag|-f TAG] command [exp_result [title]]
Moreover if 'command not found' appears on STDERR it should produce WARNING.
=over
=item command
Command to execute.
=item exp_result
Specification of expect resutl.
It can be a list of values or intervals or * for any result. Also negation (!) can be used.
Example:
<=2,7,10-12,>252,!254 means following values 0,1,2,7,10,11,12,253,255
=item title
Text which will be displayed and logged at the beginning and the end of command execution.
=item --fail-tag | -f
If the command fails use TAG instead of FAIL.
=back
Returns exit code of the executed command.
=cut
tcfRun() {
LogMore_ -f "begin $*"
optsBegin
optsAdd 'fail-tag|f' --mandatory
optsAdd 'timeout' --optional 'timeout="${1:-10}"'
optsAdd 'kill-timeout|kt' --mandatory --default 5
optsAdd 'signal' --mandatory --default TERM
optsAdd 'check-code' --mandatory --default 'kill -0 $cmdpid >&/dev/null'
optsAdd 'kill-code' --mandatory --default '/bin/kill -$signal -- $cmdpid'
optsAdd 'allow-skip|as' --flag
optsAdd 'no-assert|n' --flag
optsDone; eval "${optsCode}"
LogMore_ -f "after opts $*"
[[ -z "$allowskip" ]] && tcfChk
local orig_expecode="${2:-0}"
local expecode="$orig_expecode"
[[ "$expecode" == "*" ]] && expecode="0-255"
local command="$1"
local comment="Running command '$command'"
[[ -n "$3" ]] && comment="$3"
[[ -n "$expecode" ]] && {
expecode=$(echo "$expecode" | tr ',-' '\n ' | sed -e 's/^!=/!/;s/^=//;s/^<=\(.\+\)$/0 \1/;s/^>=\(.\+\)$/\1 255/;s/^<\(.\+\)$/0 \$(( \1 - 1 ))/;s/^>\(.\+\)$/\$(( \1 + 1 )) 255/' | while read line; do [[ "$line" =~ ^[^\ ]+$ ]] && echo "$line" || eval seq $line; done; )
tcfE2R
LogMoreLow -f "orig_expecode='$orig_expecode'"
LogMoreLow -f "expecode='$expecode'"
}
tcfTry ${noassert:+--no-assert} "$comment" && {
local errout=$(mktemp)
LogMoreLow -f "executing '$command'"
if [[ "$optsPresent" =~ $(echo "\<timeout\>") ]]; then
LogDebug -f "using watchdog feature"
local ec="$(mktemp)"
eval "$command; echo $? > $ec 2> >(tee $errout)" &
local cmdpid=$!
local time_start=$(date +%s)
local timeout_t=$(( $time_start + $timeout ))
while true; do
if ! eval "$checkcode"; then
Log "command finished in $(($(date +%s) - $time_start )) seconds"
local res="$(cat $ec)"
break
elif [[ $(date +%s) -ge $timeout_t ]]; then
echo
Log "command is still running, sending $signal signal"
eval "$killcode"
tcfNOK 255
echo 255 > $ec
let timeout_t+=killtimeout
signal=KILL
fi
sleep 0.1
done
rm -f $ec
else
eval "$command" 2> >(tee $errout)
local res=$?
fi
LogMoreLow -f "got '$res'"
local resmatch=$(echo "$expecode" | grep "^\!\?${res}$")
LogMoreLow -f "resmatch='$resmatch'"
[[ -n "$resmatch" && ! "$resmatch" =~ '!' ]]
if tcfE2R; then
! grep -iq "command not found" $errout || { failtag='WARNING'; tcfNOK; }
else
Log "Expected result was '$orig_expecode', got '$res'!"
fi
tcfFin ${failtag:+--fail-tag "$failtag"}; }
rm -f $errout
[[ -z "$allowskip" ]] && tcfFin
LogMore_ -f "end $*"
return $res
}; # end of tcfRun }}}
: <<'=cut'
=pod
=head2 Functions for logging
=cut
# tcfAssert0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
tcfAssert0() {
LogMoreLow -f "begin '$*'"
local RES="${3:-FAIL}"
[[ $2 -eq 0 ]] && RES='PASS'
Log "$1" $RES
LogMoreLow -f "end"
}; # end of tcfAssert0 }}}
# tcfCheckFinal ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
: <<'=cut'
=pod
=head3 tcfCheckFinal
Check that all tcfTry / tcfChk functions have been close by tcfFin.
tcfCheckFinal
=cut
tcfCheckFinal() {
tcfAssert0 "Check that TCF block cache is empty" ${#__INTERNAL_tcf_current_level_data[@]}
tcfAssert0 "Check that TCF current level is 0" $__INTERNAL_tcf_current_level_val
}; # end of tcfCheckFinal }}}
echo "done."
: <<'=cut'
=pod
=head2 Self check functions
=cut
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# tcfSelfCheck {{{
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
: <<'=cut'
=pod
=head3 tcfSelfCheck
Does some basic functionality tests.
tcfSelfCheck
The function is called also by the following command:
./lib.sh selfcheck
=cut
tcfSelfCheck() {
tcfChk "check 1" &&{
tcfTry "try 1.1 - true" &&{
true
tcfFin;}
tcfTry "try 1.2 - false" &&{
false
tcfFin;}
tcfTry "try 1.3 - true" &&{
true
tcfFin;}
tcfFin;}
tcfChk "check 2" &&{
tcfTry "try 2.1 - true" &&{
true
tcfFin;}
tcfTry "try 2.2 - true - ignore" &&{
true
tcfFin -i;}
tcfTry "try 2.3 - true" &&{
true
tcfFin;}
tcfFin;}
tcfChk "check 3" &&{
tcfTry "try 3.1 - true" &&{
true
tcfFin;}
tcfTry "try 3.2 - false - ignore" &&{
false
tcfFin -i;}
tcfTry "try 3.3 - true" &&{
true
tcfFin;}
tcfFin;}
tcfCheckFinal
tcfAssert0 "Overall result" $(tcfRES -p)
LogReport
}
if [[ "$1" == "selfcheck" ]]; then
tcfSelfCheck
fi; # end of tcfSelfCheck }}}
# tcfLibraryLoaded ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
tcfLibraryLoaded() {
rlImport distribution/Log
declare -F rlDie > /dev/null && {
#rlJournalStart
#rlPhaseStartSetup "TCF"
echo -e "\nrunning inside the beakerlib - using rlAssert0"
true; tcfAssert0() {
local text="$1"
[[ "$3" != "FAIL" && "$3" != "PASS" ]] && text="$text - $3"
__INTERNAL_ConditionalAssert "$text" "$2"
}
__INTERNAL_tcf_do_hack
#rlPhaseEnd
#rlJournalEnd
};
if declare -F rlE2R >& /dev/null; then
__INTERNAL_tcf_kill_old_plugin
fi
true
}; # end of tcfLibraryLoaded }}}
: <<'=cut'
=pod
=head1 AUTHORS
=over
=item *
Dalibor Pospisil <dapospis@redhat.com>
=back
=cut

View File

@ -0,0 +1,60 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Makefile of /distribution/Library/testUser
# Description: Block style coding with ability of skipping parts.
# Author: Dalibor Pospisil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export TEST=/distribution/Library/testUser
export TESTVERSION=1.0
BUILT_FILES=
FILES=$(METADATA) lib.sh Makefile
.PHONY: all install download clean
run: $(FILES) build
./runtest.sh
build: $(BUILT_FILES)
test -x runtest.sh || chmod a+x runtest.sh
clean:
rm -f *~ $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@echo "Owner: Dalibor Pospisil <dapospis@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "Description: Setup/cleanup standard testing user." >> $(METADATA)
@echo "Type: Library" >> $(METADATA)
@echo "TestTime: 5m" >> $(METADATA)
@echo "RhtsRequires: library(distribution/Log)" >> $(METADATA)
@echo "Provides: library(distribution/testUser)" >> $(METADATA)
@echo "License: GPLv2" >> $(METADATA)
rhts-lint $(METADATA)

View File

@ -0,0 +1,234 @@
#!/bin/bash
# try-check-final.sh
# Authors: Dalibor Pospíšil <dapospis@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# library-prefix = testUser
# library-version = 7
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
: <<'=cut'
=pod
=head1 NAME
BeakerLib library testUser
=head1 DESCRIPTION
This library provide s function for maintaining testing users.
=head1 USAGE
To use this functionality you need to import library distribution/testUser and add
following line to Makefile.
@echo "RhtsRequires: library(distribution/testUser)" >> $(METADATA)
=head1 VARIABLES
=over
=item testUser
Array of testing user login names.
=item testUserPasswd
Array of testing users passwords.
=item testUserUID
Array of testing users UIDs.
=item testUserGID
Array of testing users primary GIDs.
=item testUserGroup
Array of testing users primary group names.
=item testUserGIDs
Array of space separated testing users all GIDs.
=item testUserGroups
Array of space separated testing users all group names.
=item testUserGecos
Array of testing users gecos fields.
=item testUserHomeDir
Array of testing users home directories.
=item testUserShell
Array of testing users default shells.
=back
=head1 FUNCTIONS
=cut
echo -n "loading library testUser... "
: <<'=cut'
=pod
=head3 testUserSetup, testUserCleanup
Creates/removes testing user(s).
rlPhaseStartSetup
testUserSetup [NUM]
rlPhaseEnd
rlPhaseStartCleanup
testUserCleanup
rlPhaseEnd
=over
=item NUM
Optional number of user to be created. If not specified one user is created.
=back
Returns 0 if success.
=cut
testUserSetup() {
# parameter dictates how many users should be created, defaults to 1
local res=0
local count_created=0
local count_wanted=${1:-"1"}
local index=0
(( $count_wanted < 1 )) && return 1
while (( $count_created != $count_wanted ));do
let index++
local newUser="testuser${index}"
local newUserPasswd="redhat"
id "$newUser" &> /dev/null && continue # if user with the name exists, try again
# create
useradd -m $newUser >&2 || ((res++))
echo "$newUserPasswd" | passwd --stdin $newUser || ((res++))
# save the users array
testUser+=($newUser)
testUserPasswd+=($newUserPasswd)
set | grep "^testUser=" > $__INTERNAL_testUser_users_file
set | grep "^testUserPasswd=" >> $__INTERNAL_testUser_users_file
((count_created++))
done
__INTERNAL_testUserRefillInfo || ((res++))
echo ${res}
[[ $res -eq 0 ]]
}
__INTERNAL_testUserRefillInfo() {
local res=0
local user
testUserUID=()
testUserGID=()
testUserGroup=()
testUserGIDs=()
testUserGroups=()
testUserGecos=()
testUserHomeDir=()
testUserShell=()
for user in ${testUser[@]}; do
local ent_passwd=$(getent passwd ${user}) || ((res++))
local users_id="$(id ${user})" || ((res++))
# testUser is filled during user creation - already present
# testUserPasswd is saved same way as testUser - already present
testUserUID+=("$(echo "$ent_passwd" | cut -d ':' -f 3)")
testUserGID+=("$(echo "$ent_passwd" | cut -d ':' -f 4)")
testUserGroup+=("$(echo "$users_id" | sed -r 's/.*gid=(\S+).*/\1/;s/[[:digit:]]+\(//g;s/\)//g;s/,/ /g')")
testUserGIDs+=("$(echo "$users_id" | sed -r 's/.*groups=(\S+).*/\1/;s/\([^\)]+\)//g;s/\)//g;s/,/ /g')")
testUserGroups+=("$(echo "$users_id" | sed -r 's/.*groups=(\S+).*/\1/;s/[[:digit:]]+\(//g;s/\)//g;s/,/ /g')")
testUserGecos+=("$(echo "$ent_passwd" | cut -d ':' -f 5)")
testUserHomeDir+=("$(echo "$ent_passwd" | cut -d ':' -f 6)")
testUserShell+=("$(echo "$ent_passwd" | cut -d ':' -f 7)")
done
echo ${res}
[[ $res -eq 0 ]]
}
testUserCleanup() {
local res=0
for user in ${testUser[@]}; do
userdel -rf "$user" >&2 || ((res++))
done
unset testUser
__INTERNAL_testUserRefillInfo
rm -f $__INTERNAL_testUser_users_file >&2 || ((res++))
echo ${res}
[[ $res -eq 0 ]]
}
# testUserLibraryLoaded ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
testUserLibraryLoaded() {
local res=0
# necessary init steps
__INTERNAL_testUser_users_file="$BEAKERLIB_DIR/users"
# try to fill in users array with previous data
[[ -f ${__INTERNAL_testUser_users_file} ]] && . ${__INTERNAL_testUser_users_file} >&2
__INTERNAL_testUserRefillInfo >&2 || ((res++))
[[ $res -eq 0 ]]
}; # end of testUserLibraryLoaded }}}
: <<'=cut'
=pod
=head1 AUTHORS
=over
=item *
Dalibor Pospisil <dapospis@redhat.com>
=back
=cut
echo "done."

File diff suppressed because one or more lines are too long

53
tests/tests.yml Normal file
View File

@ -0,0 +1,53 @@
---
- hosts: localhost
tags: [ always ]
tasks:
- set_fact:
our_required_packages:
- sudo
- passwd # sudoers-options-sanity-test needs passwd command
- postfix # sudoers-options-sanity-test needs mailq command
- wget # upstream-testsuite-execution-and-rebuild-test needs wget command
- yum-utils # upstream-testsuite-execution-and-rebuild-test needs yum-builddep command
- rpm-build # upstream-testsuite-execution-and-rebuild-test needs rpmbuild command
- openssh-clients # use_pty-option needs ssh command
- expect # use_pty-option needs expect command
- procps # run-as needs ps command
- hosts: localhost
tags:
- classic
roles:
- role: standard-test-beakerlib
tests:
- sudoers-options-sanity-test
- upstream-testsuite-execution-and-rebuild-test
#- use_pty-option # test logic is currently broken; maintainer is looking into it
- run-as
- fully-qualified-hostnames
required_packages: "{{ our_required_packages }}"
- hosts: localhost
tags:
- container
roles:
- role: standard-test-beakerlib
tests:
- sudoers-options-sanity-test
- upstream-testsuite-execution-and-rebuild-test
#- use_pty-option # cannot run (needs sshd configured and running)
- run-as
#- fully-qualified-hostnames # cannot run (needs sshd configured and running)
required_packages: "{{ our_required_packages }}"
- hosts: localhost
tags:
- atomic
roles:
- role: standard-test-beakerlib
tests:
- run-as
# - sudoers-options-sanity-test # cannot run (needs to re-install package)
# - upstream-testsuite-execution-and-rebuild-test # cannot run (needs compiler suite)
# - use_pty-option # cannot run (needs expect)
# - fully-qualified-hostnames # cannot run (needs expect)

View File

@ -0,0 +1,70 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Makefile of /CoreOS/sudo/Sanity/upstream-testsuite-execution-and-rebuild-test
# Description: This test rebuild sudo source rpm and checks that rebuild is OK. The second - main - part is about upstream testsuite execution.
# Author: Ales Marecek <amarecek@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2013 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export TEST=/CoreOS/sudo/Sanity/upstream-testsuite-execution-and-rebuild-test
export TESTVERSION=1.0
BUILT_FILES=
FILES=$(METADATA) runtest.sh Makefile PURPOSE
.PHONY: all install download clean
run: $(FILES) build
./runtest.sh
build: $(BUILT_FILES)
test -x runtest.sh || chmod a+x runtest.sh
clean:
rm -f *~ $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@echo "Owner: Ales Marecek <amarecek@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "Description: This test rebuild sudo source rpm and checks that rebuild is OK. The second - main - part is about upstream testsuite execution." >> $(METADATA)
@echo "Type: Sanity" >> $(METADATA)
@echo "TestTime: 15m" >> $(METADATA)
@echo "RunFor: sudo" >> $(METADATA)
@echo "Requires: sudo" >> $(METADATA)
@echo "Requires: sed" >> $(METADATA)
@echo "Requires: grep" >> $(METADATA)
@echo "Requires: rpm-build" >> $(METADATA)
@echo "Requires: yum-utils" >> $(METADATA)
@echo "Requires: make" >> $(METADATA)
@echo "Requires: libcap-devel" >> $(METADATA)
@echo "Requires: audit-libs-devel" >> $(METADATA)
@echo "Priority: Normal" >> $(METADATA)
@echo "License: GPLv2" >> $(METADATA)
@echo "Confidential: no" >> $(METADATA)
@echo "Destructive: no" >> $(METADATA)
rhts-lint $(METADATA)

View File

@ -0,0 +1,3 @@
PURPOSE of /CoreOS/sudo/Sanity/upstream-testsuite-execution-and-rebuild-test
Description: This test rebuild sudo source rpm and checks that rebuild is OK. The second - main - part is about upstream testsuite execution.
Author: Ales Marecek <amarecek@redhat.com>

View File

@ -0,0 +1,80 @@
#!/bin/bash
# vim: dict=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# runtest.sh of /CoreOS/sudo/Sanity/upstream-testsuite-execution-and-rebuild-test
# Description: This test rebuild sudo source rpm and checks that rebuild is OK. The second - main - part is about upstream testsuite execution.
# Author: Ales Marecek <amarecek@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2013 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Include Beaker environment
. /usr/bin/rhts-environment.sh || exit 1
. /usr/share/beakerlib/beakerlib.sh || exit 1
PACKAGE="sudo"
_SPEC_DIR="$(rpm --eval=%_specdir)"
_BUILD_DIR="$(rpm --eval=%_builddir)"
_LOG_REBUILD_F="${PACKAGE}-rebuild.log"
_LOG_TESTSUITE_F="${PACKAGE}-testsuite.log"
rlJournalStart
rlPhaseStartSetup
rlAssertRpm $PACKAGE
rlRun "TmpDir=\$(mktemp -d)" 0 "Creating tmp directory"
rlRun "pushd $TmpDir"
# Source package is needed for code inspection
rlFetchSrcForInstalled "${PACKAGE}" || yumdownloader --source "${PACKAGE}"
rlRun "find . -size 0 -delete" 0 "Remove empty src.rpm-s"
rlRun "yum-builddep -y --nogpgcheck ${PACKAGE}-*.src.rpm" 0 "Installing build dependencies"
[ -d ${_BUILD_DIR} ] && rlRun "rm -rf ${_BUILD_DIR}/*" 0 "Cleaning build directory"
rlRun "rpm -ivh ${PACKAGE}-*.src.rpm" 0 "Installing source rpm"
rlPhaseEnd
rlPhaseStartTest
rlRun "QA_RPATHS=0x0002 rpmbuild -ba ${_SPEC_DIR}/${PACKAGE}.spec" 0 "Test: Rebuild of source '${PACKAGE}' package"
rlGetPhaseState
if [ $? -eq 0 ]; then
cd ${_BUILD_DIR}/${PACKAGE}-*
rlRun -s "make check" 0 "Test: Upstream testsuite"
cd ${TmpDir}
while read -r I; do
if [[ "$I" =~ $(echo '([^:]+): .+ tests run, .+ errors, (.*)% success rate') ]]; then
[[ "${BASH_REMATCH[2]}" == "100" ]]
rlAssert0 "Test: Checking tests of '${BASH_REMATCH[1]}'" $?
elif [[ "$I" =~ $(echo "([^:]+): .+ tests passed; (.+)/.+ tests failed") ]]; then
[[ "${BASH_REMATCH[2]}" == "0" ]]
rlAssert0 "Test: Checking tests of '${BASH_REMATCH[1]}'" $?
fi
done < $rlRun_LOG
rm -f $rlRun_LOG
else
rlFail "Skipping testsuite part because rebuild part failed."
fi
rlPhaseEnd
rlPhaseStartCleanup
rlRun "popd"
rlRun "rm -r $TmpDir" 0 "Removing tmp directory"
rlPhaseEnd
rlJournalPrintText
rlJournalEnd

View File

@ -0,0 +1,72 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Makefile of /CoreOS/sudo/Sanity/use_pty-option
# Description: checks if use_pty option in /etc/sudoers works as expected
# Author: Milos Malik <mmalik@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2011 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export TEST=/CoreOS/sudo/Sanity/use_pty-option
export TESTVERSION=1.0
BUILT_FILES=
FILES=$(METADATA) runtest.sh Makefile PURPOSE forker.sh ssh-sudo.exp
.PHONY: all install download clean
run: $(FILES) build
./runtest.sh
build: $(BUILT_FILES)
chmod a+x runtest.sh
chmod a+x ssh-sudo.exp
clean:
rm -f *~ $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@echo "Owner: Milos Malik <mmalik@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "Description: checks if use_pty option in /etc/sudoers works as expected" >> $(METADATA)
@echo "Type: Sanity" >> $(METADATA)
@echo "TestTime: 10m" >> $(METADATA)
@echo "RunFor: sudo" >> $(METADATA)
@echo "Requires: sudo" >> $(METADATA)
@echo "Requires: iputils" >> $(METADATA)
@echo "Requires: sed" >> $(METADATA)
@echo "Requires: grep" >> $(METADATA)
@echo "Requires: mktemp" >> $(METADATA)
@echo "Requires: openssh-server" >> $(METADATA)
@echo "Requires: openssh-clients" >> $(METADATA)
@echo "Requires: expect" >> $(METADATA)
@echo "Requires: shadow-utils" >> $(METADATA)
@echo "Priority: Normal" >> $(METADATA)
@echo "License: GPLv2" >> $(METADATA)
@echo "Confidential: no" >> $(METADATA)
@echo "Destructive: no" >> $(METADATA)
rhts-lint $(METADATA)

View File

@ -0,0 +1,4 @@
PURPOSE of /CoreOS/sudo/Sanity/use_pty-option
Description: checks if use_pty option in /etc/sudoers works as expected
Author: Milos Malik <mmalik@redhat.com>

View File

@ -0,0 +1,5 @@
#!/bin/bash
for i in `seq 1 10`; do
( ping -c 10 -q www.redhat.com & )
done

76
tests/use_pty-option/runtest.sh Executable file
View File

@ -0,0 +1,76 @@
#!/bin/bash
# vim: dict=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# runtest.sh of /CoreOS/sudo/Sanity/use_pty-option
# Description: checks if use_pty option in /etc/sudoers works as expected
# Author: Milos Malik <mmalik@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2011 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# 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.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Include rhts environment
. /usr/bin/rhts-environment.sh
. /usr/share/beakerlib/beakerlib.sh
PACKAGE="sudo"
USER_NAME="user${RANDOM}"
USER_SECRET="s3kr3T${RANDOM}"
rlJournalStart
rlPhaseStartSetup
rlAssertRpm ${PACKAGE}
OUTPUT_FILE=`mktemp`
rlFileBackup /etc/sudoers
rlFileBackup --clean ~/.ssh
rlRun "useradd ${USER_NAME}"
rlRun "echo ${USER_SECRET} | passwd --stdin ${USER_NAME}"
rlRun "cp ./forker.sh /home/${USER_NAME}/"
rlRun "chown ${USER_NAME}:${USER_NAME} /home/${USER_NAME}/forker.sh"
rlRun "chmod u+x /home/${USER_NAME}/forker.sh"
rlRun "echo \"${USER_NAME} ALL = NOPASSWD: /home/${USER_NAME}/forker.sh\" >> /etc/sudoers"
rlRun "sed -i 's/^.*requiretty.*$//' /etc/sudoers"
rlRun "echo \"Defaults !requiretty\" >> /etc/sudoers"
rlRun "> ~/.ssh/known_hosts"
rlPhaseEnd
rlPhaseStartTest "use_pty option is enabled"
rlRun "sed -i 's/^.*use_pty.*$//' /etc/sudoers"
rlRun "echo \"Defaults use_pty\" >> /etc/sudoers"
rlRun "./ssh-sudo.exp ${USER_NAME} ${USER_SECRET} localhost ./forker.sh 2>&1 | tee ${OUTPUT_FILE}"
rlAssertNotGrep "ping statistics" ${OUTPUT_FILE}
rlPhaseEnd
rlPhaseStartTest "use_pty option is disabled"
rlRun "sed -i 's/^.*use_pty.*$//' /etc/sudoers"
rlRun "echo \"Defaults !use_pty\" >> /etc/sudoers"
rlRun "./ssh-sudo.exp ${USER_NAME} ${USER_SECRET} localhost ./forker.sh 2>&1 | tee ${OUTPUT_FILE}"
rlAssertGrep "ping statistics" ${OUTPUT_FILE}
rlPhaseEnd
rlPhaseStartCleanup
rlRun "userdel -rf ${USER_NAME}"
rlFileRestore
rm -f ${OUTPUT_FILE}
rlPhaseEnd
rlJournalPrintText
rlJournalEnd

View File

@ -0,0 +1,20 @@
#!/usr/bin/expect -f
# usage:
# ./ssh-sudo.exp username password hostname command
set username [lrange $argv 0 0]
set password [lrange $argv 1 1]
set hostname [lrange $argv 2 2]
set command [lrange $argv 3 3]
set timeout 15
spawn ssh $username@$hostname sudo $command
expect "*yes/no*" {
send -- "yes\r"
}
expect "*assword*" {
send -- "$password\r"
}
expect "*assword*" {
send -- "$password\r"
}
expect eof