merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

test_merchant_high_fee_order.c (5791B)


      1 /*
      2   This file is part of TALER
      3   (C) 2026 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Lesser General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 
     13   You should have received a copy of the GNU General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file src/backend/test_merchant_high_fee_order.c
     18  * @brief unit test for the deposit-fee arithmetic in GET /private/orders/ID
     19  */
     20 #include "platform.h"
     21 #include <gnunet/gnunet_util_lib.h>
     22 #include <taler/taler_json_lib.h>
     23 #include "taler-merchant-httpd_helper.h"
     24 
     25 
     26 /**
     27  * Wrapper around #TMH_compute_expected_transfer that also checks the
     28  * resulting expected total against an expected value.
     29  *
     30  * @param label label for the test case
     31  * @param amount order amount string
     32  * @param refund refund amount string
     33  * @param deposit_fee deposit fee total string
     34  * @param deposit_fee_refunded refunded deposit fee string
     35  * @param max_fee maximum merchant fee string, or NULL
     36  * @param want expected total string (only checked on success)
     37  * @param want_ret expected return value
     38  */
     39 static void
     40 test_case (const char *label,
     41            const char *amount,
     42            const char *refund,
     43            const char *deposit_fee,
     44            const char *deposit_fee_refunded,
     45            const char *max_fee,
     46            const char *want,
     47            enum GNUNET_GenericReturnValue want_ret)
     48 {
     49   struct TALER_Amount contract_amount;
     50   struct TALER_Amount refund_amount;
     51   struct TALER_Amount deposit_fees_total;
     52   struct TALER_Amount deposit_fees_refunded_total;
     53   struct TALER_Amount max_fee_amount;
     54   struct TALER_Amount expected_total;
     55   enum GNUNET_GenericReturnValue ret;
     56 
     57   GNUNET_assert (GNUNET_OK ==
     58                  TALER_string_to_amount (amount,
     59                                          &contract_amount));
     60   GNUNET_assert (GNUNET_OK ==
     61                  TALER_string_to_amount (refund,
     62                                          &refund_amount));
     63   GNUNET_assert (GNUNET_OK ==
     64                  TALER_string_to_amount (deposit_fee,
     65                                          &deposit_fees_total));
     66   GNUNET_assert (GNUNET_OK ==
     67                  TALER_string_to_amount (deposit_fee_refunded,
     68                                          &deposit_fees_refunded_total));
     69   if (NULL != max_fee)
     70     GNUNET_assert (GNUNET_OK ==
     71                    TALER_string_to_amount (max_fee,
     72                                            &max_fee_amount));
     73 
     74   ret = TMH_compute_expected_transfer (
     75     &contract_amount,
     76     &refund_amount,
     77     &deposit_fees_total,
     78     &deposit_fees_refunded_total,
     79     (NULL != max_fee) ? &max_fee_amount : NULL,
     80     NULL != max_fee,
     81     &expected_total);
     82 
     83   if (ret != want_ret)
     84   {
     85     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     86                 "Test '%s': expected return %d, got %d\n",
     87                 label,
     88                 want_ret,
     89                 ret);
     90     GNUNET_assert (0);
     91   }
     92   if (GNUNET_OK == ret)
     93   {
     94     struct TALER_Amount want_total;
     95 
     96     GNUNET_assert (GNUNET_OK ==
     97                    TALER_string_to_amount (want,
     98                                            &want_total));
     99     if (0 != TALER_amount_cmp (&expected_total,
    100                                &want_total))
    101     {
    102       const char *got = TALER_amount2s (&expected_total);
    103 
    104       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    105                   "Test '%s': expected total %s, got %s\n",
    106                   label,
    107                   want,
    108                   got);
    109       GNUNET_assert (0);
    110     }
    111   }
    112 }
    113 
    114 
    115 int
    116 main (int argc,
    117       char *const argv[])
    118 {
    119   (void) argc;
    120   (void) argv;
    121 
    122   test_case ("fee below amount",
    123              "TESTKUDOS:10",
    124              "TESTKUDOS:0",
    125              "TESTKUDOS:1",
    126              "TESTKUDOS:0",
    127              "TESTKUDOS:2",
    128              "TESTKUDOS:9",
    129              GNUNET_OK);
    130 
    131   /* the per-coin deposit fee exceeds
    132      the order amount, but the merchant max_fee caps what the merchant
    133      pays.  Without the max_fee cap this would fail with
    134      deposit fees exceed total. */
    135   test_case ("fee exceeds amount but capped by max_fee",
    136              "TESTKUDOS:1",
    137              "TESTKUDOS:0",
    138              "TESTKUDOS:2",
    139              "TESTKUDOS:0",
    140              "TESTKUDOS:0.2",
    141              "TESTKUDOS:0.8",
    142              GNUNET_OK);
    143 
    144   test_case ("fee exceeds amount with refunded fee",
    145              "TESTKUDOS:1",
    146              "TESTKUDOS:0",
    147              "TESTKUDOS:2",
    148              "TESTKUDOS:0.5",
    149              "TESTKUDOS:0.2",
    150              "TESTKUDOS:0.8",
    151              GNUNET_OK);
    152 
    153   /* Without a max_fee the strict check must still fail when fees exceed
    154      the amount. */
    155   test_case ("fee exceeds amount without max_fee",
    156              "TESTKUDOS:1",
    157              "TESTKUDOS:0",
    158              "TESTKUDOS:2",
    159              "TESTKUDOS:0",
    160              NULL,
    161              NULL,
    162              GNUNET_NO);
    163 
    164   /* Refunded deposit fees must not exceed the total deposit fees. */
    165   test_case ("refunded fees exceed total",
    166              "TESTKUDOS:10",
    167              "TESTKUDOS:0",
    168              "TESTKUDOS:1",
    169              "TESTKUDOS:2",
    170              "TESTKUDOS:2",
    171              NULL,
    172              GNUNET_SYSERR);
    173 
    174   /* Refunds must not exceed the contract value. */
    175   test_case ("refund exceeds contract",
    176              "TESTKUDOS:1",
    177              "TESTKUDOS:2",
    178              "TESTKUDOS:0.1",
    179              "TESTKUDOS:0",
    180              "TESTKUDOS:0.1",
    181              NULL,
    182              GNUNET_SYSERR);
    183 
    184   return 0;
    185 }