Add first version
[ric-plt/sdl.git] / tst / eventfd_test.cpp
diff --git a/tst/eventfd_test.cpp b/tst/eventfd_test.cpp
new file mode 100644 (file)
index 0000000..c383bc6
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+   Copyright (c) 2018-2019 Nokia.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+#include <type_traits>
+#include <memory>
+#include <cstdint>
+#include <sys/eventfd.h>
+#include <gmock/gmock.h>
+#include "private/eventfd.hpp"
+#include "private/timerfd.hpp"
+#include "private/tst/systemmock.hpp"
+#include "private/tst/enginemock.hpp"
+
+using namespace shareddatalayer;
+using namespace shareddatalayer::tst;
+using namespace testing;
+
+namespace
+{
+    class EventFDTest: public testing::Test
+    {
+    public:
+        const int efd;
+        NiceMock<SystemMock> systemMock;
+        EngineMock engineMock;
+        std::unique_ptr<EventFD> eventFD;
+        Engine::EventHandler savedEventHandler;
+
+        EventFDTest(): efd(123)
+        {
+            InSequence dummy;
+            EXPECT_CALL(systemMock, eventfd(0U, EFD_CLOEXEC | EFD_NONBLOCK))
+                .Times(1)
+                .WillOnce(Return(efd));
+            EXPECT_CALL(engineMock, addMonitoredFD(Matcher<FileDescriptor&>(_), Engine::EVENT_IN, _))
+                .Times(1)
+                .WillOnce(Invoke([this] (FileDescriptor& fd, unsigned int, const Engine::EventHandler& eh)
+                                 {
+                                     EXPECT_EQ(efd, static_cast<int>(fd));
+                                     savedEventHandler = eh;
+                                 }));
+            eventFD.reset(new EventFD(systemMock, engineMock));
+            Mock::VerifyAndClear(&systemMock);
+            Mock::VerifyAndClear(&engineMock);
+        }
+
+        void expectWrite()
+        {
+            EXPECT_CALL(systemMock, write(efd, NotNull(), sizeof(uint64_t)))
+                .Times(1)
+                .WillOnce(Invoke([] (int, const void* buf, size_t) -> ssize_t
+                                 {
+                                     EXPECT_EQ(1U, *static_cast<const uint64_t*>(buf));
+                                     return sizeof(uint64_t);
+                                 }));
+        }
+
+        void expectRead()
+        {
+            EXPECT_CALL(systemMock, read(efd, NotNull(), sizeof(uint64_t)))
+                .Times(1)
+                .WillOnce(Return(sizeof(uint64_t)));
+        }
+
+        void post(const EventFD::Callback& callback)
+        {
+            eventFD->post(callback);
+        }
+
+        void post(int i)
+        {
+            post(std::bind(&EventFDTest::callback, this, i));
+        }
+
+        MOCK_METHOD1(callback, void(int i));
+    };
+}
+
+TEST_F(EventFDTest, IsNotCopyableAndIsNotMovable)
+{
+    EXPECT_FALSE(std::is_copy_assignable<EventFD>::value);
+    EXPECT_FALSE(std::is_move_assignable<EventFD>::value);
+    EXPECT_FALSE(std::is_copy_constructible<EventFD>::value);
+    EXPECT_FALSE(std::is_move_constructible<EventFD>::value);
+}
+
+TEST_F(EventFDTest, PostWritesToEventFD)
+{
+    expectWrite();
+    post(1);
+}
+
+TEST_F(EventFDTest, HandleEventsExecutesAllCallbacksInFIFOOrder)
+{
+    post(1);
+    post(2);
+    InSequence dummy;
+    expectRead();
+    EXPECT_CALL(*this, callback(1))
+        .Times(1);
+    EXPECT_CALL(*this, callback(2))
+        .Times(1);
+    savedEventHandler(Engine::EVENT_IN);
+}
+
+TEST_F(EventFDTest, CallbacksAddedInPostAreNotExecutedDuringTheSameHandleEvents)
+{
+    post([this] () { post(1); });
+    InSequence dummy;
+    expectRead();
+    EXPECT_CALL(*this, callback(_))
+        .Times(0);
+    savedEventHandler(Engine::EVENT_IN);
+}
+
+TEST_F(EventFDTest, ExecutedCallbackIsDestroyedBeforeExecutingTheNextCallback)
+{
+    std::shared_ptr<int> data(std::make_shared<int>(1));
+    std::weak_ptr<int> weak(data);
+    post([data] () { static_cast<void>(data); });
+    data.reset();
+    post([weak] () { EXPECT_EQ(nullptr, weak.lock()); });
+    savedEventHandler(Engine::EVENT_IN);
+}
+
+TEST_F(EventFDTest, PostingNullCallbackCallsSHAREDDATALAYER_ABORT)
+{
+    EXPECT_EXIT(post(EventFD::Callback()),
+         KilledBySignal(SIGABRT), "ABORT.*eventfd\\.cpp");
+}