#include "ejdb_test.h" #include #include CURL *curl; int init_suite() { curl_global_init(CURL_GLOBAL_ALL); curl = curl_easy_init(); if (!curl) { return 1; } int rc = ejdb_init(); return rc; } int clean_suite() { curl_easy_cleanup(curl); curl_global_cleanup(); return 0; } static size_t curl_write_xstr(void *contents, size_t size, size_t nmemb, void *op) { IWXSTR *xstr = op; assert(xstr); iwxstr_cat(xstr, contents, size * nmemb); return size * nmemb; } static void jbr_test1_1() { char url[64]; uint32_t port = iwu_rand_range(20000) + 20000; EJDB_OPTS opts = { .kv = { .path = "jbr_test1_1.db", .oflags = IWKV_TRUNC }, .no_wal = true, .http = { .bind = "127.0.0.1", .blocking = false, .enabled = true, .port = port } }; long code; EJDB db; iwrc rc = ejdb_open(&opts, &db); if (rc) { iwlog_ecode_error3(rc); } CU_ASSERT_EQUAL_FATAL(rc, 0); IWXSTR *xstr = iwxstr_new(); IWXSTR *hstr = iwxstr_new(); struct curl_slist *headers = curl_slist_append(0, "Content-Type: application/json"); snprintf(url, sizeof(url), "http://localhost:%" PRIu32 "/c1/1", port); // Check no element in collection CURLcode cc = curl_easy_setopt(curl, CURLOPT_URL, url); CU_ASSERT_EQUAL_FATAL(cc, 0); cc = curl_easy_perform(curl); CU_ASSERT_EQUAL_FATAL(cc, 0); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); CU_ASSERT_EQUAL_FATAL(code, 404); snprintf(url, sizeof(url), "http://localhost:%" PRIu32 "/c1", port); // Save a document using POST curl_easy_reset(curl); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST"); CU_ASSERT_EQUAL_FATAL(cc, 0); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "{\"foo\":\"bar\"}"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_xstr); curl_easy_setopt(curl, CURLOPT_WRITEDATA, xstr); cc = curl_easy_perform(curl); CU_ASSERT_EQUAL_FATAL(cc, 0); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); CU_ASSERT_EQUAL_FATAL(code, 200); CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "1"); // Now get document JSON using GET curl_easy_reset(curl); iwxstr_clear(xstr); iwxstr_clear(hstr); snprintf(url, sizeof(url), "http://localhost:%" PRIu32 "/c1/1", port); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_xstr); curl_easy_setopt(curl, CURLOPT_WRITEDATA, xstr); curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curl_write_xstr); curl_easy_setopt(curl, CURLOPT_HEADERDATA, hstr); cc = curl_easy_perform(curl); CU_ASSERT_EQUAL_FATAL(cc, 0); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); CU_ASSERT_EQUAL_FATAL(code, 200); CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\n" " \"foo\": \"bar\"\n" "}" ); CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(hstr), "content-type:application/json")); CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(hstr), "content-length:17")); CU_ASSERT_EQUAL(iwxstr_size(xstr), 17); // PUT document under specific ID curl_easy_reset(curl); iwxstr_clear(xstr); iwxstr_clear(hstr); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); CU_ASSERT_EQUAL_FATAL(cc, 0); snprintf(url, sizeof(url), "http://localhost:%" PRIu32 "/c1/33", port); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "{\"foo\":\"b\nar\"}"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_xstr); curl_easy_setopt(curl, CURLOPT_WRITEDATA, xstr); cc = curl_easy_perform(curl); CU_ASSERT_EQUAL_FATAL(cc, 0); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); CU_ASSERT_EQUAL_FATAL(code, 200); // Check the last doc curl_easy_reset(curl); iwxstr_clear(xstr); iwxstr_clear(hstr); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_xstr); curl_easy_setopt(curl, CURLOPT_WRITEDATA, xstr); curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curl_write_xstr); curl_easy_setopt(curl, CURLOPT_HEADERDATA, hstr); cc = curl_easy_perform(curl); CU_ASSERT_EQUAL_FATAL(cc, 0); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); CU_ASSERT_EQUAL_FATAL(code, 200); CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\n" " \"foo\": \"b\\nar\"\n" "}" ); CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(hstr), "content-type:application/json")); CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(hstr), "content-length:19")); CU_ASSERT_EQUAL(iwxstr_size(xstr), 19); // Perform a query curl_easy_reset(curl); iwxstr_clear(xstr); iwxstr_clear(hstr); snprintf(url, sizeof(url), "http://localhost:%" PRIu32 "/", port); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "@c1/foo"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_xstr); curl_easy_setopt(curl, CURLOPT_WRITEDATA, xstr); curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curl_write_xstr); curl_easy_setopt(curl, CURLOPT_HEADERDATA, hstr); cc = curl_easy_perform(curl); CU_ASSERT_EQUAL_FATAL(cc, 0); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); CU_ASSERT_EQUAL_FATAL(code, 200); CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(xstr), "33\t{\"foo\":\"b\\nar\"}")); CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(xstr), "1\t{\"foo\":\"bar\"}")); // Query with explain curl_easy_reset(curl); iwxstr_clear(xstr); iwxstr_clear(hstr); curl_slist_free_all(headers); headers = curl_slist_append(0, "X-Hints: explain"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "@c1/foo"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_xstr); curl_easy_setopt(curl, CURLOPT_WRITEDATA, xstr); curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curl_write_xstr); curl_easy_setopt(curl, CURLOPT_HEADERDATA, hstr); cc = curl_easy_perform(curl); CU_ASSERT_EQUAL_FATAL(cc, 0); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); CU_ASSERT_EQUAL_FATAL(code, 200); CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(xstr), "[INDEX] NO [COLLECTOR] PLAIN")); CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(xstr), "--------------------")); CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(xstr), "33\t{\"foo\":\"b\\nar\"}")); CU_ASSERT_PTR_NOT_NULL(strstr(iwxstr_ptr(xstr), "1\t{\"foo\":\"bar\"}")); // Delete resource curl_easy_reset(curl); iwxstr_clear(xstr); iwxstr_clear(hstr); snprintf(url, sizeof(url), "http://localhost:%" PRIu32 "/c1/33", port); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); cc = curl_easy_perform(curl); CU_ASSERT_EQUAL_FATAL(cc, 0); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); CU_ASSERT_EQUAL_FATAL(code, 200); // Check the resource has been deleted curl_easy_reset(curl); iwxstr_clear(xstr); iwxstr_clear(hstr); curl_easy_setopt(curl, CURLOPT_URL, url); cc = curl_easy_perform(curl); CU_ASSERT_EQUAL_FATAL(cc, 0); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); CU_ASSERT_EQUAL_FATAL(code, 404); // Apply patch curl_easy_reset(curl); iwxstr_clear(xstr); iwxstr_clear(hstr); curl_slist_free_all(headers); headers = curl_slist_append(0, "Content-Type: application/json"); snprintf(url, sizeof(url), "http://localhost:%" PRIu32 "/c1/1", port); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "[{\"op\":\"replace\", \"path\":\"/foo\", \"value\":\"zzz\"}]"); cc = curl_easy_perform(curl); CU_ASSERT_EQUAL_FATAL(cc, 0); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); CU_ASSERT_EQUAL_FATAL(code, 200); // Check patch applied curl_easy_reset(curl); iwxstr_clear(xstr); iwxstr_clear(hstr); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_xstr); curl_easy_setopt(curl, CURLOPT_WRITEDATA, xstr); curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curl_write_xstr); curl_easy_setopt(curl, CURLOPT_HEADERDATA, hstr); cc = curl_easy_perform(curl); CU_ASSERT_EQUAL_FATAL(cc, 0); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); CU_ASSERT_EQUAL_FATAL(code, 200); CU_ASSERT_STRING_EQUAL(iwxstr_ptr(xstr), "{\n" " \"foo\": \"zzz\"\n" "}" ); iwxstr_destroy(xstr); iwxstr_destroy(hstr); curl_slist_free_all(headers); rc = ejdb_close(&db); CU_ASSERT_EQUAL_FATAL(rc, 0); } int main() { CU_pSuite pSuite = NULL; if (CUE_SUCCESS != CU_initialize_registry()) { return CU_get_error(); } pSuite = CU_add_suite("jbr_test1", init_suite, clean_suite); if (NULL == pSuite) { CU_cleanup_registry(); return CU_get_error(); } if ( (NULL == CU_add_test(pSuite, "jbr_test1_1", jbr_test1_1))) { CU_cleanup_registry(); return CU_get_error(); } CU_basic_set_mode(CU_BRM_VERBOSE); CU_basic_run_tests(); int ret = CU_get_error() || CU_get_number_of_failures(); CU_cleanup_registry(); return ret; }