merchant

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

testing_api_cmd_get_units.c (9678B)


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