Line data Source code
1 : /* 2 : This file is part of TALER 3 : Copyright (C) 2014-2021 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/testing_api_cmd_batch.c 21 : * @brief Implement batch-execution of CMDs. 22 : * @author Marcello Stanisci 23 : */ 24 : #include "platform.h" 25 : #include "taler_json_lib.h" 26 : #include <gnunet/gnunet_curl_lib.h> 27 : #include "taler_testing_lib.h" 28 : 29 : 30 : /** 31 : * State for a "batch" CMD. 32 : */ 33 : struct BatchState 34 : { 35 : /** 36 : * CMDs batch. 37 : */ 38 : struct TALER_TESTING_Command *batch; 39 : 40 : /** 41 : * Internal command pointer. 42 : */ 43 : unsigned int batch_ip; 44 : }; 45 : 46 : 47 : /** 48 : * Run the command. 49 : * 50 : * @param cls closure. 51 : * @param cmd the command being executed. 52 : * @param is the interpreter state. 53 : */ 54 : static void 55 0 : batch_run (void *cls, 56 : const struct TALER_TESTING_Command *cmd, 57 : struct TALER_TESTING_Interpreter *is) 58 : { 59 0 : struct BatchState *bs = cls; 60 : 61 0 : if (NULL != bs->batch[bs->batch_ip].label) 62 0 : TALER_LOG_INFO ("Running batched command: %s\n", 63 : bs->batch[bs->batch_ip].label); 64 : 65 : /* hit end command, leap to next top-level command. */ 66 0 : if (NULL == bs->batch[bs->batch_ip].label) 67 : { 68 0 : TALER_LOG_INFO ("Exiting from batch: %s\n", 69 : cmd->label); 70 0 : TALER_TESTING_interpreter_next (is); 71 0 : return; 72 : } 73 0 : bs->batch[bs->batch_ip].start_time 74 0 : = bs->batch[bs->batch_ip].last_req_time 75 0 : = GNUNET_TIME_absolute_get (); 76 0 : bs->batch[bs->batch_ip].num_tries = 1; 77 0 : bs->batch[bs->batch_ip].run (bs->batch[bs->batch_ip].cls, 78 0 : &bs->batch[bs->batch_ip], 79 : is); 80 : } 81 : 82 : 83 : /** 84 : * Cleanup the state from a "reserve status" CMD, and possibly 85 : * cancel a pending operation thereof. 86 : * 87 : * @param cls closure. 88 : * @param cmd the command which is being cleaned up. 89 : */ 90 : static void 91 0 : batch_cleanup (void *cls, 92 : const struct TALER_TESTING_Command *cmd) 93 : { 94 0 : struct BatchState *bs = cls; 95 : 96 : (void) cmd; 97 0 : for (unsigned int i = 0; 98 0 : NULL != bs->batch[i].label; 99 0 : i++) 100 0 : bs->batch[i].cleanup (bs->batch[i].cls, 101 0 : &bs->batch[i]); 102 0 : GNUNET_free (bs->batch); 103 0 : GNUNET_free (bs); 104 0 : } 105 : 106 : 107 : /** 108 : * Offer internal data from a "batch" CMD, to other commands. 109 : * 110 : * @param cls closure. 111 : * @param[out] ret result. 112 : * @param trait name of the trait. 113 : * @param index index number of the object to offer. 114 : * @return #GNUNET_OK on success. 115 : */ 116 : static enum GNUNET_GenericReturnValue 117 0 : batch_traits (void *cls, 118 : const void **ret, 119 : const char *trait, 120 : unsigned int index) 121 : { 122 0 : struct BatchState *bs = cls; 123 : struct TALER_TESTING_Trait traits[] = { 124 0 : TALER_TESTING_make_trait_batch_cmds (&bs->batch), 125 0 : TALER_TESTING_trait_end () 126 : }; 127 : 128 : /* Always return current command. */ 129 0 : return TALER_TESTING_get_trait (traits, 130 : ret, 131 : trait, 132 : index); 133 : } 134 : 135 : 136 : struct TALER_TESTING_Command 137 0 : TALER_TESTING_cmd_batch (const char *label, 138 : struct TALER_TESTING_Command *batch) 139 : { 140 : struct BatchState *bs; 141 : unsigned int i; 142 : 143 0 : bs = GNUNET_new (struct BatchState); 144 : 145 : /* Get number of commands. */ 146 0 : for (i = 0; NULL != batch[i].label; i++) 147 : /* noop */ 148 : ; 149 : 150 0 : bs->batch = GNUNET_new_array (i + 1, 151 : struct TALER_TESTING_Command); 152 0 : memcpy (bs->batch, 153 : batch, 154 : sizeof (struct TALER_TESTING_Command) * i); 155 : { 156 0 : struct TALER_TESTING_Command cmd = { 157 : .cls = bs, 158 : .label = label, 159 : .run = &batch_run, 160 : .cleanup = &batch_cleanup, 161 : .traits = &batch_traits 162 : }; 163 : 164 0 : return cmd; 165 : } 166 : } 167 : 168 : 169 : void 170 0 : TALER_TESTING_cmd_batch_next (struct TALER_TESTING_Interpreter *is) 171 : { 172 0 : struct BatchState *bs = is->commands[is->ip].cls; 173 : 174 0 : if (NULL == bs->batch[bs->batch_ip].label) 175 : { 176 0 : is->commands[is->ip].finish_time = GNUNET_TIME_absolute_get (); 177 0 : is->ip++; 178 0 : return; 179 : } 180 0 : bs->batch[bs->batch_ip].finish_time = GNUNET_TIME_absolute_get (); 181 0 : bs->batch_ip++; 182 : } 183 : 184 : 185 : bool 186 25 : TALER_TESTING_cmd_is_batch (const struct TALER_TESTING_Command *cmd) 187 : { 188 25 : return cmd->run == &batch_run; 189 : } 190 : 191 : 192 : struct TALER_TESTING_Command * 193 0 : TALER_TESTING_cmd_batch_get_current (const struct TALER_TESTING_Command *cmd) 194 : { 195 0 : struct BatchState *bs = cmd->cls; 196 : 197 0 : GNUNET_assert (cmd->run == &batch_run); 198 0 : return &bs->batch[bs->batch_ip]; 199 : } 200 : 201 : 202 : void 203 0 : TALER_TESTING_cmd_batch_set_current (const struct TALER_TESTING_Command *cmd, 204 : unsigned int new_ip) 205 : { 206 0 : struct BatchState *bs = cmd->cls; 207 : 208 : /* sanity checks */ 209 0 : GNUNET_assert (cmd->run == &batch_run); 210 0 : for (unsigned int i = 0; i < new_ip; i++) 211 0 : GNUNET_assert (NULL != bs->batch[i].label); 212 : /* actual logic */ 213 0 : bs->batch_ip = new_ip; 214 0 : }