File indexing completed on 2024-04-28 15:40:21

0001 #!/bin/bash
0002 
0003 # SPDX-FileCopyrightText: 2018-2021 Johannes Zarl-Zierl <johannes@zarl-zierl.at>
0004 #
0005 # SPDX-License-Identifier: BSD-2-Clause
0006 
0007 export LC_ALL=C
0008 myname=`basename "$0"`
0009 mydir=`dirname "$0"`
0010 
0011 DEPS="kphotoalbum convert exiv2 kdialog"
0012 # basic kphotoalbumrc options to make testing less annoying (i.e. prevent some pop-ups):
0013 BASE_RC="\n[Thumbnails]\ndisplayCategories=true\n[Notification Messages]\nimage_config_typein_show_help=false\n[TipOfDay]\nRunOnStart=false"
0014 TEMPDIR=
0015 KEEP_TEMPDIR=0
0016 declare -A _checks _context _check_db_file
0017 
0018 result_ok=0
0019 result_failed=1
0020 result_err_crash=2
0021 result_err_setup=3
0022 
0023 declare -A LOG_LEVELS
0024 LOG_LEVELS[debug]=0
0025 LOG_LEVELS[info]=1
0026 LOG_LEVELS[notice]=2
0027 LOG_LEVELS[warning]=3
0028 LOG_LEVELS[err]=4
0029 # default log level:
0030 LOG_LEVEL=2
0031 
0032 ### functions
0033 
0034 cleanup()
0035 {
0036         if [[ "$KEEP_TEMPDIR" == 1 ]]
0037         then
0038                 log info "NOT removing temporary directory '$TEMPDIR'."
0039         else
0040                 if [[ -d "$TEMPDIR" ]]
0041                 then
0042                         log debug "Removing '$TEMPDIR'..."
0043                         rm -rf "$TEMPDIR"
0044                 fi
0045         fi
0046 }
0047 
0048 log()
0049 {
0050         lvl="$1"
0051         shift
0052         if [ "${LOG_LEVELS[$lvl]}" -ge "$LOG_LEVEL" ]
0053         then
0054                 echo "$myname[$lvl]: $*" >&2
0055         fi
0056 }
0057 
0058 print_help()
0059 {
0060         echo "Usage: $myname --check ] [PARAMETERS...] [--all|CHECKS...]" >&2
0061         echo "       $myname --help" >&2
0062         echo "       $myname --list" >&2
0063         echo "       $myname --print" >&2
0064         echo "" >&2
0065         echo "List or run integration tests for KPhotoAlbum." >&2
0066         echo "This script allows guided integration tests that present the user with concrete things to check." >&2
0067         echo "" >&2
0068         echo "Modes:" >&2
0069         echo "-c|--check                                  Run the specified checks." >&2
0070         echo "-l|--list                                   List available checks." >&2
0071         echo "-p|--print                                  Print available checks with description." >&2
0072         echo "" >&2
0073         echo "Parameters:" >&2
0074         echo "--all                                       Run all tests (only valid for --check)." >&2
0075         echo "--keep-tempdir                              Do not remove temporary files." >&2
0076         echo "--log-level debug|info|notice|warning|err   Set log level (default: notice)." >&2
0077         echo "--tempdir DIR                               Use DIR for temporary files (implies --keep-tempdir)." >&2
0078         echo "" >&2
0079 }
0080 
0081 setup_check()
0082 # setup_check DIR
0083 # sets up a demo db in DIR/db
0084 {
0085         local check_dir="$1"
0086         if ! mkdir "$check_dir" "$check_dir/db" "$check_dir/QtProject"
0087         then
0088                 log err "Could not create check directories for prefix '$check_dir'!"
0089                 return 1
0090         fi
0091 
0092         # set logging rules
0093         cat > "$check_dir/QtProject/qtlogging.ini" <<EOF
0094 [Rules]
0095 *=false
0096 kphotoalbum.*=true
0097 EOF
0098 
0099         # copy demo database (except movie.avi)
0100         # ... movie.avi often makes problems with thumbnailing, causing kphotoalbum to add a token.
0101         # ... Since this does not happen reproducibly for all platforms, better not add the movie file as long as it isn't required for a test.
0102         if ! cp -r "$mydir/../demo/"*.jpg "$mydir/../demo/index.xml" "$check_dir/db"
0103         then
0104                 log err "Could not copy demo database to '$check_dir/db'!"
0105                 return 1
0106         fi
0107 }
0108 
0109 do_list()
0110 {
0111         for check in "${!_checks[@]}"
0112         do
0113                 echo "$check"
0114         done | sort
0115 }
0116 
0117 do_print()
0118 {
0119         for check in "${!_checks[@]}"
0120         do
0121                 echo "$check -- ${_checks[$check]}"
0122         done | sort
0123 }
0124 
0125 do_checks()
0126 {
0127         let num_total=0
0128         let num_ok=0
0129         let num_failed=0
0130         let num_err_crash=0
0131         let num_err_setup=0
0132         local names_failed=
0133         local names_err_crash=
0134         local names_err_setup=
0135 
0136         for name
0137         do
0138                 let num_total++
0139                 do_check "$name"
0140                 case "$?" in
0141                         $result_ok)
0142                                 log info "$name: OK"
0143                                 let num_ok++
0144                                 ;;
0145                         $result_failed)
0146                                 log info "$name: FAILED"
0147                                 let num_failed++
0148                                 names_failed="$names_failed $name"
0149                                 ;;
0150                         $result_err_crash)
0151                                 log info "$name: ERROR (crash)"
0152                                 let num_err_crash++
0153                                 names_err_crash="$names_err_crash $name"
0154                                 ;;
0155                         $result_err_setup)
0156                                 log info "$name: ERROR (setup failed)"
0157                                 let num_err_setup++
0158                                 names_err_setup="$names_err_setup $name"
0159                                 ;;
0160                         *)
0161                                 log err "Internal error: invalid return code while running '$name'!"
0162                                 exit 1
0163                 esac
0164         done
0165 
0166         log notice "Summary: $num_ok of $num_total OK, $num_failed failed, $(( num_err_crash + num_err_setup)) errors."
0167         log notice "Failed: $names_failed"
0168         log notice "Crashed: $names_err_crash"
0169         log notice "Setup error: $names_err_setup"
0170 
0171         # return ok if no test failed:
0172         test "$num_total" -eq "$num_ok"
0173 }
0174 
0175 do_check()
0176 {
0177         local check_name="$1"
0178         local check_desc="${_checks[$check_name]}"
0179         if [ -n "$check_desc" ]
0180         then
0181                 log info "Running check $check_name ($check_desc)..."
0182                 "$check_name"
0183         else
0184                 log err "No check named '$check_name'!"
0185                 exit 1
0186         fi
0187 }
0188 
0189 generic_check()
0190 # generic_check TESTNAME
0191 # Runs the generic check workflow:
0192 # 1. Prepare files for the test (setup_check, prepare_TESTNAME)
0193 # 2. Execute kphotoalbum via call_TESTNAME
0194 # 3. Check index.xml against reference, if available
0195 # 4. Otherwise ask the user to verify manually.
0196 #
0197 # generic_check expects the prepare_TESTNAME and call_TESTNAME functions to be defined.
0198 {
0199         local check_name="$1"
0200         local check_dir="$TEMPDIR/$check_name"
0201         setup_check "$check_dir" || return $result_err_setup
0202         kdialog --msgbox "<h1>$check_name</h1>${_context[$check_name]}"
0203         export XDG_CONFIG_HOME="$check_dir"
0204         prepare_$check_name "$check_dir"
0205         call_$check_name "$check_dir" > "$check_dir/log" 2>&1 || return $result_err_crash
0206         local check_db_file="$mydir/${_check_db_file[$check_name]}"
0207         if [[ -n "$check_db_file" ]]
0208         then
0209                 test -f "$check_db_file" || echo "$check_db_file does not exist!"
0210                 if ! diff -u "$check_db_file" "$check_dir/db/index.xml"
0211                 then
0212                         log notice "$check_name: Mismatch in index.xml!"
0213                         return $result_failed
0214                 else
0215                         return $result_ok
0216                 fi
0217         fi
0218         # fallback: ask the user to verify
0219         if kdialog --yesno "<h1>$check_name &mdash; Did KPhotoAlbum pass the test?</h1><p>As a reminder what you should check:</p><hr/><div style='text-size=small'>${_context[$check_name]}</div>"
0220         then
0221                 return $result_ok
0222         else
0223                 log notice "$check_name: Failed test as determined by user."
0224                 return $result_failed
0225         fi
0226 }
0227 
0228 
0229 ### MAIN
0230 
0231 for dep in $DEPS
0232 do
0233         if ! command -v "$dep" >/dev/null
0234         then
0235                 log err "Could not find required dependency '$dep'!"
0236                 exit 2
0237         fi
0238 done
0239 
0240 version=`kphotoalbum --version 2>&1`
0241 
0242 TEMP=`getopt -o clhp --long "all,check,help,keep-tempdir,list,log-level:,print,tempdir:" -n "$myname" -- "$@"`
0243 if [ $? != 0 ] ; then log err "Terminating..." ; exit 1 ; fi
0244 
0245 # Note the quotes around `$TEMP': they are essential!
0246 eval set -- "$TEMP"
0247 
0248 MODE=check
0249 while true ; do
0250         case "$1" in
0251                 -h|--help) print_help ; exit ;;
0252                 -l|--list) MODE="list" ; shift ;;
0253                 -c|--check) MODE="check" ; shift ;;
0254                 -p|--print) MODE="print" ; shift ;;
0255                 --keep-tempdir) KEEP_TEMPDIR=1 ; shift ;;
0256                 --tempdir) TEMPDIR="$2" ; KEEP_TEMPDIR=1 ; shift 2 ;;
0257                 --all) RUN_ALL=1 ; shift ;;
0258                 --log-level) LOG_LEVEL="${LOG_LEVELS[$2]}" ; shift 2 ;;
0259                 --) shift ; break ;;
0260                 *) echo "Internal error!" ; exit 1 ;;
0261         esac
0262 done
0263 log info "Using $version (`command -v kphotoalbum`)..."
0264 
0265 if [ -z "$TEMPDIR" ]
0266 then
0267         TEMPDIR=`mktemp -d --tmpdir kphotoalbum-tests-XXXXXX`
0268 fi
0269 
0270 trap cleanup EXIT
0271 
0272 # read test files
0273 for f in "$mydir/integration-tests/"*.sh
0274 do
0275         . "$f"
0276 done
0277 
0278 case $MODE in
0279         list|print)
0280                 do_$MODE
0281                 ;;
0282         check)
0283                 if [[ "$RUN_ALL" == 1 ]]
0284                 then
0285                         eval set -- "${!_checks[@]}"
0286                 fi
0287                 do_checks "$@"
0288                 ;;
0289 esac