Add synchronous SDL readiness waiting API
[ric-plt/sdl.git] / tst / syncstorageimpl_test.cpp
1 /*
2    Copyright (c) 2018-2019 Nokia.
3
4    Licensed under the Apache License, Version 2.0 (the "License");
5    you may not use this file except in compliance with the License.
6    You may obtain a copy of the License at
7
8        http://www.apache.org/licenses/LICENSE-2.0
9
10    Unless required by applicable law or agreed to in writing, software
11    distributed under the License is distributed on an "AS IS" BASIS,
12    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13    See the License for the specific language governing permissions and
14    limitations under the License.
15 */
16
17 /*
18  * This source code is part of the near-RT RIC (RAN Intelligent Controller)
19  * platform project (RICP).
20 */
21
22 #include <gtest/gtest.h>
23 #include "private/error.hpp"
24 #include "private/redis/asyncredisstorage.hpp"
25 #include "private/syncstorageimpl.hpp"
26 #include "private/tst/asyncstoragemock.hpp"
27 #include "private/tst/systemmock.hpp"
28 #include <sdl/backenderror.hpp>
29 #include <sdl/invalidnamespace.hpp>
30 #include <sdl/notconnected.hpp>
31 #include <sdl/operationinterrupted.hpp>
32 #include <sdl/rejectedbybackend.hpp>
33 #include <sdl/rejectedbysdl.hpp>
34
35 using namespace shareddatalayer;
36 using namespace shareddatalayer::redis;
37 using namespace shareddatalayer::tst;
38 using namespace testing;
39
40 namespace
41 {
42     class SyncStorageImplTest: public testing::Test
43     {
44     public:
45         std::unique_ptr<SyncStorageImpl> syncStorage;
46         /* AsyncStorageMock ownership will be passed to implementation. To be able to do verification
47          * with the mock object also here after its ownership is passed we take raw pointer to
48          * AsyncStorageMock before passing it to implementation. Works fine, as implementation will
49          * not release injected mock object before test case execution finishes
50          */
51         std::unique_ptr<StrictMock<AsyncStorageMock>> asyncStorageMockPassedToImplementation;
52         StrictMock<AsyncStorageMock>* asyncStorageMockRawPtr;
53         StrictMock<SystemMock> systemMock;
54         AsyncStorage::ModifyAck savedModifyAck;
55         AsyncStorage::ModifyIfAck savedModifyIfAck;
56         AsyncStorage::GetAck savedGetAck;
57         AsyncStorage::FindKeysAck savedFindKeysAck;
58         AsyncStorage::ReadyAck savedReadyAck;
59         int pFd;
60         SyncStorage::DataMap dataMap;
61         SyncStorage::Keys keys;
62         const SyncStorage::Namespace ns;
63         std::chrono::steady_clock::duration TEST_READY_WAIT_TIMEOUT;
64         std::chrono::steady_clock::duration TEST_OPERATION_WAIT_TIMEOUT;
65         int TEST_READY_POLL_WAIT_TIMEOUT;
66         int TEST_OPERATION_POLL_WAIT_TIMEOUT;
67         SyncStorageImplTest():
68             asyncStorageMockPassedToImplementation(new StrictMock<AsyncStorageMock>()),
69             asyncStorageMockRawPtr(asyncStorageMockPassedToImplementation.get()),
70             pFd(10),
71             dataMap({{ "key1", { 0x0a, 0x0b, 0x0c } }, { "key2", { 0x0d, 0x0e, 0x0f, 0xff } }}),
72             keys({ "key1", "key2" }),
73             ns("someKnownNamespace"),
74             TEST_READY_WAIT_TIMEOUT(std::chrono::minutes(1)),
75             TEST_OPERATION_WAIT_TIMEOUT(std::chrono::seconds(1)),
76             TEST_READY_POLL_WAIT_TIMEOUT(std::chrono::duration_cast<std::chrono::milliseconds>(TEST_READY_WAIT_TIMEOUT).count() / 10),
77             TEST_OPERATION_POLL_WAIT_TIMEOUT(std::chrono::duration_cast<std::chrono::milliseconds>(TEST_OPERATION_WAIT_TIMEOUT).count() / 10)
78         {
79             expectConstructorCalls();
80             syncStorage.reset(new SyncStorageImpl(std::move(asyncStorageMockPassedToImplementation), systemMock));
81         }
82
83         ~SyncStorageImplTest()
84         {
85             syncStorage->setOperationTimeout(std::chrono::steady_clock::duration::zero());
86         }
87
88         void expectConstructorCalls()
89         {
90             InSequence dummy;
91             EXPECT_CALL(*asyncStorageMockRawPtr, fd())
92                 .Times(1)
93                 .WillOnce(Return(pFd));
94         }
95
96         void expectSdlReadinessCheck(int timeout)
97         {
98             InSequence dummy;
99             expectPollForPendingEvents_ReturnNoEvents();
100             expectWaitReadyAsync();
101             expectPollWait(timeout);
102             expectHandleEvents_callWaitReadyAck();
103         }
104
105         void expectPollForPendingEvents_ReturnNoEvents()
106         {
107             EXPECT_CALL(systemMock, poll( _, 1, 0))
108                 .Times(1)
109                 .WillOnce(Invoke([](struct pollfd *, nfds_t, int)
110                                  {
111                                      return 0;
112                                  }));
113         }
114
115         void expectPollWait(int timeout)
116         {
117             EXPECT_CALL(systemMock, poll( _, 1, timeout))
118                 .Times(1)
119                 .WillOnce(Invoke([](struct pollfd *fds, nfds_t, int)
120                                  {
121                                      fds->revents = POLLIN;
122                                      return 1;
123                                  }));
124         }
125
126         void expectPollError()
127         {
128             EXPECT_CALL(systemMock, poll( _, 1, -1))
129                 .Times(1)
130                 .WillOnce(Invoke([](struct pollfd *fds, nfds_t, int)
131                                  {
132                                      fds->revents = POLLIN;
133                                      return -1;
134                                  }));
135         }
136
137         void expectPollExceptionalCondition()
138         {
139             EXPECT_CALL(systemMock, poll( _, 1, -1))
140                 .Times(1)
141                 .WillOnce(Invoke([](struct pollfd *fds, nfds_t, int)
142                                  {
143                                      fds->revents = POLLPRI;
144                                      return 1;
145                                  }));
146         }
147
148         void expectHandleEvents()
149         {
150             EXPECT_CALL(*asyncStorageMockRawPtr, handleEvents())
151                 .Times(1);
152         }
153
154         void expectHandleEvents_callWaitReadyAck()
155         {
156             EXPECT_CALL(*asyncStorageMockRawPtr, handleEvents())
157                 .Times(1)
158                 .WillOnce(Invoke([this]()
159                                  {
160                                     savedReadyAck(std::error_code());
161                                  }));
162         }
163
164         void expectHandleEvents_callWaitReadyAckWithError()
165         {
166             EXPECT_CALL(*asyncStorageMockRawPtr, handleEvents())
167                 .Times(1)
168                 .WillOnce(Invoke([this]()
169                                  {
170                                     savedReadyAck(AsyncRedisCommandDispatcherErrorCode::NOT_CONNECTED);
171                                  }));
172         }
173
174         void expectHandleEvents_callModifyAck()
175         {
176             EXPECT_CALL(*asyncStorageMockRawPtr, handleEvents())
177                 .Times(1)
178                 .WillOnce(Invoke([this]()
179                                  {
180                                     savedModifyAck(std::error_code());
181                                  }));
182         }
183
184         void expectWaitReadyAsync()
185         {
186             EXPECT_CALL(*asyncStorageMockRawPtr, waitReadyAsync(ns,_))
187                 .Times(1)
188                 .WillOnce(SaveArg<1>(&savedReadyAck));
189         }
190
191         void expectModifyAckWithError()
192         {
193             EXPECT_CALL(*asyncStorageMockRawPtr, handleEvents())
194                 .Times(1)
195                 .WillOnce(Invoke([this]()
196                                  {
197                                     savedModifyAck(AsyncRedisCommandDispatcherErrorCode::OUT_OF_MEMORY);
198                                  }));
199         }
200
201         void expectModifyIfAck(const std::error_code& error, bool status)
202         {
203             EXPECT_CALL(*asyncStorageMockRawPtr, handleEvents())
204                 .Times(1)
205                 .WillOnce(Invoke([this, error, status]()
206                                  {
207                                     savedModifyIfAck(error, status);
208                                  }));
209         }
210
211         void expectGetAckWithError()
212         {
213             EXPECT_CALL(*asyncStorageMockRawPtr, handleEvents())
214                 .Times(1)
215                 .WillOnce(Invoke([this]()
216                                  {
217                                     savedGetAck(AsyncRedisCommandDispatcherErrorCode::OUT_OF_MEMORY, dataMap);
218                                  }));
219         }
220
221         void expectGetAck()
222         {
223             EXPECT_CALL(*asyncStorageMockRawPtr, handleEvents())
224                 .Times(1)
225                 .WillOnce(Invoke([this]()
226                                  {
227                                     savedGetAck(std::error_code(), dataMap);
228                                  }));
229         }
230
231         void expectFindKeysAck()
232         {
233             EXPECT_CALL(*asyncStorageMockRawPtr, handleEvents())
234                 .Times(1)
235                 .WillOnce(Invoke([this]()
236                                  {
237                                     savedFindKeysAck(std::error_code(), keys);
238                                  }));
239         }
240
241         void expectFindKeysAckWithError()
242         {
243             EXPECT_CALL(*asyncStorageMockRawPtr, handleEvents())
244                 .Times(1)
245                 .WillOnce(Invoke([this]()
246                                  {
247                                     savedFindKeysAck(AsyncRedisCommandDispatcherErrorCode::OUT_OF_MEMORY, keys);
248                                  }));
249         }
250
251         void expectSetAsync(const SyncStorage::DataMap& dataMap)
252         {
253             EXPECT_CALL(*asyncStorageMockRawPtr, setAsync(ns, dataMap, _))
254                 .Times(1)
255                 .WillOnce(SaveArg<2>(&savedModifyAck));
256         }
257
258         void expectSetIfAsync(const SyncStorage::Key& key, const SyncStorage::Data& oldData, const SyncStorage::Data& newData)
259         {
260             EXPECT_CALL(*asyncStorageMockRawPtr, setIfAsync(ns, key, oldData, newData, _))
261                 .Times(1)
262                 .WillOnce(SaveArg<4>(&savedModifyIfAck));
263         }
264
265         void expectGetAsync(const SyncStorage::Keys& keys)
266         {
267             EXPECT_CALL(*asyncStorageMockRawPtr, getAsync(ns, keys, _))
268                 .Times(1)
269                 .WillOnce(SaveArg<2>(&savedGetAck));
270         }
271
272         void expectFindKeysAsync()
273         {
274             EXPECT_CALL(*asyncStorageMockRawPtr, findKeysAsync(ns, _, _))
275                 .Times(1)
276                 .WillOnce(SaveArg<2>(&savedFindKeysAck));
277         }
278
279         void expectRemoveAsync(const SyncStorage::Keys& keys)
280         {
281             EXPECT_CALL(*asyncStorageMockRawPtr, removeAsync(ns, keys, _))
282                 .Times(1)
283                 .WillOnce(SaveArg<2>(&savedModifyAck));
284         }
285
286         void expectRemoveIfAsync(const SyncStorage::Key& key, const SyncStorage::Data& data)
287         {
288             EXPECT_CALL(*asyncStorageMockRawPtr, removeIfAsync(ns, key, data, _))
289                 .Times(1)
290                 .WillOnce(SaveArg<3>(&savedModifyIfAck));
291         }
292
293         void expectRemoveAllAsync()
294         {
295             EXPECT_CALL(*asyncStorageMockRawPtr, removeAllAsync(ns, _))
296                 .Times(1)
297                 .WillOnce(SaveArg<1>(&savedModifyAck));
298         }
299
300         void expectSetIfNotExistsAsync(const SyncStorage::Key& key, const SyncStorage::Data& data)
301         {
302             EXPECT_CALL(*asyncStorageMockRawPtr, setIfNotExistsAsync(ns, key, data, _))
303                 .Times(1)
304                 .WillOnce(SaveArg<3>(&savedModifyIfAck));
305         }
306     };
307 }
308
309 TEST_F(SyncStorageImplTest, IsNotCopyable)
310 {
311     InSequence dummy;
312     EXPECT_FALSE(std::is_copy_constructible<SyncStorageImpl>::value);
313     EXPECT_FALSE(std::is_copy_assignable<SyncStorageImpl>::value);
314 }
315
316 TEST_F(SyncStorageImplTest, ImplementssyncStorage)
317 {
318     InSequence dummy;
319     EXPECT_TRUE((std::is_base_of<SyncStorage, SyncStorageImpl>::value));
320 }
321
322 TEST_F(SyncStorageImplTest, EventsAreNotHandledWhenPollReturnsError)
323 {
324     InSequence dummy;
325     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
326     expectSetAsync(dataMap);
327     expectPollError();
328     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
329     expectHandleEvents_callModifyAck();
330     syncStorage->set(ns, dataMap);
331 }
332
333 TEST_F(SyncStorageImplTest, EventsAreNotHandledWhenThereIsAnExceptionalConditionOnTheFd)
334 {
335     InSequence dummy;
336     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
337     expectSetAsync(dataMap);
338     expectPollExceptionalCondition();
339     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
340     expectHandleEvents_callModifyAck();
341     syncStorage->set(ns, dataMap);
342 }
343
344 TEST_F(SyncStorageImplTest, WaitReadySuccessfully)
345 {
346     InSequence dummy;
347     expectWaitReadyAsync();
348     expectPollWait(TEST_READY_POLL_WAIT_TIMEOUT);
349     expectHandleEvents_callWaitReadyAck();
350     syncStorage->waitReady(ns, TEST_READY_WAIT_TIMEOUT);
351 }
352
353 TEST_F(SyncStorageImplTest, WaitReadyCanThrowRejectedBySdl)
354 {
355     InSequence dummy;
356     expectWaitReadyAsync();
357     EXPECT_THROW(syncStorage->waitReady(ns, std::chrono::nanoseconds(1)), RejectedBySdl);
358 }
359
360 TEST_F(SyncStorageImplTest, WaitReadyCanThrowNotConnected)
361 {
362     InSequence dummy;
363     expectWaitReadyAsync();
364     expectPollWait(TEST_READY_POLL_WAIT_TIMEOUT);
365     expectHandleEvents_callWaitReadyAckWithError();
366     EXPECT_THROW(syncStorage->waitReady(ns, TEST_READY_WAIT_TIMEOUT), NotConnected);
367 }
368
369 TEST_F(SyncStorageImplTest, SetSuccessfully)
370 {
371     InSequence dummy;
372     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
373     expectSetAsync(dataMap);
374     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
375     expectHandleEvents_callModifyAck();
376     syncStorage->set(ns, dataMap);
377 }
378
379 TEST_F(SyncStorageImplTest, SetWithReadinessTimeoutSuccessfully)
380 {
381     InSequence dummy;
382     expectSdlReadinessCheck(TEST_OPERATION_POLL_WAIT_TIMEOUT);
383     expectSetAsync(dataMap);
384     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
385     expectHandleEvents_callModifyAck();
386     syncStorage->setOperationTimeout(TEST_OPERATION_WAIT_TIMEOUT);
387     syncStorage->set(ns, dataMap);
388 }
389
390 TEST_F(SyncStorageImplTest, SetCanThrowBackendError)
391 {
392     InSequence dummy;
393     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
394     expectSetAsync(dataMap);
395     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
396     expectModifyAckWithError();
397     EXPECT_THROW(syncStorage->set(ns, dataMap), BackendError);
398 }
399
400 TEST_F(SyncStorageImplTest, SetIfSuccessfully)
401 {
402     InSequence dummy;
403     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
404     expectSetAsync(dataMap);
405     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
406     expectHandleEvents_callModifyAck();
407     syncStorage->set(ns, dataMap);
408     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
409     expectSetIfAsync("key1", { 0x0a, 0x0b, 0x0c }, { 0x0d, 0x0e, 0x0f });
410     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
411     expectHandleEvents_callModifyAck();
412     syncStorage->setIf(ns, "key1", { 0x0a, 0x0b, 0x0c }, { 0x0d, 0x0e, 0x0f });
413 }
414
415 TEST_F(SyncStorageImplTest, SetIfWithReadinessTimeoutSuccessfully)
416 {
417     InSequence dummy;
418     expectSdlReadinessCheck(TEST_OPERATION_POLL_WAIT_TIMEOUT);
419     expectSetAsync(dataMap);
420     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
421     expectHandleEvents_callModifyAck();
422     syncStorage->setOperationTimeout(TEST_OPERATION_WAIT_TIMEOUT);
423     syncStorage->set(ns, dataMap);
424     expectSdlReadinessCheck(TEST_OPERATION_POLL_WAIT_TIMEOUT);
425     expectSetIfAsync("key1", { 0x0a, 0x0b, 0x0c }, { 0x0d, 0x0e, 0x0f });
426     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
427     expectHandleEvents_callModifyAck();
428     syncStorage->setIf(ns, "key1", { 0x0a, 0x0b, 0x0c }, { 0x0d, 0x0e, 0x0f });
429 }
430
431 TEST_F(SyncStorageImplTest, SetIfCanThrowBackendError)
432 {
433     InSequence dummy;
434     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
435     expectSetAsync(dataMap);
436     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
437     expectHandleEvents_callModifyAck();
438     syncStorage->set(ns, dataMap);
439     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
440     expectSetIfAsync("key1", { 0x0a, 0x0b, 0x0c }, { 0x0d, 0x0e, 0x0f });
441     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
442     expectModifyIfAck(AsyncRedisCommandDispatcherErrorCode::OUT_OF_MEMORY, false);
443     EXPECT_THROW(syncStorage->setIf(ns, "key1", { 0x0a, 0x0b, 0x0c }, { 0x0d, 0x0e, 0x0f }), BackendError);
444 }
445
446 TEST_F(SyncStorageImplTest, SetIfNotExistsSuccessfully)
447 {
448     InSequence dummy;
449     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
450     expectSetIfNotExistsAsync("key1", { 0x0a, 0x0b, 0x0c });
451     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
452     expectModifyIfAck(std::error_code(), true);
453     EXPECT_TRUE(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }));
454 }
455
456 TEST_F(SyncStorageImplTest, SetIfNotExistsIfWithReadinessTimeoutSuccessfully)
457 {
458     InSequence dummy;
459     expectSdlReadinessCheck(TEST_OPERATION_POLL_WAIT_TIMEOUT);
460     expectSetIfNotExistsAsync("key1", { 0x0a, 0x0b, 0x0c });
461     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
462     expectModifyIfAck(std::error_code(), true);
463     syncStorage->setOperationTimeout(TEST_OPERATION_WAIT_TIMEOUT);
464     EXPECT_TRUE(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }));
465 }
466
467 TEST_F(SyncStorageImplTest, SetIfNotExistsReturnsFalseIfKeyAlreadyExists)
468 {
469     InSequence dummy;
470     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
471     expectSetIfNotExistsAsync("key1", { 0x0a, 0x0b, 0x0c });
472     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
473     expectModifyIfAck(std::error_code(), false);
474     EXPECT_FALSE(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }));
475 }
476
477 TEST_F(SyncStorageImplTest, SetIfNotExistsCanThrowBackendError)
478 {
479     InSequence dummy;
480     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
481     expectSetIfNotExistsAsync("key1", { 0x0a, 0x0b, 0x0c });
482     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
483     expectModifyIfAck(AsyncRedisCommandDispatcherErrorCode::OUT_OF_MEMORY, false);
484     EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), BackendError);
485 }
486
487 TEST_F(SyncStorageImplTest, GetSuccessfully)
488 {
489     InSequence dummy;
490     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
491     expectGetAsync(keys);
492     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
493     expectGetAck();
494     auto map(syncStorage->get(ns, keys));
495     EXPECT_EQ(map, dataMap);
496 }
497
498 TEST_F(SyncStorageImplTest, GetWithReadinessTimeoutSuccessfully)
499 {
500     InSequence dummy;
501     expectSdlReadinessCheck(TEST_OPERATION_POLL_WAIT_TIMEOUT);
502     expectGetAsync(keys);
503     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
504     expectGetAck();
505     syncStorage->setOperationTimeout(TEST_OPERATION_WAIT_TIMEOUT);
506     auto map(syncStorage->get(ns, keys));
507     EXPECT_EQ(map, dataMap);
508 }
509
510 TEST_F(SyncStorageImplTest, GetCanThrowBackendError)
511 {
512     InSequence dummy;
513     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
514     expectGetAsync(keys);
515     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
516     expectGetAckWithError();
517     EXPECT_THROW(syncStorage->get(ns, keys), BackendError);
518 }
519
520 TEST_F(SyncStorageImplTest, RemoveSuccessfully)
521 {
522     InSequence dummy;
523     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
524     expectRemoveAsync(keys);
525     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
526     expectHandleEvents_callModifyAck();
527     syncStorage->remove(ns, keys);
528 }
529
530 TEST_F(SyncStorageImplTest, RemoveWithReadinessTimeoutSuccessfully)
531 {
532     InSequence dummy;
533     expectSdlReadinessCheck(TEST_OPERATION_POLL_WAIT_TIMEOUT);
534     expectRemoveAsync(keys);
535     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
536     expectHandleEvents_callModifyAck();
537     syncStorage->setOperationTimeout(TEST_OPERATION_WAIT_TIMEOUT);
538     syncStorage->remove(ns, keys);
539 }
540
541 TEST_F(SyncStorageImplTest, RemoveCanThrowBackendError)
542 {
543     InSequence dummy;
544     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
545     expectRemoveAsync(keys);
546     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
547     expectModifyAckWithError();
548     EXPECT_THROW(syncStorage->remove(ns, keys), BackendError);
549 }
550
551 TEST_F(SyncStorageImplTest, RemoveIfSuccessfully)
552 {
553     InSequence dummy;
554     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
555     expectRemoveIfAsync("key1", { 0x0a, 0x0b, 0x0c });
556     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
557     expectModifyIfAck(std::error_code(), true);
558     EXPECT_TRUE(syncStorage->removeIf(ns, "key1", { 0x0a, 0x0b, 0x0c }));
559 }
560
561 TEST_F(SyncStorageImplTest, RemoveIfWithReadinessTimeoutSuccessfully)
562 {
563     InSequence dummy;
564     expectSdlReadinessCheck(TEST_OPERATION_POLL_WAIT_TIMEOUT);
565     expectRemoveIfAsync("key1", { 0x0a, 0x0b, 0x0c });
566     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
567     expectModifyIfAck(std::error_code(), true);
568     syncStorage->setOperationTimeout(TEST_OPERATION_WAIT_TIMEOUT);
569     EXPECT_TRUE(syncStorage->removeIf(ns, "key1", { 0x0a, 0x0b, 0x0c }));
570 }
571
572 TEST_F(SyncStorageImplTest, RemoveIfReturnsFalseIfKeyDoesnotMatch)
573 {
574     InSequence dummy;
575     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
576     expectRemoveIfAsync("key1", { 0x0a, 0x0b, 0x0c });
577     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
578     expectModifyIfAck(std::error_code(), false);
579     EXPECT_FALSE(syncStorage->removeIf(ns, "key1", { 0x0a, 0x0b, 0x0c }));
580 }
581
582 TEST_F(SyncStorageImplTest, RemoveIfCanThrowBackendError)
583 {
584     InSequence dummy;
585     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
586     expectRemoveIfAsync("key1", { 0x0a, 0x0b, 0x0c });
587     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
588     expectModifyIfAck(AsyncRedisCommandDispatcherErrorCode::OUT_OF_MEMORY, false);
589     EXPECT_THROW(syncStorage->removeIf(ns, "key1", { 0x0a, 0x0b, 0x0c }), BackendError);
590 }
591
592 TEST_F(SyncStorageImplTest, FindKeysSuccessfully)
593 {
594     InSequence dummy;
595     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
596     expectFindKeysAsync();
597     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
598     expectFindKeysAck();
599     auto ids(syncStorage->findKeys(ns, "*"));
600     EXPECT_EQ(ids, keys);
601 }
602
603 TEST_F(SyncStorageImplTest, FindKeysWithReadinessTimeoutSuccessfully)
604 {
605     InSequence dummy;
606     expectSdlReadinessCheck(TEST_OPERATION_POLL_WAIT_TIMEOUT);
607     expectFindKeysAsync();
608     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
609     expectFindKeysAck();
610     syncStorage->setOperationTimeout(TEST_OPERATION_WAIT_TIMEOUT);
611     auto ids(syncStorage->findKeys(ns, "*"));
612     EXPECT_EQ(ids, keys);
613 }
614
615 TEST_F(SyncStorageImplTest, FindKeysAckCanThrowBackendError)
616 {
617     InSequence dummy;
618     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
619     expectFindKeysAsync();
620     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
621     expectFindKeysAckWithError();
622     EXPECT_THROW(syncStorage->findKeys(ns, "*"), BackendError);
623 }
624
625 TEST_F(SyncStorageImplTest, RemoveAllSuccessfully)
626 {
627     InSequence dummy;
628     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
629     expectRemoveAllAsync();
630     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
631     expectHandleEvents_callModifyAck();
632     syncStorage->removeAll(ns);
633 }
634
635 TEST_F(SyncStorageImplTest, RemoveAllWithReadinessTimeoutSuccessfully)
636 {
637     InSequence dummy;
638     expectSdlReadinessCheck(TEST_OPERATION_POLL_WAIT_TIMEOUT);
639     expectRemoveAllAsync();
640     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
641     expectHandleEvents_callModifyAck();
642     syncStorage->setOperationTimeout(TEST_OPERATION_WAIT_TIMEOUT);
643     syncStorage->removeAll(ns);
644 }
645
646 TEST_F(SyncStorageImplTest, RemoveAllCanThrowBackendError)
647 {
648     InSequence dummy;
649     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
650     expectRemoveAllAsync();
651     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
652     expectModifyAckWithError();
653     EXPECT_THROW(syncStorage->removeAll(ns), BackendError);
654 }
655
656 TEST_F(SyncStorageImplTest, AllAsyncRedisStorageErrorCodesThrowCorrectException)
657 {
658     InSequence dummy;
659     std::error_code ec;
660
661     for (AsyncRedisStorage::ErrorCode arsec = AsyncRedisStorage::ErrorCode::SUCCESS; arsec < AsyncRedisStorage::ErrorCode::END_MARKER; ++arsec)
662     {
663         if (arsec != AsyncRedisStorage::ErrorCode::SUCCESS)
664         {
665             expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
666             expectSetIfNotExistsAsync("key1", { 0x0a, 0x0b, 0x0c });
667             expectPollWait(SyncStorageImpl::NO_TIMEOUT);
668         }
669
670         switch (arsec)
671         {
672             case AsyncRedisStorage::ErrorCode::SUCCESS:
673                 break;
674             case AsyncRedisStorage::ErrorCode::INVALID_NAMESPACE:
675                 expectModifyIfAck(arsec, false);
676                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), InvalidNamespace);
677                 break;
678             case AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED:
679                 expectModifyIfAck(arsec, false);
680                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), NotConnected);
681                 break;
682             default:
683                 FAIL() << "No mapping for AsyncRedisStorage::ErrorCode value: " << arsec;
684                 break;
685         }
686     }
687 }
688
689 TEST_F(SyncStorageImplTest, AllDispatcherErrorCodesThrowCorrectException)
690 {
691     InSequence dummy;
692     std::error_code ec;
693
694     for (AsyncRedisCommandDispatcherErrorCode aec = AsyncRedisCommandDispatcherErrorCode::SUCCESS; aec < AsyncRedisCommandDispatcherErrorCode::END_MARKER; ++aec)
695     {
696         if (aec != AsyncRedisCommandDispatcherErrorCode::SUCCESS)
697         {
698             expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
699             expectSetIfNotExistsAsync("key1", { 0x0a, 0x0b, 0x0c });
700             expectPollWait(SyncStorageImpl::NO_TIMEOUT);
701         }
702
703         switch (aec)
704         {
705             case AsyncRedisCommandDispatcherErrorCode::SUCCESS:
706                 break;
707             case AsyncRedisCommandDispatcherErrorCode::UNKNOWN_ERROR:
708                 expectModifyIfAck(aec, false);
709                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), BackendError);
710                 break;
711             case AsyncRedisCommandDispatcherErrorCode::CONNECTION_LOST:
712                 expectModifyIfAck(aec, false);
713                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), OperationInterrupted);
714                 break;
715             case AsyncRedisCommandDispatcherErrorCode::PROTOCOL_ERROR:
716                 expectModifyIfAck(aec, false);
717                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), RejectedByBackend);
718                 break;
719             case AsyncRedisCommandDispatcherErrorCode::OUT_OF_MEMORY:
720                 expectModifyIfAck(aec, false);
721                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), BackendError);
722                 break;
723             case AsyncRedisCommandDispatcherErrorCode::DATASET_LOADING:
724                 expectModifyIfAck(aec, false);
725                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), NotConnected);
726                 break;
727             case AsyncRedisCommandDispatcherErrorCode::NOT_CONNECTED:
728                 expectModifyIfAck(aec, false);
729                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), NotConnected);
730                 break;
731             case AsyncRedisCommandDispatcherErrorCode::IO_ERROR:
732                 expectModifyIfAck(aec, false);
733                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), BackendError);
734                 break;
735             case AsyncRedisCommandDispatcherErrorCode::WRITING_TO_SLAVE:
736                 expectModifyIfAck(aec, false);
737                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), BackendError);
738                 break;
739             default:
740                 FAIL() << "No mapping for AsyncRedisCommandDispatcherErrorCode value: " << aec;
741                 break;
742         }
743     }
744 }
745
746 TEST_F(SyncStorageImplTest, CanThrowStdExceptionIfDispatcherErrorCodeCannotBeMappedToSdlException)
747 {
748     InSequence dummy;
749     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
750     expectSetIfNotExistsAsync("key1", { 0x0a, 0x0b, 0x0c });
751     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
752     expectModifyIfAck(std::error_code(1, std::system_category()), false);
753     EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), std::range_error);
754 }