diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml new file mode 100644 index 0000000..669811e --- /dev/null +++ b/.github/workflows/unit-tests.yml @@ -0,0 +1,42 @@ +name: unit-tests + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + build-and-test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install system deps + run: | + sudo apt-get update + sudo apt-get install -y build-essential cmake git python3 python3-pip + git clone https://github.com/google/googletest.git -b v1.14.0 && cd googletest && cmake . && make && sudo make install + - name: Create build directory + run: | + mkdir -p build + cd build + cmake -DBUILD_TESTING=ON .. + + - name: Build + run: | + cd build + cmake --build . -- -j$(nproc) + + - name: Run unit tests + run: | + cd build + ctest --output-on-failure -j2 + + - name: Upload ctest results (Testing directory) + if: always() + uses: actions/upload-artifact@v4 + with: + name: ctest-results + path: build/Testing diff --git a/src/serial.cpp b/src/serial.cpp index e54484f..2d96552 100644 --- a/src/serial.cpp +++ b/src/serial.cpp @@ -8,6 +8,7 @@ #include "libserial/serial.hpp" #include +#include namespace libserial { @@ -94,22 +95,21 @@ size_t Serial::readUntil(std::shared_ptr buffer, char terminator) { throw SerialException("Read timeout exceeded while waiting for terminator"); } - // Use select() to check if data is available with remaining timeout - fd_set read_fds; - FD_ZERO(&read_fds); - FD_SET(fd_serial_port_, &read_fds); + // Use poll() to check if data is available with remaining timeout. + // poll() does not have the FD_SETSIZE limitation that select() has + // and is more robust for larger file descriptor values. + struct pollfd pfd; + pfd.fd = fd_serial_port_; + pfd.events = POLLIN; - struct timeval timeout; int64_t remaining_timeout = read_timeout_ - elapsed; - timeout.tv_sec = remaining_timeout / 1000; - timeout.tv_usec = (remaining_timeout % 1000) * 1000; + int timeout_ms = static_cast(remaining_timeout); - int select_result = select(fd_serial_port_ + 1, &read_fds, nullptr, nullptr, &timeout); - - if (select_result < 0) { - throw SerialException("Error in select(): " + std::string(strerror(errno))); + int poll_result = poll(&pfd, 1, timeout_ms); + if (poll_result < 0) { + throw SerialException("Error in poll(): " + std::string(strerror(errno))); } - else if (select_result == 0) { + else if (poll_result == 0) { throw SerialException("Read timeout exceeded while waiting for data"); } }