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-aggregator
|
||||||
usr/bin/taler-exchange-closer
|
usr/bin/taler-exchange-closer
|
||||||
usr/bin/taler-exchange-dbinit
|
usr/bin/taler-exchange-dbinit
|
||||||
|
usr/bin/taler-exchange-expire
|
||||||
usr/bin/taler-exchange-httpd
|
usr/bin/taler-exchange-httpd
|
||||||
|
usr/bin/taler-exchange-router
|
||||||
usr/bin/taler-exchange-secmod-cs
|
usr/bin/taler-exchange-secmod-cs
|
||||||
usr/bin/taler-exchange-secmod-eddsa
|
usr/bin/taler-exchange-secmod-eddsa
|
||||||
usr/bin/taler-exchange-secmod-rsa
|
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-aggregator*
|
||||||
usr/share/man/man1/taler-exchange-closer*
|
usr/share/man/man1/taler-exchange-closer*
|
||||||
usr/share/man/man1/taler-exchange-dbinit*
|
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-httpd*
|
||||||
|
usr/share/man/man1/taler-exchange-router*
|
||||||
usr/share/man/man1/taler-exchange-secmod-eddsa*
|
usr/share/man/man1/taler-exchange-secmod-eddsa*
|
||||||
usr/share/man/man1/taler-exchange-secmod-rsa*
|
usr/share/man/man1/taler-exchange-secmod-rsa*
|
||||||
usr/share/man/man1/taler-exchange-secmod-cs*
|
usr/share/man/man1/taler-exchange-secmod-cs*
|
||||||
|
@ -95,6 +95,12 @@ static int global_ret;
|
|||||||
*/
|
*/
|
||||||
static int test_mode;
|
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.
|
* Select a shard to work on.
|
||||||
@ -188,6 +194,7 @@ static void
|
|||||||
release_shard (struct Shard *s)
|
release_shard (struct Shard *s)
|
||||||
{
|
{
|
||||||
enum GNUNET_DB_QueryStatus qs;
|
enum GNUNET_DB_QueryStatus qs;
|
||||||
|
unsigned long long wc = (unsigned long long) s->work_counter;
|
||||||
|
|
||||||
qs = db_plugin->complete_shard (
|
qs = db_plugin->complete_shard (
|
||||||
db_plugin->cls,
|
db_plugin->cls,
|
||||||
@ -209,10 +216,14 @@ release_shard (struct Shard *s)
|
|||||||
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
|
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
"Purse expiration shard completed with %llu purses\n",
|
"Purse expiration shard completed with %llu purses\n",
|
||||||
(unsigned long long) s->work_counter);
|
wc);
|
||||||
/* normal case */
|
/* normal case */
|
||||||
break;
|
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,
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
"Failed to obtain database connection!\n");
|
"Failed to obtain database connection!\n");
|
||||||
|
abort_shard (s);
|
||||||
global_ret = EXIT_FAILURE;
|
global_ret = EXIT_FAILURE;
|
||||||
GNUNET_SCHEDULER_shutdown ();
|
GNUNET_SCHEDULER_shutdown ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (db_plugin->start (db_plugin->cls,
|
if (GNUNET_OK !=
|
||||||
|
db_plugin->start (db_plugin->cls,
|
||||||
"expire-purse"))
|
"expire-purse"))
|
||||||
{
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
global_ret = EXIT_FAILURE;
|
global_ret = EXIT_FAILURE;
|
||||||
db_plugin->rollback (db_plugin->cls);
|
db_plugin->rollback (db_plugin->cls);
|
||||||
abort_shard (s);
|
abort_shard (s);
|
||||||
@ -290,6 +304,7 @@ run_expire (void *cls)
|
|||||||
case GNUNET_DB_STATUS_SOFT_ERROR:
|
case GNUNET_DB_STATUS_SOFT_ERROR:
|
||||||
db_plugin->rollback (db_plugin->cls);
|
db_plugin->rollback (db_plugin->cls);
|
||||||
abort_shard (s);
|
abort_shard (s);
|
||||||
|
GNUNET_assert (NULL == task);
|
||||||
task = GNUNET_SCHEDULER_add_now (&run_shard,
|
task = GNUNET_SCHEDULER_add_now (&run_shard,
|
||||||
NULL);
|
NULL);
|
||||||
return;
|
return;
|
||||||
@ -303,6 +318,7 @@ run_expire (void *cls)
|
|||||||
{
|
{
|
||||||
release_shard (s);
|
release_shard (s);
|
||||||
}
|
}
|
||||||
|
GNUNET_assert (NULL == task);
|
||||||
task = GNUNET_SCHEDULER_add_now (&run_shard,
|
task = GNUNET_SCHEDULER_add_now (&run_shard,
|
||||||
NULL);
|
NULL);
|
||||||
return;
|
return;
|
||||||
@ -310,6 +326,7 @@ run_expire (void *cls)
|
|||||||
/* commit, and go again immediately */
|
/* commit, and go again immediately */
|
||||||
s->work_counter++;
|
s->work_counter++;
|
||||||
(void) commit_or_warn ();
|
(void) commit_or_warn ();
|
||||||
|
GNUNET_assert (NULL == task);
|
||||||
task = GNUNET_SCHEDULER_add_now (&run_expire,
|
task = GNUNET_SCHEDULER_add_now (&run_expire,
|
||||||
s);
|
s);
|
||||||
}
|
}
|
||||||
@ -343,9 +360,15 @@ run_shard (void *cls)
|
|||||||
qs = db_plugin->begin_shard (db_plugin->cls,
|
qs = db_plugin->begin_shard (db_plugin->cls,
|
||||||
"expire",
|
"expire",
|
||||||
shard_size,
|
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_start.abs_value_us,
|
||||||
&s->shard_end.abs_value_us);
|
&s->shard_end.abs_value_us);
|
||||||
|
jump_mode = false;
|
||||||
if (0 >= qs)
|
if (0 >= qs)
|
||||||
{
|
{
|
||||||
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
|
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
|
||||||
@ -355,6 +378,7 @@ run_shard (void *cls)
|
|||||||
GNUNET_free (s);
|
GNUNET_free (s);
|
||||||
delay = GNUNET_TIME_randomized_backoff (delay,
|
delay = GNUNET_TIME_randomized_backoff (delay,
|
||||||
GNUNET_TIME_UNIT_SECONDS);
|
GNUNET_TIME_UNIT_SECONDS);
|
||||||
|
GNUNET_assert (NULL == task);
|
||||||
task = GNUNET_SCHEDULER_add_delayed (delay,
|
task = GNUNET_SCHEDULER_add_delayed (delay,
|
||||||
&run_shard,
|
&run_shard,
|
||||||
NULL);
|
NULL);
|
||||||
@ -368,9 +392,10 @@ run_shard (void *cls)
|
|||||||
GNUNET_SCHEDULER_shutdown ();
|
GNUNET_SCHEDULER_shutdown ();
|
||||||
return;
|
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,
|
&run_shard,
|
||||||
NULL);
|
NULL);
|
||||||
abort_shard (s);
|
abort_shard (s);
|
||||||
@ -379,12 +404,12 @@ run_shard (void *cls)
|
|||||||
/* If this is a first-time run, we immediately
|
/* If this is a first-time run, we immediately
|
||||||
try to catch up with the present */
|
try to catch up with the present */
|
||||||
if (GNUNET_TIME_absolute_is_zero (s->shard_start))
|
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,
|
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_start.abs_value_us,
|
||||||
(unsigned long long) s->shard_end.abs_value_us);
|
(unsigned long long) s->shard_end.abs_value_us);
|
||||||
|
GNUNET_assert (NULL == task);
|
||||||
task = GNUNET_SCHEDULER_add_now (&run_expire,
|
task = GNUNET_SCHEDULER_add_now (&run_expire,
|
||||||
s);
|
s);
|
||||||
}
|
}
|
||||||
|
@ -333,6 +333,37 @@ TEH_handler_purses_get (struct TEH_RequestContext *rc,
|
|||||||
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
|
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
|
||||||
break; /* handled below */
|
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))
|
if (GNUNET_TIME_absolute_is_past (gc->purse_expiration.abs_time))
|
||||||
{
|
{
|
||||||
|
@ -1193,6 +1193,14 @@ BEGIN
|
|||||||
'(merge_pub);'
|
'(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
|
END
|
||||||
$$;
|
$$;
|
||||||
|
|
||||||
|
@ -2505,8 +2505,7 @@ UPDATE known_coins
|
|||||||
THEN 1
|
THEN 1
|
||||||
ELSE 0
|
ELSE 0
|
||||||
END
|
END
|
||||||
WHERE coin_pub=in_coin_pub
|
WHERE coin_pub=in_coin_pub;
|
||||||
LIMIT 1; -- just to be extra safe
|
|
||||||
|
|
||||||
|
|
||||||
out_conflict=FALSE;
|
out_conflict=FALSE;
|
||||||
@ -3363,7 +3362,6 @@ END $$;
|
|||||||
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION exchange_do_expire_purse(
|
CREATE OR REPLACE FUNCTION exchange_do_expire_purse(
|
||||||
IN in_partner_id INT8,
|
|
||||||
IN in_start_time INT8,
|
IN in_start_time INT8,
|
||||||
IN in_end_time INT8,
|
IN in_end_time INT8,
|
||||||
OUT out_found BOOLEAN)
|
OUT out_found BOOLEAN)
|
||||||
@ -3375,25 +3373,26 @@ DECLARE
|
|||||||
my_deposit record;
|
my_deposit record;
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|
||||||
UPDATE purse_requests
|
SELECT purse_pub
|
||||||
SET refunded=TRUE,
|
INTO my_purse_pub
|
||||||
finished=TRUE
|
FROM purse_requests
|
||||||
WHERE (purse_expiration >= in_start_time) AND
|
WHERE (purse_expiration >= in_start_time) AND
|
||||||
(purse_expiration < in_end_time) AND
|
(purse_expiration < in_end_time) AND
|
||||||
(NOT finished) AND
|
(NOT finished) AND
|
||||||
(NOT refunded)
|
(NOT refunded)
|
||||||
RETURNING purse_pub
|
ORDER BY purse_expiration ASC
|
||||||
,in_reserve_quota
|
LIMIT 1;
|
||||||
,flags
|
|
||||||
INTO my_purse_pub
|
|
||||||
,my_rq
|
|
||||||
,my_flags;
|
|
||||||
out_found = FOUND;
|
out_found = FOUND;
|
||||||
IF NOT FOUND
|
IF NOT FOUND
|
||||||
THEN
|
THEN
|
||||||
RETURN;
|
RETURN;
|
||||||
END IF;
|
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
|
-- restore balance to each coin deposited into the purse
|
||||||
FOR my_deposit IN
|
FOR my_deposit IN
|
||||||
SELECT coin_pub
|
SELECT coin_pub
|
||||||
@ -3402,7 +3401,7 @@ FOR my_deposit IN
|
|||||||
FROM purse_deposits
|
FROM purse_deposits
|
||||||
WHERE purse_pub = my_purse_pub
|
WHERE purse_pub = my_purse_pub
|
||||||
LOOP
|
LOOP
|
||||||
UPDATE
|
UPDATE known_coins SET
|
||||||
remaining_frac=remaining_frac+my_deposit.amount_with_fee_frac
|
remaining_frac=remaining_frac+my_deposit.amount_with_fee_frac
|
||||||
- CASE
|
- CASE
|
||||||
WHEN remaining_frac+my_deposit.amount_with_fee_frac >= 100000000
|
WHEN remaining_frac+my_deposit.amount_with_fee_frac >= 100000000
|
||||||
@ -3415,9 +3414,7 @@ LOOP
|
|||||||
THEN 1
|
THEN 1
|
||||||
ELSE 0
|
ELSE 0
|
||||||
END
|
END
|
||||||
FROM known_coins
|
WHERE coin_pub = my_deposit.coin_pub;
|
||||||
WHERE coin_pub = my_deposit.coin_pub
|
|
||||||
LIMIT 1; -- just to be extra safe
|
|
||||||
END LOOP;
|
END LOOP;
|
||||||
END $$;
|
END $$;
|
||||||
|
|
||||||
|
@ -1211,6 +1211,30 @@ TALER_TESTING_cmd_exec_wirewatch (const char *label,
|
|||||||
const char *config_filename);
|
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.
|
* Run a "taler-exchange-aggregator" CMD.
|
||||||
*
|
*
|
||||||
|
@ -169,6 +169,11 @@ handle_purse_get_finished (void *cls,
|
|||||||
/* Exchange does not know about transaction;
|
/* Exchange does not know about transaction;
|
||||||
we should pass the reply to the application */
|
we should pass the reply to the application */
|
||||||
break;
|
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:
|
case MHD_HTTP_INTERNAL_SERVER_ERROR:
|
||||||
dr.hr.ec = TALER_JSON_get_error_code (j);
|
dr.hr.ec = TALER_JSON_get_error_code (j);
|
||||||
dr.hr.hint = TALER_JSON_get_error_hint (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_aggregator.c \
|
||||||
testing_api_cmd_exec_auditor-offline.c \
|
testing_api_cmd_exec_auditor-offline.c \
|
||||||
testing_api_cmd_exec_closer.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_transfer.c \
|
||||||
testing_api_cmd_exec_wirewatch.c \
|
testing_api_cmd_exec_wirewatch.c \
|
||||||
testing_api_cmd_insert_deposit.c \
|
testing_api_cmd_insert_deposit.c \
|
||||||
|
@ -45,6 +45,14 @@ DB = postgres
|
|||||||
# exchange (or the twister) is actually listening.
|
# exchange (or the twister) is actually listening.
|
||||||
BASE_URL = "http://localhost:8081/"
|
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]
|
[exchangedb-postgres]
|
||||||
CONFIG = "postgres:///talercheck"
|
CONFIG = "postgres:///talercheck"
|
||||||
|
|
||||||
|
@ -45,6 +45,15 @@ DB = postgres
|
|||||||
# exchange (or the twister) is actually listening.
|
# exchange (or the twister) is actually listening.
|
||||||
BASE_URL = "http://localhost:8081/"
|
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]
|
[exchangedb-postgres]
|
||||||
CONFIG = "postgres:///talercheck"
|
CONFIG = "postgres:///talercheck"
|
||||||
|
|
||||||
|
@ -277,6 +277,62 @@ run (void *cls,
|
|||||||
TALER_TESTING_cmd_end ()
|
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[] = {
|
struct TALER_TESTING_Command commands[] = {
|
||||||
/* setup exchange */
|
/* setup exchange */
|
||||||
TALER_TESTING_cmd_auditor_add ("add-auditor-OK",
|
TALER_TESTING_cmd_auditor_add ("add-auditor-OK",
|
||||||
@ -313,6 +369,8 @@ run (void *cls,
|
|||||||
push),
|
push),
|
||||||
TALER_TESTING_cmd_batch ("pull",
|
TALER_TESTING_cmd_batch ("pull",
|
||||||
pull),
|
pull),
|
||||||
|
TALER_TESTING_cmd_batch ("expire",
|
||||||
|
expire),
|
||||||
/* End the suite. */
|
/* End the suite. */
|
||||||
TALER_TESTING_cmd_end ()
|
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_balance = expected_balance;
|
||||||
ss->expected_response_code = expected_http_status;
|
ss->expected_response_code = expected_http_status;
|
||||||
ss->timeout = timeout;
|
ss->timeout = timeout;
|
||||||
|
ss->wait_for_merge = wait_for_merge;
|
||||||
{
|
{
|
||||||
struct TALER_TESTING_Command cmd = {
|
struct TALER_TESTING_Command cmd = {
|
||||||
.cls = ss,
|
.cls = ss,
|
||||||
|
Loading…
Reference in New Issue
Block a user