mirror of
https://github.com/microsoft/GSL.git
synced 2024-11-03 17:56:43 -05:00
tests and changes for final_act
This commit is contained in:
parent
652d886963
commit
b8af699165
@ -40,25 +40,97 @@ using std::shared_ptr;
|
||||
//
|
||||
|
||||
// Final_act allows you to ensure something gets run at the end of a scope
|
||||
template <class F>
|
||||
class Final_act
|
||||
template <typename F_t>
|
||||
class Final_act_noexcept
|
||||
{
|
||||
F_t f;
|
||||
bool run;
|
||||
|
||||
public:
|
||||
explicit Final_act(F f) : f_(f) {}
|
||||
explicit Final_act_noexcept(F_t f_) : f(f_), run(true) { }
|
||||
|
||||
Final_act(const Final_act&& other) : f_(other.f_) {}
|
||||
Final_act(const Final_act&) = delete;
|
||||
Final_act& operator=(const Final_act&) = delete;
|
||||
~Final_act_noexcept()
|
||||
{
|
||||
if (!run) return;
|
||||
f();
|
||||
}
|
||||
|
||||
~Final_act() { f_(); }
|
||||
Final_act_noexcept(const Final_act_noexcept& s) = delete;
|
||||
Final_act_noexcept(Final_act_noexcept&& s)
|
||||
: f(std::move(s.f)), run(s.run)
|
||||
{ s.run = false; }
|
||||
|
||||
private:
|
||||
F f_;
|
||||
Final_act_noexcept& operator=(const Final_act_noexcept& s) = delete;
|
||||
|
||||
Final_act_noexcept& operator=(Final_act_noexcept&& s)
|
||||
{
|
||||
f = std::move(s.f);
|
||||
run = s.run;
|
||||
s.run = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void release() { run = false; }
|
||||
};
|
||||
|
||||
// Final_act allows you to ensure something gets run at the end of a scope
|
||||
template <typename F_t>
|
||||
class Final_act
|
||||
{
|
||||
F_t f;
|
||||
bool run;
|
||||
|
||||
public:
|
||||
explicit Final_act(F_t f_) : f(f_), run(true) { }
|
||||
|
||||
~Final_act()
|
||||
{
|
||||
if (!run)
|
||||
return;
|
||||
|
||||
try { f(); }
|
||||
catch (...) { }
|
||||
}
|
||||
|
||||
Final_act(const Final_act& s) = delete;
|
||||
|
||||
Final_act(Final_act&& s) : f(std::move(s.f)), run(s.run)
|
||||
{
|
||||
s.run = false;
|
||||
}
|
||||
|
||||
Final_act& operator=(const Final_act& s) = delete;
|
||||
|
||||
Final_act& operator=(Final_act&& s)
|
||||
{
|
||||
f = std::move(s.f);
|
||||
run = s.run;
|
||||
s.run = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void release() { run = false; }
|
||||
};
|
||||
|
||||
template <bool b, typename T, typename U>
|
||||
struct if_type_else_type { };
|
||||
|
||||
template <typename T, typename U>
|
||||
struct if_type_else_type<true, T, U> { typedef T type; };
|
||||
|
||||
template <typename T, typename U>
|
||||
struct if_type_else_type<false, T, U> { typedef U type; };
|
||||
|
||||
template <bool b, typename T, typename U>
|
||||
using if_type_else_type_t = typename if_type_else_type<b, T, U>::type;
|
||||
|
||||
// finally() - convenience function to generate a Final_act
|
||||
template <class F>
|
||||
Final_act<F> finally(F f) { return Final_act<F>(f); }
|
||||
template <typename F_t, typename Final_act_t = if_type_else_type_t<
|
||||
noexcept(std::declval<F_t&>()()),
|
||||
Final_act_noexcept<F_t>, Final_act<F_t>>>
|
||||
auto finally(F_t f) {
|
||||
return Final_act_t(std::move(f));
|
||||
}
|
||||
|
||||
// narrow_cast(): a searchable way to do narrowing casts of values
|
||||
template<class T, class U>
|
||||
|
@ -87,6 +87,20 @@ add_test(
|
||||
COMMAND bounds_tests
|
||||
)
|
||||
|
||||
add_executable(final_act_tests
|
||||
final_act_tests.cpp
|
||||
)
|
||||
target_link_libraries(final_act_tests
|
||||
UnitTest++
|
||||
)
|
||||
install(TARGETS final_act_tests
|
||||
RUNTIME DESTINATION bin
|
||||
)
|
||||
add_test(
|
||||
NAME final_act_tests
|
||||
COMMAND final_act_tests
|
||||
)
|
||||
|
||||
add_executable(maybenull_tests
|
||||
maybenull_tests.cpp
|
||||
)
|
||||
|
70
tests/final_act_tests.cpp
Normal file
70
tests/final_act_tests.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <UnitTest++/UnitTest++.h>
|
||||
#include <gsl.h>
|
||||
#include <exception>
|
||||
|
||||
using namespace std;
|
||||
using namespace Guide;
|
||||
|
||||
struct Increment {
|
||||
int* i_;
|
||||
|
||||
Increment(int& i) : i_(&i) {}
|
||||
|
||||
void operator()() const noexcept { ++*i_; }
|
||||
};
|
||||
|
||||
struct ThrowOnInvocation {
|
||||
class Exception : public exception {};
|
||||
void operator()() const { throw Exception(); }
|
||||
};
|
||||
|
||||
SUITE(finallyTests) {
|
||||
TEST(SingleInvocationOnConvenienceConstruction) {
|
||||
int i = 0;
|
||||
{ auto f = finally(Increment(i)); }
|
||||
CHECK(i == 1);
|
||||
}
|
||||
|
||||
TEST(SingleInvocationOnMoveConstruction) {
|
||||
int i = 0;
|
||||
{
|
||||
auto f = Final_act<Increment>(Increment(i));
|
||||
auto ff(move(f));
|
||||
}
|
||||
CHECK(i == 1);
|
||||
}
|
||||
|
||||
TEST(NoexceptFinalActIsCreated) {
|
||||
int i = 0;
|
||||
auto f = finally(Increment(i));
|
||||
CHECK((is_same<decltype(f), Final_act_noexcept<Increment>>::value));
|
||||
}
|
||||
|
||||
TEST(FinalActDoesNotThrow) {
|
||||
bool exceptionCaught = false;
|
||||
try {
|
||||
finally(ThrowOnInvocation());
|
||||
} catch (...) {
|
||||
exceptionCaught = true;
|
||||
}
|
||||
CHECK(!exceptionCaught);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, const char* []) { return UnitTest::RunAllTests(); }
|
Loading…
Reference in New Issue
Block a user