Skip to content

Commit

Permalink
feat: provide a way to set property during testing (#395)
Browse files Browse the repository at this point in the history
* fix: make tester init_test_app_property_from_json internal

* feat: support set property for single extension testing

* feat: add more python standalone test case

* fix: refine codes

* fix: refine codes

---------

Co-authored-by: Hu Yueh-Wei <[email protected]>
  • Loading branch information
sunxilin and halajohn authored Dec 13, 2024
1 parent 1b9c6c7 commit f395b74
Show file tree
Hide file tree
Showing 17 changed files with 238 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

namespace ten {

class extension_tester_internal_accessor_t;

class extension_tester_t {
public:
virtual ~extension_tester_t() {
Expand All @@ -36,9 +38,11 @@ class extension_tester_t {
extension_tester_t &operator=(const extension_tester_t &&) = delete;
// @}

void set_test_mode_single(const char *addon_name) {
void set_test_mode_single(const char *addon_name,
const char *property_json_str = nullptr) {
TEN_ASSERT(addon_name, "Invalid argument.");
ten_extension_tester_set_test_mode_single(c_extension_tester, addon_name);
ten_extension_tester_set_test_mode_single(c_extension_tester, addon_name,
property_json_str);
}

void set_test_mode_graph(const char *graph_json) {
Expand All @@ -51,12 +55,6 @@ class extension_tester_t {
ten_extension_tester_add_addon_base_dir(c_extension_tester, addon_path);
}

void init_test_app_property_from_json(const char *property_json_str) {
TEN_ASSERT(property_json_str, "Invalid argument.");
ten_extension_tester_init_test_app_property_from_json(c_extension_tester,
property_json_str);
}

bool run(error_t *err = nullptr) {
TEN_ASSERT(c_extension_tester, "Should not happen.");
return ten_extension_tester_run(c_extension_tester);
Expand Down Expand Up @@ -102,6 +100,8 @@ class extension_tester_t {
std::unique_ptr<video_frame_t> video_frame) {}

private:
friend class extension_tester_internal_accessor_t;

void invoke_cpp_extension_tester_on_start(
ten_env_tester_t &cpp_ten_env_tester) {
on_start(cpp_ten_env_tester);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,11 +221,6 @@ class ten_client_proxy_t {
impl_.add_addon_base_dir(addon_path);
}

void init_app_property_json(const char *app_property_json) {
TEN_ASSERT(app_property_json, "Invalid argument.");
impl_.init_test_app_property_from_json(app_property_json);
}

void start_graph(const char *graph_json) {
TEN_ASSERT(graph_json, "Invalid argument.");
impl_.set_test_mode_graph(graph_json);
Expand Down
3 changes: 2 additions & 1 deletion core/include/ten_runtime/test/extension_tester.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ TEN_RUNTIME_API void ten_extension_tester_destroy(ten_extension_tester_t *self);
// to this extension, and all outputs from the extension will be sent back to
// the tester.
TEN_RUNTIME_API void ten_extension_tester_set_test_mode_single(
ten_extension_tester_t *self, const char *addon_name);
ten_extension_tester_t *self, const char *addon_name,
const char *property_json_str);

// Testing a complete graph which must contain exactly one proxy extension. All
// messages input by the tester will be directed to this proxy extension, and
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// Copyright © 2024 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.
//
#pragma once

#include "ten_runtime/binding/cpp/detail/test/extension_tester.h"

namespace ten {

class extension_tester_internal_accessor_t {
public:
static void init_test_app_property_from_json(extension_tester_t &tester,
const char *property_json_str) {
TEN_ASSERT(property_json_str, "Invalid argument.");
ten_extension_tester_init_test_app_property_from_json(
tester.c_extension_tester, property_json_str);
}
};

} // namespace ten
1 change: 1 addition & 0 deletions core/include_internal/ten_runtime/binding/cpp/ten.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "include_internal/ten_runtime/binding/cpp/detail/msg/cmd/timer.h" // IWYU pragma: export
#include "include_internal/ten_runtime/binding/cpp/detail/ten_env_impl.h" // IWYU pragma: export
#include "include_internal/ten_runtime/binding/cpp/detail/ten_env_internal_accessor.h" // IWYU pragma: export
#include "include_internal/ten_runtime/binding/cpp/detail/test/extension_tester_internal_accessor.h" // IWYU pragma: export
#include "ten_runtime/addon/extension/extension.h" // IWYU pragma: export
#include "ten_runtime/binding/cpp/detail/addon.h" // IWYU pragma: export
#include "ten_runtime/binding/cpp/detail/addon_manager.h" // IWYU pragma: export
Expand Down
1 change: 1 addition & 0 deletions core/include_internal/ten_runtime/test/extension_tester.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ struct ten_extension_tester_t {
union {
struct {
ten_string_t addon_name;
ten_string_t property_json;
} addon;

struct {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class _Msg:
extension_group: str | None,
extension: str | None,
) -> None: ...
def set_property_from_json(self, path: str, json: str) -> None: ...
def set_property_from_json(self, path: str, json_str: str) -> None: ...
def get_property_to_json(self, path: str | None = None) -> str: ...
def get_property_int(self, path: str) -> int: ...
def set_property_int(self, path: str, value: int) -> None: ...
Expand Down Expand Up @@ -204,7 +204,9 @@ class _TenEnvTester:
def stop_test(self) -> None: ...

class _ExtensionTester:
def set_test_mode_single(self, addon_name: str) -> None: ...
def set_test_mode_single(
self, addon_name: str, property_json_str: str | None
) -> None: ...
def run(self) -> None: ...

def _register_addon_as_extension(
Expand Down
8 changes: 6 additions & 2 deletions core/src/ten_runtime/binding/python/interface/ten/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,12 @@ def add_addon_base_dir(self, base_dir: str) -> None:
self.addon_base_dirs.append(base_dir)

@final
def set_test_mode_single(self, addon_name: str) -> None:
return _ExtensionTester.set_test_mode_single(self, addon_name)
def set_test_mode_single(
self, addon_name: str, property_json_str: str | None = None
) -> None:
return _ExtensionTester.set_test_mode_single(
self, addon_name, property_json_str
)

@final
def run(self) -> None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,20 +307,21 @@ static PyObject *ten_py_extension_tester_set_test_mode_single(PyObject *self,
ten_py_extension_tester_check_integrity(py_extension_tester),
"Invalid argument.");

if (PyTuple_GET_SIZE(args) != 1) {
if (PyTuple_GET_SIZE(args) != 2) {
return ten_py_raise_py_value_error_exception(
"Invalid argument count when extension_tester.set_test_mode_single.");
}

const char *addon_name = NULL;
if (!PyArg_ParseTuple(args, "s", &addon_name)) {
const char *property_json_str = NULL;
if (!PyArg_ParseTuple(args, "sz", &addon_name, &property_json_str)) {
return ten_py_raise_py_value_error_exception(
"Failed to parse arguments when "
"extension_tester.set_test_mode_single.");
}

ten_extension_tester_set_test_mode_single(
py_extension_tester->c_extension_tester, addon_name);
py_extension_tester->c_extension_tester, addon_name, property_json_str);

Py_RETURN_NONE;
}
Expand Down
37 changes: 34 additions & 3 deletions core/src/ten_runtime/test/extension_tester.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
#include "ten_utils/container/list.h"
#include "ten_utils/container/list_str.h"
#include "ten_utils/io/runloop.h"
#include "ten_utils/lib/error.h"
#include "ten_utils/lib/event.h"
#include "ten_utils/lib/json.h"
#include "ten_utils/lib/signature.h"
#include "ten_utils/lib/smart_ptr.h"
#include "ten_utils/lib/string.h"
Expand Down Expand Up @@ -96,14 +98,37 @@ ten_extension_tester_t *ten_extension_tester_create(
}

void ten_extension_tester_set_test_mode_single(ten_extension_tester_t *self,
const char *addon_name) {
const char *addon_name,
const char *property_json_str) {
TEN_ASSERT(self && ten_extension_tester_check_integrity(self, true),
"Invalid argument.");
TEN_ASSERT(addon_name, "Invalid argument.");

self->test_mode = TEN_EXTENSION_TESTER_TEST_MODE_SINGLE;
ten_string_init_from_c_str(&self->test_target.addon.addon_name, addon_name,
strlen(addon_name));

if (property_json_str && strlen(property_json_str) > 0) {
ten_error_t err;
ten_error_init(&err);

ten_json_t *json = ten_json_from_string(property_json_str, &err);
if (json) {
ten_json_destroy(json);
} else {
TEN_ASSERT(0, "Failed to parse property json: %s",
ten_error_errmsg(&err));
}

ten_error_deinit(&err);

ten_string_init_from_c_str(&self->test_target.addon.property_json,
property_json_str, strlen(property_json_str));
} else {
const char *empty_json = "{}";
ten_string_init_from_c_str(&self->test_target.addon.property_json,
empty_json, strlen(empty_json));
}
}

void ten_extension_tester_set_test_mode_graph(ten_extension_tester_t *self,
Expand Down Expand Up @@ -154,6 +179,7 @@ static void ten_extension_tester_destroy_test_target(

if (self->test_mode == TEN_EXTENSION_TESTER_TEST_MODE_SINGLE) {
ten_string_deinit(&self->test_target.addon.addon_name);
ten_string_deinit(&self->test_target.addon.property_json);
} else if (self->test_mode == TEN_EXTENSION_TESTER_TEST_MODE_GRAPH) {
ten_string_deinit(&self->test_target.graph.graph_json);
}
Expand Down Expand Up @@ -233,6 +259,9 @@ static void ten_extension_tester_create_and_start_graph(
const char *addon_name =
ten_string_get_raw_str(&self->test_target.addon.addon_name);

const char *property_json_str =
ten_string_get_raw_str(&self->test_target.addon.property_json);

ten_string_t graph_json_str;
ten_string_init_formatted(&graph_json_str,
"{\
Expand All @@ -247,7 +276,8 @@ static void ten_extension_tester_create_and_start_graph(
\"name\": \"%s\",\
\"addon\": \"%s\",\
\"extension_group\": \"test_extension_group_2\",\
\"app\": \"localhost\"\
\"app\": \"localhost\",\
\"property\": %s\
}],\
\"connections\": [{\
\"app\": \"localhost\",\
Expand Down Expand Up @@ -323,8 +353,9 @@ static void ten_extension_tester_create_and_start_graph(
}]\
}]\
}",
addon_name, addon_name, property_json_str,
addon_name, addon_name, addon_name, addon_name,
addon_name, addon_name, addon_name);
addon_name);
rc = ten_cmd_start_graph_set_graph_from_json_str(
start_graph_cmd, ten_string_get_raw_str(&graph_json_str), NULL);
TEN_ASSERT(rc, "Should not happen.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,8 @@ def on_cmd(self, ten_env: TenEnv, cmd: Cmd) -> None:
if cmd.get_name() == "hello_world":
self.cached_cmd = cmd
self.return_if_all_data_received(ten_env)
elif cmd.get_name() == "greeting":
greeting = ten_env.get_property_string("greeting")
cmd_result = CmdResult.create(StatusCode.OK)
cmd_result.set_property_string("detail", greeting)
ten_env.return_result(cmd_result, cmd)
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ export PYTHONPATH=.ten/app/ten_packages/system/ten_runtime_python/lib:.ten/app/t
#
# Refer to https://github.com/pytorch/pytorch/issues/102360?from_wecom=1#issuecomment-1708989096

python -m pytest -s tests/
python -m pytest -s tests/test_basic.py
python -m pytest -s tests/test_set_property.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#
# Copyright © 2024 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.
#
from pathlib import Path
from typing import Optional
from ten import (
ExtensionTester,
TenEnvTester,
Cmd,
CmdResult,
StatusCode,
TenError,
)


class ExtensionTesterSetProperty(ExtensionTester):
def check_greeting(
self,
ten_env: TenEnvTester,
result: Optional[CmdResult],
error: Optional[TenError],
):
if error is not None:
assert False, error

assert result is not None

statusCode = result.get_status_code()
print("receive hello_world, status:" + str(statusCode))

if statusCode == StatusCode.OK:
detail = result.get_property_string("detail")
assert detail == "hola"

ten_env.stop_test()

def on_start(self, ten_env: TenEnvTester) -> None:
cmd = Cmd.create("greeting")

ten_env.send_cmd(
cmd,
lambda ten_env, result, error: self.check_greeting(
ten_env, result, error
),
)

print("tester on_start_done")
ten_env.on_start_done()


def test_set_property():
tester = ExtensionTesterSetProperty()
tester.add_addon_base_dir(str(Path(__file__).resolve().parent.parent))
tester.set_test_mode_single(
"default_extension_python", '{"greeting": "hola"}'
)
tester.run()


if __name__ == "__main__":
test_set_property()
2 changes: 1 addition & 1 deletion tests/ten_runtime/smoke/standalone_test/basic_c.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ TEST(StandaloneTest, BasicC) { // NOLINT
ten_extension_tester_t *tester = ten_extension_tester_create(
ten_extension_tester_on_start, nullptr, nullptr, nullptr, nullptr);
ten_extension_tester_set_test_mode_single(
tester, "standalone_test_basic_c__test_extension_1");
tester, "standalone_test_basic_c__test_extension_1", nullptr);

bool rc = ten_extension_tester_run(tester);
TEN_ASSERT(rc, "Should not happen.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ TEST(StandaloneTest, BasicGraphCrossApp) { // NOLINT

auto *tester = new extension_tester_1();

tester->init_test_app_property_from_json(
R"({
ten::extension_tester_internal_accessor_t::init_test_app_property_from_json(
*tester, R"({
"_ten": {
"uri": "client:aaa"
}
Expand Down
2 changes: 1 addition & 1 deletion tests/ten_runtime/smoke/standalone_test/on_cmd_c.cc
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ TEST(StandaloneTest, OnCmdC) { // NOLINT
ten_extension_tester_on_start, ten_extension_tester_on_cmd, nullptr,
nullptr, nullptr);
ten_extension_tester_set_test_mode_single(
tester, "standalone_test_on_cmd_c__test_extension_1");
tester, "standalone_test_on_cmd_c__test_extension_1", nullptr);

bool rc = ten_extension_tester_run(tester);
TEN_ASSERT(rc, "Should not happen.");
Expand Down
Loading

0 comments on commit f395b74

Please sign in to comment.