diff --git a/.clang-format b/.clang-format index 18ddea3..734b084 100644 --- a/.clang-format +++ b/.clang-format @@ -5,7 +5,6 @@ AlignConsecutiveDeclarations: false AlignEscapedNewlines: Left AlignOperands: true AlignTrailingComments: true -AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: None diff --git a/include/cpp_lmdb/cpp_lmdb.hpp b/include/cpp_lmdb/cpp_lmdb.hpp index bc69798..f0bab30 100644 --- a/include/cpp_lmdb/cpp_lmdb.hpp +++ b/include/cpp_lmdb/cpp_lmdb.hpp @@ -17,7 +17,6 @@ // std #include -#include #include #include #include diff --git a/include/cpp_lmdb/dbs.hpp b/include/cpp_lmdb/dbs.hpp index 0f7a291..a9845d9 100644 --- a/include/cpp_lmdb/dbs.hpp +++ b/include/cpp_lmdb/dbs.hpp @@ -11,10 +11,6 @@ // lmdb #include "lmdb.h" -// std -#include -#include - namespace lmdb { namespace details @@ -31,14 +27,17 @@ class db_base { using transaction = transaction; template - auto make_transaction() const - -> std::expected, error_t> + auto make_transaction() const LMDB_NOEXCEPT + -> LMDB_RESULT(transaction) { auto txn = details::make_tx(_api, _env, ReadOnly); - if (!txn) - return std::unexpected{error_t{txn.error()}}; - return transaction{_db_index, std::move(txn.value())}; + auto const make_transaction + = [this](auto &&txn) -> LMDB_RESULT(transaction) { + return transaction{_db_index, std::move(txn)}; + }; + + return LMDB_AND_THEN(std::move(txn), make_transaction); } private: @@ -62,7 +61,8 @@ class ro_db : public details::db_base { public: using base::base; - auto begin_ro_transaction() const -> std::expected + auto begin_ro_transaction() const LMDB_NOEXCEPT + -> LMDB_RESULT(ro_transaction) { return base::template make_transaction(); } @@ -79,13 +79,13 @@ class rw_db : public ro_db { public: using base::base; - auto begin_rw_transaction() -> std::expected + auto begin_rw_transaction() LMDB_NOEXCEPT -> LMDB_RESULT(rw_transaction) { return base::template make_transaction(); } - auto commit_transaction(rw_transaction &&transaction) - -> std::expected + auto commit_transaction(rw_transaction &&transaction) LMDB_NOEXCEPT + -> LMDB_RESULT(void) { return std::move(transaction).commit(); } diff --git a/include/cpp_lmdb/details/details.hpp b/include/cpp_lmdb/details/details.hpp index 298fff7..510fa4b 100644 --- a/include/cpp_lmdb/details/details.hpp +++ b/include/cpp_lmdb/details/details.hpp @@ -1,15 +1,14 @@ #pragma once +#include "cpp_lmdb/error.hpp" #include "cpp_lmdb/types.hpp" // lmdb #include "lmdb.h" // std -#include #include #include -#include namespace lmdb::details { @@ -34,7 +33,9 @@ inline auto to_byte_span(MDB_val const &value) noexcept inline auto to_mdb_val(byte_span const &value) noexcept { - return MDB_val{value.size(), const_cast(value.data())}; + return MDB_val{ + .mv_size = value.size(), + .mv_data = const_cast(value.data())}; } template @@ -53,37 +54,34 @@ struct txn_deleter { LmdbApi const &api; }; +template +struct overloaded : Ts... { + using Ts::operator()...; +}; + template using txn_unique_ptr_t = std::unique_ptr>; template constexpr auto make_tx( - LmdbApi const &api, MDB_env &env, read_only_t const read_only) - -> std::expected, int> + LmdbApi const &api, + MDB_env &env, + read_only_t const read_only) LMDB_NOEXCEPT + -> LMDB_RESULT(txn_unique_ptr_t) { MDB_txn *txn{nullptr}; - if (auto const result = api.mdb_txn_begin( - &env, - nullptr, - read_only == read_only_t::yes ? MDB_RDONLY : 0, - &txn); - result != MDB_SUCCESS) { - return std::unexpected{result}; - } + LMDB_CALL_API(api.mdb_txn_begin( + &env, nullptr, read_only == read_only_t::yes ? MDB_RDONLY : 0, &txn)); return txn_unique_ptr_t{txn, details::txn_deleter{api}}; } template constexpr auto commit_tx(LmdbApi const &api, txn_unique_ptr_t &&tx) - -> std::expected + LMDB_NOEXCEPT -> LMDB_RESULT(void) { - if (auto const result = api.mdb_txn_commit(tx.release()); - result != MDB_SUCCESS) { - return std::unexpected{result}; - } - - return {}; + LMDB_CALL_API(api.mdb_txn_commit(tx.release())); + LMDB_REPORT_SUCCESS(); } template @@ -102,14 +100,11 @@ using cursor_unique_ptr_t template constexpr auto make_cursor( - LmdbApi const &api, MDB_txn *const txn, MDB_dbi const dbi) - -> std::expected, int> + LmdbApi const &api, MDB_txn *const txn, MDB_dbi const dbi) LMDB_NOEXCEPT + -> LMDB_RESULT(cursor_unique_ptr_t) { MDB_cursor *cursor{nullptr}; - if (auto const result = api.mdb_cursor_open(txn, dbi, &cursor); - result != MDB_SUCCESS) { - return std::unexpected{result}; - } + LMDB_CALL_API(api.mdb_cursor_open(txn, dbi, &cursor)); return cursor_unique_ptr_t{cursor, cursor_deleter{api}}; } diff --git a/include/cpp_lmdb/environment.hpp b/include/cpp_lmdb/environment.hpp index 5d1e2a7..f697b8b 100644 --- a/include/cpp_lmdb/environment.hpp +++ b/include/cpp_lmdb/environment.hpp @@ -3,6 +3,7 @@ #include "cpp_lmdb/concepts.hpp" #include "cpp_lmdb/db_item.hpp" #include "cpp_lmdb/dbs.hpp" +#include "cpp_lmdb/error.hpp" #include "cpp_lmdb/iterators.hpp" #include "cpp_lmdb/transactions.hpp" #include "cpp_lmdb/types.hpp" @@ -18,9 +19,7 @@ // std #include -#include #include -#include #include namespace lmdb @@ -66,54 +65,63 @@ class environment_base { using LmdbApiType = std::remove_reference_t; template - using open_db_result = std::expected< - std::conditional_t< - ReadOnly == read_only_t::yes, - ro_db, - rw_db>, - error_t>; + using open_db_result = std::conditional_t< + ReadOnly == read_only_t::yes, + ro_db, + rw_db>; template auto open_db( char const *const name, create_if_not_exists const create_flag - = create_if_not_exists::no) const - -> open_db_result + = create_if_not_exists::no) const LMDB_NOEXCEPT + -> LMDB_RESULT((open_db_result)) { auto &api = _env.get_deleter().api; - auto transaction = make_tx(api, *_env, ReadOnly); - if (!transaction) - return std::unexpected{error_t{transaction.error()}}; - - const auto creation_flags - = key_value_trait_helper::db_key_value_flags() - | (create_flag == create_if_not_exists::yes ? MDB_CREATE : 0); - - MDB_dbi db_index{}; - LMDB_CALL_API(api.mdb_dbi_open( - transaction->get(), name, creation_flags, &db_index)); - - if constexpr (key_value_trait_helper::has_key_cmp_fun) { - LMDB_CALL_API(api.mdb_set_compare( - transaction->get(), - db_index, - cmp)); - } - - if constexpr (key_value_trait_helper< - KeyValueTrait>::has_value_cmp_fun) { - LMDB_CALL_API(api.mdb_set_dupsort( - transaction->get(), - db_index, - cmp)); - } - - if (auto const result = commit_tx(api, std::move(transaction.value())); - !result) - return std::unexpected{error_t{result.error()}}; - - return typename open_db_result::value_type{ - api, db_index, *_env}; + + auto txn = make_tx(api, *_env, ReadOnly); + + using result_type + = LMDB_RESULT((open_db_result)); + + auto const open_db = + [&env = _env, &api, name, create_flag](auto &&txn) -> result_type { + const auto creation_flags + = key_value_trait_helper::db_key_value_flags() + | (create_flag == create_if_not_exists::yes ? MDB_CREATE + : 0); + + MDB_dbi db_index{}; + LMDB_CALL_API( + api.mdb_dbi_open(txn.get(), name, creation_flags, &db_index)); + + if constexpr ( + key_value_trait_helper::has_key_cmp_fun) { + LMDB_CALL_API(api.mdb_set_compare( + txn.get(), + db_index, + cmp)); + } + + if constexpr ( + key_value_trait_helper::has_value_cmp_fun) { + LMDB_CALL_API(api.mdb_set_dupsort( + txn.get(), + db_index, + cmp)); + } + + auto result = commit_tx(api, std::move(txn)); + + auto const make_db = [&env, &api, db_index]() -> result_type { + return open_db_result{ + api, db_index, *env}; + }; + + return LMDB_AND_THEN(std::move(result), make_db); + }; + + return LMDB_AND_THEN(std::move(txn), open_db); } private: @@ -134,7 +142,7 @@ class ro_environment : public details::environment_base { template auto open_ro_db(char const *const name) const noexcept - -> std::expected, error_t> + -> LMDB_RESULT(ro_db) { return details::environment_base< LmdbApi>::template open_db(name); @@ -156,7 +164,7 @@ class rw_environment : public ro_environment { char const *const name, create_if_not_exists const create_flag = create_if_not_exists::no) noexcept - -> std::expected, error_t> + -> LMDB_RESULT(rw_db) { return base::template open_db( name, create_flag); @@ -179,8 +187,8 @@ template < auto make_environment( char const *const environment_path, db_file_mode_t const db_file_mode, - LmdbApi &&api = LmdbApi{}) - LMDB_NOEXCEPT->LMDB_RESULT((environment_t)) + LmdbApi &&api = LmdbApi{}) LMDB_NOEXCEPT + -> LMDB_RESULT((environment_t)) { MDB_env *env{nullptr}; LMDB_CALL_API(api.mdb_env_create(&env)); diff --git a/include/cpp_lmdb/error.hpp b/include/cpp_lmdb/error.hpp index ca4ce08..f5ef699 100644 --- a/include/cpp_lmdb/error.hpp +++ b/include/cpp_lmdb/error.hpp @@ -3,8 +3,12 @@ #include "lmdb.h" // std +#ifdef CPP_LMDB_EXCEPTIONS_ENABLED #include +#include +#else #include +#endif namespace lmdb { @@ -39,9 +43,58 @@ class lmdb_exception : public std::exception { lmdb_exception(error_t error) noexcept : _error{error} {} - auto what() const noexcept -> char const* override + auto what() const noexcept -> char const * override { - return ""; + switch (_error) { + using enum error_t; + case key_exist: + return "Key already exists in the database"; + case not_found: + return "Key/data pair not found (EOF)"; + case page_not_found: + return "Requested page not found - this usually indicates " + "corruption"; + case corrupted: + return "Located page was wrong type"; + case panic: + return "Update of meta page failed or environment had fatal " + "error"; + case version_mismatch: + return "Environment version mismatch"; + case invalid: + return "File is not a valid LMDB file"; + case map_full: + return "Environment mapsize reached"; + case dbs_full: + return "Environment maxdbs reached"; + case readers_full: + return "Environment maxreaders reached"; + case tls_full: + return "Thread local storage full"; + case txn_full: + return "Transaction has too many dirty pages"; + case cursor_full: + return "Cursor stack too deep - internal error"; + case page_full: + return "Page has not enough space - internal error"; + case map_resized: + return "Database contents grew beyond mapsize"; + case incompatible: + return "The specified database is not compatible with the " + "requested operation"; + case bad_rslot: + return "Invalid reuse of reader locktable slot"; + case bad_txn: + return "Transaction is not valid for requested operation"; + case bad_valsize: + return "The specified size is not valid for the specified " + "key/data pair"; + case bad_dbi: + return "The specified DBI handle is not valid for " + "requested operation"; + } + + return "Unknown error"; } auto error() const noexcept -> error_t @@ -53,7 +106,7 @@ class lmdb_exception : public std::exception { error_t _error; }; -#endif // CPP_LMDB_EXCEPTIONS_ENABLED +#endif // CPP_LMDB_EXCEPTIONS_ENABLED } // namespace lmdb @@ -63,13 +116,50 @@ template struct extract_parantesized_arg { using arg = A; }; +template +struct extract_parantesized_arg { + using arg = void; +}; #ifdef CPP_LMDB_EXCEPTIONS_ENABLED -#define LMDB_RESULT(res_type) \ - typename extract_parantesized_arg::arg +struct void_placeholder_t { + void_placeholder_t() = default; + void_placeholder_t(void_placeholder_t const &) = default; + void_placeholder_t(void_placeholder_t &&) = default; + auto operator=(void_placeholder_t const &) + -> void_placeholder_t & = default; + auto operator=(void_placeholder_t &&) -> void_placeholder_t & = default; + + template + requires(!std::is_same_v>) + explicit void_placeholder_t(T &&, Ts &&...) noexcept + {} +}; + +template + requires(!std::is_void_v>) +auto invoke_void(F &&f, Args &&...args) +{ + return std::invoke(std::forward(f), std::forward(args)...); +} + +template + requires(std::is_void_v>) +auto invoke_void(F &&f, Args &&...args) +{ + std::invoke(std::forward(f), std::forward(args)...); + return void_placeholder_t{}; +} + +#define LMDB_RESULT(res_type) \ + typename std::conditional_t< \ + std::is_void_v< \ + typename extract_parantesized_arg::arg>, \ + void_placeholder_t, \ + typename extract_parantesized_arg::arg> + #define LMDB_NOEXCEPT -// #define LMDB_NOEXCEPT_COND(cond) noexcept(cond) #define LMDB_REPORT_ERROR(code) \ throw ::lmdb::lmdb_exception \ @@ -77,6 +167,19 @@ struct extract_parantesized_arg { code \ } +#define LMDB_REPORT_SUCCESS() \ + return \ + {} + +#define LMDB_AND_THEN(result, expr) \ + [](R &&r, E &&e) { \ + if constexpr (!std::is_same_v) { \ + return invoke_void(std::forward(e), std::forward(r)); \ + } else { \ + return invoke_void(std::forward(e)); \ + } \ + }(result, expr) + #else #define LMDB_RESULT(res_type) \ @@ -92,6 +195,15 @@ struct extract_parantesized_arg { code \ } +#define LMDB_REPORT_SUCCESS() \ + return \ + {} + +#define LMDB_AND_THEN(result, expr) \ + [](R &&r, E &&e) { \ + return std::forward(r).and_then(std::forward(e)); \ + }(result, expr) + #endif #define LMDB_CALL_API(expr) \ diff --git a/include/cpp_lmdb/iterators.hpp b/include/cpp_lmdb/iterators.hpp index 6256636..dee7320 100644 --- a/include/cpp_lmdb/iterators.hpp +++ b/include/cpp_lmdb/iterators.hpp @@ -1,5 +1,6 @@ #pragma once +#include "cpp_lmdb/concepts.hpp" #include "cpp_lmdb/db_item.hpp" #include "cpp_lmdb/error.hpp" @@ -10,7 +11,6 @@ #include #include #include -#include namespace lmdb { @@ -37,8 +37,7 @@ class ro_iterator_stub { namespace details { template < - template - class Derived, + template class Derived, deserialization_trait KeyTrait, deserialization_trait ValueTrait, lmdb_api_like LmdbApi> diff --git a/include/cpp_lmdb/transactions.hpp b/include/cpp_lmdb/transactions.hpp index 66bf56a..4cc43e2 100644 --- a/include/cpp_lmdb/transactions.hpp +++ b/include/cpp_lmdb/transactions.hpp @@ -3,8 +3,8 @@ #include "cpp_lmdb/concepts.hpp" #include "cpp_lmdb/db_item.hpp" #include "cpp_lmdb/iterators.hpp" -#include "cpp_lmdb/views.hpp" #include "cpp_lmdb/types.hpp" +#include "cpp_lmdb/views.hpp" // details #include "cpp_lmdb/details/details.hpp" @@ -15,7 +15,6 @@ // std #include -#include namespace lmdb { @@ -44,22 +43,22 @@ class transaction { public: transaction( - MDB_dbi const db_index, details::txn_unique_ptr_t &&txn) noexcept + MDB_dbi const db_index, + details::txn_unique_ptr_t &&txn) noexcept : _db_index{db_index} , _txn{std::move(txn)} , _api{_txn.get_deleter().api} {} - auto try_insert(key_type const &key, value_type const &value) noexcept - -> std::expected + auto try_insert(key_type const &key, value_type const &value) LMDB_NOEXCEPT + -> LMDB_RESULT(void) requires(ReadOnly == read_only_t::no) { return insert_impl(key, value, MDB_NOOVERWRITE); } - auto try_insert_duplicate( - key_type const &key, value_type const &value) noexcept - -> std::expected + auto try_insert_duplicate(key_type const &key, value_type const &value) + LMDB_NOEXCEPT -> LMDB_RESULT(void) requires( ReadOnly == read_only_t::no && details::key_value_trait_helper< @@ -68,15 +67,14 @@ class transaction { return insert_impl(key, value, MDB_NODUPDATA); } - auto insert(key_type const &key, value_type const &value) noexcept - -> std::expected + auto insert(key_type const &key, value_type const &value) LMDB_NOEXCEPT + -> LMDB_RESULT(void) requires(ReadOnly == read_only_t::no) { return insert_impl(key, value, 0); } - auto delete_key(key_type const &key) noexcept - -> std::expected + auto delete_key(key_type const &key) LMDB_NOEXCEPT -> LMDB_RESULT(void) { auto const key_bytes = key_trait::to_bytes(key); auto mdb_key = to_mdb_val(key_bytes); @@ -84,14 +82,14 @@ class transaction { if (auto const result = _api.mdb_del(_txn.get(), _db_index, &mdb_key, nullptr); result != MDB_SUCCESS) { - return std::unexpected{error_t{result}}; + LMDB_REPORT_ERROR(error_t{result}); } - return {}; + LMDB_REPORT_SUCCESS(); } - auto get(key_type const &key) const noexcept - -> std::expected + auto get(key_type const &key) const LMDB_NOEXCEPT + -> LMDB_RESULT(value_type) requires(!details::key_value_trait_helper< KeyValueTrait>::duplicates_enabled) { @@ -102,7 +100,7 @@ class transaction { if (auto const result = _api.mdb_get(_txn.get(), _db_index, &mdb_key, &mdb_value); result != MDB_SUCCESS) { - return std::unexpected{error_t{result}}; + LMDB_REPORT_ERROR(error_t{result}); } return value_trait::from_bytes(details::to_byte_span(mdb_value)); @@ -110,54 +108,54 @@ class transaction { // TODO: probably, if exceptions are not enabled, iterator should be // returned instead of view as error reporting from views will be limited - auto iterate() const noexcept -> std::expected + auto iterate() const LMDB_NOEXCEPT -> LMDB_RESULT(ro_view) { - auto cursor = details::make_cursor(_api, _txn.get(), _db_index); - if (!cursor) - return std::unexpected{error_t{cursor.error()}}; + auto cursor_or_error + = details::make_cursor(_api, _txn.get(), _db_index); + + auto const make_ro_view = [](auto &&cursor) -> LMDB_RESULT(ro_view) { + return ro_view{std::move(cursor)}; + }; - return ro_view{std::move(*cursor)}; + return LMDB_AND_THEN(std::move(cursor_or_error), make_ro_view); } - auto iterate_by_key(key_type const &key) const noexcept - -> std::expected + auto iterate_by_key(key_type const &key) const LMDB_NOEXCEPT + -> LMDB_RESULT(ro_dup_view) requires( details::key_value_trait_helper::duplicates_enabled) { - auto cursor = details::make_cursor(_api, _txn.get(), _db_index); - if (!cursor) - return std::unexpected{error_t{cursor.error()}}; + auto cursor_or_error + = details::make_cursor(_api, _txn.get(), _db_index); - auto const key_bytes = key_trait::to_bytes(key); - return ro_dup_view{std::move(*cursor), key_bytes}; + auto const make_ro_dup_view + = [&key](auto &&cursor) -> LMDB_RESULT(ro_dup_view) { + auto const key_bytes = key_trait::to_bytes(key); + return ro_dup_view{std::move(cursor), key_bytes}; + }; + + return LMDB_AND_THEN(std::move(cursor_or_error), make_ro_dup_view); } private: auto insert_impl( key_type const &key, value_type const &value, unsigned int flags) - -> std::expected + -> LMDB_RESULT(void) { const auto key_bytes = key_trait::to_bytes(key); auto mdb_key = details::to_mdb_val(key_bytes); const auto value_bytes = value_trait::to_bytes(value); auto mdb_value = details::to_mdb_val(value_bytes); - if (auto const result - = _api.mdb_put(_txn.get(), _db_index, &mdb_key, &mdb_value, flags); - result != MDB_SUCCESS) { - return std::unexpected{error_t{result}}; - } + LMDB_CALL_API( + _api.mdb_put(_txn.get(), _db_index, &mdb_key, &mdb_value, flags)); - return {}; + LMDB_REPORT_SUCCESS(); } - auto commit() && noexcept -> std::expected + auto commit() && LMDB_NOEXCEPT -> LMDB_RESULT(void) { - if (auto const result = commit_tx(_api, std::move(_txn)); !result) { - return std::unexpected{error_t{result.error()}}; - } - - return {}; + return commit_tx(_api, std::move(_txn)); } private: diff --git a/include/cpp_lmdb/views.hpp b/include/cpp_lmdb/views.hpp index deb0936..187b7ec 100644 --- a/include/cpp_lmdb/views.hpp +++ b/include/cpp_lmdb/views.hpp @@ -3,6 +3,7 @@ #include "cpp_lmdb/iterators.hpp" #include +#include namespace lmdb { diff --git a/test/integration/test_db_int_keys_and_values.cpp b/test/integration/test_db_int_keys_and_values.cpp index 3f4159c..fd95c78 100644 --- a/test/integration/test_db_int_keys_and_values.cpp +++ b/test/integration/test_db_int_keys_and_values.cpp @@ -7,7 +7,6 @@ #include "gtest/gtest.h" // std -#include #include using namespace ::testing; // NOLINT(google-build-using-namespace) diff --git a/test/link_time_substitution_example/test_example.cpp b/test/link_time_substitution_example/test_example.cpp index baf69c3..ad1858a 100644 --- a/test/link_time_substitution_example/test_example.cpp +++ b/test/link_time_substitution_example/test_example.cpp @@ -7,9 +7,6 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -// std -#include - namespace { // classes for technique demonstration diff --git a/test/unit/test_error_handling_exceptions.cpp b/test/unit/test_error_handling_exceptions.cpp index 0846bc5..2f41e1a 100644 --- a/test/unit/test_error_handling_exceptions.cpp +++ b/test/unit/test_error_handling_exceptions.cpp @@ -1,4 +1,6 @@ +#include #define CPP_LMDB_EXCEPTIONS_ENABLED +#include "cpp_lmdb/environment.hpp" #include "cpp_lmdb/error.hpp" #include "mocks.hpp" @@ -8,6 +10,7 @@ // std #include +#include namespace cpp_lmdb_tests { @@ -15,12 +18,25 @@ namespace { struct test_result {}; -void test_function_noexcept() LMDB_NOEXCEPT{}; +[[maybe_unused]] auto test_function_noexcept() LMDB_NOEXCEPT {}; } // namespace static_assert(std::is_same_v); static_assert(!noexcept(test_function_noexcept())); +static_assert(std::is_same_v< + decltype(lmdb::make_environment( + "", lmdb::default_file_mode)), + lmdb::rw_environment<>>); + +using db_trait + = lmdb::unique_key, lmdb::trivial_trait>; + +static_assert(std::is_same_v< + decltype(std::declval>() + .template open_ro_db("db")), + lmdb::ro_db>); + TEST(error_handling_exceptions, report_error) { try { @@ -55,4 +71,5 @@ TEST(error_handling_exceptions, api_call_no_exception) EXPECT_NO_THROW(LMDB_CALL_API(api.mdb_env_create(&env))); } + } // namespace cpp_lmdb_tests diff --git a/test/unit/test_error_handling_expected.cpp b/test/unit/test_error_handling_expected.cpp index 03b77cd..a0c8bc3 100644 --- a/test/unit/test_error_handling_expected.cpp +++ b/test/unit/test_error_handling_expected.cpp @@ -7,6 +7,7 @@ // std #include +#include namespace cpp_lmdb_tests { @@ -15,7 +16,7 @@ namespace { struct test_result {}; -void test_function_noexcept() LMDB_NOEXCEPT{}; +[[maybe_unused]] auto test_function_noexcept() LMDB_NOEXCEPT {}; } // namespace static_assert(std::is_same_v< @@ -23,6 +24,21 @@ static_assert(std::is_same_v< std::expected>); static_assert(noexcept(test_function_noexcept())); +static_assert(std::is_same_v< + decltype(lmdb::make_environment( + "", lmdb::default_file_mode)), + std::expected, lmdb::error_t>>); + +using db_trait + = lmdb::unique_key, lmdb::trivial_trait>; + +static_assert(std::is_same_v< + decltype(std::declval>() + .template open_ro_db("db")), + std::expected< + lmdb::ro_db, + lmdb::error_t>>); + TEST(error_handling_expected, report_error) { auto const error = []() { LMDB_REPORT_ERROR(lmdb::error_t::bad_dbi); }(); diff --git a/test/unit/test_transaction.cpp b/test/unit/test_transaction.cpp index dbeca2a..85d2dde 100644 --- a/test/unit/test_transaction.cpp +++ b/test/unit/test_transaction.cpp @@ -249,7 +249,7 @@ TEST_F(test_transaction, trivial_types_transaction_iterate) auto const& db_view = *result; auto const it = db_view.begin(); - ASSERT_NE(it, db_view.end()); + EXPECT_NE(it, db_view.end()); } using test_trait_dup