Browse Source

daemon: dev-mocktime command

Useful for precise timing control for testing.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 9 years ago
parent
commit
a3e3f83d9f
  1. 2
      daemon/Makefile
  2. 52
      daemon/controlled_time.c
  3. 9
      daemon/controlled_time.h
  4. 1
      daemon/jsonrpc.c
  5. 1
      daemon/jsonrpc.h
  6. 6
      daemon/lightning-cli.c
  7. 6
      daemon/lightningd.c
  8. 5
      daemon/log.c
  9. 3
      daemon/timeout.c

2
daemon/Makefile

@ -15,6 +15,7 @@ DAEMON_LIB_OBJS := $(DAEMON_LIB_SRC:.c=.o)
DAEMON_SRC := \
daemon/bitcoind.c \
daemon/controlled_time.c \
daemon/cryptopkt.c \
daemon/dns.c \
daemon/jsonrpc.c \
@ -39,6 +40,7 @@ DAEMON_JSMN_HEADERS := daemon/jsmn/jsmn.h
DAEMON_HEADERS := \
daemon/bitcoind.h \
daemon/configdir.h \
daemon/controlled_time.h \
daemon/cryptopkt.h \
daemon/dns.h \
daemon/json.h \

52
daemon/controlled_time.c

@ -0,0 +1,52 @@
#include "controlled_time.h"
#include "jsonrpc.h"
#include "lightningd.h"
#include "log.h"
#include <inttypes.h>
#include <stdio.h>
static struct timeabs mock_time;
struct timeabs controlled_time(void)
{
if (mock_time.ts.tv_sec)
return mock_time;
return time_now();
}
static void json_mocktime(struct command *cmd,
const char *buffer, const jsmntok_t *params)
{
struct json_result *response = new_json_result(cmd);
jsmntok_t *mocktimetok;
u64 prev_time, mocktime;
char mocktimestr[STR_MAX_CHARS(int64_t)];
json_get_params(buffer, params,
"mocktime", &mocktimetok,
NULL);
prev_time = controlled_time().ts.tv_sec;
if (!mocktimetok || !json_tok_u64(buffer, mocktimetok, &mocktime)) {
command_fail(cmd, "Need valid mocktime");
return;
}
mock_time.ts.tv_sec = mocktime;
json_object_start(response, NULL);
sprintf(mocktimestr, "%"PRIi64,
(s64)controlled_time().ts.tv_sec - prev_time);
json_add_string(response, "offset", mocktimestr);
json_object_end(response);
log_unusual(cmd->dstate->base_log,
"mocktime set to %"PRIu64, (u64)mock_time.ts.tv_sec);
command_success(cmd, response);
}
const struct json_command mocktime_command = {
"dev-mocktime",
json_mocktime,
"Set current time to {mocktime} seconds (0 to return to normal)",
"Returns the offset on success"
};

9
daemon/controlled_time.h

@ -0,0 +1,9 @@
#ifndef LIGHTNING_DAEMON_CONTROLLED_TIME_H
#define LIGHTNING_DAEMON_CONTROLLED_TIME_H
#include "config.h"
#include <ccan/short_types/short_types.h>
#include <ccan/time/time.h>
struct timeabs controlled_time(void);
#endif /* LIGHTNING_DAEMON_CONTROLLED_TIME_H */

1
daemon/jsonrpc.c

@ -244,6 +244,7 @@ static const struct json_command *cmdlist[] = {
/* Developer/debugging options. */
&echo_command,
&rhash_command,
&mocktime_command
};
static void json_help(struct command *cmd,

1
daemon/jsonrpc.h

@ -61,4 +61,5 @@ extern const struct json_command getpeers_command;
extern const struct json_command newhtlc_command;
extern const struct json_command fulfillhtlc_command;
extern const struct json_command failhtlc_command;
extern const struct json_command mocktime_command;
#endif /* LIGHTNING_DAEMON_JSONRPC_H */

6
daemon/lightning-cli.c

@ -2,6 +2,7 @@
* Helper to submit via JSON-RPC and get back response.
*/
#include "configdir.h"
#include "controlled_time.h"
#include "json.h"
#include "version.h"
#include <ccan/err/err.h>
@ -39,6 +40,11 @@ static void tal_freefn(void *ptr)
tal_free(ptr);
}
struct timeabs controlled_time(void)
{
return time_now();
}
int main(int argc, char *argv[])
{
int fd, i, off;

6
daemon/lightningd.c

@ -1,5 +1,6 @@
#include "bitcoind.h"
#include "configdir.h"
#include "controlled_time.h"
#include "jsonrpc.h"
#include "lightningd.h"
#include "log.h"
@ -147,7 +148,7 @@ static struct lightningd_state *lightningd_state(void)
"lightningd(%u):", (int)getpid());
list_head_init(&dstate->peers);
timers_init(&dstate->timers, time_now());
timers_init(&dstate->timers, controlled_time());
txwatch_hash_init(&dstate->txwatches);
txowatch_hash_init(&dstate->txowatches);
dstate->secpctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY
@ -240,6 +241,9 @@ int main(int argc, char *argv[])
/* Create timer to do watches. */
setup_watch_timer(dstate);
/* Make sure we use the artificially-controlled time for timers */
io_time_override(controlled_time);
log_info(dstate->base_log, "Hello world!");
/* If io_loop returns NULL, either a timer expired, or all fds closed */

5
daemon/log.c

@ -1,3 +1,4 @@
#include "controlled_time.h"
#include "log.h"
#include "pseudorand.h"
#include <ccan/array_size/array_size.h>
@ -102,7 +103,7 @@ struct log_record *new_log_record(const tal_t *ctx,
lr->max_mem = max_mem;
lr->print = log_default_print;
lr->print_level = printlevel;
lr->init_time = time_now();
lr->init_time = controlled_time();
list_head_init(&lr->log);
return lr;
@ -183,7 +184,7 @@ static struct log_entry *new_log_entry(struct log *log, enum log_level level)
{
struct log_entry *l = tal(log->lr, struct log_entry);
l->time = time_now();
l->time = controlled_time();
l->level = level;
l->skipped = 0;
l->prefix = log->prefix;

3
daemon/timeout.c

@ -1,3 +1,4 @@
#include "controlled_time.h"
#include "lightningd.h"
#include "timeout.h"
@ -14,7 +15,7 @@ void refresh_timeout(struct lightningd_state *dstate, struct timeout *t)
{
timer_del(&dstate->timers, &t->timer);
timer_add(&dstate->timers, &t->timer,
timeabs_add(time_now(), t->interval));
timeabs_add(controlled_time(), t->interval));
}
/* FIXME: Make all timers one-shot! */

Loading…
Cancel
Save