diff options
Diffstat (limited to 'test/basic.c')
-rw-r--r-- | test/basic.c | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/test/basic.c b/test/basic.c new file mode 100644 index 0000000..15f5c8a --- /dev/null +++ b/test/basic.c @@ -0,0 +1,228 @@ +/* + Tests for high-level HTTP interface (ne_basic.h) + Copyright (C) 2002-2003, Joe Orton <joe@manyfish.co.uk> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "config.h" + +#include <sys/types.h> + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include <fcntl.h> + +#include "ne_basic.h" + +#include "tests.h" +#include "child.h" +#include "utils.h" + +static int content_type(void) +{ + int n; + static const struct { + const char *value, *type, *subtype, *charset; + } ctypes[] = { + { "foo/bar", "foo", "bar", NULL }, + { "foo/bar ", "foo", "bar", NULL }, + { "application/xml", "application", "xml", NULL }, + /* text/ subtypes default to charset ISO-8859-1. */ + { "text/lemon", "text", "lemon", "ISO-8859-1" }, +#undef TXU +#define TXU "text", "xml", "utf-8" + /* 2616 doesn't *say* that charset can be quoted, but bets are + * that some servers do it anyway. */ + { "text/xml; charset=utf-8", TXU }, + { "text/xml; charset=utf-8; foo=bar", TXU }, + { "text/xml;charset=utf-8", TXU }, + { "text/xml ;charset=utf-8", TXU }, + { "text/xml;charset=utf-8;foo=bar", TXU }, + { "text/xml; foo=bar; charset=utf-8", TXU }, + { "text/xml; foo=bar; charset=utf-8; bar=foo", TXU }, + { "text/xml; charset=\"utf-8\"", TXU }, + { "text/xml; charset='utf-8'", TXU }, + { "text/xml; foo=bar; charset=\"utf-8\"; bar=foo", TXU }, +#undef TXU + /* badly quoted charset should come out as NULL */ + { "foo/lemon; charset=\"utf-8", "foo", "lemon", NULL }, + { NULL } + }; + + for (n = 0; ctypes[n].value != NULL; n++) { + ne_content_type ct = {0}; + + ne_content_type_handler(&ct, ctypes[n].value); + + ONV(strcmp(ct.type, ctypes[n].type), + ("for `%s': type was `%s'", ctypes[n].value, ct.type)); + + ONV(strcmp(ct.subtype, ctypes[n].subtype), + ("for `%s': subtype was `%s'", ctypes[n].value, ct.subtype)); + + ONV(ctypes[n].charset && ct.charset == NULL, + ("for `%s': charset unset", ctypes[n].value)); + + ONV(ctypes[n].charset == NULL && ct.charset != NULL, + ("for `%s': unexpected charset `%s'", ctypes[n].value, + ct.charset)); + + ONV(ctypes[n].charset && ct.charset && + strcmp(ctypes[n].charset, ct.charset), + ("for `%s': charset was `%s'", ctypes[n].value, ct.charset)); + + NE_FREE(ct.value); + } + + return OK; +} + +/* Do ranged GET for range 'start' to 'end'; with 'resp' as response. + * If 'fail' is non-NULL, expect ne_get_range to fail, and fail the + * test with given message if it doesn't. */ +static int do_range(off_t start, off_t end, const char *fail, + char *resp) +{ + ne_session *sess; + ne_content_range range = {0}; + int fd, ret; + + CALL(make_session(&sess, single_serve_string, resp)); + + range.start = start; + range.end = end; + + fd = open("/dev/null", O_WRONLY); + + ret = ne_get_range(sess, "/foo", &range, fd); + + close(fd); + CALL(await_server()); + + if (fail) { +#if 0 + t_warning("error was %s", ne_get_error(sess)); +#endif + ONN(fail, ret == NE_OK); + } else { + ONREQ(ret); + } + + ne_session_destroy(sess); + return OK; +} + +static int get_range(void) +{ + return do_range(1, 10, NULL, + "HTTP/1.1 206 Widgets\r\n" "Connection: close\r\n" + "Content-Range: bytes 1-10\r\n" + "Content-Length: 10\r\n\r\nabcdefghij"); +} + +static int fail_range_length(void) +{ + return do_range(1, 10, "range response length mismatch should fail", + "HTTP/1.1 206 Widgets\r\n" "Connection: close\r\n" + "Content-Range: bytes 1-2\r\n" + "Content-Length: 2\r\n\r\nab"); +} + +static int fail_range_units(void) +{ + return do_range(1, 2, "range response units check should fail", + "HTTP/1.1 206 Widgets\r\n" "Connection: close\r\n" + "Content-Range: fish 1-2\r\n" + "Content-Length: 2\r\n\r\nab"); +} + +static int fail_range_notrange(void) +{ + return do_range(1, 2, "non-ranged response should fail", + "HTTP/1.1 200 Widgets\r\n" "Connection: close\r\n" + "Content-Range: bytes 1-2\r\n" + "Content-Length: 2\r\n\r\nab"); +} + +static int fail_range_unsatify(void) +{ + return do_range(1, 2, "unsatisfiable range should fail", + "HTTP/1.1 416 No Go\r\n" "Connection: close\r\n" + "Content-Length: 2\r\n\r\nab"); +} + +static int dav_capabilities(void) +{ + static const struct { + const char *hdrs; + unsigned int class1, class2, exec; + } caps[] = { + { "DAV: 1,2\r\n", 1, 1, 0 }, + { "DAV: 1 2\r\n", 0, 0, 0 }, + /* these aren't strictly legal DAV: headers: */ + { "DAV: 2,1\r\n", 1, 1, 0 }, + { "DAV: 1, 2 \r\n", 1, 1, 0 }, + { "DAV: 1\r\nDAV:2\r\n", 1, 1, 0 }, + { NULL, 0, 0, 0 } + }; + char resp[BUFSIZ]; + int n; + + for (n = 0; caps[n].hdrs != NULL; n++) { + ne_server_capabilities c = {0}; + ne_session *sess; + + ne_snprintf(resp, BUFSIZ, "HTTP/1.0 200 OK\r\n" + "Connection: close\r\n" + "%s" "\r\n", caps[n].hdrs); + + CALL(make_session(&sess, single_serve_string, resp)); + + ONREQ(ne_options(sess, "/foo", &c)); + + ONV(c.dav_class1 != caps[n].class1, + ("class1 was %d not %d", c.dav_class1, caps[n].class1)); + ONV(c.dav_class2 != caps[n].class2, + ("class2 was %d not %d", c.dav_class2, caps[n].class2)); + ONV(c.dav_executable != caps[n].exec, + ("class2 was %d not %d", c.dav_executable, caps[n].exec)); + + CALL(await_server()); + + ne_session_destroy(sess); + } + + return OK; +} + +ne_test tests[] = { + T(lookup_localhost), + T(content_type), + T(get_range), + T(fail_range_length), + T(fail_range_units), + T(fail_range_notrange), + T(fail_range_unsatify), + T(dav_capabilities), + T(NULL) +}; + |