| /* |
| 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 <sys/epoll.h> |
| #include <async.h> |
| #include <gtest/gtest.h> |
| #include "private/redis/hiredisepolladapter.hpp" |
| #include "private/tst/enginemock.hpp" |
| #include "private/tst/hiredissystemmock.hpp" |
| |
| using namespace shareddatalayer; |
| using namespace shareddatalayer::redis; |
| using namespace shareddatalayer::tst; |
| using namespace testing; |
| |
| namespace |
| { |
| class HiredisEpollAdapterTest: public testing::Test |
| { |
| public: |
| StrictMock<EngineMock> engineMock; |
| StrictMock<HiredisSystemMock> hiredisSystemMock; |
| redisAsyncContext ac; |
| int acFd; |
| std::unique_ptr<HiredisEpollAdapter> adapter; |
| Engine::EventHandler savedEventHandler; |
| |
| HiredisEpollAdapterTest(): |
| ac { }, |
| acFd(10) |
| { |
| ac.c.fd = acFd; |
| adapter.reset(new HiredisEpollAdapter(engineMock, hiredisSystemMock)); |
| } |
| |
| void expectAddMonitoredFD(int fd, unsigned int events) |
| { |
| EXPECT_CALL(engineMock, addMonitoredFD(fd,events,_)) |
| .Times(1) |
| .WillOnce(SaveArg<2>(&savedEventHandler)); |
| } |
| |
| void expectModifyMonitoredFD(int fd, unsigned int events) |
| { |
| EXPECT_CALL(engineMock, modifyMonitoredFD(fd,events)) |
| .Times(1); |
| } |
| |
| void expectDeleteMonitoredFD(int fd) |
| { |
| EXPECT_CALL(engineMock, deleteMonitoredFD(fd)) |
| .Times(1); |
| } |
| }; |
| |
| class HiredisEpollAdapterAttachedTest: public HiredisEpollAdapterTest |
| { |
| public: |
| HiredisEpollAdapterAttachedTest() |
| { |
| expectAddMonitoredFD(ac.c.fd, 0); |
| adapter->attach(&ac); |
| } |
| |
| ~HiredisEpollAdapterAttachedTest() |
| { |
| expectDeleteMonitoredFD(ac.c.fd); |
| } |
| }; |
| } |
| |
| TEST_F(HiredisEpollAdapterTest, IsNotCopyable) |
| { |
| EXPECT_FALSE(std::is_copy_constructible<HiredisEpollAdapter>::value); |
| EXPECT_FALSE(std::is_copy_assignable<HiredisEpollAdapter>::value); |
| } |
| |
| TEST_F(HiredisEpollAdapterAttachedTest, CanHandleInputEvents) |
| { |
| InSequence dummy; |
| expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN); |
| ac.ev.addRead(ac.ev.data); |
| EXPECT_CALL(hiredisSystemMock, redisAsyncHandleRead(&ac)) |
| .Times(1); |
| savedEventHandler(EngineMock::EVENT_IN); |
| } |
| |
| TEST_F(HiredisEpollAdapterAttachedTest, DoesNotHandleInputEventIfNotReading) |
| { |
| InSequence dummy; |
| EXPECT_CALL(hiredisSystemMock, redisAsyncHandleRead(&ac)) |
| .Times(0); |
| savedEventHandler(EngineMock::EVENT_IN); |
| } |
| |
| TEST_F(HiredisEpollAdapterAttachedTest, CanHandleOutputEvents) |
| { |
| InSequence dummy; |
| expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_OUT); |
| ac.ev.addWrite(ac.ev.data); |
| EXPECT_CALL(hiredisSystemMock, redisAsyncHandleWrite(&ac)) |
| .Times(1); |
| savedEventHandler(EngineMock::EVENT_OUT); |
| } |
| |
| TEST_F(HiredisEpollAdapterAttachedTest, DoesNotHandleOutputEventIfNotWriting) |
| { |
| InSequence dummy; |
| EXPECT_CALL(hiredisSystemMock, redisAsyncHandleWrite(&ac)) |
| .Times(0); |
| savedEventHandler(EngineMock::EVENT_OUT); |
| } |
| |
| TEST_F(HiredisEpollAdapterAttachedTest, CanBeAttachedAndEventStateChangedIdempotently) |
| { |
| InSequence dummy; |
| EXPECT_EQ(adapter.get(), ac.ev.data); |
| expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN); |
| ac.ev.addRead(ac.ev.data); |
| expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN | EngineMock::EVENT_OUT); |
| ac.ev.addWrite(ac.ev.data); |
| expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_OUT); |
| ac.ev.delRead(ac.ev.data); |
| expectModifyMonitoredFD(ac.c.fd, 0); |
| ac.ev.delWrite(ac.ev.data); |
| expectModifyMonitoredFD(ac.c.fd,EngineMock::EVENT_IN); |
| ac.ev.addRead(ac.ev.data); |
| expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN | EngineMock::EVENT_OUT); |
| ac.ev.addWrite(ac.ev.data); |
| expectDeleteMonitoredFD(ac.c.fd); |
| ac.ev.cleanup(ac.ev.data); |
| expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_OUT); |
| ac.ev.addWrite(ac.ev.data); |
| expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN | EngineMock::EVENT_OUT); |
| ac.ev.addRead(ac.ev.data); |
| expectAddMonitoredFD(ac.c.fd, 0); |
| adapter->attach(&ac); |
| } |
| |
| TEST_F(HiredisEpollAdapterAttachedTest, FurtherAttachementsResetEventState) |
| { |
| InSequence dummy; |
| expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN); |
| ac.ev.addRead(ac.ev.data); |
| expectAddMonitoredFD(ac.c.fd, 0); |
| adapter->attach(&ac); |
| expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_OUT); |
| ac.ev.addWrite(ac.ev.data); |
| } |
| |
| TEST_F(HiredisEpollAdapterAttachedTest, InputEventIsSetOnce) |
| { |
| InSequence dummy; |
| expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_IN); |
| ac.ev.addRead(ac.ev.data); |
| ac.ev.addRead(ac.ev.data); |
| } |
| |
| TEST_F(HiredisEpollAdapterAttachedTest, OutputEventIsSetOnce) |
| { |
| InSequence dummy; |
| expectModifyMonitoredFD(ac.c.fd, EngineMock::EVENT_OUT); |
| ac.ev.addWrite(ac.ev.data); |
| ac.ev.addWrite(ac.ev.data); |
| } |
| |
| TEST_F(HiredisEpollAdapterAttachedTest, MakesCleanupIfDestructedWhileAttahced) |
| { |
| InSequence dummy; |
| expectDeleteMonitoredFD(ac.c.fd); |
| adapter.reset(new HiredisEpollAdapter(engineMock, hiredisSystemMock)); |
| expectAddMonitoredFD(ac.c.fd, 0); |
| adapter->attach(&ac); |
| } |
| |
| TEST_F(HiredisEpollAdapterTest, DoesNotMakeCleanupIfDestructedWhileNotAttahced) |
| { |
| InSequence dummy; |
| adapter.reset(new HiredisEpollAdapter(engineMock, hiredisSystemMock)); |
| } |