--- /dev/null
+#!/bin/bash
+# -*- bash -*-
+
+# Copyright (C) 2022, 2023 Jacob Bachmeyer
+#
+# This file is part of a testsuite for the GNU FTP upload system.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# 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, see <http://www.gnu.org/licenses/>.
+
+: ${GNUPGHOME:=~/.gnupg-mock}
+
+# parse command line
+declare -a Files Keyrings
+OmitDefaultKeyring=false
+WantFingerprints=false
+WantSubkeyFingerprints=false
+WantColonDelimited=false
+while [ $# -gt 0 ]; do
+ case $1 in
+ --version)
+ echo 'gpg (Testing mock)'
+ exit 0
+ ;;
+ --homedir)
+ GNUPGHOME=$2
+ shift 2
+ ;;
+ --output|-o)
+ OutputFile=$2
+ shift 2
+ ;;
+ --no-default-keyring)
+ OmitDefaultKeyring=true
+ shift
+ ;;
+ --fingerprint|--with-fingerprint)
+ $WantFingerprints && WantSubkeyFingerprints=true
+ WantFingerprints=true
+ shift
+ ;;
+ --with-colons)
+ WantColonDelimited=true
+ shift
+ ;;
+ --fixed-list-mode)
+ # The testing mock always uses this mode.
+ shift
+ ;;
+ --keyring)
+ # unlike gpgv, gpg can create keyrings
+ case $2 in
+ */*)
+ Keyrings=( "${Keyrings[@]}" "$2" )
+ ;;
+ *)
+ Keyrings=( "${Keyrings[@]}" "${GNUPGHOME}/$2" )
+ ;;
+ esac
+ shift 2
+ ;;
+ --import|--export|--list-keys|--delete-key)
+ Command=${1#--}
+ shift
+ ;;
+ -*)
+ echo bogus option $1
+ cat <<EOF
+This testing mock only supports the subset of GPG functionality needed
+for testing the tools in this package. Other options and commands are
+not supported.
+EOF
+ exit 2
+ ;;
+ *)
+ Files=("${Files[@]}" "$1")
+ shift
+ ;;
+ esac
+done
+
+$OmitDefaultKeyring || Keyrings=( ${GNUPGHOME}/pubring.gpg "${Keyrings[@]}" )
+
+function list_keyring_basic() (
+ echo "$1"
+ echo ${1//?/-}
+ last_id=
+ while read record; do
+ id=$(IFS=: ; set -- $record ; echo $1)
+ status=$(IFS=: ; set -- $record ; echo $2)
+ primary=$(IFS=: ; set -- $record ; echo ${3:-$1})
+ user=$(IFS=: ; set -- $record ; echo $4)
+ expire=$(IFS=: ; set -- $record ; echo $5)
+ #
+ [ x$id = x ] && continue
+ if [ x$primary = x$id ]; then type=pub; else type=sub; fi
+ #
+ if [ x$id != x$last_id ]; then
+ if [ x$status = xR ]; then
+ stat=" [revoked: $(date +'%Y-%m-%d')]"
+ elif [ -n "$expire" ]; then
+ if [ $(date -d "$expire" +%s) -lt $(date -d now +%s) ]; then
+ stat=" [expired: $(date +'%Y-%m-%d')]"
+ else
+ stat=" [expires: $(date +'%Y-%m-%d')]"
+ fi
+ else
+ stat=''
+ fi
+ printf "%-6s4096R/%8s %s${stat}\n" \
+ $type ${id:0-8} $(date +'%Y-%m-%d')
+ $WantFingerprints && [ x$type = xpub ] && printf \
+ '%-6sKey Fingerprint = 0000 0000 0000 0000 0000 %s\n' \
+ '' "0000 ${id:0:4} ${id:4:4} ${id:8:4} ${id:12:4}"
+ fi
+ [ x$type = xpub ] && printf '%-20s %s\n' uid "$user"
+ #
+ last_id=$id
+ done <"$1"
+)
+
+function list_keyring_colon_delimited() (
+ keydate=$(date -d '1 day ago' +%s)
+ echo tru::1:$keydate:0
+ # TODO
+ while read record; do
+ id=$(IFS=: ; set -- $record ; echo $1)
+ status=$(IFS=: ; set -- $record ; echo $2)
+ primary=$(IFS=: ; set -- $record ; echo ${3:-$1})
+ user=$(IFS=: ; set -- $record ; echo $4)
+ expire=$(IFS=: ; set -- $record ; echo $5)
+ #
+ [ x$id = x ] && continue
+ #
+ if [ x$primary = x$id ]; then
+ type=pub; keycaps=scSC; otr=u ;
+ else
+ type=sub; keycaps=s ; otr='';
+ fi
+ #
+ if [ -n "$expire" ]; then
+ keyexpire=$(date -d "$expire" +%s)
+ else
+ keyexpire=''
+ fi
+ #
+ if [ x$status = xR ]; then
+ trust=r
+ elif [ -n "$expire" ] \
+ && [ $keyexpire -lt $(date -d now +%s) ]; then
+ trust=e
+ else
+ trust=u
+ fi
+ #
+ uidsha1=$(echo -n "$user" | sha1sum - | awk '{print toupper($1)}')
+ #
+ if [ x$id != x$last_id ]; then
+ echo $type:$trust:4096:1:$id:$keydate:$keyexpire::$otr:::$keycaps:
+ if $WantFingerprints \
+ && [ x$type = xpub ] || $WantSubkeyFingerprints; then
+ echo fpr:::::::::$(printf '%40s' $id | tr ' ' 0):
+ fi
+ fi
+ if [ x$type = xpub ]; then
+ echo uid:u::::$keydate::$uidsha1::$user:
+ fi
+ #
+ last_id=$id
+ done <"$1"
+)
+
+function list_keyring() {
+ if $WantColonDelimited; then
+ list_keyring_colon_delimited "$@"
+ else
+ list_keyring_basic "$@"
+ fi
+}
+
+case ${Command:?no command given} in
+ import)
+ # The mock keyring format is such that import is accomplished by
+ # simply appending the import files to each keyring.
+ if [ "${#Files[*]}" -gt 0 ]; then
+ for file in "${Files[@]}"; do
+ for keyring in "${Keyrings[@]}"; do
+ [ -f "$file" ] && cat "$file" >>"$keyring"
+ done
+ done
+ else
+ # Import with no files? Read stdin instead.
+ TmpFile=mockgpg-scratchpad.$$
+ cat >"$TmpFile"
+ for keyring in "${Keyrings[@]}"; do
+ cat "$TmpFile" >>"$keyring"
+ done
+ rm -f "$TmpFile"
+ fi
+ ;;
+ export)
+ # The mock keyring format simply lists the appropriate lines here.
+ # The "files" are actually key IDs.
+ for keyid in "${Files[@]}"; do
+ [ ${#keyid} -gt 8 ] && keyid=${keyid:0-8}
+ if [ x${OutputFile:+set} = xset ]; then
+ grep -h '^0*'"$keyid": "${Keyrings[@]}" > "$OutputFile"
+ else
+ grep -h '^0*'"$keyid": "${Keyrings[@]}"
+ fi
+ done
+ ;;
+ delete-key)
+ # This simply requires removing the indicated ID from all keyrings.
+ # The "files" are actually key IDs.
+ for keyid in "${Files[@]}"; do
+ [ ${#keyid} -gt 8 ] && keyid=${keyid:0-8}
+ sed -i -e '/^0*'"$keyid"':/d' "${Keyrings[@]}"
+ done
+ ;;
+ list-keys)
+ for keyring in "${Keyrings[@]}"; do
+ list_keyring "$keyring"
+ done
+ ;;
+esac
+
+#EOF
# DejaGnu library file for mockGPG support procedures
-# Copyright (C) 2021 Jacob Bachmeyer
+# Copyright (C) 2021, 2022, 2023 Jacob Bachmeyer
#
# This file is part of a testsuite for the GNU FTP upload system.
#
}
}
+# Match the keys in a keyring file against a list of expected keys
+#
+# Call as:
+# check_test_keyring <test-name> /some/file/some/where {
+# { id <subkey-long-ID> name <user> [is <state>]
+# [subkey-of <primary-key-long-ID>]
+# [expires <expiration>] }...
+# }
+#
+# If the name clause is repeated, the key is required to be duplicated with
+# one entry for each name given. If no <state> is given, the key is
+# required to be valid. If the subkey-of clause is not used, the key is
+# required to be a primary key. If the expires clause is given, the
+# expiration time must match; if not given, the key must not have an
+# expiration time.
+proc check_test_keyring { testname file keylist } {
+ array set allkeyids {}
+
+ # prepare expected keys
+ array set wantkeys {}
+ foreach keyrec $keylist {
+ if { [lindex $keyrec 0] ne "id" } {
+ error "id clause must be listed first in key record: $keyrec"
+ }
+ set keyid [format "%016s" [string toupper [lindex $keyrec 1]]]
+ set wantkeys($keyid,state) V
+ foreach { fld val } $keyrec {
+ switch -- $fld {
+ id {
+ set allkeyids($keyid) 1
+ }
+ name {
+ lappend wantkeys($keyid,names) $val
+ }
+ is {
+ switch -- $val {
+ valid { set wantkeys($keyid,state) V }
+ revoked { set wantkeys($keyid,state) R }
+ }
+ }
+ subkey-of {
+ set wantkeys($keyid,parent) $val
+ }
+ expired -
+ expires {
+ set wantkeys($keyid,expiration) $val
+ }
+ default { error "invalid key record: $keyrec" }
+ }
+ }
+ }
+
+ # read keyring contents
+ array set havekeys {}
+ if { [catch {open $file} chan] } {
+ perror $chan
+ unresolved $testname
+ return
+ }
+ while { [gets $chan keyrec] >= 0 } {
+ if { [regexp -- {^(?:#|[[:space:]]*$)} $keyrec] } { continue }
+
+ set fields [split $keyrec :]
+ set keyid [lindex $fields 0]
+
+ set allkeyids($keyid) 1
+ set havekeys($keyid,state) [lindex $fields 1]
+ if { [string length [lindex $fields 2]] > 0
+ && [lindex $fields 2] ne $keyid} {
+ set havekeys($keyid,parent) [lindex $fields 2]
+ }
+ lappend havekeys($keyid,names) [lindex $fields 3]
+ if { [string length [lindex $fields 4]] > 0 } {
+ set havekeys($keyid,expiration) [lindex $fields 4]
+ }
+ }
+ close $chan
+
+ # match keyring contents
+ set result pass
+ foreach keyid [lsort -dictionary [array names allkeyids]] {
+
+ if { ![info exists wantkeys($keyid,state)] } {
+ verbose -log "unexpected key ID $keyid"
+ set result fail
+ continue
+ } elseif { ![info exists havekeys($keyid,state)] } {
+ verbose -log "missing key ID $keyid"
+ set result fail
+ continue
+ }
+
+ if { $wantkeys($keyid,state) ne $havekeys($keyid,state) } {
+ verbose -log "key states differ for key ID $keyid"
+ verbose -log " wanted $wantkeys($keyid,state),\
+ have $havekeys($keyid,state)"
+ set result fail
+ }
+
+ if { [info exists wantkeys($keyid,parent)]
+ && ![info exists havekeys($keyid,parent)] } {
+ verbose -log "key ID $keyid should be a subkey\
+ of $wantkeys($keyid,parent)"
+ set result fail
+ } elseif { [info exists havekeys($keyid,parent)]
+ && ![info exists wantkeys($keyid,parent)] } {
+ verbose -log "key ID $keyid should be a primary key,\
+ not a subkey of $havekeys($keyid,parent)"
+ set result fail
+ } elseif { [info exists wantkeys($keyid,parent)]
+ && [info exists havekeys($keyid,parent)]
+ && $wantkeys($keyid,parent) ne $havekeys($keyid,parent) } {
+ verbose -log "parent keys differ for key ID $keyid"
+ verbose -log " want: $wantkeys($keyid,parent)"
+ verbose -log " have: $havekeys($keyid,parent)"
+ set result fail
+ }
+
+ if { [lsort $wantkeys($keyid,names)]
+ ne [lsort $havekeys($keyid,names)] } {
+ verbose -log "name sets differ for key ID $keyid"
+ verbose -log " want: [lsort $wantkeys($keyid,names)]"
+ verbose -log " have: [lsort $havekeys($keyid,names)]"
+ set result fail
+ }
+
+ if { [info exists wantkeys($keyid,expiration)]
+ && ![info exists havekeys($keyid,expiration)] } {
+ verbose -log "key ID $keyid should expire\
+ at $wantkeys($keyid,expiration)"
+ set result fail
+ } elseif { [info exists havekeys($keyid,expiration)]
+ && ![info exists wantkeys($keyid,expiration)] } {
+ verbose -log "key ID $keyid should not expire\
+ at $havekeys($keyid,expiration)"
+ set result fail
+ } elseif { [info exists wantkeys($keyid,expiration)]
+ && [info exists havekeys($keyid,expiration)]
+ && $wantkeys($keyid,expiration) \
+ ne $havekeys($keyid,expiration) } {
+ verbose -log "expiration times differ for key ID $keyid"
+ verbose -log " want: $wantkeys($keyid,expiration)"
+ verbose -log " have: $havekeys($keyid,expiration)"
+ set result fail
+ }
+
+ }
+
+ $result $testname
+}
+
# Prepare a keyring file suitable for the GPG mock tools.
# Call as:
# write_test_keyring /some/file/some/where {
foreach { fld val } $keyrec {
switch -- $fld {
id {
- lset keyfields 0 [format "%016s" $val]
+ lset keyfields 0 [format "%016s" [string toupper $val]]
}
name {
lset keyfields 3 $val
--- /dev/null
+# Keyring management tests for GPG mock
+
+# Copyright (C) 2022, 2023 Jacob Bachmeyer
+#
+# This file is part of a testsuite for the GNU FTP upload system.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# 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, see <http://www.gnu.org/licenses/>.
+
+file mkdir $GNUPGHOME
+
+#
+
+proc run_gpg { keyrings args } {
+ global MOCKGPG
+ upvar 1 spawn_id spawn_id
+ set cmd [list spawn $MOCKGPG --no-default-keyring]
+ foreach ring $keyrings { lappend cmd --keyring $ring }
+ verbose -log "$cmd $args"
+ eval $cmd $args
+ expect eof
+ wait
+ catch close
+}
+
+proc testfile { name } {
+ global GNUPGHOME
+ return [file join $GNUPGHOME $name]
+}
+
+#
+
+write_test_keyring [testfile k1a.pgp] {
+ { id 1001 name {test 1-1} }
+}
+write_test_keyring [testfile k1b.pgp] {
+ { id 1002 name {test 1-2} }
+}
+catch {file delete [testfile K1.gpg]}
+
+run_gpg [testfile K1.gpg] --import [testfile k1a.pgp] [testfile k1b.pgp]
+
+check_test_keyring "simple import" [testfile K1.gpg] {
+ { id 1001 name {test 1-1} }
+ { id 1002 name {test 1-2} }
+}
+
+#
+
+write_test_keyring [testfile K2.gpg] {
+ { id 1003 name {test 1-3} }
+ { id 1004 name {test 1-4} }
+}
+
+run_gpg [testfile K2.gpg] --export 1004 -o [testfile k2b.pgp]
+
+check_test_keyring "simple export" [testfile k2b.pgp] {
+ { id 1004 name {test 1-4} }
+}
+
+#
+
+write_test_keyring [testfile K3a.gpg] {
+ { id 1001 name {test 1-1} }
+ { id 1002 name {test 1-2} }
+}
+write_test_keyring [testfile K3b.gpg] {
+ { id 1003 name {test 1-3} }
+ { id 1004 name {test 1-4} }
+}
+
+exec $MOCKGPG --no-default-keyring --keyring [testfile K3b.gpg] --export 1003 \
+ | $MOCKGPG --no-default-keyring --keyring [testfile K3a.gpg] --import
+
+check_test_keyring "key transfer (source)" [testfile K3b.gpg] {
+ { id 1003 name {test 1-3} }
+ { id 1004 name {test 1-4} }
+}
+check_test_keyring "key transfer (target)" [testfile K3a.gpg] {
+ { id 1001 name {test 1-1} }
+ { id 1002 name {test 1-2} }
+ { id 1003 name {test 1-3} }
+}
+
+#
+
+write_test_keyring [testfile K4a.gpg] {
+ { id 1001 name {test 1-1} }
+ { id 1002 name {test 1-2} }
+}
+write_test_keyring [testfile K4b.gpg] {
+ { id 1003 name {test 1-3} }
+ { id 1004 name {test 1-4} }
+}
+
+exec $MOCKGPG --no-default-keyring --keyring [testfile K4b.gpg] \
+ --export 1003 1004 \
+ | $MOCKGPG --no-default-keyring --keyring [testfile K4a.gpg] \
+ --import
+
+check_test_keyring "multiple key transfer (source)" [testfile K4b.gpg] {
+ { id 1003 name {test 1-3} }
+ { id 1004 name {test 1-4} }
+}
+check_test_keyring "multiple key transfer (target)" [testfile K4a.gpg] {
+ { id 1001 name {test 1-1} }
+ { id 1002 name {test 1-2} }
+ { id 1003 name {test 1-3} }
+ { id 1004 name {test 1-4} }
+}
+
+#
+
+write_test_keyring [testfile K5.gpg] {
+ { id 1001 name {test 1-1} }
+ { id 1002 name {test 1-2} }
+ { id 1003 name {test 1-3} }
+ { id 1004 name {test 1-4} }
+}
+
+run_gpg [testfile K5.gpg] --delete-key 00001002 00001003
+
+check_test_keyring "key removal by ID" [testfile K5.gpg] {
+ { id 1001 name {test 1-1} }
+ { id 1004 name {test 1-4} }
+}
+
+#
+
+write_test_keyring [testfile K6.gpg] {
+ { id 1001 name {test 1-1} }
+ { id 1002 name {test 1-2} }
+ { id 1003 name {test 1-3} }
+ { id 1004 name {test 1-4} }
+}
+
+run_gpg [testfile K6.gpg] --delete-key \
+ 0000000000000000000000000000000000001002 \
+ 0000000000000000000000000000000000001003
+
+check_test_keyring "key removal by fingerprint" [testfile K6.gpg] {
+ { id 1001 name {test 1-1} }
+ { id 1004 name {test 1-4} }
+}
+
+#
+
+if { [mock_total_failures] == 0 } {
+ file delete -force $GNUPGHOME
+}
+
+#EOF
--- /dev/null
+# Keyring listing tests for GPG mock
+
+# Copyright (C) 2022, 2023 Jacob Bachmeyer
+#
+# This file is part of a testsuite for the GNU FTP upload system.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# 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, see <http://www.gnu.org/licenses/>.
+
+file mkdir $GNUPGHOME
+
+#
+
+proc spawn_gpg { keyrings args } {
+ global MOCKGPG
+ upvar 1 spawn_id spawn_id
+ set cmd [list spawn $MOCKGPG --no-default-keyring]
+ foreach ring $keyrings { lappend cmd --keyring $ring }
+ verbose -log "$cmd $args"
+ eval $cmd $args
+}
+
+proc testfile { name } {
+ global GNUPGHOME
+ return [file join $GNUPGHOME $name]
+}
+
+#
+
+proc check_key_listing { testname keyring infolist } {
+ set result unresolved
+ set linenum 0
+
+ spawn_gpg $keyring --list-keys
+
+ expect -ex $keyring {
+ set heading_len [string length $expect_out(0,string)]
+ }
+ expect -re "\\r*\\n-{$heading_len}\\r*\\n" {
+ set result pass
+ }
+
+ expect {
+ -re {^[\r\n]+} { exp_continue }
+ -re {***:(?x)
+ ^(?:
+ ([ps]ub)\s+[[:alnum:]]+/([[:xdigit:]]+)
+ (?:\s[[]([^][]+)[]])?[^\n]+\n
+ |(uid)\s+([^\r\n]+)[\r\n]+
+ )
+ } {
+ set want_type [lindex $infolist $linenum 0]
+ if { $want_type eq $expect_out(1,string) } {
+ # pubkey/subkey ID line matching expected type
+ if { [format "%08s" [lindex $infolist $linenum 1]]
+ ne $expect_out(2,string) } {
+ verbose -log "key ID unexpected;\
+ want [lindex $infolist $linenum 1];\
+ have $expect_out(2,string)"
+ set result fail
+ }
+ if { [info exists expect_out(3,string)]
+ && (([lindex $infolist $linenum 2] eq "r"
+ && ![regexp revoked $expect_out(3,string)])
+ || ([lindex $infolist $linenum 2] eq "e"
+ && ![regexp expired $expect_out(3,string)])
+ || ($expect_out(3,string) ne ""
+ && ![regexp expires $expect_out(3,string)])) } {
+ verbose -log "key state unexpected"
+ set result fail
+ }
+ } elseif { $want_type eq $expect_out(4,string) } {
+ # uid line matching expected type
+ if { [lindex $infolist $linenum 1]
+ ne $expect_out(5,string) } {
+ verbose -log "uid name unexpected;\
+ want {[lindex $infolist $linenum 1]};\
+ have {$expect_out(4,string)}"
+ set result fail
+ }
+ } else {
+ verbose -log "line type unexpected\n \
+ want: [lindex $infolist $linenum]\n \
+ have: $expect_out(0,string)"
+ set result fail
+ }
+ incr linenum
+ exp_continue
+ }
+ eof {
+ if { $linenum < [llength $infolist] } {
+ verbose -log "EOF with more lines expected\
+ (at $linenum of [llength $infolist])"
+ set result fail
+ }
+ wait
+ catch close
+ }
+ }
+
+ $result $testname
+}
+
+proc check_key_colon_listing { testname keyring infolist } {
+ set result unresolved
+ set linenum 0
+
+ spawn_gpg $keyring --list-keys --fixed-list-mode \
+ --with-colons --with-fingerprint --with-fingerprint
+
+ expect -re {tru::?:[^\n]+\n} { set result pass }
+
+ expect {
+ -re {^[\r\n]+} { exp_continue }
+ -re {^((?:[^:\r\n]*:)+)\r*\n} {
+ # prepend an empty dummy field so the indexes will match the
+ # 1-based field numbers in the GPG documentation
+ set fields [split ":$expect_out(1,string)" :]
+
+ if { [lindex $fields 1] eq [lindex $infolist $linenum 0] } {
+ switch -- [lindex $fields 1] {
+ pub -
+ sub {
+ set w_id [format "%016s" [lindex $infolist $linenum 1]]
+ if { $w_id ne [lindex $fields 5] } {
+ verbose -log "key ID unexpected;\
+ want ${w_id};\
+ have [lindex $fields 5]"
+ set result fail
+ }
+ if { [lindex $infolist $linenum 2] ne ""
+ && [lindex $infolist $linenum 2] \
+ ne [lindex $fields 2] } {
+ verbose -log "key state unexpected;\
+ want [lindex $infolist $linenum 2];\
+ have [lindex $fields 2]"
+ set result fail
+ }
+ }
+ fpr {
+ set w_fp [format "%040s" [lindex $infolist $linenum 1]]
+ if { $w_fp ne [lindex $fields 10] } {
+ verbose -log "key fingerprint unexpected\n \
+ want ${w_fp}\n \
+ have [lindex $fields 10]"
+ set result fail
+ }
+ }
+ uid {
+ if { [lindex $infolist $linenum 1] \
+ ne [lindex $fields 10] } {
+ verbose -log "uid name unexpected;\
+ want {[lindex $infolist $linenum 1]};\
+ have {[lindex $fields 10]}"
+ set result fail
+ }
+ }
+ }
+ } else {
+ verbose -log "line type unexpected\n \
+ want: [lindex $infolist $linenum]\n \
+ have: $expect_out(0,string)"
+ set result fail
+ }
+
+ incr linenum
+ exp_continue
+ }
+ eof {
+ if { $linenum < [llength $infolist] } {
+ verbose -log "EOF with more lines expected\
+ (at $linenum of [llength $infolist])"
+ set result fail
+ }
+ wait
+ catch close
+ }
+ }
+
+ $result $testname
+}
+
+#
+
+write_test_keyring [testfile L1.gpg] {
+ { id 1001 name {test 1 A} }
+ { id 1001 name {test 1 B} }
+ { id 1002 name {test 1 sub} subkey-of 1001 }
+}
+
+check_key_listing "simple key listing (plain)" [testfile L1.gpg] {
+ { pub 1001 }
+ { uid {test 1 A} }
+ { uid {test 1 B} }
+ { sub 1002 }
+}
+check_key_colon_listing "simple key listing (colons)" [testfile L1.gpg] {
+ { pub 1001 }
+ { fpr 1001 }
+ { uid {test 1 A} }
+ { uid {test 1 B} }
+ { sub 1002 }
+ { fpr 1002 }
+}
+
+#
+
+write_test_keyring [testfile L2.gpg] {
+ { id 2001 name {test 2} is revoked }
+}
+
+check_key_listing "revoked key (plain)" [testfile L2.gpg] {
+ { pub 2001 r }
+ { uid {test 2} }
+}
+check_key_colon_listing "revoked key (colons)" [testfile L2.gpg] {
+ { pub 2001 r }
+ { fpr 2001 }
+ { uid {test 2} }
+}
+
+#
+
+write_test_keyring [testfile L3a.gpg] {
+ { id 3001 name {test 3 A} expires {+5 minutes} }
+}
+write_test_keyring [testfile L3b.gpg] {
+ { id 3002 name {test 3 B} expired {5 minutes ago} }
+}
+
+check_key_listing "key will expire (plain)" [testfile L3a.gpg] {
+ { pub 3001 }
+ { uid {test 3 A} }
+}
+check_key_colon_listing "key will expire (colons)" [testfile L3a.gpg] {
+ { pub 3001 }
+ { fpr 3001 }
+ { uid {test 3 A} }
+}
+
+check_key_listing "expired key (plain)" [testfile L3b.gpg] {
+ { pub 3002 e }
+ { uid {test 3 B} }
+}
+check_key_colon_listing "expired key (colons)" [testfile L3b.gpg] {
+ { pub 3002 e }
+ { fpr 3002 }
+ { uid {test 3 B} }
+}
+
+#
+
+if { [mock_total_failures] == 0 } {
+ file delete -force $GNUPGHOME
+}
+
+#EOF