merchant

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

testing_api_cmd_get_unit.c (9707B)


      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_unit.c
     21  * @brief command to test GET /private/units/$ID
     22  * @author Bohdan Potuzhnyi
     23  */
     24 #include "platform.h"
     25 struct GetUnitState;
     26 #define TALER_MERCHANT_GET_PRIVATE_UNIT_RESULT_CLOSURE struct GetUnitState
     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-UNIT.h>
     32 
     33 
     34 /**
     35  * State for a GET /private/units/$ID command.
     36  */
     37 struct GetUnitState
     38 {
     39   /**
     40    * In-flight request handle.
     41    */
     42   struct TALER_MERCHANT_GetPrivateUnitHandle *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    * Unit identifier to fetch.
     56    */
     57   const char *unit_id;
     58 
     59   /**
     60    * Expected HTTP status.
     61    */
     62   unsigned int http_status;
     63 
     64   /**
     65    * Optional command label providing expected traits.
     66    */
     67   const char *reference;
     68 };
     69 
     70 
     71 /**
     72  * Compare response @a entry with traits from @a ref_cmd.
     73  */
     74 static bool
     75 unit_matches_reference (const struct TALER_MERCHANT_UnitEntry *entry,
     76                         const struct TALER_TESTING_Command *ref_cmd)
     77 {
     78   const char *unit_id;
     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                 "Unit trait resolution failed for reference `%s'\n",
     86                 ref_cmd->label);
     87     return false;
     88   }
     89   if (0 != strcmp (entry->unit,
     90                    unit_id))
     91   {
     92     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     93                 "Unit mismatch: expected id %s got %s\n",
     94                 unit_id,
     95                 entry->unit);
     96     return false;
     97   }
     98 
     99   {
    100     const char *unit_name_long = NULL;
    101 
    102     if (GNUNET_OK ==
    103         TALER_TESTING_get_trait_unit_name_long (ref_cmd,
    104                                                 &unit_name_long))
    105     {
    106       if ( (NULL != unit_name_long) &&
    107            (0 != strcmp (entry->unit_name_long,
    108                          unit_name_long)) )
    109       {
    110         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    111                     "Unit %s mismatch: expected long label '%s' got '%s'\n",
    112                     entry->unit,
    113                     unit_name_long,
    114                     entry->unit_name_long);
    115         return false;
    116       }
    117     }
    118   }
    119   {
    120     const char *unit_name_short = NULL;
    121 
    122     if (GNUNET_OK ==
    123         TALER_TESTING_get_trait_unit_name_short (ref_cmd,
    124                                                  &unit_name_short))
    125     {
    126       if ( (NULL != unit_name_short) &&
    127            (0 != strcmp (entry->unit_name_short,
    128                          unit_name_short)) )
    129       {
    130         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    131                     "Unit %s mismatch: expected short label '%s' got '%s'\n",
    132                     entry->unit,
    133                     unit_name_short,
    134                     entry->unit_name_short);
    135         return false;
    136       }
    137     }
    138   }
    139   {
    140     const bool *unit_allow_fraction = NULL;
    141 
    142     if (GNUNET_OK ==
    143         TALER_TESTING_get_trait_unit_allow_fraction (ref_cmd,
    144                                                      &unit_allow_fraction))
    145     {
    146       if ( (NULL != unit_allow_fraction) &&
    147            (*unit_allow_fraction != entry->unit_allow_fraction) )
    148       {
    149         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    150                     "Unit %s mismatch: expected allow_fraction %d got %d\n",
    151                     entry->unit,
    152                     (int) *unit_allow_fraction,
    153                     (int) entry->unit_allow_fraction);
    154         return false;
    155       }
    156     }
    157   }
    158   {
    159     const uint32_t *unit_precision_level = NULL;
    160 
    161     if (GNUNET_OK ==
    162         TALER_TESTING_get_trait_unit_precision_level (ref_cmd,
    163                                                       &unit_precision_level))
    164     {
    165       if ( (NULL != unit_precision_level) &&
    166            (*unit_precision_level != entry->unit_precision_level) )
    167       {
    168         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    169                     "Unit %s mismatch: expected precision %u got %u\n",
    170                     entry->unit,
    171                     (unsigned int) *unit_precision_level,
    172                     (unsigned int) entry->unit_precision_level);
    173         return false;
    174       }
    175     }
    176   }
    177   {
    178     const bool *unit_active = NULL;
    179 
    180     if (GNUNET_OK ==
    181         TALER_TESTING_get_trait_unit_active (ref_cmd,
    182                                              &unit_active))
    183     {
    184       if ( (NULL != unit_active) &&
    185            (*unit_active != entry->unit_active) )
    186       {
    187         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    188                     "Unit %s mismatch: expected active flag %d got %d\n",
    189                     entry->unit,
    190                     (int) *unit_active,
    191                     (int) entry->unit_active);
    192         return false;
    193       }
    194     }
    195   }
    196   {
    197     const json_t *unit_name_long_i18n = NULL;
    198 
    199     if (GNUNET_OK ==
    200         TALER_TESTING_get_trait_unit_name_long_i18n (ref_cmd,
    201                                                      &unit_name_long_i18n))
    202     {
    203       if ( (NULL != unit_name_long_i18n) &&
    204            ( (NULL == entry->unit_name_long_i18n) ||
    205              (1 != json_equal (unit_name_long_i18n,
    206                                entry->unit_name_long_i18n)) ) )
    207       {
    208         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    209                     "Unit %s mismatch: long_i18n differs\n",
    210                     entry->unit);
    211         return false;
    212       }
    213     }
    214   }
    215   {
    216     const json_t *unit_name_short_i18n = NULL;
    217 
    218     if (GNUNET_OK ==
    219         TALER_TESTING_get_trait_unit_name_short_i18n (ref_cmd,
    220                                                       &unit_name_short_i18n))
    221     {
    222       if ( (NULL != unit_name_short_i18n) &&
    223            ( (NULL == entry->unit_name_short_i18n) ||
    224              (1 != json_equal (unit_name_short_i18n,
    225                                entry->unit_name_short_i18n)) ) )
    226       {
    227         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    228                     "Unit %s mismatch: short_i18n differs\n",
    229                     entry->unit);
    230         return false;
    231       }
    232     }
    233   }
    234   return true;
    235 }
    236 
    237 
    238 /**
    239  * Completion callback.
    240  */
    241 static void
    242 get_unit_cb (struct GetUnitState *gug,
    243              const struct TALER_MERCHANT_GetPrivateUnitResponse *ugr)
    244 {
    245 
    246   gug->ugh = NULL;
    247   if (gug->http_status != ugr->hr.http_status)
    248   {
    249     TALER_TESTING_unexpected_status_with_body (gug->is,
    250                                                ugr->hr.http_status,
    251                                                gug->http_status,
    252                                                ugr->hr.reply);
    253     return;
    254   }
    255   if ( (MHD_HTTP_OK == ugr->hr.http_status) &&
    256        (NULL != gug->reference) )
    257   {
    258     const struct TALER_TESTING_Command *ref_cmd;
    259 
    260     ref_cmd = TALER_TESTING_interpreter_lookup_command (gug->is,
    261                                                         gug->reference);
    262     if (NULL == ref_cmd)
    263     {
    264       GNUNET_break (0);
    265       TALER_TESTING_interpreter_fail (gug->is);
    266       return;
    267     }
    268     if (! unit_matches_reference (&ugr->details.ok.unit,
    269                                   ref_cmd))
    270     {
    271       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    272                   "GET /private/units/%s response does not match expectation from `%s'\n",
    273                   gug->unit_id,
    274                   gug->reference);
    275       TALER_TESTING_interpreter_fail (gug->is);
    276       return;
    277     }
    278   }
    279   TALER_TESTING_interpreter_next (gug->is);
    280 }
    281 
    282 
    283 /**
    284  * Issue GET request.
    285  */
    286 static void
    287 get_unit_run (void *cls,
    288               const struct TALER_TESTING_Command *cmd,
    289               struct TALER_TESTING_Interpreter *is)
    290 {
    291   struct GetUnitState *gug = cls;
    292 
    293   gug->is = is;
    294   gug->ugh = TALER_MERCHANT_get_private_unit_create (
    295     TALER_TESTING_interpreter_get_context (is),
    296     gug->merchant_url,
    297     gug->unit_id);
    298   {
    299     enum TALER_ErrorCode ec;
    300 
    301     ec = TALER_MERCHANT_get_private_unit_start (
    302       gug->ugh,
    303       &get_unit_cb,
    304       gug);
    305     GNUNET_assert (TALER_EC_NONE == ec);
    306   }
    307 }
    308 
    309 
    310 /**
    311  * Cleanup.
    312  */
    313 static void
    314 get_unit_cleanup (void *cls,
    315                   const struct TALER_TESTING_Command *cmd)
    316 {
    317   struct GetUnitState *gug = cls;
    318 
    319   if (NULL != gug->ugh)
    320   {
    321     TALER_MERCHANT_get_private_unit_cancel (gug->ugh);
    322     gug->ugh = NULL;
    323   }
    324   GNUNET_free (gug);
    325 }
    326 
    327 
    328 struct TALER_TESTING_Command
    329 TALER_TESTING_cmd_merchant_get_unit (const char *label,
    330                                      const char *merchant_url,
    331                                      const char *unit_id,
    332                                      unsigned int http_status,
    333                                      const char *reference)
    334 {
    335   struct GetUnitState *gug;
    336 
    337   gug = GNUNET_new (struct GetUnitState);
    338   gug->merchant_url = merchant_url;
    339   gug->unit_id = unit_id;
    340   gug->http_status = http_status;
    341   gug->reference = reference;
    342 
    343   {
    344     struct TALER_TESTING_Command cmd = {
    345       .cls = gug,
    346       .label = label,
    347       .run = &get_unit_run,
    348       .cleanup = &get_unit_cleanup
    349     };
    350 
    351     return cmd;
    352   }
    353 }
    354 
    355 
    356 /* end of testing_api_cmd_get_unit.c */