folly copyright 2015 -> copyright 2016
[folly.git] / folly / io / async / test / NotificationQueueTest.cpp
index c831ee10debef0664ef5fb7c35438ac76d7064e1..f8e1e51ab01e9e7c94a328cb9c6ca411c76af7d9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015 Facebook, Inc.
+ * Copyright 2016 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -360,15 +360,16 @@ void QueueTest::destroyCallback() {
   // avoid destroying the function object.
   class DestroyTestConsumer : public IntQueue::Consumer {
    public:
-    DestroyTestConsumer() {}
-
     void messageAvailable(int&& value) override {
+      DestructorGuard g(this);
       if (fn && *fn) {
         (*fn)(value);
       }
     }
 
     std::function<void(int)> *fn;
+   protected:
+    virtual ~DestroyTestConsumer() = default;
   };
 
   EventBase eventBase;
@@ -381,11 +382,13 @@ void QueueTest::destroyCallback() {
   // This way one consumer will be destroyed from inside its messageAvailable()
   // callback, and one consume will be destroyed when it isn't inside
   // messageAvailable().
-  std::unique_ptr<DestroyTestConsumer> consumer1(new DestroyTestConsumer);
-  std::unique_ptr<DestroyTestConsumer> consumer2(new DestroyTestConsumer);
+  std::unique_ptr<DestroyTestConsumer, DelayedDestruction::Destructor>
+    consumer1(new DestroyTestConsumer);
+  std::unique_ptr<DestroyTestConsumer, DelayedDestruction::Destructor>
+    consumer2(new DestroyTestConsumer);
   std::function<void(int)> fn = [&](int) {
-    consumer1.reset();
-    consumer2.reset();
+    consumer1 = nullptr;
+    consumer2 = nullptr;
   };
   consumer1->fn = &fn;
   consumer2->fn = &fn;
@@ -433,9 +436,7 @@ TEST(NotificationQueueTest, ConsumeUntilDrained) {
 
   // Make sure there can only be one drainer at once
   folly::Baton<> callbackBaton, threadStartBaton;
-  consumer.fn = [&](int i) {
-    callbackBaton.wait();
-  };
+  consumer.fn = [&](int /* i */) { callbackBaton.wait(); };
   QueueConsumer competingConsumer;
   competingConsumer.startConsuming(&eventBase, &queue);
   queue.putMessage(1);
@@ -484,9 +485,7 @@ TEST(NotificationQueueTest, ConsumeUntilDrainedStress) {
 
     // Make sure there can only be one drainer at once
     folly::Baton<> callbackBaton, threadStartBaton;
-    consumer.fn = [&](int i) {
-      callbackBaton.wait();
-    };
+    consumer.fn = [&](int /* i */) { callbackBaton.wait(); };
     QueueConsumer competingConsumer;
     competingConsumer.startConsuming(&eventBase, &queue);
     queue.putMessage(1);
@@ -569,11 +568,11 @@ TEST(NotificationQueueTest, DestroyCallbackPipe) {
 }
 
 /*
- * Test code that creates a TNotificationQueue, then forks, and incorrectly
+ * Test code that creates a NotificationQueue, then forks, and incorrectly
  * tries to send a message to the queue from the child process.
  *
  * The child process should crash in this scenario, since the child code has a
- * bug.  (Older versions of TNotificationQueue didn't catch this in the child,
+ * bug.  (Older versions of NotificationQueue didn't catch this in the child,
  * resulting in a crash in the parent process.)
  */
 TEST(NotificationQueueTest, UseAfterFork) {
@@ -617,6 +616,7 @@ TEST(NotificationQueueTest, UseAfterFork) {
       // We shouldn't reach here.
       _exit(0);
     }
+    PCHECK(pid > 0);
 
     // Parent.  Wait for the child to exit.
     auto waited = waitpid(pid, &childStatus, 0);
@@ -627,7 +627,7 @@ TEST(NotificationQueueTest, UseAfterFork) {
   }
 
   // The child process should have crashed when it tried to call putMessage()
-  // on our TNotificationQueue.
+  // on our NotificationQueue.
   EXPECT_TRUE(WIFSIGNALED(childStatus));
   EXPECT_EQ(SIGABRT, WTERMSIG(childStatus));
 
@@ -640,3 +640,21 @@ TEST(NotificationQueueTest, UseAfterFork) {
   EXPECT_EQ(5678, consumer.messages.front());
   consumer.messages.pop_front();
 }
+
+TEST(NotificationQueueConsumer, make) {
+  int value = 0;
+  EventBase evb;
+  NotificationQueue<int> queue(32);
+
+  auto consumer = decltype(queue)::Consumer::make([&](
+      int&& msg) noexcept { value = msg; });
+
+  consumer->startConsuming(&evb, &queue);
+
+  int const newValue = 10;
+  queue.tryPutMessage(newValue);
+
+  evb.loopOnce();
+
+  EXPECT_EQ(newValue, value);
+}