From d0f80c0814e53d098dc64fef859b299c0a7c0ce4 Mon Sep 17 00:00:00 2001 From: Jan Dorniak Date: Tue, 23 Feb 2021 12:09:20 +0100 Subject: [PATCH] add pool_invalid_argument exception --- include/libpmemobj++/pexceptions.hpp | 20 ++++++++++++++- include/libpmemobj++/pool.hpp | 34 ++++++++++++++++--------- tests/CMakeLists.txt | 5 ++++ tests/pool/pool.cpp | 38 +++++++++++++++++++++++++--- tests/pool/pool_6.cmake | 11 ++++++++ tests/pool/pool_6_none.out.match | 1 + tests/pool/pool_7.cmake | 11 ++++++++ tests/pool/pool_7_none.out.match | 1 + tests/pool/pool_8.cmake | 13 ++++++++++ tests/pool/pool_8_none.out.match | 2 ++ 10 files changed, 120 insertions(+), 16 deletions(-) create mode 100644 tests/pool/pool_6.cmake create mode 100644 tests/pool/pool_6_none.out.match create mode 100644 tests/pool/pool_7.cmake create mode 100644 tests/pool/pool_7_none.out.match create mode 100644 tests/pool/pool_8.cmake create mode 100644 tests/pool/pool_8_none.out.match diff --git a/include/libpmemobj++/pexceptions.hpp b/include/libpmemobj++/pexceptions.hpp index 58b72cb4db..608b3edc34 100644 --- a/include/libpmemobj++/pexceptions.hpp +++ b/include/libpmemobj++/pexceptions.hpp @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2016-2020, Intel Corporation */ +/* Copyright 2016-2021, Intel Corporation */ /** * @file @@ -55,6 +55,24 @@ class pool_error : public std::runtime_error { } }; +/** + * Custom pool error class. + * + * Thrown when there is an invalid argument passed to create/open pool. + */ +class pool_invalid_argument : public pool_error { +public: + using pool_error::pool_error; + + pool_invalid_argument & + with_pmemobj_errormsg() + { + (*this) = pool_invalid_argument(what() + std::string(": ") + + detail::errormsg()); + return *this; + } +}; + /** * Custom transaction error class. * diff --git a/include/libpmemobj++/pool.hpp b/include/libpmemobj++/pool.hpp index 2a6fa85966..5c66bba88a 100644 --- a/include/libpmemobj++/pool.hpp +++ b/include/libpmemobj++/pool.hpp @@ -10,6 +10,7 @@ #define LIBPMEMOBJ_CPP_POOL_HPP #include +#include #include #include #include @@ -108,9 +109,7 @@ class pool_base { #else pmemobjpool *pop = pmemobj_open(path.c_str(), layout.c_str()); #endif - if (pop == nullptr) - throw pmem::pool_error("Failed opening pool") - .with_pmemobj_errormsg(); + check_pool(pop, "opening"); pmemobj_set_user_data(pop, new detail::pool_data); @@ -144,9 +143,7 @@ class pool_base { pmemobjpool *pop = pmemobj_create(path.c_str(), layout.c_str(), size, mode); #endif - if (pop == nullptr) - throw pmem::pool_error("Failed creating pool") - .with_pmemobj_errormsg(); + check_pool(pop, "creating"); pmemobj_set_user_data(pop, new detail::pool_data); @@ -191,9 +188,7 @@ class pool_base { open(const std::wstring &path, const std::wstring &layout) { pmemobjpool *pop = pmemobj_openW(path.c_str(), layout.c_str()); - if (pop == nullptr) - throw pmem::pool_error("Failed opening pool") - .with_pmemobj_errormsg(); + check_pool(pop, "opening"); pmemobj_set_user_data(pop, new detail::pool_data); @@ -223,9 +218,7 @@ class pool_base { { pmemobjpool *pop = pmemobj_createW(path.c_str(), layout.c_str(), size, mode); - if (pop == nullptr) - throw pmem::pool_error("Failed creating pool") - .with_pmemobj_errormsg(); + check_pool(pop, "creating"); pmemobj_set_user_data(pop, new detail::pool_data); @@ -434,6 +427,23 @@ class pool_base { } protected: + static void + check_pool(pmemobjpool *pop, std::string mode) + { + if (pop == nullptr) { + if (errno == EINVAL || errno == EFBIG || + errno == ENOENT || errno == EEXIST) { + throw pmem::pool_invalid_argument( + "Failed " + mode + " pool") + .with_pmemobj_errormsg(); + } else { + throw pmem::pool_error("Failed " + mode + + " pool") + .with_pmemobj_errormsg(); + } + } + } + /* The pool opaque handle */ PMEMobjpool *pop; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 604912715e..1e61f930aa 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -161,6 +161,11 @@ add_test_generic(NAME pool CASE 2 TRACERS none) add_test_generic(NAME pool CASE 3 TRACERS none) add_test_generic(NAME pool CASE 4 TRACERS none) add_test_generic(NAME pool CASE 5 TRACERS none) +add_test_generic(NAME pool CASE 6 TRACERS none) +add_test_generic(NAME pool CASE 7 TRACERS none) +if (NOT WIN32) + add_test_generic(NAME pool CASE 8 TRACERS none) +endif() if(WIN32) build_test(pool_win pool/pool_win.cpp) diff --git a/tests/pool/pool.cpp b/tests/pool/pool.cpp index dd2ab3b074..5b2856b943 100644 --- a/tests/pool/pool.cpp +++ b/tests/pool/pool.cpp @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2015-2020, Intel Corporation */ +/* Copyright 2015-2021, Intel Corporation */ /* * obj_cpp_pool.c -- cpp pool implementation test @@ -23,6 +23,27 @@ struct root { nvobj::p val; }; +/* emulate no more space in the memory */ +void * +null_alloc_func(size_t s) +{ + errno = ENOSPC; + return nullptr; +} + +void +test_pool_exceptions() +{ + /* try catching pool_invalid_argument as a pool_error */ + try { + throw pmem::pool_invalid_argument("test"); + } catch (pmem::pool_error &e) { + return; + } + + UT_ASSERT(0); +} + /* * pool_create -- (internal) test pool create */ @@ -35,9 +56,12 @@ pool_create(const char *path, const char *layout, size_t poolsize, pop = nvobj::pool::create(path, layout, poolsize, mode); nvobj::persistent_ptr root = pop.root(); UT_ASSERT(root != nullptr); - } catch (pmem::pool_error &e) { + } catch (pmem::pool_invalid_argument &e) { UT_OUT("%s: pool::create: %s", path, e.what()); return; + } catch (pmem::pool_error &e) { + UT_OUT("%s: pool::create: (pool_error) %s", path, e.what()); + return; } os_stat_t stbuf; @@ -69,9 +93,12 @@ pool_open(const char *path, const char *layout) nvobj::pool pop; try { pop = nvobj::pool::open(path, layout); - } catch (pmem::pool_error &e) { + } catch (pmem::pool_invalid_argument &e) { UT_OUT("%s: pool::open: %s", path, e.what()); return; + } catch (pmem::pool_error &e) { + UT_OUT("%s: pool::open: (pool_error) %s", path, e.what()); + return; } UT_OUT("%s: pool::open: Success", path); @@ -142,6 +169,9 @@ test(int argc, char *argv[]) layout = argv[3]; switch (argv[1][0]) { + case 'n': + pmemobj_set_funcs(null_alloc_func, NULL, NULL, NULL); + /* no break */ case 'c': poolsize = std::stoul(argv[4], nullptr, 0) * MB; /* in megabytes */ @@ -165,6 +195,8 @@ test(int argc, char *argv[]) default: UT_FATAL("unknown operation"); } + + test_pool_exceptions(); } int diff --git a/tests/pool/pool_6.cmake b/tests/pool/pool_6.cmake new file mode 100644 index 0000000000..4857e89eac --- /dev/null +++ b/tests/pool/pool_6.cmake @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2021, Intel Corporation + +include(${SRC_DIR}/../helpers.cmake) + +setup() + +# test for creating pool, without enough memory available +execute(${TEST_EXECUTABLE} n ${DIR}/testfile "test" 20 0600) + +finish() diff --git a/tests/pool/pool_6_none.out.match b/tests/pool/pool_6_none.out.match new file mode 100644 index 0000000000..1554dc7f75 --- /dev/null +++ b/tests/pool/pool_6_none.out.match @@ -0,0 +1 @@ +$(nW)testfile: pool::create: (pool_error) Failed creating pool: $(*) diff --git a/tests/pool/pool_7.cmake b/tests/pool/pool_7.cmake new file mode 100644 index 0000000000..5cf95a7db5 --- /dev/null +++ b/tests/pool/pool_7.cmake @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2021, Intel Corporation + +include(${SRC_DIR}/../helpers.cmake) + +setup() + +# test for creating too small pool +execute(${TEST_EXECUTABLE} c ${DIR}/testfile "test" 1 0600) + +finish() diff --git a/tests/pool/pool_7_none.out.match b/tests/pool/pool_7_none.out.match new file mode 100644 index 0000000000..1c55a13b36 --- /dev/null +++ b/tests/pool/pool_7_none.out.match @@ -0,0 +1 @@ +$(nW)testfile: pool::create: Failed creating pool: $(*) diff --git a/tests/pool/pool_8.cmake b/tests/pool/pool_8.cmake new file mode 100644 index 0000000000..a9b4012b25 --- /dev/null +++ b/tests/pool/pool_8.cmake @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright 2021, Intel Corporation + +include(${SRC_DIR}/../helpers.cmake) + +setup() + +# test for opening pool without access +execute(${TEST_EXECUTABLE} c ${DIR}/testfile "test" 20 0600) +execute_process(COMMAND chmod 000 ${DIR}/testfile) +execute(${TEST_EXECUTABLE} o ${DIR}/testfile "test") + +finish() diff --git a/tests/pool/pool_8_none.out.match b/tests/pool/pool_8_none.out.match new file mode 100644 index 0000000000..b6c89796ee --- /dev/null +++ b/tests/pool/pool_8_none.out.match @@ -0,0 +1,2 @@ +$(nW)testfile: file size $(N) mode $(N) +$(nW)testfile: pool::open: (pool_error) Failed opening pool: $(*)