LCOV - code coverage report
Current view: top level - lib - test_stefan.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 56 63 88.9 %
Date: 2025-06-05 21:03:14 Functions: 2 2 100.0 %

          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 "platform.h"
      23             : #include "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 1.16