Skip to content

Commit

Permalink
feat: add codes (#282)
Browse files Browse the repository at this point in the history
  • Loading branch information
halajohn authored Nov 16, 2024
1 parent d3cf1b4 commit fa6a91d
Show file tree
Hide file tree
Showing 5 changed files with 257 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@
"request": "launch",
"program": "${workspaceFolder}/out/linux/x64/tests/standalone/ten_runtime_smoke_test",
"args": [
"--gtest_filter=ExtensionTest.NoAudioFrameDest"
"--gtest_filter=LogTest.LogFile"
],
"cwd": "${workspaceFolder}/out/linux/x64/tests/standalone/",
"env": {
Expand Down
122 changes: 120 additions & 2 deletions core/src/ten_utils/log/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,85 @@
#include "include_internal/ten_utils/log/output.h"
#include "ten_utils/lib/file.h"

#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#define PATH_SEPARATOR '\\'
#else
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#define PATH_SEPARATOR '/'
#endif

// Function to create directories recursively.
static bool create_directories(const char *path) {
char *path_copy = strdup(path);
assert(path_copy && "Failed to allocate memory.");
if (!path_copy) {
return false;
}

size_t len = strlen(path_copy);
// Remove trailing separators.
while (len > 0 && (path_copy[len - 1] == '/' || path_copy[len - 1] == '\\')) {
path_copy[len - 1] = '\0';
len--;
}

for (size_t i = 1; i < len; i++) {
if (path_copy[i] == '/' || path_copy[i] == '\\') {
char temp = path_copy[i];
path_copy[i] = '\0';

// Skip if path is root on Unix or drive letter on Windows.
#if defined(_WIN32) || defined(_WIN64)
if (i == 2 && path_copy[1] == ':') {
path_copy[i] = temp;
continue;
}
#endif

#if defined(_WIN32) || defined(_WIN64)
if (!CreateDirectoryA(path_copy, NULL)) {
DWORD err = GetLastError();
if (err != ERROR_ALREADY_EXISTS) {
free(path_copy);
return false;
}
}
#else
if (mkdir(path_copy, 0755) != 0) {
if (errno != EEXIST) {
free(path_copy);
return false;
}
}
#endif
path_copy[i] = temp;
}
}

#if defined(_WIN32) || defined(_WIN64)
if (!CreateDirectoryA(path_copy, NULL)) {
DWORD err = GetLastError();
if (err != ERROR_ALREADY_EXISTS) {
free(path_copy);
return false;
}
}
#else
if (mkdir(path_copy, 0755) != 0) {
if (errno != EEXIST) {
free(path_copy);
return false;
}
}
#endif

free(path_copy);
return true;
}

static void ten_log_output_set(ten_log_t *self,
const ten_log_output_func_t output_cb,
const ten_log_close_func_t close_cb,
Expand Down Expand Up @@ -48,12 +127,45 @@ static void ten_log_close_file_cb(void *user_data) {
}

static int *get_log_fd(const char *log_path) {
assert(log_path && "log_path cannot be NULL.");

// Duplicate the log_path to manipulate it.
char *path_copy = strdup(log_path);
assert(path_copy && "Failed to allocate memory.");
if (!path_copy) {
return NULL;
}

// Find the directory part of the path.
char *last_sep = strrchr(path_copy, PATH_SEPARATOR);
if (last_sep) {
*last_sep = '\0'; // Terminate the string to get the directory path.

// Create directories recursively.
if (create_directories(path_copy) != true) {
// Failed to create directories
free(path_copy);
return NULL;
}
}

free(path_copy);

// Now, attempt to open the file.
FILE *fp = fopen(log_path, "ab");
if (!fp) {
// Handle fopen failure.
return NULL;
}

int *fd_ptr = malloc(sizeof(int));
assert(fd_ptr && "Failed to allocate memory.");
if (!fd_ptr) {
(void)fclose(fp);
return NULL;
}

FILE *fp = fopen(log_path, "ab");
*fd_ptr = ten_file_get_fd(fp);

return fd_ptr;
}

Expand Down Expand Up @@ -88,6 +200,12 @@ void ten_log_set_output_to_file(ten_log_t *self, const char *log_path) {
assert(log_path && "Invalid argument.");

int *fd = get_log_fd(log_path);
if (!fd) {
// Failed to open log file or create directories.
ten_log_set_output_to_stderr(self);
return;
}

ten_log_output_set(self, ten_log_output_to_file_cb, ten_log_close_file_cb,
fd);

Expand Down
1 change: 1 addition & 0 deletions tests/ten_runtime/smoke/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ ten_executable("ten_runtime_smoke_test") {
"data_test",
"extension_test",
"graph_test",
"log",
"msg_test",
"notify_test",
"result_conversion",
Expand Down
24 changes: 24 additions & 0 deletions tests/ten_runtime/smoke/log/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#
# 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.
#
import("//build/ten_runtime/glob.gni")
import("//build/ten_runtime/ten.gni")

glob("log") {
file_list = all_native_files
deps = [
"//third_party/msgpack:msgpackc",
"//third_party/nlohmann_json",
]
include_dirs = [
"//packages",
"//tests/ten_runtime",
]
public_deps = [
"//third_party/googlemock",
"//third_party/googletest",
]
}
111 changes: 111 additions & 0 deletions tests/ten_runtime/smoke/log/log_file.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
//
// 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.
//
#include <nlohmann/json.hpp>
#include <string>

#include "gtest/gtest.h"
#include "include_internal/ten_runtime/binding/cpp/ten.h"
#include "ten_utils/lib/thread.h"
#include "tests/common/client/cpp/msgpack_tcp.h"
#include "tests/ten_runtime/smoke/extension_test/util/binding/cpp/check.h"

namespace {

class test_extension : public ten::extension_t {
public:
explicit test_extension(const std::string &name) : ten::extension_t(name) {}

void on_cmd(ten::ten_env_t &ten_env,
std::unique_ptr<ten::cmd_t> cmd) override {
TEN_ENV_LOG_DEBUG(ten_env,
(std::string("on_cmd ") + cmd->get_name()).c_str());

if (std::string(cmd->get_name()) == "hello_world") {
auto cmd_result = ten::cmd_result_t::create(TEN_STATUS_CODE_OK);
cmd_result->set_property("detail", "hello world, too");
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_env.init_property_from_json(
// clang-format off
R"({
"_ten": {
"uri": "msgpack://127.0.0.1:8001/",
"log_level": 2,
"log_file": "aaa/log_file.log"
}
})"
// clang-format on
,
nullptr);
ASSERT_EQ(rc, true);

ten_env.on_configure_done();
}
};

void *test_app_thread_main(TEN_UNUSED void *args) {
auto *app = new test_app();
app->run();
delete app;

return nullptr;
}

TEN_CPP_REGISTER_ADDON_AS_EXTENSION(log_file__test_extension, test_extension);

} // namespace

TEST(LogTest, LogFile) { // NOLINT
auto *app_thread =
ten_thread_create("app thread", test_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/");

// Send graph.
nlohmann::json resp = client->send_json_and_recv_resp_in_json(
R"({
"_ten": {
"type": "start_graph",
"seq_id": "55",
"nodes": [{
"type": "extension",
"name": "test_extension",
"addon": "log_file__test_extension",
"extension_group": "test_extension_group",
"app": "msgpack://127.0.0.1:8001/"
}]
}
})"_json);
ten_test::check_status_code_is(resp, TEN_STATUS_CODE_OK);

// Send a user-defined 'hello world' command.
resp = client->send_json_and_recv_resp_in_json(
R"({
"_ten": {
"name": "hello_world",
"seq_id": "137",
"dest": [{
"app": "msgpack://127.0.0.1:8001/",
"extension_group": "test_extension_group",
"extension": "test_extension"
}]
}
})"_json);
ten_test::check_result_is(resp, "137", TEN_STATUS_CODE_OK,
"hello world, too");

delete client;

ten_thread_join(app_thread, -1);
}

0 comments on commit fa6a91d

Please sign in to comment.