ubus: add count test to validate large message sizes
authorAlexandru Ardelean <ardeleanalex@gmail.com>
Fri, 27 Jun 2014 16:11:45 +0000 (19:11 +0300)
committerFelix Fietkau <nbd@openwrt.org>
Thu, 3 Jul 2014 10:47:11 +0000 (12:47 +0200)
Client creates a string "1 2 3 ... 10000 ...", sends it to the server
along with the maximum number in the string.

Server creates another string like the client sent.

It validates it and, returns strcmp()'s result.

This is loop-ed every 2 seconds.

examples/CMakeLists.txt
examples/client.c
examples/count.c [new file with mode: 0644]
examples/count.h [new file with mode: 0644]
examples/server.c

index 3d06161..0279f6e 100644 (file)
@@ -4,9 +4,9 @@ ADD_DEFINITIONS(-I..)
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/..)
 
 IF (BUILD_EXAMPLES)
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/..)
 
 IF (BUILD_EXAMPLES)
-       ADD_EXECUTABLE(server server.c)
+       ADD_EXECUTABLE(server server.c count.c)
        TARGET_LINK_LIBRARIES(server ubus ubox blobmsg_json)
 
        TARGET_LINK_LIBRARIES(server ubus ubox blobmsg_json)
 
-       ADD_EXECUTABLE(client client.c)
+       ADD_EXECUTABLE(client client.c count.c)
        TARGET_LINK_LIBRARIES(client ubus ubox)
 ENDIF()
        TARGET_LINK_LIBRARIES(client ubus ubox)
 ENDIF()
index 4d6b6ec..b586eaf 100644 (file)
@@ -17,6 +17,7 @@
 #include <libubox/ustream.h>
 
 #include "libubus.h"
 #include <libubox/ustream.h>
 
 #include "libubus.h"
+#include "count.h"
 
 static struct ubus_context *ctx;
 static struct blob_buf b;
 
 static struct ubus_context *ctx;
 static struct blob_buf b;
@@ -55,10 +56,85 @@ static void test_client_notify_cb(struct uloop_timeout *timeout)
        uloop_timeout_set(timeout, 1000);
 }
 
        uloop_timeout_set(timeout, 1000);
 }
 
+enum {
+       RETURN_CODE,
+       __RETURN_MAX,
+};
+
+static const struct blobmsg_policy return_policy[__RETURN_MAX] = {
+       [RETURN_CODE] = { .name = "rc", .type = BLOBMSG_TYPE_INT32 },
+};
+
+static void test_count_data_cb(struct ubus_request *req,
+                                   int type, struct blob_attr *msg)
+{
+       struct blob_attr *tb[__RETURN_MAX];
+       int rc;
+       uint32_t count_to = *(uint32_t *)req->priv;
+
+       blobmsg_parse(return_policy, __RETURN_MAX, tb, blob_data(msg), blob_len(msg));
+
+       if (!tb[RETURN_CODE]) {
+               fprintf(stderr, "No return code received from server\n");
+               return;
+       }
+       rc = blobmsg_get_u32(tb[RETURN_CODE]);
+       if (rc)
+               fprintf(stderr, "Corruption of data with count up to '%u'\n", count_to);
+       else
+               fprintf(stderr, "Server validated our count up to '%u'\n", count_to);
+}
+
+static void test_count(struct uloop_timeout *timeout)
+{
+       enum {
+               COUNT_TO_MIN = 10000,
+               COUNT_TO_MAX = 1000000,
+               PROGRESSION  = 100,
+       };
+
+       uint32_t id;
+       static uint32_t count_to = 100000;
+       static int count_progression = PROGRESSION;
+       char *s;
+
+       if (count_to <= COUNT_TO_MIN)
+               count_progression = PROGRESSION;
+       else if (count_to >= COUNT_TO_MAX)
+               count_progression = -PROGRESSION;
+
+       count_to += count_progression;
+
+       s = count_to_number(count_to);
+       if (!s)
+               fprintf(stderr, "Could not allocate memory to count up to '%u'\n", count_to);
+
+       fprintf(stderr, "Sending count up to '%u'; string has length '%u'\n",
+               count_to, (uint32_t)strlen(s));
+       blob_buf_init(&b, 0);
+       blobmsg_add_u32(&b, "to", count_to);
+       blobmsg_add_string(&b, "string", s);
+
+       if (ubus_lookup_id(ctx, "test", &id)) {
+               fprintf(stderr, "Failed to look up test object\n");
+               return;
+       }
+
+       ubus_invoke(ctx, id, "count", b.head, test_count_data_cb, &count_to, 5000);
+
+       free(s);
+
+       uloop_timeout_set(timeout, 2000);
+}
+
 static struct uloop_timeout notify_timer = {
        .cb = test_client_notify_cb,
 };
 
 static struct uloop_timeout notify_timer = {
        .cb = test_client_notify_cb,
 };
 
+static struct uloop_timeout count_timer = {
+       .cb = test_count,
+};
+
 static void test_client_fd_data_cb(struct ustream *s, int bytes)
 {
        char *data, *sep;
 static void test_client_fd_data_cb(struct ustream *s, int bytes)
 {
        char *data, *sep;
@@ -121,6 +197,8 @@ static void client_main(void)
        req.complete_cb = test_client_complete_cb;
        ubus_complete_request_async(ctx, &req);
 
        req.complete_cb = test_client_complete_cb;
        ubus_complete_request_async(ctx, &req);
 
+       uloop_timeout_set(&count_timer, 2000);
+
        uloop_run();
 }
 
        uloop_run();
 }
 
diff --git a/examples/count.c b/examples/count.c
new file mode 100644 (file)
index 0000000..e3e9c8a
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2011 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include "count.h"
+
+char *count_to_number(uint32_t num)
+{
+       uint32_t ptr = 0, size = 0;
+       uint32_t written = 0, i;
+       int new_line_every_n_numbers = 30;
+       char *s;
+
+       for (i=0; i < num; ++i) {
+               size += snprintf(NULL, 0, "%u ", i);
+               if (i > 0 && i % new_line_every_n_numbers == 0)
+                       size++;
+       }
+       size++; /* one for null char */
+
+       s = calloc(size, sizeof(char));
+       if (!s)
+               goto out;
+
+       for (i=0; i < num; ++i) {
+               written = sprintf(&s[ptr], "%u ", i);
+               ptr  += written;
+               if (i > 0 && i % new_line_every_n_numbers == 0) {
+                       sprintf(&s[ptr], "\n");
+                       ptr++;
+               }
+       }
+
+out:
+       return s;
+}
diff --git a/examples/count.h b/examples/count.h
new file mode 100644 (file)
index 0000000..1f90f21
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2011 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __COUNT_H
+#define __COUNT_H
+
+char *count_to_number(uint32_t num);
+
+#endif
index 95eba5e..bbb3347 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <libubox/blobmsg_json.h>
 #include "libubus.h"
 
 #include <libubox/blobmsg_json.h>
 #include "libubus.h"
+#include "count.h"
 
 static struct ubus_context *ctx;
 static struct ubus_subscriber test_event;
 
 static struct ubus_context *ctx;
 static struct ubus_subscriber test_event;
@@ -149,9 +150,48 @@ static int test_watch(struct ubus_context *ctx, struct ubus_object *obj,
        return ret;
 }
 
        return ret;
 }
 
+enum {
+    COUNT_TO,
+    COUNT_STRING,
+    __COUNT_MAX
+};
+
+static const struct blobmsg_policy count_policy[__COUNT_MAX] = {
+    [COUNT_TO] = { .name = "to", .type = BLOBMSG_TYPE_INT32 },
+    [COUNT_STRING] = { .name = "string", .type = BLOBMSG_TYPE_STRING },
+};
+
+static int test_count(struct ubus_context *ctx, struct ubus_object *obj,
+                     struct ubus_request_data *req, const char *method,
+                     struct blob_attr *msg)
+{
+       struct blob_attr *tb[__COUNT_MAX];
+       char *s1, *s2;
+       uint32_t num;
+
+       blobmsg_parse(count_policy, __COUNT_MAX, tb, blob_data(msg), blob_len(msg));
+       if (!tb[COUNT_TO] || !tb[COUNT_STRING])
+               return UBUS_STATUS_INVALID_ARGUMENT;
+
+       num = blobmsg_get_u32(tb[COUNT_TO]);
+       s1 = blobmsg_get_string(tb[COUNT_STRING]);
+       s2 = count_to_number(num);
+       if (!s1 || !s2) {
+               free(s2);
+               return UBUS_STATUS_UNKNOWN_ERROR;
+       }
+       blob_buf_init(&b, 0);
+       blobmsg_add_u32(&b, "rc", strcmp(s1, s2));
+       ubus_send_reply(ctx, req, b.head);
+       free(s2);
+
+       return 0;
+}
+
 static const struct ubus_method test_methods[] = {
        UBUS_METHOD("hello", test_hello, hello_policy),
        UBUS_METHOD("watch", test_watch, watch_policy),
 static const struct ubus_method test_methods[] = {
        UBUS_METHOD("hello", test_hello, hello_policy),
        UBUS_METHOD("watch", test_watch, watch_policy),
+       UBUS_METHOD("count", test_count, count_policy),
 };
 
 static struct ubus_object_type test_object_type =
 };
 
 static struct ubus_object_type test_object_type =