1
0
mirror of https://github.com/mail-in-a-box/mailinabox.git synced 2026-03-04 15:54:48 +01:00

1. Better code organization & simplify

2. Add "populate" data for upgrades - enabled in both system-setup scripts
3. Add "upgrade" test runner suite
This commit is contained in:
downtownallday
2020-06-19 12:12:49 -04:00
parent 144aa6e5d6
commit 1bd7b2c4c7
20 changed files with 987 additions and 509 deletions

View File

@@ -12,6 +12,8 @@ set +eu
. suites/_mgmt-functions.sh || exit 1
# globals - all global variables are UPPERCASE
ASSETS_DIR="assets"
MIAB_DIR=".."
BASE_OUTPUTDIR="$(realpath out)"
PYMAIL="./test_mail.py"
declare -i OVERALL_SUCCESSES=0

View File

@@ -35,207 +35,26 @@ assert_is_configured() {
}
nextcloud_url() {
# eg: http://localhost/cloud/
carddav_url | sed 's|\(.*\)/remote.php/.*|\1/|'
}
carddav_url() {
# get the carddav url as configured in z-push for the user specified
# eg: http://localhost/cloud/remote.php/dav/addressbooks/users/admin/contacts/
local user="${1:-%u}"
local path="${2:-CARDDAV_DEFAULT_PATH}"
local php='include "/usr/local/lib/z-push/backend/carddav/config.php"; print CARDDAV_PROTOCOL . "://" . CARDDAV_SERVER . ":" . CARDDAV_PORT . '
php="$php$path;"
local url
url="$(php -n -r "$php")"
[ $? -ne 0 ] && die "Unable to run php to extract carddav url from z-push"
sed "s/%u/$user/" <<< "$url"
}
carddav_rest() {
# issue a CardDAV rest call to Nextcloud
# SEE: https://tools.ietf.org/html/rfc6352
local verb="$1"
local uri="$2"
local auth_user="$3"
local auth_pass="$4"
shift; shift; shift; shift # remaining arguments are data
local url
case "$uri" in
/* )
url="$(nextcloud_url)${uri#/}"
;;
http*)
url="$uri"
;;
* )
url="$(carddav_url "$auth_user")${uri#/}"
;;
esac
local data=()
local item output
for item; do data+=("--data" "$item"); done
local ct
case "${data[1]}" in
BEGIN:VCARD* )
ct="text/vcard"
;;
* )
ct='text/xml; charset="utf-8"'
esac
record "spawn: curl -w \"%{http_code}\" -X $verb -H 'Content-Type: $ct' --user \"${auth_user}:xxx\" ${data[@]} \"$url\""
output=$(curl -s -S -w "%{http_code}" -X $verb -H "Content-Type: $ct" --user "${auth_user}:${auth_pass}" "${data[@]}" "$url" 2>>$TEST_OF)
local code=$?
# http status is last 3 characters of output, extract it
REST_HTTP_CODE=$(awk '{S=substr($0,length($0)-2)} END {print S}' <<<"$output")
REST_OUTPUT=$(awk 'BEGIN{L=""}{ if(L!="") print L; L=$0 } END { print substr(L,1,length(L)-3) }' <<<"$output")
REST_ERROR=""
[ -z "$REST_HTTP_CODE" ] && REST_HTTP_CODE="000"
if [ $code -ne 0 -o \
$REST_HTTP_CODE -lt 200 -o \
$REST_HTTP_CODE -ge 300 ]
then
REST_ERROR="REST status $REST_HTTP_CODE: $REST_OUTPUT"
REST_ERROR_BRIEF=$(python3 -c "import xml.etree.ElementTree as ET; print(ET.fromstring(r'''$REST_OUTPUT''').find('s:message',{'s':'http://sabredav.org/ns'}).text)" 2>/dev/null)
if [ -z "$REST_ERROR_BRIEF" ]; then
REST_ERROR_BRIEF="$REST_ERROR"
else
REST_ERROR_BRIEF="$REST_HTTP_CODE: $REST_ERROR_BRIEF"
fi
if [ $code -ne 0 ]; then
REST_ERROR_BRIEF="curl exit code $code: $REST_ERROR_BRIEF"
REST_ERROR="curl exit code $code: $REST_ERROR"
fi
record "${F_DANGER}$REST_ERROR${F_RESET}"
return 2
fi
record "CURL succeded, HTTP status $REST_HTTP_CODE"
record "$output"
return 0
}
carddav_ls() {
# return all .vcf files in array 'FILES'
local user="$1"
local pass="$2"
carddav_rest PROPFIND "" "$user" "$pass" || return $?
local file FILES=()
python3 -c "import xml.etree.ElementTree as ET; [print(el.find('d:href',{'d':'DAV:'}).text) for el in ET.fromstring(r'''$REST_OUTPUT''').findall('d:response',{'d':'DAV:'}) if el.find('d:href',{'d':'DAV:'}) is not None]" |
while read file; do
# skip non .vcf entries
case "$file" in
*.vcf )
FILES+=( "$(basename "$file")" )
;;
* )
;;
esac
done
}
make_collection() {
local user="$1"
local pass="$2"
local name="$3"
local desc="${4:-$name}"
local xml="<?xml version=\"1.0\" encoding=\"utf-8\" ?>
<D:mkcol xmlns:D=\"DAV:\"
xmlns:C=\"urn:ietf:params:xml:ns:carddav\">
<D:set>
<D:prop>
<D:resourcetype>
<D:collection/>
<C:addressbook/>
</D:resourcetype>
<D:displayname>$name</D:displayname>
<C:addressbook-description xml:lang=\"en\">$desc</C:addressbook-description>
</D:prop>
</D:set>
</D:mkcol>"
record "[create address book '$name' for $user]"
local url="$(carddav_url "$user" CARDDAV_PATH)"
carddav_rest MKCOL "$url" "$user" "$pass" "$xml"
}
add_contact() {
local user="$1"
local pass="$2"
local c_name="$3"
local c_phone="$4"
local c_email="$5"
local c_uid="${6:-$(generate_uuid)}"
local file_name="$c_uid.vcf"
local vcard="BEGIN:VCARD
VERSION:3.0
UID:$c_uid
REV;VALUE=DATE-AND-OR-TIME:$(date -u +%Y%m%dT%H%M%SZ)
FN:$c_name
EMAIL;TYPE=INTERNET,PREF:$c_email
NOTE:Miab-LDAP QA
ORG:Miab-LDAP
TEL;TYPE=WORK,VOICE:$c_phone
END:VCARD"
record "[add contact '$c_name' to $user]"
carddav_rest PUT "$file_name" "$user" "$pass" "$vcard"
}
delete_contact() {
local user="$1"
local pass="$2"
local c_uid="$3"
local file_name="$c_uid.vcf"
record "[delete contact with vcard uid '$c_uid' from $user]"
carddav_rest DELETE "$file_name" "$user" "$pass"
}
force_roundcube_carddav_refresh() {
local user="$1"
local pass="$2"
local code
record "[forcing refresh of roundcube contact for $user]"
copy_or_die assets/mail/roundcube/carddav_refresh.sh $RCM_DIR/bin
pushd "$RCM_DIR" >/dev/null
bin/carddav_refresh.sh "$user" "$pass" >>$TEST_OF 2>&1
code=$?
popd >/dev/null
return $code
}
assert_roundcube_carddav_contact_exists() {
local user="$1"
local pass="$2"
local c_uid="$3"
local output
record "[checking that roundcube contact with vcard UID=$c_uid exists]"
output="$(sqlite3 $STORAGE_ROOT/mail/roundcube/roundcube.sqlite "select name from carddav_contacts where cuid='$c_uid'" 2>>$TEST_OF)"
if [ $? -ne 0 ]; then
test_failure "Error querying roundcube sqlite database"
return 1
fi
if [ -z "$output" ]; then
roundcube_carddav_contact_exists "$user" "$pass" "$c_uid" 2>>$TEST_OF
local rc=$?
if [ $rc -eq 0 ]; then
return
elif [ $rc -eq 1 ]; then
test_failure "Contact not found in Roundcube"
record "Not found"
record "Existing entries (name,vcard-uid):"
output="$(sqlite3 $STORAGE_ROOT/mail/roundcube/roundcube.sqlite "select name,cuid FROM carddav_contacts" 2>>$TEST_OF)"
return 1
else
record "$output"
record "Existing entries:"
roundcube_dump_contacts >>$TEST_OF 2>&1
else
test_failure "Error querying roundcube contacts"
return
fi
return 0
}
@@ -245,9 +64,12 @@ test_mail_from_nextcloud() {
}
test_nextcloud_contacts() {
test_start "nextcloud_contacts"
test_start "nextcloud-contacts"
assert_is_configured || test_end && return
if ! assert_is_configured; then
test_end
return
fi
local alice="alice.nc@somedomain.com"
local alice_pw="$(generate_password 16)"
@@ -263,28 +85,37 @@ test_nextcloud_contacts() {
# LDAP and that Roundcube is able to reach Nextcloud for contacts
#
#make_collection "$alice" "$alice_pw" "contacts"
#record "[create address book 'contacts' for $alice]"
#carddav_make_addressbook "$alice" "$alice_pw" "contacts" 2>>$TEST_OF
# add new contact to alice's Nextcloud account using CardDAV API
local c_uid="$(generate_uuid)"
add_contact \
record "[add contact 'JimIno' to $alice]"
if ! carddav_add_contact \
"$alice" \
"$alice_pw" \
"JimIno" \
"555-1212" \
"jim@ino.com" \
"$c_uid" \
|| test_failure "Could not add contact for $alice in Nextcloud: $REST_ERROR_BRIEF"
2>>$TEST_OF
then
test_failure "Could not add contact for $alice in Nextcloud: $REST_ERROR_BRIEF"
test_end
return
fi
# force a refresh/sync of the contacts in Roundcube
force_roundcube_carddav_refresh "$alice" "$alice_pw" || \
record "[forcing refresh of roundcube contact for $alice]"
roundcube_force_carddav_refresh "$alice" "$alice_pw" >>$TEST_OF 2>&1 || \
test_failure "Could not refresh roundcube contacts for $alice"
# query the roundcube sqlite database for the new contact
assert_roundcube_carddav_contact_exists "$alice" "$alice_pw" "$c_uid"
# delete the contact
delete_contact "$alice" "$alice_pw" "$c_uid" || \
record "[delete contact with vcard uid '$c_uid' from $alice]"
carddav_delete_contact "$alice" "$alice_pw" "$c_uid" 2>>$TEST_OF || \
test_failure "Unable to delete contact for $alice in Nextcloud"

48
tests/suites/upgrade.sh Normal file
View File

@@ -0,0 +1,48 @@
#
# the system must have been populated proir to any upgrade with one of
# the tests/system-setup/populate scripts to use this suite
#
# supply the name of the populate script that was used as an argument
# eg. if basic-populate.sh was used to populate, supply "basic" to the
# script as an argument
#
verify_populate() {
local populate_name="$1"
local verify_script="system-setup/populate/${populate_name}-verify.sh"
test_start "verify '$populate_name' population set"
if [ ! -e "$verify_script" ]; then
test_failure "Verify script $(basename "$verify_script") does not exist"
else
record "[run verify-upgrade script $verify_script]"
local output rc
output=$("$verify_script" 2>>$TEST_OF)
rc=$?
if [ $rc -ne 0 ]
then
if [ $rc -eq 127 ]; then
test_failure "verify script would not run (wd=$(pwd))"
else
test_failure "verify script exited with $rc: $output"
fi
fi
fi
test_end
}
suite_start "upgrade"
export ASSETS_DIR
export MIAB_DIR
verify_populate "$1"
suite_end