merchant

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

testing_api_cmd_get_units.c (9920B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2025 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify
      6   it under the terms of the GNU General Public License as
      7   published by the Free Software Foundation; either version 3, or
      8   (at your option) any later version.
      9 
     10   TALER is distributed in the hope that it will be useful, but
     11   WITHOUT ANY WARRANTY; without even the implied warranty of
     12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13   GNU General Public License for more details.
     14 
     15   You should have received a copy of the GNU General Public
     16   License along with TALER; see the file COPYING.  If not, see
     17   <http://www.gnu.org/licenses/>
     18 */
     19 /**
     20  * @file src/testing/testing_api_cmd_get_units.c
     21  * @brief command to test GET /private/units
     22  * @author Bohdan Potuzhnyi
     23  */
     24 #include "platform.h"
     25 struct GetUnitsState;
     26 #define TALER_MERCHANT_GET_PRIVATE_UNITS_RESULT_CLOSURE struct GetUnitsState
     27 #include <jansson.h>
     28 #include <taler/taler_testing_lib.h>
     29 #include "taler/taler_merchant_service.h"
     30 #include "taler/taler_merchant_testing_lib.h"
     31 #include <taler/merchant/get-private-units.h>
     32 
     33 
     34 /**
     35  * State for a GET /private/units command.
     36  */
     37 struct GetUnitsState
     38 {
     39   /**
     40    * In-flight request handle.
     41    */
     42   struct TALER_MERCHANT_GetPrivateUnitsHandle *ugh;
     43 
     44   /**
     45    * Interpreter context.
     46    */
     47   struct TALER_TESTING_Interpreter *is;
     48 
     49   /**
     50    * Merchant backend base URL.
     51    */
     52   const char *merchant_url;
     53 
     54   /**
     55    * Expected HTTP status.
     56    */
     57   unsigned int http_status;
     58 
     59   /**
     60    * Expected references that must appear in the listing.
     61    */
     62   const char **references;
     63 
     64   /**
     65    * Length of @e references.
     66    */
     67   unsigned int references_length;
     68 };
     69 
     70 
     71 /**
     72  * Verify that @a entry matches the traits from @a ref_cmd.
     73  */
     74 static enum GNUNET_GenericReturnValue
     75 check_unit_matches (const struct TALER_MERCHANT_UnitEntry *entry,
     76                     const struct TALER_TESTING_Command *ref_cmd)
     77 {
     78   const char *unit_id = NULL;
     79 
     80   if (GNUNET_OK !=
     81       TALER_TESTING_get_trait_unit_id (ref_cmd,
     82                                        &unit_id))
     83   {
     84     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     85                 "Internal error: command `%s' lacks unit_id trait\n",
     86                 ref_cmd->label);
     87     return GNUNET_SYSERR;
     88   }
     89   if (0 != strcmp (entry->unit,
     90                    unit_id))
     91     return GNUNET_NO;
     92 
     93   {
     94     const char *unit_name_long = NULL;
     95 
     96     if (GNUNET_OK ==
     97         TALER_TESTING_get_trait_unit_name_long (ref_cmd,
     98                                                 &unit_name_long))
     99     {
    100       if ( (NULL != unit_name_long) &&
    101            (0 != strcmp (entry->unit_name_long,
    102                          unit_name_long)) )
    103         return GNUNET_SYSERR;
    104     }
    105   }
    106   {
    107     const char *unit_name_short = NULL;
    108 
    109     if (GNUNET_OK ==
    110         TALER_TESTING_get_trait_unit_name_short (ref_cmd,
    111                                                  &unit_name_short))
    112     {
    113       if ( (NULL != unit_name_short) &&
    114            (0 != strcmp (entry->unit_name_short,
    115                          unit_name_short)) )
    116         return GNUNET_SYSERR;
    117     }
    118   }
    119   {
    120     const bool *unit_allow_fraction = NULL;
    121 
    122     if (GNUNET_OK ==
    123         TALER_TESTING_get_trait_unit_allow_fraction (ref_cmd,
    124                                                      &unit_allow_fraction))
    125     {
    126       if ( (NULL != unit_allow_fraction) &&
    127            (*unit_allow_fraction != entry->unit_allow_fraction) )
    128       {
    129         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    130                     "Unit %s mismatch: expected allow_fraction %d got %d\n",
    131                     entry->unit,
    132                     (int) *unit_allow_fraction,
    133                     (int) entry->unit_allow_fraction);
    134         return GNUNET_SYSERR;
    135       }
    136     }
    137   }
    138   {
    139     const uint32_t *unit_precision_level = NULL;
    140 
    141     if (GNUNET_OK ==
    142         TALER_TESTING_get_trait_unit_precision_level (ref_cmd,
    143                                                       &unit_precision_level))
    144     {
    145       if ( (NULL != unit_precision_level) &&
    146            (*unit_precision_level != entry->unit_precision_level) )
    147       {
    148         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    149                     "Unit %s mismatch: expected precision %u got %u\n",
    150                     entry->unit,
    151                     (unsigned int) *unit_precision_level,
    152                     (unsigned int) entry->unit_precision_level);
    153         return GNUNET_SYSERR;
    154       }
    155     }
    156   }
    157   {
    158     const bool *unit_active = NULL;
    159 
    160     if (GNUNET_OK ==
    161         TALER_TESTING_get_trait_unit_active (ref_cmd,
    162                                              &unit_active))
    163     {
    164       if ( (NULL != unit_active) &&
    165            (*unit_active != entry->unit_active) )
    166       {
    167         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    168                     "Unit %s mismatch: expected active %d got %d\n",
    169                     entry->unit,
    170                     (int) *unit_active,
    171                     (int) entry->unit_active);
    172         return GNUNET_SYSERR;
    173       }
    174     }
    175   }
    176   {
    177     const json_t *unit_name_long_i18n = NULL;
    178 
    179     if (GNUNET_OK ==
    180         TALER_TESTING_get_trait_unit_name_long_i18n (ref_cmd,
    181                                                      &unit_name_long_i18n))
    182     {
    183       if ( (NULL != unit_name_long_i18n) &&
    184            ( (NULL == entry->unit_name_long_i18n) ||
    185              (1 != json_equal (unit_name_long_i18n,
    186                                entry->unit_name_long_i18n)) ) )
    187       {
    188         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    189                     "Unit %s mismatch: long_i18n differs\n",
    190                     entry->unit);
    191         return GNUNET_SYSERR;
    192       }
    193     }
    194   }
    195   {
    196     const json_t *unit_name_short_i18n = NULL;
    197 
    198     if (GNUNET_OK ==
    199         TALER_TESTING_get_trait_unit_name_short_i18n (ref_cmd,
    200                                                       &unit_name_short_i18n))
    201     {
    202       if ( (NULL != unit_name_short_i18n) &&
    203            ( (NULL == entry->unit_name_short_i18n) ||
    204              (1 != json_equal (unit_name_short_i18n,
    205                                entry->unit_name_short_i18n)) ) )
    206       {
    207         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    208                     "Unit %s mismatch: short_i18n differs\n",
    209                     entry->unit);
    210         return GNUNET_SYSERR;
    211       }
    212     }
    213   }
    214   return GNUNET_OK;
    215 }
    216 
    217 
    218 /**
    219  * Completion callback for GET /private/units.
    220  */
    221 static void
    222 get_units_cb (struct GetUnitsState *gus,
    223               const struct TALER_MERCHANT_GetPrivateUnitsResponse *ugr)
    224 {
    225 
    226   gus->ugh = NULL;
    227   if (gus->http_status != ugr->hr.http_status)
    228   {
    229     TALER_TESTING_unexpected_status_with_body (gus->is,
    230                                                ugr->hr.http_status,
    231                                                gus->http_status,
    232                                                ugr->hr.reply);
    233     return;
    234   }
    235   if (MHD_HTTP_OK == ugr->hr.http_status)
    236   {
    237     for (unsigned int i = 0; i < gus->references_length; ++i)
    238     {
    239       const char *label = gus->references[i];
    240       const struct TALER_TESTING_Command *ref_cmd;
    241       enum GNUNET_GenericReturnValue match = GNUNET_NO;
    242 
    243       ref_cmd = TALER_TESTING_interpreter_lookup_command (gus->is,
    244                                                           label);
    245       if (NULL == ref_cmd)
    246       {
    247         GNUNET_break (0);
    248         TALER_TESTING_interpreter_fail (gus->is);
    249         return;
    250       }
    251       for (unsigned int j = 0;
    252            j < ugr->details.ok.units_length;
    253            ++j)
    254       {
    255         match = check_unit_matches (&ugr->details.ok.units[j],
    256                                     ref_cmd);
    257         if (GNUNET_SYSERR == match)
    258           break;
    259         if (GNUNET_OK == match)
    260           break;
    261       }
    262       if (GNUNET_SYSERR == match)
    263       {
    264         GNUNET_break (0);
    265         TALER_TESTING_interpreter_fail (gus->is);
    266         return;
    267       }
    268       if (GNUNET_OK != match)
    269       {
    270         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    271                     "Unit referenced by `%s' not found in GET /private/units response\n",
    272                     label);
    273         TALER_TESTING_interpreter_fail (gus->is);
    274         return;
    275       }
    276     }
    277   }
    278   TALER_TESTING_interpreter_next (gus->is);
    279 }
    280 
    281 
    282 /**
    283  * Issue the GET request.
    284  */
    285 static void
    286 get_units_run (void *cls,
    287                const struct TALER_TESTING_Command *cmd,
    288                struct TALER_TESTING_Interpreter *is)
    289 {
    290   struct GetUnitsState *gus = cls;
    291 
    292   gus->is = is;
    293   gus->ugh = TALER_MERCHANT_get_private_units_create (
    294     TALER_TESTING_interpreter_get_context (is),
    295     gus->merchant_url);
    296   {
    297     enum TALER_ErrorCode ec;
    298 
    299     ec = TALER_MERCHANT_get_private_units_start (
    300       gus->ugh,
    301       &get_units_cb,
    302       gus);
    303     GNUNET_assert (TALER_EC_NONE == ec);
    304   }
    305 }
    306 
    307 
    308 /**
    309  * Cleanup.
    310  */
    311 static void
    312 get_units_cleanup (void *cls,
    313                    const struct TALER_TESTING_Command *cmd)
    314 {
    315   struct GetUnitsState *gus = cls;
    316 
    317   if (NULL != gus->ugh)
    318   {
    319     TALER_MERCHANT_get_private_units_cancel (gus->ugh);
    320     gus->ugh = NULL;
    321   }
    322   GNUNET_array_grow (gus->references,
    323                      gus->references_length,
    324                      0);
    325   GNUNET_free (gus);
    326 }
    327 
    328 
    329 struct TALER_TESTING_Command
    330 TALER_TESTING_cmd_merchant_get_units (const char *label,
    331                                       const char *merchant_url,
    332                                       unsigned int http_status,
    333                                       ...)
    334 {
    335   struct GetUnitsState *gus;
    336   va_list ap;
    337   const char *ref;
    338 
    339   gus = GNUNET_new (struct GetUnitsState);
    340   gus->merchant_url = merchant_url;
    341   gus->http_status = http_status;
    342 
    343   va_start (ap, http_status);
    344   while (NULL != (ref = va_arg (ap, const char *)))
    345   {
    346     GNUNET_array_append (gus->references,
    347                          gus->references_length,
    348                          ref);
    349   }
    350   va_end (ap);
    351 
    352   {
    353     struct TALER_TESTING_Command cmd = {
    354       .cls = gus,
    355       .label = label,
    356       .run = &get_units_run,
    357       .cleanup = &get_units_cleanup
    358     };
    359 
    360     return cmd;
    361   }
    362 }
    363 
    364 
    365 /* end of testing_api_cmd_get_units.c */