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

Generated by: LCOV version 2.0-1