LCOV - code coverage report
Current view: top level - util - test_amount.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 120 120
Test Date: 2026-01-04 22:17:00 Functions: 100.0 % 1 1

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   (C) 2015, 2021 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 <http://www.gnu.org/licenses/>
      15              : */
      16              : 
      17              : /**
      18              :  * @file util/test_amount.c
      19              :  * @brief Tests for amount logic
      20              :  * @author Christian Grothoff <christian@grothoff.org>
      21              :  */
      22              : #include "taler/platform.h"
      23              : #include "taler/taler_util.h"
      24              : 
      25              : 
      26              : int
      27            1 : main (int argc,
      28              :       const char *const argv[])
      29              : {
      30              :   struct TALER_Amount a1;
      31              :   struct TALER_Amount a2;
      32              :   struct TALER_Amount a3;
      33              :   struct TALER_Amount r;
      34              :   char *c;
      35              : 
      36              :   (void) argc;
      37              :   (void) argv;
      38            1 :   GNUNET_log_setup ("test-amout",
      39              :                     "WARNING",
      40              :                     NULL);
      41              :   /* test invalid conversions */
      42            1 :   GNUNET_log_skip (6, GNUNET_NO);
      43              :   /* non-numeric */
      44            1 :   GNUNET_assert (GNUNET_SYSERR ==
      45              :                  TALER_string_to_amount ("EUR:4a",
      46              :                                          &a1));
      47              :   /* non-numeric */
      48            1 :   GNUNET_assert (GNUNET_SYSERR ==
      49              :                  TALER_string_to_amount ("EUR:4.4a",
      50              :                                          &a1));
      51              :   /* non-numeric */
      52            1 :   GNUNET_assert (GNUNET_SYSERR ==
      53              :                  TALER_string_to_amount ("EUR:4.a4",
      54              :                                          &a1));
      55              :   /* no currency */
      56            1 :   GNUNET_assert (GNUNET_SYSERR ==
      57              :                  TALER_string_to_amount (":4.a4",
      58              :                                          &a1));
      59              :   /* precision too high */
      60            1 :   GNUNET_assert (GNUNET_SYSERR ==
      61              :                  TALER_string_to_amount ("EUR:4.123456789",
      62              :                                          &a1));
      63              :   /* value too big */
      64            1 :   GNUNET_assert (GNUNET_SYSERR ==
      65              :                  TALER_string_to_amount (
      66              :                    "EUR:1234567890123456789012345678901234567890123456789012345678901234567890",
      67              :                    &a1));
      68            1 :   GNUNET_log_skip (0, GNUNET_YES);
      69              : 
      70              :   /* test conversion without fraction */
      71            1 :   GNUNET_assert (GNUNET_OK ==
      72              :                  TALER_string_to_amount ("EUR:4",
      73              :                                          &a1));
      74            1 :   GNUNET_assert (0 == strcasecmp ("EUR",
      75              :                                   a1.currency));
      76            1 :   GNUNET_assert (4 == a1.value);
      77            1 :   GNUNET_assert (0 == a1.fraction);
      78              : 
      79              :   /* test conversion with leading zero in fraction */
      80            1 :   GNUNET_assert (GNUNET_OK ==
      81              :                  TALER_string_to_amount ("EUR:0.02",
      82              :                                          &a2));
      83            1 :   GNUNET_assert (0 == strcasecmp ("EUR",
      84              :                                   a2.currency));
      85            1 :   GNUNET_assert (0 == a2.value);
      86            1 :   GNUNET_assert (TALER_AMOUNT_FRAC_BASE / 100 * 2 == a2.fraction);
      87            1 :   c = TALER_amount_to_string (&a2);
      88            1 :   GNUNET_assert (0 == strcasecmp ("EUR:0.02",
      89              :                                   c));
      90            1 :   GNUNET_free (c);
      91              : 
      92              :   /* test conversion with leading space and with fraction */
      93            1 :   GNUNET_assert (GNUNET_OK ==
      94              :                  TALER_string_to_amount (" EUR:4.12",
      95              :                                          &a2));
      96            1 :   GNUNET_assert (0 == strcasecmp ("EUR",
      97              :                                   a2.currency));
      98            1 :   GNUNET_assert (4 == a2.value);
      99            1 :   GNUNET_assert (TALER_AMOUNT_FRAC_BASE / 100 * 12 == a2.fraction);
     100              : 
     101              :   /* test use of local currency */
     102            1 :   GNUNET_assert (GNUNET_OK ==
     103              :                  TALER_string_to_amount (" LOCAL:4444.1000",
     104              :                                          &a3));
     105            1 :   GNUNET_assert (0 == strcasecmp ("LOCAL",
     106              :                                   a3.currency));
     107            1 :   GNUNET_assert (4444 == a3.value);
     108            1 :   GNUNET_assert (TALER_AMOUNT_FRAC_BASE / 10 == a3.fraction);
     109              : 
     110              :   /* test CMP with equal and unequal currencies */
     111            1 :   GNUNET_assert (GNUNET_NO ==
     112              :                  TALER_amount_cmp_currency (&a1,
     113              :                                             &a3));
     114            1 :   GNUNET_assert (GNUNET_YES ==
     115              :                  TALER_amount_cmp_currency (&a1,
     116              :                                             &a2));
     117              : 
     118              :   /* test subtraction failure (currency mismatch) */
     119            1 :   GNUNET_assert (TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE ==
     120              :                  TALER_amount_subtract (&a3,
     121              :                                         &a3,
     122              :                                         &a2));
     123            1 :   GNUNET_assert (GNUNET_SYSERR ==
     124              :                  TALER_amount_normalize (&a3));
     125              : 
     126              :   /* test subtraction failure (negative result) */
     127            1 :   GNUNET_assert (TALER_AAR_INVALID_NEGATIVE_RESULT ==
     128              :                  TALER_amount_subtract (&a3,
     129              :                                         &a1,
     130              :                                         &a2));
     131            1 :   GNUNET_assert (GNUNET_SYSERR ==
     132              :                  TALER_amount_normalize (&a3));
     133              : 
     134              :   /* test subtraction success cases */
     135            1 :   GNUNET_assert (TALER_AAR_RESULT_POSITIVE ==
     136              :                  TALER_amount_subtract (&a3,
     137              :                                         &a2,
     138              :                                         &a1));
     139            1 :   GNUNET_assert (TALER_AAR_RESULT_ZERO ==
     140              :                  TALER_amount_subtract (&a3,
     141              :                                         &a1,
     142              :                                         &a1));
     143            1 :   GNUNET_assert (0 == a3.value);
     144            1 :   GNUNET_assert (0 == a3.fraction);
     145            1 :   GNUNET_assert (GNUNET_NO ==
     146              :                  TALER_amount_normalize (&a3));
     147              : 
     148              :   /* test addition success */
     149            1 :   GNUNET_assert (TALER_AAR_RESULT_POSITIVE ==
     150              :                  TALER_amount_add (&a3,
     151              :                                    &a3,
     152              :                                    &a2));
     153            1 :   GNUNET_assert (GNUNET_NO ==
     154              :                  TALER_amount_normalize (&a3));
     155              : 
     156              :   /* test normalization */
     157            1 :   a3.fraction = 2 * TALER_AMOUNT_FRAC_BASE;
     158            1 :   a3.value = 4;
     159            1 :   GNUNET_assert (GNUNET_YES ==
     160              :                  TALER_amount_normalize (&a3));
     161              : 
     162              :   /* test conversion to string */
     163            1 :   c = TALER_amount_to_string (&a3);
     164            1 :   GNUNET_assert (0 == strcmp ("EUR:6",
     165              :                               c));
     166            1 :   GNUNET_free (c);
     167              : 
     168              :   /* test normalization with fraction overflow */
     169            1 :   a3.fraction = 2 * TALER_AMOUNT_FRAC_BASE + 1;
     170            1 :   a3.value = 4;
     171            1 :   GNUNET_assert (GNUNET_YES ==
     172              :                  TALER_amount_normalize (&a3));
     173            1 :   c = TALER_amount_to_string (&a3);
     174            1 :   GNUNET_assert (0 == strcmp ("EUR:6.00000001",
     175              :                               c));
     176            1 :   GNUNET_free (c);
     177              : 
     178              :   /* test normalization with overflow */
     179            1 :   a3.fraction = 2 * TALER_AMOUNT_FRAC_BASE + 1;
     180            1 :   a3.value = UINT64_MAX - 1;
     181            1 :   GNUNET_assert (GNUNET_SYSERR ==
     182              :                  TALER_amount_normalize (&a3));
     183            1 :   c = TALER_amount_to_string (&a3);
     184            1 :   GNUNET_assert (NULL == c);
     185              : 
     186              :   /* test addition with overflow */
     187            1 :   a1.fraction = TALER_AMOUNT_FRAC_BASE - 1;
     188            1 :   a1.value = TALER_AMOUNT_MAX_VALUE - 5;
     189            1 :   a2.fraction = 2;
     190            1 :   a2.value = 5;
     191            1 :   GNUNET_assert (TALER_AAR_INVALID_RESULT_OVERFLOW ==
     192              :                  TALER_amount_add (&a3,
     193              :                                    &a1,
     194              :                                    &a2));
     195              : 
     196              :   /* test addition with underflow on fraction */
     197            1 :   a1.fraction = 1;
     198            1 :   a1.value = TALER_AMOUNT_MAX_VALUE;
     199            1 :   a2.fraction = 2;
     200            1 :   a2.value = 0;
     201            1 :   GNUNET_assert (TALER_AAR_RESULT_POSITIVE ==
     202              :                  TALER_amount_subtract (&a3,
     203              :                                         &a1,
     204              :                                         &a2));
     205            1 :   GNUNET_assert (TALER_AMOUNT_MAX_VALUE - 1 ==
     206              :                  a3.value);
     207            1 :   GNUNET_assert (TALER_AMOUNT_FRAC_BASE - 1 ==
     208              :                  a3.fraction);
     209              : 
     210              :   /* test division */
     211            1 :   GNUNET_assert (GNUNET_OK ==
     212              :                  TALER_string_to_amount ("EUR:3.33",
     213              :                                          &a1));
     214            1 :   TALER_amount_divide (&a2,
     215              :                        &a1,
     216              :                        1);
     217            1 :   GNUNET_assert (0 == strcasecmp ("EUR",
     218              :                                   a2.currency));
     219            1 :   GNUNET_assert (3 == a2.value);
     220            1 :   GNUNET_assert (TALER_AMOUNT_FRAC_BASE / 100 * 33 == a2.fraction);
     221              : 
     222            1 :   TALER_amount_divide (&a2,
     223              :                        &a1,
     224              :                        3);
     225            1 :   GNUNET_assert (0 == strcasecmp ("EUR",
     226              :                                   a2.currency));
     227            1 :   GNUNET_assert (1 == a2.value);
     228            1 :   GNUNET_assert (TALER_AMOUNT_FRAC_BASE / 100 * 11 == a2.fraction);
     229              : 
     230            1 :   TALER_amount_divide (&a2,
     231              :                        &a1,
     232              :                        2);
     233            1 :   GNUNET_assert (0 == strcasecmp ("EUR",
     234              :                                   a2.currency));
     235            1 :   GNUNET_assert (1 == a2.value);
     236            1 :   GNUNET_assert (TALER_AMOUNT_FRAC_BASE / 1000 * 665 == a2.fraction);
     237            1 :   TALER_amount_divide (&a2,
     238              :                        &a1,
     239              :                        TALER_AMOUNT_FRAC_BASE * 2);
     240            1 :   GNUNET_assert (0 == strcasecmp ("EUR",
     241              :                                   a2.currency));
     242            1 :   GNUNET_assert (0 == a2.value);
     243            1 :   GNUNET_assert (1 == a2.fraction);
     244              : 
     245              :   /* test rounding #1 */
     246            1 :   GNUNET_assert (GNUNET_OK ==
     247              :                  TALER_string_to_amount ("EUR:0.01",
     248              :                                          &r));
     249            1 :   GNUNET_assert (GNUNET_OK ==
     250              :                  TALER_string_to_amount ("EUR:4.001",
     251              :                                          &a1));
     252            1 :   GNUNET_assert (GNUNET_OK ==
     253              :                  TALER_string_to_amount ("EUR:4",
     254              :                                          &a2));
     255            1 :   GNUNET_assert (GNUNET_OK ==
     256              :                  TALER_amount_round_down (&a1,
     257              :                                           &r));
     258            1 :   GNUNET_assert (GNUNET_NO ==
     259              :                  TALER_amount_round_down (&a1,
     260              :                                           &r));
     261            1 :   GNUNET_assert (0 == TALER_amount_cmp (&a1,
     262              :                                         &a2));
     263              : 
     264              :   /* test rounding #2 */
     265            1 :   GNUNET_assert (GNUNET_OK ==
     266              :                  TALER_string_to_amount ("EUR:0.001",
     267              :                                          &r));
     268              : 
     269            1 :   GNUNET_assert (GNUNET_OK ==
     270              :                  TALER_string_to_amount ("EUR:4.001",
     271              :                                          &a1));
     272            1 :   GNUNET_assert (GNUNET_OK ==
     273              :                  TALER_string_to_amount ("EUR:4.001",
     274              :                                          &a2));
     275            1 :   GNUNET_assert (GNUNET_NO ==
     276              :                  TALER_amount_round_down (&a1,
     277              :                                           &r));
     278            1 :   GNUNET_assert (0 == TALER_amount_cmp (&a1,
     279              :                                         &a2));
     280              : 
     281              :   /* test rounding #3 */
     282            1 :   GNUNET_assert (GNUNET_OK ==
     283              :                  TALER_string_to_amount ("BTC:5",
     284              :                                          &r));
     285            1 :   GNUNET_assert (GNUNET_OK ==
     286              :                  TALER_string_to_amount ("BTC:12.3",
     287              :                                          &a1));
     288            1 :   GNUNET_assert (GNUNET_OK ==
     289              :                  TALER_string_to_amount ("BTC:10",
     290              :                                          &a2));
     291            1 :   GNUNET_assert (GNUNET_OK ==
     292              :                  TALER_amount_round_down (&a1,
     293              :                                           &r));
     294            1 :   GNUNET_assert (0 == TALER_amount_cmp (&a1,
     295              :                                         &a2));
     296              : 
     297              :   /* test multiplication */
     298            1 :   GNUNET_assert (GNUNET_OK ==
     299              :                  TALER_string_to_amount ("BTC:0",
     300              :                                          &a1));
     301            1 :   GNUNET_assert (TALER_AAR_RESULT_ZERO ==
     302              :                  TALER_amount_multiply (&a2,
     303              :                                         &a1,
     304              :                                         42));
     305            1 :   GNUNET_assert (0 == TALER_amount_cmp (&a1,
     306              :                                         &a2));
     307            1 :   GNUNET_assert (GNUNET_OK ==
     308              :                  TALER_string_to_amount ("BTC:5.001",
     309              :                                          &a1));
     310            1 :   GNUNET_assert (GNUNET_OK ==
     311              :                  TALER_string_to_amount ("BTC:5001",
     312              :                                          &r));
     313            1 :   GNUNET_assert (TALER_AAR_RESULT_POSITIVE ==
     314              :                  TALER_amount_multiply (&a2,
     315              :                                         &a1,
     316              :                                         1000));
     317            1 :   GNUNET_assert (0 == TALER_amount_cmp (&r,
     318              :                                         &a2));
     319            1 :   GNUNET_assert (1000 ==
     320              :                  TALER_amount_divide2 (&a2,
     321              :                                        &a1));
     322            1 :   GNUNET_assert (GNUNET_OK ==
     323              :                  TALER_string_to_amount ("BTC:5006.00099999",
     324              :                                          &r));
     325            1 :   GNUNET_assert (1000 ==
     326              :                  TALER_amount_divide2 (&r,
     327              :                                        &a1));
     328            1 :   GNUNET_assert (GNUNET_OK ==
     329              :                  TALER_string_to_amount ("BTC:5000.99999999",
     330              :                                          &r));
     331            1 :   GNUNET_assert (999 ==
     332              :                  TALER_amount_divide2 (&r,
     333              :                                        &a1));
     334            1 :   GNUNET_assert (GNUNET_OK ==
     335              :                  TALER_string_to_amount ("BTC:0",
     336              :                                          &a1));
     337            1 :   GNUNET_assert (INT_MAX ==
     338              :                  TALER_amount_divide2 (&a2,
     339              :                                        &a1));
     340            1 :   GNUNET_assert (0 ==
     341              :                  TALER_amount_divide2 (&a1,
     342              :                                        &a2));
     343            1 :   return 0;
     344              : }
     345              : 
     346              : 
     347              : /* end of test_amount.c */
        

Generated by: LCOV version 2.0-1