LCOV - code coverage report
Current view: top level - testing - test_exchange_api_age_restriction.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 68 68
Test Date: 2026-04-14 15:39:31 Functions: 100.0 % 2 2

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   Copyright (C) 2023 Taler Systems SA
       4              : 
       5              :   TALER is free software; you can redistribute it and/or modify
       6              :   it under the terms of the GNU General Public License as
       7              :   published by the Free Software Foundation; either version 3, or
       8              :   (at your option) any later version.
       9              : 
      10              :   TALER is distributed in the hope that it will be useful, but
      11              :   WITHOUT ANY WARRANTY; without even the implied warranty of
      12              :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13              :   GNU General Public License for more details.
      14              : 
      15              :   You should have received a copy of the GNU General Public
      16              :   License along with TALER; see the file COPYING.  If not, see
      17              :   <http://www.gnu.org/licenses/>
      18              : */
      19              : /**
      20              :  * @file testing/test_exchange_api_age_restriction.c
      21              :  * @brief testcase to test exchange's age-restrictrition related HTTP API interfaces
      22              :  * @author Özgür Kesim
      23              :  */
      24              : #include "taler/taler_util.h"
      25              : #include "taler/taler_json_lib.h"
      26              : #include <gnunet/gnunet_util_lib.h>
      27              : #include <gnunet/gnunet_testing_lib.h>
      28              : #include <microhttpd.h>
      29              : #include "taler/taler_bank_service.h"
      30              : #include "taler/taler_testing_lib.h"
      31              : #include "taler/taler_extensions.h"
      32              : 
      33              : /**
      34              :  * Configuration file we use.  One (big) configuration is used
      35              :  * for the various components for this test.
      36              :  */
      37              : static char *config_file;
      38              : 
      39              : /**
      40              :  * Our credentials.
      41              :  */
      42              : static struct TALER_TESTING_Credentials cred;
      43              : 
      44              : /**
      45              :  * Some tests behave differently when using CS as we cannot
      46              :  * reuse the coin private key for different denominations
      47              :  * due to the derivation of it with the /csr values. Hence
      48              :  * some tests behave differently in CS mode, hence this
      49              :  * flag.
      50              :  */
      51              : static bool uses_cs;
      52              : 
      53              : /**
      54              :  * Execute the taler-exchange-wirewatch command with
      55              :  * our configuration file.
      56              :  *
      57              :  * @param label label to use for the command.
      58              :  */
      59              : #define CMD_EXEC_WIREWATCH(label) \
      60              :         TALER_TESTING_cmd_exec_wirewatch2 (label, config_file, \
      61              :                                            "exchange-account-2")
      62              : 
      63              : /**
      64              :  * Execute the taler-exchange-aggregator, closer and transfer commands with
      65              :  * our configuration file.
      66              :  *
      67              :  * @param label label to use for the command.
      68              :  */
      69              : #define CMD_EXEC_AGGREGATOR(label) \
      70              :         TALER_TESTING_cmd_sleep ("sleep-before-aggregator", 2), \
      71              :         TALER_TESTING_cmd_exec_aggregator (label "-aggregator", config_file), \
      72              :         TALER_TESTING_cmd_exec_transfer (label "-transfer", config_file)
      73              : 
      74              : 
      75              : /**
      76              :  * Run wire transfer of funds from some user's account to the
      77              :  * exchange.
      78              :  *
      79              :  * @param label label to use for the command.
      80              :  * @param amount amount to transfer, i.e. "EUR:1"
      81              :  */
      82              : #define CMD_TRANSFER_TO_EXCHANGE(label,amount) \
      83              :         TALER_TESTING_cmd_admin_add_incoming (label, amount, \
      84              :                                               &cred.ba,                \
      85              :                                               cred.user42_payto)
      86              : 
      87              : /**
      88              :  * Main function that will tell the interpreter what commands to
      89              :  * run.
      90              :  *
      91              :  * @param cls closure
      92              :  * @param is interpreter we use to run commands
      93              :  */
      94              : static void
      95            2 : run (void *cls,
      96              :      struct TALER_TESTING_Interpreter *is)
      97              : {
      98              :   /**
      99              :    * Test withdrawal with age restriction.  Success is expected (because the
     100              :    * amount is below the kyc threshold ), so it MUST be
     101              :    * called _after_ TALER_TESTING_cmd_exec_offline_sign_extensions is called,
     102              :    * i. e. age restriction is activated in the exchange!
     103              :    *
     104              :    * FIXME: create a test that tries to withdraw coins with age restriction but
     105              :    * (expectedly) fails because the exchange doesn't support age restriction
     106              :    * yet.
     107              :    */
     108              :   struct TALER_TESTING_Command withdraw_age[] = {
     109              :     /**
     110              :      * Move money to the exchange's bank account.
     111              :      */
     112            2 :     CMD_TRANSFER_TO_EXCHANGE (
     113              :       "create-reserve-age",
     114              :       "EUR:6.01"),
     115            2 :     TALER_TESTING_cmd_check_bank_admin_transfer (
     116              :       "check-create-reserve-age",
     117              :       "EUR:6.01",
     118              :       cred.user42_payto,
     119              :       cred.exchange_payto,
     120              :       "create-reserve-age"),
     121              :     /**
     122              :      * Make a reserve exist, according to the previous
     123              :      * transfer.
     124              :      */
     125            2 :     CMD_EXEC_WIREWATCH ("wirewatch-age"),
     126              :     /**
     127              :      * Withdraw EUR:5.
     128              :      */
     129            2 :     TALER_TESTING_cmd_withdraw_amount (
     130              :       "withdraw-coin-age-1",
     131              :       "create-reserve-age",
     132              :       "EUR:5",
     133              :       13,
     134              :       MHD_HTTP_OK),
     135              :     /**
     136              :      * Idempotent withdrawal.
     137              :      */
     138            2 :     TALER_TESTING_cmd_withdraw_amount_reuse_all_secrets (
     139              :       "withdraw-coin-age-idem-1",
     140              :       "create-reserve-age",
     141              :       "EUR:5",
     142              :       13,
     143              :       "withdraw-coin-age-1",
     144              :       MHD_HTTP_OK),
     145              : 
     146            2 :     TALER_TESTING_cmd_end ()
     147              :   };
     148              : 
     149              :   struct TALER_TESTING_Command spend_age[] = {
     150              :     /**
     151              :      * Spend the coin.
     152              :      */
     153            2 :     TALER_TESTING_cmd_set_var (
     154              :       "account-priv",
     155              :       TALER_TESTING_cmd_deposit (
     156              :         "deposit-simple-age-fail-kyc",
     157              :         "withdraw-coin-age-1",
     158              :         0,
     159              :         cred.user42_payto,
     160              :         "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}",
     161            2 :         GNUNET_TIME_UNIT_ZERO,
     162              :         "EUR:4.99",
     163              :         MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS)),
     164            2 :     TALER_TESTING_cmd_admin_add_kycauth (
     165              :       "kyc-auth-transfer",
     166              :       "EUR:0.01",
     167              :       &cred.ba,
     168              :       cred.user42_payto,
     169              :       "deposit-simple-age-fail-kyc"),
     170            2 :     TALER_TESTING_cmd_admin_add_kycauth (
     171              :       "kyc-auth-transfer",
     172              :       "EUR:0.01",
     173              :       &cred.ba,
     174              :       cred.user43_payto,
     175              :       "deposit-simple-age-fail-kyc"),
     176            2 :     CMD_EXEC_WIREWATCH (
     177              :       "import-kyc-account-withdraw"),
     178            2 :     TALER_TESTING_cmd_deposit (
     179              :       "deposit-simple-age",
     180              :       "withdraw-coin-age-1",
     181              :       0,
     182              :       cred.user42_payto,
     183              :       "{\"items\":[{\"name\":\"ice cream\",\"value\":2}]}",
     184            2 :       GNUNET_TIME_UNIT_ZERO,
     185              :       "EUR:4.99",
     186              :       MHD_HTTP_OK),
     187            2 :     TALER_TESTING_cmd_deposit_replay (
     188              :       "deposit-simple-replay-age",
     189              :       "deposit-simple-age",
     190              :       MHD_HTTP_OK),
     191            2 :     TALER_TESTING_cmd_end ()
     192              :   };
     193              : 
     194              :   struct TALER_TESTING_Command refresh_age[] = {
     195              :     /* Fill reserve with EUR:5, 1ct is for fees. */
     196            2 :     CMD_TRANSFER_TO_EXCHANGE (
     197              :       "refresh-create-reserve-age-1",
     198              :       "EUR:6.01"),
     199            2 :     TALER_TESTING_cmd_check_bank_admin_transfer (
     200              :       "ck-refresh-create-reserve-age-1",
     201              :       "EUR:6.01",
     202              :       cred.user42_payto,
     203              :       cred.exchange_payto,
     204              :       "refresh-create-reserve-age-1"),
     205              :     /**
     206              :      * Make previous command effective.
     207              :      */
     208            2 :     CMD_EXEC_WIREWATCH ("wirewatch-age-2"),
     209              :     /**
     210              :      * Withdraw EUR:5 with age restriction for age 13.
     211              :      */
     212            2 :     TALER_TESTING_cmd_withdraw_amount (
     213              :       "refresh-withdraw-coin-age-1",
     214              :       "refresh-create-reserve-age-1",
     215              :       "EUR:5",
     216              :       13,
     217              :       MHD_HTTP_OK),
     218              :     /* Try to partially spend (deposit) 1 EUR of the 5 EUR coin
     219              :      * (in full) (merchant would receive EUR:0.99 due to 1 ct
     220              :      * deposit fee)
     221              :      */
     222            2 :     TALER_TESTING_cmd_deposit (
     223              :       "refresh-deposit-partial-age",
     224              :       "refresh-withdraw-coin-age-1",
     225              :       0,
     226              :       cred.user42_payto,
     227              :       "{\"items\":[{\"name\":\"ice cream\",\"value\":\"EUR:3\"}]}",
     228            2 :       GNUNET_TIME_UNIT_ZERO,
     229              :       "EUR:1",
     230              :       MHD_HTTP_OK),
     231              :     /**
     232              :      * Melt the rest of the coin's value
     233              :      * (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */
     234            2 :     TALER_TESTING_cmd_melt_double (
     235              :       "refresh-melt-age-1",
     236              :       "refresh-withdraw-coin-age-1",
     237              :       MHD_HTTP_OK,
     238              :       NULL),
     239              :     /**
     240              :      * Complete (successful) melt operation, and
     241              :      * withdraw the coins
     242              :      */
     243            2 :     TALER_TESTING_cmd_melt_reveal (
     244              :       "refresh-reveal-age-1",
     245              :       "refresh-melt-age-1",
     246              :       MHD_HTTP_OK),
     247              :     /**
     248              :      * Do it again to check idempotency
     249              :      */
     250            2 :     TALER_TESTING_cmd_melt_reveal (
     251              :       "refresh-reveal-age-1-idempotency",
     252              :       "refresh-melt-age-1",
     253              :       MHD_HTTP_OK),
     254              :     /**
     255              :      * Try to spend a refreshed EUR:1 coin
     256              :      */
     257            2 :     TALER_TESTING_cmd_deposit (
     258              :       "refresh-deposit-refreshed-age-1a",
     259              :       "refresh-reveal-age-1-idempotency",
     260              :       0,
     261              :       cred.user42_payto,
     262              :       "{\"items\":[{\"name\":\"ice cream\",\"value\":4}]}",
     263            2 :       GNUNET_TIME_UNIT_ZERO,
     264              :       "EUR:1",
     265              :       MHD_HTTP_OK),
     266              :     /**
     267              :      * Try to spend a refreshed EUR:0.1 coin
     268              :      */
     269            2 :     TALER_TESTING_cmd_deposit (
     270              :       "refresh-deposit-refreshed-age-1b",
     271              :       "refresh-reveal-age-1",
     272              :       3,
     273              :       cred.user43_payto,
     274              :       "{\"items\":[{\"name\":\"ice cream\",\"value\":5}]}",
     275            2 :       GNUNET_TIME_UNIT_ZERO,
     276              :       "EUR:0.1",
     277              :       MHD_HTTP_OK),
     278              :     /* Test running a failing melt operation (same operation
     279              :      * again must fail) */
     280            2 :     TALER_TESTING_cmd_melt (
     281              :       "refresh-melt-failing-age",
     282              :       "refresh-withdraw-coin-age-1",
     283              :       MHD_HTTP_CONFLICT,
     284              :       NULL),
     285              :     /* Test running a failing melt operation (on a coin that
     286              :        was itself revealed and subsequently deposited) */
     287            2 :     TALER_TESTING_cmd_melt (
     288              :       "refresh-melt-failing-age-2",
     289              :       "refresh-reveal-age-1",
     290              :       MHD_HTTP_CONFLICT,
     291              :       NULL),
     292            2 :     TALER_TESTING_cmd_end ()
     293              :   };
     294              : 
     295              :   /**
     296              :    * Test with age-withdraw, after kyc process has set a birthdate
     297              :    */
     298              :   struct TALER_TESTING_Command age_withdraw[] = {
     299            2 :     CMD_TRANSFER_TO_EXCHANGE (
     300              :       "create-reserve-kyc-1",
     301              :       "EUR:30.02"),
     302            2 :     TALER_TESTING_cmd_check_bank_admin_transfer (
     303              :       "check-create-reserve-kyc-1",
     304              :       "EUR:30.02",
     305              :       cred.user42_payto,
     306              :       cred.exchange_payto,
     307              :       "create-reserve-kyc-1"),
     308            2 :     CMD_EXEC_WIREWATCH ("wirewatch-age-withdraw-1"),
     309            2 :     TALER_TESTING_cmd_withdraw_amount (
     310              :       "withdraw-coin-1-lacking-kyc",
     311              :       "create-reserve-kyc-1",
     312              :       "EUR:10",
     313              :       0,    /* age restriction off */
     314              :       MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS),
     315            2 :     TALER_TESTING_cmd_admin_add_kycauth (
     316              :       "setup-account-key",
     317              :       "EUR:0.01",
     318              :       &cred.ba,
     319              :       cred.user42_payto,
     320              :       NULL /* create new key */),
     321            2 :     CMD_EXEC_WIREWATCH (
     322              :       "import-kyc-account"),
     323            2 :     TALER_TESTING_cmd_check_kyc_get (
     324              :       "check-kyc-withdraw",
     325              :       "withdraw-coin-1-lacking-kyc",
     326              :       "setup-account-key",
     327              :       TALER_EXCHANGE_KLPT_KYC_AUTH_TRANSFER,
     328              :       MHD_HTTP_ACCEPTED),
     329            2 :     TALER_TESTING_cmd_get_kyc_info (
     330              :       "get-kyc-info",
     331              :       "check-kyc-withdraw",
     332              :       MHD_HTTP_OK),
     333            2 :     TALER_TESTING_cmd_post_kyc_start (
     334              :       "start-kyc-process",
     335              :       "get-kyc-info",
     336              :       0,
     337              :       MHD_HTTP_OK),
     338            2 :     TALER_TESTING_cmd_proof_kyc_oauth2 (
     339              :       "proof-withdraw-kyc",
     340              :       "withdraw-coin-1-lacking-kyc",
     341              :       "test-oauth2",
     342              :       "pass",
     343              :       MHD_HTTP_SEE_OTHER),
     344            2 :     TALER_TESTING_cmd_withdraw_amount (
     345              :       "withdraw-coin-1-with-kyc",
     346              :       "create-reserve-kyc-1",
     347              :       "EUR:10",
     348              :       0,   /* age restriction off */
     349              :       MHD_HTTP_CONFLICT),
     350            2 :     TALER_TESTING_cmd_withdraw_with_age_proof (
     351              :       "age-withdraw-coin-1-too-low",
     352              :       "create-reserve-kyc-1",
     353              :       18,      /* Too high */
     354              :       MHD_HTTP_CONFLICT,
     355              :       "EUR:10",
     356              :       NULL),
     357            2 :     TALER_TESTING_cmd_withdraw_with_age_proof (
     358              :       "age-withdraw-coins-1",
     359              :       "create-reserve-kyc-1",
     360              :       8,
     361              :       MHD_HTTP_CREATED,
     362              :       "EUR:10",
     363              :       "EUR:10",
     364              :       "EUR:5",
     365              :       NULL),
     366            2 :     TALER_TESTING_cmd_withdraw_reveal_age_proof (
     367              :       "age-withdraw-coins-reveal-1",
     368              :       "age-withdraw-coins-1",
     369              :       MHD_HTTP_OK),
     370            2 :     TALER_TESTING_cmd_end (),
     371              :   };
     372              : 
     373              :   {
     374              :     struct TALER_TESTING_Command commands[] = {
     375            2 :       TALER_TESTING_cmd_run_fakebank (
     376              :         "run-fakebank",
     377            2 :         cred.cfg,
     378              :         "exchange-account-2"),
     379            2 :       TALER_TESTING_cmd_system_start (
     380              :         "start-taler",
     381              :         config_file,
     382              :         "-e",
     383              :         NULL),
     384            2 :       TALER_TESTING_cmd_get_exchange (
     385              :         "get-exchange",
     386            2 :         cred.cfg,
     387              :         NULL,
     388              :         true,
     389              :         true),
     390            2 :       TALER_TESTING_cmd_oauth_with_birthdate (
     391              :         "oauth-service-with-birthdate",
     392              :         "2015-00-00",    /* enough for a while */
     393              :         6666),
     394            2 :       TALER_TESTING_cmd_batch ("withdraw-age",
     395              :                                withdraw_age),
     396            2 :       TALER_TESTING_cmd_batch ("spend-age",
     397              :                                spend_age),
     398            2 :       TALER_TESTING_cmd_batch ("refresh-age",
     399              :                                refresh_age),
     400            2 :       TALER_TESTING_cmd_batch ("age-withdraw",
     401              :                                age_withdraw),
     402              :       /* End the suite. */
     403            2 :       TALER_TESTING_cmd_end ()
     404              :     };
     405              : 
     406              :     (void) cls;
     407            2 :     TALER_TESTING_run (is,
     408              :                        commands);
     409              :   }
     410            2 : }
     411              : 
     412              : 
     413              : int
     414            2 : main (int argc,
     415              :       char *const *argv)
     416              : {
     417              :   (void) argc;
     418              :   {
     419              :     char *cipher;
     420              : 
     421            2 :     cipher = GNUNET_STRINGS_get_suffix_from_binary_name (argv[0]);
     422            2 :     GNUNET_assert (NULL != cipher);
     423            2 :     uses_cs = (0 == strcmp (cipher,
     424            2 :                             "cs"));
     425            2 :     GNUNET_asprintf (
     426              :       &config_file,
     427              :       "test_exchange_api_age_restriction-%s.conf",
     428              :       cipher);
     429            2 :     GNUNET_free (cipher);
     430              :   }
     431            2 :   return TALER_TESTING_main (
     432              :     argv,
     433              :     "INFO",
     434              :     config_file,
     435              :     "exchange-account-2",
     436              :     TALER_TESTING_BS_FAKEBANK,
     437              :     &cred,
     438              :     &run,
     439              :     NULL);
     440              : }
     441              : 
     442              : 
     443              : /* end of test_exchange_api_age_restriction.c */
        

Generated by: LCOV version 2.0-1