diff --git a/.vscode/launch.json b/.vscode/launch.json index e527dc6011..9ddd1686ce 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -137,7 +137,7 @@ "request": "launch", "program": "${workspaceFolder}/out/linux/x64/tests/standalone/ten_runtime_smoke_test", "args": [ - "--gtest_filter=AudioFrameTest.MultiDestAudioFrame" + "--gtest_filter=ExtensionTest.ExtensionSendMsgToIncorrectEngine" ], "cwd": "${workspaceFolder}/out/linux/x64/tests/standalone/", "env": { diff --git a/core/include/ten_utils/lib/string.h b/core/include/ten_utils/lib/string.h index f45f722ac0..276e38a3db 100644 --- a/core/include/ten_utils/lib/string.h +++ b/core/include/ten_utils/lib/string.h @@ -69,8 +69,10 @@ inline bool ten_string_check_integrity(const ten_string_t *self) { */ TEN_UTILS_API ten_string_t *ten_string_create(void); -TEN_UTILS_API ten_string_t *ten_string_create_from_c_str(const char *str, - size_t size); +TEN_UTILS_API ten_string_t *ten_string_create_from_c_str_with_size( + const char *str, size_t size); + +TEN_UTILS_API ten_string_t *ten_string_create_from_c_str(const char *str); /** * @brief Create a string object from c string. @@ -177,8 +179,12 @@ TEN_UTILS_API void ten_string_prepend_from_va_list(ten_string_t *self, TEN_UTILS_API void ten_string_set_formatted(ten_string_t *self, const char *fmt, ...); +TEN_UTILS_API void ten_string_set_from_c_str_with_size(ten_string_t *self, + const char *str, + size_t size); + TEN_UTILS_API void ten_string_set_from_c_str(ten_string_t *self, - const char *str, size_t size); + const char *str); /** * @brief Check if the string object is empty. diff --git a/core/include_internal/ten_runtime/app/predefined_graph.h b/core/include_internal/ten_runtime/app/predefined_graph.h index eb87acffdc..54db4fd3db 100644 --- a/core/include_internal/ten_runtime/app/predefined_graph.h +++ b/core/include_internal/ten_runtime/app/predefined_graph.h @@ -31,6 +31,14 @@ typedef struct ten_predefined_graph_info_t { // name is the same as the graph ID of that instance. Therefore, the 'engine' // field is only meaningful when the 'singleton' field is set to true. ten_engine_t *engine; + + // Used to record the cmd ID of the `start_graph` command when the app + // launches the `auto_start` predefined graph. After the app receives the + // command result, this information is used to verify whether the received + // command result corresponds to a previously sent `start_graph` command. If + // it does, and the start graph operation fails, the app will proactively + // close itself. + ten_string_t start_graph_cmd_id; } ten_predefined_graph_info_t; TEN_RUNTIME_PRIVATE_API ten_predefined_graph_info_t * diff --git a/core/src/ten_runtime/addon/addon_host.c b/core/src/ten_runtime/addon/addon_host.c index e64fd5ef76..9a540fc11d 100644 --- a/core/src/ten_runtime/addon/addon_host.c +++ b/core/src/ten_runtime/addon/addon_host.c @@ -123,7 +123,7 @@ void ten_addon_host_find_and_set_base_dir(ten_addon_host_t *self, // If the addon's base dir cannot be found by searching upward through the // parent folders, simply trust the passed-in parameter as the addon’s base // dir. - ten_string_set_from_c_str(&self->base_dir, start_path, strlen(start_path)); + ten_string_set_from_c_str(&self->base_dir, start_path); } } diff --git a/core/src/ten_runtime/addon/ten_env/on_xxx.c b/core/src/ten_runtime/addon/ten_env/on_xxx.c index 2eeff1c5a1..9ad917f19f 100644 --- a/core/src/ten_runtime/addon/ten_env/on_xxx.c +++ b/core/src/ten_runtime/addon/ten_env/on_xxx.c @@ -92,8 +92,7 @@ void ten_addon_on_init_done(ten_env_t *self) { // runtime would use that name instead of the name specified in the codes to // register it to the extension store. if (strlen(manifest_name)) { - ten_string_set_from_c_str(&addon_host->name, manifest_name, - strlen(manifest_name)); + ten_string_set_from_c_str(&addon_host->name, manifest_name); } } } diff --git a/core/src/ten_runtime/app/metadata.c b/core/src/ten_runtime/app/metadata.c index f4dd063fab..6189e2ce5a 100644 --- a/core/src/ten_runtime/app/metadata.c +++ b/core/src/ten_runtime/app/metadata.c @@ -92,7 +92,7 @@ bool ten_app_init_uri(ten_app_t *self, ten_value_t *value) { ? ten_value_peek_raw_str(value, NULL) : ten_string_get_raw_str(&default_url); - ten_string_set_from_c_str(&self->uri, url_str, strlen(url_str)); + ten_string_set_from_c_str(&self->uri, url_str); ten_string_deinit(&default_url); diff --git a/core/src/ten_runtime/app/msg_interface/common.c b/core/src/ten_runtime/app/msg_interface/common.c index a5ee826ee0..35a760f75b 100644 --- a/core/src/ten_runtime/app/msg_interface/common.c +++ b/core/src/ten_runtime/app/msg_interface/common.c @@ -22,6 +22,8 @@ #include "include_internal/ten_runtime/msg/msg.h" #include "include_internal/ten_runtime/protocol/protocol.h" #include "ten_runtime/app/app.h" +#include "ten_runtime/common/status_code.h" +#include "ten_runtime/msg/cmd/close_app/cmd.h" #include "ten_runtime/msg/cmd/stop_graph/cmd.h" #include "ten_runtime/msg/cmd_result/cmd_result.h" #include "ten_runtime/msg/msg.h" @@ -274,6 +276,43 @@ static bool ten_app_handle_stop_graph_cmd(ten_app_t *self, return true; } +/** + * @return true if this function handles @param cmd, false otherwise. + */ +static bool ten_app_handle_cmd_result(ten_app_t *self, ten_shared_ptr_t *cmd, + ten_error_t *err) { + TEN_ASSERT(self && ten_app_check_integrity(self, true), "Should not happen."); + TEN_ASSERT(cmd && ten_cmd_base_check_integrity(cmd), "Should not happen."); + + TEN_STATUS_CODE status_code = ten_cmd_result_get_status_code(cmd); + bool is_auto_start_predefined_graph_cmd_result = false; + + // Verify whether the received command result corresponds to a previously sent + // `start_graph` command for the `auto_start` predefined graph. + ten_list_foreach (&self->predefined_graph_infos, iter) { + ten_predefined_graph_info_t *predefined_graph_info = + (ten_predefined_graph_info_t *)ten_ptr_listnode_get(iter.node); + + if (ten_string_is_equal_c_str(&predefined_graph_info->start_graph_cmd_id, + ten_cmd_base_get_cmd_id(cmd))) { + TEN_ASSERT(predefined_graph_info->auto_start, "Should not happen."); + is_auto_start_predefined_graph_cmd_result = true; + } + } + + if (is_auto_start_predefined_graph_cmd_result && + status_code == TEN_STATUS_CODE_ERROR) { + // If auto-starting the predefined graph fails, gracefully close the app. + ten_shared_ptr_t *close_app_cmd = ten_cmd_close_app_create(); + ten_msg_clear_and_set_dest(close_app_cmd, + ten_string_get_raw_str(&self->uri), NULL, NULL, + NULL, err); + ten_env_send_cmd(self->ten_env, close_app_cmd, NULL, NULL, err); + } + + return is_auto_start_predefined_graph_cmd_result; +} + bool ten_app_dispatch_msg(ten_app_t *self, ten_shared_ptr_t *msg, ten_error_t *err) { // The source of the out message is the current app. @@ -333,6 +372,11 @@ bool ten_app_handle_in_msg(ten_app_t *self, ten_connection_t *connection, case TEN_MSG_TYPE_CMD_STOP_GRAPH: return ten_app_handle_stop_graph_cmd(self, msg, err); + case TEN_MSG_TYPE_CMD_RESULT: + if (!ten_app_handle_cmd_result(self, msg, err)) { + return ten_app_handle_msg_default_handler(self, connection, msg, err); + } + default: return ten_app_handle_msg_default_handler(self, connection, msg, err); } diff --git a/core/src/ten_runtime/app/predefined_graph.c b/core/src/ten_runtime/app/predefined_graph.c index 00a548d483..84883faf9a 100644 --- a/core/src/ten_runtime/app/predefined_graph.c +++ b/core/src/ten_runtime/app/predefined_graph.c @@ -20,6 +20,7 @@ #include "include_internal/ten_runtime/extension_group/extension_group_info/json.h" #include "include_internal/ten_runtime/extension_group/extension_group_info/value.h" #include "include_internal/ten_runtime/msg/cmd_base/cmd/start_graph/cmd.h" +#include "include_internal/ten_runtime/msg/cmd_base/cmd_base.h" #include "include_internal/ten_runtime/msg/msg.h" #include "ten_runtime/msg/cmd/start_graph/cmd.h" #include "ten_runtime/msg/msg.h" @@ -46,6 +47,7 @@ ten_predefined_graph_info_t *ten_predefined_graph_info_create(void) { self->auto_start = false; self->singleton = false; self->engine = NULL; + ten_string_init(&self->start_graph_cmd_id); return self; } @@ -56,6 +58,7 @@ void ten_predefined_graph_info_destroy(ten_predefined_graph_info_t *self) { ten_string_deinit(&self->name); ten_list_clear(&self->extensions_info); ten_list_clear(&self->extension_groups_info); + ten_string_deinit(&self->start_graph_cmd_id); TEN_FREE(self); } @@ -174,6 +177,18 @@ bool ten_app_start_predefined_graph( ten_msg_set_src_to_app(start_graph_cmd, self); + // @{ + // Since the app needs to record the `start_graph` command ID for the + // `auto_start` predefined graph, so that it can later identify if the + // received command result corresponds to this type of `start_graph` command, + // it is necessary to assign the command ID here and record it. + if (predefined_graph_info->auto_start) { + ten_cmd_base_gen_cmd_id_if_empty(start_graph_cmd); + ten_string_set_from_c_str(&predefined_graph_info->start_graph_cmd_id, + ten_cmd_base_get_cmd_id(start_graph_cmd)); + } + // @} + predefined_graph_info->engine = ten_app_create_engine(self, start_graph_cmd); // There is no 'connection' when creating predefined graph, so it's always no @@ -351,8 +366,7 @@ bool ten_app_get_predefined_graphs_from_property(ten_app_t *self) { } ten_string_set_from_c_str( &predefined_graph_info->name, - ten_value_peek_raw_str(predefined_graph_info_name_value, &err), - strlen(ten_value_peek_raw_str(predefined_graph_info_name_value, &err))); + ten_value_peek_raw_str(predefined_graph_info_name_value, &err)); ten_value_t *predefined_graph_info_auto_start_value = ten_value_object_peek(predefined_graph_info_value, TEN_STR_AUTO_START); diff --git a/core/src/ten_runtime/app/ten_env/on_xxx.c b/core/src/ten_runtime/app/ten_env/on_xxx.c index 3542739ed5..4ac287e853 100644 --- a/core/src/ten_runtime/app/ten_env/on_xxx.c +++ b/core/src/ten_runtime/app/ten_env/on_xxx.c @@ -185,10 +185,8 @@ void ten_app_on_configure_done(ten_env_t *ten_env) { ten_app_adjust_and_validate_property_on_configure_done(self); if (ten_string_is_empty(&self->uri)) { - ten_string_set_from_c_str(&self->uri, TEN_STR_LOCALHOST, - strlen(TEN_STR_LOCALHOST)); + ten_string_set_from_c_str(&self->uri, TEN_STR_LOCALHOST); } - ten_addon_load_all_from_app_base_dir(ten_string_get_raw_str(&self->base_dir), &err); ten_addon_load_all_from_ten_package_base_dirs(&self->ten_package_base_dirs, diff --git a/core/src/ten_runtime/common/loc.c b/core/src/ten_runtime/common/loc.c index f475a138ac..1ba7c76d02 100644 --- a/core/src/ten_runtime/common/loc.c +++ b/core/src/ten_runtime/common/loc.c @@ -354,7 +354,7 @@ void ten_loc_set_from_value(ten_loc_t *self, ten_value_t *value) { const char *app_str = ten_value_peek_raw_str(app_value, NULL); if (app_str && strlen(app_str) > 0) { - ten_string_set_from_c_str(&self->app_uri, app_str, strlen(app_str)); + ten_string_set_from_c_str(&self->app_uri, app_str); } } @@ -363,7 +363,7 @@ void ten_loc_set_from_value(ten_loc_t *self, ten_value_t *value) { const char *graph_str = ten_value_peek_raw_str(graph_value, NULL); if (graph_str && strlen(graph_str) > 0) { - ten_string_set_from_c_str(&self->graph_id, graph_str, strlen(graph_str)); + ten_string_set_from_c_str(&self->graph_id, graph_str); } } @@ -374,8 +374,7 @@ void ten_loc_set_from_value(ten_loc_t *self, ten_value_t *value) { const char *group_name_str = ten_value_peek_raw_str(extension_group_value, NULL); if (group_name_str && strlen(group_name_str) > 0) { - ten_string_set_from_c_str(&self->extension_group_name, group_name_str, - strlen(group_name_str)); + ten_string_set_from_c_str(&self->extension_group_name, group_name_str); } } @@ -385,8 +384,7 @@ void ten_loc_set_from_value(ten_loc_t *self, ten_value_t *value) { const char *extension_name_str = ten_value_peek_raw_str(extension_value, NULL); if (extension_name_str && strlen(extension_name_str) > 0) { - ten_string_set_from_c_str(&self->extension_name, extension_name_str, - strlen(extension_name_str)); + ten_string_set_from_c_str(&self->extension_name, extension_name_str); } } } diff --git a/core/src/ten_runtime/metadata/manifest.c b/core/src/ten_runtime/metadata/manifest.c index d17d1fcd07..cda0722aa2 100644 --- a/core/src/ten_runtime/metadata/manifest.c +++ b/core/src/ten_runtime/metadata/manifest.c @@ -40,7 +40,7 @@ bool ten_manifest_get_type_and_name(const char *filename, TEN_ADDON_TYPE *type, *type = ten_addon_type_from_string(type_str); const char *name_str = ten_json_object_peek_string(json, TEN_STR_NAME); - ten_string_set_from_c_str(name, name_str, strlen(name_str)); + ten_string_set_from_c_str(name, name_str); ten_json_destroy(json); diff --git a/core/src/ten_runtime/metadata/metadata_info.c b/core/src/ten_runtime/metadata/metadata_info.c index 34f4778a4e..e4ab2f0ecc 100644 --- a/core/src/ten_runtime/metadata/metadata_info.c +++ b/core/src/ten_runtime/metadata/metadata_info.c @@ -99,7 +99,7 @@ static ten_string_t *ten_metadata_info_filename_to_absolute_path( const char *base_dir = ten_app_get_base_dir(ten_env_get_attached_app(self->belonging_to)); if (base_dir) { - path = ten_string_create_from_c_str(base_dir, strlen(base_dir)); + path = ten_string_create_from_c_str(base_dir); } break; } @@ -108,7 +108,7 @@ static ten_string_t *ten_metadata_info_filename_to_absolute_path( const char *base_dir = ten_extension_group_get_base_dir( ten_env_get_attached_extension_group(self->belonging_to)); if (base_dir) { - path = ten_string_create_from_c_str(base_dir, strlen(base_dir)); + path = ten_string_create_from_c_str(base_dir); } break; } @@ -117,7 +117,7 @@ static ten_string_t *ten_metadata_info_filename_to_absolute_path( const char *base_dir = ten_extension_get_base_dir( ten_env_get_attached_extension(self->belonging_to)); if (base_dir) { - path = ten_string_create_from_c_str(base_dir, strlen(base_dir)); + path = ten_string_create_from_c_str(base_dir); } break; } @@ -126,7 +126,7 @@ static ten_string_t *ten_metadata_info_filename_to_absolute_path( const char *base_dir = ten_addon_host_get_base_dir( ten_env_get_attached_addon(self->belonging_to)); if (base_dir) { - path = ten_string_create_from_c_str(base_dir, strlen(base_dir)); + path = ten_string_create_from_c_str(base_dir); } break; } diff --git a/core/src/ten_runtime/msg/cmd_base/cmd_result/cmd.c b/core/src/ten_runtime/msg/cmd_base/cmd_result/cmd.c index 7d4021de9e..47be644605 100644 --- a/core/src/ten_runtime/msg/cmd_base/cmd_result/cmd.c +++ b/core/src/ten_runtime/msg/cmd_base/cmd_result/cmd.c @@ -403,7 +403,7 @@ static void ten_raw_cmd_result_set_original_cmd_name( "Invalid argument."); ten_string_set_from_c_str(ten_value_peek_string(&self->original_cmd_name), - original_cmd_name, strlen(original_cmd_name)); + original_cmd_name); } void ten_cmd_result_set_original_cmd_name(ten_shared_ptr_t *self, diff --git a/core/src/ten_runtime/msg/msg.c b/core/src/ten_runtime/msg/msg.c index 26fdd88fd4..19d9f9fa81 100644 --- a/core/src/ten_runtime/msg/msg.c +++ b/core/src/ten_runtime/msg/msg.c @@ -926,7 +926,7 @@ void ten_msg_correct_dest(ten_shared_ptr_t *msg, ten_engine_t *engine) { // 'correct' the real destination location from 'localhost' to the real // URI of the app. - ten_string_set_from_c_str(&dest_loc->app_uri, app_uri, strlen(app_uri)); + ten_string_set_from_c_str(&dest_loc->app_uri, app_uri); is_local_app = true; } diff --git a/core/src/ten_utils/lib/sys/general/string.c b/core/src/ten_utils/lib/sys/general/string.c index 642002f0f2..36fec010cf 100644 --- a/core/src/ten_utils/lib/sys/general/string.c +++ b/core/src/ten_utils/lib/sys/general/string.c @@ -30,11 +30,21 @@ ten_string_t *ten_string_create(void) { return self; } -ten_string_t *ten_string_create_from_c_str(const char *str, size_t size) { +ten_string_t *ten_string_create_from_c_str_with_size(const char *str, + size_t size) { TEN_ASSERT(str, "Invalid argument."); ten_string_t *result = ten_string_create(); - ten_string_set_from_c_str(result, str, size); + ten_string_set_from_c_str_with_size(result, str, size); + + return result; +} + +ten_string_t *ten_string_create_from_c_str(const char *str) { + TEN_ASSERT(str, "Invalid argument."); + + ten_string_t *result = ten_string_create(); + ten_string_set_from_c_str(result, str); return result; } @@ -164,8 +174,8 @@ void ten_string_init_from_c_str(ten_string_t *self, const char *str, ten_string_set_formatted(self, "%.*s", size, str); } -void ten_string_set_from_c_str(ten_string_t *self, const char *str, - size_t size) { +void ten_string_set_from_c_str_with_size(ten_string_t *self, const char *str, + size_t size) { TEN_ASSERT(self && ten_string_check_integrity(self) && str, "Invalid argument."); TEN_ASSERT(size, "Invalid argument."); @@ -173,6 +183,13 @@ void ten_string_set_from_c_str(ten_string_t *self, const char *str, ten_string_set_formatted(self, "%.*s", size, str); } +void ten_string_set_from_c_str(ten_string_t *self, const char *str) { + TEN_ASSERT(self && ten_string_check_integrity(self) && str, + "Invalid argument."); + + ten_string_set_formatted(self, "%s", str); +} + void ten_string_set_formatted(ten_string_t *self, const char *fmt, ...) { TEN_ASSERT(self && ten_string_check_integrity(self), "Invalid argument."); diff --git a/core/src/ten_utils/lib/sys/posix/path.c b/core/src/ten_utils/lib/sys/posix/path.c index 7eeec37df5..bc14d8b0e3 100644 --- a/core/src/ten_utils/lib/sys/posix/path.c +++ b/core/src/ten_utils/lib/sys/posix/path.c @@ -237,7 +237,7 @@ ten_dir_fd_t *ten_path_open_dir(const char *path) { dir->itor.entry = NULL; dir->itor.dir = dir; - dir->path = ten_string_create_from_c_str(path, strlen(path)); + dir->path = ten_string_create_from_c_str(path); return dir; } diff --git a/core/src/ten_utils/lib/sys/win/path.c b/core/src/ten_utils/lib/sys/win/path.c index a66856c783..97765c73f3 100644 --- a/core/src/ten_utils/lib/sys/win/path.c +++ b/core/src/ten_utils/lib/sys/win/path.c @@ -288,7 +288,7 @@ ten_dir_fd_t *ten_path_open_dir(const char *path) { goto error; } - dir->path = ten_string_create_from_c_str(path, strlen(path)); + dir->path = ten_string_create_from_c_str(path); dir->itor.dir = dir; return dir; diff --git a/tests/ten_runtime/smoke/predefined_graph/predefined_graph_incorrect_1.cc b/tests/ten_runtime/smoke/predefined_graph/predefined_graph_incorrect_1.cc index b0df5a59c6..229540f53b 100644 --- a/tests/ten_runtime/smoke/predefined_graph/predefined_graph_incorrect_1.cc +++ b/tests/ten_runtime/smoke/predefined_graph/predefined_graph_incorrect_1.cc @@ -6,7 +6,6 @@ // #include "gtest/gtest.h" #include "include_internal/ten_runtime/binding/cpp/ten.h" -#include "tests/common/client/cpp/msgpack_tcp.h" #include "tests/ten_runtime/smoke/util/binding/cpp/check.h" namespace { @@ -53,7 +52,7 @@ class test_app : public ten::app_t { "nodes": [{ "type": "extension", "name": "predefined_graph", - "addon": "predefined_graph_incorrect_1__predefined_graph", + "addon": "incorrect_addon", "extension_group": "predefined_graph_group" }] }] @@ -83,20 +82,5 @@ TEN_CPP_REGISTER_ADDON_AS_EXTENSION( TEST(PredefinedGraphTest, PredefinedGraphIncorrect1) { // NOLINT auto *app_thread = ten_thread_create("app thread", app_thread_main, nullptr); - // Create a client and connect to the app. - auto *client = new ten::msgpack_tcp_client_t("msgpack://127.0.0.1:8001/"); - - // Do not need to send 'start_graph' command first. - // The 'graph_id' MUST be "default" if we want to send the request to - // predefined graph. - auto test_cmd = ten::cmd_t::create("test"); - test_cmd->set_dest("msgpack://127.0.0.1:8001/", "default", - "predefined_graph_group", "predefined_graph"); - auto cmd_result = client->send_cmd_and_recv_result(std::move(test_cmd)); - ten_test::check_status_code(cmd_result, TEN_STATUS_CODE_OK); - ten_test::check_detail_with_json(cmd_result, R"({"id": 1, "name": "a"})"); - - delete client; - ten_thread_join(app_thread, -1); } diff --git a/tests/ten_runtime/smoke/predefined_graph/predefined_graph_incorrect_2.cc b/tests/ten_runtime/smoke/predefined_graph/predefined_graph_incorrect_2.cc new file mode 100644 index 0000000000..8785838c8b --- /dev/null +++ b/tests/ten_runtime/smoke/predefined_graph/predefined_graph_incorrect_2.cc @@ -0,0 +1,91 @@ +// +// Copyright © 2025 Agora +// This file is part of TEN Framework, an open source project. +// Licensed under the Apache License, Version 2.0, with certain conditions. +// Refer to the "LICENSE" file in the root directory for more information. +// +#include "gtest/gtest.h" +#include "include_internal/ten_runtime/binding/cpp/ten.h" +#include "tests/ten_runtime/smoke/util/binding/cpp/check.h" + +namespace { + +class test_predefined_graph : public ten::extension_t { + public: + explicit test_predefined_graph(const char *name) : ten::extension_t(name) {} + + void on_cmd(ten::ten_env_t &ten_env, + std::unique_ptr cmd) override { + nlohmann::json const detail = {{"id", 1}, {"name", "a"}}; + + auto cmd_result = ten::cmd_result_t::create(TEN_STATUS_CODE_OK); + cmd_result->set_property_from_json("detail", detail.dump().c_str()); + ten_env.return_result(std::move(cmd_result), std::move(cmd)); + } +}; + +class test_app : public ten::app_t { + public: + void on_configure(ten::ten_env_t &ten_env) override { + bool rc = ten::ten_env_internal_accessor_t::init_manifest_from_json( + ten_env, + // clang-format off + R"({ + "type": "app", + "name": "test_app", + "version": "0.1.0" + })" + // clang-format on + ); + ASSERT_EQ(rc, true); + + rc = ten_env.init_property_from_json( + // clang-format off + R"###({ + "_ten": { + "uri": "msgpack://127.0.0.1:8001/", + "log_level": 2, + "predefined_graphs": [{ + "name": "default", + "auto_start": true, + "singleton": true, + "nodes": [{ + "type": "extension", + "name": "predefined_graph", + "addon": "incorrect_addon", + "extension_group": "predefined_graph_group" + },{ + "type": "extension", + "name": "predefined_graph", + "addon": "predefined_graph_incorrect_2__predefined_graph", + "extension_group": "predefined_graph_group" + }] + }] + } + })###" + // clang-format on + ); + ASSERT_EQ(rc, true); + + ten_env.on_configure_done(); + } +}; + +void *app_thread_main(TEN_UNUSED void *args) { + auto *app = new test_app(); + app->run(); + delete app; + + return nullptr; +} + +TEN_CPP_REGISTER_ADDON_AS_EXTENSION( + predefined_graph_incorrect_2__predefined_graph, test_predefined_graph); + +} // namespace + +TEST(PredefinedGraphTest, PredefinedGraphIncorrect2) { // NOLINT + auto *app_thread = ten_thread_create("app thread", app_thread_main, nullptr); + + ten_thread_join(app_thread, -1); +} diff --git a/tests/ten_runtime/smoke/predefined_graph/predefined_graph_incorrect_3.cc b/tests/ten_runtime/smoke/predefined_graph/predefined_graph_incorrect_3.cc new file mode 100644 index 0000000000..d08851e9ce --- /dev/null +++ b/tests/ten_runtime/smoke/predefined_graph/predefined_graph_incorrect_3.cc @@ -0,0 +1,91 @@ +// +// Copyright © 2025 Agora +// This file is part of TEN Framework, an open source project. +// Licensed under the Apache License, Version 2.0, with certain conditions. +// Refer to the "LICENSE" file in the root directory for more information. +// +#include "gtest/gtest.h" +#include "include_internal/ten_runtime/binding/cpp/ten.h" +#include "tests/ten_runtime/smoke/util/binding/cpp/check.h" + +namespace { + +class test_predefined_graph : public ten::extension_t { + public: + explicit test_predefined_graph(const char *name) : ten::extension_t(name) {} + + void on_cmd(ten::ten_env_t &ten_env, + std::unique_ptr cmd) override { + nlohmann::json const detail = {{"id", 1}, {"name", "a"}}; + + auto cmd_result = ten::cmd_result_t::create(TEN_STATUS_CODE_OK); + cmd_result->set_property_from_json("detail", detail.dump().c_str()); + ten_env.return_result(std::move(cmd_result), std::move(cmd)); + } +}; + +class test_app : public ten::app_t { + public: + void on_configure(ten::ten_env_t &ten_env) override { + bool rc = ten::ten_env_internal_accessor_t::init_manifest_from_json( + ten_env, + // clang-format off + R"({ + "type": "app", + "name": "test_app", + "version": "0.1.0" + })" + // clang-format on + ); + ASSERT_EQ(rc, true); + + rc = ten_env.init_property_from_json( + // clang-format off + R"###({ + "_ten": { + "uri": "msgpack://127.0.0.1:8001/", + "log_level": 2, + "predefined_graphs": [{ + "name": "default", + "auto_start": true, + "singleton": true, + "nodes": [{ + "type": "extension", + "name": "incorrect_extension", + "addon": "incorrect_addon", + "extension_group": "predefined_graph_group" + },{ + "type": "extension", + "name": "normal_extension", + "addon": "predefined_graph_incorrect_3__predefined_graph", + "extension_group": "predefined_graph_group" + }] + }] + } + })###" + // clang-format on + ); + ASSERT_EQ(rc, true); + + ten_env.on_configure_done(); + } +}; + +void *app_thread_main(TEN_UNUSED void *args) { + auto *app = new test_app(); + app->run(); + delete app; + + return nullptr; +} + +TEN_CPP_REGISTER_ADDON_AS_EXTENSION( + predefined_graph_incorrect_3__predefined_graph, test_predefined_graph); + +} // namespace + +TEST(PredefinedGraphTest, PredefinedGraphIncorrect3) { // NOLINT + auto *app_thread = ten_thread_create("app thread", app_thread_main, nullptr); + + ten_thread_join(app_thread, -1); +}