Skip to content
Merged
6 changes: 1 addition & 5 deletions HACKING.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,4 @@ variable. -->

### conan

If you are going to build/run grpc/sfml related parts of code, then you can use conan to install all required dependecies. Install conan and just call cmd
```cmd
conan install . --output-folder=build --build=missing -s compiler.cppstd=gnu20 -c tools.system.package_manager:mode=install -c tools.system.package_manager:sudo=True --settings=build_type=Release
```
or if your cmake version is >= 3.24, then cmake would do it by itself if you set variable `RPP_USE_CONAN`.
if your cmake version is >= 3.24, you can use conan to install RPP's dependencies. To use it your Cmake preset should be inherited from `use-conan`. CMake would configure conan properly.
2 changes: 2 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ DEALINGS IN THE SOFTWARE.
ReactivePlusPlus library uses:
- [PVS-Studio](https://pvs-studio.com/pvs-studio/?utm_source=website&utm_medium=github&utm_campaign=open_source) - static analyzer for C, C++, C#, and Java code.
- [snitch](https://github.com/cschreib/snitch) for unit testing only, fetched automatically in case of `RPP_BUILD_TESTS` enabled
- [trompeloeil](https://github.com/rollbear/trompeloeil) for mocking in unit testing only, fetched automatically in case of `RPP_BUILD_TESTS` enabled
- [nanobench](https://github.com/martinus/nanobench) for benchmarking only, fetched automatically in case of `RPP_BUILD_BENCHMARKS` enabled
- [RxCpp](https://github.com/ReactiveX/RxCpp) only for comparison of performance between RPP and RxCpp in CI benchmarks. Used as cmake dependency under option
- [reactivex.io](https://reactivex.io) as source for insipration and definition of entities used in RPP. Some comments used in RPP source code taken from [reactivex.io](https://reactivex.io)
- [rxmarbles python](https://pypi.org/project/rxmarbles/) as generator of marbles graphs in doxygen documentation
Expand Down
8 changes: 6 additions & 2 deletions cmake/dependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,23 @@ macro(rpp_fetch_library_extended NAME URL TAG TARGET_NAME)
endmacro()

macro(rpp_fetch_library NAME URL TAG)
rpp_fetch_library_extended(${NAME} ${URL} ${TAG} ${NAME})
find_package(${NAME} QUIET)
if (NOT ${NAME}_FOUND)
message("-- RPP: Fetching ${NAME}...")
rpp_fetch_library_extended(${NAME} ${URL} ${TAG} ${NAME})
endif()
endmacro()

# ==================== RXCPP =======================
if (RPP_BUILD_RXCPP AND RPP_BUILD_BENCHMARKS)
set(RXCPP_DISABLE_TESTS_AND_EXAMPLES 1)

rpp_fetch_library(rxcpp https://github.com/ReactiveX/RxCpp.git origin/main)
endif()

# ===================== Snitch ===================
if (RPP_BUILD_TESTS)
rpp_fetch_library(snitch https://github.com/cschreib/snitch.git main)
rpp_fetch_library(trompeloeil https://github.com/rollbear/trompeloeil.git main)
endif()


Expand Down
1 change: 1 addition & 0 deletions cmake/dev-mode.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
if(POLICY CMP0091)
cmake_policy(SET CMP0091 NEW)
endif()

if(POLICY CMP0144)
cmake_policy(SET CMP0144 NEW)
endif()
12 changes: 12 additions & 0 deletions cmake/variables.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,18 @@ if (RPP_DEVELOPER_MODE)
option(RPP_ENABLE_COVERAGE "Enable coverage support separate from CTest's" OFF)
option(RPP_BUILD_RXCPP "Build RxCpp to compare results with it." OFF)

if (DEFINED CONAN_ARGS)
if (RPP_BUILD_TESTS)
set(CONAN_ARGS "${CONAN_ARGS};-o rpp/*:with_tests=True")
endif()
if (RPP_BUILD_SFML_CODE)
set(CONAN_ARGS "${CONAN_ARGS};-o rpp/*:with_sfml=True")
endif()
if (RPP_BUILD_BENCHMARKS)
set(CONAN_ARGS "${CONAN_ARGS};-o rpp/*:with_benchmarks=True")
endif()
endif()

if(RPP_ENABLE_COVERAGE)
include(cmake/coverage.cmake)
endif()
Expand Down
39 changes: 34 additions & 5 deletions conanfile.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,40 @@
from conan import ConanFile

class Config(ConanFile):
class RppConan(ConanFile):
name = "rpp"
settings = "os", "compiler", "build_type", "arch"
generators = "CMakeDeps", "CMakeToolchain"

options = {
"with_grpc" : [False, True],
"with_sfml" : [False, True],
"with_tests" : [False, True],
"with_cmake" : [False, True],
"with_benchmarks" : [False, True]
}
default_options = {
"with_grpc" : False,
"with_sfml" : False,
"with_tests": False,
"with_cmake": False,
"with_benchmarks" : False
}

def requirements(self):
self.requires("sfml/2.6.1")
# self.requires("grpc/1.54.3", transitive_libs=True, transitive_headers=True)
# self.requires("protobuf/3.21.12")
# self.requires("libmount/2.39", override=True)
if self.options.with_tests:
self.requires("trompeloeil/47")
self.requires("snitch/1.2.3")

if self.options.with_benchmarks:
self.requires("nanobench/4.3.11")

if self.options.with_sfml:
self.requires("sfml/2.6.1", options={"audio": False})

# if self.options.with_grpc:
# self.requires("grpc/1.54.3", transitive_libs=True, transitive_headers=True)
# self.requires("protobuf/3.21.12")
# self.requires("libmount/2.39", override=True)

if self.options.with_cmake:
self.tool_requires("cmake/3.29.3")
2 changes: 1 addition & 1 deletion src/benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ set(TARGET benchmarks)

add_executable(${TARGET} benchmarks.cpp)

target_link_libraries(${TARGET} PRIVATE rpp nanobench)
target_link_libraries(${TARGET} PRIVATE rpp nanobench::nanobench)
if (RPP_BUILD_RXCPP)
target_link_libraries(${TARGET} PRIVATE rxcpp)
target_compile_definitions(${TARGET} PRIVATE RPP_BUILD_RXCPP)
Expand Down
1 change: 1 addition & 0 deletions src/benchmarks/benchmarks.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#define ANKERL_NANOBENCH_IMPLEMENT
#include <nanobench.h>

#include <rpp/rpp.hpp>
Expand Down
2 changes: 1 addition & 1 deletion src/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ macro(add_test_target target_name module files)
set(TARGET ${target_name})

add_executable(${TARGET} ${files})
target_link_libraries(${TARGET} PRIVATE snitch::snitch rpp_tests_utils ${module})
target_link_libraries(${TARGET} PRIVATE snitch::snitch trompeloeil::trompeloeil rpp_tests_utils ${module})
set_target_properties(${TARGET} PROPERTIES FOLDER Tests/Suites/${module})

add_test_with_coverage(${TARGET})
Expand Down
115 changes: 42 additions & 73 deletions src/tests/rpp/test_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,81 +11,65 @@
#include <snitch/snitch.hpp>

#include <rpp/observables/dynamic_observable.hpp>
#include <rpp/observers/mock_observer.hpp>
#include <rpp/operators/buffer.hpp>
#include <rpp/operators/merge.hpp>
#include <rpp/sources/error.hpp>
#include <rpp/sources/just.hpp>

#include "disposable_observable.hpp"
#include "rpp_trompeloil.hpp"

TEST_CASE("buffer bundles items")
{
trompeloeil::sequence s{};
auto mock = mock_observer<std::vector<int>>{};

SECTION("observable of -1-2-3-|")
{
auto mock = mock_observer_strategy<std::vector<int>>{};
auto obs = rpp::source::just(1, 2, 3);
SECTION("subscribe on it via buffer(0)")
auto obs = rpp::source::just(1, 2, 3);
SECTION("buffer(0) - shall see -{1}-{2}-{3}-|")
{
obs | rpp::ops::buffer(0)
| rpp::ops::subscribe(mock);
SECTION("shall see -{1}-{2}-{3}-|")
{
CHECK(mock.get_received_values() == std::vector{std::vector{1}, std::vector{2}, std::vector{3}});
CHECK(mock.get_on_completed_count() == 1);
CHECK(mock.get_on_error_count() == 0);
}
REQUIRE_CALL(*mock, on_next(std::vector{1})).IN_SEQUENCE(s);
REQUIRE_CALL(*mock, on_next(std::vector{2})).IN_SEQUENCE(s);
REQUIRE_CALL(*mock, on_next(std::vector{3})).IN_SEQUENCE(s);
REQUIRE_CALL(*mock, on_completed()).IN_SEQUENCE(s);

obs | rpp::ops::buffer(0) | rpp::ops::subscribe(mock);
}
SECTION("subscribe on it via buffer(1)")
SECTION("buffer(1) - shall see -{1}-{2}-{3}-|")
{
REQUIRE_CALL(*mock, on_next(std::vector{1})).IN_SEQUENCE(s);
REQUIRE_CALL(*mock, on_next(std::vector{2})).IN_SEQUENCE(s);
REQUIRE_CALL(*mock, on_next(std::vector{3})).IN_SEQUENCE(s);
REQUIRE_CALL(*mock, on_completed()).IN_SEQUENCE(s);

obs | rpp::ops::buffer(1)
| rpp::ops::subscribe(mock);
SECTION("shall see -{1}-{2}-{3}-|")
{
CHECK(mock.get_received_values() == std::vector{std::vector{1}, std::vector{2}, std::vector{3}});
CHECK(mock.get_on_completed_count() == 1);
CHECK(mock.get_on_error_count() == 0);
}
}
SECTION("subscribe on it via buffer(2)")
SECTION("buffer(2) - shall see -{1,2}-{3}|")
{
REQUIRE_CALL(*mock, on_next(std::vector{1, 2})).IN_SEQUENCE(s);
REQUIRE_CALL(*mock, on_next(std::vector{3})).IN_SEQUENCE(s);
REQUIRE_CALL(*mock, on_completed()).IN_SEQUENCE(s);

obs | rpp::ops::buffer(2)
| rpp::ops::subscribe(mock);
SECTION("shall see -{1,2}-{3}|")
{
CHECK(mock.get_received_values() == std::vector<std::vector<int>>{
std::vector{1, 2},
std::vector{3},
});
CHECK(mock.get_on_completed_count() == 1);
CHECK(mock.get_on_error_count() == 0);
}
}
SECTION("subscribe on it via buffer(3)")
SECTION("buffer(3) - shall see -{1,2,3}-|")
{
REQUIRE_CALL(*mock, on_next(std::vector{1, 2, 3})).IN_SEQUENCE(s);
REQUIRE_CALL(*mock, on_completed()).IN_SEQUENCE(s);

obs | rpp::ops::buffer(3)
| rpp::ops::subscribe(mock);
SECTION("shall see -{1,2,3}-|")
{
CHECK(mock.get_received_values() == std::vector<std::vector<int>>{
std::vector{1, 2, 3},
});
CHECK(mock.get_on_completed_count() == 1);
CHECK(mock.get_on_error_count() == 0);
}
}
SECTION("subscribe on it via buffer(4)")
SECTION("buffer(4) - shall see -{1,2,3}-|")
{
REQUIRE_CALL(*mock, on_next(std::vector{1, 2, 3})).IN_SEQUENCE(s);
REQUIRE_CALL(*mock, on_completed()).IN_SEQUENCE(s);

obs | rpp::ops::buffer(4)
| rpp::ops::subscribe(mock);
SECTION("shall see -{1,2,3}-|")
{
CHECK(mock.get_received_values() == std::vector<std::vector<int>>{
std::vector{1, 2, 3},
});
CHECK(mock.get_on_completed_count() == 1);
CHECK(mock.get_on_error_count() == 0);
}
}
}

Expand All @@ -95,43 +79,28 @@ TEST_CASE("buffer bundles items")
rpp::source::error<int>(std::make_exception_ptr(std::runtime_error{""})).as_dynamic(),
rpp::source::just(2).as_dynamic())
| rpp::ops::merge();
auto mock = mock_observer_strategy<std::vector<int>>{};
SECTION("subscribe on it via buffer(0)")
SECTION("buffer(0) - shall see -{1}-x, which means error event is through")
{
REQUIRE_CALL(*mock, on_next(std::vector{1})).IN_SEQUENCE(s);
REQUIRE_CALL(*mock, on_error(trompeloeil::_)).IN_SEQUENCE(s);

obs | rpp::ops::buffer(0)
| rpp::ops::subscribe(mock);
SECTION("shall see -{1}-x, which means error event is through")
{
CHECK(mock.get_received_values() == std::vector<std::vector<int>>{
std::vector{1},
});
CHECK(mock.get_on_completed_count() == 0);
CHECK(mock.get_on_error_count() == 1);
}
}
SECTION("subscribe on it via buffer(1)")
SECTION("buffer(1) - shall see -{1}-x, which means error event is through")
{
REQUIRE_CALL(*mock, on_next(std::vector{1})).IN_SEQUENCE(s);
REQUIRE_CALL(*mock, on_error(trompeloeil::_)).IN_SEQUENCE(s);

obs | rpp::ops::buffer(1)
| rpp::ops::subscribe(mock);
SECTION("shall see -{1}-x, which means error event is through")
{
CHECK(mock.get_received_values() == std::vector<std::vector<int>>{
std::vector{1},
});
CHECK(mock.get_on_completed_count() == 0);
CHECK(mock.get_on_error_count() == 1);
}
}
SECTION("subscribe on it via buffer(2)")
SECTION("buffer(2) - shall see --x, which means error event is through")
{
REQUIRE_CALL(*mock, on_error(trompeloeil::_)).IN_SEQUENCE(s);

obs | rpp::ops::buffer(2)
| rpp::ops::subscribe(mock);
SECTION("shall see --x, which means error event is through")
{
CHECK(mock.get_received_values().empty());
CHECK(mock.get_on_completed_count() == 0);
CHECK(mock.get_on_error_count() == 1);
}
}
}
}
Expand Down
24 changes: 12 additions & 12 deletions src/tests/rpp/test_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@

#include <snitch/snitch.hpp>

#include <rpp/observers/mock_observer.hpp>
#include <rpp/operators/map.hpp>
#include <rpp/sources/just.hpp>

#include "copy_count_tracker.hpp"
#include "disposable_observable.hpp"
#include "rpp_trompeloil.hpp"

#include <stdexcept>
#include <string>
Expand All @@ -26,27 +26,27 @@ TEMPLATE_TEST_CASE("map modifies values and forward errors/completions", "", rpp

SECTION("map changes value")
{
mock_observer_strategy<std::string> mock{};
mock_observer<std::string> mock{};
trompeloeil::sequence seq;

obs | rpp::operators::map([](auto v) { return std::string("TEST ") + std::to_string(v); }) | rpp::operators::subscribe(mock);
REQUIRE_CALL(*mock, on_next("TEST 1")).IN_SEQUENCE(seq);
REQUIRE_CALL(*mock, on_next("TEST 2")).IN_SEQUENCE(seq);
REQUIRE_CALL(*mock, on_completed()).IN_SEQUENCE(seq);

CHECK(mock.get_received_values() == std::vector<std::string>{"TEST 1", "TEST 2"});
CHECK(mock.get_on_error_count() == 0);
CHECK(mock.get_on_completed_count() == 1);
obs | rpp::operators::map([](auto v) { return std::string("TEST ") + std::to_string(v); }) | rpp::operators::subscribe(std::move(mock));
}


SECTION("map with exception value")
{
mock_observer_strategy<int> mock{};
mock_observer<int> mock{};
trompeloeil::sequence seq;

auto map = rpp::operators::map([](int) -> int { throw std::runtime_error{""}; });
REQUIRE_CALL(*mock, on_error(trompeloeil::_)).IN_SEQUENCE(seq);

obs | map | rpp::operators::subscribe(mock); // NOLINT
auto map = rpp::operators::map([](int) -> int { throw std::runtime_error{"map failed"}; });

CHECK(mock.get_received_values() == std::vector<int>{});
CHECK(mock.get_on_error_count() == 1);
CHECK(mock.get_on_completed_count() == 0);
obs | map | rpp::operators::subscribe(std::move(mock)); // NOLINT
}
}

Expand Down
Loading