diff --git a/build/arm32v7-alpine-builder.dockerfile b/build/arm32v7-alpine-builder.dockerfile index 80810c8..a1b0455 100644 --- a/build/arm32v7-alpine-builder.dockerfile +++ b/build/arm32v7-alpine-builder.dockerfile @@ -28,7 +28,7 @@ RUN set -x \ openssl \ openssl-dev \ linux-headers \ - && pip3 install meson + && pip3 install 'meson==0.54.3' COPY src /usr/local/src diff --git a/build/arm32v7-ubuntu-builder.dockerfile b/build/arm32v7-ubuntu-builder.dockerfile index d63e4d5..e0c6871 100644 --- a/build/arm32v7-ubuntu-builder.dockerfile +++ b/build/arm32v7-ubuntu-builder.dockerfile @@ -26,7 +26,7 @@ RUN set -x \ ca-certificates \ openssl \ libssl-dev \ - && pip3 install --system meson + && pip3 install --system 'meson==0.54.3' COPY src /usr/local/src diff --git a/build/x86_64-alpine-builder.dockerfile b/build/x86_64-alpine-builder.dockerfile index f257d94..2cb665d 100644 --- a/build/x86_64-alpine-builder.dockerfile +++ b/build/x86_64-alpine-builder.dockerfile @@ -25,7 +25,7 @@ RUN set -x \ openssl \ openssl-dev \ linux-headers \ - && pip3 install meson + && pip3 install 'meson==0.54.3' COPY src /usr/local/src diff --git a/build/x86_64-ubuntu-builder.dockerfile b/build/x86_64-ubuntu-builder.dockerfile index b3c045a..96b13d6 100644 --- a/build/x86_64-ubuntu-builder.dockerfile +++ b/build/x86_64-ubuntu-builder.dockerfile @@ -23,7 +23,7 @@ RUN set -x \ ca-certificates \ openssl \ libssl-dev \ - && pip3 install --system meson + && pip3 install --system 'meson==0.54.3' COPY src /usr/local/src diff --git a/changelog.md b/changelog.md index 538ba63..b861c1d 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,10 @@ ## 0.5.0 _(unknown)_ +### Features + +* Removed dependency to libjansson + ### Fixes * Fix deadlock reading files larger that a few KBytes (Isseue #82) diff --git a/doc/build.md b/doc/build.md index 2b5d329..78e2ff3 100644 --- a/doc/build.md +++ b/doc/build.md @@ -39,7 +39,6 @@ After that, you will find the API documentation in the doc/api subdirectory. - [libfuse3](https://github.com/libfuse/libfuse/) - [libwebsockets](https://libwebsockets.org/) -- [Jansson](https://jansson.readthedocs.io) - [GoogleTest](https://github.com/google/googletest) *(optional)* ### Installation from source @@ -66,17 +65,6 @@ After that, you will find the API documentation in the doc/api subdirectory. make sudo make install -#### Jansson - - wget -O libjansson-2.12.tar.gz https://github.com/akheron/jansson/archive/v2.12.tar.gz - tar -xf libjansson-2.12.tar.gz - cd jansson-2.12 - mkdir .build - cd .build - cmake .. - make - sudo make install - #### GoogleTest Installation of GoogleTest is optional webfuse library, but required to compile tests. diff --git a/lib/webfuse/impl/client_protocol.c b/lib/webfuse/impl/client_protocol.c index 1d9370d..10bb30f 100644 --- a/lib/webfuse/impl/client_protocol.c +++ b/lib/webfuse/impl/client_protocol.c @@ -9,6 +9,8 @@ #include "webfuse/impl/timer/manager.h" #include "webfuse/impl/jsonrpc/response.h" #include "webfuse/impl/jsonrpc/proxy.h" +#include "webfuse/impl/json/doc.h" +#include "webfuse/impl/json/node.h" #include "webfuse/impl/message.h" #include "webfuse/impl/message_queue.h" @@ -30,26 +32,26 @@ struct wf_impl_client_protocol_add_filesystem_context static void wf_impl_client_protocol_process( struct wf_client_protocol * protocol, - char const * data, + char * data, size_t length) { - - json_t * message = json_loadb(data, length, 0, NULL); - if (NULL != message) + struct wf_json_doc * doc = wf_impl_json_doc_loadb(data, length); + if (NULL != doc) { + struct wf_json const * message = wf_impl_json_doc_root(doc); if (wf_impl_jsonrpc_is_response(message)) { wf_impl_jsonrpc_proxy_onresult(protocol->proxy, message); } - json_decref(message); + wf_impl_json_doc_dispose(doc); } } static void wf_impl_client_protocol_receive( struct wf_client_protocol * protocol, - char const * data, + char * data, size_t length, bool is_final_fragment) { @@ -77,7 +79,7 @@ wf_impl_client_protocol_receive( static bool wf_impl_client_protocol_send( - json_t * request, + struct wf_message * message, void * user_data) { bool result = false; @@ -85,13 +87,13 @@ wf_impl_client_protocol_send( if (NULL != protocol->wsi) { - struct wf_message * message = wf_impl_message_create(request); - if (NULL != message) - { - wf_impl_slist_append(&protocol->messages, &message->item); - lws_callback_on_writable(protocol->wsi); - result = true; - } + wf_impl_slist_append(&protocol->messages, &message->item); + lws_callback_on_writable(protocol->wsi); + result = true; + } + else + { + wf_impl_message_dispose(message); } return result; @@ -101,8 +103,8 @@ wf_impl_client_protocol_send( static void wf_impl_client_protocol_on_authenticate_finished( void * user_data, - json_t const * result, - json_t const * WF_UNUSED_PARAM(error)) + struct wf_json const * result, + struct wf_jsonrpc_error const * WF_UNUSED_PARAM(error)) { struct wf_client_protocol * protocol = user_data; int const reason = (NULL != result) ? WF_CLIENT_AUTHENTICATED : WF_CLIENT_AUTHENTICATION_FAILED; @@ -113,19 +115,19 @@ wf_impl_client_protocol_on_authenticate_finished( static void wf_impl_client_protocol_on_add_filesystem_finished( void * user_data, - json_t const * result, - json_t const * WF_UNUSED_PARAM(error)) + struct wf_json const * result, + struct wf_jsonrpc_error const * WF_UNUSED_PARAM(error)) { struct wf_impl_client_protocol_add_filesystem_context * context = user_data; struct wf_client_protocol * protocol = context->protocol; int reason = WF_CLIENT_FILESYSTEM_ADD_FAILED; - if (NULL == protocol->filesystem) + if ((NULL == protocol->filesystem) && (NULL != result)) { - json_t * id = json_object_get(result, "id"); - if (json_is_string(id)) + struct wf_json const * id = wf_impl_json_object_get(result, "id"); + if (wf_impl_json_is_string(id)) { - char const * name = json_string_value(id); + char const * name = wf_impl_json_string_get(id); struct wf_mountpoint * mountpoint = wf_impl_mountpoint_create(context->local_path); protocol->filesystem = wf_impl_filesystem_create(protocol->wsi,protocol->proxy, name, mountpoint); if (NULL != protocol->filesystem) @@ -330,14 +332,13 @@ wf_impl_client_protocol_authenticate( wf_impl_credentials_init_default(&creds); protocol->callback(protocol->user_data, WF_CLIENT_AUTHENTICATE_GET_CREDENTIALS, &creds); - json_incref(creds.data); wf_impl_jsonrpc_proxy_invoke( protocol->proxy, &wf_impl_client_protocol_on_authenticate_finished, protocol, "authenticate", "sj", - creds.type, creds.data); + creds.type, &wf_impl_credentials_write, &creds); wf_impl_credentials_cleanup(&creds); } diff --git a/lib/webfuse/impl/credentials.c b/lib/webfuse/impl/credentials.c index ab72731..89c6daa 100644 --- a/lib/webfuse/impl/credentials.c +++ b/lib/webfuse/impl/credentials.c @@ -1,28 +1,54 @@ #include "webfuse/impl/credentials.h" +#include "webfuse/impl/json/writer.h" +#include "webfuse/impl/json/node.h" + +#include #include +#define WF_CREDENTIALS_INITIAL_CAPACITY 2 + void wf_impl_credentials_init_default( struct wf_credentials * credentials) { credentials->type = NULL; - credentials->data = json_object(); + credentials->capacity = WF_CREDENTIALS_INITIAL_CAPACITY; + credentials->entries = malloc(sizeof(struct wf_credentials_entry) * credentials->capacity); + credentials->size = 0; } void wf_impl_credentials_init( struct wf_credentials * credentials, char const * type, - json_t * data) + struct wf_json const * data) { + size_t count = (NULL != data) ? wf_impl_json_object_size(data) : 0; credentials->type = strdup(type); - credentials->data = data; - json_incref(credentials->data); + credentials->capacity = (count > 0) ? count : WF_CREDENTIALS_INITIAL_CAPACITY; + credentials->entries = malloc(sizeof(struct wf_credentials_entry) * credentials->capacity); + credentials->size = 0; + + for (size_t i = 0; i < count; i++) + { + char const * key = wf_impl_json_object_key(data, i); + struct wf_json const * value = wf_impl_json_object_value(data, i); + + if (wf_impl_json_is_string(value)) + { + wf_impl_credentials_add(credentials, key, wf_impl_json_string_get(value)); + } + } } void wf_impl_credentials_cleanup( struct wf_credentials * credentials) { + for (size_t i = 0; i < credentials->size; i++) + { + free(credentials->entries[i].key); + free(credentials->entries[i].value); + } + free(credentials->entries); free(credentials->type); - json_decref(credentials->data); } char const * wf_impl_credentials_type( @@ -35,15 +61,15 @@ char const * wf_impl_credentials_get( struct wf_credentials const * credentials, char const * key) { - char const * result = NULL; - - json_t * value_holder = json_object_get(credentials->data, key); - if (json_is_string(value_holder)) + for (size_t i = 0; i < credentials->size; i++) { - result = json_string_value(value_holder); + if (0 == strcmp(key, credentials->entries[i].key)) + { + return credentials->entries[i].value; + } } - return result; + return NULL; } void wf_impl_credentials_set_type( @@ -59,6 +85,41 @@ void wf_impl_credentials_add( char const * key, char const * value) { - json_object_set_new(credentials->data, key, json_string(value)); + for(size_t i = 0; i < credentials->size; i++) + { + if (0 == strcmp(key, credentials->entries[i].key)) + { + free(credentials->entries[i].value); + credentials->entries[i].value = strdup(value); + return; + } + } + + if (credentials->size >= credentials->capacity) + { + credentials->capacity *= 2; + credentials->entries = realloc(credentials->entries, credentials->capacity); + } + + credentials->entries[credentials->size].key = strdup(key); + credentials->entries[credentials->size].value = strdup(value); + credentials->size++; } +void +wf_impl_credentials_write( + struct wf_json_writer * writer, + void * data) +{ + struct wf_credentials * credentials = data; + + wf_impl_json_write_object_begin(writer); + for (size_t i = 0; i < credentials->size; i++) + { + char const * key = credentials->entries[i].key; + char const * value = credentials->entries[i].value; + + wf_impl_json_write_object_string(writer, key, value); + } + wf_impl_json_write_object_end(writer); +} diff --git a/lib/webfuse/impl/credentials.h b/lib/webfuse/impl/credentials.h index 59b4c0c..11978f1 100644 --- a/lib/webfuse/impl/credentials.h +++ b/lib/webfuse/impl/credentials.h @@ -1,23 +1,38 @@ #ifndef WF_ADAPTER_IMPL_CREDENTIALS_H #define WF_ADAPTER_IMPL_CREDENTIALS_H -#include +#ifndef __cplusplus +#include +#else +#include +#endif #ifdef __cplusplus extern "C" { #endif +struct wf_json_writer; +struct wf_json; + +struct wf_credentials_entry +{ + char * key; + char * value; +}; + struct wf_credentials { char * type; - json_t * data; + struct wf_credentials_entry * entries; + size_t capacity; + size_t size; }; extern void wf_impl_credentials_init( struct wf_credentials * credentials, char const * type, - json_t * data); + struct wf_json const * data); extern void wf_impl_credentials_init_default( struct wf_credentials * credentials); @@ -41,6 +56,11 @@ extern void wf_impl_credentials_add( char const * key, char const * value); +extern void +wf_impl_credentials_write( + struct wf_json_writer * writer, + void * data); + #ifdef __cplusplus } #endif diff --git a/lib/webfuse/impl/json/doc.c b/lib/webfuse/impl/json/doc.c new file mode 100644 index 0000000..e76bf83 --- /dev/null +++ b/lib/webfuse/impl/json/doc.c @@ -0,0 +1,44 @@ +#include "webfuse/impl/json/doc.h" +#include "webfuse/impl/json/node_intern.h" +#include "webfuse/impl/json/reader.h" +#include "webfuse/impl/json/parser.h" + +#include + +struct wf_json_doc +{ + struct wf_json root; +}; + +struct wf_json_doc * +wf_impl_json_doc_loadb( + char * data, + size_t length) +{ + struct wf_json_reader reader; + wf_impl_json_reader_init(&reader, data, length); + + struct wf_json_doc * doc = malloc(sizeof(struct wf_json_doc)); + if (!wf_impl_json_parse_value(&reader, &doc->root)) + { + free(doc); + doc = NULL; + } + + return doc; +} + +void +wf_impl_json_doc_dispose( + struct wf_json_doc * doc) +{ + wf_impl_json_cleanup(&doc->root); + free(doc); +} + +struct wf_json const * +wf_impl_json_doc_root( + struct wf_json_doc * doc) +{ + return &doc->root; +} diff --git a/lib/webfuse/impl/json/doc.h b/lib/webfuse/impl/json/doc.h new file mode 100644 index 0000000..9735bfa --- /dev/null +++ b/lib/webfuse/impl/json/doc.h @@ -0,0 +1,36 @@ +#ifndef WF_IMPL_JSON_DOC_H +#define WF_IMPL_JSON_DOC_H + +#ifndef __cplusplus +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wf_json_doc; +struct wf_json; + +extern struct wf_json_doc * +wf_impl_json_doc_loadb( + char * data, + size_t length); + +extern void +wf_impl_json_doc_dispose( + struct wf_json_doc * doc); + +extern struct wf_json const * +wf_impl_json_doc_root( + struct wf_json_doc * doc); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/webfuse/impl/json/node.c b/lib/webfuse/impl/json/node.c new file mode 100644 index 0000000..49fc6c6 --- /dev/null +++ b/lib/webfuse/impl/json/node.c @@ -0,0 +1,206 @@ +#include "webfuse/impl/json/node_intern.h" + +#include +#include + +static struct wf_json const wf_json_undefined = +{ + .type = WF_JSON_TYPE_UNDEFINED, + .value = { .b = false } +}; + +enum wf_json_type +wf_impl_json_type( + struct wf_json const * json) +{ + return json->type; +} + +bool +wf_impl_json_bool_get( + struct wf_json const * json) +{ + return (WF_JSON_TYPE_BOOL == json->type) ? json->value.b : false; +} + +bool +wf_impl_json_is_undefined( + struct wf_json const * json) +{ + return (WF_JSON_TYPE_UNDEFINED == json->type); +} + +bool +wf_impl_json_is_null( + struct wf_json const * json) +{ + return (WF_JSON_TYPE_NULL == json->type); +} + +bool +wf_impl_json_is_bool( + struct wf_json const * json) +{ + return (WF_JSON_TYPE_BOOL == json->type); +} + +bool +wf_impl_json_is_int( + struct wf_json const * json) +{ + return (WF_JSON_TYPE_INT == json->type); +} + +bool +wf_impl_json_is_string( + struct wf_json const * json) +{ + return (WF_JSON_TYPE_STRING == json->type); +} + +bool +wf_impl_json_is_array( + struct wf_json const * json) +{ + return (WF_JSON_TYPE_ARRAY == json->type); +} + +bool +wf_impl_json_is_object( + struct wf_json const * json) +{ + return (WF_JSON_TYPE_OBJECT == json->type); +} + +int +wf_impl_json_int_get( + struct wf_json const * json) +{ + return (WF_JSON_TYPE_INT == json->type) ? json->value.i : 0; +} + +char const * +wf_impl_json_string_get( + struct wf_json const * json) +{ + return (WF_JSON_TYPE_STRING == json->type) ? json->value.s.data : ""; +} + +size_t +wf_impl_json_string_size( + struct wf_json const * json) +{ + return (WF_JSON_TYPE_STRING == json->type) ? json->value.s.size : 0; +} + + +struct wf_json const * +wf_impl_json_array_get( + struct wf_json const * json, + size_t pos) +{ + struct wf_json const * result = &wf_json_undefined; + if ((WF_JSON_TYPE_ARRAY == json->type) && (pos < json->value.a.size)) + { + result = &(json->value.a.items[pos]); + } + + return result; +} + +size_t +wf_impl_json_array_size( + struct wf_json const * json) +{ + return (WF_JSON_TYPE_ARRAY == json->type) ? json->value.a.size : 0; +} + +struct wf_json const * +wf_impl_json_object_get( + struct wf_json const * json, + char const * key) + { + if (WF_JSON_TYPE_OBJECT == json->type) + { + size_t const count = json->value.o.size; + for(size_t i = 0; i < count; i++) + { + struct wf_json_object_item * actual = &(json->value.o.items[i]); + if (0 == strcmp(key, actual->key)) + { + return &(actual->json); + } + } + } + + return &wf_json_undefined; + } + +size_t +wf_impl_json_object_size( + struct wf_json const * json) +{ + return (WF_JSON_TYPE_OBJECT == json->type) ? json->value.o.size : 0; +} + +char const * +wf_impl_json_object_key( + struct wf_json const * json, + size_t pos) +{ + char const * result = ""; + if ((WF_JSON_TYPE_OBJECT == json->type) && (pos < json->value.o.size)) + { + result = json->value.o.items[pos].key; + } + + return result; +} + +struct wf_json const * +wf_impl_json_object_value( + struct wf_json const * json, + size_t pos) +{ + struct wf_json const * result = &wf_json_undefined; + if ((WF_JSON_TYPE_OBJECT == json->type) && (pos < json->value.o.size)) + { + result = &(json->value.o.items[pos].json); + } + + return result; + +} + +void +wf_impl_json_cleanup( + struct wf_json * json) +{ + switch (json->type) + { + case WF_JSON_TYPE_ARRAY: + { + size_t const count = json->value.a.size; + for(size_t i = 0; i < count; i++) + { + struct wf_json * actual = &(json->value.a.items[i]); + wf_impl_json_cleanup(actual); + } + free(json->value.a.items); + } + break; + case WF_JSON_TYPE_OBJECT: + { + size_t const count = json->value.o.size; + for(size_t i = 0; i < count; i++) + { + struct wf_json * actual = &(json->value.o.items[i].json); + wf_impl_json_cleanup(actual); + } + free(json->value.o.items); + } + break; + default: + break; + } +} diff --git a/lib/webfuse/impl/json/node.h b/lib/webfuse/impl/json/node.h new file mode 100644 index 0000000..28441c0 --- /dev/null +++ b/lib/webfuse/impl/json/node.h @@ -0,0 +1,109 @@ +#ifndef WF_IMPL_JSON_NODE_H +#define WF_IMPL_JSON_NODE_H + +#ifndef __cplusplus +#include +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +enum wf_json_type +{ + WF_JSON_TYPE_UNDEFINED, + WF_JSON_TYPE_NULL, + WF_JSON_TYPE_BOOL, + WF_JSON_TYPE_INT, + WF_JSON_TYPE_STRING, + WF_JSON_TYPE_ARRAY, + WF_JSON_TYPE_OBJECT +}; + +struct wf_json; + +extern enum wf_json_type +wf_impl_json_type( + struct wf_json const * json); + +extern bool +wf_impl_json_is_undefined( + struct wf_json const * json); + +extern bool +wf_impl_json_is_null( + struct wf_json const * json); + +extern bool +wf_impl_json_is_bool( + struct wf_json const * json); + +extern bool +wf_impl_json_is_int( + struct wf_json const * json); + +extern bool +wf_impl_json_is_string( + struct wf_json const * json); + +extern bool +wf_impl_json_is_array( + struct wf_json const * json); + +extern bool +wf_impl_json_is_object( + struct wf_json const * json); + +extern bool +wf_impl_json_bool_get( + struct wf_json const * json); + +extern int +wf_impl_json_int_get( + struct wf_json const * json); + +extern char const * +wf_impl_json_string_get( + struct wf_json const * json); + +extern size_t +wf_impl_json_string_size( + struct wf_json const * json); + +extern struct wf_json const * +wf_impl_json_array_get( + struct wf_json const * json, + size_t pos); + +extern size_t +wf_impl_json_array_size( + struct wf_json const * json); + +extern struct wf_json const * +wf_impl_json_object_get( + struct wf_json const * json, + char const * key); + +extern size_t +wf_impl_json_object_size( + struct wf_json const * json); + +extern char const * +wf_impl_json_object_key( + struct wf_json const * json, + size_t pos); + +extern struct wf_json const * +wf_impl_json_object_value( + struct wf_json const * json, + size_t pos); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/webfuse/impl/json/node_intern.h b/lib/webfuse/impl/json/node_intern.h new file mode 100644 index 0000000..b591bbb --- /dev/null +++ b/lib/webfuse/impl/json/node_intern.h @@ -0,0 +1,60 @@ +#ifndef WF_IMPL_JSON_NODE_INTERN_H +#define WF_IMPL_JSON_NODE_INTERN_H + +#include "webfuse/impl/json/node.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wf_json_string +{ + char * data; + size_t size; +}; + +struct wf_json_array +{ + struct wf_json * items; + size_t size; +}; + +struct wf_json_object_item; + +struct wf_json_object +{ + struct wf_json_object_item * items; + size_t size; +}; + +union wf_json_value +{ + bool b; + int i; + struct wf_json_string s; + struct wf_json_array a; + struct wf_json_object o; +}; + +struct wf_json +{ + enum wf_json_type type; + union wf_json_value value; +}; + +struct wf_json_object_item +{ + struct wf_json json; + char * key; +}; + +extern void +wf_impl_json_cleanup( + struct wf_json * json); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/webfuse/impl/json/parser.c b/lib/webfuse/impl/json/parser.c new file mode 100644 index 0000000..9047b42 --- /dev/null +++ b/lib/webfuse/impl/json/parser.c @@ -0,0 +1,291 @@ +#include "webfuse/impl/json/parser.h" +#include "webfuse/impl/json/reader.h" +#include "webfuse/impl/json/node_intern.h" + +#include + +#define WF_JSON_PARSER_INITIAL_CAPACITY 4 + +static bool +wf_impl_json_parse_null( + struct wf_json_reader * reader, + struct wf_json * json); + +static bool +wf_impl_json_parse_true( + struct wf_json_reader * reader, + struct wf_json * json); + +static bool +wf_impl_json_parse_false( + struct wf_json_reader * reader, + struct wf_json * json); + +static bool +wf_impl_json_parse_int( + struct wf_json_reader * reader, + struct wf_json * json); + +static bool +wf_impl_json_parse_string( + struct wf_json_reader * reader, + struct wf_json * json); + +static bool +wf_impl_json_parse_array( + struct wf_json_reader * reader, + struct wf_json * json); + +static bool +wf_impl_json_parse_object( + struct wf_json_reader * reader, + struct wf_json * json); + +// -- + +bool +wf_impl_json_parse_value( + struct wf_json_reader * reader, + struct wf_json * json) +{ + bool result = false; + char const c = wf_impl_json_reader_skip_whitespace(reader); + + switch (c) + { + case 'n': + result = wf_impl_json_parse_null(reader, json); + break; + case 't': + result = wf_impl_json_parse_true(reader, json); + break; + case 'f': + result = wf_impl_json_parse_false(reader, json); + break; + case '\"': + result = wf_impl_json_parse_string(reader, json); + break; + case '[': + result = wf_impl_json_parse_array(reader, json); + break; + case '{': + result = wf_impl_json_parse_object(reader, json); + break; + case '-': // fall-through + case '0': // fall-through + case '1': // fall-through + case '2': // fall-through + case '3': // fall-through + case '4': // fall-through + case '5': // fall-through + case '6': // fall-through + case '7': // fall-through + case '8': // fall-through + case '9': + result = wf_impl_json_parse_int(reader, json); + break; + default: + result = false; + break; + } + + return result; +} + +// -- + +static bool +wf_impl_json_parse_null( + struct wf_json_reader * reader, + struct wf_json * json) +{ + bool const result = wf_impl_json_reader_read_const(reader, "null", 4); + if (result) + { + json->type = WF_JSON_TYPE_NULL; + } + + return result; +} + +static bool +wf_impl_json_parse_true( + struct wf_json_reader * reader, + struct wf_json * json) +{ + bool const result = wf_impl_json_reader_read_const(reader, "true", 4); + if (result) + { + json->type = WF_JSON_TYPE_BOOL; + json->value.b = true; + } + + return result; +} + +static bool +wf_impl_json_parse_false( + struct wf_json_reader * reader, + struct wf_json * json) +{ + bool const result = wf_impl_json_reader_read_const(reader, "false", 5); + if (result) + { + json->type = WF_JSON_TYPE_BOOL; + json->value.b = false; + } + + return result; +} + + +static bool +wf_impl_json_parse_int( + struct wf_json_reader * reader, + struct wf_json * json) +{ + int value; + bool const result = wf_impl_json_reader_read_int(reader, &value); + if (result) + { + json->type = WF_JSON_TYPE_INT; + json->value.i = value; + } + + return result; +} + +static bool +wf_impl_json_parse_string( + struct wf_json_reader * reader, + struct wf_json * json) +{ + char * value; + size_t size; + bool const result = wf_impl_json_reader_read_string(reader, &value, &size); + if (result) + { + json->type = WF_JSON_TYPE_STRING; + json->value.s.data = value; + json->value.s.size = size; + } + + return result; +} + +static bool +wf_impl_json_parse_array( + struct wf_json_reader * reader, + struct wf_json * json) +{ + wf_impl_json_reader_skip_whitespace(reader); + char c = wf_impl_json_reader_get_char(reader); + if ('[' != c) { return false; } + + size_t capacity = WF_JSON_PARSER_INITIAL_CAPACITY; + json->type = WF_JSON_TYPE_ARRAY; + json->value.a.items = malloc(sizeof(struct wf_json) * capacity); + json->value.a.size = 0; + + c = wf_impl_json_reader_skip_whitespace(reader); + if (']' == c) + { + wf_impl_json_reader_get_char(reader); + return true; + } + + bool result; + do + { + if (json->value.a.size >= capacity) + { + capacity *= 2; + json->value.a.items = realloc(json->value.a.items, sizeof(struct wf_json) * capacity); + } + + result = wf_impl_json_parse_value(reader, &(json->value.a.items[json->value.a.size])); + if (result) + { + json->value.a.size++; + wf_impl_json_reader_skip_whitespace(reader); + c = wf_impl_json_reader_get_char(reader); + } + } while ((result) && (',' == c)); + + if (']' != c) + { + result = false; + } + + if (!result) + { + wf_impl_json_cleanup(json); + } + + return result; +} + +static bool +wf_impl_json_parse_object( + struct wf_json_reader * reader, + struct wf_json * json) +{ + wf_impl_json_reader_skip_whitespace(reader); + char c = wf_impl_json_reader_get_char(reader); + if ('{' != c) { return false; } + + size_t capacity = WF_JSON_PARSER_INITIAL_CAPACITY; + json->type = WF_JSON_TYPE_OBJECT; + json->value.o.items = malloc(sizeof(struct wf_json_object_item) * capacity); + json->value.o.size = 0; + + c = wf_impl_json_reader_skip_whitespace(reader); + if ('}' == c) + { + wf_impl_json_reader_get_char(reader); + return true; + } + + bool result; + do + { + if (json->value.o.size >= capacity) + { + capacity *= 2; + json->value.o.items = realloc(json->value.o.items, sizeof(struct wf_json_object_item) * capacity); + } + + struct wf_json_object_item * item = &(json->value.o.items[json->value.o.size]); + size_t key_size; + result = wf_impl_json_reader_read_string(reader, &(item->key), &key_size); + if (result) + { + wf_impl_json_reader_skip_whitespace(reader); + result = (':' == wf_impl_json_reader_get_char(reader)); + } + + if (result) + { + result = wf_impl_json_parse_value(reader, &(item->json)); + } + + if (result) + { + json->value.o.size++; + wf_impl_json_reader_skip_whitespace(reader); + c = wf_impl_json_reader_get_char(reader); + } + } while ((result) && (',' == c)); + + if ('}' != c) + { + result = false; + } + + if (!result) + { + wf_impl_json_cleanup(json); + } + + return result; +} \ No newline at end of file diff --git a/lib/webfuse/impl/json/parser.h b/lib/webfuse/impl/json/parser.h new file mode 100644 index 0000000..93b1380 --- /dev/null +++ b/lib/webfuse/impl/json/parser.h @@ -0,0 +1,25 @@ +#ifndef WF_IMPL_JSON_PARSER_H +#define WF_IMPL_JSON_PARSER_H + +#ifndef __cplusplus +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wf_json_reader; +struct wf_json; + +extern bool +wf_impl_json_parse_value( + struct wf_json_reader * reader, + struct wf_json * json); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/webfuse/impl/json/reader.c b/lib/webfuse/impl/json/reader.c new file mode 100644 index 0000000..2f9af2f --- /dev/null +++ b/lib/webfuse/impl/json/reader.c @@ -0,0 +1,181 @@ +#include "webfuse/impl/json/reader.h" + +#include + +static char +wf_impl_json_unescape( + char c); + +void +wf_impl_json_reader_init( + struct wf_json_reader * reader, + char * contents, + size_t length) +{ + reader->contents = contents; + reader->length = length; + reader->pos = 0; +} + +char +wf_impl_json_reader_skip_whitespace( + struct wf_json_reader * reader) +{ + char c = wf_impl_json_reader_peek(reader); + while ((' ' == c) || ('\n' == c) || ('\t' == c) || ('\r' == c)) + { + reader->pos++; + c = wf_impl_json_reader_peek(reader); + } + + return c; +} + +char +wf_impl_json_reader_peek( + struct wf_json_reader * reader) +{ + char result = '\0'; + if (reader->pos < reader->length) + { + result = reader->contents[reader->pos]; + } + + return result; +} + +char +wf_impl_json_reader_get_char( + struct wf_json_reader * reader) +{ + char result = '\0'; + if (reader->pos < reader->length) + { + result = reader->contents[reader->pos++]; + } + + return result; +} + +void +wf_impl_json_reader_unget_char( + struct wf_json_reader * reader) +{ + if (0 < reader->pos) + { + reader->pos--; + } +} + +bool +wf_impl_json_reader_read_const( + struct wf_json_reader * reader, + char const * value, + size_t length) +{ + size_t remaining = reader->length - reader->pos; + bool const result = ((remaining >= length) && (0 == strncmp((&reader->contents[reader->pos]), value, length))); + if (result) + { + reader->pos += length; + } + + return result; +} + +bool +wf_impl_json_reader_read_int( + struct wf_json_reader * reader, + int * value) +{ + char c = wf_impl_json_reader_get_char(reader); + bool const is_signed = ('-' == c); + if (is_signed) + { + c = wf_impl_json_reader_get_char(reader); + } + + bool const result = (('0' <= c) && (c <= '9')); + if (result) + { + int v = c - '0'; + c = wf_impl_json_reader_peek(reader); + while (('0' <= c) && (c <= '9')) + { + v *= 10; + v += c - '0'; + reader->pos++; + c = wf_impl_json_reader_peek(reader); + } + + *value = (is_signed) ? -v : v; + } + + return result; +} + +bool +wf_impl_json_reader_read_string( + struct wf_json_reader * reader, + char * * value, + size_t * size) +{ + wf_impl_json_reader_skip_whitespace(reader); + char c = wf_impl_json_reader_get_char(reader); + if ('\"' != c) { return false; } + + size_t start = reader->pos; + size_t p = reader->pos; + c = wf_impl_json_reader_get_char(reader); + while (('\"' != c) && ('\0' != c)) + { + if ('\\' != c) + { + reader->contents[p++] = c; + } + else + { + char unescaped = wf_impl_json_unescape(wf_impl_json_reader_get_char(reader)); + if ('\0' != unescaped) + { + reader->contents[p++] = unescaped; + + } + else + { + return false; + } + } + + c = wf_impl_json_reader_get_char(reader); + } + + bool const result = ('\"' == c); + if (result) + { + reader->contents[p] = '\0'; + *value = &(reader->contents[start]); + *size = p - start; + } + + return result; +} + +static char +wf_impl_json_unescape( + char c) +{ + switch (c) + { + case '\"': return '\"'; + case '\\': return '\\'; + case '/': return '/'; + case 'b': return '\b'; + case 'f': return '\f'; + case 'n': return '\n'; + case 'r': return '\r'; + case 't': return '\t'; + default: + return '\0'; + } +} diff --git a/lib/webfuse/impl/json/reader.h b/lib/webfuse/impl/json/reader.h new file mode 100644 index 0000000..1b432aa --- /dev/null +++ b/lib/webfuse/impl/json/reader.h @@ -0,0 +1,66 @@ +#ifndef WF_IMPL_JSON_READER_H +#define WF_IMPL_JSON_READER_H + +#ifndef __cplusplus +#include +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wf_json_reader +{ + char * contents; + size_t length; + size_t pos; +}; + +extern void +wf_impl_json_reader_init( + struct wf_json_reader * reader, + char * contents, + size_t length); + +extern char +wf_impl_json_reader_skip_whitespace( + struct wf_json_reader * reader); + +extern char +wf_impl_json_reader_peek( + struct wf_json_reader * reader); + +extern char +wf_impl_json_reader_get_char( + struct wf_json_reader * reader); + +extern void +wf_impl_json_reader_unget_char( + struct wf_json_reader * reader); + +extern bool +wf_impl_json_reader_read_const( + struct wf_json_reader * reader, + char const * value, + size_t length); + +extern bool +wf_impl_json_reader_read_int( + struct wf_json_reader * reader, + int * value); + +extern bool +wf_impl_json_reader_read_string( + struct wf_json_reader * reader, + char * * value, + size_t * size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/webfuse/impl/json/writer.c b/lib/webfuse/impl/json/writer.c index 40834da..9f63966 100644 --- a/lib/webfuse/impl/json/writer.c +++ b/lib/webfuse/impl/json/writer.c @@ -263,12 +263,12 @@ wf_impl_json_write_bytes( size_t length) { size_t encoded_length = wf_impl_base64_encoded_size(length); - wf_impl_json_reserve(writer, length + WF_JSON_WRITER_ADDITIONAL_STRING_SIZE); + wf_impl_json_reserve(writer, encoded_length + WF_JSON_WRITER_ADDITIONAL_STRING_SIZE); wf_impl_json_begin_value(writer); wf_impl_json_write_raw_char(writer, '\"'); wf_impl_base64_encode((uint8_t const *) data, length, &(writer->data[writer->offset]), encoded_length); - writer->offset = encoded_length; + writer->offset += encoded_length; wf_impl_json_write_raw_char(writer, '\"'); wf_impl_json_end_value(writer); @@ -412,7 +412,7 @@ wf_impl_json_write_object_begin_object( char const * key) { wf_impl_json_write_object_key(writer, key); - wf_impl_json_write_array_end(writer); + wf_impl_json_write_object_begin(writer); } // -- diff --git a/lib/webfuse/impl/jsonrpc/error.c b/lib/webfuse/impl/jsonrpc/error.c index b54c4bc..a8dd8c4 100644 --- a/lib/webfuse/impl/jsonrpc/error.c +++ b/lib/webfuse/impl/jsonrpc/error.c @@ -1,17 +1,51 @@ #include "webfuse/impl/jsonrpc/error.h" -json_t * +#include +#include + +struct wf_jsonrpc_error +{ + int code; + char * message; +}; + +struct wf_jsonrpc_error * wf_impl_jsonrpc_error( int code, char const * message) { - json_t * error = json_object(); - json_object_set_new(error, "code", json_integer(code)); - json_object_set_new(error, "message", json_string(message)); + struct wf_jsonrpc_error * error = malloc(sizeof(struct wf_jsonrpc_error)); + error->code = code; + error->message = strdup(message); return error; } +void +wf_impl_jsonrpc_error_dispose( + struct wf_jsonrpc_error * error) +{ + if (NULL != error) + { + free(error->message); + free(error); + } +} + +int +wf_impl_jsonrpc_error_code( + struct wf_jsonrpc_error const * error) +{ + return error->code; +} + +char const * +wf_impl_jsonrpc_error_message( + struct wf_jsonrpc_error const * error) +{ + return error->message; +} + void wf_impl_jsonrpc_propate_error( wf_jsonrpc_proxy_finished_fn * finised, @@ -19,9 +53,12 @@ wf_impl_jsonrpc_propate_error( int code, char const * message) { - json_t * error = wf_impl_jsonrpc_error(code, message); - finised(user_data, NULL, error); + struct wf_jsonrpc_error error = + { + .code = code, + .message = (char*) message + }; - json_decref(error); + finised(user_data, NULL, &error); } diff --git a/lib/webfuse/impl/jsonrpc/error.h b/lib/webfuse/impl/jsonrpc/error.h index 6a0cf2c..f3fce21 100644 --- a/lib/webfuse/impl/jsonrpc/error.h +++ b/lib/webfuse/impl/jsonrpc/error.h @@ -1,7 +1,6 @@ #ifndef WF_IMPL_JSONRPC_ERROR_H #define WF_IMPL_JSONRPC_ERROR_H -#include #include "webfuse/impl/jsonrpc/proxy_finished_fn.h" #ifdef __cplusplus @@ -9,11 +8,25 @@ extern "C" { #endif -extern json_t * +struct wf_jsonrpc_error; + +extern struct wf_jsonrpc_error * wf_impl_jsonrpc_error( int code, char const * message); +extern void +wf_impl_jsonrpc_error_dispose( + struct wf_jsonrpc_error * error); + +extern int +wf_impl_jsonrpc_error_code( + struct wf_jsonrpc_error const * error); + +extern char const * +wf_impl_jsonrpc_error_message( + struct wf_jsonrpc_error const * error); + extern void wf_impl_jsonrpc_propate_error( wf_jsonrpc_proxy_finished_fn * finised, diff --git a/lib/webfuse/impl/jsonrpc/method_invoke_fn.h b/lib/webfuse/impl/jsonrpc/method_invoke_fn.h index 10bb88b..ceca8ac 100644 --- a/lib/webfuse/impl/jsonrpc/method_invoke_fn.h +++ b/lib/webfuse/impl/jsonrpc/method_invoke_fn.h @@ -1,19 +1,18 @@ #ifndef WF_IMPL_JSONRPC_METHOD_INVOKE_FN_H #define WF_IMPL_JSONRPC_METHOD_INVOKE_FN_H -#include - #ifdef __cplusplus extern "C" { #endif struct wf_jsonrpc_request; +struct wf_json; typedef void wf_jsonrpc_method_invoke_fn( struct wf_jsonrpc_request * request, char const * method_name, - json_t * params, + struct wf_json const * params, void * user_data); #ifdef __cplusplus diff --git a/lib/webfuse/impl/jsonrpc/proxy.c b/lib/webfuse/impl/jsonrpc/proxy.c index c3d1235..9009be8 100644 --- a/lib/webfuse/impl/jsonrpc/proxy.c +++ b/lib/webfuse/impl/jsonrpc/proxy.c @@ -2,12 +2,17 @@ #include "webfuse/impl/jsonrpc/proxy_request_manager.h" #include "webfuse/impl/jsonrpc/response_intern.h" #include "webfuse/impl/jsonrpc/error.h" +#include "webfuse/impl/json/writer.h" +#include "webfuse/impl/message.h" #include "webfuse/status.h" +#include #include #include +#define WF_JSONRPC_PROXY_DEFAULT_MESSAGE_SIZE 1024 + struct wf_jsonrpc_proxy * wf_impl_jsonrpc_proxy_create( struct wf_timer_manager * manager, @@ -29,15 +34,17 @@ void wf_impl_jsonrpc_proxy_dispose( } -static json_t * wf_impl_jsonrpc_request_create( +static struct wf_message * +wf_impl_jsonrpc_request_create( char const * method, int id, char const * param_info, va_list args) { - json_t * request = json_object(); - json_object_set_new(request, "method", json_string(method)); - json_t * params = json_array(); + struct wf_json_writer * writer = wf_impl_json_writer_create(WF_JSONRPC_PROXY_DEFAULT_MESSAGE_SIZE, LWS_PRE); + wf_impl_json_write_object_begin(writer); + wf_impl_json_write_object_string(writer, "method", method); + wf_impl_json_write_object_begin_array(writer, "params"); for (char const * param_type = param_info; '\0' != *param_type; param_type++) { @@ -46,37 +53,41 @@ static json_t * wf_impl_jsonrpc_request_create( case 's': { char const * const value = va_arg(args, char const *); - json_array_append_new(params, json_string(value)); + wf_impl_json_write_string(writer, value); } break; case 'i': { int const value = va_arg(args, int); - json_array_append_new(params, json_integer(value)); + wf_impl_json_write_int(writer, value); } break; case 'j': { - json_t * const value = va_arg(args, json_t *); - json_array_append_new(params, value); + wf_jsonrpc_custom_write_fn * write = va_arg(args, wf_jsonrpc_custom_write_fn *); + void * data = va_arg(args, void *); + write(writer, data); } break; default: - fprintf(stderr, "fatal: unknown param_type '%c'\n", *param_type); - json_decref(params); - json_decref(request); - return NULL; + fprintf(stderr, "fatal: unknown param_type '%c'\n", *param_type); + break; } } - + wf_impl_json_write_array_end(writer); - json_object_set_new(request, "params", params); if (0 != id) { - json_object_set_new(request, "id", json_integer(id)); + wf_impl_json_write_object_int(writer, "id", id); } + + wf_impl_json_write_object_end(writer); - return request; + size_t length; + char * message = wf_impl_json_writer_take(writer, &length); + wf_impl_json_writer_dispose(writer); + + return wf_impl_message_create(message, length); } void wf_impl_jsonrpc_proxy_init( @@ -110,18 +121,13 @@ void wf_impl_jsonrpc_proxy_vinvoke( int id = wf_impl_jsonrpc_proxy_request_manager_add_request( proxy->request_manager, finished, user_data); - json_t * request = wf_impl_jsonrpc_request_create(method_name, id, param_info, args); - bool const is_send = ((NULL != request) && (proxy->send(request, proxy->user_data))); + struct wf_message * request = wf_impl_jsonrpc_request_create(method_name, id, param_info, args); + bool const is_send = proxy->send(request, proxy->user_data); if (!is_send) { wf_impl_jsonrpc_proxy_request_manager_cancel_request( proxy->request_manager, id, WF_BAD, "Bad: failed to send request"); } - - if (NULL != request) - { - json_decref(request); - } } extern void wf_impl_jsonrpc_proxy_vnotify( @@ -130,19 +136,14 @@ extern void wf_impl_jsonrpc_proxy_vnotify( char const * param_info, va_list args) { - json_t * request = wf_impl_jsonrpc_request_create(method_name, 0, param_info, args); - - if (NULL != request) - { - proxy->send(request, proxy->user_data); - json_decref(request); - } + struct wf_message * request = wf_impl_jsonrpc_request_create(method_name, 0, param_info, args); + proxy->send(request, proxy->user_data); } void wf_impl_jsonrpc_proxy_onresult( struct wf_jsonrpc_proxy * proxy, - json_t * message) + struct wf_json const * message) { struct wf_jsonrpc_response response; wf_impl_jsonrpc_response_init(&response, message); diff --git a/lib/webfuse/impl/jsonrpc/proxy.h b/lib/webfuse/impl/jsonrpc/proxy.h index dd5a73e..5bd003c 100644 --- a/lib/webfuse/impl/jsonrpc/proxy.h +++ b/lib/webfuse/impl/jsonrpc/proxy.h @@ -11,7 +11,6 @@ using std::size_t; #endif -#include #include "webfuse/impl/jsonrpc/send_fn.h" #include "webfuse/impl/jsonrpc/proxy_finished_fn.h" @@ -21,6 +20,13 @@ extern "C" { struct wf_jsonrpc_proxy; struct wf_timer_manager; +struct wf_json_writer; +struct wf_json; + +typedef void +wf_jsonrpc_custom_write_fn( + struct wf_json_writer * writer, + void * data); extern struct wf_jsonrpc_proxy * wf_impl_jsonrpc_proxy_create( @@ -64,7 +70,7 @@ extern void wf_impl_jsonrpc_proxy_notify( extern void wf_impl_jsonrpc_proxy_onresult( struct wf_jsonrpc_proxy * proxy, - json_t * message); + struct wf_json const * message); #ifdef __cplusplus } diff --git a/lib/webfuse/impl/jsonrpc/proxy_finished_fn.h b/lib/webfuse/impl/jsonrpc/proxy_finished_fn.h index 0ea5a97..300f5fc 100644 --- a/lib/webfuse/impl/jsonrpc/proxy_finished_fn.h +++ b/lib/webfuse/impl/jsonrpc/proxy_finished_fn.h @@ -1,17 +1,18 @@ #ifndef WF_IMPL_JSONRPC_PROXY_FINISHED_FN_H #define WF_IMPL_JSONRPC_PROXY_FINISHED_FN_H -#include - #ifdef __cplusplus extern "C" { #endif +struct wf_jsonrpc_error; +struct wf_json; + typedef void wf_jsonrpc_proxy_finished_fn( void * user_data, - json_t const * result, - json_t const * error); + struct wf_json const * result, + struct wf_jsonrpc_error const * error); #ifdef __cplusplus } diff --git a/lib/webfuse/impl/jsonrpc/request.c b/lib/webfuse/impl/jsonrpc/request.c index 93e2e70..df443eb 100644 --- a/lib/webfuse/impl/jsonrpc/request.c +++ b/lib/webfuse/impl/jsonrpc/request.c @@ -1,9 +1,16 @@ #include "webfuse/impl/jsonrpc/request.h" #include "webfuse/impl/jsonrpc/error.h" +#include "webfuse/impl/json/writer.h" +#include "webfuse/impl/json/node.h" +#include "webfuse/impl/jsonrpc/response_writer.h" +#include "webfuse/impl/message.h" + +#include #include struct wf_jsonrpc_request { + struct wf_jsonrpc_response_writer * writer; int id; wf_jsonrpc_send_fn * send; void * user_data; @@ -11,14 +18,16 @@ struct wf_jsonrpc_request bool wf_impl_jsonrpc_is_request( - json_t * message) + struct wf_json const * message) { - json_t * id = json_object_get(message, "id"); - json_t * method = json_object_get(message, "method"); - json_t * params = json_object_get(message, "params"); + if (NULL == message) { return false; } - return (json_is_integer(id) && json_is_string(method) && - (json_is_array(params) || json_is_object(params))); + struct wf_json const * id = wf_impl_json_object_get(message, "id"); + struct wf_json const * method = wf_impl_json_object_get(message, "method"); + struct wf_json const * params = wf_impl_json_object_get(message, "params"); + + return ( (wf_impl_json_is_int(id)) && (wf_impl_json_is_string(method)) && + ( (wf_impl_json_is_array(params)) || (wf_impl_json_is_object(params)) )); } @@ -29,6 +38,7 @@ wf_impl_jsonrpc_request_create( void * user_data) { struct wf_jsonrpc_request * request = malloc(sizeof(struct wf_jsonrpc_request)); + request->writer = wf_impl_jsonrpc_response_writer_create(id); request->id = id; request->send = send; request->user_data = user_data; @@ -40,6 +50,7 @@ void wf_impl_jsonrpc_request_dispose( struct wf_jsonrpc_request * request) { + wf_impl_jsonrpc_response_writer_dispose(request->writer); free(request); } @@ -50,18 +61,21 @@ wf_impl_jsonrpc_request_get_userdata( return request->user_data; } +struct wf_jsonrpc_response_writer * +wf_impl_jsonrpc_request_get_response_writer( + struct wf_jsonrpc_request * request) +{ + return request->writer; +} + void wf_impl_jsonrpc_respond( - struct wf_jsonrpc_request * request, - json_t * result) + struct wf_jsonrpc_request * request) { - json_t * response = json_object(); - json_object_set_new(response, "result", result); - json_object_set_new(response, "id", json_integer(request->id)); + struct wf_message * response = wf_impl_jsonrpc_response_writer_take_message(request->writer); request->send(response, request->user_data); - json_decref(response); wf_impl_jsonrpc_request_dispose(request); } @@ -70,11 +84,21 @@ void wf_impl_jsonrpc_respond_error( int code, char const * message) { - json_t * response = json_object(); - json_object_set_new(response, "error", wf_impl_jsonrpc_error(code, message)); - json_object_set_new(response, "id", json_integer(request->id)); + struct wf_json_writer * writer = wf_impl_json_writer_create(128, LWS_PRE); + wf_impl_json_write_object_begin(writer); + wf_impl_json_write_object_begin_object(writer, "error"); + wf_impl_json_write_object_int(writer, "code", code); + wf_impl_json_write_object_string(writer, "message", message); + wf_impl_json_write_object_end(writer); + wf_impl_json_write_object_int(writer, "id", request->id); + wf_impl_json_write_object_end(writer); + size_t length; + char * data = wf_impl_json_writer_take(writer, &length); + wf_impl_json_writer_dispose(writer); + + struct wf_message * response = wf_impl_message_create(data, length); request->send(response, request->user_data); - json_decref(response); + wf_impl_jsonrpc_request_dispose(request); } diff --git a/lib/webfuse/impl/jsonrpc/request.h b/lib/webfuse/impl/jsonrpc/request.h index 747c480..bd4355d 100644 --- a/lib/webfuse/impl/jsonrpc/request.h +++ b/lib/webfuse/impl/jsonrpc/request.h @@ -11,7 +11,6 @@ using std::size_t; #endif -#include #include "webfuse/impl/jsonrpc/send_fn.h" #ifdef __cplusplus @@ -20,9 +19,11 @@ extern "C" #endif struct wf_jsonrpc_request; +struct wf_jsonrpc_response_writer; +struct wf_json; extern bool wf_impl_jsonrpc_is_request( - json_t * message); + struct wf_json const * message); extern struct wf_jsonrpc_request * wf_impl_jsonrpc_request_create( @@ -36,9 +37,12 @@ extern void wf_impl_jsonrpc_request_dispose( extern void * wf_impl_jsonrpc_request_get_userdata( struct wf_jsonrpc_request * request); +extern struct wf_jsonrpc_response_writer * +wf_impl_jsonrpc_request_get_response_writer( + struct wf_jsonrpc_request * request); + extern void wf_impl_jsonrpc_respond( - struct wf_jsonrpc_request * request, - json_t * result); + struct wf_jsonrpc_request * request); extern void wf_impl_jsonrpc_respond_error( struct wf_jsonrpc_request * request, diff --git a/lib/webfuse/impl/jsonrpc/response.c b/lib/webfuse/impl/jsonrpc/response.c index 7661828..ac430fa 100644 --- a/lib/webfuse/impl/jsonrpc/response.c +++ b/lib/webfuse/impl/jsonrpc/response.c @@ -1,54 +1,57 @@ #include "webfuse/impl/jsonrpc/response_intern.h" #include "webfuse/impl/jsonrpc/error.h" +#include "webfuse/impl/json/node.h" #include "webfuse/status.h" bool wf_impl_jsonrpc_is_response( - json_t * message) + struct wf_json const * message) { - json_t * id = json_object_get(message, "id"); - json_t * err = json_object_get(message, "error"); - json_t * result = json_object_get(message, "result"); + if (NULL == message) { return false; } - return (json_is_integer(id) && - (json_is_object(err) || (NULL != result))); + struct wf_json const * id = wf_impl_json_object_get(message, "id"); + struct wf_json const * err = wf_impl_json_object_get(message, "error"); + struct wf_json const * result = wf_impl_json_object_get(message, "result"); + + return ((wf_impl_json_is_int(id)) && + ((wf_impl_json_is_object(err)) || (!wf_impl_json_is_undefined(result)))); } void wf_impl_jsonrpc_response_init( struct wf_jsonrpc_response * result, - json_t * response) + struct wf_json const * response) { result->id = -1; result->result = NULL; result->error = NULL; - json_t * id_holder = json_object_get(response, "id"); - if (!json_is_integer(id_holder)) + struct wf_json const * id_holder = wf_impl_json_object_get(response, "id"); + if (!wf_impl_json_is_int(id_holder)) { result->error = wf_impl_jsonrpc_error(WF_BAD_FORMAT, "invalid format: missing id"); return; } - result->id = json_integer_value(id_holder); - result->result = json_object_get(response, "result"); - if (NULL != result->result) + result->id = wf_impl_json_int_get(id_holder); + result->result = wf_impl_json_object_get(response, "result"); + if (wf_impl_json_is_undefined(result->result)) { - json_incref(result->result); - } - else - { - json_t * error = json_object_get(response, "error"); - if ((json_is_object(error)) && (json_is_integer(json_object_get(error, "code")))) + int code = WF_BAD_FORMAT; + char const * message = "invalid format: invalid error object"; + + struct wf_json const * error = wf_impl_json_object_get(response, "error"); + struct wf_json const * code_holder = wf_impl_json_object_get(error, "code"); + if (wf_impl_json_is_int(code_holder)) { - result->error = error; - json_incref(result->error); - } - else - { - result->error = wf_impl_jsonrpc_error(WF_BAD_FORMAT, "invalid format: invalid error object"); + code = wf_impl_json_int_get(code_holder); + struct wf_json const * message_holder = wf_impl_json_object_get(error, "message"); + message = wf_impl_json_string_get(message_holder); } + + result->error = wf_impl_jsonrpc_error(code, message); + result->result = NULL; } } @@ -56,13 +59,5 @@ void wf_impl_jsonrpc_response_cleanup( struct wf_jsonrpc_response * response) { - if (NULL != response->result) - { - json_decref(response->result); - } - - if (NULL != response->error) - { - json_decref(response->error); - } + wf_impl_jsonrpc_error_dispose(response->error); } diff --git a/lib/webfuse/impl/jsonrpc/response.h b/lib/webfuse/impl/jsonrpc/response.h index 2c50000..b94e8bb 100644 --- a/lib/webfuse/impl/jsonrpc/response.h +++ b/lib/webfuse/impl/jsonrpc/response.h @@ -5,15 +5,15 @@ #include #endif -#include - #ifdef __cplusplus extern "C" { #endif +struct wf_json; + extern bool wf_impl_jsonrpc_is_response( - json_t * message); + struct wf_json const * message); #ifdef __cplusplus } diff --git a/lib/webfuse/impl/jsonrpc/response_intern.h b/lib/webfuse/impl/jsonrpc/response_intern.h index 9c48e2b..e4bda75 100644 --- a/lib/webfuse/impl/jsonrpc/response_intern.h +++ b/lib/webfuse/impl/jsonrpc/response_intern.h @@ -14,16 +14,19 @@ using std::size_t; extern "C" { #endif +struct wf_jsonrpc_error; +struct wf_json; + struct wf_jsonrpc_response { - json_t * result; - json_t * error; + struct wf_json const * result; + struct wf_jsonrpc_error * error; int id; }; extern void wf_impl_jsonrpc_response_init( struct wf_jsonrpc_response * response, - json_t * message); + struct wf_json const * message); extern void wf_impl_jsonrpc_response_cleanup( struct wf_jsonrpc_response * response); diff --git a/lib/webfuse/impl/jsonrpc/response_writer.c b/lib/webfuse/impl/jsonrpc/response_writer.c new file mode 100644 index 0000000..67248a0 --- /dev/null +++ b/lib/webfuse/impl/jsonrpc/response_writer.c @@ -0,0 +1,67 @@ +#include "webfuse/impl/jsonrpc/response_writer.h" +#include "webfuse/impl/message.h" +#include "webfuse/impl/json/writer.h" + +#include +#include + +#define WF_RESPONSE_WRITER_DEFAULT_MESSAGE_SIZE 1024 + +struct wf_jsonrpc_response_writer +{ + struct wf_json_writer * json_writer; + int id; +}; + +struct wf_jsonrpc_response_writer * +wf_impl_jsonrpc_response_writer_create(int id) +{ + struct wf_jsonrpc_response_writer * writer = malloc(sizeof(struct wf_jsonrpc_response_writer)); + writer->json_writer = wf_impl_json_writer_create(WF_RESPONSE_WRITER_DEFAULT_MESSAGE_SIZE, LWS_PRE); + writer->id = id; + + wf_impl_json_write_object_begin(writer->json_writer); + wf_impl_json_write_object_begin_object(writer->json_writer, "result"); + + return writer; +} + +void +wf_impl_jsonrpc_response_writer_dispose( + struct wf_jsonrpc_response_writer * writer) +{ + wf_impl_json_writer_dispose(writer->json_writer); + free(writer); +} + +struct wf_message * +wf_impl_jsonrpc_response_writer_take_message( + struct wf_jsonrpc_response_writer * writer) +{ + wf_impl_json_write_object_end(writer->json_writer); + wf_impl_json_write_object_int(writer->json_writer, "id", writer->id); + wf_impl_json_write_object_end(writer->json_writer); + + size_t length; + char * data = wf_impl_json_writer_take(writer->json_writer, &length); + + return wf_impl_message_create(data, length); +} + +void +wf_impl_jsonrpc_response_add_int( + struct wf_jsonrpc_response_writer * writer, + char const * key, + int value) +{ + wf_impl_json_write_object_int(writer->json_writer, key, value); +} + +void +wf_impl_jsonrpc_response_add_string( + struct wf_jsonrpc_response_writer * writer, + char const * key, + char const * value) +{ + wf_impl_json_write_object_string(writer->json_writer, key, value); +} diff --git a/lib/webfuse/impl/jsonrpc/response_writer.h b/lib/webfuse/impl/jsonrpc/response_writer.h new file mode 100644 index 0000000..95fb8b8 --- /dev/null +++ b/lib/webfuse/impl/jsonrpc/response_writer.h @@ -0,0 +1,40 @@ +#ifndef WF_IMPL_JSONRPC_RESPONSE_WRITER_H +#define WF_IMPL_JSONRPC_RESPONSE_WRITER_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wf_jsonrpc_response_writer; +struct wf_messge; + +extern struct wf_jsonrpc_response_writer * +wf_impl_jsonrpc_response_writer_create(int id); + +extern void +wf_impl_jsonrpc_response_writer_dispose( + struct wf_jsonrpc_response_writer * writer); + +extern struct wf_message * +wf_impl_jsonrpc_response_writer_take_message( + struct wf_jsonrpc_response_writer * writer); + +extern void +wf_impl_jsonrpc_response_add_int( + struct wf_jsonrpc_response_writer * writer, + char const * key, + int value); + +extern void +wf_impl_jsonrpc_response_add_string( + struct wf_jsonrpc_response_writer * writer, + char const * key, + char const * value); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/webfuse/impl/jsonrpc/send_fn.h b/lib/webfuse/impl/jsonrpc/send_fn.h index 3c448fd..3074d96 100644 --- a/lib/webfuse/impl/jsonrpc/send_fn.h +++ b/lib/webfuse/impl/jsonrpc/send_fn.h @@ -5,15 +5,16 @@ #include #endif -#include #ifdef __cplusplus extern "C" { #endif +struct wf_message; + typedef bool wf_jsonrpc_send_fn( - json_t * request, + struct wf_message * request, void * user_data); #ifdef __cplusplus diff --git a/lib/webfuse/impl/jsonrpc/server.c b/lib/webfuse/impl/jsonrpc/server.c index e366ddf..fba5acc 100644 --- a/lib/webfuse/impl/jsonrpc/server.c +++ b/lib/webfuse/impl/jsonrpc/server.c @@ -1,6 +1,7 @@ #include "webfuse/impl/jsonrpc/server.h" #include "webfuse/impl/jsonrpc/method.h" #include "webfuse/impl/jsonrpc/request.h" +#include "webfuse/impl/json/node.h" #include "webfuse/status.h" #include "webfuse/impl/util/util.h" @@ -70,7 +71,7 @@ void wf_impl_jsonrpc_server_add( static void wf_impl_jsonrpc_server_invalid_method_invoke( struct wf_jsonrpc_request * request, char const * WF_UNUSED_PARAM(method_name), - json_t * WF_UNUSED_PARAM(params), + struct wf_json const * WF_UNUSED_PARAM(params), void * WF_UNUSED_PARAM(user_data)) { wf_impl_jsonrpc_respond_error(request, WF_BAD_NOTIMPLEMENTED, "not implemented"); @@ -105,20 +106,20 @@ wf_impl_jsonrpc_server_get_method( void wf_impl_jsonrpc_server_process( struct wf_jsonrpc_server * server, - json_t * request_data, + struct wf_json const * request_data, wf_jsonrpc_send_fn * send, void * user_data) { - json_t * method_holder = json_object_get(request_data, "method"); - json_t * params = json_object_get(request_data, "params"); - json_t * id_holder = json_object_get(request_data, "id"); + struct wf_json const * method_holder = wf_impl_json_object_get(request_data, "method"); + struct wf_json const * params = wf_impl_json_object_get(request_data, "params"); + struct wf_json const * id_holder = wf_impl_json_object_get(request_data, "id"); - if (json_is_string(method_holder) && - (json_is_array(params) || (json_is_object(params))) && - json_is_integer(id_holder)) + if ((wf_impl_json_is_string(method_holder)) && + ((wf_impl_json_is_array(params)) || (wf_impl_json_is_object(params))) && + (wf_impl_json_is_int(id_holder))) { - char const * method_name = json_string_value(method_holder); - int id = json_integer_value(id_holder); + char const * method_name = wf_impl_json_string_get(method_holder); + int id = wf_impl_json_int_get(id_holder); struct wf_jsonrpc_request * request = wf_impl_jsonrpc_request_create(id, send, user_data); struct wf_jsonrpc_method const * method = wf_impl_jsonrpc_server_get_method(server, method_name); diff --git a/lib/webfuse/impl/jsonrpc/server.h b/lib/webfuse/impl/jsonrpc/server.h index 6f60914..a76addb 100644 --- a/lib/webfuse/impl/jsonrpc/server.h +++ b/lib/webfuse/impl/jsonrpc/server.h @@ -8,7 +8,6 @@ #include #endif -#include #include "webfuse/impl/jsonrpc/method_invoke_fn.h" #include "webfuse/impl/jsonrpc/send_fn.h" @@ -18,6 +17,7 @@ extern "C" #endif struct wf_jsonrpc_server; +struct wf_json; extern struct wf_jsonrpc_server * wf_impl_jsonrpc_server_create(void); @@ -34,7 +34,7 @@ extern void wf_impl_jsonrpc_server_add( extern void wf_impl_jsonrpc_server_process( struct wf_jsonrpc_server * server, - json_t * request, + struct wf_json const * request, wf_jsonrpc_send_fn * send, void * user_data); diff --git a/lib/webfuse/impl/message.c b/lib/webfuse/impl/message.c index 8df799d..c5bf0a7 100644 --- a/lib/webfuse/impl/message.c +++ b/lib/webfuse/impl/message.c @@ -3,26 +3,23 @@ #include #include -extern struct wf_message * wf_impl_message_create(json_t const * value) +extern struct wf_message * +wf_impl_message_create( + char * data, + size_t length) { - struct wf_message * message = NULL; - size_t const length = json_dumpb(value, NULL, 0, JSON_COMPACT); - - if (0 < length) - { - char * data = malloc(sizeof(struct wf_message) + LWS_PRE + length); - message = (struct wf_message *) data; - message->data = &data[sizeof(struct wf_message) + LWS_PRE]; - message->length = length; - - json_dumpb(value, message->data, length, JSON_COMPACT); - } + struct wf_message * message = malloc(sizeof(struct wf_message)); + message->data = data; + message->length = length; return message; } -void wf_impl_message_dispose( +void +wf_impl_message_dispose( struct wf_message * message) { + char * raw_data = message->data - LWS_PRE; + free(raw_data); free(message); } diff --git a/lib/webfuse/impl/message.h b/lib/webfuse/impl/message.h index 8e75437..1cefdf7 100644 --- a/lib/webfuse/impl/message.h +++ b/lib/webfuse/impl/message.h @@ -8,7 +8,6 @@ using std::size_t; #endif -#include #include "webfuse/impl/util/slist.h" struct wf_message @@ -23,10 +22,13 @@ extern "C" { #endif -extern struct wf_message * wf_impl_message_create( - json_t const * value); +extern struct wf_message * +wf_impl_message_create( + char * value, + size_t length); -extern void wf_impl_message_dispose( +extern void +wf_impl_message_dispose( struct wf_message * message); #ifdef __cplusplus diff --git a/lib/webfuse/impl/operation/close.c b/lib/webfuse/impl/operation/close.c index 159b775..b8e40ed 100644 --- a/lib/webfuse/impl/operation/close.c +++ b/lib/webfuse/impl/operation/close.c @@ -3,7 +3,6 @@ #include #include -#include #include "webfuse/impl/jsonrpc/proxy.h" diff --git a/lib/webfuse/impl/operation/getattr.c b/lib/webfuse/impl/operation/getattr.c index a943bc9..3384095 100644 --- a/lib/webfuse/impl/operation/getattr.c +++ b/lib/webfuse/impl/operation/getattr.c @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -11,11 +12,12 @@ #include "webfuse/impl/jsonrpc/proxy.h" #include "webfuse/impl/util/json_util.h" #include "webfuse/impl/util/util.h" +#include "webfuse/impl/json/node.h" void wf_impl_operation_getattr_finished( void * user_data, - json_t const * result, - json_t const * error) + struct wf_json const * result, + struct wf_jsonrpc_error const * error) { wf_status status = wf_impl_jsonrpc_get_status(error); struct wf_impl_operation_getattr_context * context = user_data; @@ -23,15 +25,15 @@ void wf_impl_operation_getattr_finished( struct stat buffer; if (NULL != result) { - json_t * mode_holder = json_object_get(result, "mode"); - json_t * type_holder = json_object_get(result, "type"); - if ((json_is_integer(mode_holder)) && (json_is_string(type_holder))) + struct wf_json const * mode_holder = wf_impl_json_object_get(result, "mode"); + struct wf_json const * type_holder = wf_impl_json_object_get(result, "type"); + if ((wf_impl_json_is_int(mode_holder)) && (wf_impl_json_is_string(type_holder))) { memset(&buffer, 0, sizeof(struct stat)); buffer.st_ino = context->inode; - buffer.st_mode = json_integer_value(mode_holder) & 0555; - char const * type = json_string_value(type_holder); + buffer.st_mode = wf_impl_json_int_get(mode_holder) & 0555; + char const * type = wf_impl_json_string_get(type_holder); if (0 == strcmp("file", type)) { buffer.st_mode |= S_IFREG; diff --git a/lib/webfuse/impl/operation/getattr.h b/lib/webfuse/impl/operation/getattr.h index b3841a5..4d24e8d 100644 --- a/lib/webfuse/impl/operation/getattr.h +++ b/lib/webfuse/impl/operation/getattr.h @@ -3,7 +3,6 @@ #include "webfuse/impl/fuse_wrapper.h" -#include #include #ifdef __cplusplus @@ -11,6 +10,9 @@ extern "C" { #endif +struct wf_jsonrpc_error; +struct wf_json; + struct wf_impl_operation_getattr_context { fuse_req_t request; @@ -22,8 +24,8 @@ struct wf_impl_operation_getattr_context extern void wf_impl_operation_getattr_finished( void * user_data, - json_t const * result, - json_t const * error); + struct wf_json const * result, + struct wf_jsonrpc_error const * error); extern void wf_impl_operation_getattr ( fuse_req_t request, diff --git a/lib/webfuse/impl/operation/lookup.c b/lib/webfuse/impl/operation/lookup.c index 99f8fbb..6a72382 100644 --- a/lib/webfuse/impl/operation/lookup.c +++ b/lib/webfuse/impl/operation/lookup.c @@ -12,13 +12,14 @@ #include #include "webfuse/impl/jsonrpc/proxy.h" +#include "webfuse/impl/json/node.h" #include "webfuse/impl/util/json_util.h" #include "webfuse/impl/util/util.h" void wf_impl_operation_lookup_finished( void * user_data, - json_t const * result, - json_t const * error + struct wf_json const * result, + struct wf_jsonrpc_error const * error ) { wf_status status = wf_impl_jsonrpc_get_status(error); @@ -27,19 +28,19 @@ void wf_impl_operation_lookup_finished( if (NULL != result) { - json_t * inode_holder = json_object_get(result, "inode"); - json_t * mode_holder = json_object_get(result, "mode"); - json_t * type_holder = json_object_get(result, "type"); - if ((json_is_integer(inode_holder)) && - (json_is_integer(mode_holder)) && - (json_is_string(type_holder))) + struct wf_json const * inode_holder = wf_impl_json_object_get(result, "inode"); + struct wf_json const * mode_holder = wf_impl_json_object_get(result, "mode"); + struct wf_json const * type_holder = wf_impl_json_object_get(result, "type"); + if ((wf_impl_json_is_int(inode_holder)) && + (wf_impl_json_is_int(mode_holder)) && + (wf_impl_json_is_string(type_holder))) { memset(&buffer, 0, sizeof(struct stat)); - buffer.ino = json_integer_value(inode_holder); + buffer.ino = wf_impl_json_int_get(inode_holder); buffer.attr.st_ino = buffer.ino; - buffer.attr.st_mode = json_integer_value(mode_holder) & 0555; - char const * type = json_string_value(type_holder); + buffer.attr.st_mode = wf_impl_json_int_get(mode_holder) & 0555; + char const * type = wf_impl_json_string_get(type_holder); if (0 == strcmp("file", type)) { buffer.attr.st_mode |= S_IFREG; diff --git a/lib/webfuse/impl/operation/lookup.h b/lib/webfuse/impl/operation/lookup.h index ba738b7..4f7d4f9 100644 --- a/lib/webfuse/impl/operation/lookup.h +++ b/lib/webfuse/impl/operation/lookup.h @@ -3,7 +3,6 @@ #include "webfuse/impl/fuse_wrapper.h" -#include #include #ifdef __cplusplus @@ -11,6 +10,9 @@ extern "C" { #endif +struct wf_jsonrpc_error; +struct wf_json; + struct wf_impl_operation_lookup_context { fuse_req_t request; @@ -21,8 +23,8 @@ struct wf_impl_operation_lookup_context extern void wf_impl_operation_lookup_finished( void * user_data, - json_t const * result, - json_t const * error); + struct wf_json const * result, + struct wf_jsonrpc_error const * error); extern void wf_impl_operation_lookup ( fuse_req_t req, diff --git a/lib/webfuse/impl/operation/open.c b/lib/webfuse/impl/operation/open.c index d947678..166ddbd 100644 --- a/lib/webfuse/impl/operation/open.c +++ b/lib/webfuse/impl/operation/open.c @@ -2,6 +2,7 @@ #include "webfuse/impl/operation/context.h" #include "webfuse/impl/jsonrpc/proxy.h" +#include "webfuse/impl/json/node.h" #include "webfuse/impl/util/util.h" #include "webfuse/status.h" #include "webfuse/impl/util/json_util.h" @@ -11,8 +12,8 @@ void wf_impl_operation_open_finished( void * user_data, - json_t const * result, - json_t const * error) + struct wf_json const * result, + struct wf_jsonrpc_error const * error) { wf_status status = wf_impl_jsonrpc_get_status(error); fuse_req_t request = user_data; @@ -21,10 +22,10 @@ void wf_impl_operation_open_finished( if (NULL != result) { - json_t * handle_holder = json_object_get(result, "handle"); - if (json_is_integer(handle_holder)) + struct wf_json const * handle_holder = wf_impl_json_object_get(result, "handle"); + if (wf_impl_json_is_int(handle_holder)) { - file_info.fh = json_integer_value(handle_holder); + file_info.fh = wf_impl_json_int_get(handle_holder); } else { diff --git a/lib/webfuse/impl/operation/open.h b/lib/webfuse/impl/operation/open.h index 1ef6104..72a6ddd 100644 --- a/lib/webfuse/impl/operation/open.h +++ b/lib/webfuse/impl/operation/open.h @@ -2,13 +2,15 @@ #define WF_ADAPTER_IMPL_OPERATION_OPEN_H #include "webfuse/impl/fuse_wrapper.h" -#include #ifdef __cplusplus extern "C" { #endif +struct wf_jsonrpc_error; +struct wf_json; + extern void wf_impl_operation_open( fuse_req_t request, fuse_ino_t inode, @@ -16,8 +18,8 @@ extern void wf_impl_operation_open( extern void wf_impl_operation_open_finished( void * user_data, - json_t const * result, - json_t const * error); + struct wf_json const * result, + struct wf_jsonrpc_error const * error); #ifdef __cplusplus } diff --git a/lib/webfuse/impl/operation/read.c b/lib/webfuse/impl/operation/read.c index 3721f1b..25754b8 100644 --- a/lib/webfuse/impl/operation/read.c +++ b/lib/webfuse/impl/operation/read.c @@ -2,43 +2,40 @@ #include "webfuse/impl/operation/context.h" #include +#include #include #include -#include #include "webfuse/impl/jsonrpc/proxy.h" +#include "webfuse/impl/json/node.h" #include "webfuse/impl/util/base64.h" #include "webfuse/impl/util/json_util.h" // do not read chunks larger than 1 MByte #define WF_MAX_READ_LENGTH (1024 * 1024) -char * wf_impl_fill_buffer( - char const * data, +char * wf_impl_operation_read_transform( + char * data, size_t data_size, char const * format, size_t count, wf_status * status) { *status = WF_GOOD; - char * buffer = malloc(count); + char * buffer = data; if (0 < count) { if (0 == strcmp("identity", format)) { - if (count == data_size) - { - memcpy(buffer, data, count); - } - else + if (count != data_size) { *status = WF_BAD; } } else if (0 == strcmp("base64", format)) { - size_t result = wf_impl_base64_decode(data, data_size, (uint8_t *) buffer, count); + size_t result = wf_impl_base64_decode(data, data_size, (uint8_t *) data, count); if (result != count) { *status = WF_BAD; @@ -50,19 +47,13 @@ char * wf_impl_fill_buffer( } } - if (WF_GOOD != *status) - { - free(buffer); - buffer = NULL; - } - return buffer; } void wf_impl_operation_read_finished( void * user_data, - json_t const * result, - json_t const * error) + struct wf_json const * result, + struct wf_jsonrpc_error const * error) { wf_status status = wf_impl_jsonrpc_get_status(error); fuse_req_t request = user_data; @@ -71,20 +62,20 @@ void wf_impl_operation_read_finished( size_t length = 0; if (NULL != result) { - json_t * data_holder = json_object_get(result, "data"); - json_t * format_holder = json_object_get(result, "format"); - json_t * count_holder = json_object_get(result, "count"); + struct wf_json const * data_holder = wf_impl_json_object_get(result, "data"); + struct wf_json const * format_holder = wf_impl_json_object_get(result, "format"); + struct wf_json const * count_holder = wf_impl_json_object_get(result, "count"); - if (json_is_string(data_holder) && - json_is_string(format_holder) && - json_is_integer(count_holder)) + if ((wf_impl_json_is_string(data_holder)) && + (wf_impl_json_is_string(format_holder)) && + (wf_impl_json_is_int(count_holder))) { - char const * const data = json_string_value(data_holder); - size_t const data_size = json_string_length(data_holder); - char const * const format = json_string_value(format_holder); - length = (size_t) json_integer_value(count_holder); + char * const data = (char*) wf_impl_json_string_get(data_holder); + size_t const data_size = wf_impl_json_string_size(data_holder); + char const * const format = wf_impl_json_string_get(format_holder); + length = (size_t) wf_impl_json_int_get(count_holder); - buffer = wf_impl_fill_buffer(data, data_size, format, length, &status); + buffer = wf_impl_operation_read_transform(data, data_size, format, length, &status); } else { @@ -100,9 +91,6 @@ void wf_impl_operation_read_finished( { fuse_reply_err(request, ENOENT); } - - free(buffer); - } void wf_impl_operation_read( diff --git a/lib/webfuse/impl/operation/read.h b/lib/webfuse/impl/operation/read.h index e675492..20c4859 100644 --- a/lib/webfuse/impl/operation/read.h +++ b/lib/webfuse/impl/operation/read.h @@ -4,20 +4,21 @@ #include "webfuse/impl/fuse_wrapper.h" #include "webfuse/status.h" -#include - #ifdef __cplusplus extern "C" { #endif +struct wf_jsonrpc_error; +struct wf_json; + extern void wf_impl_operation_read( fuse_req_t request, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi); -extern char * wf_impl_fill_buffer( - char const * data, +extern char * wf_impl_operation_read_transform( + char * data, size_t data_size, char const * format, size_t count, @@ -25,8 +26,8 @@ extern char * wf_impl_fill_buffer( extern void wf_impl_operation_read_finished( void * user_data, - json_t const * result, - json_t const * error); + struct wf_json const * result, + struct wf_jsonrpc_error const * error); #ifdef __cplusplus diff --git a/lib/webfuse/impl/operation/readdir.c b/lib/webfuse/impl/operation/readdir.c index 78f99ab..a338950 100644 --- a/lib/webfuse/impl/operation/readdir.c +++ b/lib/webfuse/impl/operation/readdir.c @@ -10,6 +10,7 @@ #include #include "webfuse/impl/jsonrpc/proxy.h" +#include "webfuse/impl/json/node.h" #include "webfuse/impl/util/util.h" #include "webfuse/impl/util/json_util.h" @@ -68,8 +69,8 @@ static size_t wf_impl_min(size_t a, size_t b) void wf_impl_operation_readdir_finished( void * user_data, - json_t const * result, - json_t const * error) + struct wf_json const * result, + struct wf_jsonrpc_error const * error) { wf_status status = wf_impl_jsonrpc_get_status(error); struct wf_impl_operation_readdir_context * context = user_data; @@ -77,21 +78,21 @@ void wf_impl_operation_readdir_finished( struct wf_impl_dirbuffer buffer; wf_impl_dirbuffer_init(&buffer); - if (json_is_array(result)) + if ((NULL != result) && (wf_impl_json_is_array(result))) { - size_t const count = json_array_size(result); + size_t const count = wf_impl_json_array_size(result); for(size_t i = 0; i < count; i++) { - json_t * entry =json_array_get(result, i); - if (json_is_object(entry)) + struct wf_json const * entry = wf_impl_json_array_get(result, i); + if (wf_impl_json_is_object(entry)) { - json_t * name_holder = json_object_get(entry, "name"); - json_t * inode_holder = json_object_get(entry, "inode"); + struct wf_json const * name_holder = wf_impl_json_object_get(entry, "name"); + struct wf_json const * inode_holder = wf_impl_json_object_get(entry, "inode"); - if ((json_is_string(name_holder)) && (json_is_integer(inode_holder))) + if ((wf_impl_json_is_string(name_holder)) && (wf_impl_json_is_int(inode_holder))) { - char const * name = json_string_value(name_holder); - fuse_ino_t entry_inode = (fuse_ino_t) json_integer_value(inode_holder); + char const * name = wf_impl_json_string_get(name_holder); + fuse_ino_t entry_inode = (fuse_ino_t) wf_impl_json_int_get(inode_holder); wf_impl_dirbuffer_add(context->request, &buffer, name, entry_inode); } else diff --git a/lib/webfuse/impl/operation/readdir.h b/lib/webfuse/impl/operation/readdir.h index b5bc097..ee7438f 100644 --- a/lib/webfuse/impl/operation/readdir.h +++ b/lib/webfuse/impl/operation/readdir.h @@ -2,13 +2,15 @@ #define WF_ADAPTER_IMPL_OPERATION_READDIR_H #include "webfuse/impl/fuse_wrapper.h" -#include #ifdef __cplusplus extern "C" { #endif +struct wf_jsonrpc_error; +struct wf_json; + struct wf_impl_operation_readdir_context { fuse_req_t request; @@ -25,8 +27,8 @@ extern void wf_impl_operation_readdir ( extern void wf_impl_operation_readdir_finished( void * user_data, - json_t const * result, - json_t const * error); + struct wf_json const * result, + struct wf_jsonrpc_error const * error); #ifdef __cplusplus } diff --git a/lib/webfuse/impl/server_protocol.c b/lib/webfuse/impl/server_protocol.c index 48792c0..d411d0f 100644 --- a/lib/webfuse/impl/server_protocol.c +++ b/lib/webfuse/impl/server_protocol.c @@ -12,6 +12,8 @@ #include "webfuse/impl/status.h" #include "webfuse/impl/jsonrpc/request.h" +#include "webfuse/impl/jsonrpc/response_writer.h" +#include "webfuse/impl/json/node.h" #include "webfuse/impl/timer/manager.h" #include "webfuse/impl/timer/timer.h" @@ -113,17 +115,17 @@ void wf_impl_server_protocol_init_lws( static void wf_impl_server_protocol_authenticate( struct wf_jsonrpc_request * request, char const * WF_UNUSED_PARAM(method_name), - json_t * params, + struct wf_json const * params, void * WF_UNUSED_PARAM(user_data)) { bool result = false; - json_t * type_holder = json_array_get(params, 0); - json_t * creds_holder = json_array_get(params, 1); + struct wf_json const * type_holder = wf_impl_json_array_get(params, 0); + struct wf_json const * creds_holder = wf_impl_json_array_get(params, 1); - if (json_is_string(type_holder) && json_is_object(creds_holder)) + if ((wf_impl_json_is_string(type_holder)) && (wf_impl_json_is_object(creds_holder))) { - char const * type = json_string_value(type_holder); + char const * type = wf_impl_json_string_get(type_holder); struct wf_credentials creds; wf_impl_credentials_init(&creds, type, creds_holder); @@ -136,8 +138,7 @@ static void wf_impl_server_protocol_authenticate( if (result) { - json_t * result = json_object(); - wf_impl_jsonrpc_respond(request, result); + wf_impl_jsonrpc_respond(request); } else { @@ -163,7 +164,7 @@ static bool wf_impl_server_protocol_check_name(char const * value) static void wf_impl_server_protocol_add_filesystem( struct wf_jsonrpc_request * request, char const * WF_UNUSED_PARAM(method_name), - json_t * params, + struct wf_json const * params, void * WF_UNUSED_PARAM(user_data)) { struct wf_impl_session * session = wf_impl_jsonrpc_request_get_userdata(request); @@ -172,10 +173,10 @@ static void wf_impl_server_protocol_add_filesystem( char const * name = NULL; if (WF_GOOD == status) { - json_t * name_holder = json_array_get(params, 0); - if (json_is_string(name_holder)) + struct wf_json const * name_holder = wf_impl_json_array_get(params, 0); + if (wf_impl_json_is_string(name_holder)) { - name = json_string_value(name_holder); + name = wf_impl_json_string_get(name_holder); if (wf_impl_server_protocol_check_name(name)) { bool const success = wf_impl_session_add_filesystem(session, name); @@ -198,16 +199,14 @@ static void wf_impl_server_protocol_add_filesystem( if (WF_GOOD == status) { - json_t * result = json_object(); - json_object_set_new(result, "id", json_string(name)); - wf_impl_jsonrpc_respond(request, result); + struct wf_jsonrpc_response_writer * writer = wf_impl_jsonrpc_request_get_response_writer(request); + wf_impl_jsonrpc_response_add_string(writer, "id", name); + wf_impl_jsonrpc_respond(request); } else { wf_impl_jsonrpc_respond_error(request, status, wf_impl_status_tostring(status)); } - - } void wf_impl_server_protocol_init( diff --git a/lib/webfuse/impl/session.c b/lib/webfuse/impl/session.c index 5d3d078..f1fd36b 100644 --- a/lib/webfuse/impl/session.c +++ b/lib/webfuse/impl/session.c @@ -11,6 +11,7 @@ #include "webfuse/impl/jsonrpc/proxy.h" #include "webfuse/impl/jsonrpc/request.h" #include "webfuse/impl/jsonrpc/response.h" +#include "webfuse/impl/json/doc.h" #include #include @@ -20,15 +21,13 @@ #define WF_DEFAULT_MESSAGE_SIZE (8 * 1024) static bool wf_impl_session_send( - json_t * request, + struct wf_message * message, void * user_data) { struct wf_impl_session * session = user_data; - struct wf_message * message = wf_impl_message_create(request); + bool result = false; - bool result = (session->is_authenticated || wf_impl_jsonrpc_is_response(request)) && (NULL != session->wsi); - - if (result) + if (NULL != session->wsi) { wf_impl_slist_append(&session->messages, &message->item); lws_callback_on_writable(session->wsi); @@ -151,12 +150,13 @@ void wf_impl_session_onwritable( static void wf_impl_session_process( struct wf_impl_session * session, - char const * data, + char * data, size_t length) { - json_t * message = json_loadb(data, length, 0, NULL); - if (NULL != message) + struct wf_json_doc * doc = wf_impl_json_doc_loadb(data, length); + if (NULL != doc) { + struct wf_json const * message = wf_impl_json_doc_root(doc); if (wf_impl_jsonrpc_is_response(message)) { wf_impl_jsonrpc_proxy_onresult(session->rpc, message); @@ -166,13 +166,13 @@ static void wf_impl_session_process( wf_impl_jsonrpc_server_process(session->server, message, &wf_impl_session_send, session); } - json_decref(message); + wf_impl_json_doc_dispose(doc); } } void wf_impl_session_receive( struct wf_impl_session * session, - char const * data, + char * data, size_t length, bool is_final_fragment) { diff --git a/lib/webfuse/impl/session.h b/lib/webfuse/impl/session.h index 6453993..58417a3 100644 --- a/lib/webfuse/impl/session.h +++ b/lib/webfuse/impl/session.h @@ -62,7 +62,7 @@ extern bool wf_impl_session_add_filesystem( extern void wf_impl_session_receive( struct wf_impl_session * session, - char const * data, + char * data, size_t length, bool is_final_fragment); diff --git a/lib/webfuse/impl/util/json_util.c b/lib/webfuse/impl/util/json_util.c index b2fdc77..7593182 100644 --- a/lib/webfuse/impl/util/json_util.c +++ b/lib/webfuse/impl/util/json_util.c @@ -1,13 +1,20 @@ #include "webfuse/impl/util/json_util.h" +#include "webfuse/impl/jsonrpc/error.h" +#include "webfuse/impl/json/node.h" -int wf_impl_json_get_int(json_t const * object, char const * key, int default_value) +int +wf_impl_json_get_int( + struct wf_json const * object, + char const * key, + int default_value) { + if (NULL == object) { return default_value; } int result = default_value; - json_t * holder = json_object_get(object, key); - if (json_is_integer(holder)) + struct wf_json const * holder = wf_impl_json_object_get(object, key); + if (wf_impl_json_is_int(holder)) { - result = json_integer_value(holder); + result = wf_impl_json_int_get(holder); } return result; @@ -15,12 +22,12 @@ int wf_impl_json_get_int(json_t const * object, char const * key, int default_va wf_status wf_impl_jsonrpc_get_status( - json_t const * error) + struct wf_jsonrpc_error const * error) { wf_status status = WF_GOOD; if (NULL != error) { - status = wf_impl_json_get_int(error, "code", WF_BAD_FORMAT); + status = wf_impl_jsonrpc_error_code(error); } return status; diff --git a/lib/webfuse/impl/util/json_util.h b/lib/webfuse/impl/util/json_util.h index 64b4eed..5c36530 100644 --- a/lib/webfuse/impl/util/json_util.h +++ b/lib/webfuse/impl/util/json_util.h @@ -1,7 +1,6 @@ #ifndef WF_IMPL_UTIL_JSON_UTIL_H #define WF_IMPL_UTIL_JSON_UTIL_H -#include #include "webfuse/status.h" #ifdef __cplusplus @@ -9,15 +8,18 @@ extern "C" { #endif +struct wf_jsonrpc_error; +struct wf_json; + extern int wf_impl_json_get_int( - json_t const * object, + struct wf_json const * object, char const * key, int default_value); extern wf_status wf_impl_jsonrpc_get_status( - json_t const * error); + struct wf_jsonrpc_error const * error); #ifdef __cplusplus } diff --git a/meson.build b/meson.build index 1a04770..b417804 100644 --- a/meson.build +++ b/meson.build @@ -9,7 +9,6 @@ if not libwebsockets_dep.found() libwebsockets_dep = libwebsockets.dependency('websockets_shared') endif -jansson_dep = dependency('jansson', version: '>=2.11', fallback: ['jansson', 'jansson_dep']) libfuse_dep = dependency('fuse3', version: '>=3.8.0', fallback: ['fuse3', 'libfuse_dep']) pkg_config = import('pkgconfig') @@ -29,6 +28,10 @@ webfuse_static = static_library('webfuse', 'lib/webfuse/impl/timer/timepoint.c', 'lib/webfuse/impl/timer/timer.c', 'lib/webfuse/impl/json/writer.c', + 'lib/webfuse/impl/json/node.c', + 'lib/webfuse/impl/json/doc.c', + 'lib/webfuse/impl/json/reader.c', + 'lib/webfuse/impl/json/parser.c', 'lib/webfuse/impl/jsonrpc/proxy.c', 'lib/webfuse/impl/jsonrpc/proxy_request_manager.c', 'lib/webfuse/impl/jsonrpc/proxy_variadic.c', @@ -36,6 +39,7 @@ webfuse_static = static_library('webfuse', 'lib/webfuse/impl/jsonrpc/method.c', 'lib/webfuse/impl/jsonrpc/request.c', 'lib/webfuse/impl/jsonrpc/response.c', + 'lib/webfuse/impl/jsonrpc/response_writer.c', 'lib/webfuse/impl/jsonrpc/error.c', 'lib/webfuse/impl/message.c', 'lib/webfuse/impl/message_queue.c', @@ -63,31 +67,31 @@ webfuse_static = static_library('webfuse', 'lib/webfuse/impl/client_tlsconfig.c', c_args: ['-fvisibility=hidden'], include_directories: private_inc_dir, - dependencies: [libfuse_dep, libwebsockets_dep, jansson_dep]) + dependencies: [libfuse_dep, libwebsockets_dep]) webfuse_static_dep = declare_dependency( include_directories: inc_dir, link_with: [webfuse_static], - dependencies: [libfuse_dep, libwebsockets_dep, jansson_dep]) + dependencies: [libfuse_dep, libwebsockets_dep]) webfuse = shared_library('webfuse', 'lib/webfuse/api.c', version: meson.project_version(), c_args: ['-fvisibility=hidden', '-DWF_API=WF_EXPORT'], include_directories: private_inc_dir, - dependencies: [webfuse_static_dep, libfuse_dep, libwebsockets_dep, jansson_dep], + dependencies: [webfuse_static_dep, libfuse_dep, libwebsockets_dep], install: true) webfuse_dep = declare_dependency( include_directories: inc_dir, link_with: [webfuse], - dependencies: [libfuse_dep, libwebsockets_dep, jansson_dep]) + dependencies: [libfuse_dep, libwebsockets_dep]) install_subdir('include/webfuse', install_dir: 'include') pkg_config.generate( libraries: [webfuse], - requires: ['fuse3', 'libwebsockets', 'jansson'], + requires: ['fuse3', 'libwebsockets'], subdirs: '.', version: meson.project_version(), name: 'libwebfuse', @@ -117,6 +121,10 @@ test_certs_dep = declare_dependency( alltests = executable('alltests', 'test/webfuse/json/test_writer.cc', + 'test/webfuse/json/test_doc.cc', + 'test/webfuse/json/test_node.cc', + 'test/webfuse/json/test_reader.cc', + 'test/webfuse/json/test_parser.cc', 'test/webfuse/jsonrpc/mock_timer_callback.cc', 'test/webfuse/jsonrpc/mock_timer.cc', 'test/webfuse/jsonrpc/test_is_request.cc', @@ -136,8 +144,8 @@ alltests = executable('alltests', 'test/webfuse/test_util/ws_client.cc', 'test/webfuse/test_util/adapter_client.cc', 'test/webfuse/test_util/file.cc', - 'test/webfuse/test_util/jansson_test_environment.cc', 'test/webfuse/test_util/lws_test_environment.cc', + 'test/webfuse/test_util/json_doc.cc', 'test/webfuse/mocks/mock_authenticator.cc', 'test/webfuse/mocks/mock_fuse.cc', 'test/webfuse/mocks/mock_operation_context.cc', @@ -193,7 +201,6 @@ alltests = executable('alltests', webfuse_static_dep, libwebsockets_dep, libfuse_dep, - jansson_dep, gtest_dep, gmock_main_dep, test_certs_dep diff --git a/subprojects/jansson.wrap b/subprojects/jansson.wrap deleted file mode 100644 index 6282afd..0000000 --- a/subprojects/jansson.wrap +++ /dev/null @@ -1,10 +0,0 @@ -[wrap-file] -directory = jansson-2.11 - -source_url = http://www.digip.org/jansson/releases/jansson-2.11.tar.bz2 -source_filename = jansson-2.11.tar.bz2 -source_hash = 783132e2fc970feefc2fa54199ef65ee020bd8e0e991a78ea44b8586353a0947 - -patch_url = https://wrapdb.mesonbuild.com/v1/projects/jansson/2.11/3/get_zip -patch_filename = jansson-2.11-3-wrap.zip -patch_hash = 0bcac510994890048d42658c674e33dd7d88715fc1e3bf49d10012f57b0e0020 \ No newline at end of file diff --git a/test/webfuse/json/test_doc.cc b/test/webfuse/json/test_doc.cc new file mode 100644 index 0000000..fd1b085 --- /dev/null +++ b/test/webfuse/json/test_doc.cc @@ -0,0 +1,23 @@ +#include "webfuse/impl/json/doc.h" +#include "webfuse/impl/json/node.h" +#include + +TEST(json_doc, loadb) +{ + char text[] = "true"; + wf_json_doc * doc = wf_impl_json_doc_loadb(text, 4); + ASSERT_NE(nullptr, doc); + + wf_json const * root = wf_impl_json_doc_root(doc); + ASSERT_EQ(WF_JSON_TYPE_BOOL, wf_impl_json_type(root)); + ASSERT_TRUE(wf_impl_json_bool_get(root)); + + wf_impl_json_doc_dispose(doc); +} + +TEST(json_doc, loadb_fail_invalid_json) +{ + char text[] = "true"; + wf_json_doc * doc = wf_impl_json_doc_loadb(text, 3); + ASSERT_EQ(nullptr, doc); +} \ No newline at end of file diff --git a/test/webfuse/json/test_node.cc b/test/webfuse/json/test_node.cc new file mode 100644 index 0000000..2cdf213 --- /dev/null +++ b/test/webfuse/json/test_node.cc @@ -0,0 +1,89 @@ +#include "webfuse/impl/json/node.h" +#include "webfuse/test_util/json_doc.hpp" + +#include + +using webfuse_test::JsonDoc; + +TEST(json_node, null) +{ + JsonDoc doc("null"); + ASSERT_EQ(WF_JSON_TYPE_NULL, wf_impl_json_type(doc.root())); + ASSERT_TRUE(wf_impl_json_is_null(doc.root())); +} + +TEST(json_node, true) +{ + JsonDoc doc("true"); + ASSERT_EQ(WF_JSON_TYPE_BOOL, wf_impl_json_type(doc.root())); + ASSERT_TRUE(wf_impl_json_is_bool(doc.root())); + ASSERT_TRUE(wf_impl_json_bool_get(doc.root())); +} + +TEST(json_node, false) +{ + JsonDoc doc("false"); + ASSERT_EQ(WF_JSON_TYPE_BOOL, wf_impl_json_type(doc.root())); + ASSERT_TRUE(wf_impl_json_is_bool(doc.root())); + ASSERT_FALSE(wf_impl_json_bool_get(doc.root())); +} + +TEST(json_node, int) +{ + JsonDoc doc("42"); + ASSERT_EQ(WF_JSON_TYPE_INT, wf_impl_json_type(doc.root())); + ASSERT_TRUE(wf_impl_json_is_int(doc.root())); + ASSERT_EQ(42, wf_impl_json_int_get(doc.root())); +} + +TEST(json_node, string) +{ + JsonDoc doc("\"brummni\""); + ASSERT_EQ(WF_JSON_TYPE_STRING, wf_impl_json_type(doc.root())); + ASSERT_TRUE(wf_impl_json_is_string(doc.root())); + ASSERT_STREQ("brummni", wf_impl_json_string_get(doc.root())); +} + +TEST(json_node, array) +{ + JsonDoc doc("[1,2,3]"); + ASSERT_EQ(WF_JSON_TYPE_ARRAY, wf_impl_json_type(doc.root())); + ASSERT_TRUE(wf_impl_json_is_array(doc.root())); + ASSERT_EQ(3, wf_impl_json_array_size(doc.root())); + ASSERT_EQ(WF_JSON_TYPE_INT, wf_impl_json_type(wf_impl_json_array_get(doc.root(), 0))); + ASSERT_EQ(WF_JSON_TYPE_UNDEFINED, wf_impl_json_type(wf_impl_json_array_get(doc.root(), 4))); +} + +TEST(json_node, object) +{ + JsonDoc doc("{\"answer\": 42}"); + ASSERT_EQ(WF_JSON_TYPE_OBJECT, wf_impl_json_type(doc.root())); + ASSERT_TRUE(wf_impl_json_is_object(doc.root())); + ASSERT_EQ(1, wf_impl_json_object_size(doc.root())); + + ASSERT_EQ(WF_JSON_TYPE_INT, wf_impl_json_type(wf_impl_json_object_get(doc.root(), "answer"))); + ASSERT_STREQ("answer", wf_impl_json_object_key(doc.root(), 0)); + ASSERT_EQ(WF_JSON_TYPE_INT, wf_impl_json_type(wf_impl_json_object_value(doc.root(), 0))); + + ASSERT_EQ(WF_JSON_TYPE_UNDEFINED, wf_impl_json_type(wf_impl_json_object_get(doc.root(), "unknown"))); + ASSERT_STREQ("", wf_impl_json_object_key(doc.root(), 1)); + ASSERT_EQ(WF_JSON_TYPE_UNDEFINED, wf_impl_json_type(wf_impl_json_object_value(doc.root(), 1))); +} + +TEST(json_node, default_values) +{ + JsonDoc doc("null"); + + ASSERT_EQ (false, wf_impl_json_bool_get(doc.root())); + ASSERT_EQ (0 , wf_impl_json_int_get(doc.root())); + ASSERT_STREQ("" , wf_impl_json_string_get(doc.root())); + + ASSERT_EQ (0 , wf_impl_json_array_size(doc.root())); + ASSERT_EQ (WF_JSON_TYPE_UNDEFINED, wf_impl_json_type(wf_impl_json_array_get(doc.root(), 0))); + + ASSERT_EQ (0 , wf_impl_json_object_size(doc.root())); + ASSERT_STREQ("" , wf_impl_json_object_key(doc.root(), 0)); + ASSERT_EQ (WF_JSON_TYPE_UNDEFINED, wf_impl_json_type(wf_impl_json_object_get(doc.root(), 0))); + ASSERT_EQ (WF_JSON_TYPE_UNDEFINED, wf_impl_json_type(wf_impl_json_object_value(doc.root(), 0))); + +} \ No newline at end of file diff --git a/test/webfuse/json/test_parser.cc b/test/webfuse/json/test_parser.cc new file mode 100644 index 0000000..e51be86 --- /dev/null +++ b/test/webfuse/json/test_parser.cc @@ -0,0 +1,123 @@ +#include "webfuse/impl/json/parser.h" +#include "webfuse/impl/json/reader.h" +#include "webfuse/impl/json/node_intern.h" + +#include +#include + +namespace +{ + +bool try_parse(std::string const & value) +{ + std::string contents = value; + struct wf_json_reader reader; + wf_impl_json_reader_init(&reader, const_cast(contents.data()), contents.size()); + wf_json json; + + bool const result = wf_impl_json_parse_value(&reader, &json); + if (result) + { + wf_impl_json_cleanup(&json); + } + + return result; +} + +} + + +TEST(json_parser, fail_no_contents) +{ + ASSERT_FALSE(try_parse("")); +} + +TEST(json_parser, fail_invalid_null) +{ + ASSERT_FALSE(try_parse("none")); +} + +TEST(json_parser, fail_invalid_true) +{ + ASSERT_FALSE(try_parse("tru")); +} + +TEST(json_parser, fail_invalid_false) +{ + ASSERT_FALSE(try_parse("fals")); +} + +TEST(json_parser, fail_invalid_int) +{ + ASSERT_FALSE(try_parse("-")); +} + +TEST(json_parser, fail_invalid_string) +{ + ASSERT_FALSE(try_parse("\"invalid")); +} + +TEST(json_parser, empty_array) +{ + ASSERT_TRUE(try_parse("[]")); +} + +TEST(json_parser, large_array) +{ + ASSERT_TRUE(try_parse("[1,2,3,4,5,6,7,8,9]")); +} + +TEST(json_parser, fail_unterminated_array) +{ + ASSERT_FALSE(try_parse("[1")); +} + +TEST(json_parser, fail_missing_array_separator) +{ + ASSERT_FALSE(try_parse("[1 2]")); +} + +TEST(json_parser, fail_missing_array_value) +{ + ASSERT_FALSE(try_parse("[1,]")); +} + +TEST(json_parser, empty_object) +{ + ASSERT_TRUE(try_parse("{}")); +} + +TEST(json_parser, large_object) +{ + ASSERT_TRUE(try_parse("{\"a\":1,\"b\":2,\"c\":3,\"d\":4,\"e\":5}")); +} + +TEST(json_parser, fail_unterminated_object) +{ + ASSERT_FALSE(try_parse("{\"a\":1")); +} + +TEST(json_parser, fail_invalid_object_key) +{ + ASSERT_FALSE(try_parse("{a:1}")); +} + +TEST(json_parser, fail_missing_object_terminator) +{ + ASSERT_FALSE(try_parse("{\"a\"1}")); +} + +TEST(json_parser, fail_missing_object_value) +{ + ASSERT_FALSE(try_parse("{\"a\":}")); +} + +TEST(json_parser, fail_missing_object_separator) +{ + ASSERT_FALSE(try_parse("{\"a\":1 \"b\":2}")); +} + +TEST(json_parser, fail_missing_object_item) +{ + ASSERT_FALSE(try_parse("{\"a\":1,}")); +} diff --git a/test/webfuse/json/test_reader.cc b/test/webfuse/json/test_reader.cc new file mode 100644 index 0000000..d66af66 --- /dev/null +++ b/test/webfuse/json/test_reader.cc @@ -0,0 +1,214 @@ +#include "webfuse/impl/json/reader.h" +#include +#include + +TEST(json_reader, skip_whitespace) +{ + char text[] = " \t\r\n*"; + wf_json_reader reader; + wf_impl_json_reader_init(&reader, text, 5); + char c = wf_impl_json_reader_skip_whitespace(&reader); + ASSERT_EQ('*', c); + ASSERT_STREQ("*", &reader.contents[reader.pos]); +} + +TEST(json_reader, skip_whitespace_eof) +{ + char text[] = " "; + wf_json_reader reader; + wf_impl_json_reader_init(&reader, text, 1); + char c = wf_impl_json_reader_skip_whitespace(&reader); + ASSERT_EQ('\0', c); +} + +TEST(json_reader, peek) +{ + char text[] = "*"; + wf_json_reader reader; + wf_impl_json_reader_init(&reader, text, 1); + char c = wf_impl_json_reader_peek(&reader); + ASSERT_EQ('*', c); +} + +TEST(json_reader, peek_eof) +{ + wf_json_reader reader; + wf_impl_json_reader_init(&reader, nullptr, 0); + char c = wf_impl_json_reader_peek(&reader); + ASSERT_EQ('\0', c); +} + +TEST(json_reader, get_char) +{ + char text[] = "*"; + wf_json_reader reader; + wf_impl_json_reader_init(&reader, text, 1); + ASSERT_EQ('*', wf_impl_json_reader_get_char(&reader)); + ASSERT_EQ('\0', wf_impl_json_reader_get_char(&reader)); + ASSERT_EQ('\0', wf_impl_json_reader_get_char(&reader)); +} + +TEST(json_reader, unget_char) +{ + char text[] = "*"; + wf_json_reader reader; + wf_impl_json_reader_init(&reader, text, 1); + + ASSERT_EQ('*', wf_impl_json_reader_get_char(&reader)); + wf_impl_json_reader_unget_char(&reader); + ASSERT_EQ('*', wf_impl_json_reader_get_char(&reader)); + + wf_impl_json_reader_unget_char(&reader); + wf_impl_json_reader_unget_char(&reader); + ASSERT_EQ('*', wf_impl_json_reader_get_char(&reader)); +} + +TEST(json_reader, read_const) +{ + char text[] = "value"; + wf_json_reader reader; + wf_impl_json_reader_init(&reader, text, 5); + + ASSERT_TRUE(wf_impl_json_reader_read_const(&reader, "value", 5)); +} + +TEST(json_reader, read_const_fail_out_of_bounds) +{ + char text[] = "value"; + wf_json_reader reader; + wf_impl_json_reader_init(&reader, text, 2); + + ASSERT_FALSE(wf_impl_json_reader_read_const(&reader, "value", 5)); +} + +TEST(json_reader, read_const_fail_no_match) +{ + char text[] = "hello"; + wf_json_reader reader; + wf_impl_json_reader_init(&reader, text, 5); + + ASSERT_FALSE(wf_impl_json_reader_read_const(&reader, "value", 5)); +} + +TEST(json_reader, read_positive_int) +{ + char text[] = "42"; + wf_json_reader reader; + wf_impl_json_reader_init(&reader, text, 5); + + int value; + ASSERT_TRUE(wf_impl_json_reader_read_int(&reader, &value)); + ASSERT_EQ(42, value); +} + +TEST(json_reader, read_negative_int) +{ + char text[] = "-1234"; + wf_json_reader reader; + wf_impl_json_reader_init(&reader, text, 5); + + int value; + ASSERT_TRUE(wf_impl_json_reader_read_int(&reader, &value)); + ASSERT_EQ(-1234, value); +} + +TEST(json_reader, read_int_max) +{ + std::string text = std::to_string(INT_MAX); + wf_json_reader reader; + wf_impl_json_reader_init(&reader, const_cast(text.data()), text.size()); + + int value; + ASSERT_TRUE(wf_impl_json_reader_read_int(&reader, &value)); + ASSERT_EQ(INT_MAX, value); +} + +TEST(json_reader, read_int_min) +{ + std::string text = std::to_string(INT_MIN); + wf_json_reader reader; + wf_impl_json_reader_init(&reader, const_cast(text.data()), text.size()); + + int value; + ASSERT_TRUE(wf_impl_json_reader_read_int(&reader, &value)); + ASSERT_EQ(INT_MIN, value); +} + +TEST(json_reader, read_int_fail_invalid) +{ + std::string text = "brummni"; + wf_json_reader reader; + wf_impl_json_reader_init(&reader, const_cast(text.data()), text.size()); + + int value; + ASSERT_FALSE(wf_impl_json_reader_read_int(&reader, &value)); +} + +TEST(json_reader, read_int_fail_sign_only) +{ + std::string text = "-"; + wf_json_reader reader; + wf_impl_json_reader_init(&reader, const_cast(text.data()), text.size()); + + int value; + ASSERT_FALSE(wf_impl_json_reader_read_int(&reader, &value)); +} + +TEST(json_reader, read_string) +{ + std::string text = "\"brummni\""; + wf_json_reader reader; + wf_impl_json_reader_init(&reader, const_cast(text.data()), text.size()); + + char * value; + size_t size; + ASSERT_TRUE(wf_impl_json_reader_read_string(&reader, &value, &size)); + ASSERT_STREQ("brummni", value); + ASSERT_EQ(7, size); +} + +TEST(json_reader, read_string_escaped) +{ + std::string text = "\"_\\\"_\\\\_\\/_\\b_\\f_\\n_\\r_\\t_\""; + wf_json_reader reader; + wf_impl_json_reader_init(&reader, const_cast(text.data()), text.size()); + + char * value; + size_t size; + ASSERT_TRUE(wf_impl_json_reader_read_string(&reader, &value, &size)); + ASSERT_STREQ("_\"_\\_/_\b_\f_\n_\r_\t_", value); + ASSERT_EQ(17, size); +} + +TEST(json_reader, read_string_fail_missig_start_quot) +{ + std::string text = "brummni\""; + wf_json_reader reader; + wf_impl_json_reader_init(&reader, const_cast(text.data()), text.size()); + + char * value; + size_t size; + ASSERT_FALSE(wf_impl_json_reader_read_string(&reader, &value, &size)); +} + +TEST(json_reader, read_string_fail_missig_end_quot) +{ + std::string text = "\"brummni"; + wf_json_reader reader; + wf_impl_json_reader_init(&reader, const_cast(text.data()), text.size()); + + char * value; + size_t size; + ASSERT_FALSE(wf_impl_json_reader_read_string(&reader, &value, &size)); +} + +TEST(json_reader, read_string_fail_invalid_escape_seq) +{ + std::string text = "\"\\i\""; + wf_json_reader reader; + wf_impl_json_reader_init(&reader, const_cast(text.data()), text.size()); + + char * value; + size_t size; + ASSERT_FALSE(wf_impl_json_reader_read_string(&reader, &value, &size)); +} diff --git a/test/webfuse/json/test_writer.cc b/test/webfuse/json/test_writer.cc index 421cdfd..e9ea23b 100644 --- a/test/webfuse/json/test_writer.cc +++ b/test/webfuse/json/test_writer.cc @@ -194,3 +194,77 @@ TEST(json_writer, write_deep_nested_array) ASSERT_EQ(expected, writer.take()); } + +TEST(json_writer, write_bytes) +{ + writer writer; + wf_impl_json_write_bytes(writer, "\0\0", 2); + + ASSERT_EQ("\"AAA=\"", writer.take()); +} + +TEST(json_writer, reset) +{ + writer writer; + wf_impl_json_write_string(writer, "some value"); + + wf_impl_json_writer_reset(writer); + wf_impl_json_write_int(writer,42); + + ASSERT_EQ("42", writer.take()); +} + +TEST(json_writer, write_object_null) +{ + writer writer; + wf_impl_json_write_object_begin(writer); + wf_impl_json_write_object_null(writer, "error"); + wf_impl_json_write_object_end(writer); + + ASSERT_EQ("{\"error\":null}", writer.take()); +} + +TEST(json_writer, write_object_bool) +{ + writer writer; + wf_impl_json_write_object_begin(writer); + wf_impl_json_write_object_bool(writer, "result", true); + wf_impl_json_write_object_end(writer); + + ASSERT_EQ("{\"result\":true}", writer.take()); +} + +TEST(json_writer, write_object_string_nocheck) +{ + writer writer; + wf_impl_json_write_object_begin(writer); + wf_impl_json_write_object_string_nocheck(writer, "result", "Hello,\tWorld!"); + wf_impl_json_write_object_end(writer); + + ASSERT_EQ("{\"result\":\"Hello,\tWorld!\"}", writer.take()); +} + +TEST(json_writer, write_object_bytes) +{ + writer writer; + wf_impl_json_write_object_begin(writer); + wf_impl_json_write_object_bytes(writer, "result", "\0\0", 2); + wf_impl_json_write_object_end(writer); + + + ASSERT_EQ("{\"result\":\"AAA=\"}", writer.take()); +} + +TEST(json_writer, realloc_buffer) +{ + writer writer(1); + wf_impl_json_write_string(writer, "very large contents"); + + ASSERT_EQ("\"very large contents\"", writer.take()); +} + +TEST(json_writer, unexpected_end) +{ + writer writer; + wf_impl_json_write_array_end(writer); +} diff --git a/test/webfuse/jsonrpc/test_is_request.cc b/test/webfuse/jsonrpc/test_is_request.cc index eca0b00..17207fb 100644 --- a/test/webfuse/jsonrpc/test_is_request.cc +++ b/test/webfuse/jsonrpc/test_is_request.cc @@ -1,28 +1,21 @@ -#include #include "webfuse/impl/jsonrpc/request.h" +#include "webfuse/test_util/json_doc.hpp" +#include + +using webfuse_test::JsonDoc; TEST(wf_jsonrpc_is_request, request_with_object_params) { - json_t * request = json_object(); - json_object_set_new(request, "method", json_string("method")); - json_object_set_new(request, "params", json_object()); - json_object_set_new(request, "id", json_integer(42)); + JsonDoc doc("{\"method\": \"method\", \"params\": {}, \"id\": 42}"); - ASSERT_TRUE(wf_impl_jsonrpc_is_request(request)); - - json_decref(request); + ASSERT_TRUE(wf_impl_jsonrpc_is_request(doc.root())); } TEST(wf_jsonrpc_is_request, request_with_array_params) { - json_t * request = json_object(); - json_object_set_new(request, "method", json_string("method")); - json_object_set_new(request, "params", json_array()); - json_object_set_new(request, "id", json_integer(42)); + JsonDoc doc("{\"method\": \"method\", \"params\": [], \"id\": 42}"); - ASSERT_TRUE(wf_impl_jsonrpc_is_request(request)); - - json_decref(request); + ASSERT_TRUE(wf_impl_jsonrpc_is_request(doc.root())); } TEST(wf_jsonrpc_is_request, null_request) @@ -32,81 +25,49 @@ TEST(wf_jsonrpc_is_request, null_request) TEST(wf_jsonrpc_is_request, invalid_request) { - json_t * request = json_array(); - json_array_append_new(request, json_string("method")); - json_array_append_new(request, json_object()); - json_array_append_new(request, json_integer(42)); + JsonDoc doc("[\"method\", {}, 42]"); - ASSERT_FALSE(wf_impl_jsonrpc_is_request(request)); - - json_decref(request); + ASSERT_FALSE(wf_impl_jsonrpc_is_request(doc.root())); } TEST(wf_jsonrpc_is_request, invalid_request_without_id) { - json_t * request = json_object(); - json_object_set_new(request, "method", json_string("method")); - json_object_set_new(request, "params", json_object()); + JsonDoc doc("{\"method\": \"method\", \"params\": {}}"); - ASSERT_FALSE(wf_impl_jsonrpc_is_request(request)); - - json_decref(request); + ASSERT_FALSE(wf_impl_jsonrpc_is_request(doc.root())); } TEST(wf_jsonrpc_is_request, invalid_request_due_to_invalid_id) { - json_t * request = json_object(); - json_object_set_new(request, "method", json_string("method")); - json_object_set_new(request, "params", json_object()); - json_object_set_new(request, "id", json_string("42")); + JsonDoc doc("{\"method\": \"method\", \"params\": [], \"id\": \"42\"}"); - ASSERT_FALSE(wf_impl_jsonrpc_is_request(request)); - - json_decref(request); + ASSERT_FALSE(wf_impl_jsonrpc_is_request(doc.root())); } TEST(wf_jsonrpc_is_request, invalid_request_without_method) { - json_t * request = json_object(); - json_object_set_new(request, "params", json_object()); - json_object_set_new(request, "id", json_integer(42)); + JsonDoc doc("{\"params\": [], \"id\": 42}"); - ASSERT_FALSE(wf_impl_jsonrpc_is_request(request)); - - json_decref(request); + ASSERT_FALSE(wf_impl_jsonrpc_is_request(doc.root())); } TEST(wf_jsonrpc_is_request, invalid_request_due_to_invalid_method) { - json_t * request = json_object(); - json_object_set_new(request, "method", json_integer(42)); - json_object_set_new(request, "params", json_object()); - json_object_set_new(request, "id", json_integer(42)); + JsonDoc doc("{\"method\": 42, \"params\": [], \"id\": 42}"); - ASSERT_FALSE(wf_impl_jsonrpc_is_request(request)); - - json_decref(request); + ASSERT_FALSE(wf_impl_jsonrpc_is_request(doc.root())); } TEST(wf_jsonrpc_is_request, invalid_request_without_params) { - json_t * request = json_object(); - json_object_set_new(request, "method", json_string("method")); - json_object_set_new(request, "id", json_integer(42)); + JsonDoc doc("{\"method\": \"method\", \"id\": 42}"); - ASSERT_FALSE(wf_impl_jsonrpc_is_request(request)); - - json_decref(request); + ASSERT_FALSE(wf_impl_jsonrpc_is_request(doc.root())); } TEST(wf_jsonrpc_is_request, invalid_request_due_to_invalid_params) { - json_t * request = json_object(); - json_object_set_new(request, "methdo", json_string("method")); - json_object_set_new(request, "params", json_string("params")); - json_object_set_new(request, "id", json_integer(42)); + JsonDoc doc("{\"method\": \"method\", \"params\": \"params\", \"id\": 42}"); - ASSERT_FALSE(wf_impl_jsonrpc_is_request(request)); - - json_decref(request); + ASSERT_FALSE(wf_impl_jsonrpc_is_request(doc.root())); } diff --git a/test/webfuse/jsonrpc/test_is_response.cc b/test/webfuse/jsonrpc/test_is_response.cc index 550ce53..519ebf3 100644 --- a/test/webfuse/jsonrpc/test_is_response.cc +++ b/test/webfuse/jsonrpc/test_is_response.cc @@ -1,37 +1,28 @@ -#include #include "webfuse/impl/jsonrpc/response.h" +#include "webfuse/test_util/json_doc.hpp" +#include + +using webfuse_test::JsonDoc; TEST(wf_jsonrpc_is_response, valid_result) { - json_t * message = json_object(); - json_object_set_new(message, "result", json_object()); - json_object_set_new(message, "id", json_integer(42)); + JsonDoc doc("{\"result\": {}, \"id\": 42}"); - ASSERT_TRUE(wf_impl_jsonrpc_is_response(message)); - - json_decref(message); + ASSERT_TRUE(wf_impl_jsonrpc_is_response(doc.root())); } TEST(wf_jsonrpc_is_response, valid_result_string) { - json_t * message = json_object(); - json_object_set_new(message, "result", json_string("also valid")); - json_object_set_new(message, "id", json_integer(42)); + JsonDoc doc("{\"result\": \"also valid\", \"id\": 42}"); - ASSERT_TRUE(wf_impl_jsonrpc_is_response(message)); - - json_decref(message); + ASSERT_TRUE(wf_impl_jsonrpc_is_response(doc.root())); } TEST(wf_jsonrpc_is_response, valid_error) { - json_t * message = json_object(); - json_object_set_new(message, "error", json_object()); - json_object_set_new(message, "id", json_integer(42)); + JsonDoc doc("{\"error\": {}, \"id\": 42}"); - ASSERT_TRUE(wf_impl_jsonrpc_is_response(message)); - - json_decref(message); + ASSERT_TRUE(wf_impl_jsonrpc_is_response(doc.root())); } TEST(wf_jsonrpc_is_response, invalid_null) @@ -41,54 +32,36 @@ TEST(wf_jsonrpc_is_response, invalid_null) TEST(wf_jsonrpc_is_response, invalid_message) { - json_t * message = json_array(); - json_array_append_new(message, json_object()); - json_array_append_new(message, json_integer(42)); + JsonDoc doc("[{}, 42]"); - ASSERT_FALSE(wf_impl_jsonrpc_is_response(message)); - - json_decref(message); + ASSERT_FALSE(wf_impl_jsonrpc_is_response(doc.root())); } TEST(wf_jsonrpc_is_response, invalid_missing_id) { - json_t * message = json_object(); - json_object_set_new(message, "result", json_object()); + JsonDoc doc("{\"result\": {}}"); - ASSERT_FALSE(wf_impl_jsonrpc_is_response(message)); - - json_decref(message); + ASSERT_FALSE(wf_impl_jsonrpc_is_response(doc.root())); } TEST(wf_jsonrpc_is_response, invalid_id_wrong_type) { - json_t * message = json_object(); - json_object_set_new(message, "result", json_object()); - json_object_set_new(message, "id", json_string("42")); + JsonDoc doc("{\"result\": {}, \"id\": \"42\"}"); - ASSERT_FALSE(wf_impl_jsonrpc_is_response(message)); - - json_decref(message); + ASSERT_FALSE(wf_impl_jsonrpc_is_response(doc.root())); } TEST(wf_jsonrpc_is_response, invalid_missing_result_and_error) { - json_t * message = json_object(); - json_object_set_new(message, "id", json_integer(42)); + JsonDoc doc("{\"id\": 42}"); - ASSERT_FALSE(wf_impl_jsonrpc_is_response(message)); - - json_decref(message); + ASSERT_FALSE(wf_impl_jsonrpc_is_response(doc.root())); } TEST(wf_jsonrpc_is_response, invalid_error_wrong_type) { - json_t * message = json_object(); - json_object_set_new(message, "error", json_array()); - json_object_set_new(message, "id", json_integer(42)); + JsonDoc doc("{\"error\": [], \"id\": 42}"); - ASSERT_FALSE(wf_impl_jsonrpc_is_response(message)); - - json_decref(message); + ASSERT_FALSE(wf_impl_jsonrpc_is_response(doc.root())); } diff --git a/test/webfuse/jsonrpc/test_proxy.cc b/test/webfuse/jsonrpc/test_proxy.cc index f5368d0..fd36928 100644 --- a/test/webfuse/jsonrpc/test_proxy.cc +++ b/test/webfuse/jsonrpc/test_proxy.cc @@ -1,15 +1,20 @@ #include #include "webfuse/impl/jsonrpc/proxy.h" +#include "webfuse/impl/jsonrpc/error.h" +#include "webfuse/impl/json/node.h" +#include "webfuse/impl/message.h" #include "webfuse/status.h" #include "webfuse/impl/timer/manager.h" #include "webfuse/jsonrpc/mock_timer.hpp" +#include "webfuse/test_util/json_doc.hpp" #include #include using namespace std::chrono_literals; using wf_jsonrpc_test::MockTimer; +using webfuse_test::JsonDoc; using testing::Return; using testing::_; using testing::DoAll; @@ -19,55 +24,42 @@ using testing::SaveArg; namespace { - int jsonrpc_get_status(json_t * error) - { - json_t * code = json_object_get(error, "code"); - return (json_is_integer(code)) ? json_integer_value(code) : WF_BAD_FORMAT; - } - struct SendContext { - json_t * response; + JsonDoc doc; + wf_json const * response; bool result; bool is_called; explicit SendContext(bool result_ = true) - : response(nullptr) + : doc("null") + , response(nullptr) , result(result_) , is_called(false) { } - - ~SendContext() - { - if (nullptr != response) - { - json_decref(response); - } - } }; bool jsonrpc_send( - json_t * request, + wf_message * request, void * user_data) { SendContext * context = reinterpret_cast(user_data); context->is_called = true; - context->response = request; - json_incref(request); + context->doc = std::move(JsonDoc(std::string(request->data, request->length))); + context->response = context->doc.root(); + wf_impl_message_dispose(request); return context->result; } struct FinishedContext { bool is_called; - json_t * result; - json_t * error; + wf_jsonrpc_error * error; FinishedContext() : is_called(false) - , result(nullptr) , error(nullptr) { @@ -75,27 +67,23 @@ namespace ~FinishedContext() { - if (nullptr != result) - { - json_decref(result); - } - - if (nullptr != error) - { - json_decref(error); - } + wf_impl_jsonrpc_error_dispose(error); } }; void jsonrpc_finished( void * user_data, - json_t const * result, - json_t const * error) + wf_json const *, + wf_jsonrpc_error const * error) { FinishedContext * context = reinterpret_cast(user_data); context->is_called = true; - context->result = json_deep_copy(result); - context->error = json_deep_copy(error); + + if (nullptr != error) + { + context->error = wf_impl_jsonrpc_error(wf_impl_jsonrpc_error_code(error), + wf_impl_jsonrpc_error_message(error)); + } } } @@ -126,22 +114,22 @@ TEST(wf_jsonrpc_proxy, invoke) wf_impl_jsonrpc_proxy_invoke(proxy, &jsonrpc_finished, finished_data, "foo", "si", "bar", 42); ASSERT_TRUE(send_context.is_called); - ASSERT_TRUE(json_is_object(send_context.response)); + ASSERT_TRUE(wf_impl_json_is_object(send_context.response)); - json_t * method = json_object_get(send_context.response, "method"); - ASSERT_TRUE(json_is_string(method)); - ASSERT_STREQ("foo", json_string_value(method)); + wf_json const * method = wf_impl_json_object_get(send_context.response, "method"); + ASSERT_TRUE(wf_impl_json_is_string(method)); + ASSERT_STREQ("foo", wf_impl_json_string_get(method)); - json_t * params = json_object_get(send_context.response, "params"); - ASSERT_TRUE(json_is_array(params)); - ASSERT_EQ(2, json_array_size(params)); - ASSERT_TRUE(json_is_string(json_array_get(params, 0))); - ASSERT_STREQ("bar", json_string_value(json_array_get(params, 0))); - ASSERT_TRUE(json_is_integer(json_array_get(params, 1))); - ASSERT_EQ(42, json_integer_value(json_array_get(params, 1))); + wf_json const * params = wf_impl_json_object_get(send_context.response, "params"); + ASSERT_TRUE(wf_impl_json_is_array(params)); + ASSERT_EQ(2, wf_impl_json_array_size(params)); + ASSERT_TRUE(wf_impl_json_is_string(wf_impl_json_array_get(params, 0))); + ASSERT_STREQ("bar", wf_impl_json_string_get(wf_impl_json_array_get(params, 0))); + ASSERT_TRUE(wf_impl_json_is_int(wf_impl_json_array_get(params, 1))); + ASSERT_EQ(42, wf_impl_json_int_get(wf_impl_json_array_get(params, 1))); - json_t * id = json_object_get(send_context.response, "id"); - ASSERT_TRUE(json_is_integer(id)); + wf_json const * id = wf_impl_json_object_get(send_context.response, "id"); + ASSERT_TRUE(wf_impl_json_is_int(id)); ASSERT_FALSE(finished_context.is_called); @@ -165,7 +153,7 @@ TEST(wf_jsonrpc_proxy, invoke_calls_finish_if_send_fails) wf_impl_jsonrpc_proxy_invoke(proxy, &jsonrpc_finished, finished_data, "foo", "si", "bar", 42); ASSERT_TRUE(send_context.is_called); - ASSERT_TRUE(json_is_object(send_context.response)); + ASSERT_TRUE(wf_impl_json_is_object(send_context.response)); ASSERT_TRUE(finished_context.is_called); ASSERT_FALSE(nullptr == finished_context.error); @@ -191,7 +179,7 @@ TEST(wf_jsonrpc_proxy, invoke_if_another_request_is_pending) wf_impl_jsonrpc_proxy_invoke(proxy, &jsonrpc_finished, finished_data2, "foo", ""); ASSERT_TRUE(send_context.is_called); - ASSERT_TRUE(json_is_object(send_context.response)); + ASSERT_TRUE(wf_impl_json_is_object(send_context.response)); ASSERT_FALSE(finished_context.is_called); @@ -199,7 +187,7 @@ TEST(wf_jsonrpc_proxy, invoke_if_another_request_is_pending) wf_impl_timer_manager_dispose(timer_manager); } -TEST(wf_jsonrpc_proxy, invoke_fails_if_request_is_invalid) +TEST(wf_jsonrpc_proxy, invoke_invalid_request) { struct wf_timer_manager * timer_manager = wf_impl_timer_manager_create(); @@ -211,10 +199,9 @@ TEST(wf_jsonrpc_proxy, invoke_fails_if_request_is_invalid) void * finished_data = reinterpret_cast(&finished_context); wf_impl_jsonrpc_proxy_invoke(proxy, &jsonrpc_finished, finished_data, "foo", "?", "error"); - ASSERT_FALSE(send_context.is_called); + ASSERT_TRUE(send_context.is_called); - ASSERT_TRUE(finished_context.is_called); - ASSERT_EQ(WF_BAD, jsonrpc_get_status(finished_context.error)); + ASSERT_FALSE(finished_context.is_called); wf_impl_jsonrpc_proxy_dispose(proxy); wf_impl_timer_manager_dispose(timer_manager); @@ -233,22 +220,16 @@ TEST(wf_jsonrpc_proxy, on_result) wf_impl_jsonrpc_proxy_invoke(proxy, &jsonrpc_finished, finished_data, "foo", "si", "bar", 42); ASSERT_TRUE(send_context.is_called); - ASSERT_TRUE(json_is_object(send_context.response)); + ASSERT_TRUE(wf_impl_json_is_object(send_context.response)); - json_t * id = json_object_get(send_context.response, "id"); - ASSERT_TRUE(json_is_number(id)); + wf_json const * id = wf_impl_json_object_get(send_context.response, "id"); + ASSERT_TRUE(wf_impl_json_is_int(id)); - json_t * response = json_object(); - json_object_set_new(response, "result", json_string("okay")); - json_object_set(response, "id", id); - - wf_impl_jsonrpc_proxy_onresult(proxy, response); - json_decref(response); + JsonDoc response("{\"result\": \"okay\", \"id\": " + std::to_string(wf_impl_json_int_get(id)) + "}"); + wf_impl_jsonrpc_proxy_onresult(proxy, response.root()); ASSERT_TRUE(finished_context.is_called); ASSERT_EQ(nullptr, finished_context.error); - ASSERT_TRUE(json_is_string(finished_context.result)); - ASSERT_STREQ("okay", json_string_value(finished_context.result)); wf_impl_jsonrpc_proxy_dispose(proxy); wf_impl_timer_manager_dispose(timer_manager); @@ -267,17 +248,13 @@ TEST(wf_jsonrpc_proxy, on_result_reject_response_with_unknown_id) wf_impl_jsonrpc_proxy_invoke(proxy, &jsonrpc_finished, finished_data, "foo", "si", "bar", 42); ASSERT_TRUE(send_context.is_called); - ASSERT_TRUE(json_is_object(send_context.response)); + ASSERT_TRUE(wf_impl_json_is_object(send_context.response)); - json_t * id = json_object_get(send_context.response, "id"); - ASSERT_TRUE(json_is_number(id)); + wf_json const * id = wf_impl_json_object_get(send_context.response, "id"); + ASSERT_TRUE(wf_impl_json_is_int(id)); - json_t * response = json_object(); - json_object_set_new(response, "result", json_string("okay")); - json_object_set_new(response, "id", json_integer(1 + json_integer_value(id))); - - wf_impl_jsonrpc_proxy_onresult(proxy, response); - json_decref(response); + JsonDoc response("{\"result\": \"okay\", \"id\": " + std::to_string(wf_impl_json_int_get(id) + 1) + "}"); + wf_impl_jsonrpc_proxy_onresult(proxy, response.root()); ASSERT_FALSE(finished_context.is_called); @@ -298,13 +275,13 @@ TEST(wf_jsonrpc_proxy, timeout) wf_impl_jsonrpc_proxy_invoke(proxy, &jsonrpc_finished, finished_data, "foo", "si", "bar", 42); ASSERT_TRUE(send_context.is_called); - ASSERT_TRUE(json_is_object(send_context.response)); + ASSERT_TRUE(wf_impl_json_is_object(send_context.response)); std::this_thread::sleep_for(10ms); wf_impl_timer_manager_check(timer_manager); ASSERT_TRUE(finished_context.is_called); - ASSERT_EQ(WF_BAD_TIMEOUT, jsonrpc_get_status(finished_context.error)); + ASSERT_EQ(WF_BAD_TIMEOUT, wf_impl_jsonrpc_error_code(finished_context.error)); wf_impl_jsonrpc_proxy_dispose(proxy); wf_impl_timer_manager_dispose(timer_manager); @@ -323,7 +300,7 @@ TEST(wf_jsonrpc_proxy, cleanup_pending_request) wf_impl_jsonrpc_proxy_invoke(proxy, &jsonrpc_finished, finished_data, "foo", "si", "bar", 42); ASSERT_TRUE(send_context.is_called); - ASSERT_TRUE(json_is_object(send_context.response)); + ASSERT_TRUE(wf_impl_json_is_object(send_context.response)); ASSERT_FALSE(finished_context.is_called); @@ -347,28 +324,28 @@ TEST(wf_jsonrpc_proxy, notify) wf_impl_jsonrpc_proxy_notify(proxy, "foo", "si", "bar", 42); ASSERT_TRUE(send_context.is_called); - ASSERT_TRUE(json_is_object(send_context.response)); + ASSERT_TRUE(wf_impl_json_is_object(send_context.response)); - json_t * method = json_object_get(send_context.response, "method"); - ASSERT_TRUE(json_is_string(method)); - ASSERT_STREQ("foo", json_string_value(method)); + wf_json const * method = wf_impl_json_object_get(send_context.response, "method"); + ASSERT_TRUE(wf_impl_json_is_string(method)); + ASSERT_STREQ("foo", wf_impl_json_string_get(method)); - json_t * params = json_object_get(send_context.response, "params"); - ASSERT_TRUE(json_is_array(params)); - ASSERT_EQ(2, json_array_size(params)); - ASSERT_TRUE(json_is_string(json_array_get(params, 0))); - ASSERT_STREQ("bar", json_string_value(json_array_get(params, 0))); - ASSERT_TRUE(json_is_integer(json_array_get(params, 1))); - ASSERT_EQ(42, json_integer_value(json_array_get(params, 1))); + wf_json const * params = wf_impl_json_object_get(send_context.response, "params"); + ASSERT_TRUE(wf_impl_json_is_array(params)); + ASSERT_EQ(2, wf_impl_json_array_size(params)); + ASSERT_TRUE(wf_impl_json_is_string(wf_impl_json_array_get(params, 0))); + ASSERT_STREQ("bar", wf_impl_json_string_get(wf_impl_json_array_get(params, 0))); + ASSERT_TRUE(wf_impl_json_is_int(wf_impl_json_array_get(params, 1))); + ASSERT_EQ(42, wf_impl_json_int_get(wf_impl_json_array_get(params, 1))); - json_t * id = json_object_get(send_context.response, "id"); - ASSERT_EQ(nullptr, id); + wf_json const * id = wf_impl_json_object_get(send_context.response, "id"); + ASSERT_TRUE(wf_impl_json_is_undefined(id)); wf_impl_jsonrpc_proxy_dispose(proxy); wf_impl_timer_manager_dispose(timer_manager); } -TEST(wf_jsonrpc_proxy, notify_dont_send_invalid_request) +TEST(wf_jsonrpc_proxy, notify_send_invalid_request) { struct wf_timer_manager * timer_manager = wf_impl_timer_manager_create(); @@ -378,7 +355,7 @@ TEST(wf_jsonrpc_proxy, notify_dont_send_invalid_request) wf_impl_jsonrpc_proxy_notify(proxy, "foo", "?"); - ASSERT_FALSE(send_context.is_called); + ASSERT_TRUE(send_context.is_called); wf_impl_jsonrpc_proxy_dispose(proxy); wf_impl_timer_manager_dispose(timer_manager); @@ -392,12 +369,8 @@ TEST(wf_jsonrpc_proxy, on_result_swallow_if_no_request_pending) void * send_data = reinterpret_cast(&send_context); struct wf_jsonrpc_proxy * proxy = wf_impl_jsonrpc_proxy_create(timer_manager, WF_DEFAULT_TIMEOUT, &jsonrpc_send, send_data); - json_t * response = json_object(); - json_object_set_new(response, "result", json_string("okay")); - json_object_set_new(response, "id", json_integer(42)); - - wf_impl_jsonrpc_proxy_onresult(proxy, response); - json_decref(response); + JsonDoc response("{\"result\": \"okay\", \"id\": 42}"); + wf_impl_jsonrpc_proxy_onresult(proxy, response.root()); wf_impl_jsonrpc_proxy_dispose(proxy); wf_impl_timer_manager_dispose(timer_manager); diff --git a/test/webfuse/jsonrpc/test_request.cc b/test/webfuse/jsonrpc/test_request.cc index 6152ecb..a2031f3 100644 --- a/test/webfuse/jsonrpc/test_request.cc +++ b/test/webfuse/jsonrpc/test_request.cc @@ -1,23 +1,29 @@ -#include #include "webfuse/impl/jsonrpc/request.h" +#include "webfuse/impl/json/node.h" +#include "webfuse/impl/message.h" #include "webfuse/status.h" +#include "webfuse/test_util/json_doc.hpp" + +#include + +using webfuse_test::JsonDoc; namespace { struct Context { - json_t * response; + std::string response; }; bool jsonrpc_send( - json_t * request, + wf_message * request, void * user_data) { Context * context = reinterpret_cast(user_data); - context->response = request; - json_incref(request); + context->response = std::string(request->data, request->length); + wf_impl_message_dispose(request); return true; } @@ -25,7 +31,7 @@ bool jsonrpc_send( TEST(wf_jsonrpc_request, create_dispose) { - Context context{nullptr}; + Context context; void * user_data = reinterpret_cast(&context); struct wf_jsonrpc_request * request = @@ -39,36 +45,31 @@ TEST(wf_jsonrpc_request, create_dispose) TEST(wf_jsonrpc_request, respond) { - Context context{nullptr}; + Context context; void * user_data = reinterpret_cast(&context); struct wf_jsonrpc_request * request = wf_impl_jsonrpc_request_create(42, &jsonrpc_send, user_data); - wf_impl_jsonrpc_respond(request, json_string("okay")); + wf_impl_jsonrpc_respond(request); - ASSERT_NE(nullptr, context.response); - - - json_t * response = reinterpret_cast(context.response); - ASSERT_TRUE(json_is_object(response)); + JsonDoc doc(context.response); + struct wf_json const * response = doc.root(); + ASSERT_TRUE(wf_impl_json_is_object(response)); - json_t * id = json_object_get(response, "id"); - ASSERT_TRUE(json_is_integer(id)); - ASSERT_EQ(42, json_integer_value(id)); + struct wf_json const * id = wf_impl_json_object_get(response, "id"); + ASSERT_TRUE(wf_impl_json_is_int(id)); + ASSERT_EQ(42, wf_impl_json_int_get(id)); - json_t * result = json_object_get(response, "result"); - ASSERT_TRUE(json_is_string(result)); - ASSERT_STREQ("okay", json_string_value(result)); + struct wf_json const * result = wf_impl_json_object_get(response, "result"); + ASSERT_TRUE(wf_impl_json_is_object(result)); - ASSERT_EQ(nullptr, json_object_get(response, "error")); - - json_decref(response); + ASSERT_TRUE(wf_impl_json_is_undefined(wf_impl_json_object_get(response, "error"))); } TEST(wf_jsonrpc_request, respond_error) { - Context context{nullptr}; + Context context; void * user_data = reinterpret_cast(&context); struct wf_jsonrpc_request * request = @@ -76,63 +77,24 @@ TEST(wf_jsonrpc_request, respond_error) wf_impl_jsonrpc_respond_error(request, WF_BAD, "Bad"); - ASSERT_NE(nullptr, context.response); - - - json_t * response = reinterpret_cast(context.response); - ASSERT_TRUE(json_is_object(response)); + JsonDoc doc(context.response); + struct wf_json const * response = doc.root(); + ASSERT_TRUE(wf_impl_json_is_object(response)); - json_t * id = json_object_get(response, "id"); - ASSERT_TRUE(json_is_integer(id)); - ASSERT_EQ(42, json_integer_value(id)); + struct wf_json const * id = wf_impl_json_object_get(response, "id"); + ASSERT_TRUE(wf_impl_json_is_int(id)); + ASSERT_EQ(42, wf_impl_json_int_get(id)); - ASSERT_EQ(nullptr, json_object_get(response, "result")); + ASSERT_TRUE(wf_impl_json_is_undefined(wf_impl_json_object_get(response, "result"))); - json_t * err = json_object_get(response, "error"); - ASSERT_TRUE(json_is_object(err)); + struct wf_json const * err = wf_impl_json_object_get(response, "error"); + ASSERT_TRUE(wf_impl_json_is_object(err)); - json_t * err_code = json_object_get(err, "code"); - ASSERT_TRUE(json_is_integer(err_code)); - ASSERT_EQ(WF_BAD, json_integer_value(err_code)); + struct wf_json const * err_code = wf_impl_json_object_get(err, "code"); + ASSERT_TRUE(wf_impl_json_is_int(err_code)); + ASSERT_EQ(WF_BAD, wf_impl_json_int_get(err_code)); - json_t * err_message = json_object_get(err, "message"); - ASSERT_TRUE(json_is_string(err_message)); - ASSERT_STREQ("Bad", json_string_value(err_message)); - - json_decref(response); -} - -TEST(wf_jsonrpc_request, is_request_object_params) -{ - json_t * request = json_object(); - json_object_set_new(request, "method", json_string("some_method")); - json_object_set_new(request, "params", json_object()); - json_object_set_new(request, "id", json_integer(42)); - - ASSERT_TRUE(wf_impl_jsonrpc_is_request(request)); - - json_decref(request); -} - -TEST(wf_jsonrpc_request, is_request_fail_missing_params) -{ - json_t * request = json_object(); - json_object_set_new(request, "method", json_string("some_method")); - json_object_set_new(request, "id", json_integer(42)); - - ASSERT_FALSE(wf_impl_jsonrpc_is_request(request)); - - json_decref(request); -} - -TEST(wf_jsonrpc_request, is_request_fail_params_wrong_type) -{ - json_t * request = json_object(); - json_object_set_new(request, "method", json_string("some_method")); - json_object_set_new(request, "params", json_string("invalid_params")); - json_object_set_new(request, "id", json_integer(42)); - - ASSERT_FALSE(wf_impl_jsonrpc_is_request(request)); - - json_decref(request); + struct wf_json const * err_message = wf_impl_json_object_get(err, "message"); + ASSERT_TRUE(wf_impl_json_is_string(err_message)); + ASSERT_STREQ("Bad", wf_impl_json_string_get(err_message)); } diff --git a/test/webfuse/jsonrpc/test_response.cc b/test/webfuse/jsonrpc/test_response.cc index 0a92b29..c0d4d14 100644 --- a/test/webfuse/jsonrpc/test_response.cc +++ b/test/webfuse/jsonrpc/test_response.cc @@ -1,147 +1,123 @@ -#include #include "webfuse/impl/jsonrpc/response_intern.h" +#include "webfuse/impl/jsonrpc/error.h" +#include "webfuse/impl/json/node.h" #include "webfuse/status.h" +#include "webfuse/test_util/json_doc.hpp" + +#include + +using webfuse_test::JsonDoc; TEST(wf_json_response, init_result) { - json_t * message = json_object(); - json_object_set_new(message, "result", json_integer(47)); - json_object_set_new(message, "id", json_integer(11)); + JsonDoc doc("{\"result\": 47, \"id\": 11}"); struct wf_jsonrpc_response response; - wf_impl_jsonrpc_response_init(&response, message); + wf_impl_jsonrpc_response_init(&response, doc.root()); ASSERT_EQ(nullptr, response.error); - ASSERT_TRUE(json_is_integer(response.result)); - ASSERT_EQ(47, json_integer_value(response.result)); + ASSERT_TRUE(wf_impl_json_is_int(response.result)); + ASSERT_EQ(47, wf_impl_json_int_get(response.result)); ASSERT_EQ(11, response.id); wf_impl_jsonrpc_response_cleanup(&response); - json_decref(message); } TEST(wf_json_response, init_error) { - json_t * message = json_object(); - json_t * err = json_object(); - json_object_set_new(err, "code", json_integer(42)); - json_object_set_new(err, "message", json_string("Don't Panic!")); - json_object_set_new(message, "error", err); - json_object_set_new(message, "id", json_integer(23)); + JsonDoc doc("{\"error\": {\"code\": 42, \"message\": \"Don't Panic!\"}, \"id\": 23}"); struct wf_jsonrpc_response response; - wf_impl_jsonrpc_response_init(&response, message); + wf_impl_jsonrpc_response_init(&response, doc.root()); - ASSERT_EQ(42, json_integer_value(json_object_get(response.error, "code"))); - ASSERT_STREQ("Don't Panic!", json_string_value(json_object_get(response.error, "message"))); + ASSERT_EQ(42, wf_impl_jsonrpc_error_code(response.error)); + ASSERT_STREQ("Don't Panic!", wf_impl_jsonrpc_error_message(response.error)); ASSERT_EQ(nullptr, response.result); ASSERT_EQ(23, response.id); wf_impl_jsonrpc_response_cleanup(&response); - json_decref(message); } TEST(wf_json_response, init_fail_missing_result_and_error) { - json_t * message = json_object(); - json_object_set_new(message, "id", json_integer(12)); + JsonDoc doc("{\"id\": 12}"); struct wf_jsonrpc_response response; - wf_impl_jsonrpc_response_init(&response, message); + wf_impl_jsonrpc_response_init(&response, doc.root()); - ASSERT_EQ(WF_BAD_FORMAT, json_integer_value(json_object_get(response.error, "code"))); + ASSERT_EQ(WF_BAD_FORMAT, wf_impl_jsonrpc_error_code(response.error)); ASSERT_EQ(nullptr, response.result); ASSERT_EQ(12, response.id); wf_impl_jsonrpc_response_cleanup(&response); - json_decref(message); } TEST(wf_json_response, init_fail_missing_id) { - json_t * message = json_object(); - json_object_set_new(message, "result", json_integer(47)); + JsonDoc doc("{\"result\": 47}"); struct wf_jsonrpc_response response; - wf_impl_jsonrpc_response_init(&response, message); + wf_impl_jsonrpc_response_init(&response, doc.root()); - ASSERT_EQ(WF_BAD_FORMAT, json_integer_value(json_object_get(response.error, "code"))); + ASSERT_EQ(WF_BAD_FORMAT, wf_impl_jsonrpc_error_code(response.error)); ASSERT_EQ(nullptr, response.result); ASSERT_EQ(-1, response.id); wf_impl_jsonrpc_response_cleanup(&response); - json_decref(message); } TEST(wf_json_response, init_fail_wrong_id_type) { - json_t * message = json_object(); - json_object_set_new(message, "result", json_integer(47)); - json_object_set_new(message, "id", json_string("42")); + JsonDoc doc("{\"result\": 47, \"id\": \"42\"}"); struct wf_jsonrpc_response response; - wf_impl_jsonrpc_response_init(&response, message); + wf_impl_jsonrpc_response_init(&response, doc.root()); - ASSERT_EQ(WF_BAD_FORMAT, json_integer_value(json_object_get(response.error, "code"))); + ASSERT_EQ(WF_BAD_FORMAT, wf_impl_jsonrpc_error_code(response.error)); ASSERT_EQ(nullptr, response.result); ASSERT_EQ(-1, response.id); wf_impl_jsonrpc_response_cleanup(&response); - json_decref(message); } TEST(wf_json_response, init_fail_error_missing_code) { - json_t * message = json_object(); - json_t * err = json_object(); - json_object_set_new(err, "message", json_string("Don't Panic!")); - json_object_set_new(message, "error", err); - json_object_set_new(message, "id", json_integer(23)); + JsonDoc doc("{\"error\": {\"message\": \"Don't Panic!\"}, \"id\": 23}"); struct wf_jsonrpc_response response; - wf_impl_jsonrpc_response_init(&response, message); + wf_impl_jsonrpc_response_init(&response, doc.root()); - ASSERT_EQ(WF_BAD_FORMAT, json_integer_value(json_object_get(response.error, "code"))); + ASSERT_EQ(WF_BAD_FORMAT, wf_impl_jsonrpc_error_code(response.error)); ASSERT_EQ(nullptr, response.result); ASSERT_EQ(23, response.id); wf_impl_jsonrpc_response_cleanup(&response); - json_decref(message); } TEST(wf_json_response, init_fail_error_wrong_code_type) { - json_t * message = json_object(); - json_t * err = json_object(); - json_object_set_new(err, "code", json_string("42")); - json_object_set_new(err, "message", json_string("Don't Panic!")); - json_object_set_new(message, "error", err); - json_object_set_new(message, "id", json_integer(23)); + JsonDoc doc("{\"error\": {\"code\": \"42\", \"message\": \"Don't Panic!\"}, \"id\": 23}"); struct wf_jsonrpc_response response; - wf_impl_jsonrpc_response_init(&response, message); + wf_impl_jsonrpc_response_init(&response, doc.root()); - ASSERT_EQ(WF_BAD_FORMAT, json_integer_value(json_object_get(response.error, "code"))); + ASSERT_EQ(WF_BAD_FORMAT, wf_impl_jsonrpc_error_code(response.error)); ASSERT_EQ(nullptr, response.result); ASSERT_EQ(23, response.id); wf_impl_jsonrpc_response_cleanup(&response); - json_decref(message); } TEST(wf_json_response, init_fail_error_wrong_type) { - json_t * message = json_object(); - json_object_set_new(message, "error", json_string("invalid error type")); - json_object_set_new(message, "id", json_integer(23)); + JsonDoc doc("{\"error\": \"invalid error type\", \"id\": 23}"); struct wf_jsonrpc_response response; - wf_impl_jsonrpc_response_init(&response, message); + wf_impl_jsonrpc_response_init(&response, doc.root()); - ASSERT_EQ(WF_BAD_FORMAT, json_integer_value(json_object_get(response.error, "code"))); + ASSERT_EQ(WF_BAD_FORMAT, wf_impl_jsonrpc_error_code(response.error)); ASSERT_EQ(nullptr, response.result); ASSERT_EQ(23, response.id); wf_impl_jsonrpc_response_cleanup(&response); - json_decref(message); } diff --git a/test/webfuse/jsonrpc/test_response_parser.cc b/test/webfuse/jsonrpc/test_response_parser.cc index 7d944d4..25f4dc1 100644 --- a/test/webfuse/jsonrpc/test_response_parser.cc +++ b/test/webfuse/jsonrpc/test_response_parser.cc @@ -1,56 +1,68 @@ -#include -#include #include "webfuse/impl/jsonrpc/response_intern.h" +#include "webfuse/impl/jsonrpc/error.h" +#include "webfuse/test_util/json_doc.hpp" +#include +#include -static void response_parse_str( - std::string const & buffer, - struct wf_jsonrpc_response * response) +using webfuse_test::JsonDoc; + +TEST(response_parser, invalid_no_object) { - json_t * message = json_loadb(buffer.c_str(), buffer.size(), 0, nullptr); - if (nullptr != message) - { - wf_impl_jsonrpc_response_init(response, message); - json_decref(message); - } + JsonDoc doc("[]"); + struct wf_jsonrpc_response response; + wf_impl_jsonrpc_response_init(&response, doc.root()); + + ASSERT_NE(nullptr, response.error); + ASSERT_EQ(-1, response.id); + ASSERT_EQ(nullptr, response.result); + wf_impl_jsonrpc_response_cleanup(&response); } -TEST(response_parser, test) +TEST(response_parser, invalid_empty_object) { + JsonDoc doc("{}"); struct wf_jsonrpc_response response; + wf_impl_jsonrpc_response_init(&response, doc.root()); - // no object - response_parse_str("[]", &response); ASSERT_NE(nullptr, response.error); ASSERT_EQ(-1, response.id); ASSERT_EQ(nullptr, response.result); wf_impl_jsonrpc_response_cleanup(&response); +} - // empty - response_parse_str("{}", &response); - ASSERT_NE(nullptr, response.error); - ASSERT_EQ(-1, response.id); - ASSERT_EQ(nullptr, response.result); - wf_impl_jsonrpc_response_cleanup(&response); +TEST(response_parser, invalid_missin_result_and_error) +{ + JsonDoc doc("{\"id\":42}"); + struct wf_jsonrpc_response response; + wf_impl_jsonrpc_response_init(&response, doc.root()); - // no data - response_parse_str("{\"id\":42}", &response); ASSERT_NE(nullptr, response.error); ASSERT_EQ(42, response.id); ASSERT_EQ(nullptr, response.result); wf_impl_jsonrpc_response_cleanup(&response); +} + +TEST(response_parser, custom_error_code) +{ + JsonDoc doc("{\"error\":{\"code\": 42}, \"id\": 42}"); + struct wf_jsonrpc_response response; + wf_impl_jsonrpc_response_init(&response, doc.root()); - // custom error code - response_parse_str("{\"error\":{\"code\": 42}, \"id\": 42}", &response); ASSERT_NE(nullptr, response.error); - ASSERT_EQ(42, json_integer_value(json_object_get(response.error, "code"))); + ASSERT_EQ(42, wf_impl_jsonrpc_error_code(response.error)); ASSERT_EQ(42, response.id); ASSERT_EQ(nullptr, response.result); wf_impl_jsonrpc_response_cleanup(&response); +} + +TEST(response_parser, valid_response) +{ + JsonDoc doc("{\"result\": true, \"id\": 42}"); + struct wf_jsonrpc_response response; + wf_impl_jsonrpc_response_init(&response, doc.root()); - // valid response - response_parse_str("{\"result\": true, \"id\": 42}", &response); ASSERT_EQ(nullptr, response.error); ASSERT_EQ(42, response.id); ASSERT_NE(nullptr, response.result); diff --git a/test/webfuse/jsonrpc/test_server.cc b/test/webfuse/jsonrpc/test_server.cc index c9425d5..884d98a 100644 --- a/test/webfuse/jsonrpc/test_server.cc +++ b/test/webfuse/jsonrpc/test_server.cc @@ -1,40 +1,56 @@ #include #include "webfuse/impl/jsonrpc/server.h" #include "webfuse/impl/jsonrpc/request.h" +#include "webfuse/impl/json/node.h" +#include "webfuse/impl/message.h" #include "webfuse/status.h" +#include "webfuse/test_util/json_doc.hpp" + +using webfuse_test::JsonDoc; + namespace { - struct Context + class Context { - json_t * response; + public: + Context() + : doc("{}") + , response(nullptr) + , is_called(false) + { + + } + + JsonDoc doc; + wf_json const * response; bool is_called; }; bool jsonrpc_send( - json_t * request, + wf_message * request, void * user_data) { Context * context = reinterpret_cast(user_data); context->is_called = true; - context->response = request; - json_incref(request); + context->doc = std::move(JsonDoc(std::string(request->data, request->length))); + context->response = context->doc.root(); + wf_impl_message_dispose(request); return true; } void sayHello( struct wf_jsonrpc_request * request, char const * method_name, - json_t * params, + wf_json const * params, void * user_data) { (void) method_name; (void) params; (void) user_data; - json_t * result = json_string("Hello"); - wf_impl_jsonrpc_respond(request, result); + wf_impl_jsonrpc_respond(request); } } @@ -44,58 +60,47 @@ TEST(wf_jsonrpc_server, process_request) struct wf_jsonrpc_server * server = wf_impl_jsonrpc_server_create(); wf_impl_jsonrpc_server_add(server, "sayHello", &sayHello, nullptr); - Context context{nullptr, false}; + Context context; void * user_data = reinterpret_cast(&context); - json_t * request = json_object(); - json_object_set_new(request, "method", json_string("sayHello")); - json_object_set_new(request, "params", json_array()); - json_object_set_new(request, "id", json_integer(23)); - wf_impl_jsonrpc_server_process(server, request, &jsonrpc_send, user_data); + + JsonDoc request("{\"method\": \"sayHello\", \"params\": [], \"id\": 23}"); + wf_impl_jsonrpc_server_process(server, request.root(), &jsonrpc_send, user_data); ASSERT_TRUE(context.is_called); ASSERT_NE(nullptr, context.response); - ASSERT_TRUE(json_is_object(context.response)); + ASSERT_TRUE(wf_impl_json_is_object(context.response)); - json_t * id = json_object_get(context.response, "id"); - ASSERT_TRUE(json_is_integer(id)); - ASSERT_EQ(23, json_integer_value(id)); + struct wf_json const * id = wf_impl_json_object_get(context.response, "id"); + ASSERT_TRUE(wf_impl_json_is_int(id)); + ASSERT_EQ(23, wf_impl_json_int_get(id)); - json_t * result = json_object_get(context.response, "result"); - ASSERT_TRUE(json_is_string(result)); - ASSERT_STREQ("Hello", json_string_value(result)); + struct wf_json const * result = wf_impl_json_object_get(context.response, "result"); + ASSERT_TRUE(wf_impl_json_is_object(result)); - json_decref(context.response); - json_decref(request); wf_impl_jsonrpc_server_dispose(server); } -TEST(wf_jsonrpc_server, process_request_with_oject_params) +TEST(wf_jsonrpc_server, process_request_with_object_params) { struct wf_jsonrpc_server * server = wf_impl_jsonrpc_server_create(); wf_impl_jsonrpc_server_add(server, "sayHello", &sayHello, nullptr); - Context context{nullptr, false}; + Context context; void * user_data = reinterpret_cast(&context); - json_t * request = json_object(); - json_object_set_new(request, "method", json_string("sayHello")); - json_object_set_new(request, "params", json_object()); - json_object_set_new(request, "id", json_integer(23)); - wf_impl_jsonrpc_server_process(server, request, &jsonrpc_send, user_data); + JsonDoc request("{\"method\": \"sayHello\", \"params\": {}, \"id\": 23}"); + wf_impl_jsonrpc_server_process(server, request.root(), &jsonrpc_send, user_data); ASSERT_TRUE(context.is_called); ASSERT_NE(nullptr, context.response); - ASSERT_TRUE(json_is_object(context.response)); + ASSERT_TRUE(wf_impl_json_is_object(context.response)); - json_t * id = json_object_get(context.response, "id"); - ASSERT_TRUE(json_is_integer(id)); - ASSERT_EQ(23, json_integer_value(id)); + struct wf_json const * id = wf_impl_json_object_get(context.response, "id"); + ASSERT_TRUE(wf_impl_json_is_int(id)); + ASSERT_EQ(23, wf_impl_json_int_get(id)); - json_t * result = json_object_get(context.response, "result"); - ASSERT_TRUE(json_is_string(result)); - ASSERT_STREQ("Hello", json_string_value(result)); + struct wf_json const * result = wf_impl_json_object_get(context.response, "result"); + ASSERT_TRUE(wf_impl_json_is_object(result)); - json_decref(context.response); - json_decref(request); wf_impl_jsonrpc_server_dispose(server); } @@ -104,34 +109,29 @@ TEST(wf_jsonrpc_server, invoke_unknown_method) struct wf_jsonrpc_server * server = wf_impl_jsonrpc_server_create(); wf_impl_jsonrpc_server_add(server, "sayHello", &sayHello, nullptr); - Context context{nullptr, false}; + Context context; void * user_data = reinterpret_cast(&context); - json_t * request = json_object(); - json_object_set_new(request, "method", json_string("greet")); - json_object_set_new(request, "params", json_array()); - json_object_set_new(request, "id", json_integer(42)); - wf_impl_jsonrpc_server_process(server, request, &jsonrpc_send, user_data); + JsonDoc request("{\"method\": \"greet\", \"params\": [], \"id\": 42}"); + wf_impl_jsonrpc_server_process(server, request.root(), &jsonrpc_send, user_data); ASSERT_TRUE(context.is_called); ASSERT_NE(nullptr, context.response); - ASSERT_TRUE(json_is_object(context.response)); + ASSERT_TRUE(wf_impl_json_is_object(context.response)); - json_t * id = json_object_get(context.response, "id"); - ASSERT_TRUE(json_is_integer(id)); - ASSERT_EQ(42, json_integer_value(id)); + struct wf_json const * id = wf_impl_json_object_get(context.response, "id"); + ASSERT_TRUE(wf_impl_json_is_int(id)); + ASSERT_EQ(42, wf_impl_json_int_get(id)); - json_t * err = json_object_get(context.response, "error"); - ASSERT_TRUE(json_is_object(err)); + struct wf_json const * err = wf_impl_json_object_get(context.response, "error"); + ASSERT_TRUE(wf_impl_json_is_object(err)); - json_t * err_code = json_object_get(err, "code"); - ASSERT_TRUE(json_is_integer(err_code)); - ASSERT_EQ(WF_BAD_NOTIMPLEMENTED, json_integer_value(err_code)); + struct wf_json const * err_code = wf_impl_json_object_get(err, "code"); + ASSERT_TRUE(wf_impl_json_is_int(err_code)); + ASSERT_EQ(WF_BAD_NOTIMPLEMENTED, wf_impl_json_int_get(err_code)); - json_t * err_message = json_object_get(err, "message"); - ASSERT_TRUE(json_is_string(err_message)); + struct wf_json const * err_message = wf_impl_json_object_get(err, "message"); + ASSERT_TRUE(wf_impl_json_is_string(err_message)); - json_decref(context.response); - json_decref(request); wf_impl_jsonrpc_server_dispose(server); } @@ -139,16 +139,13 @@ TEST(wf_jsonrpc_server, skip_invalid_request_missing_id) { struct wf_jsonrpc_server * server = wf_impl_jsonrpc_server_create(); - Context context{nullptr, false}; + Context context; void * user_data = reinterpret_cast(&context); - json_t * request = json_object(); - json_object_set_new(request, "method", json_string("sayHello")); - json_object_set_new(request, "params", json_array()); - wf_impl_jsonrpc_server_process(server, request, &jsonrpc_send, user_data); + JsonDoc request("{\"method\": \"sayHello\", \"params\": []}"); + wf_impl_jsonrpc_server_process(server, request.root(), &jsonrpc_send, user_data); ASSERT_FALSE(context.is_called); - json_decref(request); wf_impl_jsonrpc_server_dispose(server); } @@ -156,17 +153,13 @@ TEST(wf_jsonrpc_server, skip_invalid_request_wrong_id_type) { struct wf_jsonrpc_server * server = wf_impl_jsonrpc_server_create(); - Context context{nullptr, false}; + Context context; void * user_data = reinterpret_cast(&context); - json_t * request = json_object(); - json_object_set_new(request, "method", json_string("sayHello")); - json_object_set_new(request, "params", json_array()); - json_object_set_new(request, "id", json_string("42")); - wf_impl_jsonrpc_server_process(server, request, &jsonrpc_send, user_data); + JsonDoc request("{\"method\": \"sayHello\", \"params\": [], \"id\": \"42\"}"); + wf_impl_jsonrpc_server_process(server, request.root(), &jsonrpc_send, user_data); ASSERT_FALSE(context.is_called); - json_decref(request); wf_impl_jsonrpc_server_dispose(server); } @@ -174,16 +167,13 @@ TEST(wf_jsonrpc_server, skip_invalid_request_missing_params) { struct wf_jsonrpc_server * server = wf_impl_jsonrpc_server_create(); - Context context{nullptr, false}; + Context context; void * user_data = reinterpret_cast(&context); - json_t * request = json_object(); - json_object_set_new(request, "method", json_string("sayHello")); - json_object_set_new(request, "id", json_integer(42)); - wf_impl_jsonrpc_server_process(server, request, &jsonrpc_send, user_data); + JsonDoc request("{\"method\": \"sayHello\", \"id\": 23}"); + wf_impl_jsonrpc_server_process(server, request.root(), &jsonrpc_send, user_data); ASSERT_FALSE(context.is_called); - json_decref(request); wf_impl_jsonrpc_server_dispose(server); } @@ -191,17 +181,13 @@ TEST(wf_jsonrpc_server, skip_invalid_request_wrong_params_type) { struct wf_jsonrpc_server * server = wf_impl_jsonrpc_server_create(); - Context context{nullptr, false}; + Context context; void * user_data = reinterpret_cast(&context); - json_t * request = json_object(); - json_object_set_new(request, "method", json_string("sayHello")); - json_object_set_new(request, "params", json_string("invalid")); - json_object_set_new(request, "id", json_integer(42)); - wf_impl_jsonrpc_server_process(server, request, &jsonrpc_send, user_data); + JsonDoc request("{\"method\": \"sayHello\", \"params\": \"invalid\", \"id\": 42}"); + wf_impl_jsonrpc_server_process(server, request.root(), &jsonrpc_send, user_data); ASSERT_FALSE(context.is_called); - json_decref(request); wf_impl_jsonrpc_server_dispose(server); } @@ -209,16 +195,13 @@ TEST(wf_jsonrpc_server, skip_invalid_request_missing_method) { struct wf_jsonrpc_server * server = wf_impl_jsonrpc_server_create(); - Context context{nullptr, false}; + Context context; void * user_data = reinterpret_cast(&context); - json_t * request = json_object(); - json_object_set_new(request, "params", json_array()); - json_object_set_new(request, "id", json_integer(42)); - wf_impl_jsonrpc_server_process(server, request, &jsonrpc_send, user_data); + JsonDoc request("{\"params\": [], \"id\": 23}"); + wf_impl_jsonrpc_server_process(server, request.root(), &jsonrpc_send, user_data); ASSERT_FALSE(context.is_called); - json_decref(request); wf_impl_jsonrpc_server_dispose(server); } @@ -226,16 +209,12 @@ TEST(wf_jsonrpc_server, skip_invalid_request_wront_method_type) { struct wf_jsonrpc_server * server = wf_impl_jsonrpc_server_create(); - Context context{nullptr, false}; + Context context; void * user_data = reinterpret_cast(&context); - json_t * request = json_object(); - json_object_set_new(request, "method", json_integer(42)); - json_object_set_new(request, "params", json_array()); - json_object_set_new(request, "id", json_integer(42)); - wf_impl_jsonrpc_server_process(server, request, &jsonrpc_send, user_data); + JsonDoc request("{\"method\": 42, \"params\": [], \"id\": 23}"); + wf_impl_jsonrpc_server_process(server, request.root(), &jsonrpc_send, user_data); ASSERT_FALSE(context.is_called); - json_decref(request); wf_impl_jsonrpc_server_dispose(server); } \ No newline at end of file diff --git a/test/webfuse/mocks/getattr_matcher.hpp b/test/webfuse/mocks/getattr_matcher.hpp index c1f6cbb..2b53eff 100644 --- a/test/webfuse/mocks/getattr_matcher.hpp +++ b/test/webfuse/mocks/getattr_matcher.hpp @@ -1,31 +1,31 @@ #ifndef WF_GETATTR_MATCHER_HPP #define WF_GETATTR_MATCHER_HPP +#include "webfuse/impl/json/node.h" #include -#include namespace webfuse_test { MATCHER_P(GetAttr, inode, "") { - if (!json_is_array(arg)) + if (!wf_impl_json_is_array(arg)) { *result_listener << "json array expected"; return false; } - json_t * inode_ = json_array_get(arg, 1); - if (!json_is_integer(inode_)) + wf_json const * inode_ = wf_impl_json_array_get(arg, 1); + if (!wf_impl_json_is_int(inode_)) { *result_listener << "inode is expectoed to an integer"; return false; } - if (inode != json_integer_value(inode_)) + if (inode != wf_impl_json_int_get(inode_)) { *result_listener << "inode mismatch: expected" << inode - << " but was " << json_integer_value(inode_); + << " but was " << wf_impl_json_int_get(inode_); return false; } diff --git a/test/webfuse/mocks/lookup_matcher.hpp b/test/webfuse/mocks/lookup_matcher.hpp index e9c5a55..7c9b761 100644 --- a/test/webfuse/mocks/lookup_matcher.hpp +++ b/test/webfuse/mocks/lookup_matcher.hpp @@ -1,8 +1,8 @@ #ifndef WF_LOOKUP_MATCHER_HPP #define WF_LOOKUP_MATCHER_HPP +#include "webfuse/impl/json/node.h" #include -#include #include namespace webfuse_test @@ -10,35 +10,35 @@ namespace webfuse_test MATCHER_P2(Lookup, parent, name, "") { - if (!json_is_array(arg)) + if (!wf_impl_json_is_array(arg)) { *result_listener << "json array expected"; return false; } - json_t * parent_ = json_array_get(arg, 1); - if (!json_is_integer(parent_)) + wf_json const * parent_ = wf_impl_json_array_get(arg, 1); + if (!wf_impl_json_is_int(parent_)) { *result_listener << "parent is expected to be an integer"; return false; } - if (parent != json_integer_value(parent_)) + if (parent != wf_impl_json_int_get(parent_)) { *result_listener << "parent mismatch: expected " << parent - << " but was " << json_integer_value(parent_); + << " but was " << wf_impl_json_int_get(parent_); return false; } - json_t * name_ = json_array_get(arg, 2); - if (!json_is_string(name_)) + wf_json const * name_ = wf_impl_json_array_get(arg, 2); + if (!wf_impl_json_is_string(name_)) { *result_listener << "name is expected to be a string"; return false; } - if (0 != strcmp(name, json_string_value(name_))) + if (0 != strcmp(name, wf_impl_json_string_get(name_))) { *result_listener << "name mismatch: expected \"" << name - << "\" but was \"" << json_string_value(name_) << "\""; + << "\" but was \"" << wf_impl_json_string_get(name_) << "\""; return false; } diff --git a/test/webfuse/mocks/mock_invokation_handler.hpp b/test/webfuse/mocks/mock_invokation_handler.hpp index 9c79159..ef5721b 100644 --- a/test/webfuse/mocks/mock_invokation_handler.hpp +++ b/test/webfuse/mocks/mock_invokation_handler.hpp @@ -10,7 +10,7 @@ namespace webfuse_test class MockInvokationHander: public InvokationHandler { public: - MOCK_METHOD2(Invoke, std::string(char const * method, json_t * params)); + MOCK_METHOD2(Invoke, std::string(char const * method, wf_json const * params)); }; } diff --git a/test/webfuse/mocks/open_matcher.hpp b/test/webfuse/mocks/open_matcher.hpp index 1bc7bf4..b34c987 100644 --- a/test/webfuse/mocks/open_matcher.hpp +++ b/test/webfuse/mocks/open_matcher.hpp @@ -1,31 +1,31 @@ #ifndef WF_OPEN_MATCHER_HPP #define WF_OPEN_MATCHER_HPP +#include "webfuse/impl/json/node.h" #include -#include namespace webfuse_test { MATCHER_P(Open, inode, "") { - if (!json_is_array(arg)) + if (!wf_impl_json_is_array(arg)) { *result_listener << "json array expected"; return false; } - json_t * inode_ = json_array_get(arg, 1); - if (!json_is_integer(inode_)) + wf_json const * inode_ = wf_impl_json_array_get(arg, 1); + if (!wf_impl_json_is_int(inode_)) { *result_listener << "inode is expectoed to an integer"; return false; } - if (inode != json_integer_value(inode_)) + if (inode != wf_impl_json_int_get(inode_)) { *result_listener << "inode mismatch: expected" << inode - << " but was " << json_integer_value(inode_); + << " but was " << wf_impl_json_int_get(inode_); return false; } diff --git a/test/webfuse/mocks/readdir_matcher.hpp b/test/webfuse/mocks/readdir_matcher.hpp index 6c8134f..86355c3 100644 --- a/test/webfuse/mocks/readdir_matcher.hpp +++ b/test/webfuse/mocks/readdir_matcher.hpp @@ -2,30 +2,30 @@ #define WF_READDIR_MATCHER_HPP #include -#include +#include "webfuse/impl/json/node.h" namespace webfuse_test { MATCHER_P(ReadDir, inode, "") { - if (!json_is_array(arg)) + if (!wf_impl_json_is_array(arg)) { *result_listener << "json array expected"; return false; } - json_t * inode_ = json_array_get(arg, 1); - if (!json_is_integer(inode_)) + wf_json const * inode_ = wf_impl_json_array_get(arg, 1); + if (!wf_impl_json_is_int(inode_)) { *result_listener << "inode is expectoed to an integer"; return false; } - if (inode != json_integer_value(inode_)) + if (inode != wf_impl_json_int_get(inode_)) { *result_listener << "inode mismatch: expected" << inode - << " but was " << json_integer_value(inode_); + << " but was " << wf_impl_json_int_get(inode_); return false; } diff --git a/test/webfuse/operation/test_getattr.cc b/test/webfuse/operation/test_getattr.cc index f3ea09c..6947f6d 100644 --- a/test/webfuse/operation/test_getattr.cc +++ b/test/webfuse/operation/test_getattr.cc @@ -1,13 +1,16 @@ #include "webfuse/impl/operation/getattr.h" +#include "webfuse/impl/jsonrpc/error.h" #include "webfuse/status.h" +#include "webfuse/test_util/json_doc.hpp" #include "webfuse/mocks/mock_fuse.hpp" #include "webfuse/mocks/mock_operation_context.hpp" #include "webfuse/mocks/mock_jsonrpc_proxy.hpp" #include +using webfuse_test::JsonDoc; using webfuse_test::MockJsonRpcProxy; using webfuse_test::MockOperationContext; using webfuse_test::FuseMock; @@ -79,16 +82,13 @@ TEST(wf_impl_operation_getattr, finished_file) FuseMock fuse; EXPECT_CALL(fuse, fuse_reply_attr(_,_,_)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "mode", json_integer(0755)); - json_object_set_new(result, "type", json_string("file")); + JsonDoc result("{\"mode\": 493, \"type\": \"file\"}"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_getattr_context))); context->inode = 1; context->gid = 0; context->uid = 0; - wf_impl_operation_getattr_finished(context, result, nullptr); - json_decref(result); + wf_impl_operation_getattr_finished(context, result.root(), nullptr); } TEST(wf_impl_operation_getattr, finished_dir) @@ -96,16 +96,13 @@ TEST(wf_impl_operation_getattr, finished_dir) FuseMock fuse; EXPECT_CALL(fuse, fuse_reply_attr(_,_,_)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "mode", json_integer(0755)); - json_object_set_new(result, "type", json_string("dir")); + JsonDoc result("{\"mode\": 493, \"type\": \"dir\"}"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_getattr_context))); context->inode = 1; context->gid = 0; context->uid = 0; - wf_impl_operation_getattr_finished(context, result, nullptr); - json_decref(result); + wf_impl_operation_getattr_finished(context, result.root(), nullptr); } TEST(wf_impl_operation_getattr, finished_unknown_type) @@ -113,16 +110,13 @@ TEST(wf_impl_operation_getattr, finished_unknown_type) FuseMock fuse; EXPECT_CALL(fuse, fuse_reply_attr(_,_,_)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "mode", json_integer(0755)); - json_object_set_new(result, "type", json_string("unknown")); + JsonDoc result("{\"mode\": 493, \"type\": \"unknown\"}"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_getattr_context))); context->inode = 1; context->gid = 0; context->uid = 0; - wf_impl_operation_getattr_finished(context, result, nullptr); - json_decref(result); + wf_impl_operation_getattr_finished(context, result.root(), nullptr); } TEST(wf_impl_operation_getattr, finished_fail_missing_mode) @@ -131,15 +125,13 @@ TEST(wf_impl_operation_getattr, finished_fail_missing_mode) EXPECT_CALL(fuse, fuse_reply_open(_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "type", json_string("file")); + JsonDoc result("{\"type\": \"file\"}"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_getattr_context))); context->inode = 1; context->gid = 0; context->uid = 0; - wf_impl_operation_getattr_finished(context, result, nullptr); - json_decref(result); + wf_impl_operation_getattr_finished(context, result.root(), nullptr); } TEST(wf_impl_operation_getattr, finished_fail_invalid_mode_type) @@ -148,33 +140,28 @@ TEST(wf_impl_operation_getattr, finished_fail_invalid_mode_type) EXPECT_CALL(fuse, fuse_reply_open(_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "mode", json_string("0755")); - json_object_set_new(result, "type", json_string("file")); + JsonDoc result("{\"mode\": \"0755\", \"type\": \"file\"}"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_getattr_context))); context->inode = 1; context->gid = 0; context->uid = 0; - wf_impl_operation_getattr_finished(context, result, nullptr); - json_decref(result); + wf_impl_operation_getattr_finished(context, result.root(), nullptr); } -TEST(wf_impl_operation_getattr, finished_fail_type_mode) +TEST(wf_impl_operation_getattr, finished_fail_missing_type) { FuseMock fuse; EXPECT_CALL(fuse, fuse_reply_open(_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "mode", json_integer(0755)); + JsonDoc result("{\"mode\": 493}"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_getattr_context))); context->inode = 1; context->gid = 0; context->uid = 0; - wf_impl_operation_getattr_finished(context, result, nullptr); - json_decref(result); + wf_impl_operation_getattr_finished(context, result.root(), nullptr); } TEST(wf_impl_operation_getattr, finished_fail_invalid_type_type) @@ -183,16 +170,13 @@ TEST(wf_impl_operation_getattr, finished_fail_invalid_type_type) EXPECT_CALL(fuse, fuse_reply_open(_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "mode", json_integer(0755)); - json_object_set_new(result, "type", json_integer(42)); + JsonDoc result("{\"mode\": 493, \"type\": 42}"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_getattr_context))); context->inode = 1; context->gid = 0; context->uid = 0; - wf_impl_operation_getattr_finished(context, result, nullptr); - json_decref(result); + wf_impl_operation_getattr_finished(context, result.root(), nullptr); } TEST(wf_impl_operation_getattr, finished_error) @@ -201,13 +185,12 @@ TEST(wf_impl_operation_getattr, finished_error) EXPECT_CALL(fuse, fuse_reply_open(_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * error = json_object(); - json_object_set_new(error, "code", json_integer(WF_BAD)); + wf_jsonrpc_error * error = wf_impl_jsonrpc_error(WF_BAD, ""); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_getattr_context))); context->inode = 1; context->gid = 0; context->uid = 0; wf_impl_operation_getattr_finished(context, nullptr, error); - json_decref(error); + wf_impl_jsonrpc_error_dispose(error); } diff --git a/test/webfuse/operation/test_lookup.cc b/test/webfuse/operation/test_lookup.cc index 09dc985..4c229a9 100644 --- a/test/webfuse/operation/test_lookup.cc +++ b/test/webfuse/operation/test_lookup.cc @@ -1,13 +1,16 @@ #include "webfuse/impl/operation/lookup.h" +#include "webfuse/impl/jsonrpc/error.h" #include "webfuse/status.h" +#include "webfuse/test_util/json_doc.hpp" #include "webfuse/mocks/mock_fuse.hpp" #include "webfuse/mocks/mock_operation_context.hpp" #include "webfuse/mocks/mock_jsonrpc_proxy.hpp" #include +using webfuse_test::JsonDoc; using webfuse_test::MockJsonRpcProxy; using webfuse_test::MockOperationContext; using webfuse_test::FuseMock; @@ -77,17 +80,12 @@ TEST(wf_impl_operation_lookup, finished_file) FuseMock fuse; EXPECT_CALL(fuse, fuse_reply_entry(_,_)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "inode", json_integer(42)); - json_object_set_new(result, "mode", json_integer(0755)); - json_object_set_new(result, "type", json_string("file")); - + JsonDoc result("{\"inode\": 42, \"mode\": 493, \"type\": \"file\"}"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_lookup_context))); context->timeout = 1.0; context->gid = 0; context->uid = 0; - wf_impl_operation_lookup_finished(context, result, nullptr); - json_decref(result); + wf_impl_operation_lookup_finished(context, result.root(), nullptr); } TEST(wf_impl_operation_lookup, finished_dir) @@ -95,17 +93,12 @@ TEST(wf_impl_operation_lookup, finished_dir) FuseMock fuse; EXPECT_CALL(fuse, fuse_reply_entry(_,_)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "inode", json_integer(42)); - json_object_set_new(result, "mode", json_integer(0755)); - json_object_set_new(result, "type", json_string("dir")); - + JsonDoc result("{\"inode\": 42, \"mode\": 493, \"type\": \"dir\"}"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_lookup_context))); context->timeout = 1.0; context->gid = 0; context->uid = 0; - wf_impl_operation_lookup_finished(context, result, nullptr); - json_decref(result); + wf_impl_operation_lookup_finished(context, result.root(), nullptr); } TEST(wf_impl_operation_lookup, finished_unknown_type) @@ -113,17 +106,12 @@ TEST(wf_impl_operation_lookup, finished_unknown_type) FuseMock fuse; EXPECT_CALL(fuse, fuse_reply_entry(_,_)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "inode", json_integer(42)); - json_object_set_new(result, "mode", json_integer(0755)); - json_object_set_new(result, "type", json_string("unknown")); - + JsonDoc result("{\"inode\": 42, \"mode\": 493, \"type\": \"unknown\"}"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_lookup_context))); context->timeout = 1.0; context->gid = 0; context->uid = 0; - wf_impl_operation_lookup_finished(context, result, nullptr); - json_decref(result); + wf_impl_operation_lookup_finished(context, result.root(), nullptr); } TEST(wf_impl_operation_lookup, finished_fail_missing_inode) @@ -132,16 +120,12 @@ TEST(wf_impl_operation_lookup, finished_fail_missing_inode) EXPECT_CALL(fuse, fuse_reply_open(_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "mode", json_integer(0755)); - json_object_set_new(result, "type", json_string("file")); - + JsonDoc result("{\"mode\": 493, \"type\": \"file\"}"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_lookup_context))); context->timeout = 1.0; context->gid = 0; context->uid = 0; - wf_impl_operation_lookup_finished(context, result, nullptr); - json_decref(result); + wf_impl_operation_lookup_finished(context, result.root(), nullptr); } TEST(wf_impl_operation_lookup, finished_fail_invalid_inode_type) @@ -150,17 +134,12 @@ TEST(wf_impl_operation_lookup, finished_fail_invalid_inode_type) EXPECT_CALL(fuse, fuse_reply_open(_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "inode", json_string("42")); - json_object_set_new(result, "mode", json_string("0755")); - json_object_set_new(result, "type", json_string("file")); - + JsonDoc result("{\"inode\": \"42\", \"mode\": 493, \"type\": \"file\"}"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_lookup_context))); context->timeout = 1.0; context->gid = 0; context->uid = 0; - wf_impl_operation_lookup_finished(context, result, nullptr); - json_decref(result); + wf_impl_operation_lookup_finished(context, result.root(), nullptr); } TEST(wf_impl_operation_lookup, finished_fail_missing_mode) @@ -169,16 +148,12 @@ TEST(wf_impl_operation_lookup, finished_fail_missing_mode) EXPECT_CALL(fuse, fuse_reply_open(_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "inode", json_integer(42)); - json_object_set_new(result, "type", json_string("file")); - + JsonDoc result("{\"inode\": 42, \"type\": \"file\"}"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_lookup_context))); context->timeout = 1.0; context->gid = 0; context->uid = 0; - wf_impl_operation_lookup_finished(context, result, nullptr); - json_decref(result); + wf_impl_operation_lookup_finished(context, result.root(), nullptr); } TEST(wf_impl_operation_lookup, finished_fail_invalid_mode_type) @@ -187,35 +162,26 @@ TEST(wf_impl_operation_lookup, finished_fail_invalid_mode_type) EXPECT_CALL(fuse, fuse_reply_open(_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "inode", json_integer(42)); - json_object_set_new(result, "mode", json_string("0755")); - json_object_set_new(result, "type", json_string("file")); - + JsonDoc result("{\"inode\": 42, \"mode\": \"0755\", \"type\": \"file\"}"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_lookup_context))); context->timeout = 1.0; context->gid = 0; context->uid = 0; - wf_impl_operation_lookup_finished(context, result, nullptr); - json_decref(result); + wf_impl_operation_lookup_finished(context, result.root(), nullptr); } -TEST(wf_impl_operation_lookup, finished_fail_type_mode) +TEST(wf_impl_operation_lookup, finished_fail_missing_type) { FuseMock fuse; EXPECT_CALL(fuse, fuse_reply_open(_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "inode", json_integer(42)); - json_object_set_new(result, "mode", json_integer(0755)); - + JsonDoc result("{\"inode\": 42, \"mode\": 493}"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_lookup_context))); context->timeout = 1.0; context->gid = 0; context->uid = 0; - wf_impl_operation_lookup_finished(context, result, nullptr); - json_decref(result); + wf_impl_operation_lookup_finished(context, result.root(), nullptr); } TEST(wf_impl_operation_lookup, finished_fail_invalid_type_type) @@ -224,17 +190,12 @@ TEST(wf_impl_operation_lookup, finished_fail_invalid_type_type) EXPECT_CALL(fuse, fuse_reply_open(_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "inode", json_integer(42)); - json_object_set_new(result, "mode", json_integer(0755)); - json_object_set_new(result, "type", json_integer(42)); - + JsonDoc result("{\"inode\": 42, \"mode\": 493, \"type\": 42}"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_lookup_context))); context->timeout = 1.0; context->gid = 0; context->uid = 0; - wf_impl_operation_lookup_finished(context, result, nullptr); - json_decref(result); + wf_impl_operation_lookup_finished(context, result.root(), nullptr); } TEST(wf_impl_operation_lookup, finished_error) @@ -243,13 +204,12 @@ TEST(wf_impl_operation_lookup, finished_error) EXPECT_CALL(fuse, fuse_reply_open(_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * error = json_object(); - json_object_set_new(error, "code", json_integer(WF_BAD)); + struct wf_jsonrpc_error * error = wf_impl_jsonrpc_error(WF_BAD, ""); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_lookup_context))); context->timeout = 1.0; context->gid = 0; context->uid = 0; wf_impl_operation_lookup_finished(context, nullptr, error); - json_decref(error); + wf_impl_jsonrpc_error_dispose(error); } diff --git a/test/webfuse/operation/test_open.cc b/test/webfuse/operation/test_open.cc index e509653..88b1dd2 100644 --- a/test/webfuse/operation/test_open.cc +++ b/test/webfuse/operation/test_open.cc @@ -1,13 +1,16 @@ #include "webfuse/impl/operation/open.h" +#include "webfuse/impl/jsonrpc/error.h" #include "webfuse/status.h" +#include "webfuse/test_util/json_doc.hpp" #include "webfuse/mocks/mock_fuse.hpp" #include "webfuse/mocks/mock_operation_context.hpp" #include "webfuse/mocks/mock_jsonrpc_proxy.hpp" #include +using webfuse_test::JsonDoc; using webfuse_test::MockJsonRpcProxy; using webfuse_test::MockOperationContext; using webfuse_test::FuseMock; @@ -58,10 +61,8 @@ TEST(wf_impl_operation_open, finished) FuseMock fuse; EXPECT_CALL(fuse, fuse_reply_open(_,_)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "handle", json_integer(42)); - wf_impl_operation_open_finished(nullptr, result, nullptr); - json_decref(result); + JsonDoc result("{\"handle\": 42}"); + wf_impl_operation_open_finished(nullptr, result.root(), nullptr); } TEST(wf_impl_operation_open, finished_fail_error) @@ -70,10 +71,9 @@ TEST(wf_impl_operation_open, finished_fail_error) EXPECT_CALL(fuse, fuse_reply_open(_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * error = json_object(); - json_object_set_new(error, "code", json_integer(WF_BAD)); + struct wf_jsonrpc_error * error = wf_impl_jsonrpc_error(WF_BAD, ""); wf_impl_operation_open_finished(nullptr, nullptr, error); - json_decref(error); + wf_impl_jsonrpc_error_dispose(error); } TEST(wf_impl_operation_open, finished_fail_no_handle) @@ -82,9 +82,8 @@ TEST(wf_impl_operation_open, finished_fail_no_handle) EXPECT_CALL(fuse, fuse_reply_open(_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - wf_impl_operation_open_finished(nullptr, result, nullptr); - json_decref(result); + JsonDoc result("{}"); + wf_impl_operation_open_finished(nullptr, result.root(), nullptr); } TEST(wf_impl_operation_open, finished_fail_invalid_handle_type) @@ -93,8 +92,6 @@ TEST(wf_impl_operation_open, finished_fail_invalid_handle_type) EXPECT_CALL(fuse, fuse_reply_open(_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "handle", json_string("42")); - wf_impl_operation_open_finished(nullptr, result, nullptr); - json_decref(result); + JsonDoc result("{\"handle\": \"42\"}"); + wf_impl_operation_open_finished(nullptr, result.root(), nullptr); } diff --git a/test/webfuse/operation/test_read.cc b/test/webfuse/operation/test_read.cc index c719c62..45f8573 100644 --- a/test/webfuse/operation/test_read.cc +++ b/test/webfuse/operation/test_read.cc @@ -1,11 +1,14 @@ #include "webfuse/impl/operation/read.h" +#include "webfuse/impl/jsonrpc/error.h" +#include "webfuse/test_util/json_doc.hpp" #include "webfuse/mocks/mock_fuse.hpp" #include "webfuse/mocks/mock_operation_context.hpp" #include "webfuse/mocks/mock_jsonrpc_proxy.hpp" #include +using webfuse_test::JsonDoc; using webfuse_test::MockJsonRpcProxy; using webfuse_test::MockOperationContext; using webfuse_test::FuseMock; @@ -81,53 +84,52 @@ TEST(wf_impl_operation_read, fail_rpc_null) TEST(wf_impl_operation_read, fill_buffer_identity) { wf_status status; - char * buffer = wf_impl_fill_buffer("brummni", 8, "identity", 8, &status); + char text[] = "brummni"; + char * buffer = wf_impl_operation_read_transform(text, 8, "identity", 8, &status); ASSERT_EQ(WF_GOOD, status); ASSERT_STREQ("brummni", buffer); - free(buffer); } TEST(wf_impl_operation_read, fill_buffer_identity_fail_inconsistent_size) { wf_status status; - char * buffer = wf_impl_fill_buffer("brummni", 8, "identity", 7, &status); + char text[] = "brummni"; + wf_impl_operation_read_transform(text, 8, "identity", 7, &status); ASSERT_NE(WF_GOOD, status); - ASSERT_EQ(nullptr, buffer); } TEST(wf_impl_operation_read, fill_buffer_base64) { wf_status status; - char * buffer = wf_impl_fill_buffer("YnJ1bW1uaQ==", 12, "base64", 7, &status); + char text[] = "YnJ1bW1uaQ=="; + char * buffer = wf_impl_operation_read_transform(text, 12, "base64", 7, &status); ASSERT_EQ(WF_GOOD, status); ASSERT_EQ(0, strncmp("brummni", buffer, 7)); - free(buffer); } TEST(wf_impl_operation_read, fill_buffer_base64_fail_invalid_data) { wf_status status; - char * buffer = wf_impl_fill_buffer("YnJ1bW1uaQ=A", 12, "base64", 8, &status); + char text[] = "YnJ1bW1uaQ=A"; + wf_impl_operation_read_transform(text, 12, "base64", 8, &status); ASSERT_NE(WF_GOOD, status); - ASSERT_EQ(nullptr, buffer); } TEST(wf_impl_operation_read, fill_buffer_empty) { wf_status status; - char * buffer = wf_impl_fill_buffer(nullptr, 0, "identity", 0, &status); + wf_impl_operation_read_transform(nullptr, 0, "identity", 0, &status); ASSERT_EQ(WF_GOOD, status); - free(buffer); } TEST(wf_impl_operation_read, fill_buffer_fail_invalid_format) { wf_status status; - char * buffer = wf_impl_fill_buffer("some data", 9, "unknown", 9, &status); + char text[] = "some data"; + wf_impl_operation_read_transform(text, 9, "unknown", 9, &status); ASSERT_NE(WF_GOOD, status); - ASSERT_EQ(nullptr, buffer); } TEST(wf_impl_operation_read, finished) @@ -135,12 +137,8 @@ TEST(wf_impl_operation_read, finished) FuseMock fuse; EXPECT_CALL(fuse, fuse_reply_buf(_,_,7)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "data", json_string("brummni")); - json_object_set_new(result, "format", json_string("identity")); - json_object_set_new(result, "count", json_integer(7)); - wf_impl_operation_read_finished(nullptr, result, nullptr); - json_decref(result); + JsonDoc result("{\"data\": \"brummni\", \"format\": \"identity\", \"count\": 7}"); + wf_impl_operation_read_finished(nullptr, result.root(), nullptr); } TEST(wf_impl_operation_read, finished_fail_no_data) @@ -149,11 +147,8 @@ TEST(wf_impl_operation_read, finished_fail_no_data) EXPECT_CALL(fuse, fuse_reply_buf(_,_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, _)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "format", json_string("identity")); - json_object_set_new(result, "count", json_integer(7)); - wf_impl_operation_read_finished(nullptr, result, nullptr); - json_decref(result); + JsonDoc result("{\"format\": \"identity\", \"count\": 7}"); + wf_impl_operation_read_finished(nullptr, result.root(), nullptr); } TEST(wf_impl_operation_read, finished_fail_invalid_data_type) @@ -162,12 +157,8 @@ TEST(wf_impl_operation_read, finished_fail_invalid_data_type) EXPECT_CALL(fuse, fuse_reply_buf(_,_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, _)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "data", json_integer(42)); - json_object_set_new(result, "format", json_string("identity")); - json_object_set_new(result, "count", json_integer(7)); - wf_impl_operation_read_finished(nullptr, result, nullptr); - json_decref(result); + JsonDoc result("{\"data\": 42, \"format\": \"identity\", \"count\": 7}"); + wf_impl_operation_read_finished(nullptr, result.root(), nullptr); } TEST(wf_impl_operation_read, finished_fail_no_format) @@ -176,11 +167,8 @@ TEST(wf_impl_operation_read, finished_fail_no_format) EXPECT_CALL(fuse, fuse_reply_buf(_,_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, _)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "data", json_string("brummni")); - json_object_set_new(result, "count", json_integer(7)); - wf_impl_operation_read_finished(nullptr, result, nullptr); - json_decref(result); + JsonDoc result("{\"data\": \"brummni\", \"count\": 7}"); + wf_impl_operation_read_finished(nullptr, result.root(), nullptr); } TEST(wf_impl_operation_read, finished_fail_invalid_format_type) @@ -189,12 +177,8 @@ TEST(wf_impl_operation_read, finished_fail_invalid_format_type) EXPECT_CALL(fuse, fuse_reply_buf(_,_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, _)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "data", json_string("brummni")); - json_object_set_new(result, "format", json_integer(42)); - json_object_set_new(result, "count", json_integer(7)); - wf_impl_operation_read_finished(nullptr, result, nullptr); - json_decref(result); + JsonDoc result("{\"data\": \"brummni\", \"format\": 42, \"count\": 7}"); + wf_impl_operation_read_finished(nullptr, result.root(), nullptr); } TEST(wf_impl_operation_read, finished_fail_no_count) @@ -203,11 +187,8 @@ TEST(wf_impl_operation_read, finished_fail_no_count) EXPECT_CALL(fuse, fuse_reply_buf(_,_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, _)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "data", json_string("brummni")); - json_object_set_new(result, "format", json_string("identity")); - wf_impl_operation_read_finished(nullptr, result, nullptr); - json_decref(result); + JsonDoc result("{\"data\": \"brummni\", \"format\": \"identity\"}"); + wf_impl_operation_read_finished(nullptr, result.root(), nullptr); } TEST(wf_impl_operation_read, finished_fail_invalid_count_type) @@ -216,12 +197,8 @@ TEST(wf_impl_operation_read, finished_fail_invalid_count_type) EXPECT_CALL(fuse, fuse_reply_buf(_,_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, _)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - json_object_set_new(result, "data", json_string("brummni")); - json_object_set_new(result, "format", json_string("identity")); - json_object_set_new(result, "count", json_string("7")); - wf_impl_operation_read_finished(nullptr, result, nullptr); - json_decref(result); + JsonDoc result("{\"data\": \"brummni\", \"format\": \"identity\", \"count\": \"7\"}"); + wf_impl_operation_read_finished(nullptr, result.root(), nullptr); } TEST(wf_impl_operation_read, finished_fail_error) @@ -230,8 +207,7 @@ TEST(wf_impl_operation_read, finished_fail_error) EXPECT_CALL(fuse, fuse_reply_buf(_,_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, _)).Times(1).WillOnce(Return(0)); - json_t * error = json_object(); - json_object_set_new(error, "code", json_integer(WF_BAD)); + struct wf_jsonrpc_error * error = wf_impl_jsonrpc_error(WF_BAD, ""); wf_impl_operation_read_finished(nullptr, nullptr, error); - json_decref(error); + wf_impl_jsonrpc_error_dispose(error); } diff --git a/test/webfuse/operation/test_readdir.cc b/test/webfuse/operation/test_readdir.cc index deef623..b4b7591 100644 --- a/test/webfuse/operation/test_readdir.cc +++ b/test/webfuse/operation/test_readdir.cc @@ -1,13 +1,17 @@ #include "webfuse/impl/operation/readdir.h" +#include "webfuse/impl/jsonrpc/error.h" #include "webfuse/status.h" +#include "webfuse/test_util/json_doc.hpp" #include "webfuse/mocks/mock_fuse.hpp" #include "webfuse/mocks/mock_operation_context.hpp" #include "webfuse/mocks/mock_jsonrpc_proxy.hpp" #include +#include +using webfuse_test::JsonDoc; using webfuse_test::MockJsonRpcProxy; using webfuse_test::MockOperationContext; using webfuse_test::FuseMock; @@ -80,18 +84,12 @@ TEST(wf_impl_operation_readdir, finished) FuseMock fuse; EXPECT_CALL(fuse, fuse_reply_buf(_,_,_)).Times(1).WillOnce(Return(0)); - json_t * result = json_array(); - json_t * item = json_object(); - json_object_set_new(item, "name", json_string("a.file")); - json_object_set_new(item, "inode", json_integer(42)); - json_array_append_new(result, item); - + JsonDoc result("[{\"name\": \"a.file\", \"inode\": 42}]"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_readdir_context))); context->request = nullptr; context->size = 1; context->offset = 0; - wf_impl_operation_readdir_finished(reinterpret_cast(context), result, nullptr); - json_decref(result); + wf_impl_operation_readdir_finished(reinterpret_cast(context), result.root(), nullptr); } TEST(wf_impl_operation_readdir, finished_many_items) @@ -99,22 +97,20 @@ TEST(wf_impl_operation_readdir, finished_many_items) FuseMock fuse; EXPECT_CALL(fuse, fuse_reply_buf(_,_,_)).Times(1).WillOnce(Return(0)); - json_t * result = json_array(); - for(int i = 0; i < 100; i++) + std::ostringstream stream; + stream << "[" << "{\"name\": \"file_0.txt\", \"inode\": 1}"; + for(int i = 1; i < 100; i++) { - json_t * item = json_object(); - json_object_set_new(item, "name", json_sprintf("file_%d.txt", i)); - json_object_set_new(item, "inode", json_integer(1 + i)); - json_array_append_new(result, item); + stream << ",{\"name\": \"file_" << i << ".txt\", \"inode\": " << (i+1) << "}"; } + stream << "]"; - + JsonDoc result(stream.str()); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_readdir_context))); context->request = nullptr; context->size = 100; context->offset = 0; - wf_impl_operation_readdir_finished(reinterpret_cast(context), result, nullptr); - json_decref(result); + wf_impl_operation_readdir_finished(reinterpret_cast(context), result.root(), nullptr); } TEST(wf_impl_operation_readdir, finished_read_after_end) @@ -122,18 +118,12 @@ TEST(wf_impl_operation_readdir, finished_read_after_end) FuseMock fuse; EXPECT_CALL(fuse, fuse_reply_buf(_,_,_)).Times(1).WillOnce(Return(0)); - json_t * result = json_array(); - json_t * item = json_object(); - json_object_set_new(item, "name", json_string("a.file")); - json_object_set_new(item, "inode", json_integer(42)); - json_array_append_new(result, item); - + JsonDoc result("[{\"name\": \"a.file\", \"inode\": 42}]"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_readdir_context))); context->request = nullptr; context->size = 10; context->offset = 2; - wf_impl_operation_readdir_finished(reinterpret_cast(context), result, nullptr); - json_decref(result); + wf_impl_operation_readdir_finished(reinterpret_cast(context), result.root(), nullptr); } TEST(wf_impl_operation_readdir, finished_fail_error) @@ -142,15 +132,14 @@ TEST(wf_impl_operation_readdir, finished_fail_error) EXPECT_CALL(fuse, fuse_reply_buf(_,_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * error = json_array(); - json_object_set_new(error, "code", json_integer(WF_BAD)); + struct wf_jsonrpc_error * error = wf_impl_jsonrpc_error(WF_BAD, ""); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_readdir_context))); context->request = nullptr; context->size = 1; context->offset = 0; wf_impl_operation_readdir_finished(reinterpret_cast(context), nullptr, error); - json_decref(error); + wf_impl_jsonrpc_error_dispose(error); } TEST(wf_impl_operation_readdir, finished_fail_invalid_result_type) @@ -159,14 +148,12 @@ TEST(wf_impl_operation_readdir, finished_fail_invalid_result_type) EXPECT_CALL(fuse, fuse_reply_buf(_,_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * result = json_object(); - + JsonDoc result("{}"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_readdir_context))); context->request = nullptr; context->size = 1; context->offset = 0; - wf_impl_operation_readdir_finished(reinterpret_cast(context), result, nullptr); - json_decref(result); + wf_impl_operation_readdir_finished(reinterpret_cast(context), result.root(), nullptr); } TEST(wf_impl_operation_readdir, finished_fail_missing_name) @@ -175,17 +162,12 @@ TEST(wf_impl_operation_readdir, finished_fail_missing_name) EXPECT_CALL(fuse, fuse_reply_buf(_,_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * result = json_array(); - json_t * item = json_object(); - json_object_set_new(item, "inode", json_integer(42)); - json_array_append_new(result, item); - + JsonDoc result("[{\"inode\": 42}]"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_readdir_context))); context->request = nullptr; context->size = 1; context->offset = 0; - wf_impl_operation_readdir_finished(reinterpret_cast(context), result, nullptr); - json_decref(result); + wf_impl_operation_readdir_finished(reinterpret_cast(context), result.root(), nullptr); } TEST(wf_impl_operation_readdir, finished_fail_invalid_name_type) @@ -194,18 +176,12 @@ TEST(wf_impl_operation_readdir, finished_fail_invalid_name_type) EXPECT_CALL(fuse, fuse_reply_buf(_,_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * result = json_array(); - json_t * item = json_object(); - json_object_set_new(item, "name", json_integer(42)); - json_object_set_new(item, "inode", json_integer(42)); - json_array_append_new(result, item); - + JsonDoc result("[{\"name\": 42, \"inode\": 42}]"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_readdir_context))); context->request = nullptr; context->size = 1; context->offset = 0; - wf_impl_operation_readdir_finished(reinterpret_cast(context), result, nullptr); - json_decref(result); + wf_impl_operation_readdir_finished(reinterpret_cast(context), result.root(), nullptr); } TEST(wf_impl_operation_readdir, finished_fail_missing_inode) @@ -214,17 +190,12 @@ TEST(wf_impl_operation_readdir, finished_fail_missing_inode) EXPECT_CALL(fuse, fuse_reply_buf(_,_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * result = json_array(); - json_t * item = json_object(); - json_object_set_new(item, "name", json_string("a.file")); - json_array_append_new(result, item); - + JsonDoc result("[{\"name\": \"a.file\"}]"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_readdir_context))); context->request = nullptr; context->size = 1; context->offset = 0; - wf_impl_operation_readdir_finished(reinterpret_cast(context), result, nullptr); - json_decref(result); + wf_impl_operation_readdir_finished(reinterpret_cast(context), result.root(), nullptr); } TEST(wf_impl_operation_readdir, finished_fail_invalid_inode_type) @@ -233,18 +204,12 @@ TEST(wf_impl_operation_readdir, finished_fail_invalid_inode_type) EXPECT_CALL(fuse, fuse_reply_buf(_,_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * result = json_array(); - json_t * item = json_object(); - json_object_set_new(item, "name", json_string("a.file")); - json_object_set_new(item, "inode", json_string("42")); - json_array_append_new(result, item); - + JsonDoc result("[{\"name\": \"a.file\", \"inode\": \"42\"}]"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_readdir_context))); context->request = nullptr; context->size = 1; context->offset = 0; - wf_impl_operation_readdir_finished(reinterpret_cast(context), result, nullptr); - json_decref(result); + wf_impl_operation_readdir_finished(reinterpret_cast(context), result.root(), nullptr); } TEST(wf_impl_operation_readdir, finished_fail_invalid_item_type) @@ -253,13 +218,10 @@ TEST(wf_impl_operation_readdir, finished_fail_invalid_item_type) EXPECT_CALL(fuse, fuse_reply_buf(_,_,_)).Times(0); EXPECT_CALL(fuse, fuse_reply_err(_, ENOENT)).Times(1).WillOnce(Return(0)); - json_t * result = json_array(); - json_array_append_new(result, json_string("item")); - + JsonDoc result("[\"item\"]"); auto * context = reinterpret_cast(malloc(sizeof(wf_impl_operation_readdir_context))); context->request = nullptr; context->size = 1; context->offset = 0; - wf_impl_operation_readdir_finished(reinterpret_cast(context), result, nullptr); - json_decref(result); + wf_impl_operation_readdir_finished(reinterpret_cast(context), result.root(), nullptr); } diff --git a/test/webfuse/test_client.cc b/test/webfuse/test_client.cc index 37b4a8b..0924368 100644 --- a/test/webfuse/test_client.cc +++ b/test/webfuse/test_client.cc @@ -1,6 +1,3 @@ -#include -#include - #include "webfuse/test_util/adapter_client.hpp" #include "webfuse/client_tlsconfig.h" #include "webfuse/credentials.h" @@ -13,8 +10,12 @@ #include "webfuse/mocks/open_matcher.hpp" #include "webfuse/mocks/getattr_matcher.hpp" +#include +#include + #include #include +#include using webfuse_test::AdapterClient; using webfuse_test::WsServer; @@ -148,8 +149,7 @@ TEST(AdapterClient, IgnoreInvalidJsonMessage) client.Connect(); ASSERT_EQ(std::future_status::ready, connected.get_future().wait_for(TIMEOUT)); - json_t * invalid_request = json_object(); - server.SendMessage(invalid_request); + server.SendMessage("{}"); client.Disconnect(); ASSERT_EQ(std::future_status::ready, disconnected.get_future().wait_for(TIMEOUT)); @@ -566,26 +566,21 @@ TEST(AdapterClient, ReadFile) EXPECT_CALL(handler, Invoke(StrEq("open"), Open(2))).Times(1) .WillOnce(Return("{\"handle\": 42}")); EXPECT_CALL(handler, Invoke(StrEq("read"), _)).Times(AnyNumber()) - .WillRepeatedly(Invoke([](char const *, json_t * params) { - int offset = json_integer_value(json_array_get(params, 3)); - int length = json_integer_value(json_array_get(params, 4)); + .WillRepeatedly(Invoke([](char const *, wf_json const * params) { + int offset = wf_impl_json_int_get(wf_impl_json_array_get(params, 3)); + int length = wf_impl_json_int_get(wf_impl_json_array_get(params, 4)); int remaining = (offset < 4096) ? 4096 - offset : 0; int count = (length < remaining) ? length : remaining; - std::string data = std::string(count, '*'); + std::ostringstream result; + result << "{" + << "\"data\": \"" << std::string(count, '*') << "\"," + << "\"format\": \"identity\"," + << "\"count\": " << count + << "}"; - json_t * result = json_object(); - json_object_set_new(result, "data", json_string(data.c_str())); - json_object_set_new(result, "format", json_string("identity")); - json_object_set_new(result, "count", json_integer(count)); - - char * result_text = json_dumps(result, 0); - std::string result_str = result_text; - free(result_text); - json_decref(result); - - return result_str; + return result.str(); })); EXPECT_CALL(handler, Invoke(StrEq("close"), _)).Times(AtMost(1)); @@ -641,26 +636,21 @@ TEST(AdapterClient, ReadLargeFile) EXPECT_CALL(handler, Invoke(StrEq("open"), Open(2))).Times(1) .WillOnce(Return("{\"handle\": 42}")); EXPECT_CALL(handler, Invoke(StrEq("read"), _)).Times(AnyNumber()) - .WillRepeatedly(Invoke([](char const *, json_t * params) { - int offset = json_integer_value(json_array_get(params, 3)); - int length = json_integer_value(json_array_get(params, 4)); + .WillRepeatedly(Invoke([](char const *, wf_json const * params) { + int offset = wf_impl_json_int_get(wf_impl_json_array_get(params, 3)); + int length = wf_impl_json_int_get(wf_impl_json_array_get(params, 4)); int remaining = (offset < 102400) ? 102400 - offset : 0; int count = (length < remaining) ? length : remaining; - std::string data = std::string(count, '*'); + std::ostringstream result; + result << "{" + << "\"data\": \"" << std::string(count, '*') << "\"," + << "\"format\": \"identity\"," + << "\"count\": " << count + << "}"; - json_t * result = json_object(); - json_object_set_new(result, "data", json_string(data.c_str())); - json_object_set_new(result, "format", json_string("identity")); - json_object_set_new(result, "count", json_integer(count)); - - char * result_text = json_dumps(result, 0); - std::string result_str = result_text; - free(result_text); - json_decref(result); - - return result_str; + return result.str(); })); EXPECT_CALL(handler, Invoke(StrEq("close"), _)).Times(AtMost(1)); diff --git a/test/webfuse/test_credentials.cc b/test/webfuse/test_credentials.cc index 7eea168..4dfbc90 100644 --- a/test/webfuse/test_credentials.cc +++ b/test/webfuse/test_credentials.cc @@ -1,8 +1,10 @@ -#include - #include "webfuse/credentials.h" #include "webfuse/impl/credentials.h" -#include +#include "webfuse/test_util/json_doc.hpp" + +#include + +using webfuse_test::JsonDoc; TEST(Credentials, Type) { @@ -16,31 +18,27 @@ TEST(Credentials, Type) TEST(Credentials, Get) { struct wf_credentials creds; - json_t * data = json_object(); - json_object_set_new(data, "username", json_string("bob")); - json_object_set_new(data, "password", json_string("")); + JsonDoc doc("{\"username\": \"bob\", \"password\": \"\"}"); - wf_impl_credentials_init(&creds, "username", data); + wf_impl_credentials_init(&creds, "username", doc.root()); ASSERT_STREQ("username", wf_credentials_type(&creds)); ASSERT_STREQ("bob", wf_credentials_get(&creds, "username")); ASSERT_STREQ("", wf_credentials_get(&creds, "password")); wf_impl_credentials_cleanup(&creds); - json_decref(data); } TEST(Credentials, FailedToGetNonexistingValue) { struct wf_credentials creds; - json_t * data = json_object(); + JsonDoc doc("{}"); - wf_impl_credentials_init(&creds, "username", data); + wf_impl_credentials_init(&creds, "username", doc.root()); ASSERT_STREQ("username", wf_credentials_type(&creds)); ASSERT_STREQ(nullptr, wf_credentials_get(&creds, "username")); ASSERT_STREQ(nullptr, wf_credentials_get(&creds, "password")); wf_impl_credentials_cleanup(&creds); - json_decref(data); } TEST(Credentials, FailedToGetWithoutData) @@ -58,30 +56,27 @@ TEST(Credentials, FailedToGetWithoutData) TEST(Credentials, FailedToGetWrongDataType) { struct wf_credentials creds; - json_t * data = json_string("invalid_creds"); + JsonDoc doc("invalid_creds"); - wf_impl_credentials_init(&creds, "username", data); + wf_impl_credentials_init(&creds, "username", doc.root()); ASSERT_STREQ("username", wf_credentials_type(&creds)); ASSERT_STREQ(nullptr, wf_credentials_get(&creds, "username")); ASSERT_STREQ(nullptr, wf_credentials_get(&creds, "password")); wf_impl_credentials_cleanup(&creds); - json_decref(data); } TEST(Credentials, FailedToGetWrongElementDataType) { struct wf_credentials creds; - json_t * data = json_object(); - json_object_set_new(data, "username", json_integer(42)); + JsonDoc doc("{\"username\": 42}"); - wf_impl_credentials_init(&creds, "username", data); + wf_impl_credentials_init(&creds, "username", doc.root()); ASSERT_STREQ("username", wf_credentials_type(&creds)); ASSERT_STREQ(nullptr, wf_credentials_get(&creds, "username")); ASSERT_STREQ(nullptr, wf_credentials_get(&creds, "password")); wf_impl_credentials_cleanup(&creds); - json_decref(data); } TEST(Credentials, SetType) diff --git a/test/webfuse/test_message.cc b/test/webfuse/test_message.cc index 0e262fe..a0aafe0 100644 --- a/test/webfuse/test_message.cc +++ b/test/webfuse/test_message.cc @@ -1,22 +1,22 @@ -#include -#include #include "webfuse/impl/message.h" +#include +#include +#include + +#include + TEST(wf_message, create) { - json_t * value = json_object(); + char * data = (char*) malloc(LWS_PRE + 2); + data[LWS_PRE ] = '{'; + data[LWS_PRE + 1] = '}'; - struct wf_message * message = wf_impl_message_create(value); + struct wf_message * message = wf_impl_message_create(&(data[LWS_PRE]), 2); ASSERT_NE(nullptr, message); ASSERT_EQ(2, message->length); ASSERT_TRUE(0 == strncmp("{}", message->data, 2)); wf_impl_message_dispose(message); - json_decref(value); } -TEST(wf_message, fail_to_create) -{ - struct wf_message * message = wf_impl_message_create(nullptr); - ASSERT_EQ(nullptr, message); -} \ No newline at end of file diff --git a/test/webfuse/test_message_queue.cc b/test/webfuse/test_message_queue.cc index 4560cee..b79890d 100644 --- a/test/webfuse/test_message_queue.cc +++ b/test/webfuse/test_message_queue.cc @@ -1,18 +1,23 @@ -#include #include "webfuse/impl/message_queue.h" #include "webfuse/impl/message.h" #include "webfuse/impl/util/slist.h" +#include + +#include +#include +#include + namespace { struct wf_slist_item * create_message(char const * content) { - json_t * value = json_object(); - json_object_set_new(value, "content", json_string(content)); - struct wf_message * message = wf_impl_message_create(value); + std::string json = std::string("{\"content\": \"") + content + "\"}"; + char * data = (char*) malloc(LWS_PRE + json.size()); + memcpy(&(data[LWS_PRE]), json.c_str(), json.size()); + struct wf_message * message = wf_impl_message_create(&(data[LWS_PRE]), json.size()); - json_decref(value); return &message->item; } diff --git a/test/webfuse/test_server.cc b/test/webfuse/test_server.cc index 85aba28..b7482b3 100644 --- a/test/webfuse/test_server.cc +++ b/test/webfuse/test_server.cc @@ -1,19 +1,20 @@ -#include - -#include - #include "webfuse/server.h" #include "webfuse/server_config.h" #include "webfuse/test_util/server.hpp" #include "webfuse/test_util/ws_client.hpp" #include "webfuse/test_util/file.hpp" +#include "webfuse/test_util/json_doc.hpp" #include "webfuse/mocks/mock_invokation_handler.hpp" #include "webfuse/protocol_names.h" #include "webfuse/mocks/open_matcher.hpp" #include "webfuse/mocks/getattr_matcher.hpp" #include "webfuse/mocks/lookup_matcher.hpp" #include "webfuse/mocks/readdir_matcher.hpp" +#include "webfuse/impl/json/node.h" +#include + +using webfuse_test::JsonDoc; using webfuse_test::MockInvokationHander; using webfuse_test::WsClient; using webfuse_test::Server; @@ -85,13 +86,13 @@ TEST(server, add_filesystem) ASSERT_TRUE(connected); std::string response_text = client.Invoke("{\"method\": \"add_filesystem\", \"params\": [\"test\"], \"id\": 42}"); - json_t * response = json_loads(response_text.c_str(), 0, nullptr); - ASSERT_TRUE(json_is_object(response)); - json_t * result = json_object_get(response, "result"); - ASSERT_TRUE(json_is_object(result)); - json_t * id = json_object_get(response, "id"); - ASSERT_EQ(42, json_integer_value(id)); - json_decref(response); + JsonDoc doc(response_text); + wf_json const * response = doc.root(); + ASSERT_TRUE(wf_impl_json_is_object(response)); + wf_json const * result = wf_impl_json_object_get(response, "result"); + ASSERT_TRUE(wf_impl_json_is_object(result)); + wf_json const * id = wf_impl_json_object_get(response, "id"); + ASSERT_EQ(42, wf_impl_json_int_get(id)); std::string base_dir = server.GetBaseDir(); ASSERT_TRUE(File(base_dir).isDirectory()); @@ -112,13 +113,13 @@ TEST(server, add_filesystem_fail_missing_param) ASSERT_TRUE(connected); std::string response_text = client.Invoke("{\"method\": \"add_filesystem\", \"params\": [], \"id\": 42}"); - json_t * response = json_loads(response_text.c_str(), 0, nullptr); - ASSERT_TRUE(json_is_object(response)); - json_t * error = json_object_get(response, "error"); - ASSERT_TRUE(json_is_object(error)); - json_t * id = json_object_get(response, "id"); - ASSERT_EQ(42, json_integer_value(id)); - json_decref(response); + JsonDoc doc(response_text); + wf_json const * response = doc.root(); + ASSERT_TRUE(wf_impl_json_is_object(response)); + wf_json const * error = wf_impl_json_object_get(response, "error"); + ASSERT_TRUE(wf_impl_json_is_object(error)); + wf_json const * id = wf_impl_json_object_get(response, "id"); + ASSERT_EQ(42, wf_impl_json_int_get(id)); auto disconnected = client.Disconnect(); ASSERT_TRUE(disconnected); @@ -134,13 +135,13 @@ TEST(server, add_filesystem_fail_invalid_name_type) ASSERT_TRUE(connected); std::string response_text = client.Invoke("{\"method\": \"add_filesystem\", \"params\": [42], \"id\": 42}"); - json_t * response = json_loads(response_text.c_str(), 0, nullptr); - ASSERT_TRUE(json_is_object(response)); - json_t * error = json_object_get(response, "error"); - ASSERT_TRUE(json_is_object(error)); - json_t * id = json_object_get(response, "id"); - ASSERT_EQ(42, json_integer_value(id)); - json_decref(response); + JsonDoc doc(response_text); + wf_json const * response = doc.root(); + ASSERT_TRUE(wf_impl_json_is_object(response)); + wf_json const * error = wf_impl_json_object_get(response, "error"); + ASSERT_TRUE(wf_impl_json_is_object(error)); + wf_json const * id = wf_impl_json_object_get(response, "id"); + ASSERT_EQ(42, wf_impl_json_int_get(id)); auto disconnected = client.Disconnect(); ASSERT_TRUE(disconnected); @@ -156,13 +157,13 @@ TEST(server, add_filesystem_fail_invalid_name) ASSERT_TRUE(connected); std::string response_text = client.Invoke("{\"method\": \"add_filesystem\", \"params\": [\"invalid_1/name\"], \"id\": 42}"); - json_t * response = json_loads(response_text.c_str(), 0, nullptr); - ASSERT_TRUE(json_is_object(response)); - json_t * error = json_object_get(response, "error"); - ASSERT_TRUE(json_is_object(error)); - json_t * id = json_object_get(response, "id"); - ASSERT_EQ(42, json_integer_value(id)); - json_decref(response); + JsonDoc doc(response_text); + wf_json const * response = doc.root(); + ASSERT_TRUE(wf_impl_json_is_object(response)); + wf_json const * error = wf_impl_json_object_get(response, "error"); + ASSERT_TRUE(wf_impl_json_is_object(error)); + wf_json const * id = wf_impl_json_object_get(response, "id"); + ASSERT_EQ(42, wf_impl_json_int_get(id)); auto disconnected = client.Disconnect(); ASSERT_TRUE(disconnected); @@ -179,13 +180,13 @@ TEST(server, authenticate) ASSERT_TRUE(connected); std::string response_text = client.Invoke("{\"method\": \"authenticate\", \"params\": [\"username\", {\"username\": \"bob\", \"password\": \"secret\"}], \"id\": 42}"); - json_t * response = json_loads(response_text.c_str(), 0, nullptr); - ASSERT_TRUE(json_is_object(response)); - json_t * result = json_object_get(response, "result"); - ASSERT_TRUE(json_is_object(result)); - json_t * id = json_object_get(response, "id"); - ASSERT_EQ(42, json_integer_value(id)); - json_decref(response); + JsonDoc doc(response_text); + wf_json const * response = doc.root(); + ASSERT_TRUE(wf_impl_json_is_object(response)); + wf_json const * result = wf_impl_json_object_get(response, "result"); + ASSERT_TRUE(wf_impl_json_is_object(result)); + wf_json const * id = wf_impl_json_object_get(response, "id"); + ASSERT_EQ(42, wf_impl_json_int_get(id)); auto disconnected = client.Disconnect(); ASSERT_TRUE(disconnected); @@ -201,13 +202,13 @@ TEST(server, authenticate_fail_missing_params) ASSERT_TRUE(connected); std::string response_text = client.Invoke("{\"method\": \"authenticate\", \"params\": [], \"id\": 42}"); - json_t * response = json_loads(response_text.c_str(), 0, nullptr); - ASSERT_TRUE(json_is_object(response)); - json_t * error = json_object_get(response, "error"); - ASSERT_TRUE(json_is_object(error)); - json_t * id = json_object_get(response, "id"); - ASSERT_EQ(42, json_integer_value(id)); - json_decref(response); + JsonDoc doc(response_text); + wf_json const * response = doc.root(); + ASSERT_TRUE(wf_impl_json_is_object(response)); + wf_json const * error = wf_impl_json_object_get(response, "error"); + ASSERT_TRUE(wf_impl_json_is_object(error)); + wf_json const * id = wf_impl_json_object_get(response, "id"); + ASSERT_EQ(42, wf_impl_json_int_get(id)); auto disconnected = client.Disconnect(); ASSERT_TRUE(disconnected); @@ -223,13 +224,13 @@ TEST(server, authenticate_fail_invalid_type) ASSERT_TRUE(connected); std::string response_text = client.Invoke("{\"method\": \"authenticate\", \"params\": [42, {\"username\": \"bob\", \"password\": \"secret\"}], \"id\": 42}"); - json_t * response = json_loads(response_text.c_str(), 0, nullptr); - ASSERT_TRUE(json_is_object(response)); - json_t * error = json_object_get(response, "error"); - ASSERT_TRUE(json_is_object(error)); - json_t * id = json_object_get(response, "id"); - ASSERT_EQ(42, json_integer_value(id)); - json_decref(response); + JsonDoc doc(response_text); + wf_json const * response = doc.root(); + ASSERT_TRUE(wf_impl_json_is_object(response)); + wf_json const * error = wf_impl_json_object_get(response, "error"); + ASSERT_TRUE(wf_impl_json_is_object(error)); + wf_json const * id = wf_impl_json_object_get(response, "id"); + ASSERT_EQ(42, wf_impl_json_int_get(id)); auto disconnected = client.Disconnect(); ASSERT_TRUE(disconnected); @@ -245,13 +246,13 @@ TEST(server, authenticate_fail_invalid_credentials) ASSERT_TRUE(connected); std::string response_text = client.Invoke("{\"method\": \"authenticate\", \"params\": [\"username\", 42], \"id\": 42}"); - json_t * response = json_loads(response_text.c_str(), 0, nullptr); - ASSERT_TRUE(json_is_object(response)); - json_t * error = json_object_get(response, "error"); - ASSERT_TRUE(json_is_object(error)); - json_t * id = json_object_get(response, "id"); - ASSERT_EQ(42, json_integer_value(id)); - json_decref(response); + JsonDoc doc(response_text); + wf_json const * response = doc.root(); + ASSERT_TRUE(wf_impl_json_is_object(response)); + wf_json const * error = wf_impl_json_object_get(response, "error"); + ASSERT_TRUE(wf_impl_json_is_object(error)); + wf_json const * id = wf_impl_json_object_get(response, "id"); + ASSERT_EQ(42, wf_impl_json_int_get(id)); auto disconnected = client.Disconnect(); ASSERT_TRUE(disconnected); @@ -267,13 +268,13 @@ TEST(server, authenticate_fail_missing_credentials) ASSERT_TRUE(connected); std::string response_text = client.Invoke("{\"method\": \"authenticate\", \"params\": [\"username\"], \"id\": 42}"); - json_t * response = json_loads(response_text.c_str(), 0, nullptr); - ASSERT_TRUE(json_is_object(response)); - json_t * error = json_object_get(response, "error"); - ASSERT_TRUE(json_is_object(error)); - json_t * id = json_object_get(response, "id"); - ASSERT_EQ(42, json_integer_value(id)); - json_decref(response); + JsonDoc doc(response_text); + wf_json const * response = doc.root(); + ASSERT_TRUE(wf_impl_json_is_object(response)); + wf_json const * error = wf_impl_json_object_get(response, "error"); + ASSERT_TRUE(wf_impl_json_is_object(error)); + wf_json const * id = wf_impl_json_object_get(response, "id"); + ASSERT_EQ(42, wf_impl_json_int_get(id)); auto disconnected = client.Disconnect(); ASSERT_TRUE(disconnected); @@ -299,13 +300,13 @@ TEST(server, read) ASSERT_TRUE(connected); std::string response_text = client.Invoke("{\"method\": \"add_filesystem\", \"params\": [\"test\"], \"id\": 42}"); - json_t * response = json_loads(response_text.c_str(), 0, nullptr); - ASSERT_TRUE(json_is_object(response)); - json_t * result = json_object_get(response, "result"); - ASSERT_TRUE(json_is_object(result)); - json_t * id = json_object_get(response, "id"); - ASSERT_EQ(42, json_integer_value(id)); - json_decref(response); + JsonDoc doc(response_text); + wf_json const * response = doc.root(); + ASSERT_TRUE(wf_impl_json_is_object(response)); + wf_json const * result = wf_impl_json_object_get(response, "result"); + ASSERT_TRUE(wf_impl_json_is_object(result)); + wf_json const * id = wf_impl_json_object_get(response, "id"); + ASSERT_EQ(42, wf_impl_json_int_get(id)); std::string base_dir = server.GetBaseDir(); ASSERT_TRUE(File(base_dir).isDirectory()); @@ -330,26 +331,21 @@ TEST(server, read_large_file_contents) EXPECT_CALL(handler, Invoke(StrEq("open"), Open(2))).Times(1) .WillOnce(Return("{\"handle\": 42}")); EXPECT_CALL(handler, Invoke(StrEq("read"), _)).Times(AnyNumber()) - .WillRepeatedly(Invoke([](char const *, json_t * params) { - int offset = json_integer_value(json_array_get(params, 3)); - int length = json_integer_value(json_array_get(params, 4)); + .WillRepeatedly(Invoke([](char const *, wf_json const * params) { + int offset = wf_impl_json_int_get(wf_impl_json_array_get(params, 3)); + int length = wf_impl_json_int_get(wf_impl_json_array_get(params, 4)); int remaining = (offset < 4096) ? 4096 - offset : 0; int count = (length < remaining) ? length : remaining; - std::string data = std::string(count, '*'); + std::ostringstream result; + result << "{" + << "\"data\": \"" << std::string(count, '*') << "\"," + << "\"format\": \"identity\"," + << "\"count\": " << count + << "}"; - json_t * result = json_object(); - json_object_set_new(result, "data", json_string(data.c_str())); - json_object_set_new(result, "format", json_string("identity")); - json_object_set_new(result, "count", json_integer(count)); - - char * result_text = json_dumps(result, 0); - std::string result_str = result_text; - free(result_text); - json_decref(result); - - return result_str; + return result.str(); })); EXPECT_CALL(handler, Invoke(StrEq("close"), _)).Times(AtMost(1)); WsClient client(handler, WF_PROTOCOL_NAME_PROVIDER_CLIENT); @@ -358,13 +354,13 @@ TEST(server, read_large_file_contents) ASSERT_TRUE(connected); std::string response_text = client.Invoke("{\"method\": \"add_filesystem\", \"params\": [\"test\"], \"id\": 42}"); - json_t * response = json_loads(response_text.c_str(), 0, nullptr); - ASSERT_TRUE(json_is_object(response)); - json_t * result = json_object_get(response, "result"); - ASSERT_TRUE(json_is_object(result)); - json_t * id = json_object_get(response, "id"); - ASSERT_EQ(42, json_integer_value(id)); - json_decref(response); + JsonDoc doc(response_text); + wf_json const * response = doc.root(); + ASSERT_TRUE(wf_impl_json_is_object(response)); + wf_json const * result = wf_impl_json_object_get(response, "result"); + ASSERT_TRUE(wf_impl_json_is_object(result)); + wf_json const * id = wf_impl_json_object_get(response, "id"); + ASSERT_EQ(42, wf_impl_json_int_get(id)); std::string base_dir = server.GetBaseDir(); ASSERT_TRUE(File(base_dir).isDirectory()); @@ -390,26 +386,21 @@ TEST(server, read_large_file) EXPECT_CALL(handler, Invoke(StrEq("open"), Open(2))).Times(1) .WillOnce(Return("{\"handle\": 42}")); EXPECT_CALL(handler, Invoke(StrEq("read"), _)).Times(AnyNumber()) - .WillRepeatedly(Invoke([](char const *, json_t * params) { - int offset = json_integer_value(json_array_get(params, 3)); - int length = json_integer_value(json_array_get(params, 4)); + .WillRepeatedly(Invoke([](char const *, wf_json const * params) { + int offset = wf_impl_json_int_get(wf_impl_json_array_get(params, 3)); + int length = wf_impl_json_int_get(wf_impl_json_array_get(params, 4)); int remaining = (offset < 1024000) ? 1024000 - offset : 0; int count = (length < remaining) ? length : remaining; - std::string data = std::string(count, '*'); + std::ostringstream result; + result << "{" + << "\"data\": \"" << std::string(count, '*') << "\"," + << "\"format\": \"identity\"," + << "\"count\": " << count + << "}"; - json_t * result = json_object(); - json_object_set_new(result, "data", json_string(data.c_str())); - json_object_set_new(result, "format", json_string("identity")); - json_object_set_new(result, "count", json_integer(count)); - - char * result_text = json_dumps(result, 0); - std::string result_str = result_text; - free(result_text); - json_decref(result); - - return result_str; + return result.str(); })); EXPECT_CALL(handler, Invoke(StrEq("close"), _)).Times(AtMost(1)); WsClient client(handler, WF_PROTOCOL_NAME_PROVIDER_CLIENT); @@ -418,13 +409,13 @@ TEST(server, read_large_file) ASSERT_TRUE(connected); std::string response_text = client.Invoke("{\"method\": \"add_filesystem\", \"params\": [\"test\"], \"id\": 42}"); - json_t * response = json_loads(response_text.c_str(), 0, nullptr); - ASSERT_TRUE(json_is_object(response)); - json_t * result = json_object_get(response, "result"); - ASSERT_TRUE(json_is_object(result)); - json_t * id = json_object_get(response, "id"); - ASSERT_EQ(42, json_integer_value(id)); - json_decref(response); + JsonDoc doc(response_text); + wf_json const * response = doc.root(); + ASSERT_TRUE(wf_impl_json_is_object(response)); + wf_json const * result = wf_impl_json_object_get(response, "result"); + ASSERT_TRUE(wf_impl_json_is_object(result)); + wf_json const * id = wf_impl_json_object_get(response, "id"); + ASSERT_EQ(42, wf_impl_json_int_get(id)); std::string base_dir = server.GetBaseDir(); ASSERT_TRUE(File(base_dir).isDirectory()); @@ -450,13 +441,13 @@ TEST(server, readdir) ASSERT_TRUE(connected); std::string response_text = client.Invoke("{\"method\": \"add_filesystem\", \"params\": [\"test\"], \"id\": 42}"); - json_t * response = json_loads(response_text.c_str(), 0, nullptr); - ASSERT_TRUE(json_is_object(response)); - json_t * result = json_object_get(response, "result"); - ASSERT_TRUE(json_is_object(result)); - json_t * id = json_object_get(response, "id"); - ASSERT_EQ(42, json_integer_value(id)); - json_decref(response); + JsonDoc doc(response_text); + wf_json const * response = doc.root(); + ASSERT_TRUE(wf_impl_json_is_object(response)); + wf_json const * result = wf_impl_json_object_get(response, "result"); + ASSERT_TRUE(wf_impl_json_is_object(result)); + wf_json const * id = wf_impl_json_object_get(response, "id"); + ASSERT_EQ(42, wf_impl_json_int_get(id)); std::string base_dir = server.GetBaseDir(); ASSERT_TRUE(File(base_dir).isDirectory()); diff --git a/test/webfuse/test_server_protocol.cc b/test/webfuse/test_server_protocol.cc index bc608ba..5c1a1fd 100644 --- a/test/webfuse/test_server_protocol.cc +++ b/test/webfuse/test_server_protocol.cc @@ -1,6 +1,8 @@ #include "webfuse/test_util/server_protocol.hpp" #include "webfuse/test_util/ws_client.hpp" #include "webfuse/test_util/file.hpp" +#include "webfuse/test_util/json_doc.hpp" +#include "webfuse/impl/json/node.h" #include "webfuse/mocks/mock_invokation_handler.hpp" #include "webfuse/mocks/getattr_matcher.hpp" #include "webfuse/protocol_names.h" @@ -8,6 +10,7 @@ #include #include +using webfuse_test::JsonDoc; using webfuse_test::MockInvokationHander; using webfuse_test::WsClient; using webfuse_test::ServerProtocol; @@ -33,24 +36,24 @@ TEST(server_protocol, add_filesystem) { std::string response_text = client.Invoke("{\"method\": \"authenticate\", \"params\": [\"username\", {\"username\": \"bob\", \"password\": \"secret\"}], \"id\": 23}"); - json_t * response = json_loads(response_text.c_str(), 0, nullptr); - ASSERT_TRUE(json_is_object(response)); - json_t * result = json_object_get(response, "result"); - ASSERT_TRUE(json_is_object(result)); - json_t * id = json_object_get(response, "id"); - ASSERT_EQ(23, json_integer_value(id)); - json_decref(response); + JsonDoc doc(response_text); + wf_json const * response = doc.root(); + ASSERT_TRUE(wf_impl_json_is_object(response)); + wf_json const * result = wf_impl_json_object_get(response, "result"); + ASSERT_TRUE(wf_impl_json_is_object(result)); + wf_json const * id = wf_impl_json_object_get(response, "id"); + ASSERT_EQ(23, wf_impl_json_int_get(id)); } { std::string response_text = client.Invoke("{\"method\": \"add_filesystem\", \"params\": [\"test\"], \"id\": 42}"); - json_t * response = json_loads(response_text.c_str(), 0, nullptr); - ASSERT_TRUE(json_is_object(response)); - json_t * result = json_object_get(response, "result"); - ASSERT_TRUE(json_is_object(result)); - json_t * id = json_object_get(response, "id"); - ASSERT_EQ(42, json_integer_value(id)); - json_decref(response); + JsonDoc doc(response_text); + wf_json const * response = doc.root(); + ASSERT_TRUE(wf_impl_json_is_object(response)); + wf_json const * result = wf_impl_json_object_get(response, "result"); + ASSERT_TRUE(wf_impl_json_is_object(result)); + wf_json const * id = wf_impl_json_object_get(response, "id"); + ASSERT_EQ(42, wf_impl_json_int_get(id)); } std::string base_dir = server.GetBaseDir(); @@ -76,13 +79,13 @@ TEST(server_protocol, add_filesystem_fail_without_authentication) { std::string response_text = client.Invoke("{\"method\": \"add_filesystem\", \"params\": [\"test\"], \"id\": 42}"); - json_t * response = json_loads(response_text.c_str(), 0, nullptr); - ASSERT_TRUE(json_is_object(response)); - json_t * error = json_object_get(response, "error"); - ASSERT_TRUE(json_is_object(error)); - json_t * id = json_object_get(response, "id"); - ASSERT_EQ(42, json_integer_value(id)); - json_decref(response); + JsonDoc doc(response_text); + wf_json const * response = doc.root(); + ASSERT_TRUE(wf_impl_json_is_object(response)); + wf_json const * error = wf_impl_json_object_get(response, "error"); + ASSERT_TRUE(wf_impl_json_is_object(error)); + wf_json const * id = wf_impl_json_object_get(response, "id"); + ASSERT_EQ(42, wf_impl_json_int_get(id)); } auto disconnected = client.Disconnect(); @@ -103,13 +106,13 @@ TEST(server_protocol, authenticate_fail_wrong_credentials) { std::string response_text = client.Invoke("{\"method\": \"authenticate\", \"params\": [\"username\", {\"username\": \"alice\", \"password\": \"cheshire\"}], \"id\": 23}"); - json_t * response = json_loads(response_text.c_str(), 0, nullptr); - ASSERT_TRUE(json_is_object(response)); - json_t * error = json_object_get(response, "error"); - ASSERT_TRUE(json_is_object(error)); - json_t * id = json_object_get(response, "id"); - ASSERT_EQ(23, json_integer_value(id)); - json_decref(response); + JsonDoc doc(response_text); + wf_json const * response = doc.root(); + ASSERT_TRUE(wf_impl_json_is_object(response)); + wf_json const * error = wf_impl_json_object_get(response, "error"); + ASSERT_TRUE(wf_impl_json_is_object(error)); + wf_json const * id = wf_impl_json_object_get(response, "id"); + ASSERT_EQ(23, wf_impl_json_int_get(id)); } auto disconnected = client.Disconnect(); diff --git a/test/webfuse/test_util/invokation_handler.hpp b/test/webfuse/test_util/invokation_handler.hpp index ac8b7fe..84d5acb 100644 --- a/test/webfuse/test_util/invokation_handler.hpp +++ b/test/webfuse/test_util/invokation_handler.hpp @@ -1,9 +1,10 @@ #ifndef WF_TEST_UTIL_INVOKATION_HANDLER_HPP #define WF_TEST_UTIL_INVOKATION_HANDLER_HPP -#include #include +struct wf_json; + namespace webfuse_test { @@ -11,7 +12,7 @@ class InvokationHandler { public: virtual ~InvokationHandler() = default; - virtual std::string Invoke(char const * method, json_t * params) = 0; + virtual std::string Invoke(char const * method, wf_json const * params) = 0; }; } diff --git a/test/webfuse/test_util/jansson_test_environment.cc b/test/webfuse/test_util/jansson_test_environment.cc deleted file mode 100644 index d7e3c2d..0000000 --- a/test/webfuse/test_util/jansson_test_environment.cc +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include - -namespace webfuse_test -{ - -class JanssonTestEnvironment: public ::testing::Environment -{ -public: - ~JanssonTestEnvironment() override { } - - void SetUp() override - { - json_object_seed(0); - } -}; - -::testing::Environment * const jansson_env = ::testing::AddGlobalTestEnvironment(new JanssonTestEnvironment()); - -} \ No newline at end of file diff --git a/test/webfuse/test_util/json_doc.cc b/test/webfuse/test_util/json_doc.cc new file mode 100644 index 0000000..0f527d7 --- /dev/null +++ b/test/webfuse/test_util/json_doc.cc @@ -0,0 +1,45 @@ +#include "webfuse/test_util/json_doc.hpp" + +namespace webfuse_test +{ + +JsonDoc::JsonDoc(std::string const & text) +: contents(text) +{ + doc = wf_impl_json_doc_loadb(const_cast(contents.data()), contents.size()); +} + +JsonDoc::JsonDoc(JsonDoc && other) +{ + contents = std::move(other.contents); + doc = other.doc; + other.doc = nullptr; +} + +JsonDoc& JsonDoc::operator=(JsonDoc && other) +{ + if (this != &other) + { + wf_impl_json_doc_dispose(doc); + contents = std::move(other.contents); + doc = other.doc; + other.doc = nullptr; + } + + return *this; +} + +JsonDoc::~JsonDoc() +{ + if (nullptr != doc) + { + wf_impl_json_doc_dispose(doc); + } +} + +wf_json const * JsonDoc::root() +{ + return wf_impl_json_doc_root(doc); +} + +} \ No newline at end of file diff --git a/test/webfuse/test_util/json_doc.hpp b/test/webfuse/test_util/json_doc.hpp new file mode 100644 index 0000000..c1970be --- /dev/null +++ b/test/webfuse/test_util/json_doc.hpp @@ -0,0 +1,27 @@ +#ifndef WF_TEST_UTIL_JSON_DOC_HPP +#define WF_TEST_UTIL_JSON_DOC_HPP + +#include "webfuse/impl/json/doc.h" +#include + +namespace webfuse_test +{ + +class JsonDoc +{ + JsonDoc(JsonDoc const&) = delete; + JsonDoc& operator=(JsonDoc const&) = delete; +public: + explicit JsonDoc(std::string const & text); + JsonDoc(JsonDoc && other); + JsonDoc& operator=(JsonDoc && other); + ~JsonDoc(); + wf_json const * root(); +private: + std::string contents; + wf_json_doc * doc; +}; + +} + +#endif diff --git a/test/webfuse/test_util/ws_client.cc b/test/webfuse/test_util/ws_client.cc index d074f7b..af9cda2 100644 --- a/test/webfuse/test_util/ws_client.cc +++ b/test/webfuse/test_util/ws_client.cc @@ -1,9 +1,10 @@ #include "webfuse/test_util/ws_client.hpp" #include "webfuse/test_util/invokation_handler.hpp" +#include "webfuse/test_util/json_doc.hpp" +#include "webfuse/impl/json/node.h" #include "webfuse/status.h" #include -#include #include #include @@ -11,6 +12,7 @@ #include #include #include +#include #define TIMEOUT (std::chrono::seconds(10)) @@ -225,52 +227,33 @@ public: { lock.unlock(); - json_t * request = json_loadb(data, length, 0, nullptr); - if (nullptr != request) + JsonDoc doc(std::string(data, length)); + wf_json const * request = doc.root(); + wf_json const * method = wf_impl_json_object_get(request, "method"); + wf_json const * params = wf_impl_json_object_get(request, "params"); + wf_json const * id = wf_impl_json_object_get(request, "id"); + + std::ostringstream response; + response << "{"; + try { - json_t * method = json_object_get(request, "method"); - json_t * params = json_object_get(request, "params"); - json_t * id = json_object_get(request, "id"); - - json_t * response = json_object(); - try - { - std::string result_text = handler_.Invoke(json_string_value(method), params); - json_t * result = json_loads(result_text.c_str(), 0, nullptr); - if (nullptr != result) - { - json_object_set_new(response, "result", result); - } - else - { - json_t * error = json_object(); - json_object_set_new(error, "code", json_integer(WF_BAD)); - json_object_set_new(response, "error",error); - } - - } - catch (...) - { - json_t * error = json_object(); - json_object_set_new(error, "code", json_integer(WF_BAD)); - json_object_set_new(response, "error",error); - } - - json_object_set(response, "id", id); - - char * response_text = json_dumps(response, 0); - lock.lock(); - send_queue.push(response_text); - commands.push(command::send); - lock.unlock(); - - lws_cancel_service(context); - - free(response_text); - - json_decref(response); - json_decref(request); + std::string result_text = handler_.Invoke(wf_impl_json_string_get(method), params); + if (result_text.empty()) { throw std::runtime_error("empty"); } + response << "\"result\": " << result_text; } + catch (...) + { + response << "\"error\": {\"code\": 1}"; + } + + response << ", \"id\": " << wf_impl_json_int_get(id) << "}"; + + lock.lock(); + send_queue.push(response.str()); + commands.push(command::send); + lock.unlock(); + + lws_cancel_service(context); } } diff --git a/test/webfuse/test_util/ws_server.cc b/test/webfuse/test_util/ws_server.cc index d9631be..2e50a35 100644 --- a/test/webfuse/test_util/ws_server.cc +++ b/test/webfuse/test_util/ws_server.cc @@ -1,6 +1,8 @@ #include "webfuse/test_util/ws_server.hpp" #include "webfuse/test_util/invokation_handler.hpp" #include "webfuse/impl/util/lws_log.h" +#include "webfuse/impl/json/node.h" +#include "webfuse/test_util/json_doc.hpp" #include #include @@ -9,6 +11,8 @@ #include #include +using webfuse_test::JsonDoc; + namespace { @@ -85,7 +89,6 @@ public: void OnWritable(struct lws * wsi) override; void SendMessage(char const * message); - void SendMessage(json_t * message); private: static void Run(Private * self); @@ -127,12 +130,6 @@ void WsServer::SendMessage(char const * message) d->SendMessage(message); } -void WsServer::SendMessage(json_t * message) -{ - d->SendMessage(message); -} - - WsServer::Private::Private( InvokationHandler & handler, std::string const & protocol, @@ -264,45 +261,34 @@ void WsServer::Private::SendMessage(char const * message) } } -void WsServer::Private::SendMessage(json_t * message) -{ - char* message_text = json_dumps(message, JSON_COMPACT); - SendMessage(message_text); - json_decref(message); - free(message_text); -} - void WsServer::Private::OnMessageReceived(struct lws * wsi, char const * data, size_t length) { (void) wsi; - json_t * request = json_loadb(data, length, JSON_DECODE_ANY, nullptr); - json_t * method = json_object_get(request, "method"); - json_t * params = json_object_get(request, "params"); - json_t * id = json_object_get(request, "id"); + JsonDoc doc(std::string(data, length)); + wf_json const * request = doc.root(); + wf_json const * method = wf_impl_json_object_get(request, "method"); + wf_json const * params = wf_impl_json_object_get(request, "params"); + wf_json const * id = wf_impl_json_object_get(request, "id"); - if (json_is_string(method) && json_is_array(params) && json_is_integer(id)) + if (wf_impl_json_is_string(method) && wf_impl_json_is_array(params) && wf_impl_json_is_int(id)) { - json_t * response = json_object(); + std::ostringstream response; + response << "{"; try { - std::string result_text = handler_.Invoke(json_string_value(method), params); - json_t * result = json_loads(result_text.c_str(), JSON_DECODE_ANY, nullptr); - json_object_set_new(response, "result", result); + std::string result_text = handler_.Invoke(wf_impl_json_string_get(method), params); + response << "\"result\": " << result_text; } catch (...) { - json_t * error = json_object(); - json_object_set_new(error, "code", json_integer(1)); - json_object_set_new(response, "error", error); + response << "\"error\": {\"code\": 1}"; } + response << ", \"id\": " << wf_impl_json_int_get(id) << "}"; - json_object_set(response, "id", id); - SendMessage(response); + SendMessage(response.str().c_str()); } - - json_decref(request); } std::string const & WsServer::Private::GetUrl() const diff --git a/test/webfuse/test_util/ws_server.hpp b/test/webfuse/test_util/ws_server.hpp index e8b0dfe..0f36336 100644 --- a/test/webfuse/test_util/ws_server.hpp +++ b/test/webfuse/test_util/ws_server.hpp @@ -1,7 +1,6 @@ #ifndef WF_TEST_UTIL_WS_SERVER2_HPP #define WF_TEST_UTIL_WS_SERVER2_HPP -#include #include namespace webfuse_test @@ -22,7 +21,6 @@ public: virtual ~WsServer(); std::string const & GetUrl() const; void SendMessage(char const * message); - void SendMessage(json_t * message); private: class Private; Private * d; diff --git a/test/webfuse/util/test_util.cc b/test/webfuse/util/test_util.cc index 41e12f9..b27c57e 100644 --- a/test/webfuse/util/test_util.cc +++ b/test/webfuse/util/test_util.cc @@ -1,14 +1,15 @@ -#include #include "webfuse/impl/util/json_util.h" +#include "webfuse/test_util/json_doc.hpp" + +#include + +using webfuse_test::JsonDoc; TEST(jsonrpc_util, get_int) { - json_t * object = json_object(); - json_object_set_new(object, "key", json_integer(23)); - int value = wf_impl_json_get_int(object, "key", 42); + JsonDoc doc("{\"key\": 23}"); + int value = wf_impl_json_get_int(doc.root(), "key", 42); ASSERT_EQ(23, value); - - json_decref(object); } TEST(jsonrpc_util, failed_to_get_null_object) @@ -20,28 +21,21 @@ TEST(jsonrpc_util, failed_to_get_null_object) TEST(jsonrpc_util, failed_to_get_not_object) { - json_t * object = json_array(); - int value = wf_impl_json_get_int(nullptr, "key", 42); + JsonDoc doc("[]"); + int value = wf_impl_json_get_int(doc.root(), "key", 42); ASSERT_EQ(42, value); - - json_decref(object); } TEST(jsonrpc_util, failed_to_get_invalid_key) { - json_t * object = json_object(); - int value = wf_impl_json_get_int(object, "key", 42); + JsonDoc doc("{}"); + int value = wf_impl_json_get_int(doc.root(), "key", 42); ASSERT_EQ(42, value); - - json_decref(object); } TEST(jsonrpc_util, failed_to_get_invalid_value_type) { - json_t * object = json_object(); - json_object_set_new(object, "key", json_string("42")); - int value = wf_impl_json_get_int(object, "key", 42); + JsonDoc doc("{\"key\": \"42\"}"); + int value = wf_impl_json_get_int(doc.root(), "key", 42); ASSERT_EQ(42, value); - - json_decref(object); } \ No newline at end of file