You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
189 lines
5.2 KiB
189 lines
5.2 KiB
/*****************************************************************************
|
|
* h2output_test.c: HTTP/2 send queue test
|
|
*****************************************************************************
|
|
* Copyright (C) 2015 Rémi Denis-Courmont
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation; either version 2.1 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
|
*****************************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#undef NDEBUG
|
|
|
|
#include <assert.h>
|
|
#include <stdarg.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <vlc_common.h>
|
|
#include <vlc_threads.h>
|
|
#include <vlc_tls.h>
|
|
#include "h2frame.h"
|
|
#include "h2output.h"
|
|
|
|
#undef vlc_tick_sleep
|
|
|
|
const char vlc_module_name[] = "test_h2output";
|
|
|
|
static unsigned char counter = 0;
|
|
static bool send_failure = false;
|
|
static bool expect_hello = true;
|
|
static vlc_sem_t rx;
|
|
|
|
static int fd_callback(vlc_tls_t *tls, short *restrict events)
|
|
{
|
|
(void) tls;
|
|
(void) events;
|
|
return fileno(stderr); /* should be writable (at least most of the time) */
|
|
}
|
|
|
|
static ssize_t send_callback(vlc_tls_t *tls, const struct iovec *iov,
|
|
unsigned count)
|
|
{
|
|
assert(count == 1);
|
|
assert(tls->ops->writev == send_callback);
|
|
|
|
const uint8_t *p = iov->iov_base;
|
|
size_t len = iov->iov_len;
|
|
|
|
if (expect_hello)
|
|
{
|
|
assert(len >= 24);
|
|
assert(!memcmp(p, "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n", 24));
|
|
|
|
expect_hello = false;
|
|
vlc_sem_post(&rx);
|
|
|
|
if (len == 24)
|
|
return send_failure ? -1 : (ssize_t)len;
|
|
|
|
p += 24;
|
|
len -= 24;
|
|
}
|
|
|
|
assert(len == 9 + 1);
|
|
assert(p[9] == counter);
|
|
|
|
if (send_failure)
|
|
errno = EIO;
|
|
else
|
|
counter++;
|
|
vlc_sem_post(&rx);
|
|
|
|
return send_failure ? -1 : (ssize_t)len;
|
|
}
|
|
|
|
static const struct vlc_tls_operations fake_ops =
|
|
{
|
|
.get_fd = fd_callback,
|
|
.writev = send_callback,
|
|
};
|
|
|
|
static vlc_tls_t fake_tls =
|
|
{
|
|
.ops = &fake_ops,
|
|
};
|
|
|
|
static struct vlc_h2_frame *frame(unsigned char c)
|
|
{
|
|
struct vlc_h2_frame *f = vlc_h2_frame_data(1, &c, 1, false);
|
|
assert(f != NULL);
|
|
return f;
|
|
}
|
|
|
|
static struct vlc_h2_frame *frame_list(struct vlc_h2_frame *first, ...)
|
|
{
|
|
struct vlc_h2_frame **pp = &first;
|
|
va_list ap;
|
|
|
|
va_start(ap, first);
|
|
for (struct vlc_h2_frame *f = first;
|
|
f != NULL;
|
|
f = va_arg(ap, struct vlc_h2_frame *))
|
|
{
|
|
*pp = f;
|
|
pp = &f->next;
|
|
}
|
|
va_end(ap);
|
|
return first;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
struct vlc_h2_output *out;
|
|
|
|
/* Dummy */
|
|
out = vlc_h2_output_create(&fake_tls, false);
|
|
assert(out != NULL);
|
|
vlc_h2_output_destroy(out);
|
|
|
|
vlc_sem_init(&rx, 0);
|
|
out = vlc_h2_output_create(&fake_tls, expect_hello = true);
|
|
assert(out != NULL);
|
|
vlc_h2_output_destroy(out);
|
|
|
|
/* Success */
|
|
vlc_sem_init(&rx, 0);
|
|
out = vlc_h2_output_create(&fake_tls, false);
|
|
assert(out != NULL);
|
|
assert(vlc_h2_output_send_prio(out, NULL) == -1);
|
|
assert(vlc_h2_output_send_prio(out, frame(0)) == 0);
|
|
assert(vlc_h2_output_send_prio(out, frame(1)) == 0);
|
|
assert(vlc_h2_output_send(out, NULL) == -1);
|
|
assert(vlc_h2_output_send(out, frame(2)) == 0);
|
|
assert(vlc_h2_output_send(out, frame(3)) == 0);
|
|
assert(vlc_h2_output_send(out, frame_list(frame(4), frame(5),
|
|
frame(6), NULL)) == 0);
|
|
assert(vlc_h2_output_send(out, frame(7)) == 0);
|
|
for (unsigned i = 0; i < 8; i++)
|
|
vlc_sem_wait(&rx);
|
|
|
|
assert(vlc_h2_output_send_prio(out, frame(8)) == 0);
|
|
assert(vlc_h2_output_send(out, frame(9)) == 0);
|
|
|
|
vlc_h2_output_destroy(out);
|
|
|
|
/* Failure */
|
|
send_failure = true;
|
|
|
|
vlc_sem_init(&rx, 0);
|
|
counter = 10;
|
|
out = vlc_h2_output_create(&fake_tls, false);
|
|
assert(out != NULL);
|
|
|
|
assert(vlc_h2_output_send(out, frame(10)) == 0);
|
|
for (unsigned char i = 11; vlc_h2_output_send(out, frame(i)) == 0; i++)
|
|
vlc_tick_sleep(VLC_TICK_FROM_MS(100)); /* eventually, it should start failing */
|
|
assert(vlc_h2_output_send(out, frame(0)) == -1);
|
|
assert(vlc_h2_output_send_prio(out, frame(0)) == -1);
|
|
vlc_h2_output_destroy(out);
|
|
|
|
/* Failure during hello */
|
|
vlc_sem_init(&rx, 0);
|
|
counter = 0;
|
|
out = vlc_h2_output_create(&fake_tls, expect_hello = true);
|
|
assert(out != NULL);
|
|
vlc_sem_wait(&rx);
|
|
|
|
for (unsigned char i = 1; vlc_h2_output_send_prio(out, frame(i)) == 0; i++)
|
|
vlc_tick_sleep(VLC_TICK_FROM_MS(100));
|
|
assert(vlc_h2_output_send(out, frame(0)) == -1);
|
|
assert(vlc_h2_output_send_prio(out, frame(0)) == -1);
|
|
vlc_h2_output_destroy(out);
|
|
|
|
return 0;
|
|
}
|
|
|