merchant

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

testing_api_cmd_get_units.c (9840B)


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