/*! * test_rest.c * * Copyright (c) 2015-2020, NADAL Jean-Baptiste. All rights reserved. * * This library 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 library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA * * @Author: NADAL Jean-Baptiste * @Date: 08/01/2020 * */ /*--------------------------------------------------------------------------*/ #define ksuccess_get_body "{\"status\":\"ok\"}" #define ksuccess_delete_body "{\"status\":\"delete\"}" #define ksuccess_put_body "{\"status\":\"put\"}" #define ksuccess_post_body "{\"status\":\"post\"}" #define kerror_body "{\"status\":\"error\"}" #define ksuccess_put_param1 "{\"id\":\"1\"}" #define ksuccess_put_param2 "{\"id\":\"1977\"}" #define kserver_port "7777" #define kapi_test_get "/api/v1/test_get" #define kapi_test_put_id1 "/api/v1/test_put/:id" #define kapi_test_put_id1_body "/api/v1/test_put/1" #define kapi_test_put_id2 "/api/v1/test_put/:id/action" #define kapi_test_put_id2_body "/api/v1/test_put/1977/action" #define kpost_method "POST" #define kget_method "GET" #define kput_method "PUT" #define kdelete_method "DELETE" /*--------------------------------------------------------------------------*/ int my_error_handler(restd_resp_t *response, void *arg) { restd_http_response(response, 200, "application/json", kerror_body); return RESTD_OK; } /*--------------------------------------------------------------------------*/ int my_success_http_handler(restd_resp_t *response, void *arg) { restd_http_response(response, 200, "application/json", ksuccess_get_body); return RESTD_OK; } /*--------------------------------------------------------------------------*/ int my_success_rest_get_handler(restd_resp_t *response, void *arg) { restd_http_response(response, 200, "application/json", ksuccess_get_body); return RESTD_OK; } /*--------------------------------------------------------------------------*/ int my_success_rest_delete_handler(restd_resp_t *response, void *arg) { restd_http_response(response, 200, "application/json", ksuccess_delete_body); return RESTD_OK; } /*--------------------------------------------------------------------------*/ int my_success_rest_put_handler(restd_resp_t *response, void *arg) { char *body; body = restd_http_get_body(response); restd_http_response(response, 200, "application/json", body); free(body); return RESTD_OK; } /*--------------------------------------------------------------------------*/ int my_success_rest_post_handler(restd_resp_t *response, void *arg) { char *body; body = restd_http_get_body(response); restd_http_response(response, 200, "application/json", body); free(body); return RESTD_OK; } /*--------------------------------------------------------------------------*/ size_t write_callback(void *ptr, size_t size, size_t nmemb, void *stream) { size_t body_size = 0; size_t curent_size = size * nmemb; char *body = *((char **)stream); char *new_body; if (body != 0) { body_size = strlen(body); } new_body = (char *)realloc(body, curent_size + body_size + 1); if (new_body == NULL) { free(body); return 0; } memcpy(new_body + body_size, ptr, curent_size); new_body[curent_size + body_size] = 0; *((char **)stream) = new_body; return curent_size; } /*--------------------------------------------------------------------------*/ int exec_request(const char *request, const char *path, int expected_code, const char *body, const char *expected_body) { int ret = 0; CURL *curl_handle; CURLcode res; char *resp_body = NULL; long http_result_code; /* init libcurl */ curl_global_init(CURL_GLOBAL_ALL); /* init the curl session */ curl_handle = curl_easy_init(); /* specify URL and method */ curl_easy_setopt(curl_handle, CURLOPT_URL, path); if (strcmp(request, kget_method) == 0) { curl_easy_setopt(curl_handle, CURLOPT_HTTPGET, 1); } else if (strcmp(request, kdelete_method) == 0) { curl_easy_setopt(curl_handle, CURLOPT_HTTPGET, 0); curl_easy_setopt(curl_handle, CURLOPT_CUSTOMREQUEST, kdelete_method); } else if (strcmp(request, kput_method) == 0) { curl_easy_setopt(curl_handle, CURLOPT_HTTPGET, 0); curl_easy_setopt(curl_handle, CURLOPT_CUSTOMREQUEST, kput_method); curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, strlen(body)); curl_easy_setopt(curl_handle, CURLOPT_COPYPOSTFIELDS, body); } else if (strcmp(request, kpost_method) == 0) { curl_easy_setopt(curl_handle, CURLOPT_POST, 0); curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, strlen(body)); curl_easy_setopt(curl_handle, CURLOPT_COPYPOSTFIELDS, body); } curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 2); // Debug Only //curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1); /* send all data to this function */ curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_callback); curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &resp_body); curl_easy_setopt(curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); /* get it! */ res = curl_easy_perform(curl_handle); if (res != CURLE_OK) { printf("Error: %d\n", res); } ASSERT_EQUAL_INT(res, CURLE_OK); curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &http_result_code); ASSERT_EQUAL_INT(http_result_code, expected_code); if (resp_body == NULL) { res = 1; } else { res = strcmp(expected_body, resp_body); } // printf ("body: %s != expected_body: %s\n", resp_body, expected_body); if (res != 0) { ret = 2; goto exit; } ASSERT_EQUAL_INT(res, 0); exit: free(resp_body); /* cleanup curl stuff */ curl_easy_cleanup(curl_handle); /* we're done with libcurl, so clean it up */ curl_global_cleanup(); return ret; } /*--------------------------------------------------------------------------*/ bool found_route(restd_server_t *server, enum evhttp_cmd_type method, const char *path) { qlist_t *hooks = server->hooks; qlist_obj_t obj; bzero((void *)&obj, sizeof(qlist_obj_t)); while (hooks->getnext(hooks, &obj, false) == true) { restd_hook_t *hook = (restd_hook_t *)obj.data; if (hook->method == method) { if (hook->path && path && strcmp(hook->path, path) == 0) return true; } } return false; } /*--------------------------------------------------------------------------*/ bool contain(const char *src, const char *dest, int len) { int len_src, len_dest; int i = 0; len_src = strlen(src); if (len_src < len) return false; len_dest = strlen(dest); if (len_dest < len) return false; while (i < len) { if (src[i] != dest[i]) return false; i++; } return true; } /*--------------------------------------------------------------------------*/ bool found_special_route(restd_server_t *server, enum evhttp_cmd_type method, const char *path, int *id) { qlist_t *hooks = server->hooks; qlist_obj_t obj; bzero((void *)&obj, sizeof(qlist_obj_t)); while (hooks->getnext(hooks, &obj, false) == true) { restd_hook_t *hook = (restd_hook_t *)obj.data; if (hook->method == method) { if (hook->path && path) { int i = 0; int pos = -1; while (hook->path[i]) { if (hook->path[i] == ':') pos = i; i++; } // printf("hook path: %s, path: %s\n", hook->path, path); // printf("pos: %d\n", pos); // printf("contain: %s\n", contain(hook->path, path, pos) ? "TRUE" : "FALSE"); if (pos != -1 && contain(hook->path, path, pos)) { const char *buffer = &path[pos]; // printf("buffer: <%s>\n", buffer); *id = atoi(buffer); return true; } else if (strcmp(hook->path, path) == 0) return true; } } } return false; } /*--------------------------------------------------------------------------*/ TEST("Rest - create free\t") { restd_server_t *rest_server; rest_server = restd_server_new(); ASSERT_NOT_NULL(rest_server); restd_server_set_option(rest_server, "server.port", kserver_port); restd_server_register_hook_on_path(rest_server, EVHTTP_REQ_POST, "/api/v1/test", my_error_handler, NULL); restd_server_free(rest_server); } /*--------------------------------------------------------------------------*/ TEST("Rest - create access regular route free\t") { restd_server_t *rest_server; rest_server = restd_server_new(); ASSERT_NOT_NULL(rest_server); restd_server_set_option(rest_server, "server.port", kserver_port); restd_server_register_hook_on_path(rest_server, EVHTTP_REQ_POST, "/api/v1/test", my_success_http_handler, NULL); ASSERT_TRUE(found_route(rest_server, EVHTTP_REQ_POST, "/api/v1/test")); ASSERT_FALSE(found_route(rest_server, EVHTTP_REQ_POST, "/api/v1/notfound")); restd_server_register_hook_on_path(rest_server, EVHTTP_REQ_GET, "/api/v1/test", my_success_http_handler, NULL); ASSERT_TRUE(found_route(rest_server, EVHTTP_REQ_GET, "/api/v1/test")); restd_server_register_hook_on_path(rest_server, EVHTTP_REQ_GET, "/api/v1/test", my_success_http_handler, NULL); ASSERT_TRUE(found_route(rest_server, EVHTTP_REQ_GET, "/api/v1/test")); restd_server_register_hook_on_path(rest_server, EVHTTP_REQ_PUT, "/api/v1/test", my_success_http_handler, NULL); ASSERT_TRUE(found_route(rest_server, EVHTTP_REQ_PUT, "/api/v1/test")); restd_server_register_hook_on_path(rest_server, EVHTTP_REQ_DELETE, "/api/v1/test", my_success_http_handler, NULL); ASSERT_TRUE(found_route(rest_server, EVHTTP_REQ_DELETE, "/api/v1/test")); restd_server_free(rest_server); } /*--------------------------------------------------------------------------*/ TEST("Rest - create access route with param free\t") { restd_server_t *rest_server; int id = 0; rest_server = restd_server_new(); ASSERT_NOT_NULL(rest_server); restd_server_register_hook_on_path(rest_server, EVHTTP_REQ_GET, "/api/v1/klong/:id", my_success_http_handler, NULL); restd_server_register_hook_on_path(rest_server, EVHTTP_REQ_GET, "/api/v1/donkey", my_success_http_handler, NULL); restd_server_register_hook_on_path(rest_server, EVHTTP_REQ_GET, "/api/v1/test/:id", my_success_http_handler, NULL); ASSERT_FALSE(found_special_route(rest_server, EVHTTP_REQ_GET, "/api/v1/notfound/77", &id)); ASSERT_TRUE(found_special_route(rest_server, EVHTTP_REQ_GET, "/api/v1/test/77", &id)); ASSERT_EQUAL_INT(id, 77); restd_server_free(rest_server); } /*--------------------------------------------------------------------------*/ TEST("Rest - create start free\t") { restd_server_t *rest_server; int ret; rest_server = restd_server_new(); ASSERT_NOT_NULL(rest_server); restd_server_set_option(rest_server, "server.port", kserver_port); restd_server_set_option(rest_server, "server.thread", "1"); restd_server_register_hook_on_path(rest_server, EVHTTP_REQ_GET, "/api/v1/test/:id", my_success_http_handler, NULL); ret = restd_server_start(rest_server); ASSERT_EQUAL_INT(ret, 0); restd_server_free(rest_server); } /*--------------------------------------------------------------------------*/ TEST("Rest - create start access http hook free\t") { int ret; restd_server_t *rest_server; rest_server = restd_server_new(); ASSERT_NOT_NULL(rest_server); restd_server_set_option(rest_server, "server.port", kserver_port); restd_server_set_option(rest_server, "server.thread", "1"); restd_server_register_hook_on_path(rest_server, EVHTTP_REQ_GET, kapi_test_get, my_success_http_handler, NULL); ret = restd_server_start(rest_server); ASSERT_EQUAL_INT(ret, 0); ret = exec_request(kget_method, "http://localhost:" kserver_port kapi_test_get, 200, ksuccess_get_body, ksuccess_get_body); ASSERT_EQUAL_INT(ret, 0); restd_server_free(rest_server); } /*--------------------------------------------------------------------------*/ TEST("Rest - create start access to all rest hook free\t") { int ret; restd_server_t *rest_server; rest_server = restd_server_new(); ASSERT_NOT_NULL(rest_server); //restd_log_level(RESTD_LOG_DEBUG); restd_server_set_option(rest_server, "server.port", kserver_port); restd_server_set_option(rest_server, "server.thread", "1"); //restd_server_register_call_hooks_handler(rest_server, restd_rest_handler); restd_server_register_hook_on_path(rest_server, EVHTTP_REQ_GET, kapi_test_get, my_success_rest_get_handler, NULL); restd_server_register_hook_on_path(rest_server, EVHTTP_REQ_PUT, kapi_test_get, my_success_rest_put_handler, NULL); restd_server_register_hook_on_path(rest_server, EVHTTP_REQ_DELETE, kapi_test_get, my_success_rest_delete_handler, NULL); restd_server_register_hook_on_path(rest_server, EVHTTP_REQ_POST, kapi_test_get, my_success_rest_post_handler, NULL); ret = restd_server_start(rest_server); ASSERT_EQUAL_INT(ret, 0); sleep(1); //PRINTLN("\n - GET"); ret = exec_request(kget_method, "http://localhost:" kserver_port kapi_test_get, 200, ksuccess_get_body, ksuccess_get_body); ASSERT_EQUAL_INT(ret, 0); //PRINTLN("\n - DELETE"); ret = exec_request(kdelete_method, "http://localhost:" kserver_port kapi_test_get, 200, ksuccess_delete_body, ksuccess_delete_body); ASSERT_EQUAL_INT(ret, 0); //PRINTLN("\n - PUT"); ret = exec_request(kput_method, "http://localhost:" kserver_port kapi_test_get, 200, ksuccess_put_body, ksuccess_put_body); ASSERT_EQUAL_INT(ret, 0); //PRINTLN("\n - POST"); ret = exec_request(kpost_method, "http://localhost:" kserver_port kapi_test_get, 200, ksuccess_post_body, ksuccess_post_body); ASSERT_EQUAL_INT(ret, 0); restd_server_free(rest_server); } /*--------------------------------------------------------------------------*/ #if 0 TEST("Rest - create start access to rest hook with params free\t") { int ret; restd_server_t *rest_server; rest_server = restd_server_new(); ASSERT_NOT_NULL(rest_server); //restd_log_level(RESTD_LOG_DEBUG); restd_server_set_option(rest_server, "server.port", kserver_port); restd_server_set_option(rest_server, "server.thread", "1"); //restd_server_register_call_hooks_handler(rest_server, restd_rest_handler); restd_server_register_hook_on_path(rest_server, EVHTTP_REQ_GET, kapi_test_get, my_success_rest_get_handler, NULL); restd_server_register_hook_on_path(rest_server, EVHTTP_REQ_PUT, kapi_test_put_id1, my_success_rest_put_handler, NULL); restd_server_register_hook_on_path(rest_server, EVHTTP_REQ_PUT, kapi_test_put_id2, my_success_rest_put_handler, NULL); ret = restd_server_start(rest_server); ASSERT_EQUAL_INT(ret, 0); sleep(1); PRINTLN("\n - Param1"); ret = exec_request(kput_method, "http://localhost:" kserver_port kapi_test_put_id1_body, 200, "", ksuccess_put_param1); ASSERT_EQUAL_INT(ret, 0); restd_server_free(rest_server); } #endif