LCOV - code coverage report
Current view: top level - lib - testing_api_cmd_history.c (source / functions) Hit Total Coverage
Test: rcoverage.info Lines: 57 74 77.0 %
Date: 2018-09-19 06:18:31 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2014-2018 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             : /**
      21             :  * @file lib/testing_api_cmd_history.c
      22             :  * @brief command to test the /history API.
      23             :  * @author Marcello Stanisci
      24             :  */
      25             : 
      26             : #include "platform.h"
      27             : #include <taler/taler_exchange_service.h>
      28             : #include <taler/taler_testing_lib.h>
      29             : #include "taler_merchant_service.h"
      30             : #include "taler_merchant_testing_lib.h"
      31             : 
      32             : 
      33             : 
      34             : /**
      35             :  * State for a "history" CMD.
      36             :  */
      37             : struct HistoryState
      38             : {
      39             : 
      40             :   /**
      41             :    * Expected status code.
      42             :    */
      43             :   unsigned int http_status;
      44             : 
      45             :   /**
      46             :    * The merchant instance executing this CMD.
      47             :    */
      48             :   const char *instance;
      49             : 
      50             :   /**
      51             :    * URL of the merchant backend serving the /history request.
      52             :    */
      53             :   const char *merchant_url;
      54             : 
      55             :   /**
      56             :    * The CURL context.
      57             :    */
      58             :   struct GNUNET_CURL_Context *ctx;
      59             : 
      60             :   /**
      61             :    * The interpreter state.
      62             :    */
      63             :   struct TALER_TESTING_Interpreter *is;
      64             : 
      65             :   /**
      66             :    * Handle to the /history operation.
      67             :    */
      68             :   struct TALER_MERCHANT_HistoryOperation *ho;
      69             : 
      70             :   /**
      71             :    * Only history entries younger than this
      72             :    * value will be returned.
      73             :    */
      74             :   struct GNUNET_TIME_Absolute time;
      75             : 
      76             :   /**
      77             :    * First row index we want in the results.
      78             :    */
      79             :   unsigned int start;
      80             : 
      81             :   /**
      82             :    * How many rows we want the response to contain, at most.
      83             :    */
      84             :   unsigned int nrows;
      85             : 
      86             :   /**
      87             :    * Expected number of history entries returned by the
      88             :    * backend.
      89             :    */
      90             :   unsigned int nresult;
      91             : };
      92             : 
      93             : /**
      94             :  * Parse given JSON object to absolute time.
      95             :  *
      96             :  * @param root the json object representing data
      97             :  * @param[out] ret where to write the data
      98             :  * @return #GNUNET_OK upon successful parsing;
      99             :  *         #GNUNET_SYSERR upon error
     100             :  */
     101             : static int
     102           3 : parse_abs_time (json_t *root,
     103             :                 struct GNUNET_TIME_Absolute *ret)
     104             : {
     105             :   const char *val;
     106             :   unsigned long long int tval;
     107             : 
     108           3 :   val = json_string_value (root);
     109           3 :   if (NULL == val)
     110             :   {
     111           0 :     GNUNET_break_op (0);
     112           0 :     return GNUNET_SYSERR;
     113             :   }
     114           3 :   if ( (0 == strcasecmp (val,
     115           3 :                          "/forever/")) ||
     116           3 :        (0 == strcasecmp (val,
     117           3 :                          "/end of time/")) ||
     118           3 :        (0 == strcasecmp (val,
     119             :                          "/never/")) )
     120             :   {
     121           0 :     *ret = GNUNET_TIME_UNIT_FOREVER_ABS;
     122           0 :     return GNUNET_OK;
     123             :   }
     124           3 :   if (1 != sscanf (val,
     125             :                    "/Date(%llu)/",
     126             :                    &tval))
     127             :   {
     128           0 :     GNUNET_break_op (0);
     129           0 :     return GNUNET_SYSERR;
     130             :   }
     131             :   /* Time is in seconds in JSON, but in microseconds in
     132             :    * GNUNET_TIME_Absolute */
     133           3 :   ret->abs_value_us = tval * 1000LL * 1000LL;
     134           3 :   if ( (ret->abs_value_us) / 1000LL / 1000LL != tval)
     135             :   {
     136             :     /* Integer overflow */
     137           0 :     GNUNET_break_op (0);
     138           0 :     return GNUNET_SYSERR;
     139             :   }
     140           3 :   return GNUNET_OK;
     141             : }
     142             : 
     143             : 
     144             : /**
     145             :  * Callback for a /history request; checks that (1) HTTP status
     146             :  * is expected, the number of rows returned is expected, and that
     147             :  * the rows are sorted from the youngest to the oldest record.
     148             :  *
     149             :  * @param cls closure
     150             :  * @param http_status HTTP status returned by the merchant
     151             :  *        backend
     152             :  * @param ec taler-specific error code
     153             :  * @param json actual body containing the history
     154             :  */
     155             : static void
     156           5 : history_cb (void *cls,
     157             :             unsigned int http_status,
     158             :             enum TALER_ErrorCode ec,
     159             :             const json_t *json)
     160             : {
     161             : 
     162           5 :   struct HistoryState *hs = cls;
     163             :   unsigned int nresult;
     164             :   struct GNUNET_TIME_Absolute last_timestamp;
     165             :   struct GNUNET_TIME_Absolute entry_timestamp;
     166             : 
     167           5 :   hs->ho = NULL;
     168             : 
     169             : 
     170           5 :   if (hs->http_status != http_status)
     171           2 :       TALER_TESTING_FAIL (hs->is);
     172             : 
     173           5 :   if (0 == hs->http_status)
     174             :   {
     175             :     /* 0 was caused intentionally by the tests,
     176             :      * move on without further checking. */
     177           2 :     TALER_TESTING_interpreter_next (hs->is); 
     178           2 :     return;
     179             :   }
     180             : 
     181           3 :   nresult = json_array_size (json);
     182           3 :   if (hs->nresult != nresult)
     183             :   {
     184           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     185             :                 "Unexpected number of history entries."
     186             :                 " Got %d, expected %d\n",
     187             :                 nresult,
     188             :                 hs->nresult);
     189           0 :     TALER_TESTING_FAIL (hs->is);
     190             :   }
     191             : 
     192           3 :   last_timestamp = GNUNET_TIME_absolute_get ();
     193           3 :   last_timestamp = GNUNET_TIME_absolute_add
     194             :     (last_timestamp, GNUNET_TIME_UNIT_DAYS);
     195             :   json_t *entry;
     196             :   json_t *timestamp;
     197             :   size_t index;
     198           6 :   json_array_foreach (json, index, entry)
     199             :   {
     200           3 :     timestamp = json_object_get (entry, "timestamp");
     201           3 :     if (GNUNET_OK != parse_abs_time (timestamp, &entry_timestamp))
     202           0 :       TALER_TESTING_FAIL (hs->is);
     203             : 
     204           3 :     if (last_timestamp.abs_value_us < entry_timestamp.abs_value_us)
     205             :     {
     206           0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     207             :                   "History entries are NOT"
     208             :                   " sorted from younger to older\n");
     209           0 :       TALER_TESTING_interpreter_fail (hs->is);
     210           0 :       return;
     211             :     }
     212             : 
     213           3 :     last_timestamp = entry_timestamp;
     214             :   }
     215             : 
     216           3 :   TALER_TESTING_interpreter_next (hs->is);
     217             : }
     218             : 
     219             : /**
     220             :  * Free the state for a "history" CMD, and possibly cancel
     221             :  * any pending operation thereof.
     222             :  *
     223             :  * @param cls closure
     224             :  * @param cmd command being freed now.
     225             :  */
     226             : static void
     227           5 : history_cleanup (void *cls,
     228             :                  const struct TALER_TESTING_Command *cmd)
     229             : {
     230           5 :   struct HistoryState *hs = cls;
     231             : 
     232           5 :   if (NULL != hs->ho)
     233             :   {
     234           0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     235             :                 "/history operation did not complete\n");
     236           0 :     TALER_MERCHANT_history_cancel (hs->ho);
     237             :   }
     238           5 :   GNUNET_free (hs);
     239           5 : }
     240             : 
     241             : /**
     242             :  * Run a "history" CMD.
     243             :  *
     244             :  * @param cls closure.
     245             :  * @param cmd current command.
     246             :  * @param is interpreter state.
     247             :  */
     248             : static void
     249           5 : history_run (void *cls,
     250             :              const struct TALER_TESTING_Command *cmd,
     251             :              struct TALER_TESTING_Interpreter *is)
     252             : {
     253           5 :   struct HistoryState *hs = cls;
     254             :   
     255           5 :   hs->is = is;
     256           5 :   if (0 == hs->time.abs_value_us)
     257             :   {
     258           4 :     hs->time = GNUNET_TIME_absolute_add
     259             :       (GNUNET_TIME_absolute_get (),
     260             :        GNUNET_TIME_UNIT_HOURS);
     261           4 :     GNUNET_TIME_round_abs (&hs->time);
     262             :   }
     263           5 :   if ( NULL ==
     264           5 :      ( hs->ho = TALER_MERCHANT_history (hs->ctx,
     265             :                                         hs->merchant_url,
     266             :                                         "default",
     267             :                                         hs->start,
     268             :                                         hs->nrows,
     269             :                                         hs->time,
     270             :                                         &history_cb,
     271             :                                         hs)))
     272           0 :   TALER_TESTING_FAIL (is);
     273             : }
     274             : 
     275             : 
     276             : /**
     277             :  * Make a "history" command.
     278             :  *
     279             :  * @param label command label.
     280             :  * @param merchant_url base URL of the merchant serving the
     281             :  *        request.
     282             :  * @param ctx CURL context.
     283             :  * @param http_status expected HTTP response code
     284             :  * @param time limit towards the past for the history
     285             :  *        records we want returned.
     286             :  * @param nresult how many results are expected
     287             :  * @param start first row id we want in the result.
     288             :  * @param nrows how many row we want to receive, at most.
     289             :  */
     290             : struct TALER_TESTING_Command
     291           5 : TALER_TESTING_cmd_history (const char *label,
     292             :                            const char *merchant_url,
     293             :                            struct GNUNET_CURL_Context *ctx,
     294             :                            unsigned int http_status,
     295             :                            struct GNUNET_TIME_Absolute time,
     296             :                            unsigned int nresult,
     297             :                            unsigned int start,
     298             :                            unsigned int nrows)
     299             : {
     300             :   struct HistoryState *hs;
     301             :   struct TALER_TESTING_Command cmd;
     302             : 
     303           5 :   hs = GNUNET_new (struct HistoryState);
     304           5 :   hs->http_status = http_status;
     305           5 :   hs->time = time;
     306           5 :   hs->nresult = nresult;
     307           5 :   hs->start = start;
     308           5 :   hs->nrows = nrows;
     309           5 :   hs->merchant_url = merchant_url;
     310           5 :   hs->ctx = ctx;
     311             : 
     312           5 :   cmd.cls = hs;
     313           5 :   cmd.label = label;
     314           5 :   cmd.run = &history_run;
     315           5 :   cmd.cleanup = &history_cleanup;
     316             :   
     317           5 :   return cmd;
     318             : }
     319             : 
     320             : /* end of testing_api_cmd_history.c */

Generated by: LCOV version 1.13