Fix copyright lines
[folly.git] / folly / futures / test / ThenTest.cpp
index 4ba5398886d0b2d08249ae8e079dddaf432cfa2a..429a7714f757ee5cc32dc42b388b8485a9540654 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2015-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
-
 #include <folly/futures/Future.h>
+#include <folly/portability/GTest.h>
 
 #include <thread>
 
 using namespace folly;
 
+namespace {
 struct Widget {
   int v_, copied_, moved_;
   /* implicit */ Widget(int v) : v_(v), copied_(0), moved_(0) {}
@@ -37,6 +37,41 @@ struct Widget {
   }
 };
 
+struct CountedWidget : Widget {
+  static std::vector<Widget*> instances_;
+  bool alive = true;
+  /* implicit */ CountedWidget(int v) : Widget(v) {
+    instances_.push_back(this);
+  }
+  CountedWidget(const CountedWidget& other) : Widget(other) {
+    instances_.push_back(this);
+  }
+  CountedWidget(CountedWidget&& other) noexcept(false)
+      : Widget(std::move(other)) {
+    other.alive = false;
+    other.remove();
+    instances_.push_back(this);
+  }
+  ~CountedWidget() {
+    if (alive) {
+      remove();
+    }
+  }
+
+ private:
+  CountedWidget& operator=(const CountedWidget&) = delete;
+  CountedWidget& operator=(CountedWidget&&) = delete;
+
+  void remove() {
+    auto iter = std::find(instances_.begin(), instances_.end(), this);
+    EXPECT_TRUE(iter != instances_.end());
+    instances_.erase(iter);
+  }
+};
+
+std::vector<Widget*> CountedWidget::instances_;
+} // namespace
+
 TEST(Then, tryConstructor) {
   auto t = Try<Widget>(23);
   EXPECT_EQ(t.value().v_, 23);
@@ -171,6 +206,29 @@ TEST(Then, constValue) {
   EXPECT_EQ(future.value(), 23);
 }
 
+TEST(Then, objectAliveDuringImmediateNoParamContinuation) {
+  auto f = makeFuture<CountedWidget>(23);
+  auto called = false;
+  f.then([&] {
+    EXPECT_EQ(CountedWidget::instances_.size(), 1u);
+    EXPECT_EQ(CountedWidget::instances_[0]->v_, 23);
+    called = true;
+  });
+  EXPECT_EQ(true, called);
+}
+
+TEST(Then, objectAliveDuringDeferredNoParamContinuation) {
+  auto p = Promise<CountedWidget>{};
+  bool called = false;
+  p.getFuture().then([&] {
+    EXPECT_EQ(CountedWidget::instances_.size(), 1u);
+    EXPECT_EQ(CountedWidget::instances_[0]->v_, 23);
+    called = true;
+  });
+  p.setValue(CountedWidget{23});
+  EXPECT_EQ(true, called);
+}
+
 TEST(Then, voidThenShouldPropagateExceptions) {
   EXPECT_FALSE(makeFuture(42).then().hasException());
   EXPECT_TRUE(makeFuture<int>(std::runtime_error("err"))