exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

test-kyc.sh (24795B)


      1 #!/bin/bash
      2 #
      3 #  This file is part of TALER
      4 #  Copyright (C) 2014-2023 Taler Systems SA
      5 #
      6 #  TALER is free software; you can redistribute it and/or modify it under the
      7 #  terms of the GNU General Public License as published by the Free Software
      8 #  Foundation; either version 3, or (at your option) any later version.
      9 #
     10 #  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     11 #  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     12 #  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     13 #
     14 #  You should have received a copy of the GNU General Public License along with
     15 #  TALER; see the file COPYING.  If not, If not, see <http://www.gnu.org/license>
     16 #
     17 #
     18 # shellcheck disable=SC2317
     19 # shellcheck disable=SC1091
     20 #
     21 #
     22 # Setup database which was generated from a perfectly normal
     23 # exchange-wallet interaction with KYC enabled and transactions
     24 # blocked due to KYC and run the auditor against it.
     25 #
     26 # Check that the auditor report is as expected.
     27 #
     28 # Requires 'jq' tool and Postgres superuser rights!
     29 #
     30 set -eu
     31 #set -x
     32 
     33 # Set of numbers for all the testcases.
     34 # When adding new tests, increase the last number:
     35 ALL_TESTS=$(seq 0 1)
     36 
     37 # $TESTS determines which tests we should run.
     38 # This construction is used to make it easy to
     39 # only run a subset of the tests. To only run a subset,
     40 # pass the numbers of the tests to run as the FIRST
     41 # argument to test-kyc.sh, i.e.:
     42 #
     43 # $ test-kyc.sh "1 3"
     44 #
     45 # to run tests 1 and 3 only.  By default, all tests are run.
     46 #
     47 TESTS=${1:-$ALL_TESTS}
     48 
     49 # Global variable to run the auditor processes under valgrind
     50 # VALGRIND=valgrind
     51 VALGRIND=""
     52 
     53 # Number of seconds to let libeuifn background
     54 # tasks apply a cycle of payment submission and
     55 # history request.
     56 LIBEUFIN_SETTLE_TIME=1
     57 
     58 . setup.sh
     59 
     60 
     61 # Cleanup exchange and libeufin between runs.
     62 function cleanup()
     63 {
     64     if test ! -z "${EPID:-}"
     65     then
     66         echo -n "Stopping exchange $EPID..."
     67         kill -TERM "$EPID"
     68         wait "$EPID" || true
     69         echo "DONE"
     70         unset EPID
     71     fi
     72     stop_libeufin
     73 }
     74 
     75 # Cleanup to run whenever we exit
     76 function exit_cleanup()
     77 {
     78     echo "Running exit-cleanup"
     79     if test ! -z "${POSTGRES_PATH:-}"
     80     then
     81         echo "Stopping Postgres at ${POSTGRES_PATH}"
     82         "${POSTGRES_PATH}/pg_ctl" \
     83                         -D "$TMPDIR" \
     84                         -l /dev/null \
     85                         stop \
     86             &> /dev/null \
     87             || true
     88     fi
     89     cleanup
     90     for n in $(jobs -p)
     91     do
     92         kill "$n" 2> /dev/null || true
     93     done
     94     wait || true
     95     echo "DONE"
     96 }
     97 
     98 # Install cleanup handler (except for kill -9)
     99 trap exit_cleanup EXIT
    100 
    101 
    102 
    103 # Operations to run before the actual audit
    104 function pre_audit () {
    105     # Launch bank
    106     echo -n "Launching bank"
    107     launch_libeufin
    108     for n in $(seq 1 80)
    109     do
    110         echo -n "."
    111         sleep 0.1
    112         OK=1
    113         wget http://localhost:18082/ \
    114              -o /dev/null \
    115              -O /dev/null \
    116              >/dev/null \
    117             && break
    118         OK=0
    119     done
    120     if [ 1 != "$OK" ]
    121     then
    122         exit_skip "Failed to launch Sandbox"
    123     fi
    124     sleep "$LIBEUFIN_SETTLE_TIME"
    125     for n in $(seq 1 80)
    126     do
    127         echo -n "."
    128         sleep 0.1
    129         OK=1
    130         wget http://localhost:8082/ \
    131              -o /dev/null \
    132              -O /dev/null \
    133              >/dev/null \
    134             && break
    135         OK=0
    136     done
    137     if [ 1 != "$OK" ]
    138     then
    139         exit_skip "Failed to launch Nexus"
    140     fi
    141     echo " DONE"
    142     if test "${1:-no}" = "aggregator"
    143     then
    144         echo -n "Running exchange aggregator ..."
    145         taler-exchange-aggregator \
    146             -y \
    147             -L "INFO" \
    148             -t \
    149             -c "$CONF" \
    150             2> "${MY_TMP_DIR}/aggregator.log" \
    151             || exit_fail "FAIL"
    152         echo " DONE"
    153         echo -n "Running exchange closer ..."
    154         taler-exchange-closer \
    155             -L "INFO" \
    156             -t \
    157             -c "$CONF" \
    158             2> "${MY_TMP_DIR}/closer.log" \
    159             || exit_fail "FAIL"
    160         echo " DONE"
    161         echo -n "Running exchange transfer ..."
    162         taler-exchange-transfer \
    163             -L "INFO" \
    164             -t \
    165             -c "$CONF" \
    166             2> "${MY_TMP_DIR}/transfer.log" \
    167             || exit_fail "FAIL"
    168         echo " DONE"
    169     fi
    170 }
    171 
    172 # actual audit run
    173 function audit_only () {
    174     # Run the auditor!
    175     echo -n "Running audit(s) ..."
    176 
    177     # Restart so that first run is always fresh, and second one is incremental
    178     taler-auditor-dbinit \
    179         -r \
    180         -c "$CONF"
    181     $VALGRIND taler-helper-auditor-aggregation \
    182               -L DEBUG \
    183               -c "$CONF" \
    184               -m "$MASTER_PUB" \
    185               > test-audit-aggregation.json \
    186               2> "${MY_TMP_DIR}/test-audit-aggregation.log" \
    187         || exit_fail "aggregation audit failed"
    188     echo -n "."
    189     $VALGRIND taler-helper-auditor-aggregation \
    190               -L DEBUG \
    191               -c "$CONF" \
    192               -m "$MASTER_PUB" \
    193               > test-audit-aggregation-inc.json \
    194               2> "${MY_TMP_DIR}/test-audit-aggregation-inc.log" \
    195         || exit_fail "incremental aggregation audit failed"
    196     echo -n "."
    197     $VALGRIND taler-helper-auditor-coins \
    198               -L DEBUG \
    199               -c "$CONF" \
    200               -m "$MASTER_PUB" \
    201               > test-audit-coins.json \
    202               2> "${MY_TMP_DIR}/test-audit-coins.log" \
    203         || exit_fail "coin audit failed"
    204     echo -n "."
    205     $VALGRIND taler-helper-auditor-coins \
    206               -L DEBUG  \
    207               -c "$CONF" \
    208               -m "$MASTER_PUB" \
    209               > test-audit-coins-inc.json \
    210               2> "${MY_TMP_DIR}/test-audit-coins-inc.log" \
    211         || exit_fail "incremental coin audit failed"
    212     echo -n "."
    213     $VALGRIND taler-helper-auditor-deposits \
    214               -L DEBUG \
    215               -c "$CONF" \
    216               -m "$MASTER_PUB" \
    217               > test-audit-deposits.json \
    218               2> "${MY_TMP_DIR}/test-audit-deposits.log" \
    219         || exit_fail "deposits audit failed"
    220     echo -n "."
    221     $VALGRIND taler-helper-auditor-deposits \
    222               -L DEBUG \
    223               -c "$CONF" \
    224               -m "$MASTER_PUB" \
    225               > test-audit-deposits-inc.json \
    226               2> "${MY_TMP_DIR}/test-audit-deposits-inc.log" \
    227         || exit_fail "incremental deposits audit failed"
    228     echo -n "."
    229     $VALGRIND taler-helper-auditor-reserves \
    230               -i \
    231               -L DEBUG \
    232               -c "$CONF" \
    233               -m "$MASTER_PUB" \
    234               > test-audit-reserves.json \
    235               2> "${MY_TMP_DIR}/test-audit-reserves.log" \
    236         || exit_fail "reserves audit failed"
    237     echo -n "."
    238     $VALGRIND taler-helper-auditor-reserves \
    239               -i \
    240               -L DEBUG \
    241               -c "$CONF" \
    242               -m "$MASTER_PUB" \
    243               > test-audit-reserves-inc.json \
    244               2> "${MY_TMP_DIR}/test-audit-reserves-inc.log" \
    245         || exit_fail "incremental reserves audit failed"
    246     echo -n "."
    247     rm -f "${MY_TMP_DIR}/test-wire-audit.log"
    248     thaw() {
    249         $VALGRIND taler-helper-auditor-wire \
    250                   -i \
    251                   -L DEBUG \
    252                   -c "$CONF" \
    253                   -m "$MASTER_PUB" \
    254                   > test-audit-wire.json \
    255                   2>> "${MY_TMP_DIR}/test-wire-audit.log"
    256     }
    257     thaw || ( echo -e " FIRST CALL TO taler-helper-auditor-wire FAILED,\nRETRY AFTER TWO SECONDS..." | tee -a "${MY_TMP_DIR}/test-wire-audit.log"
    258 	      sleep 2
    259 	      thaw || exit_fail "wire audit failed" )
    260     echo -n "."
    261     $VALGRIND taler-helper-auditor-wire \
    262               -i \
    263               -L DEBUG \
    264               -c "$CONF" \
    265               -m "$MASTER_PUB" \
    266               > test-audit-wire-inc.json \
    267               2> "${MY_TMP_DIR}/test-wire-audit-inc.log" \
    268         || exit_fail "wire audit inc failed"
    269     echo -n "."
    270 
    271     echo " DONE"
    272 }
    273 
    274 
    275 # Cleanup to run after the auditor
    276 function post_audit () {
    277     taler-exchange-dbinit \
    278         -c "$CONF" \
    279         -g \
    280         || exit_fail "exchange DB GC failed"
    281     cleanup
    282     echo " DONE"
    283 }
    284 
    285 
    286 # Run audit process on current database, including report
    287 # generation.  Pass "aggregator" as $1 to run
    288 # $ taler-exchange-aggregator
    289 # before auditor (to trigger pending wire transfers).
    290 # Pass "drain" as $2 to run a drain operation as well.
    291 function run_audit () {
    292     pre_audit "${1:-no}"
    293     if test "${2:-no}" = "drain"
    294     then
    295         echo -n "Starting exchange..."
    296         taler-exchange-httpd \
    297             -c "${CONF}" \
    298             -L INFO \
    299             2> "${MY_TMP_DIR}/exchange-httpd-drain.err" &
    300         EPID=$!
    301 
    302         # Wait for all services to be available
    303         for n in $(seq 1 50)
    304         do
    305             echo -n "."
    306             sleep 0.1
    307             OK=0
    308             # exchange
    309             wget "http://localhost:8081/seed" \
    310                  -o /dev/null \
    311                  -O /dev/null \
    312                  >/dev/null \
    313                 || continue
    314             OK=1
    315             break
    316         done
    317         echo "... DONE."
    318         export CONF
    319 
    320         echo -n "Running taler-exchange-offline drain "
    321 
    322         taler-exchange-offline \
    323             -L DEBUG \
    324             -c "${CONF}" \
    325             drain TESTKUDOS:0.1 \
    326             exchange-account-1 payto://iban/DE360679?receiver-name=Exchange+Drain \
    327             upload \
    328             2> "${MY_TMP_DIR}/taler-exchange-offline-drain.log" \
    329             || exit_fail "offline draining failed"
    330         kill -TERM "$EPID"
    331         wait "$EPID" || true
    332         unset EPID
    333         echo -n "Running taler-exchange-drain ..."
    334         printf "\n" | taler-exchange-drain \
    335                         -L DEBUG \
    336                         -c "$CONF" \
    337                         2> "${MY_TMP_DIR}/taler-exchange-drain.log" \
    338             || exit_fail "FAIL"
    339         echo " DONE"
    340    fi
    341     echo -n "Running taler-exchange-transfer ..."
    342     taler-exchange-transfer \
    343         -L INFO \
    344         -t \
    345         -c "$CONF" \
    346         2> "${MY_TMP_DIR}/drain-transfer.log" \
    347         || exit_fail "FAIL"
    348     echo " DONE"
    349 
    350     audit_only
    351     post_audit
    352 }
    353 
    354 
    355 # Do a full reload of the (original) database
    356 function full_reload()
    357 {
    358     echo -n "Doing full reload of the database (loading ${BASEDB}.sql into $DB at ${PGHOST:-})... "
    359     dropdb "$DB" 2> /dev/null || true
    360     createdb -T template0 "$DB" \
    361         || exit_skip "could not create database $DB (at ${PGHOST:-})"
    362     # Import pre-generated database, -q(ietly) using single (-1) transaction
    363     psql -Aqt "$DB" \
    364          -q \
    365          -1 \
    366          -f "${BASEDB}.sql" \
    367          > /dev/null \
    368         || exit_skip "Failed to load database $DB from ${BASEDB}.sql"
    369     echo "DONE"
    370     # Technically, this call shouldn't be needed as libeufin should already be stopped here...
    371     stop_libeufin
    372 }
    373 
    374 
    375 function test_0() {
    376 
    377     echo "===========0: normal run with aggregator==========="
    378     run_audit aggregator
    379     echo "Checking output"
    380     # if an emergency was detected, that is a bug and we should fail
    381     echo -n "Test for emergencies... "
    382     jq -e .emergencies[0] < test-audit-coins.json > /dev/null && exit_fail "Unexpected emergency detected in ordinary run" || echo PASS
    383     echo -n "Test for deposit confirmation emergencies... "
    384     jq -e .deposit_confirmation_inconsistencies[0] < test-audit-deposits.json > /dev/null && exit_fail "Unexpected deposit confirmation inconsistency detected" || echo PASS
    385     echo -n "Test for emergencies by count... "
    386     jq -e .emergencies_by_count[0] < test-audit-coins.json > /dev/null && exit_fail "Unexpected emergency by count detected in ordinary run" || echo PASS
    387 
    388     echo -n "Test for wire inconsistencies... "
    389     jq -e .wire_out_amount_inconsistencies[0] < test-audit-wire.json > /dev/null && exit_fail "Unexpected wire out inconsistency detected in ordinary run"
    390     jq -e .reserve_in_amount_inconsistencies[0] < test-audit-wire.json > /dev/null && exit_fail "Unexpected reserve in inconsistency detected in ordinary run"
    391     jq -e .misattribution_inconsistencies[0] < test-audit-wire.json > /dev/null && exit_fail "Unexpected misattribution inconsistency detected in ordinary run"
    392     jq -e .row_inconsistencies[0] < test-audit-wire.json > /dev/null && exit_fail "Unexpected row inconsistency detected in ordinary run"
    393     jq -e .denomination_key_validity_withdraw_inconsistencies[0] < test-audit-reserves.json > /dev/null && exit_fail "Unexpected denomination key withdraw inconsistency detected in ordinary run"
    394     jq -e .row_minor_inconsistencies[0] < test-audit-wire.json > /dev/null && exit_fail "Unexpected minor row inconsistency detected in ordinary run"
    395     jq -e .lag_details[0] < test-audit-wire.json > /dev/null && exit_fail "Unexpected lag detected in ordinary run"
    396     jq -e .wire_format_inconsistencies[0] < test-audit-wire.json > /dev/null && exit_fail "Unexpected wire format inconsistencies detected in ordinary run"
    397 
    398 
    399     # TODO: check operation balances are correct (once we have all transaction types and wallet is deterministic)
    400     # TODO: check revenue summaries are correct (once we have all transaction types and wallet is deterministic)
    401 
    402     echo PASS
    403 
    404     LOSS=$(jq -r .total_bad_sig_loss < test-audit-aggregation.json)
    405     if [ "$LOSS" != "TESTKUDOS:0" ]
    406     then
    407         exit_fail "Wrong total bad sig loss from aggregation, got unexpected loss of $LOSS"
    408     fi
    409     LOSS=$(jq -r .irregular_loss < test-audit-coins.json)
    410     if [ "$LOSS" != "TESTKUDOS:0" ]
    411     then
    412         exit_fail "Wrong total bad sig loss from coins, got unexpected loss of $LOSS"
    413     fi
    414     LOSS=$(jq -r .total_bad_sig_loss < test-audit-reserves.json)
    415     if [ "$LOSS" != "TESTKUDOS:0" ]
    416     then
    417         exit_fail "Wrong total bad sig loss from reserves, got unexpected loss of $LOSS"
    418     fi
    419 
    420     echo -n "Test for wire amounts... "
    421     WIRED=$(jq -r .total_wire_in_delta_plus < test-audit-wire.json)
    422     if [ "$WIRED" != "TESTKUDOS:0" ]
    423     then
    424         exit_fail "Expected total wire delta plus wrong, got $WIRED"
    425     fi
    426     WIRED=$(jq -r .total_wire_in_delta_minus < test-audit-wire.json)
    427     if [ "$WIRED" != "TESTKUDOS:0" ]
    428     then
    429         exit_fail "Expected total wire delta minus wrong, got $WIRED"
    430     fi
    431     WIRED=$(jq -r .total_wire_out_delta_plus < test-audit-wire.json)
    432     if [ "$WIRED" != "TESTKUDOS:0" ]
    433     then
    434         exit_fail "Expected total wire delta plus wrong, got $WIRED"
    435     fi
    436     WIRED=$(jq -r .total_wire_out_delta_minus < test-audit-wire.json)
    437     if [ "$WIRED" != "TESTKUDOS:0" ]
    438     then
    439         exit_fail "Expected total wire delta minus wrong, got $WIRED"
    440     fi
    441     WIRED=$(jq -r .total_misattribution_in < test-audit-wire.json)
    442     if [ "$WIRED" != "TESTKUDOS:0" ]
    443     then
    444         exit_fail "Expected total misattribution in wrong, got $WIRED"
    445     fi
    446     echo "PASS"
    447 
    448     echo -n "Checking for unexpected arithmetic differences "
    449     LOSS=$(jq -r .total_arithmetic_delta_plus < test-audit-aggregation.json)
    450     if [ "$LOSS" != "TESTKUDOS:0" ]
    451     then
    452         exit_fail "Wrong arithmetic delta from aggregations, got unexpected plus of $LOSS"
    453     fi
    454     LOSS=$(jq -r .total_arithmetic_delta_minus < test-audit-aggregation.json)
    455     if [ "$LOSS" != "TESTKUDOS:0" ]
    456     then
    457         exit_fail "Wrong arithmetic delta from aggregation, got unexpected minus of $LOSS"
    458     fi
    459     LOSS=$(jq -r .total_arithmetic_delta_plus < test-audit-coins.json)
    460     if [ "$LOSS" != "TESTKUDOS:0" ]
    461     then
    462         exit_fail "Wrong arithmetic delta from coins, got unexpected plus of $LOSS"
    463     fi
    464     LOSS=$(jq -r .total_arithmetic_delta_minus < test-audit-coins.json)
    465     if [ "$LOSS" != "TESTKUDOS:0" ]
    466     then
    467         exit_fail "Wrong arithmetic delta from coins, got unexpected minus of $LOSS"
    468     fi
    469     LOSS=$(jq -r .total_arithmetic_delta_plus < test-audit-reserves.json)
    470     if [ "$LOSS" != "TESTKUDOS:0" ]
    471     then
    472         exit_fail "Wrong arithmetic delta from reserves, got unexpected plus of $LOSS"
    473     fi
    474     LOSS=$(jq -r .total_arithmetic_delta_minus < test-audit-reserves.json)
    475     if [ "$LOSS" != "TESTKUDOS:0" ]
    476     then
    477         exit_fail "Wrong arithmetic delta from reserves, got unexpected minus of $LOSS"
    478     fi
    479 
    480     jq -e .amount_arithmetic_inconsistencies[0] < test-audit-aggregation.json > /dev/null && exit_fail "Unexpected arithmetic inconsistencies from aggregations detected in ordinary run"
    481     jq -e .amount_arithmetic_inconsistencies[0] < test-audit-coins.json > /dev/null && exit_fail "Unexpected arithmetic inconsistencies from coins detected in ordinary run"
    482     jq -e .amount_arithmetic_inconsistencies[0] < test-audit-reserves.json > /dev/null && exit_fail "Unexpected arithmetic inconsistencies from reserves detected in ordinary run"
    483     echo "PASS"
    484 
    485     echo -n "Checking for unexpected wire out differences "
    486     jq -e .wire_out_inconsistencies[0] < test-audit-aggregation.json > /dev/null && exit_fail "Unexpected wire out inconsistencies detected in ordinary run"
    487     echo "PASS"
    488 
    489     # cannot easily undo aggregator, hence full reload
    490     full_reload
    491 
    492 }
    493 
    494 
    495 # Run without aggregator, hence auditor should detect wire
    496 # transfer lag!
    497 function test_1() {
    498 
    499     echo "===========1: normal run==========="
    500     run_audit
    501 
    502     echo "Checking output"
    503     # if an emergency was detected, that is a bug and we should fail
    504     echo -n "Test for emergencies... "
    505     jq -e .emergencies[0] \
    506        < test-audit-coins.json \
    507        > /dev/null \
    508         && exit_fail "Unexpected emergency detected in ordinary run";
    509     echo "PASS"
    510     echo -n "Test for emergencies by count... "
    511     jq -e .emergencies_by_count[0] \
    512        < test-audit-coins.json \
    513        > /dev/null \
    514         && exit_fail "Unexpected emergency by count detected in ordinary run"
    515     echo "PASS"
    516 
    517     echo -n "Test for wire inconsistencies... "
    518     jq -e .wire_out_amount_inconsistencies[0] \
    519        < test-audit-wire.json \
    520        > /dev/null \
    521         && exit_fail "Unexpected wire out inconsistency detected in ordinary run"
    522     jq -e .reserve_in_amount_inconsistencies[0] \
    523        < test-audit-wire.json \
    524        > /dev/null \
    525         && exit_fail "Unexpected reserve in inconsistency detected in ordinary run"
    526     jq -e .misattribution_inconsistencies[0] \
    527        < test-audit-wire.json \
    528        > /dev/null \
    529         && exit_fail "Unexpected misattribution inconsistency detected in ordinary run"
    530     jq -e .row_inconsistencies[0] \
    531        < test-audit-wire.json \
    532        > /dev/null \
    533         && exit_fail "Unexpected row inconsistency detected in ordinary run"
    534     jq -e .row_minor_inconsistencies[0] \
    535        < test-audit-wire.json \
    536        > /dev/null \
    537         && exit_fail "Unexpected minor row inconsistency detected in ordinary run"
    538     jq -e .wire_format_inconsistencies[0] \
    539        < test-audit-wire.json \
    540        > /dev/null \
    541         && exit_fail "Unexpected wire format inconsistencies detected in ordinary run"
    542 
    543     # TODO: check operation balances are correct (once we have all transaction types and wallet is deterministic)
    544     # TODO: check revenue summaries are correct (once we have all transaction types and wallet is deterministic)
    545 
    546     echo "PASS"
    547 
    548     echo -n "Check for lag detection... "
    549 
    550     # Check wire transfer lag reported (no aggregator!)
    551     # NOTE: This test is EXPECTED to fail for ~1h after
    552     # re-generating the test database as we do not
    553     # report lag of less than 1h (see GRACE_PERIOD in
    554     # taler-helper-auditor-wire.c)
    555     jq -e .lag_details[0] \
    556        < test-audit-wire.json \
    557        > /dev/null \
    558         || exit_fail "Lag not detected in run without aggregator"
    559 
    560     LAG=$(jq -r .total_amount_lag < test-audit-wire.json)
    561     if [ "$LAG" = "TESTKUDOS:0" ]
    562     then
    563         exit_fail "Expected total lag to be non-zero"
    564     fi
    565     echo "PASS"
    566 
    567 
    568     echo -n "Test for wire amounts... "
    569     WIRED=$(jq -r .total_wire_in_delta_plus < test-audit-wire.json)
    570     if [ "$WIRED" != "TESTKUDOS:0" ]
    571     then
    572         exit_fail "Expected total wire delta plus wrong, got $WIRED"
    573     fi
    574     WIRED=$(jq -r .total_wire_in_delta_minus < test-audit-wire.json)
    575     if [ "$WIRED" != "TESTKUDOS:0" ]
    576     then
    577         exit_fail "Expected total wire delta minus wrong, got $WIRED"
    578     fi
    579     WIRED=$(jq -r .total_wire_out_delta_plus < test-audit-wire.json)
    580     if [ "$WIRED" != "TESTKUDOS:0" ]
    581     then
    582         exit_fail "Expected total wire delta plus wrong, got $WIRED"
    583     fi
    584     WIRED=$(jq -r .total_wire_out_delta_minus < test-audit-wire.json)
    585     if [ "$WIRED" != "TESTKUDOS:0" ]
    586     then
    587         exit_fail "Expected total wire delta minus wrong, got $WIRED"
    588     fi
    589     WIRED=$(jq -r .total_misattribution_in < test-audit-wire.json)
    590     if [ "$WIRED" != "TESTKUDOS:0" ]
    591     then
    592         exit_fail "Expected total misattribution in wrong, got $WIRED"
    593     fi
    594     # Database was unmodified, no need to undo
    595     echo "OK"
    596 }
    597 
    598 
    599 
    600 # *************** Main test loop starts here **************
    601 
    602 
    603 # Run all the tests against the database given in $1.
    604 # Sets $fail to 0 on success, non-zero on failure.
    605 function check_with_database()
    606 {
    607     BASEDB="$1"
    608     CONF="$1.conf"
    609     echo "Running test suite with database $BASEDB using configuration $CONF"
    610     MASTER_PRIV_FILE="${BASEDB}.mpriv"
    611     taler-exchange-config \
    612         -f \
    613         -c "${CONF}" \
    614         -s exchange-offline \
    615         -o MASTER_PRIV_FILE \
    616         -V "${MASTER_PRIV_FILE}"
    617     MASTER_PUB=$(gnunet-ecc -p "$MASTER_PRIV_FILE")
    618 
    619     echo "MASTER PUB is ${MASTER_PUB} using file ${MASTER_PRIV_FILE}"
    620 
    621     # Load database
    622     full_reload
    623 
    624     # Run test suite
    625     fail=0
    626     for i in $TESTS
    627     do
    628         "test_$i"
    629         if test 0 != $fail
    630         then
    631             break
    632         fi
    633     done
    634     echo "Cleanup (disabled, leaving database $DB behind)"
    635     # dropdb $DB
    636 }
    637 
    638 # If this script is not run as root, create the temporary
    639 # storage space for postgres.
    640 # Sets PGHOST accordingly
    641 function perform_initdb() {
    642     # Available directly in path?
    643     INITDB_BIN=$(command -v initdb) || true
    644     if [[ -n "$INITDB_BIN" ]]; then
    645       echo " FOUND (in path) at $INITDB_BIN"
    646     else
    647         HAVE_INITDB=$(find /usr -name "initdb" | head -1 2> /dev/null | grep postgres) \
    648             || exit_skip " MISSING"
    649       echo " FOUND at $(dirname "$HAVE_INITDB")"
    650       INITDB_BIN=$(echo "$HAVE_INITDB" | grep bin/initdb | grep postgres | sort -n | tail -n1)
    651     fi
    652     POSTGRES_PATH=$(dirname "$INITDB_BIN")
    653 
    654     echo "Using $MY_TMP_DIR for logging and temporary data"
    655     TMPDIR="$MY_TMP_DIR/postgres"
    656     mkdir -p "$TMPDIR"
    657     echo -n "Setting up Postgres DB at $TMPDIR ..."
    658     $INITDB_BIN \
    659         --no-sync \
    660         --auth=trust \
    661         -D "${TMPDIR}" \
    662         > "${MY_TMP_DIR}/postgres-dbinit.log" \
    663         2> "${MY_TMP_DIR}/postgres-dbinit.err"
    664     echo "DONE"
    665     SOCKETDIR="${TMPDIR}/sockets"
    666     mkdir "${SOCKETDIR}"
    667     echo -n "Launching Postgres service"
    668     cat - >> "$TMPDIR/postgresql.conf" <<EOF
    669 unix_socket_directories='${TMPDIR}/sockets'
    670 fsync=off
    671 max_wal_senders=0
    672 synchronous_commit=off
    673 wal_level=minimal
    674 listen_addresses=''
    675 EOF
    676     grep -v host \
    677          < "$TMPDIR/pg_hba.conf" \
    678          > "$TMPDIR/pg_hba.conf.new"
    679     mv "$TMPDIR/pg_hba.conf.new" "$TMPDIR/pg_hba.conf"
    680     "${POSTGRES_PATH}/pg_ctl" \
    681                     -D "$TMPDIR" \
    682                     -l /dev/null \
    683                     start \
    684                     > "${MY_TMP_DIR}/postgres-start.log" \
    685                     2> "${MY_TMP_DIR}/postgres-start.err"
    686     echo " DONE"
    687     PGHOST="$TMPDIR/sockets"
    688     export PGHOST
    689 
    690 }
    691 
    692 
    693 
    694 # *************** Main logic starts here **************
    695 
    696 # ####### Setup globals ######
    697 # Postgres database to use (must match configuration file)
    698 export DB="auditor-basedb"
    699 
    700 # test required commands exist
    701 echo "Testing for jq"
    702 jq -h > /dev/null || exit_skip "jq required"
    703 echo "Testing for faketime"
    704 faketime -h > /dev/null || exit_skip "faketime required"
    705 # NOTE: really check for all three libeufin commands?
    706 echo "Testing for libeufin-bank"
    707 libeufin-bank --help >/dev/null 2> /dev/null </dev/null || exit_skip "libeufin-bank required"
    708 echo "Testing for taler-wallet-cli"
    709 taler-wallet-cli -h >/dev/null </dev/null 2>/dev/null || exit_skip "taler-wallet-cli required"
    710 
    711 MY_TMP_DIR=$(mktemp -d /tmp/taler-auditor-basedbXXXXXX)
    712 
    713 echo -n "Testing for Postgres"
    714 [ $(id -u) == 0 ] || perform_initdb
    715 
    716 MYDIR="${MY_TMP_DIR}/basedb"
    717 mkdir -p "${MYDIR}"
    718 echo "Generating fresh database at $MYDIR"
    719 if faketime -f '-1 d' ./generate-auditor-basedb.sh \
    720             -c generate-kyc-basedb.conf \
    721             -d "$MYDIR/$DB"
    722 then
    723     echo -n "Reset 'auditor-basedb' database at ${PGHOST:-} ..."
    724     dropdb "auditor-basedb" >/dev/null 2>/dev/null || true
    725     createdb "auditor-basedb" || exit_skip "Could not create database '$BASEDB' at ${PGHOST:-}"
    726     echo " DONE"
    727     check_with_database "$MYDIR/$DB"
    728     if [ "$fail" != "0" ]
    729     then
    730         exit "$fail"
    731     fi
    732 else
    733     echo "Generation failed"
    734     exit 1
    735 fi
    736 
    737 exit 0