Skip to content

Commit

Permalink
ci: Unit tests are now added. (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaskowicz1 authored Dec 26, 2023
1 parent 8da8759 commit c020fb9
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 30 deletions.
36 changes: 24 additions & 12 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,17 @@ jobs:
fail-fast: false # Don't fail everything if one fails. We want to test each OS/Compiler individually
matrix:
cfg:
- { arch: 'amd64', concurrency: 2, os: ubuntu-20.04, package: clang-10, cpp-version: clang++-10}
- { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: clang-11, cpp-version: clang++-11}
- { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: clang-12, cpp-version: clang++-12}
- { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: clang-13, cpp-version: clang++-13}
- { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: clang-14, cpp-version: clang++-14}
- { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: clang-15, cpp-version: clang++-15}
- { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: g++-9, cpp-version: g++-9}
- { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: g++-10, cpp-version: g++-10}
- { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: g++-11, cpp-version: g++-11}
- { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: g++-12, cpp-version: g++-12}
- { arch: 'amd64', concurrency: 2, os: ubuntu-20.04, package: g++-13, cpp-version: g++-13}
- { arch: 'amd64', concurrency: 2, os: ubuntu-20.04, package: clang-10, cpp-version: clang++-10, ctest: 'no', downloadcpp: 'yes'}
- { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: clang-11, cpp-version: clang++-11, ctest: 'no', downloadcpp: 'yes'}
- { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: clang-12, cpp-version: clang++-12, ctest: 'no', downloadcpp: 'yes'}
- { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: clang-13, cpp-version: clang++-13, ctest: 'no', downloadcpp: 'yes'}
- { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: clang-14, cpp-version: clang++-14, ctest: 'no', downloadcpp: 'yes'}
- { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: clang-15, cpp-version: clang++-15, ctest: 'no', downloadcpp: 'yes'}
- { arch: 'amd64', concurrency: 2, os: ubuntu-20.04, package: g++-9, cpp-version: g++-9, ctest: 'yes', downloadcpp: 'yes'}
- { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: g++-10, cpp-version: g++-10, ctest: 'no', downloadcpp: 'yes'}
- { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: g++-11, cpp-version: g++-11, ctest: 'no', downloadcpp: 'yes'}
- { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: g++-12, cpp-version: g++-12, ctest: 'no', downloadcpp: 'yes'}
- { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: g++-13, cpp-version: g++-13, ctest: 'no', downloadcpp: 'yes'}
steps:
- name: Harden Runner
uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
Expand All @@ -47,7 +47,11 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

- name: Install apt packages
run: sudo sed -i 's/azure\.//' /etc/apt/sources.list && sudo apt update && sudo apt-get install -y ${{ matrix.cfg.package }} pkg-config
run: sudo sed -i 's/azure\.//' /etc/apt/sources.list && sudo apt update && sudo apt-get install -y pkg-config

- name: Install C++ apt package
if: ${{ matrix.cfg.downloadcpp == 'yes' }}
run: sudo apt-get install -y ${{ matrix.cfg.package }}

- name: Generate CMake
run: cmake -B build
Expand All @@ -57,6 +61,14 @@ jobs:
- name: Build Project
run: cmake --build build -j${{ matrix.cfg.concurrency }}

- name: Run unit tests
if: ${{ matrix.cfg.ctest == 'yes' }}
run: cd build && ctest -VV
env:
RCON_TESTING_IP: ${{secrets.RCON_TESTING_IP}}
RCON_TESTING_PORT: ${{secrets.RCON_TESTING_PORT}}
RCON_TESTING_PASSWORD: ${{secrets.RCON_TESTING_PASSWORD}}

#- name: Package distributable
# if: ${{ matrix.cfg.cpack == 'yes' }}
# run: cd build && cpack --verbose
Expand Down
17 changes: 17 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
cmake_minimum_required(VERSION 3.10)

option(BUILD_TESTS "Build the test program" ON)

project(rconpp
VERSION 0.1.0
LANGUAGES CXX
Expand All @@ -19,3 +21,18 @@ set_target_properties(rconpp PROPERTIES
POSITION_INDEPENDENT_CODE true
LINKER_LANGUAGE CXX
)

if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif()

if(BUILD_TESTS)
add_executable(unittest "unittest/test.cpp")
target_compile_features(unittest PRIVATE cxx_std_17)
target_link_directories(unittest PRIVATE rconpp)
enable_testing()
add_test(
NAME unittest
COMMAND unittest
)
endif()
48 changes: 30 additions & 18 deletions include/rconpp/rcon.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,28 +131,32 @@ class utilities {

class rcon_client {
const std::string address{};
const uint16_t port{0};
const int port{0};
const std::string password{};
#ifdef _WIN32
SOCKET sock{INVALID_SOCKET};
#else
int sock{0};
#endif
bool connected{false};

std::vector<queued_request> requests_queued{};

std::thread queue_runner;

public:
bool connected{false};

/**
* @brief rcon constuctor. Initiates a connection to an RCON server with the parameters given.
*
* @param addr The IP Address (NOT domain) to connect to.
* @param _port The port to connect to.
* @param pass The password for the RCON server you are connecting to.
*
* @note This is a blocking call (done on purpose). It needs to wait to connect to the RCON server before anything else happens.
* It will timeout after 4 seconds if it can't connect.
*/
rcon_client(const std::string_view addr, const uint16_t _port, const std::string_view pass) : address(addr), port(_port), password(pass) {
rcon_client(const std::string_view addr, const int _port, const std::string_view pass) : address(addr), port(_port), password(pass) {

if(_port > 65535) {
std::cout << "Invalid port! The port can't exceed 65535!" << "\n";
Expand Down Expand Up @@ -223,6 +227,7 @@ class rcon_client {
* @param data Data to send to the server.
* @param id ID of the packet. Try to make sure you aren't sending multiple requests, at the same time, with the same ID as it may cause issues.
* @param type The type of packet to send.
* @param callback The callback function that will fire when the data is returned.
*
* @warning If you are expecting no response from the server, do NOT use the callback. You will halt the RCON process until the next received message (which will chain).
*/
Expand Down Expand Up @@ -367,9 +372,13 @@ class rcon_client {
}
}

std::string part(&packet_response.data[8], &packet_response.data[packet_response.size+1]);

if (packet_type == id) {
std::string part{};

if(packet_response.size > 10) {
part = std::string(&packet_response.data[8], &packet_response.data[packet_response.data.size()-1]);
}

return { part, packet_response.server_responded };
}
}
Expand All @@ -382,46 +391,49 @@ class rcon_client {
* @return A packet structure containing the length, size, data, and if server responded.
*/
packet read_packet() {
size_t packet_length = read_packet_length();
size_t packet_size = read_packet_size();

packet temp_packet{};
temp_packet.length = packet_length;
temp_packet.length = packet_size + 4;

if(packet_length > 0) {
temp_packet.size = packet_length - 4;
if(packet_size > 0) {
temp_packet.size = packet_size;
}

/*
* If the packet length is -1, the server didn't respond.
* If the packet length is 0, the server did respond but said nothing.
* If the packet size is -1, the server didn't respond.
* If the packet size is 0, the server did respond but said nothing.
*/
if (packet_length == -1) {
if (packet_size == -1) {
return temp_packet;
}
else if (packet_length == 0) {
else if (packet_size == 0) {
temp_packet.server_responded = true;
return temp_packet;
}

temp_packet.server_responded = true;

std::vector<char> buffer{};
buffer.resize(packet_length);
buffer.resize(temp_packet.length);

// Whilst we do technically read 4 more bytes than needed here, it's completely safe to do this.
recv(sock, buffer.data(), packet_length, 0);
/*
* Receiving by the length of the packet will give us 4 extra bytes, so, we do by size here.
* This is because read_packet_size() reads the first 4 bytes and discards them.
*/
recv(sock, buffer.data(), temp_packet.size, 0);

temp_packet.data = buffer;

return temp_packet;
}

int read_packet_length() {
int read_packet_size() {
std::vector<char> buffer{};
buffer.resize(4);

/*
* RCON gives the packet LENGTH in the first four (4) bytes of each packet.
* RCON gives the packet SIZE in the first four (4) bytes of each packet.
* We simply just want to read that and then return it.
*/
if (recv(sock, buffer.data(), 4, 0) == -1) {
Expand Down
21 changes: 21 additions & 0 deletions unittest/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include "../include/rconpp/rcon.h"

int main() {
if(!std::getenv("RCON_TESTING_IP") || !std::getenv("RCON_TESTING_PORT") || !std::getenv("RCON_TESTING_PASSWORD")) {
throw std::invalid_argument("Environment variables not set.");
}

rconpp::rcon_client client(std::getenv("RCON_TESTING_IP"), std::stoi(std::getenv("RCON_TESTING_PORT")), std::getenv("RCON_TESTING_PASSWORD"));

if(client.connected) {
rconpp::response res = client.send_data_sync("testing", 3, rconpp::data_type::SERVERDATA_EXECCOMMAND);

if(res.server_responded) {
std::cout << "Server responded!" << "\n";
} else {
std::cout << "No server response." << "\n";
}
} else {
std::cout << "No connection!" << "\n";
}
}

0 comments on commit c020fb9

Please sign in to comment.