diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | bindings/samples/hello3.c | 114 | ||||
-rw-r--r-- | coverage/.gitignore | 8 | ||||
-rw-r--r-- | coverage/bin/Makefile | 5 | ||||
l--------- | coverage/ldpath/strong/hellov2.so | 1 | ||||
-rwxr-xr-x | coverage/scripts/00-trace.sh | 3 | ||||
-rwxr-xr-x | coverage/scripts/01-http.sh | 1 | ||||
-rwxr-xr-x | coverage/scripts/02-hello.sh | 14 | ||||
-rwxr-xr-x[-rw-r--r--] | coverage/scripts/07-inet.sh | 0 | ||||
-rwxr-xr-x | coverage/scripts/run-test.sh | 61 | ||||
-rw-r--r-- | docs/reference-v3/types-and-globals.md | 2 | ||||
-rw-r--r-- | include/afb/afb-auth.h | 10 | ||||
-rw-r--r-- | src/afb-apiset.c | 16 | ||||
-rw-r--r-- | src/afb-apiset.h | 2 | ||||
-rw-r--r-- | src/main-afb-daemon.c | 3 | ||||
-rw-r--r-- | src/tests/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/tests/apiset/test-apiset.c | 44 | ||||
-rw-r--r-- | src/tests/wrap-json/test-wrap-json.c | 155 | ||||
-rw-r--r-- | src/wrap-json.c | 12 |
19 files changed, 410 insertions, 43 deletions
@@ -9,7 +9,6 @@ CMakeFiles/ CMakeCache.txt nbproject/private/* cmake_install.cmake -*.so .vscode stress-out* node_modules/ diff --git a/bindings/samples/hello3.c b/bindings/samples/hello3.c index 477e47bd..7e54e3a9 100644 --- a/bindings/samples/hello3.c +++ b/bindings/samples/hello3.c @@ -467,6 +467,11 @@ static void setloa (afb_req_t request) afb_req_reply_f(request, NULL, NULL, "LOA set to %d", loa); } +static void ok (afb_req_t request) +{ + afb_req_reply_f(request, NULL, NULL, NULL); +} + static void setctx (afb_req_t request) { struct json_object *x = afb_req_json(request); @@ -530,6 +535,23 @@ static void ref(afb_req_t request) afb_req_unref(request); } +static void mute(afb_req_t request) +{ +} + +void queue_cb(int signum, void *arg) +{ + afb_req_t request = arg; + afb_req_reply(request, NULL, NULL, NULL); + afb_req_unref(request); +} + +static void queue(afb_req_t request) +{ + afb_req_addref(request); + afb_api_queue_job(afb_req_get_api(request), queue_cb, request, NULL, 0); +} + static void rootdir (afb_req_t request) { ssize_t s; @@ -586,6 +608,88 @@ static void locale (afb_req_t request) static void api (afb_req_t request); +/** + * Definition of an authorization entry + */ +static struct afb_auth auths[] = { + { /* 0 */ + .type = afb_auth_Or, + .first = &auths[1], + .next = &auths[9], + }, + { /* 1 */ + .type = afb_auth_And, + .first = &auths[2], + .next = &auths[3], + }, + { /* 2 */ + .type = afb_auth_Yes + }, + { /* 3 */ + .type = afb_auth_And, + .first = &auths[4], + .next = &auths[5], + }, + { /* 4 */ + .type = afb_auth_LOA, + .loa = 0 + }, + { /* 5 */ + .type = afb_auth_Or, + .first = &auths[6], + .next = &auths[7], + }, + { /* 6 */ + .type = afb_auth_No + }, + { /* 7 */ + .type = afb_auth_Not, + .first = &auths[8] + }, + { /* 8 */ + .type = afb_auth_Yes + }, + { /* 9 */ + .type = afb_auth_And, + .first = &auths[10], + .next = &auths[13], + }, + { /* 10 */ + .type = afb_auth_Or, + .first = &auths[12], + .next = &auths[11], + }, + { /* 11 */ + .type = afb_auth_Not, + .first = &auths[13] + }, + { /* 12 */ + .type = afb_auth_Token + }, + { /* 13 */ + .type = afb_auth_And, + .first = &auths[14], + .next = &auths[17], + }, + { /* 14 */ + .type = afb_auth_Or, + .first = &auths[16], + .next = &auths[15], + }, + { /* 15 */ + .type = afb_auth_Not, + .first = &auths[16] + }, + { /* 16 */ + .type = afb_auth_Permission, + .text = "permission" + }, + { /* 17 */ + .type = afb_auth_Yes + } +}; + + // NOTE: this sample does not use session to keep test a basic as possible // in real application most APIs should be protected with AFB_SESSION_CHECK static const struct afb_verb_v3 verbs[]= { @@ -611,11 +715,15 @@ static const struct afb_verb_v3 verbs[]= { { .verb="appid", .callback=appid }, { .verb="uid", .callback=uid }, { .verb="exit", .callback=exitnow }, - { .verb="close", .callback=closess }, - { .verb="set-loa", .callback=setloa }, + { .verb="close", .callback=closess, .session=AFB_SESSION_CLOSE }, + { .verb="set-loa", .callback=setloa, .auth = &auths[0] }, + { .verb="has-loa-1", .callback=ok, .session=AFB_SESSION_LOA_1 }, + { .verb="has-loa-2", .callback=ok, .session=AFB_SESSION_LOA_2 }, + { .verb="has-loa-3", .callback=ok, .session=AFB_SESSION_LOA_3 }, { .verb="setctx", .callback=setctx, .vcbdata = (void*)(intptr_t)1 }, { .verb="setctxif", .callback=setctx, .vcbdata = (void*)(intptr_t)0 }, { .verb="getctx", .callback=getctx }, + { .verb="reftok", .callback=ok, .session=AFB_SESSION_CHECK | AFB_SESSION_REFRESH }, { .verb="info", .callback=info }, { .verb="eventloop", .callback=eventloop }, { .verb="dbus", .callback=dbus }, @@ -625,6 +733,8 @@ static const struct afb_verb_v3 verbs[]= { { .verb="rootdir", .callback=rootdir}, { .verb="locale", .callback=locale}, { .verb="api", .callback=api}, + { .verb="mute", .callback=mute}, + { .verb="queue", .callback=queue}, { .verb=NULL} }; diff --git a/coverage/.gitignore b/coverage/.gitignore index 69f6ea4f..531f1a98 100644 --- a/coverage/.gitignore +++ b/coverage/.gitignore @@ -8,7 +8,7 @@ bin/afb-daemon-cov bin/test-apiset bin/test-session bin/test-wrap-json -*.o -*.so -*.gcda -*.gcno +bin/*.o +bin/*.so +bin/*.gcda +bin/*.gcno diff --git a/coverage/bin/Makefile b/coverage/bin/Makefile index f9d561ed..ef8b68e8 100644 --- a/coverage/bin/Makefile +++ b/coverage/bin/Makefile @@ -62,11 +62,10 @@ cflags = $(ccflags) $(ldflags) defs = -DAGL_DEVEL \ -DWITH_MONITORING_OPTION \ - -DWITH_SUPERVISION \ -DAFB_VERSION=\"cov\" \ -DBINDING_INSTALL_DIR=\"$(shell pwd)/fake\" -afb_lib_src = $(shell ls $(srcdir)/*.c | egrep -v '/afs-|/main-' ) +afb_lib_src = $(shell ls $(srcdir)/*.c | egrep -v '/afs-|/main-|/fdev-epoll.c|/afb-ws-client.c' ) afb_lib_obj = $(patsubst $(srcdir)/%.c,%.o,$(afb_lib_src)) afb_lib = afb-lib.a afb_lib_defs = $(defs) @@ -74,7 +73,7 @@ afb_lib_defs = $(defs) afb_daemon_srcs = $(srcdir)/main-afb-daemon.c $(afb_lib_obj) afb_daemon_defs = $(afb_lib_defs) -afb_client_srcs = $(srcdir)/main-afb-client-demo.c $(afb_lib_src) +afb_client_srcs = $(srcdir)/main-afb-client-demo.c $(srcdir)/afb-ws-client.c $(afb_lib_src) afb_client_defs = $(defs) tst_defs = $(defs) diff --git a/coverage/ldpath/strong/hellov2.so b/coverage/ldpath/strong/hellov2.so new file mode 120000 index 00000000..f60e708b --- /dev/null +++ b/coverage/ldpath/strong/hellov2.so @@ -0,0 +1 @@ +../../bin/hellov2.so
\ No newline at end of file diff --git a/coverage/scripts/00-trace.sh b/coverage/scripts/00-trace.sh index 27edc5b1..247be611 100755 --- a/coverage/scripts/00-trace.sh +++ b/coverage/scripts/00-trace.sh @@ -2,6 +2,7 @@ $R/bin/afb-client -k $WSURL <<EOC & monitor trace {"add":{"tag":"fun","api":"*","request":"*","event":"*","session":"*","global":"*"}} -monitor trace {"add":{"tag":"T","api":"*","request":"*","event":"*","session":"*","global":"*"}} +monitor trace {"add":{"tag":"T","api":"!(monitor)","request":"*","event":"*","session":"*","global":"*"}} +monitor trace {"add":{"tag":"T","api":"monitor","request":"none"}} monitor trace {"drop":{"tag":"fun"}} EOC diff --git a/coverage/scripts/01-http.sh b/coverage/scripts/01-http.sh index 9ffd640f..cb69595e 100755 --- a/coverage/scripts/01-http.sh +++ b/coverage/scripts/01-http.sh @@ -5,6 +5,7 @@ curl -s -o /dev/null $URL/index.html curl -s -o /dev/null $URL/marrus-orthocanna.jpg curl -s -o /dev/null $URL/test.js curl -s -o /dev/null $URL/icons/marrus-orthocanna.jpg +curl -s -o /dev/null $URL/opa/item/extra/index.html curl -s -o /dev/null $URL/fake-file.html diff --git a/coverage/scripts/02-hello.sh b/coverage/scripts/02-hello.sh index 9e3a9b08..de6e2de4 100755 --- a/coverage/scripts/02-hello.sh +++ b/coverage/scripts/02-hello.sh @@ -38,9 +38,22 @@ hello eventdel {"tag":"ev2"} hello hasperm {"perm":"some-permissison"} hello appid true hello uid true +hello reftok true +hello has_loa-1 +hello has_loa-2 +hello has_loa-3 hello set-loa 1 +hello has_loa-1 +hello has_loa-2 +hello has_loa-3 hello set-loa 3 +hello has_loa-1 +hello has_loa-2 +hello has_loa-3 hello close true +hello has_loa-1 +hello has_loa-2 +hello has_loa-3 hello setctx "some-text-0" hello setctxif "some-text-1" hello getctx @@ -89,6 +102,7 @@ extra ping {"c":[1,2,3]} extra query {"c":[1,2,3]} extra blablabla {"c":[1,2,3]} extra api {"action":"addverb","verb":"ping"} +extra call {"api":"hello","verb":"eventunsub","args":{"tag":"EVENT"}} extra ping {"c":[1,2,3]} hello api {"action":"destroy","api":"extra"} extra ping {"c":[1,2,3]} diff --git a/coverage/scripts/07-inet.sh b/coverage/scripts/07-inet.sh index f4e8a297..f4e8a297 100644..100755 --- a/coverage/scripts/07-inet.sh +++ b/coverage/scripts/07-inet.sh diff --git a/coverage/scripts/run-test.sh b/coverage/scripts/run-test.sh index caaec79f..5d1b9a96 100755 --- a/coverage/scripts/run-test.sh +++ b/coverage/scripts/run-test.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash export R=$(realpath $(dirname $0)/..) export PATH="$R/bin:$R/scripts:$PATH" @@ -45,10 +45,26 @@ mk $R/bin/afb-daemon-cov --no-ldpath --traceapi fake mk $R/bin/afb-daemon-cov --traceditf all --tracesvc all --log error,alarm -LISTEN_FDNAMES=toto,demat LISTEN_FDS=5 mk $R/bin/afb-daemon-cov --no-ldpath --binding $R/bin/demat.so --ws-server sd:demat --call "demat/exit:0" +mk $R/bin/afb-daemon-cov --call noapi/noverb:false + +mk $R/bin/afb-daemon-cov --call not-a-call + +LISTEN_FDNAMES=toto,demat LISTEN_FDS=5 +typeset -x LISTEN_FDNAMES LISTEN_FDS +mk $R/bin/afb-daemon-cov --no-ldpath --binding $R/bin/demat.so --ws-server sd:demat --call "demat/exit:0" +typeset +x LISTEN_FDNAMES LISTEN_FDS mk $R/bin/afb-daemon-cov --weak-ldpaths $R/ldpath/weak --binding $R/bin/demat.so --ws-server sd:demat --call "demat/exit:0" +AFB_DEBUG_BREAK=zero,one,two,main-start AFB_DEBUG_WAIT="here I am" +typeset -x AFB_DEBUG_BREAK AFB_DEBUG_WAIT +mk $R/bin/afb-daemon-cov --rootdir $R/i-will-never-exist +typeset +x AFB_DEBUG_BREAK AFB_DEBUG_WAIT + +mk $R/bin/afb-daemon-cov --workdir=/etc/you/should/not/be/able/to/create/me + +mk $R/bin/afb-daemon-cov --exec $R/it-doesn-t-exist + ########################################################## # test of the bench ########################################################## @@ -85,7 +101,7 @@ $R/bin/afb-daemon-cov \ --name binder-cov \ --port 8888 \ --roothttp $R/www \ - --rootbase /opx \ + --rootbase /opa \ --rootapi /api \ --alias /icons:$R/www \ --apitimeout 90 \ @@ -104,13 +120,48 @@ $R/bin/afb-daemon-cov \ --traceapi all \ --traceses all \ --traceevt all \ + --traceglob none \ --monitoring \ --call demat/ping:true \ + --call hello/ping:false \ --ws-server unix:$R/apis/ws/hello \ --ws-server unix:$R/apis/ws/salut \ - --ws-server localhost:9595/salut \ - --ws-client localhost:9595/salut2 \ --exec $R/scripts/run-parts.sh @p @t +########################################################## +# true life test +########################################################## +mk \ +valgrind \ + --log-file=$R/valgrind.out \ + --trace-children=no \ + --track-fds=yes \ + --leak-check=full \ + --show-leak-kinds=all \ + --num-callers=50 \ +$R/bin/afb-daemon-cov \ + --quiet \ + --quiet \ + --foreground \ + --roothttp $R/www \ + --alias /icons:$R/www \ + --workdir . \ + --uploaddir . \ + --rootdir . \ + --ldpaths $R/ldpath/strong \ + --binding $R/bin/demat.so \ + --auto-api $R/apis/auto \ + --random-token \ + --ws-server unix:$R/apis/ws/hello \ + --ws-server unix:$R/apis/ws/salut \ + --ws-server localhost:9595/salut \ + --exec \ + afb-daemon \ + --auto-api $R/apis/auto \ + --auto-api $R/apis/ws \ + --ws-client localhost:@p/salut2 \ + $R/scripts/run-parts.sh @@p @@t + exit 0 + diff --git a/docs/reference-v3/types-and-globals.md b/docs/reference-v3/types-and-globals.md index 50abeecb..5c10ba97 100644 --- a/docs/reference-v3/types-and-globals.md +++ b/docs/reference-v3/types-and-globals.md @@ -198,7 +198,7 @@ enum afb_auth_type /** authorized if token valid, no data */ afb_auth_Token, - /** authorized if LOA greater than data 'loa' */ + /** authorized if LOA greater than or equal to data 'loa' */ afb_auth_LOA, /** authorized if permission 'text' is granted */ diff --git a/include/afb/afb-auth.h b/include/afb/afb-auth.h index 31cbf6f8..b9162cdc 100644 --- a/include/afb/afb-auth.h +++ b/include/afb/afb-auth.h @@ -34,7 +34,7 @@ enum afb_auth_type /** authorized if token valid, no data */ afb_auth_Token, - /** authorized if LOA greater than data 'loa' */ + /** authorized if LOA greater than or equal to data 'loa' */ afb_auth_LOA, /** authorized if permission 'text' is granted */ @@ -60,18 +60,18 @@ struct afb_auth { /** type of entry @see afb_auth_type */ enum afb_auth_type type; - + union { /** text when @ref type == @ref afb_auth_Permission */ const char *text; - + /** level of assurancy when @ref type == @ref afb_auth_LOA */ unsigned loa; - + /** first child when @ref type in { @ref afb_auth_Or, @ref afb_auth_And, @ref afb_auth_Not } */ const struct afb_auth *first; }; - + /** second child when @ref type in { @ref afb_auth_Or, @ref afb_auth_And } */ const struct afb_auth *next; }; diff --git a/src/afb-apiset.c b/src/afb-apiset.c index f837fae7..6229b371 100644 --- a/src/afb-apiset.c +++ b/src/afb-apiset.c @@ -427,17 +427,23 @@ struct afb_apiset *afb_apiset_subset_get(struct afb_apiset *set) * Set the subset of the set * @param set the api set * @param subset the subset to set + * + * @return 0 in case of success or -1 if it had created a loop */ -void afb_apiset_subset_set(struct afb_apiset *set, struct afb_apiset *subset) +int afb_apiset_subset_set(struct afb_apiset *set, struct afb_apiset *subset) { struct afb_apiset *tmp; - if (subset == set) { - /* avoid infinite loop */ - subset = NULL; - } + + /* avoid infinite loop */ + for (tmp = subset ; tmp ; tmp = tmp->subset) + if (tmp == set) + return -1; + tmp = set->subset; set->subset = afb_apiset_addref(subset); afb_apiset_unref(tmp); + + return 0; } void afb_apiset_onlack_set(struct afb_apiset *set, int (*callback)(void*, struct afb_apiset*, const char*), void *closure, void (*cleanup)(void*)) diff --git a/src/afb-apiset.h b/src/afb-apiset.h index 5aacecc6..1a115fbf 100644 --- a/src/afb-apiset.h +++ b/src/afb-apiset.h @@ -38,7 +38,7 @@ extern void afb_apiset_onlack_set( void *closure, void (*cleanup)(void*closure)); -extern void afb_apiset_subset_set(struct afb_apiset *set, struct afb_apiset *subset); +extern int afb_apiset_subset_set(struct afb_apiset *set, struct afb_apiset *subset); extern struct afb_apiset *afb_apiset_subset_get(struct afb_apiset *set); extern int afb_apiset_add(struct afb_apiset *set, const char *name, struct afb_api_item api); diff --git a/src/main-afb-daemon.c b/src/main-afb-daemon.c index 3f32e879..f1996811 100644 --- a/src/main-afb-daemon.c +++ b/src/main-afb-daemon.c @@ -534,8 +534,7 @@ static void startup_call_unref(struct afb_xreq *xreq) free(sreq->api); free(sreq->verb); json_object_put(sreq->xreq.json); - sreq->index++; - if (sreq->index < sreq->count) + if (++sreq->index < sreq->count) startup_call_current(sreq); else { afb_session_close(sreq->session); diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index f0349a68..b516a9db 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -24,6 +24,7 @@ if(check_FOUND) add_subdirectory(session) add_subdirectory(apiset) add_subdirectory(apiv3) + add_subdirectory(wrap-json) else(check_FOUND) MESSAGE(WARNING "check not found! no test!") endif(check_FOUND) diff --git a/src/tests/apiset/test-apiset.c b/src/tests/apiset/test-apiset.c index ccab4637..b49ade90 100644 --- a/src/tests/apiset/test-apiset.c +++ b/src/tests/apiset/test-apiset.c @@ -549,6 +549,49 @@ END_TEST /*********************************************************************/ +START_TEST (check_subset) +{ + int rc; + struct afb_apiset *a, *b, *c, *d; + + a = afb_apiset_create_subset_first(NULL, "a", 0); + ck_assert_ptr_nonnull(a); + ck_assert_str_eq("a", afb_apiset_name(a)); + ck_assert_ptr_null(afb_apiset_subset_get(a)); + + b = afb_apiset_create_subset_first(a, "b", 0); + ck_assert_ptr_nonnull(b); + ck_assert_str_eq("b", afb_apiset_name(b)); + ck_assert_ptr_eq(b, afb_apiset_subset_get(a)); + ck_assert_ptr_null(afb_apiset_subset_get(b)); + + c = afb_apiset_create_subset_first(a, "c", 0); + ck_assert_ptr_nonnull(c); + ck_assert_str_eq("c", afb_apiset_name(c)); + ck_assert_ptr_eq(c, afb_apiset_subset_get(a)); + ck_assert_ptr_eq(b, afb_apiset_subset_get(c)); + ck_assert_ptr_null(afb_apiset_subset_get(b)); + + d = afb_apiset_create_subset_last(a, "d", 0); + ck_assert_ptr_nonnull(d); + ck_assert_str_eq("d", afb_apiset_name(d)); + ck_assert_ptr_eq(c, afb_apiset_subset_get(a)); + ck_assert_ptr_eq(b, afb_apiset_subset_get(c)); + ck_assert_ptr_eq(d, afb_apiset_subset_get(b)); + ck_assert_ptr_null(afb_apiset_subset_get(d)); + + rc = afb_apiset_subset_set(a, b); + ck_assert(rc == 0); + ck_assert_ptr_eq(b, afb_apiset_subset_get(a)); + ck_assert_ptr_eq(d, afb_apiset_subset_get(b)); + ck_assert_ptr_null(afb_apiset_subset_get(d)); + + afb_apiset_unref(a); +} +END_TEST + +/*********************************************************************/ + static Suite *suite; static TCase *tcase; @@ -575,5 +618,6 @@ int main(int ac, char **av) addtest(check_onlack); addtest(check_settings); addtest(check_classes); + addtest(check_subset); return !!srun(); } diff --git a/src/tests/wrap-json/test-wrap-json.c b/src/tests/wrap-json/test-wrap-json.c index 8e22433e..651320af 100644 --- a/src/tests/wrap-json/test-wrap-json.c +++ b/src/tests/wrap-json/test-wrap-json.c @@ -41,6 +41,69 @@ void tclone(struct json_object *object) json_object_put(o); } + +void objcb(void *closure, struct json_object *obj, const char *key) +{ + const char *prefix = closure; + printf(" %s {%s} %s\n", prefix ?: "", key ?: "[]", json_object_to_json_string_ext(obj, JSON_C_TO_STRING_NOSLASHESCAPE)); +} + +void arrcb(void *closure, struct json_object *obj) +{ + objcb(closure, obj, NULL); +} + +void tforall(struct json_object *object) +{ + wrap_json_for_all(object, objcb, "wrap_json_for_all"); + wrap_json_optobject_for_all(object, objcb, "wrap_json_optobject_for_all"); + wrap_json_object_for_all(object, objcb, "wrap_json_object_for_all"); + wrap_json_optarray_for_all(object, arrcb, "wrap_json_optarray_for_all"); + wrap_json_array_for_all(object, arrcb, "wrap_json_array_for_all"); +} + +struct mix +{ + int n; + struct json_object *pair[2]; +}; + +void mixcb(void *closure, struct json_object *obj, const char *key) +{ + struct mix *mix = closure; + + if (!mix->n) { + mix->pair[0] = json_object_new_object(); + mix->pair[1] = json_object_new_object(); + } + json_object_object_add(mix->pair[mix->n & 1], key, json_object_get(obj)); + mix->n++; +} + +void tmix(struct json_object *object) +{ + struct json_object *z; + struct mix mix = { .n = 0 }; + + wrap_json_object_for_all(object, mixcb, &mix); + if (mix.n) { + z = wrap_json_object_add(wrap_json_clone(mix.pair[0]), mix.pair[1]); + if (!wrap_json_contains(z, mix.pair[0])) + printf(" ERROR mix/1\n"); + if (!wrap_json_contains(z, mix.pair[1])) + printf(" ERROR mix/2\n"); + if (!wrap_json_contains(z, object)) + printf(" ERROR mix/3\n"); + if (!wrap_json_contains(object, z)) + printf(" ERROR mix/4\n"); + if (!wrap_json_equal(object, z)) + printf(" ERROR mix/5\n"); + json_object_put(z); + json_object_put(mix.pair[0]); + json_object_put(mix.pair[1]); + } +} + void p(const char *desc, ...) { int rc; @@ -66,11 +129,74 @@ struct json_object *xo[10]; size_t xz[10]; uint8_t *xy[10]; +int extrchk(const char *desc, const char **array, int length, va_list args) +{ + unsigned m, k; + int n; + + if (!desc) + return 0; + + n = 0; + k = m = 0; + while(*desc) { + switch(*desc) { + case '{': + case '[': k = !(*desc - '{'); m = (m << 1) | k; break; + case '}': + case ']': m = m >> 1; k = m&1; break; + case 's': + if (!k) + (void)va_arg(args, char**); + else { + if (n > length) + return -1; + array[n++] = va_arg(args, const char*); + } + break; + case '%': (void)va_arg(args, size_t*); k = m&1; break; + case 'n': k = m&1; break; + case 'b': + case 'i': (void)va_arg(args, int*); k = m&1; break; + case 'I': (void)va_arg(args, int64_t*); k = m&1; break; + case 'f': + case 'F': (void)va_arg(args, double*); k = m&1; break; + case 'o': (void)va_arg(args, struct json_object**), k = m&1; break; + case 'O': (void)va_arg(args, struct json_object**); k = m&1; break; + case 'y': + case 'Y': + (void)va_arg(args, uint8_t**); + (void)va_arg(args, size_t*); + k = m&1; + break; + default: + break; + } + desc++; + } + return n; +} + +const char *mkeys[5]; + +void tchk(struct json_object *object, const char *desc, const char **keys, int length, int qrc) +{ + int rm, rc; + + rm = wrap_json_match(object, desc, keys[0], keys[1], keys[2], keys[3], keys[4]); + rc = wrap_json_check(object, desc, keys[0], keys[1], keys[2], keys[3], keys[4]); + if (rc != qrc) + printf(" ERROR DIFFERS[char %d err %d] %s\n", wrap_json_get_error_position(rc), wrap_json_get_error_code(rc), wrap_json_get_error_string(rc)); + if (rm != !rc) + printf(" ERROR OF MATCH\n"); +} + void u(const char *value, const char *desc, ...) { unsigned m, k; - int rc; + int rc, n; va_list args; + const char *d; struct json_object *object, *o; memset(xs, 0, sizeof xs); @@ -85,14 +211,15 @@ void u(const char *value, const char *desc, ...) rc = wrap_json_vunpack(object, desc, args); va_end(args); if (rc) - printf(" ERROR[char %d err %d] %s\n\n", wrap_json_get_error_position(rc), wrap_json_get_error_code(rc), wrap_json_get_error_string(rc)); + printf(" ERROR[char %d err %d] %s", wrap_json_get_error_position(rc), wrap_json_get_error_code(rc), wrap_json_get_error_string(rc)); else { value = NULL; printf(" SUCCESS"); + d = desc; va_start(args, desc); k = m = 0; - while(*desc) { - switch(*desc) { + while(*d) { + switch(*d) { case '{': m = (m << 1) | 1; k = 1; break; case '}': m = m >> 1; k = m&1; break; case '[': m = m << 1; k = 0; break; @@ -102,7 +229,7 @@ void u(const char *value, const char *desc, ...) case 'n': printf(" n"); k = m&1; break; case 'b': printf(" b:%d", *va_arg(args, int*)); k = m&1; break; case 'i': printf(" i:%d", *va_arg(args, int*)); k = m&1; break; - case 'I': printf(" I:%lld", *va_arg(args, int64_t*)); k = m&1; break; + case 'I': printf(" I:%lld", (long long int)*va_arg(args, int64_t*)); k = m&1; break; case 'f': printf(" f:%f", *va_arg(args, double*)); k = m&1; break; case 'F': printf(" F:%f", *va_arg(args, double*)); k = m&1; break; case 'o': printf(" o:%s", json_object_to_json_string_ext(*va_arg(args, struct json_object**), JSON_C_TO_STRING_NOSLASHESCAPE)); k = m&1; break; @@ -112,17 +239,27 @@ void u(const char *value, const char *desc, ...) uint8_t *p = *va_arg(args, uint8_t**); size_t s = *va_arg(args, size_t*); printf(" y/%d:%.*s", (int)s, (int)s, (char*)p); - k ^= m&1; + k = m&1; break; } default: break; } - desc++; + d++; } va_end(args); - printf("\n\n"); } + printf("\n"); + va_start(args, desc); + n = extrchk(desc, mkeys, (int)(sizeof mkeys / sizeof *mkeys), args); + va_end(args); + if (n < 0) + printf(" ERROR: too much keys in %s\n", desc); + else + tchk(object, desc, mkeys, n, rc); tclone(object); + tforall(object); + tmix(object); + printf("\n"); json_object_put(object); } @@ -329,6 +466,6 @@ int main() c("{\"a\":true,\"b\":false}", "{\"a\":true}", 0, 1); c("{\"a\":true,\"b\":false}", "{\"a\":true,\"c\":false}", 0, 0); c("{\"a\":true,\"c\":false}", "{\"a\":true,\"b\":false}", 0, 0); + return 0; } - diff --git a/src/wrap-json.c b/src/wrap-json.c index a1fcb22d..6bf6f4fe 100644 --- a/src/wrap-json.c +++ b/src/wrap-json.c @@ -815,7 +815,7 @@ int wrap_json_check(struct json_object *object, const char *desc, ...) va_list args; va_start(args, desc); - rc = vunpack(object, desc, args, 0); + rc = wrap_json_vcheck(object, desc, args); va_end(args); return rc; } @@ -831,9 +831,9 @@ int wrap_json_match(struct json_object *object, const char *desc, ...) va_list args; va_start(args, desc); - rc = vunpack(object, desc, args, 0); + rc = wrap_json_vmatch(object, desc, args); va_end(args); - return !rc; + return rc; } int wrap_json_vunpack(struct json_object *object, const char *desc, va_list args) @@ -992,9 +992,13 @@ struct json_object *wrap_json_clone_depth(struct json_object *item, int depth) } /** - * Clones the 'object': returns a copy of it. But doen't clones + * Clones the 'object': returns a copy of it. But doesn't clones * the content. Synonym of wrap_json_clone_depth(object, 1). * + * Be aware that this implementation doesn't clones content that is deeper + * than 1 but it does link these contents to the original object and + * increments their use count. So, everything deeper that 1 is still available. + * * @param object the object to clone * * @return a copy of the object. |