summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--bindings/samples/hello3.c114
-rw-r--r--coverage/.gitignore8
-rw-r--r--coverage/bin/Makefile5
l---------coverage/ldpath/strong/hellov2.so1
-rwxr-xr-xcoverage/scripts/00-trace.sh3
-rwxr-xr-xcoverage/scripts/01-http.sh1
-rwxr-xr-xcoverage/scripts/02-hello.sh14
-rwxr-xr-x[-rw-r--r--]coverage/scripts/07-inet.sh0
-rwxr-xr-xcoverage/scripts/run-test.sh61
-rw-r--r--docs/reference-v3/types-and-globals.md2
-rw-r--r--include/afb/afb-auth.h10
-rw-r--r--src/afb-apiset.c16
-rw-r--r--src/afb-apiset.h2
-rw-r--r--src/main-afb-daemon.c3
-rw-r--r--src/tests/CMakeLists.txt1
-rw-r--r--src/tests/apiset/test-apiset.c44
-rw-r--r--src/tests/wrap-json/test-wrap-json.c155
-rw-r--r--src/wrap-json.c12
19 files changed, 410 insertions, 43 deletions
diff --git a/.gitignore b/.gitignore
index abc051fe..d7183090 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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.