From dbed54664c983f86ff57999150d0d17475189a93 Mon Sep 17 00:00:00 2001 From: gichan2-jang Date: Fri, 30 Jun 2023 17:04:22 +0900 Subject: [PATCH] [Services] Remote model register - Impelent registering model relotely - Add unit test Signed-off-by: gichan2-jang --- c/src/ml-api-remote-service.c | 66 +++++++++- tests/capi/unittest_capi_remote_service.cc | 143 +++++++++++++++++++++ 2 files changed, 207 insertions(+), 2 deletions(-) diff --git a/c/src/ml-api-remote-service.c b/c/src/ml-api-remote-service.c index c81c31d5..8bfac446 100644 --- a/c/src/ml-api-remote-service.c +++ b/c/src/ml-api-remote-service.c @@ -165,6 +165,21 @@ _mlrs_get_service_type (gchar * service_str) return service_type; } +/** + * @brief Get ml remote service activation type. + */ +static gboolean +_mlrs_parse_activate (gchar * activate) +{ + gboolean ret = TRUE; + + if (activate && g_ascii_strcasecmp (activate, "false") == 0) { + ret = FALSE; + } + + return ret; +} + /** * @brief Process ml remote service */ @@ -185,10 +200,48 @@ _mlrs_process_remote_service (nns_edge_data_h data_h) switch (service_type) { case ML_REMOTE_SERVICE_TYPE_MODEL_URL: - /** @todo Download the model file from given URL */ + /** @todo Download the model file from given URL. wget? cURL? */ case ML_REMOTE_SERVICE_TYPE_MODEL_RAW: - /** @todo Save model file to given path and register the model */ + { + guint version = -1; + gchar *description = NULL; + gchar *name = NULL; + gchar *current_dir = g_get_current_dir (); + gchar *dir_path = NULL; + gchar *model_path = NULL; + gchar *activate = NULL; + gboolean active_bool = TRUE; + GError *error = NULL; + + nns_edge_data_get_info (data_h, "description", &description); + nns_edge_data_get_info (data_h, "name", &name); + nns_edge_data_get_info (data_h, "activate", &activate); + active_bool = _mlrs_parse_activate (activate); + _ml_logd ("current dir: %s, key: %s, model name:%s", current_dir, + service_key, name); + + dir_path = g_build_path ("/", current_dir, service_key, NULL); + g_mkdir_with_parents (dir_path, 0755); + model_path = g_build_path ("/", current_dir, service_key, name, NULL); + if (!g_file_set_contents (model_path, (char *) data, data_len, &error)) { + _ml_loge ("Failed to write data to file: %s", + error ? error->message : "unknown error"); + g_clear_error (&error); + } + + /** + * @todo Hashing the path. Where is the default path to save the model file? + */ + ml_service_model_register (service_key, model_path, + active_bool, description, &version); + g_free (current_dir); + g_free (dir_path); + g_free (activate); + g_free (model_path); + g_free (description); + g_free (name); break; + } case ML_REMOTE_SERVICE_TYPE_PIPELINE_URL: /** @todo Download the pipeline description from given URL */ case ML_REMOTE_SERVICE_TYPE_PIPELINE_RAW: @@ -346,6 +399,9 @@ ml_remote_service_register (ml_service_h handle, ml_option_h option, void *data, nns_edge_data_h data_h = NULL; int ret = NNS_EDGE_ERROR_NONE; gchar *service_str = NULL; + gchar *description = NULL; + gchar *name = NULL; + gchar *activate = NULL; check_feature_state (ML_FEATURE_SERVICE); check_feature_state (ML_FEATURE_INFERENCE); @@ -382,6 +438,12 @@ ml_remote_service_register (ml_service_h handle, ml_option_h option, void *data, nns_edge_data_set_info (data_h, "service-type", service_str); ml_option_get (option, "service-key", (void **) &service_key); nns_edge_data_set_info (data_h, "service-key", service_key); + ml_option_get (option, "description", (void **) &description); + nns_edge_data_set_info (data_h, "description", description); + ml_option_get (option, "name", (void **) &name); + nns_edge_data_set_info (data_h, "name", name); + ml_option_get (option, "activate", (void **) &activate); + nns_edge_data_set_info (data_h, "name", activate); ret = nns_edge_data_add (data_h, data, data_len, NULL); if (NNS_EDGE_ERROR_NONE != ret) { diff --git a/tests/capi/unittest_capi_remote_service.cc b/tests/capi/unittest_capi_remote_service.cc index 97554623..727c4e93 100644 --- a/tests/capi/unittest_capi_remote_service.cc +++ b/tests/capi/unittest_capi_remote_service.cc @@ -269,6 +269,149 @@ TEST_F (MLRemoteService, registerInvalidParam_n) EXPECT_EQ (ML_ERROR_NONE, status); } + +/** + * @brief use case of model registration using ml remote service. + */ +TEST_F (MLRemoteService, registerModel) +{ + int status; + + /**============= Prepare client ============= **/ + ml_service_h client_h; + ml_option_h client_option_h = NULL; + + status = ml_option_create (&client_option_h); + EXPECT_EQ (ML_ERROR_NONE, status); + + gchar *client_node_type = g_strdup ("remote_sender"); + status = ml_option_set (client_option_h, "node-type", client_node_type, g_free); + EXPECT_EQ (ML_ERROR_NONE, status); + + gchar *client_dest_host = g_strdup ("127.0.0.1"); + status = ml_option_set (client_option_h, "host", client_dest_host, g_free); + EXPECT_EQ (ML_ERROR_NONE, status); + + guint dest_port = 3000; + status = ml_option_set (client_option_h, "port", &dest_port, NULL); + EXPECT_EQ (ML_ERROR_NONE, status); + + gchar *client_connect_type = g_strdup ("TCP"); + status = ml_option_set (client_option_h, "connect-type", client_connect_type, g_free); + EXPECT_EQ (ML_ERROR_NONE, status); + + gchar *topic = g_strdup ("remote_service_test_topic"); + status = ml_option_set (client_option_h, "topic", topic, NULL); + EXPECT_EQ (ML_ERROR_NONE, status); + + status = ml_remote_service_create (client_option_h, &client_h); + EXPECT_EQ (ML_ERROR_NONE, status); + + /**============= Prepare server ============= **/ + ml_service_h server_h; + ml_option_h server_option_h = NULL; + status = ml_option_create (&server_option_h); + EXPECT_EQ (ML_ERROR_NONE, status); + + gchar *server_node_type = g_strdup ("remote_receiver"); + status = ml_option_set (server_option_h, "node-type", server_node_type, g_free); + + gchar *dest_host = g_strdup ("127.0.0.1"); + status = ml_option_set (server_option_h, "dest-host", dest_host, g_free); + EXPECT_EQ (ML_ERROR_NONE, status); + + status = ml_option_set (server_option_h, "topic", topic, g_free); + EXPECT_EQ (ML_ERROR_NONE, status); + + status = ml_option_set (server_option_h, "dest-port", &dest_port, NULL); + EXPECT_EQ (ML_ERROR_NONE, status); + + gchar *server_connect_type = g_strdup ("TCP"); + status = ml_option_set (server_option_h, "connect-type", server_connect_type, g_free); + EXPECT_EQ (ML_ERROR_NONE, status); + + status = ml_remote_service_create (server_option_h, &server_h); + EXPECT_EQ (ML_ERROR_NONE, status); + + /** Set service option */ + const gchar *root_path = g_getenv ("MLAPI_SOURCE_ROOT_PATH"); + /* ml_remote_service_register () requires absolute path to model, ignore this case. */ + if (root_path == NULL) + return; + + gchar *test_model = g_build_filename (root_path, "tests", "test_models", + "models", "mobilenet_v1_1.0_224_quant.tflite", NULL); + EXPECT_TRUE (g_file_test (test_model, G_FILE_TEST_EXISTS)); + + gchar *contents = NULL; + gsize len = 0; + EXPECT_TRUE (g_file_get_contents (test_model, &contents, &len, NULL)); + g_message ("Model size: %zu", len); + + ml_option_h remote_service_option_h = NULL; + status = ml_option_create (&remote_service_option_h); + EXPECT_EQ (ML_ERROR_NONE, status); + + gchar *service_key = g_strdup ("model_registration_test_key"); + ml_option_set (remote_service_option_h, "service-key", service_key, g_free); + + gchar *service_type = g_strdup ("model_raw"); + ml_option_set (remote_service_option_h, "service-type", service_type, g_free); + + gchar *activate = g_strdup ("true"); + ml_option_set (remote_service_option_h, "activate", activate, g_free); + + gchar *description = g_strdup ("temp descriptio for remote model register test"); + ml_option_set (remote_service_option_h, "description", description, g_free); + + gchar *name = g_strdup ("mobilenet_v1_1.0_224_quant.tflite"); + ml_option_set (remote_service_option_h, "name", name, g_free); + + status = ml_remote_service_register (client_h, remote_service_option_h, contents, len); + EXPECT_EQ (ML_ERROR_NONE, status); + + /** Wait for the server to register the pipeline. */ + g_usleep (1000000); + + // Get model file + ml_option_h activated_model_option_h; + status = ml_service_model_get_activated (service_key, &activated_model_option_h); + EXPECT_EQ (ML_ERROR_NONE, status); + EXPECT_NE (activated_model_option_h, nullptr); + + gchar *activated_model_path; + status = ml_option_get (activated_model_option_h, "path", (void **) &activated_model_path); + EXPECT_EQ (ML_ERROR_NONE, status); + g_message ("Activated model path: %s", activated_model_path); + + gchar *activated_model_contents = NULL; + gsize activated_model_len = 0; + EXPECT_TRUE (g_file_get_contents (activated_model_path, + &activated_model_contents, &activated_model_len, NULL)); + g_message ("Model size: %zu", activated_model_len); + g_usleep (1000000); + EXPECT_EQ (len, activated_model_len); + EXPECT_EQ (memcmp (contents, activated_model_contents, len), 0); + g_message ("Compare done"); + g_usleep (1000000); + + g_free (contents); + g_free (test_model); + g_free (activated_model_contents); + status = ml_service_destroy (server_h); + EXPECT_EQ (ML_ERROR_NONE, status); + status = ml_service_destroy (client_h); + EXPECT_EQ (ML_ERROR_NONE, status); + status = ml_option_destroy (server_option_h); + EXPECT_EQ (ML_ERROR_NONE, status); + status = ml_option_destroy (remote_service_option_h); + EXPECT_EQ (ML_ERROR_NONE, status); + status = ml_option_destroy (client_option_h); + EXPECT_EQ (ML_ERROR_NONE, status); + status = ml_option_destroy (activated_model_option_h); + EXPECT_EQ (ML_ERROR_NONE, status); +} + /** * @brief Main gtest */