refactor(exint): improve queue implementation and rename project
- Rename project from extern_interface to external_interface - Update CMakeLists.txt to use new project name and add compiler flags - Implement QueueException and related classes in dataqueue.hpp - Update event handling and thread management in event.cpp - Modify external_interface initialization and naming conventions - Update logging and test cases to reflect changes
This commit is contained in:
parent
6653710be9
commit
5ca1a439f3
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required(VERSION 3.15)
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
|
||||||
project(extern_interface CXX)
|
project(external_interface CXX)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
if (NOT CMAKE_CROSSCOMPILING)
|
if (NOT CMAKE_CROSSCOMPILING)
|
||||||
|
@ -8,7 +8,7 @@ if (NOT CMAKE_CROSSCOMPILING)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
set(CMAKE_CXX_FLAGS "-std=c++11 -fPIC -Wall ${CMAKE_CXX_FLAGS}")
|
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall ${CMAKE_CXX_FLAGS}")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-g ${CMAKE_CXX_FLAGS}")
|
set(CMAKE_CXX_FLAGS_DEBUG "-g ${CMAKE_CXX_FLAGS}")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "-g -O2 ${CMAKE_CXX_FLAGS}")
|
set(CMAKE_CXX_FLAGS_RELEASE "-g -O2 ${CMAKE_CXX_FLAGS}")
|
||||||
elseif (WIN32)
|
elseif (WIN32)
|
||||||
|
@ -34,8 +34,12 @@ include_directories(./include)
|
||||||
|
|
||||||
aux_source_directory(./src SRC_LIST)
|
aux_source_directory(./src SRC_LIST)
|
||||||
|
|
||||||
add_library(extern_interface_static STATIC ${SRC_LIST})
|
add_library(exint_static STATIC ${SRC_LIST})
|
||||||
add_library(extern_interface SHARED ${SRC_LIST})
|
add_library(exint SHARED ${SRC_LIST})
|
||||||
|
|
||||||
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
|
target_compile_options(exint PRIVATE -Wno-nonnull -fvisibility=hidden)
|
||||||
|
endif()
|
||||||
|
|
||||||
# 设置测试文件和公共源文件
|
# 设置测试文件和公共源文件
|
||||||
set(TESTS_DIR "${CMAKE_SOURCE_DIR}/tests")
|
set(TESTS_DIR "${CMAKE_SOURCE_DIR}/tests")
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
//#define COM_FRAME_DEBUG
|
// #define COM_FRAME_DEBUG
|
||||||
|
|
||||||
#define COM_FRAME_MAGIC_NUMBER 0xEB90
|
#define COM_FRAME_MAGIC_NUMBER 0xEB90
|
||||||
#define COM_FRAME_DEFAULT_PAYLOAD_LENGTH 2
|
#define COM_FRAME_DEFAULT_PAYLOAD_LENGTH 2
|
||||||
|
|
|
@ -1,15 +1,21 @@
|
||||||
#ifndef _INCLUDED_QUEUE_
|
#ifndef _INCLUDED_QUEUE_
|
||||||
#define _INCLUDED_QUEUE_
|
#define _INCLUDED_QUEUE_
|
||||||
|
|
||||||
#include <list>
|
#include <deque>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <chrono>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
class QueueException;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class DataQueue {
|
class DataQueue {
|
||||||
public:
|
public:
|
||||||
DataQueue() = default;
|
DataQueue() : m_CurrEpoch(0) {}
|
||||||
DataQueue(DataQueue&) = delete;
|
DataQueue(const DataQueue&) = delete;
|
||||||
|
|
||||||
|
~DataQueue() { Clear(); }
|
||||||
|
|
||||||
void Push(T data)
|
void Push(T data)
|
||||||
{
|
{
|
||||||
|
@ -21,37 +27,95 @@ public:
|
||||||
T Pop()
|
T Pop()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(m_Mutex);
|
std::unique_lock<std::mutex> lock(m_Mutex);
|
||||||
|
auto epoch = m_CurrEpoch;
|
||||||
while (m_Queue.empty())
|
while (m_Queue.empty())
|
||||||
{
|
{
|
||||||
m_Cond.wait(lock);
|
m_Cond.wait(lock);
|
||||||
|
if (epoch != m_CurrEpoch) {
|
||||||
|
throw QueueException(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
T data = std::move(m_Queue.front());
|
T data = std::move(m_Queue.front());
|
||||||
m_Queue.pop_front();
|
m_Queue.pop_front();
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Empty()
|
template <typename Rep = uint64_t, typename Period = std::milli>
|
||||||
|
T Pop(const std::chrono::duration<Rep, Period> timeout)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(m_Mutex);
|
||||||
|
auto epoch = m_CurrEpoch;
|
||||||
|
while (m_Queue.empty())
|
||||||
|
{
|
||||||
|
if (m_Cond.wait_for(lock, timeout) == std::cv_status::timeout) {
|
||||||
|
throw QueueTimeout(this);
|
||||||
|
}
|
||||||
|
if (epoch != m_CurrEpoch) {
|
||||||
|
throw QueueException(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Empty() noexcept
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_Mutex);
|
std::lock_guard<std::mutex> lock(m_Mutex);
|
||||||
return m_Queue.empty();
|
return m_Queue.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Size()
|
size_t Size() noexcept
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_Mutex);
|
std::lock_guard<std::mutex> lock(m_Mutex);
|
||||||
return m_Queue.size();
|
return m_Queue.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clear()
|
void Clear() noexcept
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_Mutex);
|
std::lock_guard<std::mutex> lock(m_Mutex);
|
||||||
m_Queue.clear();
|
m_Queue.clear();
|
||||||
|
m_CurrEpoch++;
|
||||||
|
m_Cond.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::list<T> m_Queue;
|
std::deque<T> m_Queue;
|
||||||
std::mutex m_Mutex;
|
std::mutex m_Mutex;
|
||||||
std::condition_variable m_Cond;
|
std::condition_variable m_Cond;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t m_CurrEpoch;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QueueException : public std::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QueueException(void* queue) : queue(queue) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
DataQueue<T>* GetQueue() const noexcept
|
||||||
|
{
|
||||||
|
return static_cast<DataQueue<T>*>(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void* queue;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QueueCleared : QueueException
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const char* what() const noexcept override
|
||||||
|
{
|
||||||
|
return "queue cleared";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class QueueTimeout : QueueException
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const char* what() const noexcept override
|
||||||
|
{
|
||||||
|
return "queue timeout";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -187,7 +187,7 @@ extern char g_strSystemLogPath[500];
|
||||||
extern char g_strPCMSavePath[500];
|
extern char g_strPCMSavePath[500];
|
||||||
extern struct tm g_tCurLocalTime;
|
extern struct tm g_tCurLocalTime;
|
||||||
|
|
||||||
extern bool g_bKeepEtifRuning;
|
extern bool g_bKeepExintRuning;
|
||||||
extern long g_iSaveInputAudio;
|
extern long g_iSaveInputAudio;
|
||||||
extern long g_iSaveTTSAudio;
|
extern long g_iSaveTTSAudio;
|
||||||
extern long g_iSaveHostAudio;
|
extern long g_iSaveHostAudio;
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void handle_pack(uint32_t type, size_t len, union PacketData data);
|
void exint_handle_pack(uint32_t type, size_t len, union PacketData data);
|
||||||
|
int exint_init_from_tty(int host_com_tty, int telemetry_com_tty, et_callback_t cb);
|
||||||
|
|
||||||
void* telemetry_host_com_thread(void* args);
|
void* telemetry_host_com_thread(void* args);
|
||||||
void* upper_host_com_thread(void* arg);
|
void* upper_host_com_thread(void* arg);
|
||||||
|
@ -18,7 +19,7 @@ void* upper_host_com_thread(void* arg);
|
||||||
extern int g_iHostCom_tty_id;
|
extern int g_iHostCom_tty_id;
|
||||||
extern int g_iTelemetry_Com_tty_id;
|
extern int g_iTelemetry_Com_tty_id;
|
||||||
extern int g_iEnableAlarmCode;
|
extern int g_iEnableAlarmCode;
|
||||||
extern bool g_bKeepEtifRuning;
|
extern bool g_bKeepExintRuning;
|
||||||
extern int g_iExternTimeDifference;
|
extern int g_iExternTimeDifference;
|
||||||
extern int g_iUseHostComForTelemetry;
|
extern int g_iUseHostComForTelemetry;
|
||||||
extern uint8_t g_iAlarmCode[4];
|
extern uint8_t g_iAlarmCode[4];
|
||||||
|
|
|
@ -24,6 +24,7 @@ void exint_event(const char *event_name, size_t args_size, void *args);
|
||||||
int exint_event_register(const char *event_name, event_callback callback, void* user_data);
|
int exint_event_register(const char *event_name, event_callback callback, void* user_data);
|
||||||
int exint_event_unregister(const char *event_name, event_callback callback, void* user_data);
|
int exint_event_unregister(const char *event_name, event_callback callback, void* user_data);
|
||||||
void* exint_event_thread(void*);
|
void* exint_event_thread(void*);
|
||||||
|
void exint_event_thread_exit();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#define EXTERN_INTERFACE_PUBLIC __declspec(dllexport)
|
#define EXTERN_INTERFACE_PUBLIC __declspec(dllexport)
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
#define EXTERN_INTERFACE_PUBLIC __attribute__ ((dllexport))
|
#define EXTERN_INTERFACE_PUBLIC __attribute__ ((visibility("default")))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -56,7 +56,7 @@ int exint_init(const char* config_path, et_callback_t cb);
|
||||||
EXTERN_INTERFACE_PUBLIC
|
EXTERN_INTERFACE_PUBLIC
|
||||||
void exint_send(uint32_t type, size_t len, union PacketData data);
|
void exint_send(uint32_t type, size_t len, union PacketData data);
|
||||||
EXTERN_INTERFACE_PUBLIC
|
EXTERN_INTERFACE_PUBLIC
|
||||||
void extern_interface_deinit();
|
void exint_finialize();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,8 @@ private:
|
||||||
class LoggerStreamBuf : public std::streambuf {
|
class LoggerStreamBuf : public std::streambuf {
|
||||||
public:
|
public:
|
||||||
LoggerStreamBuf(Logger& logger, Logger::Level level);
|
LoggerStreamBuf(Logger& logger, Logger::Level level);
|
||||||
|
LoggerStreamBuf(const LoggerStreamBuf&) = delete;
|
||||||
|
LoggerStreamBuf(LoggerStreamBuf&& loggerStream) = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int overflow(int c) override;
|
int overflow(int c) override;
|
||||||
|
|
|
@ -203,8 +203,8 @@ ssize_t ComFrame_Send(int tty_id, const ComFrame* frame, const bool swap_endian)
|
||||||
uint32_t length = ComFrame_Length(frame, swap_endian);
|
uint32_t length = ComFrame_Length(frame, swap_endian);
|
||||||
char* buf = (char*)frame;
|
char* buf = (char*)frame;
|
||||||
#ifdef COM_FRAME_DEBUG
|
#ifdef COM_FRAME_DEBUG
|
||||||
PrintFilePos(); printf("send length: %d\n", ComFrame_Length(frame, swap_endian));
|
printf("send length: %d\n", ComFrame_Length(frame, swap_endian));
|
||||||
PrintFilePos(); printf("send checksum: %04x\n", ComFrame_Checksum(frame, swap_endian));
|
printf("send checksum: %04x\n", ComFrame_Checksum(frame, swap_endian));
|
||||||
#endif
|
#endif
|
||||||
while (length > 0) {
|
while (length > 0) {
|
||||||
ssize_t written = write(tty_id, buf, length);
|
ssize_t written = write(tty_id, buf, length);
|
||||||
|
@ -253,15 +253,18 @@ ComFrame* ComFrame_ReceiveEx(int tty_id, void* buffer, const size_t buffer_size,
|
||||||
if (recv_size <= 0 && cached_size == offset) {
|
if (recv_size <= 0 && cached_size == offset) {
|
||||||
usleep(2);
|
usleep(2);
|
||||||
continue;
|
continue;
|
||||||
|
} else if (recv_size < 0) {
|
||||||
|
perror("com read error");
|
||||||
|
recv_size = 0;
|
||||||
}
|
}
|
||||||
#ifdef COM_FRAME_DEBUG
|
#ifdef COM_FRAME_DEBUG
|
||||||
PrintFilePos(); printf(
|
printf(
|
||||||
"receive com data (received=%zd,cached=%zu,number=%04x)\n",
|
"receive com data (received=%zd,cached=%zu,number=%04x)\n",
|
||||||
recv_size, cached_size, ComFrame_HEADER(buffer)->magic_number
|
recv_size, cached_size, ComFrame_HEADER(buffer)->magic_number
|
||||||
);
|
);
|
||||||
PrintFilePos(); printf("buffer: ");
|
printf("buffer: ");
|
||||||
for (size_t i = 0; i < cached_size + recv_size; ++i) {
|
for (size_t i = 0; i < cached_size + recv_size; ++i) {
|
||||||
PrintFilePos(); printf("%02x", ((uint8_t*)buffer)[i]);
|
printf("%02x", ((uint8_t*)buffer)[i]);
|
||||||
}
|
}
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
#endif
|
#endif
|
||||||
|
@ -275,7 +278,7 @@ ComFrame* ComFrame_ReceiveEx(int tty_id, void* buffer, const size_t buffer_size,
|
||||||
if (swap_endian)
|
if (swap_endian)
|
||||||
ComFrameHeader_SwapEndian(ComFrame_HEADER(((uint8_t*)buffer) + offset));
|
ComFrameHeader_SwapEndian(ComFrame_HEADER(((uint8_t*)buffer) + offset));
|
||||||
#ifdef COM_FRAME_DEBUG
|
#ifdef COM_FRAME_DEBUG
|
||||||
PrintFilePos(); printf("find valid data (length=%u)\n", ComFrame_LENGTH(((uint8_t*)buffer)+offset));
|
printf("find valid data (length=%u)\n", ComFrame_LENGTH(((uint8_t*)buffer)+offset));
|
||||||
#endif
|
#endif
|
||||||
pred_size = ComFrame_LENGTH(((uint8_t*)buffer) + offset);
|
pred_size = ComFrame_LENGTH(((uint8_t*)buffer) + offset);
|
||||||
if (pred_size > buffer_size) {
|
if (pred_size > buffer_size) {
|
||||||
|
|
|
@ -3,13 +3,14 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <atomic>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "dataqueue.hpp"
|
#include "dataqueue.hpp"
|
||||||
#include "exint/event.h"
|
#include "exint/event.h"
|
||||||
#include "exint/detail.h"
|
#include "exint/detail.h"
|
||||||
|
|
||||||
|
std::atomic_bool _is_event_thread_running { false };
|
||||||
DataQueue<std::tuple<const char*, event_callback, size_t, std::unique_ptr<uint8_t[]>, void*>> _event_queue;
|
DataQueue<std::tuple<const char*, event_callback, size_t, std::unique_ptr<uint8_t[]>, void*>> _event_queue;
|
||||||
|
|
||||||
static std::unordered_map<std::string, std::vector<std::pair<event_callback, void*>>>& get_event_map() {
|
static std::unordered_map<std::string, std::vector<std::pair<event_callback, void*>>>& get_event_map() {
|
||||||
|
@ -22,8 +23,17 @@ void exint_event(const char *event_name, size_t args_size, void *args) {
|
||||||
auto it = event_map.find(event_name);
|
auto it = event_map.find(event_name);
|
||||||
if (it != event_map.end()) {
|
if (it != event_map.end()) {
|
||||||
for (auto &pair : it->second) {
|
for (auto &pair : it->second) {
|
||||||
auto args_copy = new uint8_t[args_size];
|
if (!_is_event_thread_running) {
|
||||||
|
pair.first(event_name, args_size, args, pair.second);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
uint8_t* args_copy;
|
||||||
|
if (args_size == 0) {
|
||||||
|
args_copy = NULL;
|
||||||
|
} else {
|
||||||
|
args_copy = new uint8_t[args_size];
|
||||||
memcpy(args_copy, args, args_size);
|
memcpy(args_copy, args, args_size);
|
||||||
|
}
|
||||||
_event_queue.Push(std::make_tuple(event_name, pair.first, args_size, std::unique_ptr<uint8_t[]>(args_copy), pair.second));
|
_event_queue.Push(std::make_tuple(event_name, pair.first, args_size, std::unique_ptr<uint8_t[]>(args_copy), pair.second));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,14 +70,31 @@ int exint_event_unregister(const char *event_name, event_callback callback, void
|
||||||
}
|
}
|
||||||
|
|
||||||
void* exint_event_thread(void*) {
|
void* exint_event_thread(void*) {
|
||||||
|
bool is_running = false;
|
||||||
|
if (!_is_event_thread_running.compare_exchange_strong(is_running, true)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
const char* event_name;
|
const char* event_name;
|
||||||
event_callback callback;
|
event_callback callback;
|
||||||
size_t args_size;
|
size_t args_size;
|
||||||
std::unique_ptr<uint8_t[]> args;
|
std::unique_ptr<uint8_t[]> args;
|
||||||
void* user_data;
|
void* user_data;
|
||||||
while (g_bKeepEtifRuning) {
|
while (g_bKeepExintRuning) {
|
||||||
|
try {
|
||||||
std::tie(event_name, callback, args_size, args, user_data) = _event_queue.Pop();
|
std::tie(event_name, callback, args_size, args, user_data) = _event_queue.Pop();
|
||||||
|
} catch (const QueueException&) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
callback(event_name, args_size, args.get(), user_data);
|
callback(event_name, args_size, args.get(), user_data);
|
||||||
}
|
}
|
||||||
|
_is_event_thread_running.store(false);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void exint_event_thread_exit() {
|
||||||
|
bool is_running = true;
|
||||||
|
if (!_is_event_thread_running.compare_exchange_strong(is_running, false)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_event_queue.Clear();
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ int g_iHostCom_tty_id;
|
||||||
int g_iTelemetry_Com_tty_id;
|
int g_iTelemetry_Com_tty_id;
|
||||||
int g_iEnableAlarmCode = true;
|
int g_iEnableAlarmCode = true;
|
||||||
bool g_bTelemetry_Open = true;
|
bool g_bTelemetry_Open = true;
|
||||||
bool g_bKeepEtifRuning = false;
|
bool g_bKeepExintRuning = false;
|
||||||
int g_iExternTimeDifference = 0;
|
int g_iExternTimeDifference = 0;
|
||||||
int g_iUseHostComForTelemetry = true;
|
int g_iUseHostComForTelemetry = true;
|
||||||
uint8_t g_iAlarmCode[4] = {0xAA, 0xAA, 0xAA, 0xAA};
|
uint8_t g_iAlarmCode[4] = {0xAA, 0xAA, 0xAA, 0xAA};
|
||||||
|
@ -42,7 +42,18 @@ int exint_init(const char* config_path, et_callback_t cb) {
|
||||||
if (read_config(config_path)) return -1;
|
if (read_config(config_path)) return -1;
|
||||||
et_callback = cb;
|
et_callback = cb;
|
||||||
|
|
||||||
g_bKeepEtifRuning = true;
|
g_bKeepExintRuning = true;
|
||||||
|
pthread_create(&event_thread, NULL, exint_event_thread, NULL);
|
||||||
|
pthread_create(&upperhost_thread, NULL, upper_host_com_thread, NULL);
|
||||||
|
pthread_create(&telemetry_thread, NULL, telemetry_host_com_thread, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int exint_init_from_tty(int host_com_tty, int telemetry_com_tty, et_callback_t cb) {
|
||||||
|
et_callback = cb;
|
||||||
|
g_iHostCom_tty_id = host_com_tty;
|
||||||
|
g_iTelemetry_Com_tty_id = telemetry_com_tty;
|
||||||
|
g_bKeepExintRuning = true;
|
||||||
pthread_create(&event_thread, NULL, exint_event_thread, NULL);
|
pthread_create(&event_thread, NULL, exint_event_thread, NULL);
|
||||||
pthread_create(&upperhost_thread, NULL, upper_host_com_thread, NULL);
|
pthread_create(&upperhost_thread, NULL, upper_host_com_thread, NULL);
|
||||||
pthread_create(&telemetry_thread, NULL, telemetry_host_com_thread, NULL);
|
pthread_create(&telemetry_thread, NULL, telemetry_host_com_thread, NULL);
|
||||||
|
@ -65,13 +76,13 @@ void exint_send(uint32_t type, size_t len, union PacketData data) {
|
||||||
exint_event(event_name, len, data_pointer);
|
exint_event(event_name, len, data_pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void extern_interface_deinit() {
|
void exint_finialize() {
|
||||||
g_bKeepEtifRuning = false;
|
g_bKeepExintRuning = false;
|
||||||
pthread_cancel(event_thread);
|
pthread_cancel(event_thread);
|
||||||
pthread_cancel(upperhost_thread);
|
pthread_cancel(upperhost_thread);
|
||||||
pthread_cancel(telemetry_thread);
|
pthread_cancel(telemetry_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_pack(uint32_t type, size_t len, union PacketData data) {
|
void exint_handle_pack(uint32_t type, size_t len, union PacketData data) {
|
||||||
et_callback(type, len, data);
|
et_callback(type, len, data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ volatile bool g_bNeedReboot = false;
|
||||||
volatile int32_t g_iMS2Reboot = 1000;
|
volatile int32_t g_iMS2Reboot = 1000;
|
||||||
|
|
||||||
void get_telemetry_data(TelemetryRequestData* data) {
|
void get_telemetry_data(TelemetryRequestData* data) {
|
||||||
handle_pack(ET_TYPE_TELEMETRY_REQUEST, sizeof(TelemetryRequestData), { .pd_pointer = data });
|
exint_handle_pack(ET_TYPE_TELEMETRY_REQUEST, sizeof(TelemetryRequestData), { .pd_pointer = data });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create a msg data for upper host telemetry*/
|
/* create a msg data for upper host telemetry*/
|
||||||
|
@ -189,19 +189,17 @@ void* telemetry_host_com_thread(void* path) {//Integrated Business Unit, telemet
|
||||||
const uint16_t address = COM_FRAME_ADDRESS_VOIX; // TODO
|
const uint16_t address = COM_FRAME_ADDRESS_VOIX; // TODO
|
||||||
size_t offset = 0, cached_size = 0;
|
size_t offset = 0, cached_size = 0;
|
||||||
uint8_t* buffer = new uint8_t[buffer_size];
|
uint8_t* buffer = new uint8_t[buffer_size];
|
||||||
uint8_t err_data[2];
|
|
||||||
uint64_t iTelemetryAnswerTimes = 0;
|
uint64_t iTelemetryAnswerTimes = 0;
|
||||||
void* pDataBlock;
|
|
||||||
int iRet;
|
|
||||||
TelemetryCommandInfo TeleCmdInfo2Send;
|
TelemetryCommandInfo TeleCmdInfo2Send;
|
||||||
TelemetryData TelemetryData2Send; // gejp 2024.10.03
|
TelemetryData TelemetryData2Send; // gejp 2024.10.03
|
||||||
|
|
||||||
memset(&TeleCmdInfo2Send, 0, sizeof(TelemetryCommandInfo));
|
memset(&TeleCmdInfo2Send, 0, sizeof(TelemetryCommandInfo));
|
||||||
|
|
||||||
while (g_bKeepEtifRuning) {
|
while (g_bKeepExintRuning) {
|
||||||
|
|
||||||
// if ( (iTelemetryAnswerTimes % 3 == 0) && g_bNeedReboot) system("reboot");
|
// if ( (iTelemetryAnswerTimes % 3 == 0) && g_bNeedReboot) system("reboot");
|
||||||
ComFrame* frame = ComFrame_ReceiveEx(tty_id, buffer, buffer_size, &offset, &cached_size, &g_bKeepEtifRuning, true);
|
ComFrame* frame = ComFrame_ReceiveEx(tty_id, buffer, buffer_size, &offset, &cached_size, &g_bKeepExintRuning, true);
|
||||||
|
if (frame == NULL) break;
|
||||||
//ComFrame* frame = ComFrame_ReceiveEx(tty_id, buffer, buffer_size, true);
|
//ComFrame* frame = ComFrame_ReceiveEx(tty_id, buffer, buffer_size, true);
|
||||||
if (ComFrame_Verify(frame, false)) {
|
if (ComFrame_Verify(frame, false)) {
|
||||||
if (SendTelemetryErrorMsg(tty_id, address, TELEMETRY_ERROR_CHECKSUM, true))
|
if (SendTelemetryErrorMsg(tty_id, address, TELEMETRY_ERROR_CHECKSUM, true))
|
||||||
|
@ -364,28 +362,22 @@ AlarmData* GetAlarmTextByCode(uint8_t cmd_code[], uint8_t iAlarmCode[4])
|
||||||
void* upper_host_com_thread(void* arg) {//hand-control display processing unit 手控显示处理单元
|
void* upper_host_com_thread(void* arg) {//hand-control display processing unit 手控显示处理单元
|
||||||
int tty_id = g_iHostCom_tty_id;
|
int tty_id = g_iHostCom_tty_id;
|
||||||
const uint16_t address = COM_FRAME_ADDRESS_VOIX;
|
const uint16_t address = COM_FRAME_ADDRESS_VOIX;
|
||||||
const uint32_t buffer_size = 1024 * 100; // TODO
|
const uint32_t buffer_size = 1024 * 100;
|
||||||
const int64_t iHostAudioBufferSize = 1024 * 1024;
|
const int64_t iHostAudioBufferSize = 1024 * 1024;
|
||||||
|
|
||||||
uint8_t* buffer = new uint8_t[buffer_size];
|
uint8_t* buffer = new uint8_t[buffer_size];
|
||||||
int64_t iEnqueueBytes;
|
|
||||||
bool bSucc;
|
|
||||||
char* pStrNotice;
|
|
||||||
size_t offset = 0, cached_size = 0;
|
size_t offset = 0, cached_size = 0;
|
||||||
uint64_t iTelemetryAnswerTimes;
|
|
||||||
int16_t* ptrProcHostAudio = (int16_t*)malloc(iHostAudioBufferSize);
|
int16_t* ptrProcHostAudio = (int16_t*)malloc(iHostAudioBufferSize);
|
||||||
int16_t* ptrProcHostAudioEnd = ptrProcHostAudio;
|
|
||||||
int ProcHostAudioLengthMS = 1000;
|
|
||||||
int iProcHostAudioSampleCnt;
|
|
||||||
timeval tLastTime, tCurTime;
|
timeval tLastTime, tCurTime;
|
||||||
|
|
||||||
TelemetryData4UpperHost UpperHostTeleData;
|
TelemetryData4UpperHost UpperHostTeleData;
|
||||||
|
|
||||||
while (g_bKeepEtifRuning) {
|
while (g_bKeepExintRuning) {
|
||||||
|
|
||||||
ComFrame* frame = ComFrame_ReceiveEx(tty_id, buffer, buffer_size, &offset, &cached_size, &g_bKeepEtifRuning, true);
|
ComFrame* frame = ComFrame_ReceiveEx(tty_id, buffer, buffer_size, &offset, &cached_size, &g_bKeepExintRuning, true);
|
||||||
//ComFrame* frame = ComFrame_ReceiveEx(tty_id, buffer, buffer_size, true);
|
//ComFrame* frame = ComFrame_ReceiveEx(tty_id, buffer, buffer_size, true);
|
||||||
//PrintFilePos(); printf("%04X \n", ComFrame_HEADER(frame)->type);
|
//PrintFilePos(); printf("%04X \n", ComFrame_HEADER(frame)->type);
|
||||||
|
if (frame == NULL) break;
|
||||||
switch (ComFrame_HEADER(frame)->type)
|
switch (ComFrame_HEADER(frame)->type)
|
||||||
{
|
{
|
||||||
case COM_FRAME_TYPE_COMMAND:
|
case COM_FRAME_TYPE_COMMAND:
|
||||||
|
@ -446,7 +438,7 @@ void* upper_host_com_thread(void* arg) {//hand-control display processing unit
|
||||||
else
|
else
|
||||||
//-------END 2024.10.23 noted by zgb
|
//-------END 2024.10.23 noted by zgb
|
||||||
*/
|
*/
|
||||||
handle_pack(ET_TYPE_COMMAND, 6, {.pd_pointer = frame->payload});
|
exint_handle_pack(ET_TYPE_COMMAND, 6, {.pd_pointer = frame->payload});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case COM_FRAME_TYPE_SPEECH_INJECTED:
|
case COM_FRAME_TYPE_SPEECH_INJECTED:
|
||||||
|
@ -462,7 +454,7 @@ void* upper_host_com_thread(void* arg) {//hand-control display processing unit
|
||||||
COM_FRAME_ADDRESS_VOIX,
|
COM_FRAME_ADDRESS_VOIX,
|
||||||
COM_FRAME_TYPE_SPEECH_INJECTED,
|
COM_FRAME_TYPE_SPEECH_INJECTED,
|
||||||
payload, 6, true);
|
payload, 6, true);
|
||||||
handle_pack(ET_TYPE_TEXT, 6, {.pd_pointer = f_data->payload});
|
exint_handle_pack(ET_TYPE_TEXT, 6, {.pd_pointer = f_data->payload});
|
||||||
if (ComFrame_Send(tty_id, f_data, true)) {
|
if (ComFrame_Send(tty_id, f_data, true)) {
|
||||||
PrintFilePos(); fprintf(stderr, "send telemetry data frame error: %s\n", strerror(errno));
|
PrintFilePos(); fprintf(stderr, "send telemetry data frame error: %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
@ -492,7 +484,7 @@ void* upper_host_com_thread(void* arg) {//hand-control display processing unit
|
||||||
PrintFilePos(); fprintf(stderr, " com frame interval %d\n", iIntervalTime);
|
PrintFilePos(); fprintf(stderr, " com frame interval %d\n", iIntervalTime);
|
||||||
tLastTime = tCurTime;
|
tLastTime = tCurTime;
|
||||||
|
|
||||||
handle_pack(ET_TYPE_AUDIO, ComFrame_PAYLOAD_LENGTH(frame), {.pd_pointer = frame->payload});
|
exint_handle_pack(ET_TYPE_AUDIO, ComFrame_PAYLOAD_LENGTH(frame), {.pd_pointer = frame->payload});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -558,7 +550,7 @@ void* upper_host_com_thread(void* arg) {//hand-control display processing unit
|
||||||
if(!alarm)
|
if(!alarm)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
handle_pack(ET_TYPE_TEXT, sizeof(alarm), {.pd_pointer = alarm});
|
exint_handle_pack(ET_TYPE_TEXT, sizeof(alarm), {.pd_pointer = alarm});
|
||||||
|
|
||||||
uint8_t payload[6] = {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55};
|
uint8_t payload[6] = {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55};
|
||||||
ComFrame* f_data = ComFrame_New(
|
ComFrame* f_data = ComFrame_New(
|
||||||
|
|
|
@ -222,8 +222,7 @@ LoggerOStream::LoggerOStream(Logger& logger, Logger::Level level)
|
||||||
|
|
||||||
LoggerOStream::LoggerOStream(LoggerOStream&& loggerStream)
|
LoggerOStream::LoggerOStream(LoggerOStream&& loggerStream)
|
||||||
: std::ostream(std::move(loggerStream)), _streamBuf(std::move(loggerStream._streamBuf))
|
: std::ostream(std::move(loggerStream)), _streamBuf(std::move(loggerStream._streamBuf))
|
||||||
{
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
LoggerStreamBuf::LoggerStreamBuf(Logger& logger, Logger::Level level)
|
LoggerStreamBuf::LoggerStreamBuf(Logger& logger, Logger::Level level)
|
||||||
: _logger(logger), _level(level) {}
|
: _logger(logger), _level(level) {}
|
||||||
|
|
|
@ -107,7 +107,7 @@ static __inline void print_separator_ex(char lc, const char* str, const char* co
|
||||||
static int collect_testcase() {
|
static int collect_testcase() {
|
||||||
for (int i = 0; i < test_case_total; ++i) {
|
for (int i = 0; i < test_case_total; ++i) {
|
||||||
puts(test_cases[i].name);
|
puts(test_cases[i].name);
|
||||||
putchar(' ');
|
// putchar(' ');
|
||||||
}
|
}
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
#include <vector>
|
||||||
|
#include <thread>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "exint/event.h"
|
||||||
|
#include "exint/detail.h"
|
||||||
|
#include "c_testcase.h"
|
||||||
|
|
||||||
|
static std::vector<int> g_vec;
|
||||||
|
|
||||||
|
ON_EVENT(test) {
|
||||||
|
int* arg = (int*)args;
|
||||||
|
g_vec.push_back(*arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
SETUP {
|
||||||
|
g_vec.clear();
|
||||||
|
g_bKeepExintRuning = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEARDOWN {
|
||||||
|
g_bKeepExintRuning = false;
|
||||||
|
exint_event_thread_exit();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE(test_unknow_event) {
|
||||||
|
exint_event("unknow_event", 0, NULL);
|
||||||
|
END_TEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE(test_event) {
|
||||||
|
int i = 1;
|
||||||
|
exint_event("test", sizeof(int), &i);
|
||||||
|
assert_eq(g_vec.size(), 1);
|
||||||
|
assert_eq(g_vec[0], i);
|
||||||
|
END_TEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE(test_event_thread) {
|
||||||
|
bool started = false;
|
||||||
|
std::thread t([&]() {
|
||||||
|
started = true;
|
||||||
|
exint_event_thread(NULL);
|
||||||
|
});
|
||||||
|
t.detach();
|
||||||
|
while (!started) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
}
|
||||||
|
int i = 2;
|
||||||
|
exint_event("test", sizeof(int), &i);
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
if (g_vec.size() != 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
assert_eq(g_vec[0], 2);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
assert(false);
|
||||||
|
|
||||||
|
end:
|
||||||
|
END_TEST;
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
#include <thread>
|
||||||
|
#include <pty.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "comframe.h"
|
||||||
|
#include "telemetry.h"
|
||||||
|
#include "dataqueue.hpp"
|
||||||
|
#include "exint/detail.h"
|
||||||
|
#include "c_testcase.h"
|
||||||
|
|
||||||
|
static int g_telemetry_request_count = 0;
|
||||||
|
static DataQueue<std::tuple<uint32_t, size_t, PacketData>> g_data_queue;
|
||||||
|
static int host_com_master_id;
|
||||||
|
static int telemetry_com_master_id;
|
||||||
|
|
||||||
|
void exint_data_callback(uint32_t type, size_t size, PacketData data) {
|
||||||
|
if (type == ET_TYPE_TELEMETRY_REQUEST) {
|
||||||
|
g_telemetry_request_count++;
|
||||||
|
memset(data.pd_pointer, 0, size);
|
||||||
|
((TelemetryRequestData*)data.pd_pointer)->app_ver_high = 1;
|
||||||
|
((TelemetryRequestData*)data.pd_pointer)->app_ver_low = 2;
|
||||||
|
} else {
|
||||||
|
g_data_queue.Push(std::make_tuple(type, size, data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SETUP {
|
||||||
|
int host_com_slave_id, telemetry_com_slave_id;
|
||||||
|
if (openpty(&host_com_master_id, &host_com_slave_id, NULL, NULL, NULL) < 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (openpty(&telemetry_com_master_id, &telemetry_com_slave_id, NULL, NULL, NULL) < 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
init_tty(host_com_master_id, 115200);
|
||||||
|
init_tty(telemetry_com_master_id, 115200);
|
||||||
|
// init_tty(host_com_slave_id, 115200);
|
||||||
|
// init_tty(telemetry_com_slave_id, 115200);
|
||||||
|
exint_init_from_tty(host_com_slave_id, telemetry_com_slave_id, exint_data_callback);
|
||||||
|
g_telemetry_request_count = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEARDOWN {
|
||||||
|
exint_finialize();
|
||||||
|
close(host_com_master_id);
|
||||||
|
close(telemetry_com_master_id);
|
||||||
|
g_data_queue.Clear();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE(test_init) {
|
||||||
|
assert(host_com_master_id);
|
||||||
|
assert(telemetry_com_master_id);
|
||||||
|
END_TEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE(test_host_telemetry) {
|
||||||
|
auto request_msg = NewTelemetryRequestMsg(COM_FRAME_ADDRESS_VOIX, true);
|
||||||
|
ComFrame_Send(telemetry_com_master_id, request_msg, true);
|
||||||
|
ComFrame_Del(request_msg);
|
||||||
|
|
||||||
|
bool timeout_flag = true;
|
||||||
|
std::thread([&]() {
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
|
timeout_flag = false;
|
||||||
|
}).detach();
|
||||||
|
|
||||||
|
size_t offset = 0;
|
||||||
|
size_t cached_size = 0;
|
||||||
|
auto telemetry_reply = ComFrame_ReceiveEx(telemetry_com_master_id, NULL, 100, &offset, &cached_size, &timeout_flag, true);
|
||||||
|
assert(telemetry_reply);
|
||||||
|
assert_eq(g_telemetry_request_count, 1);
|
||||||
|
|
||||||
|
TelemetryData* telemetry_data = (TelemetryData*)ComFrame_PAYLOAD(telemetry_reply);
|
||||||
|
assert_eq(ComFrame_TYPE(telemetry_reply), COM_FRAME_TYPE_TELEMETRY_ANSWER);
|
||||||
|
assert_eq(ComFrame_PAYLOAD_LENGTH(telemetry_reply), sizeof(TelemetryData));
|
||||||
|
assert_eq(telemetry_data->application_version_high, 1);
|
||||||
|
|
||||||
|
END_TEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE(test_send_command) {
|
||||||
|
ComFrame* command_frame = NULL;
|
||||||
|
bool timeout_flag = true;
|
||||||
|
std::thread([&]() {
|
||||||
|
size_t offset = 0;
|
||||||
|
size_t cached_size = 0;
|
||||||
|
command_frame = ComFrame_ReceiveEx(host_com_master_id, NULL, 100, &offset, &cached_size, &timeout_flag, true);
|
||||||
|
}).detach();
|
||||||
|
|
||||||
|
char command_data[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
|
||||||
|
exint_send(ET_TYPE_COMMAND, 6, { .pd_pointer = command_data });
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
if (command_frame) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
timeout_flag = false;
|
||||||
|
assert(command_frame);
|
||||||
|
assert_eq(ComFrame_TYPE(command_frame), COM_FRAME_TYPE_REQUEST);
|
||||||
|
assert_eq(ComFrame_PAYLOAD_LENGTH(command_frame), 6);
|
||||||
|
assert_eq(ComFrame_PAYLOAD(command_frame)[0], 0x00);
|
||||||
|
assert_eq(ComFrame_PAYLOAD(command_frame)[5], 0x05);
|
||||||
|
END_TEST;
|
||||||
|
}
|
|
@ -0,0 +1,132 @@
|
||||||
|
#include <sstream>
|
||||||
|
#include "c_testcase.h"
|
||||||
|
#include "logging/interface.h"
|
||||||
|
#include "logging/logger.hpp"
|
||||||
|
|
||||||
|
using namespace logging;
|
||||||
|
|
||||||
|
TEST_CASE(test_init) {
|
||||||
|
log_info("test_init before");
|
||||||
|
log_init(NULL);
|
||||||
|
assert_eq(log_level(), LOG_LEVEL_INFO);
|
||||||
|
log_info("test_init after");
|
||||||
|
|
||||||
|
log_debug("test_init debug");
|
||||||
|
log_warn("test_init warn");
|
||||||
|
log_error("test_init error");
|
||||||
|
log_fatal("test_init fatal");
|
||||||
|
|
||||||
|
log_init("debug");
|
||||||
|
assert_eq(log_level(), LOG_LEVEL_DEBUG);
|
||||||
|
log_warn_with_source("test_init warn with source");
|
||||||
|
log_error_from_errno("TestError");
|
||||||
|
END_TEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE(test_add_stream) {
|
||||||
|
std::stringstream ss;
|
||||||
|
log_init(NULL);
|
||||||
|
logging::global_logger->add_stream(ss);
|
||||||
|
|
||||||
|
log_info("test_stream");
|
||||||
|
auto s = ss.str();
|
||||||
|
assert_str_eq(s.c_str() + (s.length() - 19), "[INFO] test_stream\n");
|
||||||
|
ss.str("");
|
||||||
|
|
||||||
|
log_debug("test_stream debug");
|
||||||
|
s = ss.str();
|
||||||
|
assert_eq(s.length(), 0);
|
||||||
|
ss.str("");
|
||||||
|
|
||||||
|
log_set_level(LOG_LEVEL_DEBUG);
|
||||||
|
|
||||||
|
log_debug("test_stream debug");
|
||||||
|
s = ss.str();
|
||||||
|
assert_str_eq(s.c_str() + (s.length() - 26), "[DEBUG] test_stream debug\n");
|
||||||
|
ss.str("");
|
||||||
|
|
||||||
|
log_warn("test_stream warn");
|
||||||
|
s = ss.str();
|
||||||
|
assert_str_eq(s.c_str() + (s.length() - 24), "[WARN] test_stream warn\n");
|
||||||
|
ss.str("");
|
||||||
|
|
||||||
|
log_error("test_stream error");
|
||||||
|
s = ss.str();
|
||||||
|
assert_str_eq(s.c_str() + (s.length() - 26), "[ERROR] test_stream error\n");
|
||||||
|
ss.str("");
|
||||||
|
|
||||||
|
log_fatal("test_stream fatal");
|
||||||
|
s = ss.str();
|
||||||
|
assert_str_eq(s.c_str() + (s.length() - 26), "[FATAL] test_stream fatal\n");
|
||||||
|
ss.str("");
|
||||||
|
|
||||||
|
logging::global_logger->log<logging::Logger::Level::DEBUG>("test_stream debug");
|
||||||
|
s = ss.str();
|
||||||
|
assert_str_eq(s.c_str() + (s.length() - 26), "[DEBUG] test_stream debug\n");
|
||||||
|
|
||||||
|
END_TEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE(test_log_stream) {
|
||||||
|
log_init(NULL);
|
||||||
|
auto& logger = *logging::global_logger;
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
logger.add_stream(ss);
|
||||||
|
|
||||||
|
logger[LOG_LEVEL_INFO] << "test_log_stream" << std::endl;
|
||||||
|
auto s = ss.str();
|
||||||
|
assert_str_eq(s.c_str() + (s.length() - 23), "[INFO] test_log_stream\n");
|
||||||
|
ss.str("");
|
||||||
|
|
||||||
|
logger[LOG_LEVEL_DEBUG] << "test_log_stream debug" << std::endl;
|
||||||
|
s = ss.str();
|
||||||
|
assert_eq(s.length(), 0);
|
||||||
|
|
||||||
|
END_TEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE(test_sub_logger) {
|
||||||
|
log_init(NULL);
|
||||||
|
auto sublogger = get_logger("sublogger");
|
||||||
|
assert_eq(sublogger->level(), LogLevel::INFO);
|
||||||
|
assert_eq(sublogger->name(), "sublogger");
|
||||||
|
assert_eq(sublogger->parent(), logging::global_logger.get());
|
||||||
|
|
||||||
|
auto subsublogger = get_logger("sublogger::subsublogger");
|
||||||
|
assert_eq(subsublogger->level(), LogLevel::INFO);
|
||||||
|
assert_eq(subsublogger->name(), "sublogger::subsublogger");
|
||||||
|
assert_eq(subsublogger->parent(), sublogger);
|
||||||
|
|
||||||
|
auto sub1sub1logger = get_logger("sublogger1::subsublogger1");
|
||||||
|
assert_eq(sub1sub1logger->level(), LogLevel::INFO);
|
||||||
|
assert_eq(sub1sub1logger->name(), "sublogger1::subsublogger1");
|
||||||
|
auto sub1logger = get_logger("sublogger1");
|
||||||
|
assert_eq(sub1logger->level(), LogLevel::INFO);
|
||||||
|
assert_eq(sub1logger->name(), "sublogger1");
|
||||||
|
assert_eq(sub1logger->parent(), logging::global_logger.get());
|
||||||
|
assert_eq(sub1sub1logger->parent(), sub1logger);
|
||||||
|
|
||||||
|
auto root_logger = get_logger("");
|
||||||
|
assert_eq(root_logger, logging::global_logger.get());
|
||||||
|
auto root_logger1 = get_logger("::");
|
||||||
|
assert_eq(root_logger1, root_logger);
|
||||||
|
auto subsublogger1 = get_logger("sublogger::subsublogger");
|
||||||
|
assert_eq(subsublogger1, subsublogger);
|
||||||
|
auto subsublogger2 = get_logger("::sublogger::subsublogger");
|
||||||
|
assert_eq(subsublogger2, subsublogger);
|
||||||
|
auto subsublogger3 = get_logger("sublogger::subsublogger::");
|
||||||
|
assert_eq(subsublogger3, subsublogger);
|
||||||
|
auto subsublogger4 = get_logger("sublogger::::::subsublogger");
|
||||||
|
assert_eq(subsublogger4, subsublogger);
|
||||||
|
|
||||||
|
global_logger->set_level(LogLevel::DEBUG);
|
||||||
|
assert_eq(global_logger->level(), LogLevel::DEBUG);
|
||||||
|
assert_eq(sublogger->level(), LogLevel::DEBUG);
|
||||||
|
assert_eq(subsublogger->level(), LogLevel::DEBUG);
|
||||||
|
sublogger->set_level(LogLevel::WARN);
|
||||||
|
assert_eq(global_logger->level(), LogLevel::DEBUG);
|
||||||
|
assert_eq(sublogger->level(), LogLevel::WARN);
|
||||||
|
assert_eq(subsublogger->level(), LogLevel::WARN);
|
||||||
|
END_TEST;
|
||||||
|
}
|
|
@ -3,14 +3,14 @@
|
||||||
#include "c_testcase.h"
|
#include "c_testcase.h"
|
||||||
#include "dataqueue.hpp"
|
#include "dataqueue.hpp"
|
||||||
|
|
||||||
TEST_CASE(init) {
|
TEST_CASE(test_init) {
|
||||||
DataQueue<int> q;
|
DataQueue<int> q;
|
||||||
assert(q.Empty());
|
assert(q.Empty());
|
||||||
assert_eq(q.Size(), 0);
|
assert_eq(q.Size(), 0);
|
||||||
END_TEST;
|
END_TEST;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE(push) {
|
TEST_CASE(test_push) {
|
||||||
DataQueue<int> q;
|
DataQueue<int> q;
|
||||||
q.Push(10);
|
q.Push(10);
|
||||||
assert_eq(q.Size(), 1);
|
assert_eq(q.Size(), 1);
|
||||||
|
@ -18,7 +18,7 @@ TEST_CASE(push) {
|
||||||
END_TEST;
|
END_TEST;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE(pop) {
|
TEST_CASE(test_pop) {
|
||||||
DataQueue<int> q;
|
DataQueue<int> q;
|
||||||
std::thread t([&]() {
|
std::thread t([&]() {
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
|
@ -32,3 +32,23 @@ TEST_CASE(pop) {
|
||||||
t.join();
|
t.join();
|
||||||
END_TEST;
|
END_TEST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE(test_clear) {
|
||||||
|
DataQueue<int> q;
|
||||||
|
q.Push(10);
|
||||||
|
q.Clear();
|
||||||
|
assert(q.Empty());
|
||||||
|
|
||||||
|
std::thread t([&]() {
|
||||||
|
try {
|
||||||
|
q.Pop();
|
||||||
|
} catch (const QueueException&) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw std::runtime_error("QueueException not thrown");
|
||||||
|
});
|
||||||
|
usleep(100);
|
||||||
|
q.Clear();
|
||||||
|
t.join();
|
||||||
|
END_TEST;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue