LCOV - code coverage report
Current view: top level - testing - testing_api_cmd_get_product.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 55.0 % 160 88
Test Date: 2025-12-10 19:49:57 Functions: 100.0 % 5 5

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   Copyright (C) 2020-2023 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_product.c
      21              :  * @brief command to test GET /product/$ID
      22              :  * @author Christian Grothoff
      23              :  */
      24              : #include "platform.h"
      25              : #include <taler/taler_exchange_service.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 of a "GET product" CMD.
      33              :  */
      34              : struct GetProductState
      35              : {
      36              : 
      37              :   /**
      38              :    * Handle for a "GET product" request.
      39              :    */
      40              :   struct TALER_MERCHANT_ProductGetHandle *igh;
      41              : 
      42              :   /**
      43              :    * The interpreter state.
      44              :    */
      45              :   struct TALER_TESTING_Interpreter *is;
      46              : 
      47              :   /**
      48              :    * Base URL of the merchant serving the request.
      49              :    */
      50              :   const char *merchant_url;
      51              : 
      52              :   /**
      53              :    * ID of the product to run GET for.
      54              :    */
      55              :   const char *product_id;
      56              : 
      57              :   /**
      58              :    * Reference for a POST or PATCH /products CMD (optional).
      59              :    */
      60              :   const char *product_reference;
      61              : 
      62              :   /**
      63              :    * Expected HTTP response code.
      64              :    */
      65              :   unsigned int http_status;
      66              : 
      67              :   /**
      68              :    * Optional overrides for fractional fields.
      69              :    */
      70              :   const struct TALER_TESTING_ProductUnitExpectations *unit_expectations;
      71              : 
      72              : };
      73              : 
      74              : 
      75              : /**
      76              :  * Callback for a /get/product/$ID operation.
      77              :  *
      78              :  * @param cls closure for this function
      79              :  * @param pgr response details
      80              :  */
      81              : static void
      82           24 : get_product_cb (void *cls,
      83              :                 const struct TALER_MERCHANT_ProductGetResponse *pgr)
      84              : {
      85           24 :   struct GetProductState *gis = cls;
      86              :   const struct TALER_TESTING_Command *product_cmd;
      87           24 :   const struct TALER_TESTING_ProductUnitExpectations *ue =
      88              :     gis->unit_expectations;
      89              : 
      90           24 :   gis->igh = NULL;
      91           24 :   if (gis->http_status != pgr->hr.http_status)
      92              :   {
      93            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
      94              :                 "Unexpected response code %u (%d) to command %s\n",
      95              :                 pgr->hr.http_status,
      96              :                 (int) pgr->hr.ec,
      97              :                 TALER_TESTING_interpreter_get_current_label (gis->is));
      98            0 :     TALER_TESTING_interpreter_fail (gis->is);
      99            0 :     return;
     100              :   }
     101           24 :   switch (pgr->hr.http_status)
     102              :   {
     103           12 :   case MHD_HTTP_OK:
     104              :     {
     105              :       const char *expected_description;
     106              : 
     107           12 :       product_cmd = TALER_TESTING_interpreter_lookup_command (
     108              :         gis->is,
     109              :         gis->product_reference);
     110           12 :       if (GNUNET_OK !=
     111           12 :           TALER_TESTING_get_trait_product_description (product_cmd,
     112              :                                                        &expected_description))
     113            0 :         TALER_TESTING_interpreter_fail (gis->is);
     114           12 :       if (0 != strcmp (pgr->details.ok.description,
     115              :                        expected_description))
     116              :       {
     117            0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     118              :                     "Product description does not match\n");
     119            0 :         TALER_TESTING_interpreter_fail (gis->is);
     120            0 :         return;
     121              :       }
     122              :     }
     123              :     {
     124              :       const json_t *expected_description_i18n;
     125              : 
     126           12 :       if (GNUNET_OK !=
     127           12 :           TALER_TESTING_get_trait_i18n_description (product_cmd,
     128              :                                                     &expected_description_i18n))
     129            0 :         TALER_TESTING_interpreter_fail (gis->is);
     130           12 :       if (1 != json_equal (pgr->details.ok.description_i18n,
     131              :                            expected_description_i18n))
     132              :       {
     133            0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     134              :                     "Product description i18n does not match\n");
     135            0 :         TALER_TESTING_interpreter_fail (gis->is);
     136            0 :         return;
     137              :       }
     138              :     }
     139              :     {
     140              :       const struct TALER_Amount *expected_price;
     141              : 
     142           12 :       if (GNUNET_OK !=
     143           12 :           TALER_TESTING_get_trait_amount (product_cmd,
     144              :                                           &expected_price))
     145            0 :         TALER_TESTING_interpreter_fail (gis->is);
     146           12 :       if ((GNUNET_OK !=
     147           12 :            TALER_amount_cmp_currency (&pgr->details.ok.price,
     148           12 :                                       expected_price)) ||
     149           12 :           (0 != TALER_amount_cmp (&pgr->details.ok.price,
     150              :                                   expected_price)))
     151              :       {
     152            0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     153              :                     "Product price does not match\n");
     154            0 :         TALER_TESTING_interpreter_fail (gis->is);
     155            0 :         return;
     156              :       }
     157              :     }
     158              :     {
     159              :       const bool *expected_allow;
     160           12 :       bool have_allow = GNUNET_OK ==
     161           12 :                         TALER_TESTING_get_trait_product_unit_allow_fraction (
     162              :         product_cmd,
     163              :         &expected_allow);
     164           16 :       bool override_allow = (NULL != ue) &&
     165            4 :                             ue->have_unit_allow_fraction;
     166              : 
     167           12 :       if (override_allow)
     168              :       {
     169            4 :         if (pgr->details.ok.unit_allow_fraction !=
     170            4 :             ue->unit_allow_fraction)
     171              :         {
     172            0 :           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     173              :                       "Product fractional flag does not match expectation\n");
     174            0 :           TALER_TESTING_interpreter_fail (gis->is);
     175            0 :           return;
     176              :         }
     177              :       }
     178            8 :       else if (! have_allow)
     179              :       {
     180            0 :         if (pgr->details.ok.unit_allow_fraction)
     181              :         {
     182            0 :           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     183              :                       "Product fractional flag unexpected\n");
     184            0 :           TALER_TESTING_interpreter_fail (gis->is);
     185            0 :           return;
     186              :         }
     187              :       }
     188              :       else
     189              :       {
     190            8 :         if (pgr->details.ok.unit_allow_fraction != *expected_allow)
     191              :         {
     192            0 :           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     193              :                       "Product fractional flag does not match\n");
     194            0 :           TALER_TESTING_interpreter_fail (gis->is);
     195            0 :           return;
     196              :         }
     197              :         {
     198              :           const char *expected_unit_total_stock;
     199              : 
     200            8 :           if (GNUNET_OK !=
     201            8 :               TALER_TESTING_get_trait_product_unit_total_stock (
     202              :                 product_cmd,
     203              :                 &expected_unit_total_stock))
     204            0 :             TALER_TESTING_interpreter_fail (gis->is);
     205            8 :           else if (0 != strcmp (pgr->details.ok.unit_total_stock,
     206              :                                 expected_unit_total_stock))
     207              :           {
     208            0 :             GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     209              :                         "Product stock string does not match\n");
     210            0 :             TALER_TESTING_interpreter_fail (gis->is);
     211            0 :             return;
     212              :           }
     213              :         }
     214              :       }
     215              :     }
     216              :     {
     217              :       const uint32_t *expected_precision;
     218           12 :       bool have_precision = GNUNET_OK ==
     219           12 :                             TALER_TESTING_get_trait_product_unit_precision_level (
     220              :         product_cmd,
     221              :         &expected_precision);
     222           16 :       bool override_precision = (NULL != ue) &&
     223            4 :                                 ue->have_unit_precision_level;
     224              : 
     225           12 :       if (override_precision)
     226              :       {
     227            4 :         if (pgr->details.ok.unit_precision_level !=
     228            4 :             ue->unit_precision_level)
     229              :         {
     230            0 :           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     231              :                       "Product fractional precision does not match expectation\n");
     232            0 :           TALER_TESTING_interpreter_fail (gis->is);
     233            0 :           return;
     234              :         }
     235              :       }
     236            8 :       else if (have_precision)
     237              :       {
     238            8 :         if (pgr->details.ok.unit_precision_level != *expected_precision)
     239              :         {
     240            0 :           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     241              :                       "Product fractional precision does not match\n");
     242            0 :           TALER_TESTING_interpreter_fail (gis->is);
     243            0 :           return;
     244              :         }
     245              :       }
     246            0 :       else if (! pgr->details.ok.unit_allow_fraction)
     247              :       {
     248            0 :         if (0 != pgr->details.ok.unit_precision_level)
     249              :         {
     250            0 :           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     251              :                       "Product fractional precision should be zero when disallowed\n");
     252            0 :           TALER_TESTING_interpreter_fail (gis->is);
     253            0 :           return;
     254              :         }
     255              :       }
     256            0 :       else if (pgr->details.ok.unit_precision_level > 8)
     257              :       {
     258            0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     259              :                     "Product fractional precision exceeds supported range\n");
     260            0 :         TALER_TESTING_interpreter_fail (gis->is);
     261            0 :         return;
     262              :       }
     263              :     }
     264              :     {
     265              :       const char *expected_image;
     266              : 
     267           12 :       if (GNUNET_OK !=
     268           12 :           TALER_TESTING_get_trait_product_image (product_cmd,
     269              :                                                  &expected_image))
     270            0 :         TALER_TESTING_interpreter_fail (gis->is);
     271           12 :       if (0 != strcmp (pgr->details.ok.image,
     272              :                        expected_image))
     273              :       {
     274            0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     275              :                     "Product image does not match\n");
     276            0 :         TALER_TESTING_interpreter_fail (gis->is);
     277            0 :         return;
     278              :       }
     279              :     }
     280              :     {
     281              :       const json_t *expected_taxes;
     282              : 
     283           12 :       if (GNUNET_OK !=
     284           12 :           TALER_TESTING_get_trait_taxes (product_cmd,
     285              :                                          &expected_taxes))
     286            0 :         TALER_TESTING_interpreter_fail (gis->is);
     287           12 :       if (1 != json_equal (pgr->details.ok.taxes,
     288              :                            expected_taxes))
     289              :       {
     290            0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     291              :                     "Product taxes do not match\n");
     292            0 :         TALER_TESTING_interpreter_fail (gis->is);
     293            0 :         return;
     294              :       }
     295              :     }
     296              :     {
     297              :       const char *expected_unit;
     298              : 
     299           12 :       if (GNUNET_OK !=
     300           12 :           TALER_TESTING_get_trait_product_unit (product_cmd,
     301              :                                                 &expected_unit))
     302            0 :         TALER_TESTING_interpreter_fail (gis->is);
     303           12 :       if (0 != strcmp (pgr->details.ok.unit,
     304              :                        expected_unit))
     305              :       {
     306            0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     307              :                     "Product unit does not match\n");
     308            0 :         TALER_TESTING_interpreter_fail (gis->is);
     309            0 :         return;
     310              :       }
     311              :     }
     312              :     {
     313              :       const json_t *expected_location;
     314              : 
     315           12 :       if (GNUNET_OK !=
     316           12 :           TALER_TESTING_get_trait_address (product_cmd,
     317              :                                            &expected_location))
     318            0 :         TALER_TESTING_interpreter_fail (gis->is);
     319           12 :       if (NULL != expected_location)
     320              :       {
     321           10 :         if (1 != json_equal (pgr->details.ok.location,
     322              :                              expected_location))
     323              :         {
     324            0 :           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     325              :                       "Product location does not match\n");
     326            0 :           TALER_TESTING_interpreter_fail (gis->is);
     327            0 :           return;
     328              :         }
     329              :       }
     330              :     }
     331              :     {
     332              :       const int64_t *expected_total_stock;
     333              : 
     334           12 :       if (GNUNET_OK !=
     335           12 :           TALER_TESTING_get_trait_product_stock (product_cmd,
     336              :                                                  &expected_total_stock))
     337            0 :         TALER_TESTING_interpreter_fail (gis->is);
     338           12 :       if (pgr->details.ok.total_stock != *expected_total_stock)
     339              :       {
     340            0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     341              :                     "Product total stock does not match\n");
     342            0 :         TALER_TESTING_interpreter_fail (gis->is);
     343            0 :         return;
     344              :       }
     345              :     }
     346              :     {
     347              :       const struct GNUNET_TIME_Timestamp *expected_next_restock;
     348              : 
     349           12 :       if (GNUNET_OK !=
     350           12 :           TALER_TESTING_get_trait_timestamp (product_cmd,
     351              :                                              0,
     352              :                                              &expected_next_restock))
     353            0 :         TALER_TESTING_interpreter_fail (gis->is);
     354           12 :       if (GNUNET_TIME_timestamp_cmp (pgr->details.ok.next_restock,
     355              :                                      !=,
     356              :                                      *expected_next_restock))
     357              :       {
     358            0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     359              :                     "Product next restock does not match\n");
     360            0 :         TALER_TESTING_interpreter_fail (gis->is);
     361            0 :         return;
     362              :       }
     363              :     }
     364           12 :     break;
     365            4 :   case MHD_HTTP_UNAUTHORIZED:
     366            4 :     break;
     367            8 :   case MHD_HTTP_NOT_FOUND:
     368            8 :     break;
     369            0 :   default:
     370            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     371              :                 "Unhandled HTTP status.\n");
     372              :   }
     373           24 :   TALER_TESTING_interpreter_next (gis->is);
     374              : }
     375              : 
     376              : 
     377              : /**
     378              :  * Run the "GET product" CMD.
     379              :  *
     380              :  *
     381              :  * @param cls closure.
     382              :  * @param cmd command being run now.
     383              :  * @param is interpreter state.
     384              :  */
     385              : static void
     386           24 : get_product_run (void *cls,
     387              :                  const struct TALER_TESTING_Command *cmd,
     388              :                  struct TALER_TESTING_Interpreter *is)
     389              : {
     390           24 :   struct GetProductState *gis = cls;
     391              : 
     392           24 :   gis->is = is;
     393           24 :   gis->igh = TALER_MERCHANT_product_get (TALER_TESTING_interpreter_get_context (
     394              :                                            is),
     395              :                                          gis->merchant_url,
     396              :                                          gis->product_id,
     397              :                                          &get_product_cb,
     398              :                                          gis);
     399           24 :   GNUNET_assert (NULL != gis->igh);
     400           24 : }
     401              : 
     402              : 
     403              : /**
     404              :  * Free the state of a "GET product" CMD, and possibly
     405              :  * cancel a pending operation thereof.
     406              :  *
     407              :  * @param cls closure.
     408              :  * @param cmd command being run.
     409              :  */
     410              : static void
     411           24 : get_product_cleanup (void *cls,
     412              :                      const struct TALER_TESTING_Command *cmd)
     413              : {
     414           24 :   struct GetProductState *gis = cls;
     415              : 
     416           24 :   if (NULL != gis->igh)
     417              :   {
     418            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     419              :                 "GET /products/$ID operation did not complete\n");
     420            0 :     TALER_MERCHANT_product_get_cancel (gis->igh);
     421              :   }
     422           24 :   GNUNET_free (gis);
     423           24 : }
     424              : 
     425              : 
     426              : struct TALER_TESTING_Command
     427           20 : TALER_TESTING_cmd_merchant_get_product (const char *label,
     428              :                                         const char *merchant_url,
     429              :                                         const char *product_id,
     430              :                                         unsigned int http_status,
     431              :                                         const char *product_reference)
     432              : {
     433           20 :   return TALER_TESTING_cmd_merchant_get_product2 (label,
     434              :                                                   merchant_url,
     435              :                                                   product_id,
     436              :                                                   http_status,
     437              :                                                   product_reference,
     438              :                                                   NULL);
     439              : }
     440              : 
     441              : 
     442              : struct TALER_TESTING_Command
     443           24 : TALER_TESTING_cmd_merchant_get_product2 (
     444              :   const char *label,
     445              :   const char *merchant_url,
     446              :   const char *product_id,
     447              :   unsigned int http_status,
     448              :   const char *product_reference,
     449              :   const struct TALER_TESTING_ProductUnitExpectations *unit_expectations)
     450              : {
     451              :   struct GetProductState *gis;
     452              : 
     453           24 :   gis = GNUNET_new (struct GetProductState);
     454           24 :   gis->merchant_url = merchant_url;
     455           24 :   gis->product_id = product_id;
     456           24 :   gis->http_status = http_status;
     457           24 :   gis->product_reference = product_reference;
     458           24 :   gis->unit_expectations = unit_expectations;
     459              :   {
     460           24 :     struct TALER_TESTING_Command cmd = {
     461              :       .cls = gis,
     462              :       .label = label,
     463              :       .run = &get_product_run,
     464              :       .cleanup = &get_product_cleanup
     465              :     };
     466              : 
     467           24 :     return cmd;
     468              :   }
     469              : }
     470              : 
     471              : 
     472              : /* end of testing_api_cmd_get_product.c */
        

Generated by: LCOV version 2.0-1