From 829678392282902768bb6cd7201ea07981f399f2 Mon Sep 17 00:00:00 2001 From: "hyunuk.tak" Date: Wed, 23 Mar 2022 15:18:14 +0900 Subject: [PATCH] Add core test case for scan Change-Id: I22aeb57052fabf469fa78dee72fc5e5d04faf79a Signed-off-by: hyunuk.tak --- src/thread-util.c | 4 +- tests/unittest/mocks/thread-mock-dbus.cpp | 72 +++++++++++++++-------- tests/unittest/mocks/thread-mock-dummy.cpp | 94 +++++++++++++++++++++++++++++- tests/unittest/mocks/thread-mock-dummy.h | 8 ++- tests/unittest/mocks/thread-mock-util.cpp | 54 +++++++++++++++++ tests/unittest/mocks/thread-mock-util.h | 54 +++++++++++++++++ tests/unittest/thread-unittest-core.cpp | 36 +++++++++++- 7 files changed, 289 insertions(+), 33 deletions(-) create mode 100644 tests/unittest/mocks/thread-mock-util.cpp create mode 100644 tests/unittest/mocks/thread-mock-util.h diff --git a/src/thread-util.c b/src/thread-util.c index fc9eebd..81e96bb 100644 --- a/src/thread-util.c +++ b/src/thread-util.c @@ -162,8 +162,8 @@ void __thread_dbus_handle_scan_cb(gboolean res, int length = 0; uint16_t panid = 0; uint16_t joiner_udp_port = 0; - uint16_t channel = 0; - uint16_t rssi = 0; + uint8_t channel = 0; + uint8_t rssi = 0; uint8_t lqi = 0; uint8_t version = 0; bool is_native = 0; diff --git a/tests/unittest/mocks/thread-mock-dbus.cpp b/tests/unittest/mocks/thread-mock-dbus.cpp index 3342ffb..26da5e4 100644 --- a/tests/unittest/mocks/thread-mock-dbus.cpp +++ b/tests/unittest/mocks/thread-mock-dbus.cpp @@ -20,39 +20,39 @@ #include "thread-mock-dummy.h" GDBusConnection *g_bus_get_sync(GBusType bus_type, - GCancellable *cancellable, GError **error) + GCancellable *cancellable, GError **error) { - return (GDBusConnection *)GINT_TO_POINTER(0x1234); + return (GDBusConnection *)GINT_TO_POINTER(0x1111); } GDBusProxy *g_dbus_proxy_new_for_bus_sync(GBusType bus_type, - GDBusProxyFlags flags, GDBusInterfaceInfo *info, - const gchar *name, const gchar *object_path, - const gchar *interface_name, GCancellable *cancellable, - GError **error) + GDBusProxyFlags flags, GDBusInterfaceInfo *info, + const gchar *name, const gchar *object_path, + const gchar *interface_name, GCancellable *cancellable, + GError **error) { return (GDBusProxy *)GINT_TO_POINTER(0x1234); } GDBusProxy *g_dbus_proxy_new_sync(GDBusConnection *connection, - GDBusProxyFlags flags, GDBusInterfaceInfo *info, - const gchar *name, const gchar *object_path, - const gchar *interface_name, GCancellable *cancellable, - GError **error) + GDBusProxyFlags flags, GDBusInterfaceInfo *info, + const gchar *name, const gchar *object_path, + const gchar *interface_name, GCancellable *cancellable, + GError **error) { return (GDBusProxy *)GINT_TO_POINTER(0x5678); } guint g_dbus_connection_signal_subscribe(GDBusConnection *connection, - const gchar *sender, - const gchar *interface_name, - const gchar *member, - const gchar *object_path, - const gchar *arg0, - GDBusSignalFlags flags, - GDBusSignalCallback callback, - gpointer user_data, - GDestroyNotify user_data_free_func) + const gchar *sender, + const gchar *interface_name, + const gchar *member, + const gchar *object_path, + const gchar *arg0, + GDBusSignalFlags flags, + GDBusSignalCallback callback, + gpointer user_data, + GDestroyNotify user_data_free_func) { return _subscribe_signal(interface_name, member, callback, user_data); } @@ -63,12 +63,12 @@ void g_dbus_connection_signal_unsubscribe(GDBusConnection *connection, } GVariant *g_dbus_proxy_call_sync(GDBusProxy *proxy, - const gchar *method_name, - GVariant *parameters, - GDBusCallFlags flags, - gint timeout_msec, - GCancellable *cancellable, - GError **error) + const gchar *method_name, + GVariant *parameters, + GDBusCallFlags flags, + gint timeout_msec, + GCancellable *cancellable, + GError **error) { retv_if(proxy == nullptr, nullptr); @@ -81,6 +81,28 @@ GVariant *g_dbus_proxy_call_sync(GDBusProxy *proxy, return nullptr; } +void g_dbus_proxy_call(GDBusProxy *proxy, + const gchar *method_name, + GVariant *parameters, + GDBusCallFlags flags, + gint timeout_msec, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + ret_if(proxy == nullptr); + + if (proxy == GINT_TO_POINTER(0x1234)) + _handle_async_method(method_name, parameters, callback, user_data); +} + +GVariant *g_dbus_proxy_call_finish(GDBusProxy *proxy, + GAsyncResult *res, + GError **error) +{ + return _get_gdbus_async_result(error); +} + void g_object_unref(gpointer object) { } \ No newline at end of file diff --git a/tests/unittest/mocks/thread-mock-dummy.cpp b/tests/unittest/mocks/thread-mock-dummy.cpp index 717dcb4..4a3942b 100644 --- a/tests/unittest/mocks/thread-mock-dummy.cpp +++ b/tests/unittest/mocks/thread-mock-dummy.cpp @@ -16,8 +16,27 @@ #include "thread-private.h" #include "thread-dbus-handler.h" +#include "thread-mock-util.h" #include "thread-mock-dummy.h" +typedef struct { + GAsyncReadyCallback callback; + GVariant *result; + gpointer user_data; +} gdbus_result_data_s; + +static gdbus_result_data_s _gdbus_async_result; +static const int ASYNC_RESULT_DELAY = 5; + +static gboolean __reply_async_method(gpointer data) +{ + gdbus_result_data_s *gdbus_result = (gdbus_result_data_s *)data; + gdbus_result->callback((GObject *)g_object_new(G_TYPE_DBUS_PROXY, NULL), + NULL, + gdbus_result->user_data); + return FALSE; +} + static GVariant * __signal_properties_changed() { return nullptr; @@ -33,6 +52,49 @@ static GVariant *__method_factoryreset(GVariant *parameters) return g_variant_new("(i)", THREAD_ERROR_NONE); } +static GVariant *__make_scan_result() +{ + uint64_t ext_address = 0; + const char *network_name = "network_name"; + uint64_t ext_panid = 0; + uint16_t panid = 0; + uint16_t joiner_udp_port = 0; + uint8_t channel = 0; + uint8_t rssi = 0; + uint8_t lqi = 0; + uint8_t version = 0; + bool is_native = 0; + bool is_joinable = 0; + + GVariantBuilder *scan_results_builder = + g_variant_builder_new(G_VARIANT_TYPE("a(tstayqqyyyybb)")); + + GVariantBuilder *steering_data_builder = + g_variant_builder_new(G_VARIANT_TYPE("ay")); + g_variant_builder_add(steering_data_builder, "y", 1); + g_variant_builder_add(steering_data_builder, "y", '\0'); + + g_variant_builder_add(scan_results_builder, "(tstayqqyyyybb)", + ext_address, network_name, ext_panid, steering_data_builder, + panid, joiner_udp_port, channel, rssi, lqi, version, + is_native, is_joinable); + + GVariant *scan_results = g_variant_new("(a(tstayqqyyyybb))", scan_results_builder); + + g_variant_builder_unref(scan_results_builder); + + return scan_results; +} + +static void __method_scan(GVariant *parameters, + GAsyncReadyCallback callback, gpointer user_data) +{ + _gdbus_async_result.callback = callback; + _gdbus_async_result.result = __make_scan_result(); + _gdbus_async_result.user_data = user_data; + g_timeout_add(ASYNC_RESULT_DELAY, __reply_async_method, &_gdbus_async_result); +} + static GVariant *__property_device_role() { return g_variant_new("(v)", g_variant_new("s", "child")); @@ -73,19 +135,28 @@ struct { struct { const gchar *method_name; - GVariant *(*handler)(GVariant *parameters); + GVariant *(*sync_handler)(GVariant *parameters); + void(*async_handler)(GVariant *parameters, GAsyncReadyCallback callback, gpointer user_data); } thread_gdbus_method_list[] = { { THREAD_DBUS_RESET_METHOD, __method_reset, + NULL, }, { THREAD_DBUS_FACTORY_RESET_METHOD, __method_factoryreset, + NULL, + }, + { + THREAD_DBUS_SCAN_METHOD, + NULL, + __method_scan, }, { NULL, NULL, + NULL, } }; @@ -155,7 +226,20 @@ GVariant *_handle_sync_method(const gchar *method_name, return nullptr; if (__is_same_method(i, method_name)) - return thread_gdbus_method_list[i].handler(parameters); + return thread_gdbus_method_list[i].sync_handler(parameters); + } +} + +void _handle_async_method(const gchar *method_name, + GVariant *parameters, GAsyncReadyCallback callback, + gpointer user_data) +{ + for (int i = 0; ; ++i) { + if (thread_gdbus_method_list[i].method_name == NULL) + return; + + if (__is_same_method(i, method_name)) + return thread_gdbus_method_list[i].async_handler(parameters, callback, user_data); } } @@ -175,4 +259,10 @@ GVariant *_handle_property(const gchar *method_name, if (__is_same_property(i, method_name, property_name)) return thread_gdbus_property_list[i].handler(); } +} + +GVariant *_get_gdbus_async_result(GError **error) +{ + *error = nullptr; + return _gdbus_async_result.result; } \ No newline at end of file diff --git a/tests/unittest/mocks/thread-mock-dummy.h b/tests/unittest/mocks/thread-mock-dummy.h index 491a53e..8d2f35c 100644 --- a/tests/unittest/mocks/thread-mock-dummy.h +++ b/tests/unittest/mocks/thread-mock-dummy.h @@ -32,5 +32,11 @@ guint _subscribe_signal(const char *interface_name, GVariant *_handle_sync_method(const gchar *method_name, GVariant *parameters); +void _handle_async_method(const gchar *method_name, + GVariant *parameters, GAsyncReadyCallback callback, + gpointer user_data); + GVariant *_handle_property(const gchar *method_name, - GVariant *parameters); \ No newline at end of file + GVariant *parameters); + +GVariant *_get_gdbus_async_result(GError **error); \ No newline at end of file diff --git a/tests/unittest/mocks/thread-mock-util.cpp b/tests/unittest/mocks/thread-mock-util.cpp new file mode 100644 index 0000000..84d2aae --- /dev/null +++ b/tests/unittest/mocks/thread-mock-util.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "thread-mock-util.h" + +static gboolean _timeoutCallback(gpointer data) +{ + GMainLoop *mainLoop = NULL; + mainLoop = (GMainLoop *)data; + if (mainLoop != NULL) + g_main_loop_quit(mainLoop); + return FALSE; +} + +void ScanCallback(int result, thread_network_scanning_state_e state, + uint64_t ext_address, const char *network_name, uint64_t ext_panidi, + const uint8_t *steering_data, int length, uint16_t panid, uint16_t joiner_udp_port, uint16_t channel, + uint16_t rssi, uint8_t lqi, uint8_t version, bool is_native, bool is_joinable, void *user_data) +{ + if (state == THREAD_SCANNING_FINISHED) + QUIT_GMAIN_LOOP; +} + +void ThreadMainLoop::RunMainLoop() +{ + mainLoop = g_main_loop_new(NULL, false); + timeoutId = g_timeout_add(CALLBACK_TIMEOUT, _timeoutCallback, mainLoop); + g_main_loop_run(mainLoop); + if (timeoutId > 0) + g_source_remove(timeoutId); + mainLoop = NULL; +} + +void ThreadMainLoop::QuitMainLoop() +{ + if (mainLoop) + { + g_main_loop_quit(mainLoop); + mainLoop = NULL; + } +} \ No newline at end of file diff --git a/tests/unittest/mocks/thread-mock-util.h b/tests/unittest/mocks/thread-mock-util.h new file mode 100644 index 0000000..2f5fa08 --- /dev/null +++ b/tests/unittest/mocks/thread-mock-util.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include "thread-private.h" + +#define CALLBACK_TIMEOUT 10 +#define THREAD_MAIN_LOOP ThreadMainLoop::getInstance() +#define RUN_GMAIN_LOOP THREAD_MAIN_LOOP.RunMainLoop() +#define QUIT_GMAIN_LOOP THREAD_MAIN_LOOP.QuitMainLoop() + +void ScanCallback(int result, thread_network_scanning_state_e state, + uint64_t ext_address, const char *network_name, uint64_t ext_panidi, + const uint8_t *steering_data, int length, uint16_t panid, uint16_t joiner_udp_port, uint16_t channel, + uint16_t rssi, uint8_t lqi, uint8_t version, bool is_native, bool is_joinable, void *user_data); + +class ThreadMainLoop +{ +public: + static ThreadMainLoop& getInstance() + { + static ThreadMainLoop instance; + return instance; + } + + void RunMainLoop(); + void QuitMainLoop(); + +private: + ThreadMainLoop() {} + ~ThreadMainLoop() = default; + + ThreadMainLoop(const ThreadMainLoop&) = delete; + ThreadMainLoop& operator=(const ThreadMainLoop&) = delete; + +private: + GMainLoop *mainLoop; + guint timeoutId; +}; \ No newline at end of file diff --git a/tests/unittest/thread-unittest-core.cpp b/tests/unittest/thread-unittest-core.cpp index aa3bb37..d2b7ed6 100644 --- a/tests/unittest/thread-unittest-core.cpp +++ b/tests/unittest/thread-unittest-core.cpp @@ -17,10 +17,13 @@ #include #include "thread.h" +#include "mocks/thread-mock-util.h" class ThreadCoreTest : public ::testing::Test { public: + const int THREAD_DEFAULT_SCAN_TIME = 80; + thread_instance_h instance; thread_device_role_e deviceRole; thread_device_type_e deviceType; @@ -223,18 +226,21 @@ TEST_F(ThreadCoreTest, GetDeviceTypeErrorNone) TEST_F(ThreadCoreTest, ScanPramCreateNotInitialized) { EXPECT_EQ(THREAD_ERROR_NONE, thread_deinitialize()); - EXPECT_EQ(THREAD_ERROR_NOT_INITIALIZED, thread_scan_param_create(instance, 10, &scanParam)); + EXPECT_EQ(THREAD_ERROR_NOT_INITIALIZED, + thread_scan_param_create(instance, THREAD_DEFAULT_SCAN_TIME, &scanParam)); } TEST_F(ThreadCoreTest, ScanPramCreateInvalidParameter) { - EXPECT_EQ(THREAD_ERROR_INVALID_PARAMETER, thread_scan_param_create(instance, 10, &scanParam)); + EXPECT_EQ(THREAD_ERROR_INVALID_PARAMETER, + thread_scan_param_create(instance, THREAD_DEFAULT_SCAN_TIME, &scanParam)); } TEST_F(ThreadCoreTest, ScanPramCreateErrorNone) { EXPECT_EQ(THREAD_ERROR_NONE, thread_enable(&instance)); - EXPECT_EQ(THREAD_ERROR_NONE, thread_scan_param_create(instance, 10, &scanParam)); + EXPECT_EQ(THREAD_ERROR_NONE, + thread_scan_param_create(instance, THREAD_DEFAULT_SCAN_TIME, &scanParam)); } TEST_F(ThreadCoreTest, ScanPramDestroyNotInitialized) @@ -253,4 +259,28 @@ TEST_F(ThreadCoreTest, ScanPramDestroyErrorNone) EXPECT_EQ(THREAD_ERROR_NONE, thread_enable(&instance)); EXPECT_EQ(THREAD_ERROR_NONE, thread_scan_param_create(instance, 10, &scanParam)); EXPECT_EQ(THREAD_ERROR_NONE, thread_scan_param_destroy(instance, scanParam)); +} + +TEST_F(ThreadCoreTest, ScanNotInitialized) +{ + EXPECT_EQ(THREAD_ERROR_NONE, thread_deinitialize()); + EXPECT_EQ(THREAD_ERROR_NOT_INITIALIZED, + thread_scan(instance, scanParam, ScanCallback, nullptr)); +} + +TEST_F(ThreadCoreTest, ScanInvalidParameter) +{ + EXPECT_EQ(THREAD_ERROR_INVALID_PARAMETER, + thread_scan(instance, scanParam, ScanCallback, nullptr)); +} + +TEST_F(ThreadCoreTest, ScanErrorNone) +{ + EXPECT_EQ(THREAD_ERROR_NONE, thread_enable(&instance)); + EXPECT_EQ(THREAD_ERROR_NONE, + thread_scan_param_create(instance, THREAD_DEFAULT_SCAN_TIME, &scanParam)); + EXPECT_EQ(THREAD_ERROR_NONE, + thread_scan(instance, scanParam, ScanCallback, nullptr)); + + RUN_GMAIN_LOOP; } \ No newline at end of file -- 2.7.4