diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..276eaf0 --- /dev/null +++ b/.clang-format @@ -0,0 +1,3 @@ +BasedOnStyle: google +DerivePointerAlignment: false +IncludeBlocks: Preserve diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..ff355b9 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,77 @@ +name: CI + +'on': + pull_request: + push: + branches: + - develop + +env: + UBSAN_OPTIONS: print_stacktrace=1 + +jobs: + posix: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-20.04 + make: test-debug + info: g++-9 + test-debug + + - os: ubuntu-20.04 + make: test-release + info: g++-9 + test-release + + name: '${{matrix.os}}: ${{matrix.info}}' + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v2 + with: + submodules: true + + - name: Reuse ccache directory + uses: actions/cache@v2 + with: + path: ~/.ccache + key: '${{matrix.os}} ${{matrix.info}} ccache-dir ${{github.ref}} run-${{github.run_number}}' + restore-keys: | + ${{matrix.os}} ${{matrix.info}} ccache-dir ${{github.ref}} run-' + ${{matrix.os}} ${{matrix.info}} ccache- + + - name: Install packages + run: | + sudo apt update + sudo apt install --allow-downgrades -y pep8 $(cat third_party/userver/scripts/docs/en/deps/${{matrix.os}}.md | tr '\n' ' ') + + - name: Setup ccache + run: | + ccache -M 2.0GB + ccache -s + + - name: Run ${{matrix.make}} + run: | + make ${{matrix.make}} + + - name: Test install ${{matrix.make}} + if: matrix.make == 'test-release' + run: | + make dist-clean + make install PREFIX=`pwd`/local_installation/ + + - name: Test run after install + if: matrix.make == 'test-release' + run: | + ./local_installation/bin/service_template --config=./local_installation/etc/service_template/static_config.yaml & + + - name: Check work run service + if: matrix.make == 'test-release' + run: | + ps aux | grep service_template | grep config && curl http://localhost:8080/ping -v + + - name: Stop all + if: matrix.make == 'test-release' + run: | + killall service_template + diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml new file mode 100644 index 0000000..b1132dd --- /dev/null +++ b/.github/workflows/docker.yaml @@ -0,0 +1,41 @@ +name: Docker build + +'on': + pull_request: + push: + branches: + - master + - develop + - feature/** + +env: + CMAKE_OPTIONS: -DUserverGrpc_VERSION=1.51.0 + +jobs: + tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: true + + - name: Reuse ccache directory + uses: actions/cache@v2 + with: + path: .ccache + key: 'ccache-dir-${{github.ref}}_run-${{github.run_number}}' + restore-keys: | + ccache-dir-${{github.ref}}_run- + ccache- + + - name: Setup ccache + run: docker-compose run --rm service_template-container bash -c 'ccache -M 2.0GB && ccache -s' + + - name: Cmake + run: make docker-cmake-release + + - name: Build + run: make docker-build-release + + - name: Run tests + run: make docker-test-release diff --git a/.github/workflows/update-submodules.yaml b/.github/workflows/update-submodules.yaml new file mode 100644 index 0000000..9603da8 --- /dev/null +++ b/.github/workflows/update-submodules.yaml @@ -0,0 +1,22 @@ +name: Update submodules + +on: + workflow_dispatch: + +jobs: + update: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Update submodules + run: | + git submodule update --init + + - name: Commit & push changes + run: | + git config user.email "actions@github.com" + git config user.name "GitHub Actions - update submodules" + git commit -am "Update submodules" + git push diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b8a8c32 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +__pycache__ +build* +compile_commands.json +.cache/ +.idea/ +.vscode/ +.cores/ +.ccache/ +cmake-build-* +Testing/ +configs/static_config.yaml +.DS_Store diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..4d25646 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "third_party/userver"] + path = third_party/userver + url = https://github.com/userver-framework/userver.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..7dad5d3 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,55 @@ +cmake_minimum_required(VERSION 3.12) +project(service_template CXX) + +include(third_party/userver/cmake/SetupEnvironment.cmake) +include(GNUInstallDirs) + +add_subdirectory(third_party/userver) + + +# Common sources +add_library(${PROJECT_NAME}_objs OBJECT + src/hello.hpp + src/hello.cpp +) +target_link_libraries(${PROJECT_NAME}_objs PUBLIC userver-core) + + +# The Service +add_executable(${PROJECT_NAME} src/main.cpp) +target_link_libraries(${PROJECT_NAME} PRIVATE ${PROJECT_NAME}_objs) + + +# Unit Tests +add_executable(${PROJECT_NAME}_unittest + src/hello_test.cpp +) +target_link_libraries(${PROJECT_NAME}_unittest PRIVATE ${PROJECT_NAME}_objs userver-utest) +add_google_tests(${PROJECT_NAME}_unittest) + + +# Benchmarks +add_executable(${PROJECT_NAME}_benchmark + src/hello_benchmark.cpp +) +target_link_libraries(${PROJECT_NAME}_benchmark PRIVATE ${PROJECT_NAME}_objs userver-ubench) +add_google_benchmark_tests(${PROJECT_NAME}_benchmark) + +# Functional Tests +add_subdirectory(tests) + +if(DEFINED ENV{PREFIX}) + message(STATUS "Set install prefix: $ENV{PREFIX}") + file(TO_CMAKE_PATH "$ENV{PREFIX}" PREFIX_PATH) + set(CMAKE_INSTALL_PREFIX ${PREFIX_PATH}) +endif() + +set(CONFIG_VAR_PATH ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_SYSCONFDIR}/${PROJECT_NAME}/config_vars.yaml) +set(CONFIG_FALLBACK_PATH ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_SYSCONFDIR}/${PROJECT_NAME}/dynamic_config_fallback.json) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configs/static_config.yaml.in ${CMAKE_CURRENT_SOURCE_DIR}/configs/static_config.yaml) + +FILE(GLOB CONFIGS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/configs/*.yaml ${CMAKE_CURRENT_SOURCE_DIR}/configs/*.json) + +install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${PROJECT_NAME}) +install(FILES ${CONFIGS_FILES} DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/${PROJECT_NAME} COMPONENT ${PROJECT_NAME}) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e6a9684 --- /dev/null +++ b/Makefile @@ -0,0 +1,96 @@ +CMAKE_COMMON_FLAGS ?= -DCMAKE_EXPORT_COMPILE_COMMANDS=ON +CMAKE_DEBUG_FLAGS ?= -DUSERVER_SANITIZE='addr ub' +CMAKE_RELEASE_FLAGS ?= +CMAKE_OS_FLAGS ?= -DUSERVER_FEATURE_CRYPTOPP_BLAKE2=0 -DUSERVER_FEATURE_REDIS_HI_MALLOC=1 +NPROCS ?= $(shell nproc) +CLANG_FORMAT ?= clang-format + +# NOTE: use Makefile.local for customization +-include Makefile.local + +.PHONY: all +all: test-debug test-release + +# Debug cmake configuration +build_debug/Makefile: + @git submodule update --init + @mkdir -p build_debug + @cd build_debug && \ + cmake -DCMAKE_BUILD_TYPE=Debug $(CMAKE_COMMON_FLAGS) $(CMAKE_DEBUG_FLAGS) $(CMAKE_OS_FLAGS) $(CMAKE_OPTIONS) .. + +# Release cmake configuration +build_release/Makefile: + @git submodule update --init + @mkdir -p build_release + @cd build_release && \ + cmake -DCMAKE_BUILD_TYPE=Release $(CMAKE_COMMON_FLAGS) $(CMAKE_RELEASE_FLAGS) $(CMAKE_OS_FLAGS) $(CMAKE_OPTIONS) .. + +# Run cmake +.PHONY: cmake-debug cmake-release +cmake-debug cmake-release: cmake-%: build_%/Makefile + +# Build using cmake +.PHONY: build-debug build-release +build-debug build-release: build-%: cmake-% + @cmake --build build_$* -j $(NPROCS) --target service_template + +# Test +.PHONY: test-debug test-release +test-debug test-release: test-%: build-% + @cmake --build build_$* -j $(NPROCS) --target service_template_unittest + @cmake --build build_$* -j $(NPROCS) --target service_template_benchmark + @cd build_$* && ((test -t 1 && GTEST_COLOR=1 PYTEST_ADDOPTS="--color=yes" ctest -V) || ctest -V) + @pep8 tests + +# Start the service (via testsuite service runner) +.PHONY: service-start-debug service-start-release +service-start-debug service-start-release: service-start-%: build-% + @cd ./build_$* && $(MAKE) start-service_template + +# Cleanup data +.PHONY: clean-debug clean-release +clean-debug clean-release: clean-%: + cd build_$* && $(MAKE) clean + +.PHONY: dist-clean +dist-clean: + @rm -rf build_* + @rm -f ./configs/static_config.yaml + @rm -rf tests/__pycache__/ + @rm -rf tests/.pytest_cache/ + +# Install +.PHONY: install-debug install-release +install-debug install-release: install-%: build-% + @cd build_$* && \ + cmake --install . -v --component service_template + +.PHONY: install +install: install-release + +# Format the sources +.PHONY: format +format: + @find src -name '*pp' -type f | xargs $(CLANG_FORMAT) -i + @find tests -name '*.py' -type f | xargs autopep8 -i + +# Internal hidden targets that are used only in docker environment +.PHONY: --in-docker-start-debug --in-docker-start-release +--in-docker-start-debug --in-docker-start-release: --in-docker-start-%: install-% + @/home/user/.local/bin/service_template \ + --config /home/user/.local/etc/service_template/static_config.yaml + +# Build and run service in docker environment +.PHONY: docker-start-service-debug docker-start-service-release +docker-start-service-debug docker-start-service-release: docker-start-service-%: + @docker-compose run -p 8080:8080 --rm service_template-container $(MAKE) -- --in-docker-start-$* + +# Start specific target in docker environment +.PHONY: docker-cmake-debug docker-build-debug docker-test-debug docker-clean-debug docker-install-debug docker-cmake-release docker-build-release docker-test-release docker-clean-release docker-install-release +docker-cmake-debug docker-build-debug docker-test-debug docker-clean-debug docker-install-debug docker-cmake-release docker-build-release docker-test-release docker-clean-release docker-install-release: docker-%: + docker-compose run --rm service_template-container $(MAKE) $* + +# Stop docker container and cleanup data +.PHONY: docker-clean-data +docker-clean-data: + @docker-compose down -v diff --git a/Makefile.local b/Makefile.local new file mode 100644 index 0000000..5e40df6 --- /dev/null +++ b/Makefile.local @@ -0,0 +1 @@ +CMAKE_COMMON_FLAGS += -DUSERVER_FEATURE_CRYPTOPP_BLAKE=0 -DUSERVER_FEATURE_GRPC_CHANNELZ=0 diff --git a/README.md b/README.md new file mode 100644 index 0000000..f2e174d --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ +# service_template + +Template of a C++ service that uses [userver framework](https://github.com/userver-framework/userver). + + +## Download and Build + +To create your own userver-based service follow the following steps: + +1. Press the green "Use this template button" at the top of this github page +2. Clone the service `git clone your-service-repo && cd your-service-repo && git submodule update --init` +3. Give a proper name to your service and replace all the occurences of "service_template" string with that name +4. Feel free to tweak, adjust or fully rewrite the source code of your service. + + +## Makefile + +Makefile contains typicaly useful targets for development: + +* `make build-debug` - debug build of the service with all the assertions and sanitizers enabled +* `make build-release` - release build of the service with LTO +* `make test-debug` - does a `make build-debug` and runs all the tests on the result +* `make test-release` - does a `make build-release` and runs all the tests on the result +* `make service-start-debug` - builds the service in debug mode and starts it +* `make service-start-release` - builds the service in release mode and starts it +* `make` or `make all` - builds and runs all the tests in release and debug modes +* `make format` - autoformat all the C++ and Python sources +* `make clean-` - cleans the object files +* `make dist-clean` - clean all, including the CMake cached configurations +* `make install` - does a `make build-release` and run install in directory set in environment `PREFIX` +* `make install-debug` - does a `make build-debug` and runs install in directory set in environment `PREFIX` +* `make docker-COMMAND` - run `make COMMAND` in docker environment +* `make docker-build-debug` - debug build of the service with all the assertions and sanitizers enabled in docker environment +* `make docker-test-debug` - does a `make build-debug` and runs all the tests on the result in docker environment +* `make docker-start-service-release` - does a `make install-release` and runs service in docker environment +* `make docker-start-service-debug` - does a `make install-debug` and runs service in docker environment +* `make docker-clean-data` - stop docker containers + +Edit `Makefile.local` to change the default configuration and build options. + + +## License + +The original template is distributed under the [Apache-2.0 License](https://github.com/userver-framework/userver/blob/develop/LICENSE) +and [CLA](https://github.com/userver-framework/userver/blob/develop/CONTRIBUTING.md). Services based on the template may change +the license and CLA. diff --git a/configs/config_vars.yaml b/configs/config_vars.yaml new file mode 100644 index 0000000..a7ec8b1 --- /dev/null +++ b/configs/config_vars.yaml @@ -0,0 +1,7 @@ +worker-threads: 4 +worker-fs-threads: 2 +logger-level: debug + +is_testing: false + +server-port: 8080 diff --git a/configs/config_vars_testing.yaml b/configs/config_vars_testing.yaml new file mode 100644 index 0000000..828e658 --- /dev/null +++ b/configs/config_vars_testing.yaml @@ -0,0 +1,7 @@ +worker-threads: 4 +worker-fs-threads: 2 +logger-level: debug + +is_testing: true + +server-port: 8080 diff --git a/configs/dynamic_config_fallback.json b/configs/dynamic_config_fallback.json new file mode 100644 index 0000000..bcac370 --- /dev/null +++ b/configs/dynamic_config_fallback.json @@ -0,0 +1,41 @@ +{ + "USERVER_CACHES": {}, + "USERVER_CANCEL_HANDLE_REQUEST_BY_DEADLINE": false, + "USERVER_CHECK_AUTH_IN_HANDLERS": false, + "USERVER_DUMPS": {}, + "USERVER_HTTP_PROXY": "", + "USERVER_HANDLER_STREAM_API_ENABLED": false, + "USERVER_LOG_REQUEST": true, + "USERVER_LOG_REQUEST_HEADERS": false, + "USERVER_LRU_CACHES": {}, + "USERVER_RPS_CCONTROL_CUSTOM_STATUS": {}, + "USERVER_TASK_PROCESSOR_PROFILER_DEBUG": {}, + "HTTP_CLIENT_CONNECTION_POOL_SIZE": 1000, + "HTTP_CLIENT_CONNECT_THROTTLE": { + "http-limit": 6000, + "http-per-second": 1500, + "https-limit": 100, + "https-per-second": 25, + "per-host-limit": 3000, + "per-host-per-second": 500 + }, + "HTTP_CLIENT_ENFORCE_TASK_DEADLINE": { + "cancel-request": false, + "update-timeout": false + }, + "BAGGAGE_SETTINGS": { + "allowed_keys": [] + }, + "USERVER_BAGGAGE_ENABLED": false, + "USERVER_TASK_PROCESSOR_QOS": { + "default-service": { + "default-task-processor": { + "wait_queue_overload": { + "action": "ignore", + "length_limit": 5000, + "time_limit_us": 3000 + } + } + } + } +} diff --git a/configs/static_config.yaml.in b/configs/static_config.yaml.in new file mode 100644 index 0000000..83e5197 --- /dev/null +++ b/configs/static_config.yaml.in @@ -0,0 +1,66 @@ +# yaml + +config_vars: @CONFIG_VAR_PATH@ + +components_manager: + coro_pool: + initial_size: 500 # Preallocate 500 coroutines at startup. + max_size: 1000 # Do not keep more than 1000 preallocated coroutines. + + task_processors: # Task processor is an executor for coroutine tasks + + main-task-processor: # Make a task processor for CPU-bound couroutine tasks. + worker_threads: $worker-threads # Process tasks in 4 threads. + thread_name: main-worker # OS will show the threads of this task processor with 'main-worker' prefix. + + fs-task-processor: # Make a separate task processor for filesystem bound tasks. + thread_name: fs-worker + worker_threads: $worker-fs-threads + + default_task_processor: main-task-processor + + components: # Configuring components that were registered via component_list + server: + listener: # configuring the main listening socket... + port: $server-port # ...to listen on this port and... + task_processor: main-task-processor # ...process incoming requests on this task processor. + logging: + fs-task-processor: fs-task-processor + loggers: + default: + file_path: '@stderr' + level: $logger-level + overflow_behavior: discard # Drop logs if the system is too busy to write them down. + + tracer: # Component that helps to trace execution times and requests in logs. + service-name: service_template # "You know. You all know exactly who I am. Say my name. " (c) + + dynamic-config: # Dynamic config storage options, do nothing + fs-cache-path: '' + dynamic-config-fallbacks: # Load options from file and push them into the dynamic config storage. + fallback-path: @CONFIG_FALLBACK_PATH@ + testsuite-support: {} + + http-client: + load-enabled: $is_testing + fs-task-processor: fs-task-processor + + dns-client: + fs-task-processor: fs-task-processor + + tests-control: + load-enabled: $is_testing + path: /tests/{action} + method: POST + task_processor: main-task-processor + handler-ping: + path: /ping + method: GET + task_processor: main-task-processor + throttling_enabled: false + url_trailing_slash: strict-match + + handler-hello: # Finally! Our handler. + path: /hello # Registering handler by URL '/hello'. + method: GET,POST # It will only reply to GET (HEAD) and POST requests. + task_processor: main-task-processor # Run it on CPU bound task processor diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..e0ab9c7 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,28 @@ +version: "2.3" + +services: + service_template-container: + image: ghcr.io/userver-framework/ubuntu-userver-build-base:v1 + privileged: true + network_mode: bridge + environment: + - PREFIX=${PREFIX:-~/.local} + - CC + - CCACHE_DIR=/service_template/.ccache + - CCACHE_HASHDIR + - CCACHE_NOHASHDIR + - CCACHE_PREFIX + - CCACHE_SIZE + - CMAKE_OPTS + - CORES_DIR=/cores + - CXX + - MAKE_OPTS + - CMAKE_OPTIONS + volumes: + - .:/service_template:rw + - ./third_party/userver/tools/docker:/tools:ro + ports: + - 8080:8080 + working_dir: /service_template + entrypoint: + - /tools/run_as_user.sh diff --git a/src/hello.cpp b/src/hello.cpp new file mode 100644 index 0000000..d61e628 --- /dev/null +++ b/src/hello.cpp @@ -0,0 +1,38 @@ +#include "hello.hpp" + +#include + +#include + +namespace service_template { + +namespace { + +class Hello final : public userver::server::handlers::HttpHandlerBase { +public: + static constexpr std::string_view kName = "handler-hello"; + + using HttpHandlerBase::HttpHandlerBase; + + std::string HandleRequestThrow( + const userver::server::http::HttpRequest &request, + userver::server::request::RequestContext &) const override { + return service_template::SayHelloTo(request.GetArg("name")); + } +}; + +} // namespace + +std::string SayHelloTo(std::string_view name) { + if (name.empty()) { + name = "unknown user"; + } + + return fmt::format("Hello, {}!\n", name); +} + +void AppendHello(userver::components::ComponentList &component_list) { + component_list.Append(); +} + +} // namespace service_template diff --git a/src/hello.hpp b/src/hello.hpp new file mode 100644 index 0000000..a438f8b --- /dev/null +++ b/src/hello.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +#include + +namespace service_template { + +std::string SayHelloTo(std::string_view name); + +void AppendHello(userver::components::ComponentList &component_list); + +} // namespace service_template diff --git a/src/hello_benchmark.cpp b/src/hello_benchmark.cpp new file mode 100644 index 0000000..528d577 --- /dev/null +++ b/src/hello_benchmark.cpp @@ -0,0 +1,23 @@ +#include "hello.hpp" + +#include // for std::uint64_t +#include // for std::size +#include + +#include +#include + +void HelloBenchmark(benchmark::State& state) { + userver::engine::RunStandalone([&] { + constexpr std::string_view kNames[] = {"userver", "is", "awesome", "!"}; + std::uint64_t i = 0; + + for (auto _ : state) { + const auto name = kNames[i++ % std::size(kNames)]; + auto result = service_template::SayHelloTo(name); + benchmark::DoNotOptimize(result); + } + }); +} + +BENCHMARK(HelloBenchmark); diff --git a/src/hello_test.cpp b/src/hello_test.cpp new file mode 100644 index 0000000..68186df --- /dev/null +++ b/src/hello_test.cpp @@ -0,0 +1,8 @@ +#include "hello.hpp" + +#include + +UTEST(SayHelloTo, Basic) { + EXPECT_EQ(service_template::SayHelloTo("Developer"), "Hello, Developer!\n"); + EXPECT_EQ(service_template::SayHelloTo({}), "Hello, unknown user!\n"); +} diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..b8b4166 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "hello.hpp" + +int main(int argc, char* argv[]) { + auto component_list = userver::components::MinimalServerComponentList() + .Append() + .Append() + .Append() + .Append() + .Append(); + + service_template::AppendHello(component_list); + + return userver::utils::DaemonMain(argc, argv, component_list); +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..ddefe49 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,19 @@ +include(UserverTestsuite) + +set(CONFIG_VARS_PATH "${CMAKE_SOURCE_DIR}/configs/config_vars_testing.yaml") +if (EXISTS "${CONFIG_VARS_PATH}") + set(PYTEST_ARGS_CONFIG_VARS "--service-config-vars=${CONFIG_VARS_PATH}") +else() + set(PYTEST_ARGS_CONFIG_VARS "") +endif() + +userver_testsuite_add( + SERVICE_TARGET service_template + REQUIREMENTS ${CMAKE_CURRENT_SOURCE_DIR}/requirements.txt + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + PYTEST_ARGS + --service-config=${CMAKE_SOURCE_DIR}/configs/static_config.yaml + --service-binary=${CMAKE_BINARY_DIR}/service_template + --config-fallback=${CMAKE_SOURCE_DIR}/configs/dynamic_config_fallback.json + ${PYTEST_ARGS_CONFIG_VARS} +) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..699ab94 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1 @@ +pytest_plugins = ['pytest_userver.plugins.core'] diff --git a/tests/pytest.ini b/tests/pytest.ini new file mode 100644 index 0000000..c64b29b --- /dev/null +++ b/tests/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +asyncio_mode = auto +log_level = debug diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 0000000..9a64ad4 --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1 @@ +yandex-taxi-testsuite >= 0.1.7.2 diff --git a/tests/test_basic.py b/tests/test_basic.py new file mode 100644 index 0000000..452e737 --- /dev/null +++ b/tests/test_basic.py @@ -0,0 +1,5 @@ +# Start via `make test-debug` or `make test-release` +async def test_basic(service_client): + response = await service_client.post('/hello', params={'name': 'Tester'}) + assert response.status == 200 + assert response.text == 'Hello, Tester!\n' diff --git a/third_party/userver b/third_party/userver new file mode 160000 index 0000000..ef6cd42 --- /dev/null +++ b/third_party/userver @@ -0,0 +1 @@ +Subproject commit ef6cd42b3fd530b97c609ad5c5487924632b855c