Home | History | Annotate | Line # | Download | only in system
      1      1.1  christos #!/bin/sh
      2      1.1  christos #
      3      1.1  christos # Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      4      1.1  christos #
      5      1.1  christos # SPDX-License-Identifier: MPL-2.0
      6      1.1  christos #
      7      1.1  christos # This Source Code Form is subject to the terms of the Mozilla Public
      8      1.1  christos # License, v. 2.0. If a copy of the MPL was not distributed with this
      9      1.1  christos # file, you can obtain one at https://mozilla.org/MPL/2.0/.
     10      1.1  christos #
     11      1.1  christos # See the COPYRIGHT file distributed with this work for additional
     12      1.1  christos # information regarding copyright ownership.
     13      1.1  christos 
     14      1.1  christos # When sourcing the script outside the pytest environment (e.g. during helper
     15      1.1  christos # script development), the env variables have to be loaded.
     16      1.1  christos if [ -z "$TOP_SRCDIR" ]; then
     17      1.1  christos   SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd | sed -E 's|(.*bin/tests/system).*|\1|')
     18      1.1  christos   eval "$(PYTHONPATH="$SCRIPT_DIR:$PYTHONPATH" /usr/bin/env python3 -m isctest)"
     19      1.1  christos fi
     20      1.1  christos 
     21      1.1  christos testsock6() {
     22      1.1  christos   if test -n "$PERL" && $PERL -e "use IO::Socket::IP;" 2>/dev/null; then
     23      1.1  christos     $PERL "$TOP_SRCDIR/bin/tests/system/testsock6.pl" "$@"
     24      1.1  christos   else
     25      1.1  christos     false
     26      1.1  christos   fi
     27      1.1  christos }
     28      1.1  christos 
     29      1.1  christos echofail() {
     30      1.1  christos   echo "$*"
     31      1.1  christos }
     32      1.1  christos echowarn() {
     33      1.1  christos   echo "$*"
     34      1.1  christos }
     35      1.1  christos echopass() {
     36      1.1  christos   echo "$*"
     37      1.1  christos }
     38      1.1  christos echoinfo() {
     39      1.1  christos   echo "$*"
     40      1.1  christos }
     41      1.1  christos echostart() {
     42      1.1  christos   echo "$*"
     43      1.1  christos }
     44      1.1  christos echoend() {
     45      1.1  christos   echo "$*"
     46      1.1  christos }
     47      1.1  christos 
     48      1.1  christos echo_i() {
     49      1.1  christos   echo "$@" | while IFS= read -r __LINE; do
     50      1.1  christos     echoinfo "I:$__LINE"
     51      1.1  christos   done
     52      1.1  christos }
     53      1.1  christos 
     54      1.1  christos echo_ic() {
     55      1.1  christos   echo "$@" | while IFS= read -r __LINE; do
     56      1.1  christos     echoinfo "I:  $__LINE"
     57      1.1  christos   done
     58      1.1  christos }
     59      1.1  christos 
     60      1.1  christos echo_d() {
     61      1.1  christos   echo "$@" | while IFS= read -r __LINE; do
     62      1.1  christos     echoinfo "D:$__LINE"
     63      1.1  christos   done
     64      1.1  christos }
     65      1.1  christos 
     66      1.1  christos cat_i() {
     67      1.1  christos   while IFS= read -r __LINE; do
     68      1.1  christos     echoinfo "I:$__LINE"
     69      1.1  christos   done
     70      1.1  christos }
     71      1.1  christos 
     72      1.1  christos cat_d() {
     73      1.1  christos   while IFS= read -r __LINE; do
     74      1.1  christos     echoinfo "D:$__LINE"
     75      1.1  christos   done
     76      1.1  christos }
     77      1.1  christos 
     78      1.1  christos digcomp() {
     79      1.1  christos   {
     80      1.1  christos     output=$($PERL $TOP_SRCDIR/bin/tests/system/digcomp.pl "$@")
     81      1.1  christos     result=$?
     82      1.1  christos   } || true
     83      1.1  christos   [ -n "$output" ] && {
     84      1.1  christos     echo "digcomp failed:"
     85      1.1  christos     echo "$output"
     86      1.1  christos   } | cat_i
     87      1.1  christos   return $result
     88      1.1  christos }
     89      1.1  christos 
     90      1.1  christos start_server() {
     91      1.1  christos   $PERL "$TOP_SRCDIR/bin/tests/system/start.pl" "$SYSTESTDIR" "$@"
     92      1.1  christos }
     93      1.1  christos 
     94      1.1  christos stop_server() {
     95      1.1  christos   $PERL "$TOP_SRCDIR/bin/tests/system/stop.pl" "$SYSTESTDIR" "$@"
     96      1.1  christos }
     97      1.1  christos 
     98      1.1  christos send() {
     99      1.1  christos   $PERL "$TOP_SRCDIR/bin/tests/system/send.pl" "$@"
    100      1.1  christos }
    101      1.1  christos 
    102      1.1  christos #
    103      1.1  christos # Useful functions in test scripts
    104      1.1  christos #
    105      1.1  christos 
    106      1.1  christos # assert_int_equal: compare two integer variables, $1 and $2
    107      1.1  christos #
    108      1.1  christos # If $1 and $2 are equal, return 0; if $1 and $2 are not equal, report
    109      1.1  christos # the error using the description of the tested variable provided in $3
    110      1.1  christos # and return 1.
    111      1.1  christos assert_int_equal() {
    112      1.1  christos   found="$1"
    113      1.1  christos   expected="$2"
    114      1.1  christos   description="$3"
    115      1.1  christos 
    116      1.1  christos   if [ "${expected}" -ne "${found}" ]; then
    117      1.1  christos     echo_i "incorrect ${description}: got ${found}, expected ${expected}"
    118      1.1  christos     return 1
    119      1.1  christos   fi
    120      1.1  christos 
    121      1.1  christos   return 0
    122      1.1  christos }
    123      1.1  christos 
    124      1.1  christos # keyfile_to_keys_section: helper function for keyfile_to_*_keys() which
    125      1.1  christos # converts keyfile data into a key-style trust anchor configuration
    126      1.1  christos # section using the supplied parameters
    127      1.1  christos keyfile_to_keys() {
    128      1.1  christos   section_name=$1
    129      1.1  christos   key_prefix=$2
    130      1.1  christos   shift
    131      1.1  christos   shift
    132      1.1  christos   echo "$section_name {"
    133      1.1  christos   for keyname in $*; do
    134      1.1  christos     awk '!/^; /{
    135      1.1  christos 	    printf "\t\""$1"\" "
    136      1.1  christos 	    printf "'"$key_prefix "'"
    137      1.1  christos 	    printf $4 " " $5 " " $6 " \""
    138      1.1  christos 	    for (i=7; i<=NF; i++) printf $i
    139      1.1  christos 	    printf "\";\n"
    140      1.1  christos 	}' $keyname.key
    141      1.1  christos   done
    142      1.1  christos   echo "};"
    143      1.1  christos }
    144      1.1  christos 
    145      1.1  christos # keyfile_to_dskeys_section: helper function for keyfile_to_*_dskeys()
    146      1.1  christos # converts keyfile data into a DS-style trust anchor configuration
    147      1.1  christos # section using the supplied parameters
    148      1.1  christos keyfile_to_dskeys() {
    149      1.1  christos   section_name=$1
    150      1.1  christos   key_prefix=$2
    151      1.1  christos   shift
    152      1.1  christos   shift
    153      1.1  christos   echo "$section_name {"
    154      1.1  christos   for keyname in $*; do
    155      1.1  christos     $DSFROMKEY $keyname.key \
    156      1.1  christos       | awk '!/^; /{
    157      1.1  christos 	    printf "\t\""$1"\" "
    158      1.1  christos 	    printf "'"$key_prefix "'"
    159      1.1  christos 	    printf $4 " " $5 " " $6 " \""
    160      1.1  christos 	    for (i=7; i<=NF; i++) printf $i
    161      1.1  christos 	    printf "\";\n"
    162      1.1  christos 	}'
    163      1.1  christos   done
    164      1.1  christos   echo "};"
    165      1.1  christos }
    166      1.1  christos 
    167      1.1  christos # keyfile_to_trusted_keys: convert key data contained in the keyfile(s)
    168      1.1  christos # provided to a "trust-keys" section suitable for including in a
    169      1.1  christos # resolver's configuration file
    170      1.1  christos keyfile_to_trusted_keys() {
    171      1.1  christos   keyfile_to_keys "trusted-keys" "" $*
    172      1.1  christos }
    173      1.1  christos 
    174      1.1  christos # keyfile_to_static_keys: convert key data contained in the keyfile(s)
    175      1.1  christos # provided to a *static-key* "trust-anchors" section suitable for including in
    176      1.1  christos # a resolver's configuration file
    177      1.1  christos keyfile_to_static_keys() {
    178      1.1  christos   keyfile_to_keys "trust-anchors" "static-key" $*
    179      1.1  christos }
    180      1.1  christos 
    181      1.1  christos # keyfile_to_initial_keys: convert key data contained in the keyfile(s)
    182      1.1  christos # provided to an *initial-key* "trust-anchors" section suitable for including
    183      1.1  christos # in a resolver's configuration file
    184      1.1  christos keyfile_to_initial_keys() {
    185      1.1  christos   keyfile_to_keys "trust-anchors" "initial-key" $*
    186      1.1  christos }
    187      1.1  christos 
    188      1.1  christos # keyfile_to_static_ds_keys: convert key data contained in the keyfile(s)
    189      1.1  christos # provided to a *static-ds* "trust-anchors" section suitable for including in a
    190      1.1  christos # resolver's configuration file
    191      1.1  christos keyfile_to_static_ds() {
    192      1.1  christos   keyfile_to_dskeys "trust-anchors" "static-ds" $*
    193      1.1  christos }
    194      1.1  christos 
    195      1.1  christos # keyfile_to_initial_ds_keys: convert key data contained in the keyfile(s)
    196      1.1  christos # provided to an *initial-ds* "trust-anchors" section suitable for including
    197      1.1  christos # in a resolver's configuration file
    198      1.1  christos keyfile_to_initial_ds() {
    199      1.1  christos   keyfile_to_dskeys "trust-anchors" "initial-ds" $*
    200      1.1  christos }
    201      1.1  christos 
    202      1.1  christos # keyfile_to_key_id: convert a key file name to a key ID
    203      1.1  christos #
    204      1.1  christos # For a given key file name (e.g. "Kexample.+013+06160") provided as $1,
    205      1.1  christos # print the key ID with leading zeros stripped ("6160" for the
    206      1.1  christos # aforementioned example).
    207      1.1  christos keyfile_to_key_id() {
    208      1.1  christos   echo "$1" | sed "s/.*+0\{0,4\}//"
    209      1.1  christos }
    210      1.1  christos 
    211      1.1  christos # private_type_record: write a private type record recording the state of the
    212      1.1  christos # signing process
    213      1.1  christos #
    214      1.1  christos # For a given zone ($1), algorithm number ($2) and key file ($3), print the
    215      1.1  christos # private type record with default type value of 65534, indicating that the
    216      1.1  christos # signing process for this key is completed.
    217      1.1  christos private_type_record() {
    218      1.1  christos   _zone=$1
    219      1.1  christos   _algorithm=$2
    220      1.1  christos   _keyfile=$3
    221      1.1  christos 
    222      1.1  christos   _id=$(keyfile_to_key_id "$_keyfile")
    223      1.1  christos 
    224      1.1  christos   printf "%s. 0 IN TYPE65534 %s 5 %02x%04x0000\n" "$_zone" "\\#" "$_algorithm" "$_id"
    225      1.1  christos }
    226      1.1  christos 
    227      1.1  christos # nextpart*() - functions for reading files incrementally
    228      1.1  christos #
    229      1.1  christos # These functions aim to facilitate looking for (or waiting for)
    230      1.1  christos # messages which may be logged more than once throughout the lifetime of
    231      1.1  christos # a given named instance by outputting just the part of the file which
    232      1.1  christos # has been appended since the last time we read it.
    233      1.1  christos #
    234      1.1  christos # Calling some of these functions causes temporary *.prev files to be
    235      1.1  christos # created.
    236      1.1  christos #
    237      1.1  christos # Note that unlike other nextpart*() functions, nextpartread() is not
    238      1.1  christos # meant to be directly used in system tests; its sole purpose is to
    239      1.1  christos # reduce code duplication below.
    240      1.1  christos #
    241      1.1  christos # A quick usage example:
    242      1.1  christos #
    243      1.1  christos #     $ echo line1 > named.log
    244      1.1  christos #     $ echo line2 >> named.log
    245      1.1  christos #     $ nextpart named.log
    246      1.1  christos #     line1
    247      1.1  christos #     line2
    248      1.1  christos #     $ echo line3 >> named.log
    249      1.1  christos #     $ nextpart named.log
    250      1.1  christos #     line3
    251      1.1  christos #     $ nextpart named.log
    252      1.1  christos #     $ echo line4 >> named.log
    253      1.1  christos #     $ nextpartpeek named.log
    254      1.1  christos #     line4
    255      1.1  christos #     $ nextpartpeek named.log
    256      1.1  christos #     line4
    257      1.1  christos #     $ nextpartreset named.log
    258      1.1  christos #     $ nextpartpeek named.log
    259      1.1  christos #     line1
    260      1.1  christos #     line2
    261      1.1  christos #     line3
    262      1.1  christos #     line4
    263      1.1  christos #     $ nextpart named.log
    264      1.1  christos #     line1
    265      1.1  christos #     line2
    266      1.1  christos #     line3
    267      1.1  christos #     line4
    268      1.1  christos #     $ nextpart named.log
    269      1.1  christos #     $
    270      1.1  christos 
    271      1.1  christos # nextpartreset: reset the marker used by nextpart() and nextpartpeek()
    272      1.1  christos # so that it points to the start of the given file
    273      1.1  christos nextpartreset() {
    274      1.1  christos   echo "0" >$1.prev
    275      1.1  christos }
    276      1.1  christos 
    277      1.1  christos # nextpartread: read everything that's been appended to a file since the
    278      1.1  christos # last time nextpart() was called and print it to stdout, print the
    279      1.1  christos # total number of lines read from that file so far to file descriptor 3
    280      1.1  christos nextpartread() {
    281      1.1  christos   [ -f $1.prev ] || nextpartreset $1
    282      1.1  christos   prev=$(cat $1.prev)
    283      1.1  christos   awk "NR > $prev "'{ print }
    284      1.1  christos 	 END          { print NR > "/dev/stderr" }' $1 2>&3
    285      1.1  christos }
    286      1.1  christos 
    287      1.1  christos # nextpart: read everything that's been appended to a file since the
    288      1.1  christos # last time nextpart() was called
    289      1.1  christos nextpart() {
    290      1.1  christos   nextpartread $1 3>$1.prev.tmp
    291      1.1  christos   mv $1.prev.tmp $1.prev
    292      1.1  christos }
    293      1.1  christos 
    294      1.1  christos # nextpartpeek: read everything that's been appended to a file since the
    295      1.1  christos # last time nextpart() was called
    296      1.1  christos nextpartpeek() {
    297      1.1  christos   nextpartread $1 3>/dev/null
    298      1.1  christos }
    299      1.1  christos 
    300      1.1  christos # _search_log: look for message $1 in file $2 with nextpart().
    301      1.1  christos _search_log() (
    302      1.1  christos   msg="$1"
    303      1.1  christos   file="$2"
    304      1.1  christos   nextpart "$file" | grep -F -e "$msg" >/dev/null
    305      1.1  christos )
    306      1.1  christos 
    307      1.1  christos # _search_log_re: same as _search_log but the message is an grep -E regex
    308      1.1  christos _search_log_re() (
    309      1.1  christos   msg="$1"
    310      1.1  christos   file="$2"
    311      1.1  christos   nextpart "$file" | grep -E -e "$msg" >/dev/null
    312      1.1  christos )
    313      1.1  christos 
    314      1.1  christos # _search_log_peek: look for message $1 in file $2 with nextpartpeek().
    315      1.1  christos _search_log_peek() (
    316      1.1  christos   msg="$1"
    317      1.1  christos   file="$2"
    318      1.1  christos   nextpartpeek "$file" | grep -F -e "$msg" >/dev/null
    319      1.1  christos )
    320      1.1  christos 
    321      1.1  christos # wait_for_log: wait until message $2 in file $3 appears.  Bail out after
    322      1.1  christos # $1 seconds.  This needs to be used in conjunction with a prior call to
    323      1.1  christos # nextpart() or nextpartreset() on the same file to guarantee the offset is
    324      1.1  christos # set correctly.  Tests using wait_for_log() are responsible for cleaning up
    325      1.1  christos # the created <file>.prev files.
    326      1.1  christos wait_for_log() (
    327      1.1  christos   timeout="$1"
    328      1.1  christos   msg="$2"
    329      1.1  christos   file="$3"
    330      1.1  christos   retry_quiet "$timeout" _search_log "$msg" "$file" && return 0
    331      1.1  christos   echo_i "exceeded time limit waiting for literal '$msg' in $file"
    332      1.1  christos   return 1
    333      1.1  christos )
    334      1.1  christos 
    335      1.1  christos # wait_for_log_re: same as wait_for_log, but the message is an grep -E regex
    336      1.1  christos wait_for_log_re() (
    337      1.1  christos   timeout="$1"
    338      1.1  christos   msg="$2"
    339      1.1  christos   file="$3"
    340      1.1  christos   retry_quiet "$timeout" _search_log_re "$msg" "$file" && return 0
    341      1.1  christos   echo_i "exceeded time limit waiting for regex '$msg' in $file"
    342      1.1  christos   return 1
    343      1.1  christos )
    344      1.1  christos 
    345      1.1  christos # wait_for_log_peek: similar to wait_for_log() but peeking, so the file offset
    346      1.1  christos # does not change.
    347      1.1  christos wait_for_log_peek() (
    348      1.1  christos   timeout="$1"
    349      1.1  christos   msg="$2"
    350      1.1  christos   file="$3"
    351      1.1  christos   retry_quiet "$timeout" _search_log_peek "$msg" "$file" && return 0
    352      1.1  christos   echo_i "exceeded time limit waiting for literal '$msg' in $file"
    353      1.1  christos   return 1
    354      1.1  christos )
    355      1.1  christos 
    356      1.1  christos # _retry: keep running a command until it succeeds, up to $1 times, with
    357      1.1  christos # one-second intervals, optionally printing a message upon every attempt
    358      1.1  christos _retry() {
    359      1.1  christos   __retries="${1}"
    360      1.1  christos   shift
    361      1.1  christos 
    362      1.1  christos   while :; do
    363      1.1  christos     if "$@"; then
    364      1.1  christos       return 0
    365      1.1  christos     fi
    366      1.1  christos     __retries=$((__retries - 1))
    367      1.1  christos     if [ "${__retries}" -gt 0 ]; then
    368      1.1  christos       if [ "${__retry_quiet}" -ne 1 ]; then
    369      1.1  christos         echo_i "retrying"
    370      1.1  christos       fi
    371      1.1  christos       sleep 1
    372      1.1  christos     else
    373      1.1  christos       return 1
    374      1.1  christos     fi
    375      1.1  christos   done
    376      1.1  christos }
    377      1.1  christos 
    378      1.1  christos # retry: call _retry() in verbose mode
    379      1.1  christos retry() {
    380      1.1  christos   __retry_quiet=0
    381      1.1  christos   _retry "$@"
    382      1.1  christos }
    383      1.1  christos 
    384      1.1  christos # retry_quiet: call _retry() in silent mode
    385      1.1  christos retry_quiet() {
    386      1.1  christos   __retry_quiet=1
    387      1.1  christos   _retry "$@"
    388      1.1  christos }
    389      1.1  christos 
    390      1.1  christos # _repeat: keep running command up to $1 times, unless it fails
    391      1.1  christos _repeat() (
    392      1.1  christos   __retries="${1}"
    393      1.1  christos   shift
    394      1.1  christos   while :; do
    395      1.1  christos     if ! "$@"; then
    396      1.1  christos       return 1
    397      1.1  christos     fi
    398      1.1  christos     __retries=$((__retries - 1))
    399      1.1  christos     if [ "${__retries}" -le 0 ]; then
    400      1.1  christos       break
    401      1.1  christos     fi
    402      1.1  christos   done
    403      1.1  christos   return 0
    404      1.1  christos )
    405      1.1  christos 
    406      1.1  christos _times() {
    407      1.1  christos   awk "BEGIN{ for(i = 1; i <= $1; i++) print i}"
    408      1.1  christos }
    409      1.1  christos 
    410      1.1  christos rndc_reload() {
    411      1.1  christos   $RNDC -c ../_common/rndc.conf -s $2 -p ${CONTROLPORT} reload $3 2>&1 | sed 's/^/'"I:$1"' /'
    412      1.1  christos   # reloading single zone is synchronous, if we're reloading whole server
    413      1.1  christos   # we need to wait for reload to finish
    414      1.1  christos   if [ -z "$3" ]; then
    415      1.1  christos     for _ in $(_times 10); do
    416      1.1  christos       $RNDC -c ../_common/rndc.conf -s $2 -p ${CONTROLPORT} status | grep "reload/reconfig in progress" >/dev/null || break
    417      1.1  christos       sleep 1
    418      1.1  christos     done
    419      1.1  christos   fi
    420      1.1  christos }
    421      1.1  christos 
    422      1.1  christos rndc_reconfig() {
    423      1.1  christos   seconds=${3:-10}
    424      1.1  christos   $RNDC -c ../_common/rndc.conf -s "$2" -p "${CONTROLPORT}" reconfig 2>&1 | sed 's/^/'"I:$1"' /'
    425      1.1  christos   for _ in $(_times "$seconds"); do
    426      1.1  christos     "$RNDC" -c ../_common/rndc.conf -s "$2" -p "${CONTROLPORT}" status | grep "reload/reconfig in progress" >/dev/null || break
    427      1.1  christos     sleep 1
    428      1.1  christos   done
    429      1.1  christos }
    430      1.1  christos 
    431      1.1  christos # rndc_dumpdb: call "rndc dumpdb [...]" and wait until it completes
    432      1.1  christos #
    433      1.1  christos # The first argument is the name server instance to send the command to, in the
    434      1.1  christos # form of "nsX" (where "X" is the instance number), e.g. "ns5".  The remaining
    435      1.1  christos # arguments, if any, are appended to the rndc command line after "dumpdb".
    436      1.1  christos #
    437      1.1  christos # Control channel configuration for the name server instance to send the
    438      1.1  christos # command to must match the contents of bin/tests/system/_common/rndc.conf.
    439      1.1  christos #
    440      1.1  christos # rndc output is stored in a file called rndc.out.test${n}; the "n" variable is
    441      1.1  christos # required to be set by the calling tests.sh script.
    442      1.1  christos #
    443      1.1  christos # Return 0 if the dump completes successfully; return 1 if rndc returns an exit
    444      1.1  christos # code other than 0 or if the "; Dump complete" string does not appear in the
    445      1.1  christos # dump within 10 seconds.
    446      1.1  christos rndc_dumpdb() {
    447      1.1  christos   __ret=0
    448      1.1  christos   __dump_complete=0
    449      1.1  christos   __server="${1}"
    450  1.1.1.2  christos   __ip="10.53.0.$(echo "${__server}" | tr -c -d '[:digit:]')"
    451      1.1  christos 
    452      1.1  christos   shift
    453      1.1  christos   ${RNDC} -c ../_common/rndc.conf -p "${CONTROLPORT}" -s "${__ip}" dumpdb "$@" >"rndc.out.test${n}" 2>&1 || __ret=1
    454      1.1  christos 
    455      1.1  christos   for _ in 0 1 2 3 4 5 6 7 8 9; do
    456      1.1  christos     if grep '^; Dump complete$' "${__server}/named_dump.db" >/dev/null; then
    457      1.1  christos       mv "${__server}/named_dump.db" "${__server}/named_dump.db.test${n}"
    458      1.1  christos       __dump_complete=1
    459      1.1  christos       break
    460      1.1  christos     fi
    461      1.1  christos     sleep 1
    462      1.1  christos   done
    463      1.1  christos 
    464      1.1  christos   if [ ${__dump_complete} -eq 0 ]; then
    465      1.1  christos     echo_i "timed out waiting for 'rndc dumpdb' to finish"
    466      1.1  christos     __ret=1
    467      1.1  christos   fi
    468      1.1  christos 
    469      1.1  christos   return ${__ret}
    470      1.1  christos }
    471      1.1  christos 
    472      1.1  christos # get_dig_xfer_stats: extract transfer statistics from dig output stored
    473      1.1  christos # in $1, converting them to a format used by some system tests.
    474      1.1  christos get_dig_xfer_stats() {
    475      1.1  christos   LOGFILE="$1"
    476      1.1  christos   sed -n "s/^;; XFR size: .*messages \([0-9][0-9]*\).*/messages=\1/p" "${LOGFILE}"
    477      1.1  christos   sed -n "s/^;; XFR size: \([0-9][0-9]*\) records.*/records=\1/p" "${LOGFILE}"
    478      1.1  christos   sed -n "s/^;; XFR size: .*bytes \([0-9][0-9]*\).*/bytes=\1/p" "${LOGFILE}"
    479      1.1  christos }
    480      1.1  christos 
    481      1.1  christos # get_named_xfer_stats: from named log file $1, extract transfer
    482      1.1  christos # statistics for the last transfer for peer $2 and zone $3 (from a log
    483      1.1  christos # message which has to contain the string provided in $4), converting
    484      1.1  christos # them to a format used by some system tests.
    485      1.1  christos get_named_xfer_stats() {
    486      1.1  christos   LOGFILE="$1"
    487      1.1  christos   PEER="$(echo $2 | sed 's/\./\\./g')"
    488      1.1  christos   ZONE="$(echo $3 | sed 's/\./\\./g')"
    489      1.1  christos   MESSAGE="$4"
    490      1.1  christos   grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" \
    491      1.1  christos     | sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) messages.*/messages=\1/p" | tail -1
    492      1.1  christos   grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" \
    493      1.1  christos     | sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) records.*/records=\1/p" | tail -1
    494      1.1  christos   grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" \
    495      1.1  christos     | sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) bytes.*/bytes=\1/p" | tail -1
    496      1.1  christos }
    497      1.1  christos 
    498      1.1  christos grep_v() { grep -v "$@" || test $? = 1; }
    499