exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

testing_api_cmd_twister_exec_client.c (25066B)


      1 /*
      2   This file is part of TALER
      3   (C) 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 testing_api_cmd_twister_exec_client.c
     22  * @brief test commands aimed to call the CLI twister client
     23  *        to drive its behaviour.
     24  * @author Christian Grothoff <christian@grothoff.org>
     25  * @author Marcello Stanisci
     26  */
     27 
     28 #include "taler/platform.h"
     29 #include "taler/taler_testing_lib.h"
     30 #include "taler/taler_twister_testing_lib.h"
     31 
     32 
     33 /**
     34  * State for a "modify object" CMD.
     35  */
     36 struct ModifyObjectState
     37 {
     38   /**
     39    * Process handle for the twister CLI client.
     40    */
     41   struct GNUNET_Process *proc;
     42 
     43   /**
     44    * Object-like notation to the object to delete.
     45    */
     46   const char *path;
     47 
     48   /**
     49    * Value to substitute to the original one.
     50    */
     51   const char *value;
     52 
     53   /**
     54    * Config file name to pass to the CLI client.
     55    */
     56   const char *config_filename;
     57 };
     58 
     59 
     60 /**
     61  * State for a "flip object" CMD.
     62  */
     63 struct FlipObjectState
     64 {
     65   /**
     66    * Process handle for the twister CLI client.
     67    */
     68   struct GNUNET_Process *proc;
     69 
     70   /**
     71    * Object-like notation to the string-object to flip.
     72    */
     73   const char *path;
     74 
     75   /**
     76    * Config file name to pass to the CLI client.
     77    */
     78   const char *config_filename;
     79 };
     80 
     81 
     82 /**
     83  * State for a "delete object" CMD.
     84  */
     85 struct DeleteObjectState
     86 {
     87   /**
     88    * Process handle for the twister CLI client.
     89    */
     90   struct GNUNET_Process *proc;
     91 
     92   /**
     93    * Object-like notation to the object to delete.
     94    */
     95   const char *path;
     96 
     97   /**
     98    * Config file name to pass to the CLI client.
     99    */
    100   const char *config_filename;
    101 };
    102 
    103 
    104 /**
    105  * State for a "malform request" CMD.
    106  */
    107 struct MalformRequestState
    108 {
    109   /**
    110    * Process handle for the twister CLI client.
    111    */
    112   struct GNUNET_Process *proc;
    113 
    114   /**
    115    * Config file name to pass to the CLI client.
    116    */
    117   const char *config_filename;
    118 };
    119 
    120 
    121 /**
    122  * State for a "malform response" CMD.
    123  */
    124 struct MalformResponseState
    125 {
    126   /**
    127    * Process handle for the twister CLI client.
    128    */
    129   struct GNUNET_Process *proc;
    130 
    131   /**
    132    * Config file name to pass to the CLI client.
    133    */
    134   const char *config_filename;
    135 };
    136 
    137 
    138 /**
    139  * State for a "hack response code" CMD.
    140  */
    141 struct HackResponseCodeState
    142 {
    143   /**
    144    * Process handle for the twister CLI client.
    145    */
    146   struct GNUNET_Process *proc;
    147 
    148   /**
    149    * HTTP status code to substitute to the original one.
    150    */
    151   unsigned int http_status;
    152 
    153   /**
    154    * Config file name to pass to the CLI client.
    155    */
    156   const char *config_filename;
    157 };
    158 
    159 
    160 /**
    161  * Helper function to create a process running the @a filename binary.
    162  *
    163  * @param filename binary to run
    164  * @param ... argv to pass
    165  * @return NULL on error
    166  */
    167 static struct GNUNET_Process *
    168 start_process (const char *filename,
    169                ...)
    170 {
    171   struct GNUNET_Process *proc;
    172   va_list ap;
    173 
    174   proc = GNUNET_process_create (GNUNET_OS_INHERIT_STD_ERR);
    175   va_start (ap,
    176             filename);
    177   if (GNUNET_OK !=
    178       GNUNET_process_run_command_ap (
    179         proc,
    180         filename,
    181         ap))
    182   {
    183     GNUNET_break (0);
    184     GNUNET_process_destroy (proc);
    185     proc = NULL;
    186   }
    187   va_end (ap);
    188   return proc;
    189 }
    190 
    191 
    192 /**
    193  * Free the state from a "hack response code" CMD, and
    194  * possibly kill its process if it did not terminate yet.
    195  *
    196  * @param cls closure.
    197  * @param cmd the command being cleaned up.
    198  */
    199 static void
    200 hack_response_code_cleanup (
    201   void *cls,
    202   const struct TALER_TESTING_Command *cmd)
    203 {
    204   struct HackResponseCodeState *hrcs = cls;
    205 
    206   if (NULL != hrcs->proc)
    207   {
    208     GNUNET_break (GNUNET_OK ==
    209                   GNUNET_process_kill (hrcs->proc,
    210                                        SIGKILL));
    211     GNUNET_process_wait (hrcs->proc,
    212                          true,
    213                          NULL,
    214                          NULL);
    215     GNUNET_process_destroy (hrcs->proc);
    216     hrcs->proc = NULL;
    217   }
    218   GNUNET_free (hrcs);
    219 }
    220 
    221 
    222 /**
    223  * Offer data internal to a "hack response code" CMD,
    224  * to other commands.
    225  *
    226  * @param cls closure
    227  * @param[out] ret result (could be anything)
    228  * @param trait name of the trait
    229  * @param index index number of the object to offer.
    230  * @return #GNUNET_OK on success
    231  */
    232 static enum GNUNET_GenericReturnValue
    233 hack_response_code_traits (void *cls,
    234                            const void **ret,
    235                            const char *trait,
    236                            unsigned int index)
    237 {
    238 
    239   struct HackResponseCodeState *hrcs = cls;
    240   struct TALER_TESTING_Trait traits[] = {
    241     TALER_TESTING_make_trait_process (&hrcs->proc),
    242     TALER_TESTING_trait_end ()
    243   };
    244 
    245   return TALER_TESTING_get_trait (traits,
    246                                   ret,
    247                                   trait,
    248                                   index);
    249 }
    250 
    251 
    252 /**
    253  * Run a "hack response code" CMD.
    254  *
    255  * @param cls closure.
    256  * @param cmd the command being run.
    257  * @param is the interpreter state.
    258  */
    259 static void
    260 hack_response_code_run (void *cls,
    261                         const struct TALER_TESTING_Command *cmd,
    262                         struct TALER_TESTING_Interpreter *is)
    263 {
    264   struct HackResponseCodeState *hrcs = cls;
    265   char *http_status;
    266 
    267   GNUNET_asprintf (&http_status, "%u",
    268                    hrcs->http_status);
    269 
    270   hrcs->proc = start_process (
    271     "taler-twister",
    272     "taler-twister",
    273     "-c", hrcs->config_filename,
    274     "--responsecode", http_status,
    275     NULL);
    276   if (NULL == hrcs->proc)
    277   {
    278     GNUNET_break (0);
    279     TALER_TESTING_interpreter_fail (is);
    280     return;
    281   }
    282   TALER_TESTING_wait_for_sigchld (is);
    283   GNUNET_free (http_status);
    284 }
    285 
    286 
    287 struct TALER_TESTING_Command
    288 TALER_TESTING_cmd_hack_response_code (const char *label,
    289                                       const char *config_filename,
    290                                       unsigned int http_status)
    291 {
    292   struct HackResponseCodeState *hrcs;
    293 
    294   hrcs = GNUNET_new (struct HackResponseCodeState);
    295   hrcs->http_status = http_status;
    296   hrcs->config_filename = config_filename;
    297   {
    298     struct TALER_TESTING_Command cmd = {
    299       .label = label,
    300       .run = &hack_response_code_run,
    301       .cleanup = &hack_response_code_cleanup,
    302       .traits = &hack_response_code_traits,
    303       .cls = hrcs
    304     };
    305 
    306     return cmd;
    307   }
    308 }
    309 
    310 
    311 /**
    312  * Free the state from a "delete object" CMD, and
    313  * possibly kill its process if it did not terminate yet.
    314  *
    315  * @param cls closure.
    316  * @param cmd the command being cleaned up.
    317  */
    318 static void
    319 delete_object_cleanup
    320   (void *cls,
    321   const struct TALER_TESTING_Command *cmd)
    322 {
    323   struct DeleteObjectState *dos = cls;
    324 
    325   if (NULL != dos->proc)
    326   {
    327     GNUNET_break (GNUNET_OK ==
    328                   GNUNET_process_kill (dos->proc,
    329                                        SIGKILL));
    330     GNUNET_process_wait (dos->proc,
    331                          true,
    332                          NULL,
    333                          NULL);
    334     GNUNET_process_destroy (dos->proc);
    335     dos->proc = NULL;
    336   }
    337   GNUNET_free (dos);
    338 }
    339 
    340 
    341 /**
    342  * Offer data internal to a "delete object" CMD,
    343  * to other commands.
    344  *
    345  * @param cls closure
    346  * @param[out] ret result (could be anything)
    347  * @param trait name of the trait
    348  * @param index index number of the object to offer.
    349  * @return #GNUNET_OK on success
    350  */
    351 static enum GNUNET_GenericReturnValue
    352 delete_object_traits (void *cls,
    353                       const void **ret,
    354                       const char *trait,
    355                       unsigned int index)
    356 {
    357 
    358   struct DeleteObjectState *dos = cls;
    359   struct TALER_TESTING_Trait traits[] = {
    360     TALER_TESTING_make_trait_process (&dos->proc),
    361     TALER_TESTING_trait_end ()
    362   };
    363 
    364   return TALER_TESTING_get_trait (traits,
    365                                   ret,
    366                                   trait,
    367                                   index);
    368 }
    369 
    370 
    371 /**
    372  * Run a "delete object" CMD.
    373  *
    374  * @param cls closure.
    375  * @param cmd the command being run.
    376  * @param is the interpreter state.
    377  */
    378 static void
    379 delete_object_run (void *cls,
    380                    const struct TALER_TESTING_Command *cmd,
    381                    struct TALER_TESTING_Interpreter *is)
    382 {
    383   struct DeleteObjectState *dos = cls;
    384 
    385   dos->proc = start_process ("taler-twister",
    386                              "taler-twister",
    387                              "-c", dos->config_filename,
    388                              "--deleteobject", dos->path,
    389                              NULL);
    390   if (NULL == dos->proc)
    391   {
    392     GNUNET_break (0);
    393     TALER_TESTING_interpreter_fail (is);
    394     return;
    395   }
    396   TALER_TESTING_wait_for_sigchld (is);
    397 }
    398 
    399 
    400 /**
    401  * Free the state from a "modify object" CMD, and
    402  * possibly kill its process if it did not terminate yet.
    403  *
    404  * @param cls closure.
    405  * @param cmd the command being cleaned up.
    406  */
    407 static void
    408 modify_object_cleanup (void *cls,
    409                        const struct TALER_TESTING_Command *cmd)
    410 {
    411   struct ModifyObjectState *mos = cls;
    412 
    413   if (NULL != mos->proc)
    414   {
    415     GNUNET_break (GNUNET_OK ==
    416                   GNUNET_process_kill (mos->proc,
    417                                        SIGKILL));
    418     GNUNET_process_wait (mos->proc,
    419                          true,
    420                          NULL,
    421                          NULL);
    422     GNUNET_process_destroy (mos->proc);
    423     mos->proc = NULL;
    424   }
    425   GNUNET_free (mos);
    426 }
    427 
    428 
    429 /**
    430  * Offer data internal to a "modify object" CMD,
    431  * to other commands.
    432  *
    433  * @param cls closure
    434  * @param[out] ret result (could be anything)
    435  * @param trait name of the trait
    436  * @param index index number of the object to offer.
    437  * @return #GNUNET_OK on success
    438  */
    439 static enum GNUNET_GenericReturnValue
    440 modify_object_traits (void *cls,
    441                       const void **ret,
    442                       const char *trait,
    443                       unsigned int index)
    444 {
    445 
    446   struct ModifyObjectState *mos = cls;
    447   struct TALER_TESTING_Trait traits[] = {
    448     TALER_TESTING_make_trait_process (&mos->proc),
    449     TALER_TESTING_trait_end ()
    450   };
    451 
    452   return TALER_TESTING_get_trait (traits,
    453                                   ret,
    454                                   trait,
    455                                   index);
    456 }
    457 
    458 
    459 /**
    460  * Run a "modify object" CMD.  The "download fashion" of it.
    461  *
    462  * @param cls closure.
    463  * @param cmd the command being run.
    464  * @param is the interpreter state.
    465  */
    466 static void
    467 modify_object_dl_run (void *cls,
    468                       const struct TALER_TESTING_Command *cmd,
    469                       struct TALER_TESTING_Interpreter *is)
    470 {
    471   struct ModifyObjectState *mos = cls;
    472 
    473   mos->proc = start_process ("taler-twister",
    474                              "taler-twister",
    475                              "-c", mos->config_filename,
    476                              "-m", mos->path,
    477                              "--value", mos->value,
    478                              NULL);
    479   if (NULL == mos->proc)
    480   {
    481     GNUNET_break (0);
    482     TALER_TESTING_interpreter_fail (is);
    483     return;
    484   }
    485   TALER_TESTING_wait_for_sigchld (is);
    486 }
    487 
    488 
    489 /**
    490  * Run a "modify object" CMD, the "upload fashion" of it.
    491  *
    492  * @param cls closure.
    493  * @param cmd the command being run.
    494  * @param is the interpreter state.
    495  */
    496 static void
    497 modify_object_ul_run (void *cls,
    498                       const struct TALER_TESTING_Command *cmd,
    499                       struct TALER_TESTING_Interpreter *is)
    500 {
    501   struct ModifyObjectState *mos = cls;
    502 
    503   mos->proc = start_process ("taler-twister",
    504                              "taler-twister",
    505                              "-c", mos->config_filename,
    506                              "-X", mos->path,
    507                              "--value", mos->value,
    508                              NULL);
    509   if (NULL == mos->proc)
    510   {
    511     GNUNET_break (0);
    512     TALER_TESTING_interpreter_fail (is);
    513     return;
    514   }
    515   TALER_TESTING_wait_for_sigchld (is);
    516 }
    517 
    518 
    519 /**
    520  * Run a "modify header" CMD
    521  *
    522  * @param cls closure.
    523  * @param cmd the command being run.
    524  * @param is the interpreter state.
    525  */
    526 static void
    527 modify_header_dl_run (void *cls,
    528                       const struct TALER_TESTING_Command *cmd,
    529                       struct TALER_TESTING_Interpreter *is)
    530 {
    531   struct ModifyObjectState *mos = cls;
    532 
    533   mos->proc = start_process ("taler-twister",
    534                              "taler-twister",
    535                              "-H", mos->path,
    536                              "--value", mos->value,
    537                              "-c", mos->config_filename,
    538                              NULL);
    539   if (NULL == mos->proc)
    540   {
    541     GNUNET_break (0);
    542     TALER_TESTING_interpreter_fail (is);
    543     return;
    544   }
    545   TALER_TESTING_wait_for_sigchld (is);
    546 }
    547 
    548 
    549 struct TALER_TESTING_Command
    550 TALER_TESTING_cmd_delete_object (const char *label,
    551                                  const char *config_filename,
    552                                  const char *path)
    553 {
    554   struct DeleteObjectState *dos;
    555 
    556   dos = GNUNET_new (struct DeleteObjectState);
    557   dos->path = path;
    558   dos->config_filename = config_filename;
    559   {
    560     struct TALER_TESTING_Command cmd = {
    561       .label = label,
    562       .run = &delete_object_run,
    563       .cleanup = &delete_object_cleanup,
    564       .traits = &delete_object_traits,
    565       .cls = dos
    566     };
    567 
    568     return cmd;
    569   }
    570 }
    571 
    572 
    573 /**
    574  * Free the state from a "flip object" CMD, and
    575  * possibly kill its process if it did not terminate yet.
    576  *
    577  * @param cls closure.
    578  * @param cmd the command being cleaned up.
    579  */
    580 static void
    581 flip_object_cleanup
    582   (void *cls,
    583   const struct TALER_TESTING_Command *cmd)
    584 {
    585   struct FlipObjectState *fos = cls;
    586 
    587   if (NULL != fos->proc)
    588   {
    589     GNUNET_break (GNUNET_OK ==
    590                   GNUNET_process_kill (fos->proc,
    591                                        SIGKILL));
    592     GNUNET_process_wait (fos->proc,
    593                          true,
    594                          NULL,
    595                          NULL);
    596     GNUNET_process_destroy (fos->proc);
    597     fos->proc = NULL;
    598   }
    599   GNUNET_free (fos);
    600 }
    601 
    602 
    603 /**
    604  * Offer data internal to a "flip object" CMD,
    605  * to other commands.
    606  *
    607  * @param cls closure
    608  * @param[out] ret result (could be anything)
    609  * @param trait name of the trait
    610  * @param index index number of the object to offer.
    611  * @return #GNUNET_OK on success
    612  */
    613 static enum GNUNET_GenericReturnValue
    614 flip_object_traits (void *cls,
    615                     const void **ret,
    616                     const char *trait,
    617                     unsigned int index)
    618 {
    619   struct FlipObjectState *fos = cls;
    620   struct TALER_TESTING_Trait traits[] = {
    621     TALER_TESTING_make_trait_process (&fos->proc),
    622     TALER_TESTING_trait_end ()
    623   };
    624 
    625   return TALER_TESTING_get_trait (traits,
    626                                   ret,
    627                                   trait,
    628                                   index);
    629 }
    630 
    631 
    632 /**
    633  * Run a "flip object" CMD, the upload fashion of it.
    634  *
    635  * @param cls closure.
    636  * @param cmd the command being run.
    637  * @param is the interpreter state.
    638  */
    639 static void
    640 flip_upload_run (void *cls,
    641                  const struct TALER_TESTING_Command *cmd,
    642                  struct TALER_TESTING_Interpreter *is)
    643 {
    644   struct FlipObjectState *fos = cls;
    645 
    646   fos->proc = start_process ("taler-twister",
    647                              "taler-twister",
    648                              "-c", fos->config_filename,
    649                              "--flip-ul", fos->path,
    650                              NULL);
    651   if (NULL == fos->proc)
    652   {
    653     GNUNET_break (0);
    654     TALER_TESTING_interpreter_fail (is);
    655     return;
    656   }
    657   TALER_TESTING_wait_for_sigchld (is);
    658 }
    659 
    660 
    661 /**
    662  * Run a "flip object" CMD, the download fashion of it.
    663  *
    664  * @param cls closure.
    665  * @param cmd the command being run.
    666  * @param is the interpreter state.
    667  */
    668 static void
    669 flip_download_run (void *cls,
    670                    const struct TALER_TESTING_Command *cmd,
    671                    struct TALER_TESTING_Interpreter *is)
    672 {
    673   struct FlipObjectState *fos = cls;
    674 
    675   fos->proc = start_process ("taler-twister",
    676                              "taler-twister",
    677                              "-c", fos->config_filename,
    678                              "--flip-dl", fos->path,
    679                              NULL);
    680   if (NULL == fos->proc)
    681   {
    682     GNUNET_break (0);
    683     TALER_TESTING_interpreter_fail (is);
    684     return;
    685   }
    686   TALER_TESTING_wait_for_sigchld (is);
    687 }
    688 
    689 
    690 struct TALER_TESTING_Command
    691 TALER_TESTING_cmd_flip_upload (const char *label,
    692                                const char *config_filename,
    693                                const char *path)
    694 {
    695   struct FlipObjectState *dos;
    696 
    697   dos = GNUNET_new (struct FlipObjectState);
    698   dos->path = path;
    699   dos->config_filename = config_filename;
    700   {
    701     struct TALER_TESTING_Command cmd = {
    702       .label = label,
    703       .run = &flip_upload_run,
    704       .cleanup = &flip_object_cleanup,
    705       .traits = &flip_object_traits,
    706       .cls = dos
    707     };
    708 
    709     return cmd;
    710   }
    711 }
    712 
    713 
    714 struct TALER_TESTING_Command
    715 TALER_TESTING_cmd_flip_download (const char *label,
    716                                  const char *config_filename,
    717                                  const char *path)
    718 {
    719   struct FlipObjectState *dos;
    720 
    721   dos = GNUNET_new (struct FlipObjectState);
    722   dos->path = path;
    723   dos->config_filename = config_filename;
    724   {
    725     struct TALER_TESTING_Command cmd = {
    726       .label = label,
    727       .run = &flip_download_run,
    728       .cleanup = &flip_object_cleanup,
    729       .traits = &flip_object_traits,
    730       .cls = dos
    731     };
    732 
    733     return cmd;
    734   }
    735 }
    736 
    737 
    738 /**
    739  * Free the state from a "malform request" CMD, and
    740  * possibly kill its process if it did not terminate yet.
    741  *
    742  * @param cls closure.
    743  * @param cmd the command being cleaned up.
    744  */
    745 static void
    746 malform_request_cleanup (void *cls,
    747                          const struct TALER_TESTING_Command *cmd)
    748 {
    749   struct MalformRequestState *mrs = cls;
    750 
    751   if (NULL != mrs->proc)
    752   {
    753     GNUNET_break (GNUNET_OK ==
    754                   GNUNET_process_kill (mrs->proc,
    755                                        SIGKILL));
    756     GNUNET_process_wait (mrs->proc,
    757                          true,
    758                          NULL,
    759                          NULL);
    760     GNUNET_process_destroy (mrs->proc);
    761     mrs->proc = NULL;
    762   }
    763   GNUNET_free (mrs);
    764 }
    765 
    766 
    767 /**
    768  * Offer data internal to a "malform request" CMD,
    769  * to other commands.
    770  *
    771  * @param cls closure
    772  * @param[out] ret result (could be anything)
    773  * @param trait name of the trait
    774  * @param index index number of the object to offer.
    775  * @return #GNUNET_OK on success
    776  */
    777 static enum GNUNET_GenericReturnValue
    778 malform_request_traits (void *cls,
    779                         const void **ret,
    780                         const char *trait,
    781                         unsigned int index)
    782 {
    783   struct MalformRequestState *mrs = cls;
    784   struct TALER_TESTING_Trait traits[] = {
    785     TALER_TESTING_make_trait_process (&mrs->proc),
    786     TALER_TESTING_trait_end ()
    787   };
    788 
    789   return TALER_TESTING_get_trait (traits,
    790                                   ret,
    791                                   trait,
    792                                   index);
    793 }
    794 
    795 
    796 /**
    797  * Run a "malform request" CMD.
    798  *
    799  * @param cls closure.
    800  * @param cmd the command being run.
    801  * @param is the interpreter state.
    802  */
    803 static void
    804 malform_request_run (void *cls,
    805                      const struct TALER_TESTING_Command *cmd,
    806                      struct TALER_TESTING_Interpreter *is)
    807 {
    808   struct MalformRequestState *mrs = cls;
    809 
    810   mrs->proc = start_process ("taler-twister",
    811                              "taler-twister",
    812                              "-c", mrs->config_filename,
    813                              "--malformupload",
    814                              NULL);
    815   if (NULL == mrs->proc)
    816   {
    817     GNUNET_break (0);
    818     TALER_TESTING_interpreter_fail (is);
    819     return;
    820   }
    821   TALER_TESTING_wait_for_sigchld (is);
    822 }
    823 
    824 
    825 /**
    826  * Free the state from a "malform response" CMD, and
    827  * possibly kill its process if it did not terminate yet.
    828  *
    829  * @param cls closure.
    830  * @param cmd the command being cleaned up.
    831  */
    832 static void
    833 malform_response_cleanup (void *cls,
    834                           const struct TALER_TESTING_Command *cmd)
    835 {
    836   struct MalformResponseState *mrs = cls;
    837 
    838   if (NULL != mrs->proc)
    839   {
    840     GNUNET_break (GNUNET_OK ==
    841                   GNUNET_process_kill (mrs->proc,
    842                                        SIGKILL));
    843     GNUNET_process_wait (mrs->proc,
    844                          true,
    845                          NULL,
    846                          NULL);
    847     GNUNET_process_destroy (mrs->proc);
    848     mrs->proc = NULL;
    849   }
    850   GNUNET_free (mrs);
    851 }
    852 
    853 
    854 /**
    855  * Offer data internal to a "malform response" CMD,
    856  * to other commands.
    857  *
    858  * @param cls closure
    859  * @param[out] ret result (could be anything)
    860  * @param trait name of the trait
    861  * @param index index number of the object to offer.
    862  * @return #GNUNET_OK on success
    863  */
    864 static enum GNUNET_GenericReturnValue
    865 malform_response_traits (void *cls,
    866                          const void **ret,
    867                          const char *trait,
    868                          unsigned int index)
    869 {
    870   struct MalformResponseState *mrs = cls;
    871   struct TALER_TESTING_Trait traits[] = {
    872     TALER_TESTING_make_trait_process (&mrs->proc),
    873     TALER_TESTING_trait_end ()
    874   };
    875 
    876   return TALER_TESTING_get_trait (traits,
    877                                   ret,
    878                                   trait,
    879                                   index);
    880 }
    881 
    882 
    883 /**
    884  * Run a "malform response" CMD.
    885  *
    886  * @param cls closure.
    887  * @param cmd the command being run.
    888  * @param is the interpreter state.
    889  */
    890 static void
    891 malform_response_run (void *cls,
    892                       const struct TALER_TESTING_Command *cmd,
    893                       struct TALER_TESTING_Interpreter *is)
    894 {
    895   struct MalformResponseState *mrs = cls;
    896 
    897   mrs->proc = start_process ("taler-twister",
    898                              "taler-twister",
    899                              "-c", mrs->config_filename,
    900                              "--malform",
    901                              NULL);
    902   if (NULL == mrs->proc)
    903   {
    904     GNUNET_break (0);
    905     TALER_TESTING_interpreter_fail (is);
    906     return;
    907   }
    908   TALER_TESTING_wait_for_sigchld (is);
    909 }
    910 
    911 
    912 struct TALER_TESTING_Command
    913 TALER_TESTING_cmd_malform_request (const char *label,
    914                                    const char *config_filename)
    915 {
    916   struct MalformRequestState *mrs;
    917 
    918   mrs = GNUNET_new (struct MalformRequestState);
    919   mrs->config_filename = config_filename;
    920   {
    921     struct TALER_TESTING_Command cmd = {
    922       .label = label,
    923       .run = &malform_request_run,
    924       .cleanup = &malform_request_cleanup,
    925       .traits = &malform_request_traits,
    926       .cls = mrs
    927     };
    928 
    929     return cmd;
    930   }
    931 }
    932 
    933 
    934 struct TALER_TESTING_Command
    935 TALER_TESTING_cmd_malform_response (const char *label,
    936                                     const char *config_filename)
    937 {
    938   struct MalformResponseState *mrs;
    939 
    940   mrs = GNUNET_new (struct MalformResponseState);
    941   mrs->config_filename = config_filename;
    942   {
    943     struct TALER_TESTING_Command cmd = {
    944       .label = label,
    945       .run = &malform_response_run,
    946       .cleanup = &malform_response_cleanup,
    947       .traits = &malform_response_traits,
    948       .cls = mrs
    949     };
    950 
    951     return cmd;
    952   }
    953 }
    954 
    955 
    956 struct TALER_TESTING_Command
    957 TALER_TESTING_cmd_modify_object_dl (const char *label,
    958                                     const char *config_filename,
    959                                     const char *path,
    960                                     const char *value)
    961 {
    962   struct ModifyObjectState *mos;
    963 
    964   mos = GNUNET_new (struct ModifyObjectState);
    965   mos->path = path;
    966   mos->value = value;
    967   mos->config_filename = config_filename;
    968   {
    969     struct TALER_TESTING_Command cmd = {
    970       .label = label,
    971       .run = &modify_object_dl_run,
    972       .cleanup = &modify_object_cleanup,
    973       .traits = &modify_object_traits,
    974       .cls = mos
    975     };
    976 
    977     return cmd;
    978   }
    979 }
    980 
    981 
    982 struct TALER_TESTING_Command
    983 TALER_TESTING_cmd_modify_object_ul (const char *label,
    984                                     const char *config_filename,
    985                                     const char *path,
    986                                     const char *value)
    987 {
    988   struct ModifyObjectState *mos;
    989 
    990   mos = GNUNET_new (struct ModifyObjectState);
    991   mos->path = path;
    992   mos->value = value;
    993   mos->config_filename = config_filename;
    994   {
    995     struct TALER_TESTING_Command cmd = {
    996       .label = label,
    997       .run = &modify_object_ul_run,
    998       .cleanup = &modify_object_cleanup,
    999       .traits = &modify_object_traits,
   1000       .cls = mos
   1001     };
   1002 
   1003     return cmd;
   1004   }
   1005 }
   1006 
   1007 
   1008 struct TALER_TESTING_Command
   1009 TALER_TESTING_cmd_modify_header_dl (const char *label,
   1010                                     const char *config_filename,
   1011                                     const char *path,
   1012                                     const char *value)
   1013 {
   1014   struct ModifyObjectState *mos;
   1015 
   1016   mos = GNUNET_new (struct ModifyObjectState);
   1017   mos->path = path;
   1018   mos->value = value;
   1019   mos->config_filename = config_filename;
   1020   {
   1021     struct TALER_TESTING_Command cmd = {
   1022       .label = label,
   1023       .run = &modify_header_dl_run,
   1024       .cleanup = &modify_object_cleanup,
   1025       .traits = &modify_object_traits,
   1026       .cls = mos
   1027     };
   1028 
   1029     return cmd;
   1030   }
   1031 }
   1032 
   1033 
   1034 /* end of testing_api_cmd_exec_client.c */