/*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
#include <folly/ScopeGuard.h>
-#include <folly/Portability.h>
-#include <gflags/gflags.h>
-#include <gtest/gtest.h>
#include <glog/logging.h>
#include <functional>
#include <stdexcept>
+#include <folly/portability/GTest.h>
+
using folly::ScopeGuard;
using folly::makeGuard;
using std::vector;
// There is implicit conversion from func pointer
// double (*)() to function<void()>.
ScopeGuard g = makeGuard(returnsDouble);
+ (void)g;
}
vector<int> v;
{
// binding to member function.
ScopeGuard g = makeGuard(std::bind(&vector<int>::pop_back, &v));
+ (void)g;
}
EXPECT_EQ(0, v.size());
{
// bind member function with args. v is passed-by-value!
ScopeGuard g = makeGuard(std::bind(push_back, v, 2));
+ (void)g;
}
EXPECT_EQ(0, v.size()); // push_back happened on a copy of v... fail!
// pass in an argument by pointer so to avoid copy.
{
ScopeGuard g = makeGuard(std::bind(push_back, &v, 4));
+ (void)g;
}
EXPECT_EQ(1, v.size());
{
// pass in an argument by reference so to avoid copy.
ScopeGuard g = makeGuard(std::bind(push_back, std::ref(v), 4));
+ (void)g;
}
EXPECT_EQ(2, v.size());
// lambda with a reference to v
{
ScopeGuard g = makeGuard([&] { v.push_back(5); });
+ (void)g;
}
EXPECT_EQ(3, v.size());
// lambda with a copy of v
{
ScopeGuard g = makeGuard([v] () mutable { v.push_back(6); });
+ (void)g;
}
EXPECT_EQ(3, v.size());
{
MyFunctor f(&n);
ScopeGuard g = makeGuard(f);
+ (void)g;
}
EXPECT_EQ(1, n);
n = 0;
{
ScopeGuard g = makeGuard(MyFunctor(&n));
+ (void)g;
}
EXPECT_EQ(1, n);
n = 2;
{
auto g = makeGuard(MyFunctor(&n));
+ (void)g;
}
EXPECT_EQ(3, n);
n = 10;
{
const auto& g = makeGuard(MyFunctor(&n));
+ (void)g;
}
EXPECT_EQ(11, n);
}
ScopeGuard g = makeGuard([&] {
throw std::runtime_error("destructors should never throw!");
});
+ (void)g;
},
"destructors should never throw!"
);
try {
ScopeGuard guard = makeGuard([&] { cleanupOccurred = true; });
+ (void)guard;
try {
if (error == ErrorBehavior::HANDLED_ERROR) {
}
class Foo {
-public:
+ public:
Foo() {}
~Foo() {
try {
EXPECT_THROW(lambda(), std::runtime_error);
}
-int main(int argc, char** argv) {
- testing::InitGoogleTest(&argc, argv);
- gflags::ParseCommandLineFlags(&argc, &argv, true);
- return RUN_ALL_TESTS();
+TEST(ScopeGuard, TEST_THROWING_CLEANUP_ACTION) {
+ struct ThrowingCleanupAction {
+ explicit ThrowingCleanupAction(int& scopeExitExecuted)
+ : scopeExitExecuted_(scopeExitExecuted) {}
+ [[noreturn]]
+ ThrowingCleanupAction(const ThrowingCleanupAction& other)
+ : scopeExitExecuted_(other.scopeExitExecuted_) {
+ throw std::runtime_error("whoa");
+ }
+ void operator()() { ++scopeExitExecuted_; }
+
+ private:
+ int& scopeExitExecuted_;
+ };
+ int scopeExitExecuted = 0;
+ ThrowingCleanupAction onExit(scopeExitExecuted);
+ EXPECT_THROW(makeGuard(onExit), std::runtime_error);
+ EXPECT_EQ(scopeExitExecuted, 1);
}