h2output_test.c 5.06 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
/*****************************************************************************
 * 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
14
 * GNU Lesser General Public License for more details.
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
 *
 * 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>
31
#include <errno.h>
32
#include <vlc_common.h>
33
#include <vlc_tls.h>
34 35 36 37 38 39 40 41 42 43
#include "h2frame.h"
#include "h2output.h"

#undef msleep

static unsigned char counter = 0;
static bool send_failure = false;
static bool expect_hello = true;
static vlc_sem_t rx;

44 45 46
static int fd_callback(vlc_tls_t *tls)
{
    (void) tls;
47
    return fileno(stderr); /* should be writable (at least most of the time) */
48 49
}

50 51
static ssize_t send_callback(vlc_tls_t *tls, const struct iovec *iov,
                             unsigned count)
52
{
53 54
    assert(count == 1);
    assert(tls->writev == send_callback);
55

56 57
    const uint8_t *p = iov->iov_base;
    size_t len = iov->iov_len;
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76

    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);

77 78 79 80
    if (send_failure)
        errno = EIO;
    else
        counter++;
81
    vlc_sem_post(&rx);
82

83 84 85
    return send_failure ? -1 : (ssize_t)len;
}

86 87
static vlc_tls_t fake_tls =
{
88
    .get_fd = fd_callback,
89
    .writev = send_callback,
90 91
};

92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
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 */
121
    out = vlc_h2_output_create(&fake_tls, false);
122 123 124 125
    assert(out != NULL);
    vlc_h2_output_destroy(out);

    vlc_sem_init(&rx, 0);
126
    out = vlc_h2_output_create(&fake_tls, expect_hello = true);
127 128 129 130 131 132
    assert(out != NULL);
    vlc_h2_output_destroy(out);
    vlc_sem_destroy(&rx);

    /* Success */
    vlc_sem_init(&rx, 0);
133
    out = vlc_h2_output_create(&fake_tls, false);
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
    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);
    vlc_sem_destroy(&rx);

    /* Failure */
    send_failure = true;

    vlc_sem_init(&rx, 0);
    counter = 10;
158
    out = vlc_h2_output_create(&fake_tls, false);
159 160 161 162 163 164 165 166 167 168 169 170 171
    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++)
        msleep(CLOCK_FREQ/10); /* 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);
    vlc_sem_destroy(&rx);

    /* Failure during hello */
    vlc_sem_init(&rx, 0);
    counter = 0;
172
    out = vlc_h2_output_create(&fake_tls, expect_hello = true);
173 174 175 176 177 178 179 180 181 182 183 184
    assert(out != NULL);
    vlc_sem_wait(&rx);

    for (unsigned char i = 1; vlc_h2_output_send_prio(out, frame(i)) == 0; i++)
        msleep(CLOCK_FREQ/10);
    assert(vlc_h2_output_send(out, frame(0)) == -1);
    assert(vlc_h2_output_send_prio(out, frame(0)) == -1);
    vlc_h2_output_destroy(out);
    vlc_sem_destroy(&rx);

    return 0;
}