integrate purse expiration into test, bugfixes
This commit is contained in:
parent
802649c270
commit
d8f1f7b761
4
debian/taler-exchange.install
vendored
4
debian/taler-exchange.install
vendored
@ -1,7 +1,9 @@
|
||||
usr/bin/taler-exchange-aggregator
|
||||
usr/bin/taler-exchange-closer
|
||||
usr/bin/taler-exchange-dbinit
|
||||
usr/bin/taler-exchange-expire
|
||||
usr/bin/taler-exchange-httpd
|
||||
usr/bin/taler-exchange-router
|
||||
usr/bin/taler-exchange-secmod-cs
|
||||
usr/bin/taler-exchange-secmod-eddsa
|
||||
usr/bin/taler-exchange-secmod-rsa
|
||||
@ -11,7 +13,9 @@ usr/bin/taler-exchange-wire-gateway-client
|
||||
usr/share/man/man1/taler-exchange-aggregator*
|
||||
usr/share/man/man1/taler-exchange-closer*
|
||||
usr/share/man/man1/taler-exchange-dbinit*
|
||||
usr/share/man/man1/taler-exchange-expire*
|
||||
usr/share/man/man1/taler-exchange-httpd*
|
||||
usr/share/man/man1/taler-exchange-router*
|
||||
usr/share/man/man1/taler-exchange-secmod-eddsa*
|
||||
usr/share/man/man1/taler-exchange-secmod-rsa*
|
||||
usr/share/man/man1/taler-exchange-secmod-cs*
|
||||
|
@ -95,6 +95,12 @@ static int global_ret;
|
||||
*/
|
||||
static int test_mode;
|
||||
|
||||
/**
|
||||
* If this is a first-time run, we immediately
|
||||
* try to catch up with the present.
|
||||
*/
|
||||
static bool jump_mode;
|
||||
|
||||
|
||||
/**
|
||||
* Select a shard to work on.
|
||||
@ -188,6 +194,7 @@ static void
|
||||
release_shard (struct Shard *s)
|
||||
{
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
unsigned long long wc = (unsigned long long) s->work_counter;
|
||||
|
||||
qs = db_plugin->complete_shard (
|
||||
db_plugin->cls,
|
||||
@ -209,10 +216,14 @@ release_shard (struct Shard *s)
|
||||
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Purse expiration shard completed with %llu purses\n",
|
||||
(unsigned long long) s->work_counter);
|
||||
wc);
|
||||
/* normal case */
|
||||
break;
|
||||
}
|
||||
if ( (0 == wc) &&
|
||||
(test_mode) &&
|
||||
(! jump_mode) )
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
}
|
||||
|
||||
|
||||
@ -262,13 +273,16 @@ run_expire (void *cls)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to obtain database connection!\n");
|
||||
abort_shard (s);
|
||||
global_ret = EXIT_FAILURE;
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
return;
|
||||
}
|
||||
if (db_plugin->start (db_plugin->cls,
|
||||
if (GNUNET_OK !=
|
||||
db_plugin->start (db_plugin->cls,
|
||||
"expire-purse"))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
global_ret = EXIT_FAILURE;
|
||||
db_plugin->rollback (db_plugin->cls);
|
||||
abort_shard (s);
|
||||
@ -290,6 +304,7 @@ run_expire (void *cls)
|
||||
case GNUNET_DB_STATUS_SOFT_ERROR:
|
||||
db_plugin->rollback (db_plugin->cls);
|
||||
abort_shard (s);
|
||||
GNUNET_assert (NULL == task);
|
||||
task = GNUNET_SCHEDULER_add_now (&run_shard,
|
||||
NULL);
|
||||
return;
|
||||
@ -303,6 +318,7 @@ run_expire (void *cls)
|
||||
{
|
||||
release_shard (s);
|
||||
}
|
||||
GNUNET_assert (NULL == task);
|
||||
task = GNUNET_SCHEDULER_add_now (&run_shard,
|
||||
NULL);
|
||||
return;
|
||||
@ -310,6 +326,7 @@ run_expire (void *cls)
|
||||
/* commit, and go again immediately */
|
||||
s->work_counter++;
|
||||
(void) commit_or_warn ();
|
||||
GNUNET_assert (NULL == task);
|
||||
task = GNUNET_SCHEDULER_add_now (&run_expire,
|
||||
s);
|
||||
}
|
||||
@ -343,9 +360,15 @@ run_shard (void *cls)
|
||||
qs = db_plugin->begin_shard (db_plugin->cls,
|
||||
"expire",
|
||||
shard_size,
|
||||
shard_size.rel_value_us,
|
||||
jump_mode
|
||||
? GNUNET_TIME_absolute_subtract (
|
||||
GNUNET_TIME_absolute_get (),
|
||||
shard_size).
|
||||
abs_value_us
|
||||
: shard_size.rel_value_us,
|
||||
&s->shard_start.abs_value_us,
|
||||
&s->shard_end.abs_value_us);
|
||||
jump_mode = false;
|
||||
if (0 >= qs)
|
||||
{
|
||||
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
|
||||
@ -355,6 +378,7 @@ run_shard (void *cls)
|
||||
GNUNET_free (s);
|
||||
delay = GNUNET_TIME_randomized_backoff (delay,
|
||||
GNUNET_TIME_UNIT_SECONDS);
|
||||
GNUNET_assert (NULL == task);
|
||||
task = GNUNET_SCHEDULER_add_delayed (delay,
|
||||
&run_shard,
|
||||
NULL);
|
||||
@ -368,9 +392,10 @@ run_shard (void *cls)
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
return;
|
||||
}
|
||||
if (GNUNET_TIME_absolute_is_future (s->shard_end))
|
||||
if (GNUNET_TIME_absolute_is_future (s->shard_start))
|
||||
{
|
||||
task = GNUNET_SCHEDULER_add_at (s->shard_end,
|
||||
GNUNET_assert (NULL == task);
|
||||
task = GNUNET_SCHEDULER_add_at (s->shard_start,
|
||||
&run_shard,
|
||||
NULL);
|
||||
abort_shard (s);
|
||||
@ -379,12 +404,12 @@ run_shard (void *cls)
|
||||
/* If this is a first-time run, we immediately
|
||||
try to catch up with the present */
|
||||
if (GNUNET_TIME_absolute_is_zero (s->shard_start))
|
||||
s->shard_end = GNUNET_TIME_absolute_get ();
|
||||
|
||||
jump_mode = true;
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Starting shard [%llu:%llu]!\n",
|
||||
"Starting shard [%llu:%llu)!\n",
|
||||
(unsigned long long) s->shard_start.abs_value_us,
|
||||
(unsigned long long) s->shard_end.abs_value_us);
|
||||
GNUNET_assert (NULL == task);
|
||||
task = GNUNET_SCHEDULER_add_now (&run_expire,
|
||||
s);
|
||||
}
|
||||
|
@ -333,6 +333,37 @@ TEH_handler_purses_get (struct TEH_RequestContext *rc,
|
||||
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
|
||||
break; /* handled below */
|
||||
}
|
||||
if (GNUNET_TIME_absolute_cmp (gc->timeout,
|
||||
>,
|
||||
gc->purse_expiration.abs_time))
|
||||
{
|
||||
/* Timeout too high, need to replace event handler */
|
||||
struct TALER_PurseEventP rep = {
|
||||
.header.size = htons (sizeof (rep)),
|
||||
.header.type = htons (
|
||||
gc->wait_for_merge
|
||||
? TALER_DBEVENT_EXCHANGE_PURSE_MERGED
|
||||
: TALER_DBEVENT_EXCHANGE_PURSE_DEPOSITED),
|
||||
.purse_pub = gc->purse_pub
|
||||
};
|
||||
struct GNUNET_DB_EventHandler *eh2;
|
||||
|
||||
gc->timeout = gc->purse_expiration.abs_time;
|
||||
eh2 = TEH_plugin->event_listen (
|
||||
TEH_plugin->cls,
|
||||
GNUNET_TIME_absolute_get_remaining (gc->timeout),
|
||||
&rep.header,
|
||||
&db_event_cb,
|
||||
rc);
|
||||
if (NULL == eh2)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
gc->timeout = GNUNET_TIME_UNIT_ZERO_ABS;
|
||||
}
|
||||
TEH_plugin->event_listen_cancel (TEH_plugin->cls,
|
||||
gc->eh);
|
||||
gc->eh = eh2;
|
||||
}
|
||||
}
|
||||
if (GNUNET_TIME_absolute_is_past (gc->purse_expiration.abs_time))
|
||||
{
|
||||
|
@ -1193,6 +1193,14 @@ BEGIN
|
||||
'(merge_pub);'
|
||||
);
|
||||
|
||||
-- FIXME: drop index on master (crosses shards)?
|
||||
-- Or use materialized index? (needed?)
|
||||
EXECUTE FORMAT (
|
||||
'CREATE INDEX IF NOT EXISTS ' || table_name || '_purse_expiration '
|
||||
'ON ' || table_name || ' '
|
||||
'(purse_expiration);'
|
||||
);
|
||||
|
||||
END
|
||||
$$;
|
||||
|
||||
|
@ -2505,8 +2505,7 @@ UPDATE known_coins
|
||||
THEN 1
|
||||
ELSE 0
|
||||
END
|
||||
WHERE coin_pub=in_coin_pub
|
||||
LIMIT 1; -- just to be extra safe
|
||||
WHERE coin_pub=in_coin_pub;
|
||||
|
||||
|
||||
out_conflict=FALSE;
|
||||
@ -3363,7 +3362,6 @@ END $$;
|
||||
|
||||
|
||||
CREATE OR REPLACE FUNCTION exchange_do_expire_purse(
|
||||
IN in_partner_id INT8,
|
||||
IN in_start_time INT8,
|
||||
IN in_end_time INT8,
|
||||
OUT out_found BOOLEAN)
|
||||
@ -3375,25 +3373,26 @@ DECLARE
|
||||
my_deposit record;
|
||||
BEGIN
|
||||
|
||||
UPDATE purse_requests
|
||||
SET refunded=TRUE,
|
||||
finished=TRUE
|
||||
SELECT purse_pub
|
||||
INTO my_purse_pub
|
||||
FROM purse_requests
|
||||
WHERE (purse_expiration >= in_start_time) AND
|
||||
(purse_expiration < in_end_time) AND
|
||||
(NOT finished) AND
|
||||
(NOT refunded)
|
||||
RETURNING purse_pub
|
||||
,in_reserve_quota
|
||||
,flags
|
||||
INTO my_purse_pub
|
||||
,my_rq
|
||||
,my_flags;
|
||||
ORDER BY purse_expiration ASC
|
||||
LIMIT 1;
|
||||
out_found = FOUND;
|
||||
IF NOT FOUND
|
||||
THEN
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
UPDATE purse_requests
|
||||
SET refunded=TRUE,
|
||||
finished=TRUE
|
||||
WHERE purse_pub=my_purse_pub;
|
||||
|
||||
-- restore balance to each coin deposited into the purse
|
||||
FOR my_deposit IN
|
||||
SELECT coin_pub
|
||||
@ -3402,7 +3401,7 @@ FOR my_deposit IN
|
||||
FROM purse_deposits
|
||||
WHERE purse_pub = my_purse_pub
|
||||
LOOP
|
||||
UPDATE
|
||||
UPDATE known_coins SET
|
||||
remaining_frac=remaining_frac+my_deposit.amount_with_fee_frac
|
||||
- CASE
|
||||
WHEN remaining_frac+my_deposit.amount_with_fee_frac >= 100000000
|
||||
@ -3415,9 +3414,7 @@ LOOP
|
||||
THEN 1
|
||||
ELSE 0
|
||||
END
|
||||
FROM known_coins
|
||||
WHERE coin_pub = my_deposit.coin_pub
|
||||
LIMIT 1; -- just to be extra safe
|
||||
WHERE coin_pub = my_deposit.coin_pub;
|
||||
END LOOP;
|
||||
END $$;
|
||||
|
||||
|
@ -1211,6 +1211,30 @@ TALER_TESTING_cmd_exec_wirewatch (const char *label,
|
||||
const char *config_filename);
|
||||
|
||||
|
||||
/**
|
||||
* Make a "expire" CMD.
|
||||
*
|
||||
* @param label command label.
|
||||
* @param config_filename configuration filename.
|
||||
* @return the command.
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_exec_expire (const char *label,
|
||||
const char *config_filename);
|
||||
|
||||
|
||||
/**
|
||||
* Make a "router" CMD.
|
||||
*
|
||||
* @param label command label.
|
||||
* @param config_filename configuration filename.
|
||||
* @return the command.
|
||||
*/
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_exec_router (const char *label,
|
||||
const char *config_filename);
|
||||
|
||||
|
||||
/**
|
||||
* Run a "taler-exchange-aggregator" CMD.
|
||||
*
|
||||
|
@ -169,6 +169,11 @@ handle_purse_get_finished (void *cls,
|
||||
/* Exchange does not know about transaction;
|
||||
we should pass the reply to the application */
|
||||
break;
|
||||
case MHD_HTTP_GONE:
|
||||
/* purse expired */
|
||||
dr.hr.ec = TALER_JSON_get_error_code (j);
|
||||
dr.hr.hint = TALER_JSON_get_error_hint (j);
|
||||
break;
|
||||
case MHD_HTTP_INTERNAL_SERVER_ERROR:
|
||||
dr.hr.ec = TALER_JSON_get_error_code (j);
|
||||
dr.hr.hint = TALER_JSON_get_error_hint (j);
|
||||
|
@ -61,6 +61,8 @@ libtalertesting_la_SOURCES = \
|
||||
testing_api_cmd_exec_aggregator.c \
|
||||
testing_api_cmd_exec_auditor-offline.c \
|
||||
testing_api_cmd_exec_closer.c \
|
||||
testing_api_cmd_exec_expire.c \
|
||||
testing_api_cmd_exec_router.c \
|
||||
testing_api_cmd_exec_transfer.c \
|
||||
testing_api_cmd_exec_wirewatch.c \
|
||||
testing_api_cmd_insert_deposit.c \
|
||||
|
@ -45,6 +45,14 @@ DB = postgres
|
||||
# exchange (or the twister) is actually listening.
|
||||
BASE_URL = "http://localhost:8081/"
|
||||
|
||||
# How big is an individual shard to be processed
|
||||
# by taler-exchange-expire (in time). It may take
|
||||
# this much time for an expired purse to be really
|
||||
# cleaned up and the coins refunded.
|
||||
EXPIRE_SHARD_SIZE = 300 ms
|
||||
|
||||
EXPIRE_IDLE_SLEEP_INTERVAL = 1 s
|
||||
|
||||
[exchangedb-postgres]
|
||||
CONFIG = "postgres:///talercheck"
|
||||
|
||||
|
@ -45,6 +45,15 @@ DB = postgres
|
||||
# exchange (or the twister) is actually listening.
|
||||
BASE_URL = "http://localhost:8081/"
|
||||
|
||||
# How big is an individual shard to be processed
|
||||
# by taler-exchange-expire (in time). It may take
|
||||
# this much time for an expired purse to be really
|
||||
# cleaned up and the coins refunded.
|
||||
EXPIRE_SHARD_SIZE = 300 ms
|
||||
|
||||
EXPIRE_IDLE_SLEEP_INTERVAL = 1 s
|
||||
|
||||
|
||||
[exchangedb-postgres]
|
||||
CONFIG = "postgres:///talercheck"
|
||||
|
||||
|
@ -277,6 +277,62 @@ run (void *cls,
|
||||
TALER_TESTING_cmd_end ()
|
||||
};
|
||||
|
||||
struct TALER_TESTING_Command expire[] = {
|
||||
TALER_TESTING_cmd_purse_create_with_reserve (
|
||||
"purse-create-with-reserve-expire",
|
||||
MHD_HTTP_OK,
|
||||
"{\"amount\":\"EUR:1\",\"summary\":\"ice cream\"}",
|
||||
true /* upload contract */,
|
||||
GNUNET_TIME_relative_multiply (
|
||||
GNUNET_TIME_UNIT_SECONDS,
|
||||
1), /* expiration */
|
||||
"create-reserve-1"),
|
||||
TALER_TESTING_cmd_purse_poll (
|
||||
"pull-poll-purse-before-expire",
|
||||
MHD_HTTP_GONE,
|
||||
"purse-create-with-reserve-expire",
|
||||
"EUR:1",
|
||||
false,
|
||||
GNUNET_TIME_UNIT_MINUTES),
|
||||
TALER_TESTING_cmd_purse_create_with_deposit (
|
||||
"purse-with-deposit-expire",
|
||||
MHD_HTTP_OK,
|
||||
"{\"amount\":\"EUR:1\",\"summary\":\"ice cream\"}",
|
||||
true, /* upload contract */
|
||||
GNUNET_TIME_relative_multiply (
|
||||
GNUNET_TIME_UNIT_SECONDS,
|
||||
1), /* expiration */
|
||||
"withdraw-coin-1",
|
||||
"EUR:1.01",
|
||||
NULL),
|
||||
TALER_TESTING_cmd_purse_poll (
|
||||
"push-poll-purse-before-expire",
|
||||
MHD_HTTP_GONE,
|
||||
"purse-with-deposit-expire",
|
||||
"EUR:1",
|
||||
true,
|
||||
GNUNET_TIME_UNIT_MINUTES),
|
||||
TALER_TESTING_cmd_sleep ("sleep",
|
||||
2 /* seconds */),
|
||||
TALER_TESTING_cmd_exec_expire ("exec-expire",
|
||||
config_file),
|
||||
TALER_TESTING_cmd_purse_poll_finish (
|
||||
"push-merge-purse-poll-finish-expire",
|
||||
GNUNET_TIME_relative_multiply (
|
||||
GNUNET_TIME_UNIT_SECONDS,
|
||||
15),
|
||||
"push-poll-purse-before-expire"),
|
||||
TALER_TESTING_cmd_purse_poll_finish (
|
||||
"pull-deposit-purse-poll-expire-finish",
|
||||
GNUNET_TIME_relative_multiply (
|
||||
GNUNET_TIME_UNIT_SECONDS,
|
||||
15),
|
||||
"pull-poll-purse-before-expire"),
|
||||
// FIXME: check coin was refunded
|
||||
// FIXME: check reserve purse capacity is back up!
|
||||
TALER_TESTING_cmd_end ()
|
||||
};
|
||||
|
||||
struct TALER_TESTING_Command commands[] = {
|
||||
/* setup exchange */
|
||||
TALER_TESTING_cmd_auditor_add ("add-auditor-OK",
|
||||
@ -313,6 +369,8 @@ run (void *cls,
|
||||
push),
|
||||
TALER_TESTING_cmd_batch ("pull",
|
||||
pull),
|
||||
TALER_TESTING_cmd_batch ("expire",
|
||||
expire),
|
||||
/* End the suite. */
|
||||
TALER_TESTING_cmd_end ()
|
||||
};
|
||||
|
162
src/testing/testing_api_cmd_exec_expire.c
Normal file
162
src/testing/testing_api_cmd_exec_expire.c
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 3,
|
||||
or (at your option) any later version.
|
||||
|
||||
TALER is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with TALER; see the file COPYING. If not, see
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file testing/testing_api_cmd_exec_expire.c
|
||||
* @brief run the taler-exchange-expire command
|
||||
* @author Christian Grothoff
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "taler_signatures.h"
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
|
||||
/**
|
||||
* State for a "expire" CMD.
|
||||
*/
|
||||
struct ExpireState
|
||||
{
|
||||
|
||||
/**
|
||||
* Process for the expireer.
|
||||
*/
|
||||
struct GNUNET_OS_Process *expire_proc;
|
||||
|
||||
/**
|
||||
* Configuration file used by the expireer.
|
||||
*/
|
||||
const char *config_filename;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Run the command; use the `taler-exchange-expire' program.
|
||||
*
|
||||
* @param cls closure.
|
||||
* @param cmd command currently being executed.
|
||||
* @param is interpreter state.
|
||||
*/
|
||||
static void
|
||||
expire_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
struct ExpireState *ws = cls;
|
||||
|
||||
(void) cmd;
|
||||
ws->expire_proc
|
||||
= GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
|
||||
NULL, NULL, NULL,
|
||||
"taler-exchange-expire",
|
||||
"taler-exchange-expire",
|
||||
"-L", "INFO",
|
||||
"-c", ws->config_filename,
|
||||
"-t", /* exit when done */
|
||||
NULL);
|
||||
if (NULL == ws->expire_proc)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
TALER_TESTING_wait_for_sigchld (is);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free the state of a "expire" CMD, and possibly
|
||||
* kills its process if it did not terminate regularly.
|
||||
*
|
||||
* @param cls closure.
|
||||
* @param cmd the command being freed.
|
||||
*/
|
||||
static void
|
||||
expire_cleanup (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd)
|
||||
{
|
||||
struct ExpireState *ws = cls;
|
||||
|
||||
(void) cmd;
|
||||
if (NULL != ws->expire_proc)
|
||||
{
|
||||
GNUNET_break (0 ==
|
||||
GNUNET_OS_process_kill (ws->expire_proc,
|
||||
SIGKILL));
|
||||
GNUNET_OS_process_wait (ws->expire_proc);
|
||||
GNUNET_OS_process_destroy (ws->expire_proc);
|
||||
ws->expire_proc = NULL;
|
||||
}
|
||||
GNUNET_free (ws);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Offer "expire" CMD internal data to other commands.
|
||||
*
|
||||
* @param cls closure.
|
||||
* @param[out] ret result.
|
||||
* @param trait name of the trait.
|
||||
* @param index index number of the object to offer.
|
||||
* @return #GNUNET_OK on success.
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
expire_traits (void *cls,
|
||||
const void **ret,
|
||||
const char *trait,
|
||||
unsigned int index)
|
||||
{
|
||||
struct ExpireState *ws = cls;
|
||||
struct TALER_TESTING_Trait traits[] = {
|
||||
TALER_TESTING_make_trait_process (&ws->expire_proc),
|
||||
TALER_TESTING_trait_end ()
|
||||
};
|
||||
|
||||
return TALER_TESTING_get_trait (traits,
|
||||
ret,
|
||||
trait,
|
||||
index);
|
||||
}
|
||||
|
||||
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_exec_expire (const char *label,
|
||||
const char *config_filename)
|
||||
{
|
||||
struct ExpireState *ws;
|
||||
|
||||
ws = GNUNET_new (struct ExpireState);
|
||||
ws->config_filename = config_filename;
|
||||
|
||||
{
|
||||
struct TALER_TESTING_Command cmd = {
|
||||
.cls = ws,
|
||||
.label = label,
|
||||
.run = &expire_run,
|
||||
.cleanup = &expire_cleanup,
|
||||
.traits = &expire_traits
|
||||
};
|
||||
|
||||
return cmd;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* end of testing_api_cmd_exec_expire.c */
|
161
src/testing/testing_api_cmd_exec_router.c
Normal file
161
src/testing/testing_api_cmd_exec_router.c
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 3,
|
||||
or (at your option) any later version.
|
||||
|
||||
TALER is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with TALER; see the file COPYING. If not, see
|
||||
<http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file testing/testing_api_cmd_exec_router.c
|
||||
* @brief run the taler-exchange-router command
|
||||
* @author Christian Grothoff
|
||||
* @author Marcello Stanisci
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include <gnunet/gnunet_curl_lib.h>
|
||||
#include "taler_signatures.h"
|
||||
#include "taler_testing_lib.h"
|
||||
|
||||
|
||||
/**
|
||||
* State for a "router" CMD.
|
||||
*/
|
||||
struct RouterState
|
||||
{
|
||||
|
||||
/**
|
||||
* Process for the routerer.
|
||||
*/
|
||||
struct GNUNET_OS_Process *router_proc;
|
||||
|
||||
/**
|
||||
* Configuration file used by the routerer.
|
||||
*/
|
||||
const char *config_filename;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Run the command; use the `taler-exchange-router' program.
|
||||
*
|
||||
* @param cls closure.
|
||||
* @param cmd command currently being executed.
|
||||
* @param is interpreter state.
|
||||
*/
|
||||
static void
|
||||
router_run (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd,
|
||||
struct TALER_TESTING_Interpreter *is)
|
||||
{
|
||||
struct RouterState *ws = cls;
|
||||
|
||||
(void) cmd;
|
||||
ws->router_proc
|
||||
= GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
|
||||
NULL, NULL, NULL,
|
||||
"taler-exchange-router",
|
||||
"taler-exchange-router",
|
||||
"-c", ws->config_filename,
|
||||
"-t", /* exit when done */
|
||||
NULL);
|
||||
if (NULL == ws->router_proc)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_TESTING_interpreter_fail (is);
|
||||
return;
|
||||
}
|
||||
TALER_TESTING_wait_for_sigchld (is);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free the state of a "router" CMD, and possibly
|
||||
* kills its process if it did not terminate regularly.
|
||||
*
|
||||
* @param cls closure.
|
||||
* @param cmd the command being freed.
|
||||
*/
|
||||
static void
|
||||
router_cleanup (void *cls,
|
||||
const struct TALER_TESTING_Command *cmd)
|
||||
{
|
||||
struct RouterState *ws = cls;
|
||||
|
||||
(void) cmd;
|
||||
if (NULL != ws->router_proc)
|
||||
{
|
||||
GNUNET_break (0 ==
|
||||
GNUNET_OS_process_kill (ws->router_proc,
|
||||
SIGKILL));
|
||||
GNUNET_OS_process_wait (ws->router_proc);
|
||||
GNUNET_OS_process_destroy (ws->router_proc);
|
||||
ws->router_proc = NULL;
|
||||
}
|
||||
GNUNET_free (ws);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Offer "router" CMD internal data to other commands.
|
||||
*
|
||||
* @param cls closure.
|
||||
* @param[out] ret result.
|
||||
* @param trait name of the trait.
|
||||
* @param index index number of the object to offer.
|
||||
* @return #GNUNET_OK on success.
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
router_traits (void *cls,
|
||||
const void **ret,
|
||||
const char *trait,
|
||||
unsigned int index)
|
||||
{
|
||||
struct RouterState *ws = cls;
|
||||
struct TALER_TESTING_Trait traits[] = {
|
||||
TALER_TESTING_make_trait_process (&ws->router_proc),
|
||||
TALER_TESTING_trait_end ()
|
||||
};
|
||||
|
||||
return TALER_TESTING_get_trait (traits,
|
||||
ret,
|
||||
trait,
|
||||
index);
|
||||
}
|
||||
|
||||
|
||||
struct TALER_TESTING_Command
|
||||
TALER_TESTING_cmd_exec_router (const char *label,
|
||||
const char *config_filename)
|
||||
{
|
||||
struct RouterState *ws;
|
||||
|
||||
ws = GNUNET_new (struct RouterState);
|
||||
ws->config_filename = config_filename;
|
||||
|
||||
{
|
||||
struct TALER_TESTING_Command cmd = {
|
||||
.cls = ws,
|
||||
.label = label,
|
||||
.run = &router_run,
|
||||
.cleanup = &router_cleanup,
|
||||
.traits = &router_traits
|
||||
};
|
||||
|
||||
return cmd;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* end of testing_api_cmd_exec_router.c */
|
@ -261,6 +261,7 @@ TALER_TESTING_cmd_purse_poll (
|
||||
ss->expected_balance = expected_balance;
|
||||
ss->expected_response_code = expected_http_status;
|
||||
ss->timeout = timeout;
|
||||
ss->wait_for_merge = wait_for_merge;
|
||||
{
|
||||
struct TALER_TESTING_Command cmd = {
|
||||
.cls = ss,
|
||||
|
Loading…
Reference in New Issue
Block a user