Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: expand the implementation of extension tester to allow it to be used for testing the graph #296

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
f94def0
feat: support graph test in standalone testing
sunxilin Nov 18, 2024
7dc5b71
feat: add ten_env_tester_proxy for outside
sunxilin Nov 19, 2024
20fbd62
Merge branch 'main' into 268-expand-the-implementation-of-extension_t…
sunxilin Nov 19, 2024
9808ceb
fix: set start_graph cmd json for graph test
sunxilin Nov 19, 2024
719fb50
fix: modify test extension addon name
sunxilin Nov 19, 2024
a1af584
fix: add more testcases
sunxilin Nov 19, 2024
d2bc1d1
Merge branch 'main' into 268-expand-the-implementation-of-extension_t…
sunxilin Nov 20, 2024
d42be62
fix: remove check for duplicated remotes in their creation
sunxilin Nov 20, 2024
a9b32f6
fix: close duplicated remote
sunxilin Nov 20, 2024
74ebabb
fix: refine remote duplicate logic
sunxilin Nov 20, 2024
6b0694a
fix: refine remote duplicate logic
sunxilin Nov 20, 2024
54a335b
fix: refine remote duplicate logic
sunxilin Nov 20, 2024
20bda81
fix: refine thread check in tester
sunxilin Nov 20, 2024
2dfb30f
fix: rename test file
sunxilin Nov 20, 2024
e52cce9
fix: rename test file
sunxilin Nov 20, 2024
b80cb9d
fix: add more logs
sunxilin Nov 21, 2024
7844e73
fix: log level
sunxilin Nov 21, 2024
3127bee
fix: remove unused code
sunxilin Nov 21, 2024
de90189
feat: add send_audio/video_frame in cpp tester
sunxilin Nov 21, 2024
1457054
chore: fix
sunxilin Nov 21, 2024
0d64f31
Merge branch 'main' into 268-expand-the-implementation-of-extension_t…
sunxilin Nov 21, 2024
9a9c987
Merge remote-tracking branch 'origin/main' into 268-expand-the-implem…
sunxilin Nov 25, 2024
272a1ce
fix: fix graph tests
sunxilin Nov 25, 2024
32c4bfe
Merge branch 'main' into 268-expand-the-implementation-of-extension_t…
sunxilin Nov 25, 2024
afc1e0e
Merge branch 'main' into 268-expand-the-implementation-of-extension_t…
sunxilin Nov 25, 2024
c838e24
fix: add more apis for ten_client_proxy
sunxilin Nov 25, 2024
0aa27fb
Merge branch 'main' into 268-expand-the-implementation-of-extension_t…
sunxilin Nov 25, 2024
8281713
Merge branch 'main' into 268-expand-the-implementation-of-extension_t…
halajohn Nov 25, 2024
6711ad7
fix: refine codes
halajohn Nov 25, 2024
f04808f
fix: refine codes
halajohn Nov 25, 2024
b0829bc
fix: refine codes
halajohn Nov 25, 2024
8e0a0bc
fix: refine codes
halajohn Nov 25, 2024
2b1b228
fix: refine codes
halajohn Nov 25, 2024
de7f2d7
fix: refine codes
halajohn Nov 25, 2024
e352305
fix: refine codes
halajohn Nov 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
253 changes: 253 additions & 0 deletions core/include/ten_runtime/binding/cpp/experimental/ten_client_proxy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
//
// 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/internal/test/env_tester_proxy.h"
#include "ten_runtime/binding/cpp/internal/test/extension_tester.h"
#include "ten_utils/log/log.h"

namespace ten {

using ten_client_proxy_send_cmd_result_handler_func_t =
std::function<void(std::unique_ptr<ten::cmd_result_t>)>;

class ten_client_proxy_event_handler_t {
public:
ten_client_proxy_event_handler_t() = default;
virtual ~ten_client_proxy_event_handler_t() = default;

ten_client_proxy_event_handler_t(const ten_client_proxy_event_handler_t &) =
delete;
ten_client_proxy_event_handler_t(ten_client_proxy_event_handler_t &&) =
delete;
ten_client_proxy_event_handler_t &operator=(
const ten_client_proxy_event_handler_t &) = delete;
ten_client_proxy_event_handler_t &operator=(
const ten_client_proxy_event_handler_t &&) = delete;

virtual void on_start() {}

virtual void on_cmd(std::unique_ptr<cmd_t> cmd) {}

virtual void on_data(std::unique_ptr<data_t> data) {}

virtual void on_audio_frame(std::unique_ptr<audio_frame_t> audio_frame) {}

virtual void on_video_frame(std::unique_ptr<video_frame_t> video_frame) {}
};

namespace {

class ten_client_proxy_internal_impl_t : public ten::extension_tester_t {
protected:
void on_start(ten::ten_env_tester_t &ten_env_tester) override {
ten_env_tester_proxy_ = std::unique_ptr<ten::ten_env_tester_proxy_t>(
ten::ten_env_tester_proxy_t::create(ten_env_tester));
TEN_ASSERT(ten_env_tester_proxy_, "Should not happen.");

if (event_handler_ != nullptr) {
event_handler_->on_start();
}

ten_env_tester.on_start_done();
}

void on_cmd(ten::ten_env_tester_t & /*ten_env_tester*/,
std::unique_ptr<ten::cmd_t> cmd) override {
if (event_handler_ != nullptr) {
event_handler_->on_cmd(std::move(cmd));
}
}

void on_data(ten::ten_env_tester_t & /*ten_env_tester*/,
std::unique_ptr<ten::data_t> data) override {
if (event_handler_ != nullptr) {
event_handler_->on_data(std::move(data));
}
}

void on_audio_frame(
ten::ten_env_tester_t & /*ten_env_tester*/,
std::unique_ptr<ten::audio_frame_t> audio_frame) override {
if (event_handler_ != nullptr) {
event_handler_->on_audio_frame(std::move(audio_frame));
}
}

void on_video_frame(
ten::ten_env_tester_t & /*ten_env_tester*/,
std::unique_ptr<ten::video_frame_t> video_frame) override {
if (event_handler_ != nullptr) {
event_handler_->on_video_frame(std::move(video_frame));
}
}

static void proxy_on_cmd_response(
std::unique_ptr<ten::cmd_result_t> cmd_result,
const ten::ten_client_proxy_send_cmd_result_handler_func_t
&result_handler) {
if (result_handler) {
result_handler(std::move(cmd_result));
}
}

public:
void register_callback(ten::ten_client_proxy_event_handler_t *event_handler) {
event_handler_ = event_handler;
}

bool send_cmd(
std::unique_ptr<ten::cmd_t> cmd,
ten::ten_client_proxy_send_cmd_result_handler_func_t &&result_handler) {
TEN_ASSERT(ten_env_tester_proxy_, "Invalid state.");

if (ten_env_tester_proxy_ == nullptr) {
TEN_LOGE("Failed to send_cmd: %s before started.", cmd->get_name());
return false;
}

auto cmd_shared =
std::make_shared<std::unique_ptr<ten::cmd_t>>(std::move(cmd));

return ten_env_tester_proxy_->notify(
[cmd_shared, result_handler](ten::ten_env_tester_t &ten_env_tester) {
ten_env_tester.send_cmd(
std::move(*cmd_shared),
[result_handler](ten::ten_env_tester_t & /*ten_env_tester*/,
std::unique_ptr<ten::cmd_result_t> cmd_result) {
proxy_on_cmd_response(std::move(cmd_result), result_handler);
});
},
nullptr);
}

bool send_data(std::unique_ptr<ten::data_t> data) {
TEN_ASSERT(ten_env_tester_proxy_, "Invalid state.");

if (ten_env_tester_proxy_ == nullptr) {
TEN_LOGE("Failed to send_data before started.");
return false;
}

auto data_shared =
std::make_shared<std::unique_ptr<ten::data_t>>(std::move(data));

return ten_env_tester_proxy_->notify(
[data_shared](ten::ten_env_tester_t &env_tester) {
env_tester.send_data(std::move(*data_shared));
},
nullptr);
}

bool send_audio_frame(std::unique_ptr<ten::audio_frame_t> audio_frame) {
TEN_ASSERT(ten_env_tester_proxy_, "Invalid state.");

if (ten_env_tester_proxy_ == nullptr) {
TEN_LOGE("Failed to send_audio_frame before started.");
return false;
}

auto audio_frame_shared =
std::make_shared<std::unique_ptr<ten::audio_frame_t>>(
std::move(audio_frame));

return ten_env_tester_proxy_->notify(
[audio_frame_shared](ten::ten_env_tester_t &env_tester) {
env_tester.send_audio_frame(std::move(*audio_frame_shared));
},
nullptr);
}

bool send_video_frame(std::unique_ptr<ten::video_frame_t> video_frame) {
TEN_ASSERT(ten_env_tester_proxy_, "Invalid state.");

if (ten_env_tester_proxy_ == nullptr) {
TEN_LOGE("Failed to send_video_frame before started.");
return false;
}

auto video_frame_shared =
std::make_shared<std::unique_ptr<ten::video_frame_t>>(
std::move(video_frame));

return ten_env_tester_proxy_->notify(
[video_frame_shared](ten::ten_env_tester_t &env_tester) {
env_tester.send_video_frame(std::move(*video_frame_shared));
},
nullptr);
}

bool stop() {
if (ten_env_tester_proxy_ == nullptr) {
TEN_LOGE("Failed to stop before started.");
return false;
}

return ten_env_tester_proxy_->notify(
[](ten::ten_env_tester_t &env_tester) { env_tester.stop_test(); },
nullptr);
}

private:
ten::ten_client_proxy_event_handler_t *event_handler_;

// The thread-safety should be guaranteed by the caller.
std::unique_ptr<ten::ten_env_tester_proxy_t> ten_env_tester_proxy_;
};

} // namespace

class ten_client_proxy_t {
public:
ten_client_proxy_t() = default;
virtual ~ten_client_proxy_t() = default;

ten_client_proxy_t(const ten_client_proxy_t &) = delete;
ten_client_proxy_t(ten_client_proxy_t &&) = delete;
ten_client_proxy_t &operator=(const ten_client_proxy_t &) = delete;
ten_client_proxy_t &operator=(const ten_client_proxy_t &&) = delete;

void add_addon_base_dir(const char *addon_path) {
TEN_ASSERT(addon_path, "Invalid argument.");
impl_.add_addon_base_dir(addon_path);
}

void start_graph(const char *graph_json) {
TEN_ASSERT(graph_json, "Invalid argument.");
impl_.set_test_mode_graph(graph_json);
impl_.run();
}

// These functions should be called after the on_start callback is received.

void send_cmd(
std::unique_ptr<cmd_t> cmd,
ten_client_proxy_send_cmd_result_handler_func_t &&result_handler) {
impl_.send_cmd(std::move(cmd), std::move(result_handler));
}

void send_data(std::unique_ptr<data_t> data) {
impl_.send_data(std::move(data));
}

void send_audio_frame(std::unique_ptr<audio_frame_t> audio_frame) {
impl_.send_audio_frame(std::move(audio_frame));
}

void send_video_frame(std::unique_ptr<video_frame_t> video_frame) {
impl_.send_video_frame(std::move(video_frame));
}

void register_event_handler(ten_client_proxy_event_handler_t *event_handler) {
impl_.register_callback(event_handler);
}

private:
ten_client_proxy_internal_impl_t impl_;
};

} // namespace ten
Loading
Loading