LCOV - code coverage report
Current view: top level - testing - testing_api_cmd_get_product.c (source / functions) Hit Total Coverage
Test: GNU Taler merchant coverage report Lines: 63 106 59.4 %
Date: 2021-08-30 06:54:17 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2020 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             : 
      69             : 
      70             : /**
      71             :  * Callback for a /get/product/$ID operation.
      72             :  *
      73             :  * @param cls closure for this function
      74             :  * @param hr HTTP response details
      75             :  * @param description description of the product
      76             :  * @param description_i18n Map from IETF BCP 47 language tags to localized descriptions
      77             :  * @param unit unit in which the product is measured (liters, kilograms, packages, etc.)
      78             :  * @param price the price for one @a unit of the product, zero is used to imply that
      79             :  *              this product is not sold separately or that the price is not fixed and
      80             :  *              must be supplied by the front-end.  If non-zero, price must include
      81             :  *              applicable taxes.
      82             :  * @param image base64-encoded product image
      83             :  * @param taxes list of taxes paid by the merchant
      84             :  * @param total_stock in @a units, -1 to indicate "infinite" (i.e. electronic books),
      85             :  *                does NOT indicate remaining stocks, to get remaining stocks,
      86             :  *                subtract @a total_sold and @a total_lost. Note that this still
      87             :  *                does not then say how many of the remaining inventory are locked.
      88             :  * @param total_sold in @a units, total number of @a unit of product sold
      89             :  * @param total_lost in @a units, total number of @a unit of product lost from inventory
      90             :  * @param location where the product is in stock
      91             :  * @param next_restock when the next restocking is expected to happen, 0 for unknown,
      92             :  *                     #GNUNET_TIME_UNIT_FOREVER_ABS for 'never'.
      93             :  */
      94             : static void
      95           8 : get_product_cb (void *cls,
      96             :                 const struct TALER_MERCHANT_HttpResponse *hr,
      97             :                 const char *description,
      98             :                 const json_t *description_i18n,
      99             :                 const char *unit,
     100             :                 const struct TALER_Amount *price,
     101             :                 const char *image,
     102             :                 const json_t *taxes,
     103             :                 int64_t total_stock,
     104             :                 uint64_t total_sold,
     105             :                 uint64_t total_lost,
     106             :                 const json_t *location,
     107             :                 struct GNUNET_TIME_Absolute next_restock)
     108             : {
     109           8 :   struct GetProductState *gis = cls;
     110             :   const struct TALER_TESTING_Command *product_cmd;
     111             : 
     112           8 :   gis->igh = NULL;
     113           8 :   if (gis->http_status != hr->http_status)
     114             :   {
     115           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     116             :                 "Unexpected response code %u (%d) to command %s\n",
     117             :                 hr->http_status,
     118             :                 (int) hr->ec,
     119             :                 TALER_TESTING_interpreter_get_current_label (gis->is));
     120           0 :     TALER_TESTING_interpreter_fail (gis->is);
     121           0 :     return;
     122             :   }
     123           8 :   switch (hr->http_status)
     124             :   {
     125           2 :   case MHD_HTTP_OK:
     126             :     {
     127             :       const char *expected_description;
     128             : 
     129           2 :       product_cmd = TALER_TESTING_interpreter_lookup_command (
     130             :         gis->is,
     131             :         gis->product_reference);
     132           2 :       if (GNUNET_OK !=
     133           2 :           TALER_TESTING_get_trait_string (product_cmd,
     134             :                                           0,
     135             :                                           &expected_description))
     136           0 :         TALER_TESTING_interpreter_fail (gis->is);
     137           2 :       if (0 != strcmp (description,
     138             :                        expected_description))
     139             :       {
     140           0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     141             :                     "Product description does not match\n");
     142           0 :         TALER_TESTING_interpreter_fail (gis->is);
     143           0 :         return;
     144             :       }
     145             :     }
     146             :     {
     147             :       const json_t *expected_description_i18n;
     148           2 :       if (GNUNET_OK !=
     149           2 :           TALER_TESTING_get_trait_json (product_cmd,
     150             :                                         0,
     151             :                                         &expected_description_i18n))
     152           0 :         TALER_TESTING_interpreter_fail (gis->is);
     153           2 :       if (1 != json_equal (description_i18n,
     154             :                            expected_description_i18n))
     155             :       {
     156           0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     157             :                     "Product description i18n does not match\n");
     158           0 :         TALER_TESTING_interpreter_fail (gis->is);
     159           0 :         return;
     160             :       }
     161             :     }
     162             :     {
     163             :       const struct TALER_Amount *expected_price;
     164           2 :       if (GNUNET_OK !=
     165           2 :           TALER_TESTING_get_trait_amount_obj (product_cmd,
     166             :                                               0,
     167             :                                               &expected_price))
     168           0 :         TALER_TESTING_interpreter_fail (gis->is);
     169           2 :       if ((GNUNET_OK != TALER_amount_cmp_currency (price,
     170           2 :                                                    expected_price)) ||
     171           2 :           (0 != TALER_amount_cmp (price,
     172             :                                   expected_price)))
     173             :       {
     174           0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     175             :                     "Product price does not match\n");
     176           0 :         TALER_TESTING_interpreter_fail (gis->is);
     177           0 :         return;
     178             :       }
     179             :     }
     180             :     {
     181             :       const char *expected_image;
     182             : 
     183           2 :       if (GNUNET_OK !=
     184           2 :           TALER_TESTING_get_trait_string (product_cmd,
     185             :                                           3,
     186             :                                           &expected_image))
     187           0 :         TALER_TESTING_interpreter_fail (gis->is);
     188           2 :       if (0 != strcmp (image,
     189             :                        expected_image))
     190             :       {
     191           0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     192             :                     "Product image does not match\n");
     193           0 :         TALER_TESTING_interpreter_fail (gis->is);
     194           0 :         return;
     195             :       }
     196             :     }
     197             :     {
     198             :       const json_t *expected_taxes;
     199           2 :       if (GNUNET_OK !=
     200           2 :           TALER_TESTING_get_trait_json (product_cmd,
     201             :                                         2,
     202             :                                         &expected_taxes))
     203           0 :         TALER_TESTING_interpreter_fail (gis->is);
     204           2 :       if (1 != json_equal (taxes,
     205             :                            expected_taxes))
     206             :       {
     207           0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     208             :                     "Product taxes do not match\n");
     209           0 :         TALER_TESTING_interpreter_fail (gis->is);
     210           0 :         return;
     211             :       }
     212             :     }
     213             :     {
     214             :       const char *expected_unit;
     215           2 :       if (GNUNET_OK !=
     216           2 :           TALER_TESTING_get_trait_string (product_cmd,
     217             :                                           1,
     218             :                                           &expected_unit))
     219           0 :         TALER_TESTING_interpreter_fail (gis->is);
     220           2 :       if (0 != strcmp (unit,
     221             :                        expected_unit))
     222             :       {
     223           0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     224             :                     "Product unit does not match\n");
     225           0 :         TALER_TESTING_interpreter_fail (gis->is);
     226           0 :         return;
     227             :       }
     228             :     }
     229             :     {
     230             :       const json_t *expected_location;
     231           2 :       if (GNUNET_OK !=
     232           2 :           TALER_TESTING_get_trait_json (product_cmd,
     233             :                                         3,
     234             :                                         &expected_location))
     235           0 :         TALER_TESTING_interpreter_fail (gis->is);
     236           2 :       if (1 != json_equal (location,
     237             :                            expected_location))
     238             :       {
     239           0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     240             :                     "Product location does not match\n");
     241           0 :         TALER_TESTING_interpreter_fail (gis->is);
     242           0 :         return;
     243             :       }
     244             :     }
     245             :     {
     246             :       const int64_t *expected_total_stock;
     247           2 :       if (GNUNET_OK !=
     248           2 :           TALER_TESTING_get_trait_int64 (product_cmd,
     249             :                                          0,
     250             :                                          &expected_total_stock))
     251           0 :         TALER_TESTING_interpreter_fail (gis->is);
     252           2 :       if (total_stock != *expected_total_stock)
     253             :       {
     254           0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     255             :                     "Product total stock does not match\n");
     256           0 :         TALER_TESTING_interpreter_fail (gis->is);
     257           0 :         return;
     258             :       }
     259             :     }
     260             :     {
     261             :       const struct GNUNET_TIME_Absolute *expected_next_restock;
     262             :       struct GNUNET_TIME_Absolute expected_next_restock_round;
     263           2 :       if (GNUNET_OK !=
     264           2 :           TALER_TESTING_get_trait_absolute_time (product_cmd,
     265             :                                                  0,
     266             :                                                  &expected_next_restock))
     267           0 :         TALER_TESTING_interpreter_fail (gis->is);
     268           2 :       expected_next_restock_round = *expected_next_restock;
     269           2 :       GNUNET_TIME_round_abs (&expected_next_restock_round);
     270           2 :       if (next_restock.abs_value_us != expected_next_restock_round.abs_value_us)
     271             :       {
     272           0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     273             :                     "Product next restock does not match\n");
     274           0 :         TALER_TESTING_interpreter_fail (gis->is);
     275           0 :         return;
     276             :       }
     277             :     }
     278           2 :     break;
     279           2 :   case MHD_HTTP_UNAUTHORIZED:
     280           2 :     break;
     281           4 :   case MHD_HTTP_NOT_FOUND:
     282           4 :     break;
     283           0 :   default:
     284           0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     285             :                 "Unhandled HTTP status.\n");
     286             :   }
     287           8 :   TALER_TESTING_interpreter_next (gis->is);
     288             : }
     289             : 
     290             : 
     291             : /**
     292             :  * Run the "GET product" CMD.
     293             :  *
     294             :  *
     295             :  * @param cls closure.
     296             :  * @param cmd command being run now.
     297             :  * @param is interpreter state.
     298             :  */
     299             : static void
     300           8 : get_product_run (void *cls,
     301             :                  const struct TALER_TESTING_Command *cmd,
     302             :                  struct TALER_TESTING_Interpreter *is)
     303             : {
     304           8 :   struct GetProductState *gis = cls;
     305             : 
     306           8 :   gis->is = is;
     307           8 :   gis->igh = TALER_MERCHANT_product_get (is->ctx,
     308             :                                          gis->merchant_url,
     309             :                                          gis->product_id,
     310             :                                          &get_product_cb,
     311             :                                          gis);
     312           8 :   GNUNET_assert (NULL != gis->igh);
     313           8 : }
     314             : 
     315             : 
     316             : /**
     317             :  * Free the state of a "GET product" CMD, and possibly
     318             :  * cancel a pending operation thereof.
     319             :  *
     320             :  * @param cls closure.
     321             :  * @param cmd command being run.
     322             :  */
     323             : static void
     324           8 : get_product_cleanup (void *cls,
     325             :                      const struct TALER_TESTING_Command *cmd)
     326             : {
     327           8 :   struct GetProductState *gis = cls;
     328             : 
     329           8 :   if (NULL != gis->igh)
     330             :   {
     331           0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     332             :                 "GET /products/$ID operation did not complete\n");
     333           0 :     TALER_MERCHANT_product_get_cancel (gis->igh);
     334             :   }
     335           8 :   GNUNET_free (gis);
     336           8 : }
     337             : 
     338             : 
     339             : struct TALER_TESTING_Command
     340           8 : TALER_TESTING_cmd_merchant_get_product (const char *label,
     341             :                                         const char *merchant_url,
     342             :                                         const char *product_id,
     343             :                                         unsigned int http_status,
     344             :                                         const char *product_reference)
     345             : {
     346             :   struct GetProductState *gis;
     347             : 
     348           8 :   gis = GNUNET_new (struct GetProductState);
     349           8 :   gis->merchant_url = merchant_url;
     350           8 :   gis->product_id = product_id;
     351           8 :   gis->http_status = http_status;
     352           8 :   gis->product_reference = product_reference;
     353             :   {
     354           8 :     struct TALER_TESTING_Command cmd = {
     355             :       .cls = gis,
     356             :       .label = label,
     357             :       .run = &get_product_run,
     358             :       .cleanup = &get_product_cleanup
     359             :     };
     360             : 
     361           8 :     return cmd;
     362             :   }
     363             : }
     364             : 
     365             : 
     366             : /* end of testing_api_cmd_get_product.c */

Generated by: LCOV version 1.14