LCOV - code coverage report
Current view: top level - lib - test_stefan.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 88.9 % 63 56
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 it under the
       6              :   terms of the GNU 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
      15              :   <http://www.gnu.org/licenses/>
      16              : */
      17              : /**
      18              :  * @file lib/test_stefan.c
      19              :  * @brief test calculations on the STEFAN curve
      20              :  * @author Christian Grothoff
      21              :  */
      22              : #include "taler/taler_json_lib.h"
      23              : #include <gnunet/gnunet_curl_lib.h>
      24              : #include "exchange_api_handle.h"
      25              : 
      26              : 
      27              : /**
      28              :  * Check if @a a and @a b are numerically close.
      29              :  *
      30              :  * @param a an amount
      31              :  * @param b an amount
      32              :  * @return true if both values are quite close
      33              :  */
      34              : static bool
      35        35448 : amount_close (const struct TALER_Amount *a,
      36              :               const struct TALER_Amount *b)
      37              : {
      38              :   struct TALER_Amount delta;
      39              : 
      40        35448 :   switch (TALER_amount_cmp (a,
      41              :                             b))
      42              :   {
      43            0 :   case -1: /* a < b */
      44            0 :     GNUNET_assert (0 <
      45              :                    TALER_amount_subtract (&delta,
      46              :                                           b,
      47              :                                           a));
      48            0 :     break;
      49        18912 :   case 0:
      50              :     /* perfect */
      51        18912 :     return true;
      52        16536 :   case 1: /* a > b */
      53        16536 :     GNUNET_assert (0 <
      54              :                    TALER_amount_subtract (&delta,
      55              :                                           a,
      56              :                                           b));
      57        16536 :     break;
      58              :   }
      59        16536 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
      60              :               "Rounding error is %s\n",
      61              :               TALER_amount2s (&delta));
      62        16536 :   if (delta.value > 0)
      63              :   {
      64            0 :     GNUNET_break (0);
      65            0 :     return false;
      66              :   }
      67        16536 :   if (delta.fraction > 5000)
      68              :   {
      69            0 :     GNUNET_break (0);
      70            0 :     return false;
      71              :   }
      72        16536 :   return true; /* let's consider this a rounding error */
      73              : }
      74              : 
      75              : 
      76              : int
      77            1 : main (int argc,
      78              :       char **argv)
      79              : {
      80              :   struct TALER_EXCHANGE_DenomPublicKey dk;
      81            1 :   struct TALER_EXCHANGE_Keys keys = {
      82              :     .denom_keys = &dk,
      83              :     .num_denom_keys = 1
      84              :   };
      85              :   struct TALER_Amount brut;
      86              :   struct TALER_Amount net;
      87              : 
      88              :   (void) argc;
      89              :   (void) argv;
      90            1 :   GNUNET_log_setup ("test-stefan",
      91              :                     "INFO",
      92              :                     NULL);
      93            1 :   GNUNET_assert (GNUNET_OK ==
      94              :                  TALER_string_to_amount ("MAGIC:0.00001",
      95              :                                          &dk.value));
      96            1 :   GNUNET_assert (GNUNET_OK ==
      97              :                  TALER_string_to_amount ("MAGIC:1",
      98              :                                          &keys.stefan_abs));
      99            1 :   GNUNET_assert (GNUNET_OK ==
     100              :                  TALER_string_to_amount ("MAGIC:0.13",
     101              :                                          &keys.stefan_log));
     102            1 :   keys.stefan_lin = 1.15;
     103            1 :   GNUNET_assert (GNUNET_OK ==
     104              :                  TALER_string_to_amount ("MAGIC:4",
     105              :                                          &brut));
     106            1 :   GNUNET_log_skip (1,
     107              :                    GNUNET_NO);
     108            1 :   GNUNET_assert (GNUNET_SYSERR ==
     109              :                  TALER_EXCHANGE_keys_stefan_b2n (&keys,
     110              :                                                  &brut,
     111              :                                                  &net));
     112            1 :   GNUNET_assert (GNUNET_OK ==
     113              :                  TALER_string_to_amount ("MAGIC:4",
     114              :                                          &net));
     115            1 :   GNUNET_log_skip (1,
     116              :                    GNUNET_NO);
     117            1 :   GNUNET_assert (GNUNET_SYSERR ==
     118              :                  TALER_EXCHANGE_keys_stefan_n2b (&keys,
     119              :                                                  &net,
     120              :                                                  &brut));
     121            1 :   keys.stefan_lin = 1.0;
     122            1 :   GNUNET_assert (GNUNET_OK ==
     123              :                  TALER_string_to_amount ("MAGIC:4",
     124              :                                          &brut));
     125            1 :   GNUNET_log_skip (1,
     126              :                    GNUNET_NO);
     127            1 :   GNUNET_assert (GNUNET_SYSERR ==
     128              :                  TALER_EXCHANGE_keys_stefan_b2n (&keys,
     129              :                                                  &brut,
     130              :                                                  &net));
     131            1 :   GNUNET_assert (GNUNET_OK ==
     132              :                  TALER_string_to_amount ("MAGIC:4",
     133              :                                          &net));
     134            1 :   GNUNET_log_skip (1,
     135              :                    GNUNET_NO);
     136            1 :   GNUNET_assert (GNUNET_SYSERR ==
     137              :                  TALER_EXCHANGE_keys_stefan_n2b (&keys,
     138              :                                                  &net,
     139              :                                                  &brut));
     140            1 :   GNUNET_assert (0 == GNUNET_get_log_skip ());
     141            1 :   keys.stefan_lin = 0.1;
     142              : 
     143              :   /* try various values for lin and log STEFAN values */
     144           13 :   for (unsigned int li = 1; li < 13; li += 1)
     145              :   {
     146           12 :     keys.stefan_lin = 1.0 * li / 100.0;
     147              : 
     148         1200 :     for (unsigned int lx = 1; lx < 100; lx += 1)
     149              :     {
     150         1188 :       keys.stefan_log.fraction = lx * TALER_AMOUNT_FRAC_BASE / 100;
     151              : 
     152              :       /* Check brutto-to-netto is stable */
     153        13068 :       for (unsigned int i = 0; i<10; i++)
     154              :       {
     155              :         struct TALER_Amount rval;
     156              : 
     157        11880 :         brut.value = i;
     158        11880 :         brut.fraction = i * TALER_AMOUNT_FRAC_BASE / 10;
     159        11880 :         GNUNET_assert (GNUNET_SYSERR !=
     160              :                        TALER_EXCHANGE_keys_stefan_b2n (&keys,
     161              :                                                        &brut,
     162              :                                                        &net));
     163        11880 :         GNUNET_assert (GNUNET_SYSERR !=
     164              :                        TALER_EXCHANGE_keys_stefan_n2b (&keys,
     165              :                                                        &net,
     166              :                                                        &rval));
     167        11880 :         if (TALER_amount_is_zero (&net))
     168         6036 :           GNUNET_assert (TALER_amount_is_zero (&rval));
     169              :         else
     170              :         {
     171         5844 :           GNUNET_assert (amount_close (&brut,
     172              :                                        &rval));
     173         5844 :           TALER_EXCHANGE_keys_stefan_round (&keys,
     174              :                                             &rval);
     175         5844 :           GNUNET_assert (amount_close (&brut,
     176              :                                        &rval));
     177              :         }
     178              :       }
     179              : 
     180              :       /* Check netto-to-brutto is stable */
     181        13068 :       for (unsigned int i = 0; i<10; i++)
     182              :       {
     183              :         struct TALER_Amount rval;
     184              : 
     185        11880 :         net.value = i;
     186        11880 :         net.fraction = i * TALER_AMOUNT_FRAC_BASE / 10;
     187        11880 :         GNUNET_assert (GNUNET_SYSERR !=
     188              :                        TALER_EXCHANGE_keys_stefan_n2b (&keys,
     189              :                                                        &net,
     190              :                                                        &brut));
     191        11880 :         GNUNET_assert (GNUNET_SYSERR !=
     192              :                        TALER_EXCHANGE_keys_stefan_b2n (&keys,
     193              :                                                        &brut,
     194              :                                                        &rval));
     195        11880 :         GNUNET_assert (amount_close (&net,
     196              :                                      &rval));
     197        11880 :         TALER_EXCHANGE_keys_stefan_round (&keys,
     198              :                                           &rval);
     199        11880 :         GNUNET_assert (amount_close (&net,
     200              :                                      &rval));
     201              :       }
     202              :     }
     203              :   }
     204            1 :   return 0;
     205              : }
        

Generated by: LCOV version 2.0-1