]> git.cworth.org Git - notmuch/blobdiff - test/test-lib.sh
test: define test_private_C
[notmuch] / test / test-lib.sh
index 89eb744da6f253457d52ac6194b488fe27dc4b90..75a62214db5eb176fc7f96ca11b3ca80a1c2aa7d 100644 (file)
@@ -64,55 +64,7 @@ exec 6>&1 7>&2
 BASH_XTRACEFD=7
 export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
 
-# Keep the original TERM for say_color and test_emacs
-ORIGINAL_TERM=$TERM
-
-# Set SMART_TERM to vt100 for known dumb/unknown terminal.
-# Otherwise use whatever TERM is currently used so that
-# users' actual TERM environments are being used in tests.
-case ${TERM-} in
-       '' | dumb | unknown )
-               SMART_TERM=vt100 ;;
-       *)
-               SMART_TERM=$TERM ;;
-esac
-
-# For repeatability, reset the environment to known value.
-LANG=C
-LC_ALL=C
-PAGER=cat
-TZ=UTC
-TERM=dumb
-export LANG LC_ALL PAGER TERM TZ
-GIT_TEST_CMP=${GIT_TEST_CMP:-diff -u}
-if [[ ( -n "$TEST_EMACS" && -z "$TEST_EMACSCLIENT" ) || \
-      ( -z "$TEST_EMACS" && -n "$TEST_EMACSCLIENT" ) ]]; then
-    echo "error: must specify both or neither of TEST_EMACS and TEST_EMACSCLIENT" >&2
-    exit 1
-fi
-TEST_EMACS=${TEST_EMACS:-${EMACS:-emacs}}
-TEST_EMACSCLIENT=${TEST_EMACSCLIENT:-emacsclient}
-TEST_GDB=${TEST_GDB:-gdb}
-TEST_CC=${TEST_CC:-cc}
-TEST_CFLAGS=${TEST_CFLAGS:-"-g -O0"}
-TEST_SHIM_CFLAGS=${TEST_SHIM_CFLAGS:-"-fpic -shared"}
-TEST_SHIM_LDFLAGS=${TEST_SHIM_LDFLAGS:-"-ldl"}
-
-# Protect ourselves from common misconfiguration to export
-# CDPATH into the environment
-unset CDPATH
-
-unset GREP_OPTIONS
-
-# For lib/open.cc:_load_key_file
-unset XDG_CONFIG_HOME
-
-# For emacsclient
-unset ALTERNATE_EDITOR
-
-# for reproducibility
-unset EMAIL
-unset NAME
+. "$NOTMUCH_SRCDIR/test/test-vars.sh" || exit 1
 
 add_gnupg_home () {
     [ -e "${GNUPGHOME}/gpg.conf" ] && return
@@ -131,20 +83,21 @@ add_gnupg_home () {
     # Change this if we ship a new test key
     FINGERPRINT="5AEAB11F5E33DCE875DDB75B6D92612D94E46381"
     SELF_USERID="Notmuch Test Suite <test_suite@notmuchmail.org> (INSECURE!)"
+    SELF_EMAIL="test_suite@notmuchmail.org"
     printf '%s:6:\n' "$FINGERPRINT" | gpg --quiet --batch --no-tty --import-ownertrust
 }
 
 add_gpgsm_home () {
+    test_require_external_prereq openssl
+
     local fpr
     [ -e "$GNUPGHOME/gpgsm.conf" ] && return
     _gnupg_exit () { gpgconf --kill all 2>/dev/null || true; }
     at_exit_function _gnupg_exit
     mkdir -p -m 0700 "$GNUPGHOME"
-    openssl pkcs12 -export -passout pass: -inkey "$NOTMUCH_SRCDIR/test/smime/key+cert.pem" \
-       < "$NOTMUCH_SRCDIR/test/smime/test.crt" | \
-       gpgsm --batch --no-tty --no-common-certs-import --pinentry-mode=loopback --passphrase-fd 3 \
-             --disable-dirmngr --import  >"$GNUPGHOME"/import.log 2>&1 3<<<''
-    fpr=$(gpgsm --batch --list-key test_suite@notmuchmail.org | sed -n 's/.*fingerprint: //p')
+    gpgsm --batch --no-tty --no-common-certs-import --pinentry-mode=loopback --passphrase-fd 3 \
+         --disable-dirmngr --import  >"$GNUPGHOME"/import.log 2>&1 3<<<'' <$NOTMUCH_SRCDIR/test/smime/0xE0972A47.p12
+    fpr=$(gpgsm --batch --with-colons --list-key test_suite@notmuchmail.org | awk -F: '/^fpr/ {print $10}')
     echo "$fpr S relax" >> "$GNUPGHOME/trustlist.txt"
     gpgsm --quiet --batch --no-tty --no-common-certs-import --disable-dirmngr --import < $NOTMUCH_SRCDIR/test/smime/ca.crt
     echo "4D:E0:FF:63:C0:E9:EC:01:29:11:C8:7A:EE:DA:3A:9A:7F:6E:C1:0D S" >> "$GNUPGHOME/trustlist.txt"
@@ -193,56 +146,53 @@ do
 done
 
 if test -n "$debug"; then
-    print_subtest () {
-       printf " %-4s" "[$((test_count - 1))]"
-    }
+       fmt_subtest () {
+               printf -v $1 " %-4s" "[$((test_count - 1))]"
+       }
 else
-    print_subtest () {
-       true
-    }
+       fmt_subtest () {
+               printf -v $1 ''
+       }
 fi
 
 test -n "$COLORS_WITHOUT_TTY" || [ -t 1 ] || color=
 
-if [ -n "$color" ] && [ "$ORIGINAL_TERM" != 'dumb' ] && (
-               TERM=$ORIGINAL_TERM &&
-               export TERM &&
-               tput bold
-               tput setaf
-               tput sgr0
-       ) >/dev/null 2>&1
+if [ -n "$color" ] && [ "$ORIGINAL_TERM" != 'dumb' ] &&
+       tput -T "$ORIGINAL_TERM" -S <<<$'bold\nsetaf\nsgr0\n' >/dev/null 2>&1
 then
        color=t
 else
        color=
 fi
 
-if test -n "$color"; then
+if test -n "$color"
+then
+       # _tput run in subshell (``) only
+       _tput () { exec tput -T "$ORIGINAL_TERM" "$@"; }
+       unset BOLD RED GREEN BROWN SGR0
        say_color () {
-               (
-               TERM=$ORIGINAL_TERM
-               export TERM
                case "$1" in
-                       error) tput bold; tput setaf 1;; # bold red
-                       skip)  tput bold; tput setaf 2;; # bold green
-                       pass)  tput setaf 2;;            # green
-                       info)  tput setaf 3;;            # brown
-                       *) test -n "$quiet" && return;;
+                       error)  b=${BOLD=`_tput bold`}
+                               c=${RED=`_tput setaf 1`}   ;; # bold red
+                       skip)   b=${BOLD=`_tput bold`}
+                               c=${GREEN=`_tput setaf 2`} ;; # bold green
+                       pass)   b= c=${GREEN=`_tput setaf 2`} ;; # green
+                       info)   b= c=${BROWN=`_tput setaf 3`} ;; # brown
+                       *) b= c=; test -n "$quiet" && return ;;
                esac
-               shift
-               printf " "
-               printf "$@"
-               tput sgr0
-               print_subtest
-               )
+               f=$2
+               shift 2
+               sgr0=${SGR0=`_tput sgr0`}
+               fmt_subtest st
+               printf " ${b}${c}${f}${sgr0}${st}" "$@"
        }
 else
        say_color() {
                test -z "$1" && test -n "$quiet" && return
-               shift
-               printf " "
-               printf "$@"
-               print_subtest
+               f=$2
+               shift 2
+               fmt_subtest st
+               printf " ${f}${st}" "$@"
        }
 fi
 
@@ -332,11 +282,6 @@ die () {
        exit 1
 }
 
-GIT_EXIT_OK=
-# Note: TEST_TMPDIR *NOT* exported!
-TEST_TMPDIR=$(mktemp -d "${TMPDIR:-/tmp}/notmuch-test-$$.XXXXXX")
-# Put GNUPGHOME in TMPDIR to avoid problems with long paths.
-export GNUPGHOME="${TEST_TMPDIR}/gnupg"
 trap 'trap_exit' EXIT
 trap 'trap_signal' HUP INT TERM
 
@@ -402,32 +347,70 @@ test_expect_equal () {
     fi
 }
 
+test_diff_file_ () {
+    local file1 file2 testname basename1 basename2
+    file1="$1"
+    file2="$2"
+    if ! test_skip "$test_subtest_name"
+    then
+       if diff -q "$file1" "$file2" >/dev/null ; then
+           test_ok_
+       else
+           testname=$this_test.$test_count
+           basename1=`basename "$file1"`
+           basename2=`basename "$file2"`
+           cp "$file1" "$testname.$basename1"
+           cp "$file2" "$testname.$basename2"
+           test_failure_ "$(diff -u "$testname.$basename1" "$testname.$basename2")"
+       fi
+    fi
+}
+
 # Like test_expect_equal, but takes two filenames.
 test_expect_equal_file () {
-       local file1 file2 testname basename1 basename2
-       exec 1>&6 2>&7          # Restore stdout and stderr
-       if [ -z "$inside_subtest" ]; then
-               error "bug in the test script: test_expect_equal_file without test_begin_subtest"
-       fi
-       inside_subtest=
-       test "$#" = 2 ||
+    exec 1>&6 2>&7             # Restore stdout and stderr
+    if [ -z "$inside_subtest" ]; then
+       error "bug in the test script: test_expect_equal_file without test_begin_subtest"
+    fi
+    inside_subtest=
+    test "$#" = 2 ||
        error "bug in the test script: not 2 parameters to test_expect_equal_file"
 
-       file1="$1"
-       file2="$2"
-       if ! test_skip "$test_subtest_name"
-       then
-               if diff -q "$file1" "$file2" >/dev/null ; then
-                       test_ok_
-               else
-                       testname=$this_test.$test_count
-                       basename1=`basename "$file1"`
-                       basename2=`basename "$file2"`
-                       cp "$file1" "$testname.$basename1"
-                       cp "$file2" "$testname.$basename2"
-                       test_failure_ "$(diff -u "$testname.$basename1" "$testname.$basename2")"
-               fi
+    test_diff_file_ "$1" "$2"
+}
+
+# Like test_expect_equal_file, but compare the part of the two files after the first blank line
+test_expect_equal_message_body () {
+    exec 1>&6 2>&7             # Restore stdout and stderr
+    if [ -z "$inside_subtest" ]; then
+       error "bug in the test script: test_expect_equal_file without test_begin_subtest"
     fi
+    test "$#" = 2 ||
+       error "bug in the test script: not 2 parameters to test_expect_equal_file"
+
+    expected=$(sed '1,/^$/d' "$1")
+    output=$(sed '1,/^$/d' "$2")
+    test_expect_equal "$expected" "$output"
+}
+
+# Like test_expect_equal, but takes two filenames. Fails if either is empty
+test_expect_equal_file_nonempty () {
+    exec 1>&6 2>&7             # Restore stdout and stderr
+    if [ -z "$inside_subtest" ]; then
+       error "bug in the test script: test_expect_equal_file_nonempty without test_begin_subtest"
+    fi
+    inside_subtest=
+    test "$#" = 2 ||
+       error "bug in the test script: not 2 parameters to test_expect_equal_file_nonempty"
+
+    for file in "$1" "$2"; do
+       if [ ! -s "$file" ]; then
+           test_failure_ "Missing or zero length file: $file"
+           return $?
+       fi
+    done
+
+    test_diff_file_ "$1" "$2"
 }
 
 # Like test_expect_equal, but arguments are JSON expressions to be
@@ -502,16 +485,20 @@ print(msg.as_string(False))
 ' "$@"
 }
 
+notmuch_debug_sanitize () {
+    grep -v '^D.:'
+}
+
 notmuch_exception_sanitize () {
-    perl -pe 's/(A Xapian exception occurred at .*[.]cc?):([0-9]*)/\1:XXX/'
+    perl -pe 's,(A Xapian exception occurred at) .*?([^/]*[.]cc?):([0-9]*),\1 \2:XXX,'
 }
 
 notmuch_search_sanitize () {
-    perl -pe 's/("?thread"?: ?)("?)................("?)/\1\2XXX\3/'
+    notmuch_debug_sanitize | perl -pe 's/("?thread"?: ?)("?)................("?)/\1\2XXX\3/'
 }
 
 notmuch_search_files_sanitize () {
-    notmuch_dir_sanitize
+    notmuch_dir_sanitize |  sed 's/msg-[0-9][0-9][0-9]/msg-XXX/'
 }
 
 notmuch_dir_sanitize () {
@@ -523,6 +510,7 @@ notmuch_show_sanitize () {
     sed -e "$NOTMUCH_SHOW_FILENAME_SQUELCH"
 }
 notmuch_show_sanitize_all () {
+    notmuch_debug_sanitize | \
     sed \
        -e 's| filename:.*| filename:XXXXX|' \
        -e 's| id:[^ ]* | id:XXXXX |' | \
@@ -545,9 +533,10 @@ notmuch_emacs_error_sanitize () {
     shift
     for file in "$@"; do
        echo "=== $file ==="
-       cat "$file"
+       notmuch_debug_sanitize < "$file"
     done | sed \
-       -e 's/^\[.*\]$/[XXX]/' \
+       -e '/^$/d' \
+       -e '/^\[.*\]$/d' \
        -e "s|^\(command: \)\{0,1\}/.*/$command|\1YYY/$command|"
 }
 
@@ -564,26 +553,6 @@ notmuch_built_with_sanitize () {
     sed 's/^built_with[.]\(.*\)=.*$/built_with.\1=something/'
 }
 
-notmuch_passwd_sanitize () {
-    ${NOTMUCH_PYTHON} -c'
-import os, sys, pwd, socket
-
-pw = pwd.getpwuid(os.getuid())
-user = pw.pw_name
-name = pw.pw_gecos.partition(",")[0]
-fqdn = socket.getaddrinfo(socket.gethostname(), 0, 0, socket.SOCK_STREAM, 0, socket.AI_CANONNAME)[0][3]
-
-for l in sys.stdin:
-    if user:
-        l = l.replace(user, "USERNAME")
-    if fqdn:
-        l = l.replace(fqdn, "FQDN").replace(".(none)","")
-    if name:
-        l = l.replace(name, "USER_FULL_NAME")
-    sys.stdout.write(l)
-'
-}
-
 notmuch_config_sanitize () {
     notmuch_dir_sanitize | notmuch_built_with_sanitize
 }
@@ -634,20 +603,6 @@ $binary () {
        fi
 }
 
-# Explicitly require external prerequisite.  Useful when binary is
-# called indirectly (e.g. from emacs).
-# Returns success if dependency is available, failure otherwise.
-test_require_external_prereq () {
-       local binary
-       binary="$1"
-       if [[ ${test_missing_external_prereq_["${binary}"]} == t ]]; then
-               # dependency is missing, call the replacement function to note it
-               eval "$binary"
-       else
-               true
-       fi
-}
-
 # You are not expected to call test_ok_ and test_failure_ directly, use
 # the text_expect_* functions instead.
 
@@ -878,12 +833,13 @@ test_done () {
        mkdir -p "$test_results_dir"
        test_results_path="$test_results_dir/$this_test"
 
-       echo "total $test_count" >> $test_results_path
-       echo "success $test_success" >> $test_results_path
-       echo "fixed $test_fixed" >> $test_results_path
-       echo "broken $test_broken" >> $test_results_path
-       echo "failed $test_failure" >> $test_results_path
-       echo "" >> $test_results_path
+       printf %s\\n \
+               "success $test_success" \
+               "fixed $test_fixed" \
+               "broken $test_broken" \
+               "failed $test_failure" \
+               "total $test_count" \
+           > $test_results_path
 
        [ -n "$EMACS_SERVER" ] && test_emacs '(kill-emacs)'
 
@@ -900,7 +856,7 @@ test_done () {
 test_python () {
     # Note: if there is need to print debug information from python program,
     # use stdout = os.fdopen(6, 'w') or stderr = os.fdopen(7, 'w')
-    PYTHONPATH="$NOTMUCH_SRCDIR/bindings/python${PYTHONPATH:+:$PYTHONPATH}" \
+    PYTHONPATH="$NOTMUCH_BUILDDIR/bindings/python-cffi/build/stage:$NOTMUCH_SRCDIR/bindings/python${PYTHONPATH:+:$PYTHONPATH}" \
        $NOTMUCH_PYTHON -B - > OUTPUT
 }
 
@@ -913,7 +869,20 @@ test_C () {
     echo "== stdout ==" > OUTPUT.stdout
     echo "== stderr ==" > OUTPUT.stderr
     ./${exec_file} "$@" 1>>OUTPUT.stdout 2>>OUTPUT.stderr
-    notmuch_dir_sanitize OUTPUT.stdout OUTPUT.stderr | notmuch_exception_sanitize > OUTPUT
+    notmuch_dir_sanitize OUTPUT.stdout OUTPUT.stderr | notmuch_exception_sanitize | notmuch_debug_sanitize > OUTPUT
+}
+
+test_private_C () {
+    local exec_file test_file
+    exec_file="test${test_count}"
+    test_file="${exec_file}.c"
+    echo '#include <notmuch-private.h>' > ${test_file}
+    cat >> ${test_file}
+    ${TEST_CC} ${TEST_CFLAGS} -I${NOTMUCH_SRCDIR}/test -I${NOTMUCH_SRCDIR}/lib -I${NOTMUCH_SRCDIR}/util -I${NOTMUCH_SRCDIR}/compat ${NOTMUCH_GMIME_CFLAGS} -o ${exec_file} ${test_file} ${NOTMUCH_BUILDDIR}/lib/libnotmuch.a ${NOTMUCH_GMIME_LDFLAGS} ${NOTMUCH_XAPIAN_LDFLAGS} ${NOTMUCH_BUILDDIR}/util/libnotmuch_util.a ${NOTMUCH_SFSEXP_LDFLAGS} ${NOTMUCH_BUILDDIR}/parse-time-string/libparse-time-string.a -ltalloc -lstdc++
+    echo "== stdout ==" > OUTPUT.stdout
+    echo "== stderr ==" > OUTPUT.stderr
+    ./${exec_file} "$@" 1>>OUTPUT.stdout 2>>OUTPUT.stderr
+    notmuch_dir_sanitize OUTPUT.stdout OUTPUT.stderr | notmuch_exception_sanitize | notmuch_debug_sanitize > OUTPUT
 }
 
 make_shim () {