Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ find_package(Threads REQUIRED)
# include top level include directory
include_directories(${PROJECT_SOURCE_DIR}/inc)

enable_testing()

add_subdirectory(3rd)
add_subdirectory(src)
add_subdirectory(test)
30 changes: 20 additions & 10 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,26 @@ set(PROJECT_HOMEPAGE "https://github.com/Ohto-Ai/CMakeProjectTemplate/")
string(TOUPPER ${PROJECT_NAME} PROJECT_NAME_VAR)
string(REPLACE "-" "_" PROJECT_NAME_VAR ${PROJECT_NAME_VAR})

# Add source files
# Build ssh_connection as a static library so tests can link against it
add_library(webssh_cpp_ssh_lib STATIC
ssh_connection/ssh_connection.cpp
)
target_include_directories(webssh_cpp_ssh_lib PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/inc
${PROJECT_BINARY_DIR}/generated/inc)
target_link_libraries(webssh_cpp_ssh_lib PUBLIC
Threads::Threads
$<$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>:OpenSSL::SSL>
$<$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>:OpenSSL::Crypto>
libssh2_static
$<$<NOT:$<PLATFORM_ID:Windows>>:atomic>
spdlog
$<$<PLATFORM_ID:Windows>:ws2_32>)

# Add source files for the main executable
set(SOURCES
main.cpp
ssh_connection/ssh_connection.cpp
)

# Build the executable
Expand All @@ -28,11 +44,5 @@ target_include_directories(${PROJECT_NAME} PRIVATE inc)
target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_BINARY_DIR}/generated/inc)

target_link_libraries(${PROJECT_NAME} PRIVATE
Threads::Threads
$<$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>:OpenSSL::SSL>
$<$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>:OpenSSL::Crypto>
hv_static
libssh2_static
$<$<NOT:$<PLATFORM_ID:Windows>>:atomic>
spdlog
$<$<PLATFORM_ID:Windows>:ws2_32>)
webssh_cpp_ssh_lib
hv_static)
12 changes: 12 additions & 0 deletions src/ssh_connection/ssh_connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -517,3 +517,15 @@ ohtoai::ssh::detail::ssh_channel_ptr ohtoai::ssh::detail::ssh_pty_connection_man
}
return iter->second.lock();
}

void ohtoai::ssh::detail::ssh_pty_connection_manager::close_channel(const detail::channel_id_t &id) {
auto iter = channels.find(id);
if (iter == channels.end()) {
return;
}
auto ch = iter->second.lock();
channels.erase(iter);
if (ch) {
ch->close();
}
}
10 changes: 4 additions & 6 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
cmake_minimum_required(VERSION 3.10)
project(test)
project(webssh_cpp_test)

enable_testing()

add_custom_target(${PROJECT_NAME} ALL)
add_custom_target(webssh_cpp_tests ALL)

# Add test files
file(GLOB test_files "*.test.cpp")
Expand All @@ -15,15 +13,15 @@ foreach (test_file ${test_files})
target_include_directories(${test_name} PRIVATE ${CMAKE_BINARY_DIR}/src/generated/inc)
target_link_libraries(${test_name} PRIVATE
Catch2 Catch2WithMain
Threads::Threads
webssh_cpp_ssh_lib
$<$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>:OpenSSL::SSL>
$<$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>:OpenSSL::Crypto>
spdlog $<$<BOOL:${MINGW}>:ws2_32>)
target_compile_options(${test_name}
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/bigobj>)
add_test(NAME ${test_name} COMMAND ${test_name})
add_dependencies(${PROJECT_NAME} ${test_name})
add_dependencies(webssh_cpp_tests ${test_name})
list(APPEND test_list ${test_name})
endforeach ()

Expand Down
159 changes: 159 additions & 0 deletions test/mini_buffer.test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#include <catch2/catch_test_macros.hpp>
#include <mini_buffer.hpp>
#include <cstring>

TEST_CASE("mini_buffer default constructor", "[mini_buffer]") {
ohtoai::mini_buffer buf;
REQUIRE(buf.data == nullptr);
REQUIRE(buf.size == 0);
REQUIRE(buf.capacity == 0);
}

TEST_CASE("mini_buffer capacity constructor", "[mini_buffer]") {
ohtoai::mini_buffer buf(128);
REQUIRE(buf.data != nullptr);
REQUIRE(buf.size == 0);
REQUIRE(buf.capacity == 128);
}

TEST_CASE("mini_buffer reserve", "[mini_buffer]") {
SECTION("reserve grows capacity") {
ohtoai::mini_buffer buf(64);
buf.reserve(256);
REQUIRE(buf.capacity == 256);
REQUIRE(buf.size == 0);
}

SECTION("reserve smaller than current capacity is a no-op") {
ohtoai::mini_buffer buf(256);
buf.reserve(64);
REQUIRE(buf.capacity == 256);
}

SECTION("reserve preserves existing data") {
ohtoai::mini_buffer buf(64);
const char *text = "hello";
std::memcpy(buf.data, text, 5);
buf.size = 5;
buf.reserve(256);
REQUIRE(std::memcmp(buf.data, text, 5) == 0);
}
}

TEST_CASE("mini_buffer resize", "[mini_buffer]") {
SECTION("resize within capacity only changes size") {
ohtoai::mini_buffer buf(128);
buf.resize(64);
REQUIRE(buf.size == 64);
REQUIRE(buf.capacity >= 64);
}

SECTION("resize larger than capacity grows the buffer") {
ohtoai::mini_buffer buf(64);
buf.resize(256);
REQUIRE(buf.size == 256);
REQUIRE(buf.capacity >= 256);
}

SECTION("resize to zero") {
ohtoai::mini_buffer buf(64);
buf.resize(0);
REQUIRE(buf.size == 0);
}
}

TEST_CASE("mini_buffer clear", "[mini_buffer]") {
ohtoai::mini_buffer buf(128);
buf.resize(64);
REQUIRE(buf.size == 64);

buf.clear();
REQUIRE(buf.size == 0);
REQUIRE(buf.capacity == 128);
REQUIRE(buf.data != nullptr);
}

TEST_CASE("mini_buffer append", "[mini_buffer]") {
SECTION("append raw data") {
ohtoai::mini_buffer buf(64);
const char *text = "hello";
buf.append(text, 5);
REQUIRE(buf.size == 5);
REQUIRE(std::memcmp(buf.data, text, 5) == 0);
}

SECTION("append std::string") {
ohtoai::mini_buffer buf(64);
std::string text = "world";
buf.append(text);
REQUIRE(buf.size == 5);
REQUIRE(std::memcmp(buf.data, text.data(), 5) == 0);
}

SECTION("multiple appends accumulate data") {
ohtoai::mini_buffer buf(64);
buf.append("foo", 3);
buf.append("bar", 3);
REQUIRE(buf.size == 6);
REQUIRE(std::memcmp(buf.data, "foobar", 6) == 0);
}

SECTION("append another mini_buffer") {
ohtoai::mini_buffer src(64);
src.append("data", 4);

ohtoai::mini_buffer dst(64);
dst.append(src);
REQUIRE(dst.size == 4);
REQUIRE(std::memcmp(dst.data, "data", 4) == 0);
}

SECTION("append triggers resize when exceeding capacity") {
ohtoai::mini_buffer buf(4);
buf.append("hello world!", 12);
REQUIRE(buf.size == 12);
REQUIRE(buf.capacity >= 12);
REQUIRE(std::memcmp(buf.data, "hello world!", 12) == 0);
}
}

TEST_CASE("mini_buffer move semantics", "[mini_buffer]") {
SECTION("move constructor transfers ownership") {
ohtoai::mini_buffer src(128);
src.append("test", 4);
char *original_data = src.data;

ohtoai::mini_buffer dst(std::move(src));
REQUIRE(dst.data == original_data);
REQUIRE(dst.size == 4);
REQUIRE(dst.capacity == 128);
REQUIRE(src.data == nullptr);
REQUIRE(src.size == 0);
REQUIRE(src.capacity == 0);
}

SECTION("move assignment transfers ownership") {
ohtoai::mini_buffer src(128);
src.append("test", 4);
char *original_data = src.data;

ohtoai::mini_buffer dst(64);
dst = std::move(src);
REQUIRE(dst.data == original_data);
REQUIRE(dst.size == 4);
REQUIRE(dst.capacity == 128);
REQUIRE(src.data == nullptr);
}
}

TEST_CASE("mini_buffer implicit char* conversion", "[mini_buffer]") {
ohtoai::mini_buffer buf(64);
buf.append("hello", 5);

char *ptr = buf;
REQUIRE(ptr == buf.data);

const ohtoai::mini_buffer &cbuf = buf;
const char *cptr = cbuf;
REQUIRE(cptr == cbuf.data);
}
Loading
Loading