From f20218e73ecae27f9e9f9bf34e9798080de6f93d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Sun, 29 Mar 2015 01:55:10 +0100 Subject: Add more stuff And break the API. All in the name of progress! --- tests/liberty.c | 47 ++++++++++------ tests/proto.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+), 16 deletions(-) create mode 100644 tests/proto.c (limited to 'tests') diff --git a/tests/liberty.c b/tests/liberty.c index 8956ed0..349ee78 100644 --- a/tests/liberty.c +++ b/tests/liberty.c @@ -236,21 +236,6 @@ test_error (void) // --- Hash map ---------------------------------------------------------------- -static int -tolower_ascii (int c) -{ - return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c; -} - -static size_t -tolower_strxfrm (char *dest, const char *src, size_t n) -{ - size_t len = strlen (src); - while (n-- && (*dest++ = tolower_ascii (*src++))) - ; - return len; -} - static void free_counter (void *data) { @@ -280,7 +265,7 @@ test_str_map (void) // Put two reference counted objects in the map under case-insensitive keys struct str_map m; str_map_init (&m); - m.key_xfrm = tolower_strxfrm; + m.key_xfrm = tolower_ascii_strxfrm; m.free = free_counter; int *a = make_counter (); @@ -323,6 +308,34 @@ test_str_map (void) free_counter (b); } +static void +test_utf8 (void) +{ + const char valid [] = "2H₂ + O₂ ⇌ 2H₂O, R = 4.7 kΩ, ⌀ 200 mm"; + const char invalid[] = "\xf0\x90\x28\xbc"; + soft_assert ( utf8_validate (valid, sizeof valid)); + soft_assert (!utf8_validate (invalid, sizeof invalid)); +} + +static void +test_base64 (void) +{ + char data[65]; + for (size_t i = 0; i < N_ELEMENTS (data); i++) + data[i] = i; + + struct str encoded; str_init (&encoded); + struct str decoded; str_init (&decoded); + + base64_encode (data, sizeof data, &encoded); + soft_assert (base64_decode (encoded.str, false, &decoded)); + soft_assert (decoded.len == sizeof data); + soft_assert (!memcmp (decoded.str, data, sizeof data)); + + str_free (&encoded); + str_free (&decoded); +} + // --- Main -------------------------------------------------------------------- int @@ -338,6 +351,8 @@ main (int argc, char *argv[]) test_add_simple (&test, "/str", NULL, test_str); test_add_simple (&test, "/error", NULL, test_error); test_add_simple (&test, "/str-map", NULL, test_str_map); + test_add_simple (&test, "/utf-8", NULL, test_utf8); + test_add_simple (&test, "/base64", NULL, test_base64); // TODO: write tests for the rest of the library diff --git a/tests/proto.c b/tests/proto.c new file mode 100644 index 0000000..caa9cf2 --- /dev/null +++ b/tests/proto.c @@ -0,0 +1,167 @@ +/* + * tests/proto.c + * + * Copyright (c) 2015, Přemysl Janouch + * All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#define PROGRAM_NAME "test" +#define PROGRAM_VERSION "0" + +#define LIBERTY_WANT_SSL + +#define LIBERTY_WANT_PROTO_IRC +#define LIBERTY_WANT_PROTO_HTTP +#define LIBERTY_WANT_PROTO_SCGI +#define LIBERTY_WANT_PROTO_FASTCGI +#define LIBERTY_WANT_PROTO_WS + +#include "../liberty.c" + +// --- Tests ------------------------------------------------------------------- + +static void +test_http_parser (void) +{ + struct str_map parameters; + str_map_init (¶meters); + parameters.key_xfrm = tolower_ascii_strxfrm; + + char *type = NULL; + char *subtype = NULL; + soft_assert (http_parse_media_type ("TEXT/html; CHARset=\"utf\\-8\"", + &type, &subtype, ¶meters)); + soft_assert (!strcasecmp_ascii (type, "text")); + soft_assert (!strcasecmp_ascii (subtype, "html")); + soft_assert (parameters.len == 1); + soft_assert (!strcmp (str_map_find (¶meters, "charset"), "utf-8")); + str_map_free (¶meters); + + struct http_protocol *protocols; + soft_assert (http_parse_upgrade ("websocket, HTTP/2.0, , ", &protocols)); + + soft_assert (!strcmp (protocols->name, "websocket")); + soft_assert (!protocols->version); + + soft_assert (!strcmp (protocols->next->name, "HTTP")); + soft_assert (!strcmp (protocols->next->version, "2.0")); + + soft_assert (!protocols->next->next); + + LIST_FOR_EACH (struct http_protocol, iter, protocols) + http_protocol_destroy (iter); +} + +static bool +test_scgi_parser_on_headers_read (void *user_data) +{ + struct scgi_parser *parser = user_data; + soft_assert (parser->headers.len == 4); + soft_assert (!strcmp (str_map_find (&parser->headers, + "CONTENT_LENGTH"), "27")); + soft_assert (!strcmp (str_map_find (&parser->headers, + "SCGI"), "1")); + soft_assert (!strcmp (str_map_find (&parser->headers, + "REQUEST_METHOD"), "POST")); + soft_assert (!strcmp (str_map_find (&parser->headers, + "REQUEST_URI"), "/deepthought")); + return true; +} + +static bool +test_scgi_parser_on_content (void *user_data, const void *data, size_t len) +{ + (void) user_data; + soft_assert (!strncmp (data, "What is the answer to life?", len)); + return true; +} + +static void +test_scgi_parser (void) +{ + struct scgi_parser parser; + scgi_parser_init (&parser); + parser.on_headers_read = test_scgi_parser_on_headers_read; + parser.on_content = test_scgi_parser_on_content; + parser.user_data = &parser; + + // This is an example straight from the specification + const char example[] = + "70:" + "CONTENT_LENGTH" "\0" "27" "\0" + "SCGI" "\0" "1" "\0" + "REQUEST_METHOD" "\0" "POST" "\0" + "REQUEST_URI" "\0" "/deepthought" "\0" + "," + "What is the answer to life?"; + + soft_assert (scgi_parser_push (&parser, example, sizeof example, NULL)); + scgi_parser_free (&parser); +} + +static bool +test_websockets_on_frame_header (void *user_data, const struct ws_parser *self) +{ + (void) user_data; + soft_assert (self->is_fin); + soft_assert (self->is_masked); + soft_assert (self->opcode == WS_OPCODE_TEXT); + return true; +} + +static bool +test_websockets_on_frame (void *user_data, const struct ws_parser *self) +{ + (void) user_data; + soft_assert (self->input.len == self->payload_len); + soft_assert (!strncmp (self->input.str, "Hello", self->input.len)); + return true; +} + +static void +test_websockets (void) +{ + char *accept = ws_encode_response_key ("dGhlIHNhbXBsZSBub25jZQ=="); + soft_assert (!strcmp (accept, "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=")); + free (accept); + + struct ws_parser parser; + ws_parser_init (&parser); + parser.on_frame_header = test_websockets_on_frame_header; + parser.on_frame = test_websockets_on_frame; + parser.user_data = &parser; + + const char frame[] = "\x81\x85\x37\xfa\x21\x3d\x7f\x9f\x4d\x51\x58"; + soft_assert (ws_parser_push (&parser, frame, sizeof frame - 1)); + ws_parser_free (&parser); +} + +// --- Main -------------------------------------------------------------------- + +int +main (int argc, char *argv[]) +{ + struct test test; + test_init (&test, argc, argv); + + test_add_simple (&test, "/http-parser", NULL, test_http_parser); + test_add_simple (&test, "/scgi-parser", NULL, test_scgi_parser); + test_add_simple (&test, "/websockets", NULL, test_websockets); + // TODO: test FastCGI + // TODO: test IRC + + return test_run (&test); +} -- cgit v1.2.3