Merge branch 'test-regress-be-openssl-v2'

This patchset is a bunch of regression tests for bufferevent openssl layer,
some of them already show some bugs, that bugs will be fixed in the next
patches.

* test-regress-be-openssl-v2:
  test/regress_ssl: check events fd/pending after timeout triggered
  test/regress_ssl: cover case when server didn't up (failed with timeout)
  test/regress_ssl: covert that we can't change fd with underlying
  test/regress_ssl: cover that events (read/write) at finish not pending
  test/regress_ssl: cover fd manipulations
  test/regress_ssl: convert open_ssl_bufevs() to mask
  test/regress_ssl: convert client/server to mask too
  test/regress_ssl: cover "allow_dirty_shutdown"
  test/regress_ssl: convert regress_bufferevent_openssl() to bitmask
This commit is contained in:
Azat Khuzhin 2015-09-02 19:18:08 +03:00
commit af85ecfccc

View File

@ -43,6 +43,7 @@
#include "event2/util.h"
#include "event2/event.h"
#include "event2/bufferevent_ssl.h"
#include "event2/bufferevent_struct.h"
#include "event2/buffer.h"
#include "event2/listener.h"
@ -177,17 +178,63 @@ static int test_is_done = 0;
static int n_connected = 0;
static int got_close = 0;
static int got_error = 0;
static int got_timeout = 0;
static int renegotiate_at = -1;
static int stop_when_connected = 0;
static int pending_connect_events = 0;
static struct event_base *exit_base = NULL;
enum regress_openssl_type
{
REGRESS_OPENSSL_SOCKETPAIR = 1,
REGRESS_OPENSSL_FILTER = 2,
REGRESS_OPENSSL_RENEGOTIATE = 4,
REGRESS_OPENSSL_OPEN = 8,
REGRESS_OPENSSL_DIRTY_SHUTDOWN = 16,
REGRESS_OPENSSL_FD = 32,
REGRESS_OPENSSL_CLIENT = 64,
REGRESS_OPENSSL_SERVER = 128,
REGRESS_OPENSSL_FREED = 256,
REGRESS_OPENSSL_TIMEOUT = 512,
};
static void
bufferevent_openssl_check_fd(struct bufferevent *bev, int filter)
{
if (filter) {
tt_int_op(bufferevent_getfd(bev), ==, -1);
tt_int_op(bufferevent_setfd(bev, -1), ==, -1);
} else {
tt_int_op(bufferevent_getfd(bev), !=, -1);
tt_int_op(bufferevent_setfd(bev, -1), ==, 0);
}
tt_int_op(bufferevent_getfd(bev), ==, -1);
end:
;
}
static void
bufferevent_openssl_check_freed(struct bufferevent *bev)
{
tt_int_op(event_pending(&bev->ev_read, EVLIST_ALL, NULL), ==, 0);
tt_int_op(event_pending(&bev->ev_write, EVLIST_ALL, NULL), ==, 0);
end:
;
}
static void
respond_to_number(struct bufferevent *bev, void *ctx)
{
struct evbuffer *b = bufferevent_get_input(bev);
char *line;
int n;
enum regress_openssl_type type;
type = (enum regress_openssl_type)ctx;
line = evbuffer_readln(b, NULL, EVBUFFER_EOL_LF);
if (! line)
return;
@ -201,7 +248,7 @@ respond_to_number(struct bufferevent *bev, void *ctx)
bufferevent_free(bev); /* Should trigger close on other side. */
return;
}
if (!strcmp(ctx, "client") && n == renegotiate_at) {
if ((type & REGRESS_OPENSSL_CLIENT) && n == renegotiate_at) {
SSL_renegotiate(bufferevent_openssl_get_ssl(bev));
}
++n;
@ -226,6 +273,9 @@ done_writing_cb(struct bufferevent *bev, void *ctx)
static void
eventcb(struct bufferevent *bev, short what, void *ctx)
{
enum regress_openssl_type type;
type = (enum regress_openssl_type)ctx;
TT_BLATHER(("Got event %d", (int)what));
if (what & BEV_EVENT_CONNECTED) {
SSL *ssl;
@ -234,7 +284,7 @@ eventcb(struct bufferevent *bev, short what, void *ctx)
ssl = bufferevent_openssl_get_ssl(bev);
tt_assert(ssl);
peer_cert = SSL_get_peer_certificate(ssl);
if (0==strcmp(ctx, "server")) {
if (type & REGRESS_OPENSSL_SERVER) {
tt_assert(peer_cert == NULL);
} else {
tt_assert(peer_cert != NULL);
@ -246,10 +296,32 @@ eventcb(struct bufferevent *bev, short what, void *ctx)
} else if (what & BEV_EVENT_EOF) {
TT_BLATHER(("Got a good EOF"));
++got_close;
if (type & REGRESS_OPENSSL_FD) {
bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
}
if (type & REGRESS_OPENSSL_FREED) {
bufferevent_openssl_check_freed(bev);
}
bufferevent_free(bev);
} else if (what & BEV_EVENT_ERROR) {
TT_BLATHER(("Got an error."));
++got_error;
if (type & REGRESS_OPENSSL_FD) {
bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
}
if (type & REGRESS_OPENSSL_FREED) {
bufferevent_openssl_check_freed(bev);
}
bufferevent_free(bev);
} else if (what & BEV_EVENT_TIMEOUT) {
TT_BLATHER(("Got timeout."));
++got_timeout;
if (type & REGRESS_OPENSSL_FD) {
bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
}
if (type & REGRESS_OPENSSL_FREED) {
bufferevent_openssl_check_freed(bev);
}
bufferevent_free(bev);
}
end:
@ -259,7 +331,8 @@ end:
static void
open_ssl_bufevs(struct bufferevent **bev1_out, struct bufferevent **bev2_out,
struct event_base *base, int is_open, int flags, SSL *ssl1, SSL *ssl2,
evutil_socket_t *fd_pair, struct bufferevent **underlying_pair)
evutil_socket_t *fd_pair, struct bufferevent **underlying_pair,
enum regress_openssl_type type)
{
int state1 = is_open ? BUFFEREVENT_SSL_OPEN :BUFFEREVENT_SSL_CONNECTING;
int state2 = is_open ? BUFFEREVENT_SSL_OPEN :BUFFEREVENT_SSL_ACCEPTING;
@ -276,9 +349,13 @@ open_ssl_bufevs(struct bufferevent **bev1_out, struct bufferevent **bev2_out,
}
bufferevent_setcb(*bev1_out, respond_to_number, done_writing_cb,
eventcb, (void*)"client");
eventcb, (void*)(REGRESS_OPENSSL_CLIENT | (long)type));
bufferevent_setcb(*bev2_out, respond_to_number, done_writing_cb,
eventcb, (void*)"server");
eventcb, (void*)(REGRESS_OPENSSL_SERVER | (long)type));
int dirty_shutdown = type & REGRESS_OPENSSL_DIRTY_SHUTDOWN;
bufferevent_openssl_set_allow_dirty_shutdown(*bev1_out, dirty_shutdown);
bufferevent_openssl_set_allow_dirty_shutdown(*bev2_out, dirty_shutdown);
}
static void
@ -290,18 +367,19 @@ regress_bufferevent_openssl(void *arg)
SSL *ssl1, *ssl2;
X509 *cert = getcert();
EVP_PKEY *key = getkey();
const int start_open = strstr((char*)data->setup_data, "open")!=NULL;
const int filter = strstr((char*)data->setup_data, "filter")!=NULL;
int flags = BEV_OPT_DEFER_CALLBACKS;
struct bufferevent *bev_ll[2] = { NULL, NULL };
evutil_socket_t *fd_pair = NULL;
enum regress_openssl_type type;
type = (enum regress_openssl_type)data->setup_data;
tt_assert(cert);
tt_assert(key);
init_ssl();
if (strstr((char*)data->setup_data, "renegotiate")) {
if (type & REGRESS_OPENSSL_RENEGOTIATE) {
if (SSLeay() >= 0x10001000 &&
SSLeay() < 0x1000104f) {
/* 1.0.1 up to 1.0.1c has a bug where TLS1.1 and 1.2
@ -317,11 +395,11 @@ regress_bufferevent_openssl(void *arg)
SSL_use_certificate(ssl2, cert);
SSL_use_PrivateKey(ssl2, key);
if (! start_open)
if (!(type & REGRESS_OPENSSL_OPEN))
flags |= BEV_OPT_CLOSE_ON_FREE;
if (!filter) {
tt_assert(strstr((char*)data->setup_data, "socketpair"));
if (!(type & REGRESS_OPENSSL_FILTER)) {
tt_assert(type & REGRESS_OPENSSL_SOCKETPAIR);
fd_pair = data->pair;
} else {
bev_ll[0] = bufferevent_socket_new(data->base, data->pair[0],
@ -331,15 +409,15 @@ regress_bufferevent_openssl(void *arg)
}
open_ssl_bufevs(&bev1, &bev2, data->base, 0, flags, ssl1, ssl2,
fd_pair, bev_ll);
fd_pair, bev_ll, type);
if (!filter) {
if (!(type & REGRESS_OPENSSL_FILTER)) {
tt_int_op(bufferevent_getfd(bev1), ==, data->pair[0]);
} else {
tt_ptr_op(bufferevent_get_underlying(bev1), ==, bev_ll[0]);
}
if (start_open) {
if (type & REGRESS_OPENSSL_OPEN) {
pending_connect_events = 2;
stop_when_connected = 1;
exit_base = data->base;
@ -351,23 +429,47 @@ regress_bufferevent_openssl(void *arg)
bufferevent_free(bev2);
bev1 = bev2 = NULL;
open_ssl_bufevs(&bev1, &bev2, data->base, 1, flags, ssl1, ssl2,
fd_pair, bev_ll);
fd_pair, bev_ll, type);
}
bufferevent_enable(bev1, EV_READ|EV_WRITE);
bufferevent_enable(bev2, EV_READ|EV_WRITE);
if (!(type & REGRESS_OPENSSL_TIMEOUT)) {
bufferevent_enable(bev1, EV_READ|EV_WRITE);
bufferevent_enable(bev2, EV_READ|EV_WRITE);
evbuffer_add_printf(bufferevent_get_output(bev1), "1\n");
evbuffer_add_printf(bufferevent_get_output(bev1), "1\n");
event_base_dispatch(data->base);
event_base_dispatch(data->base);
tt_assert(test_is_done == 1);
tt_assert(n_connected == 2);
tt_assert(test_is_done == 1);
tt_assert(n_connected == 2);
/* We don't handle shutdown properly yet.
tt_int_op(got_close, ==, 1);
tt_int_op(got_error, ==, 0);
*/
/* We don't handle shutdown properly yet */
if (type & REGRESS_OPENSSL_DIRTY_SHUTDOWN) {
tt_int_op(got_close, ==, 1);
tt_int_op(got_error, ==, 0);
} else {
tt_int_op(got_error, ==, 1);
}
tt_int_op(got_timeout, ==, 0);
} else {
struct timeval t = { 2 };
bufferevent_enable(bev1, EV_READ|EV_WRITE);
bufferevent_disable(bev2, EV_READ|EV_WRITE);
bufferevent_set_timeouts(bev1, &t, &t);
evbuffer_add_printf(bufferevent_get_output(bev1), "1\n");
event_base_dispatch(data->base);
tt_assert(test_is_done == 0);
tt_assert(n_connected == 0);
tt_int_op(got_close, ==, 0);
tt_int_op(got_error, ==, 0);
tt_int_op(got_timeout, ==, 1);
}
end:
return;
}
@ -391,7 +493,7 @@ acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
bufferevent_setcb(bev, respond_to_number, NULL, eventcb,
(void*)"server");
(void*)(REGRESS_OPENSSL_SERVER));
bufferevent_enable(bev, EV_READ|EV_WRITE);
@ -435,7 +537,7 @@ regress_bufferevent_openssl_connect(void *arg)
tt_assert(bev);
bufferevent_setcb(bev, respond_to_number, NULL, eventcb,
(void*)"client");
(void*)(REGRESS_OPENSSL_CLIENT));
tt_assert(getsockname(evconnlistener_get_fd(listener),
(struct sockaddr*)&ss, &slen) == 0);
@ -453,22 +555,69 @@ end:
}
struct testcase_t ssl_testcases[] = {
{ "bufferevent_socketpair", regress_bufferevent_openssl, TT_ISOLATED,
&basic_setup, (void*)"socketpair" },
#define T(a) ((void *)(a))
{ "bufferevent_socketpair", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup, T(REGRESS_OPENSSL_SOCKETPAIR) },
{ "bufferevent_filter", regress_bufferevent_openssl,
TT_ISOLATED,
&basic_setup, (void*)"filter" },
TT_ISOLATED, &basic_setup, T(REGRESS_OPENSSL_FILTER) },
{ "bufferevent_renegotiate_socketpair", regress_bufferevent_openssl,
TT_ISOLATED,
&basic_setup, (void*)"socketpair renegotiate" },
TT_ISOLATED, &basic_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_RENEGOTIATE) },
{ "bufferevent_renegotiate_filter", regress_bufferevent_openssl,
TT_ISOLATED,
&basic_setup, (void*)"filter renegotiate" },
TT_ISOLATED, &basic_setup,
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_RENEGOTIATE) },
{ "bufferevent_socketpair_startopen", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup, (void*)"socketpair open" },
TT_ISOLATED, &basic_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_OPEN) },
{ "bufferevent_filter_startopen", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup, (void*)"filter open" },
TT_ISOLATED, &basic_setup,
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_OPEN) },
{ "bufferevent_socketpair_dirty_shutdown", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
{ "bufferevent_filter_dirty_shutdown", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
{ "bufferevent_renegotiate_socketpair_dirty_shutdown",
regress_bufferevent_openssl,
TT_ISOLATED,
&basic_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_RENEGOTIATE | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
{ "bufferevent_renegotiate_filter_dirty_shutdown",
regress_bufferevent_openssl,
TT_ISOLATED,
&basic_setup,
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_RENEGOTIATE | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
{ "bufferevent_socketpair_startopen_dirty_shutdown",
regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_OPEN | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
{ "bufferevent_filter_startopen_dirty_shutdown",
regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_OPEN | REGRESS_OPENSSL_DIRTY_SHUTDOWN) },
{ "bufferevent_socketpair_fd", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_FD) },
{ "bufferevent_socketpair_freed", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_FREED) },
{ "bufferevent_socketpair_freed_fd", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) },
{ "bufferevent_filter_freed_fd", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
T(REGRESS_OPENSSL_FILTER | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) },
{ "bufferevent_socketpair_timeout", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_TIMEOUT) },
{ "bufferevent_socketpair_timeout_freed_fd", regress_bufferevent_openssl,
TT_ISOLATED, &basic_setup,
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_TIMEOUT | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) },
#undef T
{ "bufferevent_connect", regress_bufferevent_openssl_connect,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },