#include #include #include #include #include #define UNUSED(a) ((void) (a)) static void die( char *test, char *fn, fhp_err_t err ) { char buf[1024]; if (fhp_strerror(err, buf, sizeof(buf)) == FHP_OK) { fprintf(stderr, "ERROR: %s(): %s(): %s\n", test, fn, buf); } else { fprintf(stderr, "ERROR: die(): fhp_strerror() failed\n"); } /* exit app */ exit(EXIT_FAILURE); } /**************/ /* basic test */ /**************/ static const char * basic_str = "GET / HTTP/1.1\r\n" "Host: pablotron.org\r\n" "Content-Type: application/x-www-form-urlencoded\r\n" "Connection: close\r\n" "Content-Length: 15\r\n" "\r\n" "hello test test"; static bool basic_cb( fhp_ctx_t *ctx, fhp_token_t token, uint8_t * const buf, size_t len ) { fhp_err_t err; UNUSED(ctx); UNUSED(buf); // get token name char token_buf[64]; if ((err = fhp_strtoken(token, token_buf, sizeof(token_buf))) != FHP_OK) return false; // debug fprintf(stderr, "test_basic_cb(): token = %s, len = %lu\n", token_buf, len); // return success return true; } static void test_basic(void) { fhp_err_t err; fhp_ctx_t ctx; // init parser if ((err = fhp_ctx_init(&ctx, NULL, basic_cb, NULL)) != FHP_OK) { die("test_basic", "fhp_ctx_init", err); } // parse data size_t len = strlen(basic_str); if ((err = fhp_ctx_push(&ctx, (uint8_t*) basic_str, len)) != FHP_OK) { die("test_basic", "fhp_ctx_push", err); } } /****************/ /* percent test */ /****************/ typedef struct { uint8_t buf[1024]; size_t buf_len; } percent_data; static const char * percent_str = "GET /foo%20bar HTTP/1.1\r\n" "Host: pablotron.org\r\n" "Connection: close\r\n" "\r\n"; static bool percent_cb( fhp_ctx_t *ctx, fhp_token_t token, uint8_t * const buf, size_t len ) { percent_data *data = fhp_ctx_get_user_data(ctx); switch (token) { case FHP_TOKEN_URL_START: // clear buffer data->buf_len = 0; break; case FHP_TOKEN_URL_FRAGMENT: // buffer overflow, do not use in real code!!! memcpy(data->buf + data->buf_len, buf, len); data->buf_len += len; break; case FHP_TOKEN_URL_END: // terminate and print buffer data->buf[data->buf_len] = '\0'; fprintf(stderr, "decoded URL: \"%s\"\n", data->buf); break; default: // do nothing NULL; } // return success return true; } static void test_percent(void) { fhp_err_t err; fhp_ctx_t ctx; percent_data data; // init parser if ((err = fhp_ctx_init(&ctx, NULL, percent_cb, &data)) != FHP_OK) { die("test_percent", "fhp_ctx_init", err); } // parse data size_t len = strlen(percent_str); if ((err = fhp_ctx_push(&ctx, (uint8_t*) percent_str, len)) != FHP_OK) { die("test_percent", "fhp_ctx_push", err); } } /******************/ /* te parser test */ /******************/ static char * te_parser_tests[] = { " ", "gzip", "deflate", "gzip,deflate,chunked", "gzip, deflate, chunked", "deflate , gzip , chunked ", " deflate , gzip , chunked ", NULL }; static void test_te_parser(void) { for (size_t i = 0; te_parser_tests[i]; i++) { fhp_err_t err; // get test string char * const s = te_parser_tests[i]; fprintf(stderr, "te testing: \"%s\"\n", s); // init parser fhp_te_parser_t p; fhp_te_parser_init(&p); // parse data if ((err = fhp_te_parser_push(&p, (uint8_t*) s, strlen(s))) != FHP_OK) { die("test_te_parser", "fhp_te_parser_push", err); } // finish parsing size_t num_tes; if ((err = fhp_te_parser_done(&p, &num_tes)) != FHP_OK) { die("test_te_parser", "fhp_te_parser_push", err); } fprintf(stderr, "te test: \"%s\", num_tes = %lu\n", s, num_tes); } } /******************/ /* cl parser test */ /******************/ static char * cl_parser_tests[] = { " 12345 ", "100", "00120", "123123123123", "18446744073709551615", // UINT64_MAX // "18446744073709551616", // UINT64_MAX + 1 // "184--46744073709551615", // test embedded garbage // "18446744073709551615 abc ", // test trailing garbage NULL }; static void test_cl_parser(void) { for (size_t i = 0; cl_parser_tests[i]; i++) { fhp_err_t err; // get test string char * const s = cl_parser_tests[i]; fprintf(stderr, "cl testing: \"%s\"\n", s); // init parser fhp_cl_parser_t p; fhp_cl_parser_init(&p); // parse data if ((err = fhp_cl_parser_push(&p, (uint8_t*) s, strlen(s))) != FHP_OK) { die("test_cl_parser", "fhp_cl_parser_push", err); } // finish parsing uint64_t val; if ((err = fhp_cl_parser_done(&p, &val)) != FHP_OK) { die("test_cl_parser", "fhp_cl_parser_push", err); } fprintf(stderr, "cl test: \"%s\", val = %lu\n", s, val); } } int main(int argc, char *argv[]) { UNUSED(argc); UNUSED(argv); test_basic(); test_percent(); test_te_parser(); test_cl_parser(); return EXIT_SUCCESS; }