Skip to content

Commit

Permalink
Feature: tools refactor
Browse files Browse the repository at this point in the history
- Enable io_uring by default if the library is found
- Simplify build scripts for Jammy build env
- Do not throw invalid_argument from getenv_port, return return 8080
  • Loading branch information
luketokheim authored Oct 25, 2022
1 parent 2853a7b commit 3fa90fc
Show file tree
Hide file tree
Showing 12 changed files with 73 additions and 53 deletions.
15 changes: 7 additions & 8 deletions .github/workflows/sanitizer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ jobs:
matrix:
sanitizer: ["address", "thread"]

env:
CC: clang-14
CXX: clang++-14

steps:
- uses: actions/checkout@v3

Expand All @@ -36,9 +40,6 @@ jobs:
# Download packages listed in our manifest. Generate toolchain file for
# CMake so that we can use find_package(...) to find deps
#
env:
CC: clang-14
CXX: clang++-14
run: >
install -d build
&& cd build
Expand All @@ -52,17 +53,15 @@ jobs:
run: >
cmake .. -GNinja
-DCMAKE_BUILD_TYPE=Debug
-DCMAKE_CXX_COMPILER=clang++-14
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
-DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
-DCMAKE_CXX_FLAGS="-fsanitize=${{ matrix.sanitizer }}"
-DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
- name: Build
#
# Build all enabled programs with the current configuration.
#
working-directory: build
run: cmake --build . --config Debug
run: cmake --build .

- name: Test
#
Expand All @@ -77,4 +76,4 @@ jobs:
env:
ASAN_OPTIONS: detect_leaks=1:color=always:alloc_dealloc_mismatch=0
TSAN_OPTIONS: halt_on_error=1:second_deadlock_stack=1
run: ctest --output-on-failure -C Debug
run: ctest --output-on-failure
10 changes: 7 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ endif()
find_package(Boost REQUIRED)
find_package(fmt REQUIRED)

target_link_libraries(httpmicroservice PUBLIC Boost::boost fmt::fmt)
target_link_libraries(
httpmicroservice
PUBLIC
Boost::boost
fmt::fmt)

option(
ENABLE_STANDALONE
Expand All @@ -39,8 +43,8 @@ endif()
find_library(URING_LIBRARY uring)
option(
ENABLE_IO_URING
"Enable the io_uring backend"
OFF)
"Enable the io_uring backend on Linux if liburing is found"
ON)
if(ENABLE_IO_URING AND URING_LIBRARY)
target_compile_definitions(
httpmicroservice
Expand Down
4 changes: 2 additions & 2 deletions examples/echo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ usrv::response get(const usrv::request& req)
}

// Route requests based on the method GET or POST
asio::awaitable<usrv::response> route(usrv::request req)
asio::awaitable<usrv::response> echo(usrv::request req)
{
switch (req.method()) {
case http::verb::get:
Expand All @@ -73,7 +73,7 @@ int main()

asio::io_context ioc;

usrv::async_run(ioc, port, route);
usrv::async_run(ioc, port, echo);

// SIGTERM is sent by Docker to ask us to stop (politely)
// SIGINT handles local Ctrl+C in a terminal
Expand Down
4 changes: 2 additions & 2 deletions include/httpmicroservice/service.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ auto make_co_handler(Executor ex, Handler handler)
}

/**
Read the PORT environment variable. Returns 8080 if it is not set. Throws
exception if the PORT variable is not an integer between 1024 and 65535.
Read the PORT environment variable. Returns 8080 if the PORT variable is not
set or is not an integer between 1024 and 65535.
Cloud Run sets the PORT environment variable.
https://cloud.google.com/run/docs/container-contract#port
Expand Down
11 changes: 5 additions & 6 deletions src/service.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
#include <httpmicroservice/service.hpp>

#include <charconv>
#include <exception>
#include <string_view>

namespace httpmicroservice {

int getenv_port()
{
constexpr auto kDefaultPort = 8080;
constexpr auto kMinPort = 1024;
constexpr auto kMaxPort = 65535;
constexpr int kDefaultPort = 8080;
constexpr int kMinPort = 1024;
constexpr int kMaxPort = 65535;

// Cloud Run sets the PORT environment variable
// https://cloud.google.com/run/docs/container-contract#port
Expand All @@ -25,12 +24,12 @@ int getenv_port()
const std::string_view str{env};
if (std::from_chars(str.data(), str.data() + str.size(), port).ec !=
std::errc{}) {
throw std::invalid_argument("PORT is not a number");
return kDefaultPort;
}
}

if ((port < kMinPort) || (port > kMaxPort)) {
throw std::invalid_argument("PORT is not between 1024 and 65535");
return kDefaultPort;
}

return port;
Expand Down
7 changes: 4 additions & 3 deletions tests/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ TEST_CASE("getenv_port", "[usrv]")
// back with std::getenv. This is intended for Docker Linux containers so
// leave Windows out.
constexpr auto kName = "PORT";
constexpr auto kPort = 8080;

REQUIRE(unsetenv(kName) == 0);

REQUIRE(usrv::getenv_port() == 8080);
REQUIRE(usrv::getenv_port() == kPort);

for (int port = 1024; port <= 65535; ++port) {
const auto str = std::to_string(port);
Expand All @@ -34,7 +35,7 @@ TEST_CASE("getenv_port", "[usrv]")
const auto str = std::to_string(port);
REQUIRE(setenv(kName, str.c_str(), 1) == 0);

REQUIRE_THROWS(usrv::getenv_port());
REQUIRE(usrv::getenv_port() == kPort);
}

constexpr std::array<const char*, 4> kBadNumber = {
Expand All @@ -43,7 +44,7 @@ TEST_CASE("getenv_port", "[usrv]")
for (auto str : kBadNumber) {
REQUIRE(setenv(kName, str, 1) == 0);

REQUIRE_THROWS(usrv::getenv_port());
REQUIRE(usrv::getenv_port() == kPort);
}
}

Expand Down
20 changes: 20 additions & 0 deletions tests/test_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,24 @@ TEST_CASE("make_co_handler", "[service]")
});

REQUIRE_THROWS(ioc.run());
}

TEST_CASE("async_run_context", "[service]")
{
namespace asio = boost::asio;
namespace http = boost::beast::http;
namespace usrv = httpmicroservice;

constexpr auto kPort = 8080;

auto handler = [](auto req) -> asio::awaitable<usrv::response> {
co_return usrv::response(http::status::ok, req.version());
};

// Run server in its own thread so we can call ctx.stop() from main
asio::io_context ctx;

auto server = std::async(std::launch::async, [&ctx, handler]() {
usrv::async_run(ctx, kPort, handler);
});
}
13 changes: 5 additions & 8 deletions tools/build_coverage.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,19 @@ export CXX=clang++-14

conan profile new coverage --detect
conan profile update settings.build_type=Debug coverage
conan profile update settings.compiler=clang coverage
conan profile update settings.compiler.version=14 coverage
conan profile update settings.compiler.libcxx=libc++ coverage
conan install .. --build=missing --profile=coverage

cmake -B . -S .. -GNinja \
cmake .. -GNinja \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_COMPILER=clang++-14 \
-DCMAKE_CXX_FLAGS="-fprofile-instr-generate -fcoverage-mapping" \
-DCMAKE_EXE_LINKER_FLAGS="-fprofile-instr-generate -fcoverage-mapping" \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake

cmake --build . --config Debug -j 8
cmake --build .

export LLVM_PROFILE_FILE=coverage.profraw
ctest -C Debug
ctest --output-on-failure
llvm-profdata-14 merge -sparse tests/coverage.profraw -o tests/coverage.profdata
llvm-cov-14 show ./tests/usrv-test -instr-profile=tests/coverage.profdata >coverage.txt
llvm-cov-14 show ./tests/usrv-test -format=html -instr-profile=tests/coverage.profdata ../src ../include >coverage.html
llvm-cov-14 report ./tests/usrv-test -instr-profile=tests/coverage.profdata ../src ../include
8 changes: 6 additions & 2 deletions tools/build_gcov.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#!/bin/sh

export CC=gcc
export CXX=g++

conan profile new gcov --detect
conan profile update settings.build_type=Debug gcov
conan install .. --build=missing --profile=gcov
Expand All @@ -14,6 +17,7 @@ cmake --build .

ctest --output-on-failure

# gcovr with jammy is buggy, use pip to get newer release
# gcovr bundled with jammy is buggy, use pip to get newer release
# pip install gcovr
python -m gcovr -r .. --filter ../include/ --filter ../src/ --html-details coverage.html
install -d coverage
python -m gcovr -r .. --filter ../include/ --filter ../src/ --html-details coverage/coverage.html
24 changes: 12 additions & 12 deletions tools/build_sanitizer.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@
export CC=clang-14
export CXX=clang++-14

export ASAN_OPTIONS=detect_leaks=1:color=always
export TSAN_OPTIONS=halt_on_error=1:second_deadlock_stack=1

conan profile new sanitizer --detect
conan profile update settings.build_type=Debug sanitizer
conan profile update settings.compiler=clang sanitizer
conan profile update settings.compiler.version=14 sanitizer
conan profile update settings.compiler.libcxx=libc++ sanitizer
conan install .. --build=missing --profile=sanitizer

cmake .. -GNinja \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_COMPILER=clang++-14 \
-DCMAKE_CXX_FLAGS="-fsanitize=address" \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake

# thread,signed-integer-overflow,null
for name in "address" "thread"
do
cmake .. -GNinja \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_FLAGS="-fsanitize=${name}" \
-DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake

cmake --build . --config Debug -j 8
cmake --build . --clean-first

ctest -C Debug
ctest --output-on-failure
done
4 changes: 2 additions & 2 deletions tools/build_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake

cmake --build . --config Release -j 8
cmake --build .

ctest -C Release
ctest --output-on-failure
6 changes: 1 addition & 5 deletions tools/build_tidy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,13 @@ export CXX=clang++-14

conan profile new tidy --detect
conan profile update settings.build_type=Release tidy
conan profile update settings.compiler=clang tidy
conan profile update settings.compiler.version=14 tidy
conan profile update settings.compiler.libcxx=libc++ tidy
conan install .. --build=missing --profile=tidy

cmake .. -GNinja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_COMPILER=clang++-14 \
-DCMAKE_CXX_CLANG_TIDY=clang-tidy-14 \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake \
-DBUILD_TESTING=OFF

cmake --build . --config Release -j 8
cmake --build .

0 comments on commit 3fa90fc

Please sign in to comment.