exchange

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

test-revocation.sh (24530B)


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