/*
- * 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include <folly/experimental/FutureDAG.h>
-#include <gtest/gtest.h>
#include <boost/thread/barrier.hpp>
+#include <folly/experimental/FutureDAG.h>
+#include <folly/portability/GTest.h>
using namespace folly;
typedef FutureDAG::Handle Handle;
Handle add() {
- auto node = folly::make_unique<TestNode>(this);
+ auto node = std::make_unique<TestNode>(this);
auto handle = node->handle;
nodes.emplace(handle, std::move(node));
return handle;
}
+ void reset() {
+ Handle source_node;
+ std::unordered_set<Handle> memo;
+ for (auto& node : nodes) {
+ for (Handle handle : node.second->dependencies) {
+ memo.insert(handle);
+ }
+ }
+ for (auto& node : nodes) {
+ if (memo.find(node.first) == memo.end()) {
+ source_node = node.first;
+ }
+ }
+ for (auto it = nodes.cbegin(); it != nodes.cend();) {
+ if (it->first != source_node) {
+ it = nodes.erase(it);
+ } else {
+ ++it;
+ }
+ }
+ dag->reset();
+ }
+
+ void remove(Handle a) {
+ for (auto& node : nodes) {
+ node.second->dependencies.erase(a);
+ }
+ nodes.erase(a);
+ dag->remove(a);
+ }
+
void dependency(Handle a, Handle b) {
- nodes.at(b)->dependencies.push_back(a);
+ nodes.at(b)->dependencies.insert(a);
dag->dependency(a, b);
}
}
struct TestNode {
- explicit TestNode(FutureDAGTest* test) {
- func = [this, test] {
- test->order.push_back(handle);
- return Future<Unit>();
- };
- handle = test->dag->add(func);
- }
+ explicit TestNode(FutureDAGTest* test)
+ : func([this, test] {
+ test->order.push_back(handle);
+ return Future<Unit>();
+ }),
+ handle(test->dag->add(func)) {}
- FutureDAG::FutureFunc func;
- Handle handle;
- std::vector<Handle> dependencies;
+ const FutureDAG::FutureFunc func;
+ const Handle handle;
+ std::set<Handle> dependencies;
};
- std::shared_ptr<FutureDAG> dag = FutureDAG::create();
+ const std::shared_ptr<FutureDAG> dag = FutureDAG::create();
std::map<Handle, std::unique_ptr<TestNode>> nodes;
std::vector<Handle> order;
};
-
TEST_F(FutureDAGTest, SingleNode) {
add();
ASSERT_NO_THROW(dag->go().get());
checkOrder();
}
+TEST_F(FutureDAGTest, RemoveSingleNode) {
+ auto h1 = add();
+ auto h2 = add();
+ remove(h2);
+ ASSERT_NO_THROW(dag->go().get());
+ checkOrder();
+}
+
+TEST_F(FutureDAGTest, RemoveNodeComplex) {
+ auto h1 = add();
+ auto h2 = add();
+ auto h3 = add();
+ dependency(h1, h3);
+ dependency(h2, h1);
+ remove(h3);
+ remove(h2);
+ remove(h1);
+ ASSERT_NO_THROW(dag->go().get());
+ checkOrder();
+}
+
+TEST_F(FutureDAGTest, ResetDAG) {
+ auto h1 = add();
+ auto h2 = add();
+ auto h3 = add();
+ dependency(h3, h1);
+ dependency(h2, h3);
+
+ reset();
+ ASSERT_NO_THROW(dag->go().get());
+ checkOrder();
+}
+
TEST_F(FutureDAGTest, FanOut) {
auto h1 = add();
auto h2 = add();
checkOrder();
}
-FutureDAG::FutureFunc makeFutureFunc = []{
- return makeFuture();
-};
+FutureDAG::FutureFunc makeFutureFunc = [] { return makeFuture(); };
-FutureDAG::FutureFunc throwFunc = []{
+FutureDAG::FutureFunc throwFunc = [] {
return makeFuture<Unit>(std::runtime_error("oops"));
};
auto barrier = std::make_shared<boost::barrier>(2);
Future<Unit> f;
{
- auto dag = FutureDAG::create();
- auto h1 = dag->add([barrier] {
+ auto localDag = FutureDAG::create();
+ auto h1 = localDag->add([barrier] {
auto p = std::make_shared<Promise<Unit>>();
- std::thread t([p, barrier]{
+ std::thread t([p, barrier] {
barrier->wait();
p->setValue();
});
t.detach();
return p->getFuture();
});
- auto h2 = dag->add(makeFutureFunc);
- dag->dependency(h1, h2);
- f = dag->go();
+ auto h2 = localDag->add(makeFutureFunc);
+ localDag->dependency(h1, h2);
+ f = localDag->go();
}
barrier->wait();
ASSERT_NO_THROW(f.get());