1 /*****************************************************************************
2 * chunked_test.c: HTTP 1.1 chunked encoding decoder test
3 *****************************************************************************
4 * Copyright (C) 2015 Rémi Denis-Courmont
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #undef NDEBUG
26
27 #include <assert.h>
28 #include <stddef.h>
29 #include <string.h>
30
31 #include <vlc_common.h>
32 #include <vlc_tls.h>
33 #include <vlc_block.h>
34 #include "conn.h"
35 #include "message.h"
36
37 /* I/O callbacks */
38 static const char *stream_content;
39 static size_t stream_length;
40 static bool stream_bad;
41
fd_callback(struct vlc_tls * tls)42 static int fd_callback(struct vlc_tls *tls)
43 {
44 (void) tls;
45 return -1;
46 }
47
recv_callback(struct vlc_tls * tls,struct iovec * iov,unsigned count)48 static ssize_t recv_callback(struct vlc_tls *tls, struct iovec *iov,
49 unsigned count)
50 {
51 size_t rcvd = 0;
52
53 while (count > 0)
54 {
55 size_t copy = iov->iov_len;
56 if (copy > stream_length)
57 copy = stream_length;
58
59 if (copy > 0)
60 {
61 memcpy(iov->iov_base, stream_content, copy);
62 stream_content += copy;
63 stream_length -= copy;
64 rcvd += copy;
65 }
66
67 iov++;
68 count--;
69 }
70 (void) tls;
71 return rcvd;
72 }
73
close_callback(struct vlc_tls * tls)74 static void close_callback(struct vlc_tls *tls)
75 {
76 (void) tls;
77 }
78
79 static struct vlc_tls chunked_tls =
80 {
81 .get_fd = fd_callback,
82 .readv = recv_callback,
83 .close = close_callback,
84 };
85
stream_close_callback(struct vlc_http_stream * stream,bool bad)86 static void stream_close_callback(struct vlc_http_stream *stream, bool bad)
87 {
88 (void) stream;
89 assert(bad == stream_bad);
90 }
91
92 static const struct vlc_http_stream_cbs chunked_stream_cbs =
93 {
94 .close = stream_close_callback,
95 };
96
97 static struct vlc_http_stream chunked_stream =
98 {
99 &chunked_stream_cbs,
100 };
101
102 /* Test cases */
103
test_good(void)104 static void test_good(void)
105 {
106 struct vlc_http_stream *s;
107 block_t *b;
108
109 /* Simple good payload */
110 stream_content =
111 "A\r\n" "1234567890\r\n"
112 "1A; ext-foo=1\r\n" "abcdefghijklmnopqrstuvwxyz\r\n"
113 "0\r\n" "\r\n";
114 stream_length = strlen(stream_content);
115 stream_bad = false;
116
117 s = vlc_chunked_open(&chunked_stream, &chunked_tls);
118 assert(s != NULL);
119 assert(vlc_http_stream_read_headers(s) == NULL);
120
121 b = vlc_http_stream_read(s);
122 assert(b != NULL);
123 assert(b->i_buffer == 10);
124 assert(!memcmp(b->p_buffer, "1234567890", 10));
125 block_Release(b);
126
127 b = vlc_http_stream_read(s);
128 assert(b != NULL);
129 assert(b->i_buffer == 26);
130 assert(!memcmp(b->p_buffer, "abcdefghijklmnopqrstuvwxyz", 26));
131 block_Release(b);
132
133 b = vlc_http_stream_read(s);
134 assert(b == NULL);
135 b = vlc_http_stream_read(s);
136 assert(b == NULL);
137
138 vlc_http_stream_close(s, false);
139 }
140
test_empty(void)141 static void test_empty(void)
142 {
143 struct vlc_http_stream *s;
144 block_t *b;
145
146 stream_content = "0\r\n";
147 stream_length = 3;
148 stream_bad = true;
149
150 s = vlc_chunked_open(&chunked_stream, &chunked_tls);
151 assert(s != NULL);
152
153 b = vlc_http_stream_read(s);
154 assert(b == NULL);
155 b = vlc_http_stream_read(s);
156 assert(b == NULL);
157 vlc_http_stream_close(s, false);
158 }
159
test_bad(const char * payload)160 static void test_bad(const char *payload)
161 {
162 struct vlc_http_stream *s;
163 block_t *b;
164
165 stream_content = payload;
166 stream_length = strlen(payload);
167 stream_bad = true;
168
169 s = vlc_chunked_open(&chunked_stream, &chunked_tls);
170 assert(s != NULL);
171
172 while ((b = vlc_http_stream_read(s)) != vlc_http_error)
173 {
174 assert(b != NULL);
175 block_Release(b);
176 }
177
178 vlc_http_stream_close(s, false);
179 }
180
main(void)181 int main(void)
182 {
183 test_good();
184 test_empty();
185 test_bad("");
186 test_bad("A\r\n" "123456789");
187 test_bad("Z\r\n" "123456789");
188
189 return 0;
190 }
191