LCOV - code coverage report
Current view: top level - lib - testing_api_cmd_history.c (source / functions) Hit Total Coverage
Test: rcoverage.info Lines: 54 74 73.0 %
Date: 2018-05-16 06:16:58 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             : struct HistoryState
      34             : {
      35             : 
      36             :   /**
      37             :    * Expected status code.
      38             :    */
      39             :   unsigned int http_status;
      40             : 
      41             :   /**
      42             :    * The merchant instance.
      43             :    */
      44             :   const char *instance;
      45             : 
      46             :   /**
      47             :    * URL of the merchant backend.
      48             :    */
      49             :   const char *merchant_url;
      50             : 
      51             :   /**
      52             :    * The curl context; used to be fed to the merchant lib.
      53             :    */
      54             :   struct GNUNET_CURL_Context *ctx;
      55             : 
      56             :   /**
      57             :    * The interpreter state.
      58             :    */
      59             :   struct TALER_TESTING_Interpreter *is;
      60             : 
      61             :   /**
      62             :    * Handle to /history.
      63             :    */
      64             :   struct TALER_MERCHANT_HistoryOperation *ho;
      65             : 
      66             :   /**
      67             :    * FIXME
      68             :    */
      69             :   struct GNUNET_TIME_Absolute time;
      70             : 
      71             :   /**
      72             :    * FIXME
      73             :    */
      74             :   unsigned int start;
      75             : 
      76             :   /**
      77             :    * FIXME
      78             :    */
      79             :   unsigned int nrows;
      80             : 
      81             :   /**
      82             :    * FIXME
      83             :    */
      84             :   unsigned int nresult;
      85             : };
      86             : 
      87             : /**
      88             :  * Parse given JSON object to absolute time.
      89             :  *
      90             :  * @param root the json object representing data
      91             :  * @param[out] ret where to write the data
      92             :  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
      93             :  */
      94             : static int
      95           3 : parse_abs_time (json_t *root,
      96             :                 struct GNUNET_TIME_Absolute *ret)
      97             : {
      98             :   const char *val;
      99             :   unsigned long long int tval;
     100             : 
     101           3 :   val = json_string_value (root);
     102           3 :   if (NULL == val)
     103             :   {
     104           0 :     GNUNET_break_op (0);
     105           0 :     return GNUNET_SYSERR;
     106             :   }
     107           3 :   if ( (0 == strcasecmp (val,
     108           3 :                          "/forever/")) ||
     109           3 :        (0 == strcasecmp (val,
     110           3 :                          "/end of time/")) ||
     111           3 :        (0 == strcasecmp (val,
     112             :                          "/never/")) )
     113             :   {
     114           0 :     *ret = GNUNET_TIME_UNIT_FOREVER_ABS;
     115           0 :     return GNUNET_OK;
     116             :   }
     117           3 :   if (1 != sscanf (val,
     118             :                    "/Date(%llu)/",
     119             :                    &tval))
     120             :   {
     121           0 :     GNUNET_break_op (0);
     122           0 :     return GNUNET_SYSERR;
     123             :   }
     124             :   /* Time is in seconds in JSON, but in microseconds in GNUNET_TIME_Absolute */
     125           3 :   ret->abs_value_us = tval * 1000LL * 1000LL;
     126           3 :   if ( (ret->abs_value_us) / 1000LL / 1000LL != tval)
     127             :   {
     128             :     /* Integer overflow */
     129           0 :     GNUNET_break_op (0);
     130           0 :     return GNUNET_SYSERR;
     131             :   }
     132           3 :   return GNUNET_OK;
     133             : }
     134             : 
     135             : 
     136             : /**
     137             :  * Callback for a /history request. It's up to this function
     138             :  * how to render the array containing transactions details (FIXME
     139             :  * link to documentation)
     140             :  *
     141             :  * @param cls closure
     142             :  * @param http_status HTTP status returned by the merchant
     143             :  *        backend
     144             :  * @param ec taler-specific error code
     145             :  * @param json actual body containing history
     146             :  */
     147             : static void
     148           3 : history_cb (void *cls,
     149             :             unsigned int http_status,
     150             :             enum TALER_ErrorCode ec,
     151             :             const json_t *json)
     152             : {
     153             : 
     154           3 :   struct HistoryState *hs = cls;
     155             :   unsigned int nresult;
     156             :   struct GNUNET_TIME_Absolute last_timestamp;
     157             :   struct GNUNET_TIME_Absolute entry_timestamp;
     158             : 
     159           3 :   hs->ho = NULL;
     160             : 
     161             : 
     162           3 :   if (hs->http_status != http_status)
     163           0 :       TALER_TESTING_FAIL (hs->is);
     164             : 
     165           3 :   if (0 == hs->http_status)
     166             :   {
     167             :     /* 0 was caused intentionally by the tests,
     168             :      * move on without further checking. */
     169           0 :     TALER_TESTING_interpreter_next (hs->is); 
     170           0 :     return;
     171             :   }
     172             : 
     173           3 :   nresult = json_array_size (json);
     174           3 :   if (hs->nresult != nresult)
     175             :   {
     176           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     177             :                 "Unexpected number of history entries."
     178             :                 " Got %d, expected %d\n",
     179             :                 nresult,
     180             :                 hs->nresult);
     181           0 :     TALER_TESTING_FAIL (hs->is);
     182             :   }
     183             : 
     184           3 :   last_timestamp = GNUNET_TIME_absolute_get ();
     185           3 :   last_timestamp = GNUNET_TIME_absolute_add
     186             :     (last_timestamp, GNUNET_TIME_UNIT_DAYS);
     187             :   json_t *entry;
     188             :   json_t *timestamp;
     189             :   size_t index;
     190           6 :   json_array_foreach (json, index, entry)
     191             :   {
     192           3 :     timestamp = json_object_get (entry, "timestamp");
     193           3 :     if (GNUNET_OK != parse_abs_time (timestamp, &entry_timestamp))
     194           0 :       TALER_TESTING_FAIL (hs->is);
     195             : 
     196           3 :     if (last_timestamp.abs_value_us < entry_timestamp.abs_value_us)
     197             :     {
     198           0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     199             :                   "History entries are NOT"
     200             :                   " sorted from younger to older\n");
     201           0 :       TALER_TESTING_interpreter_fail (hs->is);
     202           0 :       return;
     203             :     }
     204             : 
     205           3 :     last_timestamp = entry_timestamp;
     206             :   }
     207             : 
     208           3 :   TALER_TESTING_interpreter_next (hs->is);
     209             : }
     210             : 
     211             : /**
     212             :  * Clean up after the command.  Run during forced termination
     213             :  * (CTRL-C) or test failure or test success.
     214             :  *
     215             :  * @param cls closure
     216             :  */
     217             : static void
     218           3 : history_cleanup (void *cls,
     219             :                  const struct TALER_TESTING_Command *cmd)
     220             : {
     221           3 :   struct HistoryState *hs = cls;
     222             : 
     223           3 :   if (NULL != hs->ho)
     224             :   {
     225           0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     226             :                 "/history operation did not complete\n");
     227           0 :     TALER_MERCHANT_history_cancel (hs->ho);
     228             :   }
     229           3 :   GNUNET_free (hs);
     230           3 : }
     231             : 
     232             : /**
     233             :  * Runs the command.  Note that upon return, the interpreter
     234             :  * will not automatically run the next command, as the command
     235             :  * may continue asynchronously in other scheduler tasks.  Thus,
     236             :  * the command must ensure to eventually call
     237             :  * #TALER_TESTING_interpreter_next() or
     238             :  * #TALER_TESTING_interpreter_fail().
     239             :  *
     240             :  * @param is interpreter state
     241             :  */
     242             : static void
     243           3 : history_run (void *cls,
     244             :              const struct TALER_TESTING_Command *cmd,
     245             :              struct TALER_TESTING_Interpreter *is)
     246             : {
     247           3 :   struct HistoryState *hs = cls;
     248             :   
     249           3 :   hs->is = is;
     250           3 :   if (0 == hs->time.abs_value_us)
     251             :   {
     252           2 :     hs->time = GNUNET_TIME_absolute_add
     253             :       (GNUNET_TIME_absolute_get (),
     254             :        GNUNET_TIME_UNIT_HOURS);
     255           2 :     GNUNET_TIME_round_abs (&hs->time);
     256             :   }
     257           3 :   if ( NULL ==
     258           3 :      ( hs->ho = TALER_MERCHANT_history (hs->ctx,
     259             :                                         hs->merchant_url,
     260             :                                         "default",
     261             :                                         hs->start,
     262             :                                         hs->nrows,
     263             :                                         hs->time,
     264             :                                         &history_cb,
     265             :                                         hs)))
     266           0 :   TALER_TESTING_FAIL (is);
     267             : }
     268             : 
     269             : 
     270             : /**
     271             :  * Make a "history" command.
     272             :  *
     273             :  * @param label command label
     274             :  * @param merchant_url merchant base URL
     275             :  * @param ctx main CURL context
     276             :  * @param http_status expected HTTP response code
     277             :  * @param time FIXME
     278             :  * @param nresult how many results are expected
     279             :  * @param start FIXME.
     280             :  * @param nrows how many row we want to receive, at most.
     281             :  */
     282             : struct TALER_TESTING_Command
     283           3 : TALER_TESTING_cmd_history (const char *label,
     284             :                            const char *merchant_url,
     285             :                            struct GNUNET_CURL_Context *ctx,
     286             :                            unsigned int http_status,
     287             :                            struct GNUNET_TIME_Absolute time,
     288             :                            unsigned int nresult,
     289             :                            unsigned int start,
     290             :                            unsigned int nrows)
     291             : {
     292             :   struct HistoryState *hs;
     293             :   struct TALER_TESTING_Command cmd;
     294             : 
     295           3 :   hs = GNUNET_new (struct HistoryState);
     296           3 :   hs->http_status = http_status;
     297           3 :   hs->time = time;
     298           3 :   hs->nresult = nresult;
     299           3 :   hs->start = start;
     300           3 :   hs->nrows = nrows;
     301           3 :   hs->merchant_url = merchant_url;
     302           3 :   hs->ctx = ctx;
     303             : 
     304           3 :   cmd.cls = hs;
     305           3 :   cmd.label = label;
     306           3 :   cmd.run = &history_run;
     307           3 :   cmd.cleanup = &history_cleanup;
     308             :   
     309           3 :   return cmd;
     310             : }
     311             : 
     312             : /* end of testing_api_cmd_history.c */

Generated by: LCOV version 1.13