RIC:1060: Change in PTL
[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 expectListKeys()
280         {
281             EXPECT_CALL(*asyncStorageMockRawPtr, listKeys(ns, _, _))
282                 .Times(1)
283                 .WillOnce(SaveArg<2>(&savedFindKeysAck));
284         }
285
286         void expectRemoveAsync(const SyncStorage::Keys& keys)
287         {
288             EXPECT_CALL(*asyncStorageMockRawPtr, removeAsync(ns, keys, _))
289                 .Times(1)
290                 .WillOnce(SaveArg<2>(&savedModifyAck));
291         }
292
293         void expectRemoveIfAsync(const SyncStorage::Key& key, const SyncStorage::Data& data)
294         {
295             EXPECT_CALL(*asyncStorageMockRawPtr, removeIfAsync(ns, key, data, _))
296                 .Times(1)
297                 .WillOnce(SaveArg<3>(&savedModifyIfAck));
298         }
299
300         void expectRemoveAllAsync()
301         {
302             EXPECT_CALL(*asyncStorageMockRawPtr, removeAllAsync(ns, _))
303                 .Times(1)
304                 .WillOnce(SaveArg<1>(&savedModifyAck));
305         }
306
307         void expectSetIfNotExistsAsync(const SyncStorage::Key& key, const SyncStorage::Data& data)
308         {
309             EXPECT_CALL(*asyncStorageMockRawPtr, setIfNotExistsAsync(ns, key, data, _))
310                 .Times(1)
311                 .WillOnce(SaveArg<3>(&savedModifyIfAck));
312         }
313     };
314 }
315
316 TEST_F(SyncStorageImplTest, IsNotCopyable)
317 {
318     InSequence dummy;
319     EXPECT_FALSE(std::is_copy_constructible<SyncStorageImpl>::value);
320     EXPECT_FALSE(std::is_copy_assignable<SyncStorageImpl>::value);
321 }
322
323 TEST_F(SyncStorageImplTest, ImplementssyncStorage)
324 {
325     InSequence dummy;
326     EXPECT_TRUE((std::is_base_of<SyncStorage, SyncStorageImpl>::value));
327 }
328
329 TEST_F(SyncStorageImplTest, EventsAreNotHandledWhenPollReturnsError)
330 {
331     InSequence dummy;
332     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
333     expectSetAsync(dataMap);
334     expectPollError();
335     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
336     expectHandleEvents_callModifyAck();
337     syncStorage->set(ns, dataMap);
338 }
339
340 TEST_F(SyncStorageImplTest, EventsAreNotHandledWhenThereIsAnExceptionalConditionOnTheFd)
341 {
342     InSequence dummy;
343     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
344     expectSetAsync(dataMap);
345     expectPollExceptionalCondition();
346     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
347     expectHandleEvents_callModifyAck();
348     syncStorage->set(ns, dataMap);
349 }
350
351 TEST_F(SyncStorageImplTest, WaitReadySuccessfully)
352 {
353     InSequence dummy;
354     expectWaitReadyAsync();
355     expectPollWait(TEST_READY_POLL_WAIT_TIMEOUT);
356     expectHandleEvents_callWaitReadyAck();
357     syncStorage->waitReady(ns, TEST_READY_WAIT_TIMEOUT);
358 }
359
360 TEST_F(SyncStorageImplTest, WaitReadyCanThrowRejectedBySdl)
361 {
362     InSequence dummy;
363     expectWaitReadyAsync();
364     EXPECT_THROW(syncStorage->waitReady(ns, std::chrono::nanoseconds(1)), RejectedBySdl);
365 }
366
367 TEST_F(SyncStorageImplTest, WaitReadyCanThrowNotConnected)
368 {
369     InSequence dummy;
370     expectWaitReadyAsync();
371     expectPollWait(TEST_READY_POLL_WAIT_TIMEOUT);
372     expectHandleEvents_callWaitReadyAckWithError();
373     EXPECT_THROW(syncStorage->waitReady(ns, TEST_READY_WAIT_TIMEOUT), NotConnected);
374 }
375
376 TEST_F(SyncStorageImplTest, SetSuccessfully)
377 {
378     InSequence dummy;
379     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
380     expectSetAsync(dataMap);
381     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
382     expectHandleEvents_callModifyAck();
383     syncStorage->set(ns, dataMap);
384 }
385
386 TEST_F(SyncStorageImplTest, SetWithReadinessTimeoutSuccessfully)
387 {
388     InSequence dummy;
389     expectSdlReadinessCheck(TEST_OPERATION_POLL_WAIT_TIMEOUT);
390     expectSetAsync(dataMap);
391     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
392     expectHandleEvents_callModifyAck();
393     syncStorage->setOperationTimeout(TEST_OPERATION_WAIT_TIMEOUT);
394     syncStorage->set(ns, dataMap);
395 }
396
397 TEST_F(SyncStorageImplTest, SetCanThrowBackendError)
398 {
399     InSequence dummy;
400     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
401     expectSetAsync(dataMap);
402     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
403     expectModifyAckWithError();
404     EXPECT_THROW(syncStorage->set(ns, dataMap), BackendError);
405 }
406
407 TEST_F(SyncStorageImplTest, SetIfSuccessfully)
408 {
409     InSequence dummy;
410     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
411     expectSetAsync(dataMap);
412     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
413     expectHandleEvents_callModifyAck();
414     syncStorage->set(ns, dataMap);
415     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
416     expectSetIfAsync("key1", { 0x0a, 0x0b, 0x0c }, { 0x0d, 0x0e, 0x0f });
417     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
418     expectHandleEvents_callModifyAck();
419     syncStorage->setIf(ns, "key1", { 0x0a, 0x0b, 0x0c }, { 0x0d, 0x0e, 0x0f });
420 }
421
422 TEST_F(SyncStorageImplTest, SetIfWithReadinessTimeoutSuccessfully)
423 {
424     InSequence dummy;
425     expectSdlReadinessCheck(TEST_OPERATION_POLL_WAIT_TIMEOUT);
426     expectSetAsync(dataMap);
427     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
428     expectHandleEvents_callModifyAck();
429     syncStorage->setOperationTimeout(TEST_OPERATION_WAIT_TIMEOUT);
430     syncStorage->set(ns, dataMap);
431     expectSdlReadinessCheck(TEST_OPERATION_POLL_WAIT_TIMEOUT);
432     expectSetIfAsync("key1", { 0x0a, 0x0b, 0x0c }, { 0x0d, 0x0e, 0x0f });
433     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
434     expectHandleEvents_callModifyAck();
435     syncStorage->setIf(ns, "key1", { 0x0a, 0x0b, 0x0c }, { 0x0d, 0x0e, 0x0f });
436 }
437
438 TEST_F(SyncStorageImplTest, SetIfCanThrowBackendError)
439 {
440     InSequence dummy;
441     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
442     expectSetAsync(dataMap);
443     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
444     expectHandleEvents_callModifyAck();
445     syncStorage->set(ns, dataMap);
446     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
447     expectSetIfAsync("key1", { 0x0a, 0x0b, 0x0c }, { 0x0d, 0x0e, 0x0f });
448     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
449     expectModifyIfAck(AsyncRedisCommandDispatcherErrorCode::OUT_OF_MEMORY, false);
450     EXPECT_THROW(syncStorage->setIf(ns, "key1", { 0x0a, 0x0b, 0x0c }, { 0x0d, 0x0e, 0x0f }), BackendError);
451 }
452
453 TEST_F(SyncStorageImplTest, SetIfNotExistsSuccessfully)
454 {
455     InSequence dummy;
456     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
457     expectSetIfNotExistsAsync("key1", { 0x0a, 0x0b, 0x0c });
458     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
459     expectModifyIfAck(std::error_code(), true);
460     EXPECT_TRUE(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }));
461 }
462
463 TEST_F(SyncStorageImplTest, SetIfNotExistsIfWithReadinessTimeoutSuccessfully)
464 {
465     InSequence dummy;
466     expectSdlReadinessCheck(TEST_OPERATION_POLL_WAIT_TIMEOUT);
467     expectSetIfNotExistsAsync("key1", { 0x0a, 0x0b, 0x0c });
468     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
469     expectModifyIfAck(std::error_code(), true);
470     syncStorage->setOperationTimeout(TEST_OPERATION_WAIT_TIMEOUT);
471     EXPECT_TRUE(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }));
472 }
473
474 TEST_F(SyncStorageImplTest, SetIfNotExistsReturnsFalseIfKeyAlreadyExists)
475 {
476     InSequence dummy;
477     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
478     expectSetIfNotExistsAsync("key1", { 0x0a, 0x0b, 0x0c });
479     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
480     expectModifyIfAck(std::error_code(), false);
481     EXPECT_FALSE(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }));
482 }
483
484 TEST_F(SyncStorageImplTest, SetIfNotExistsCanThrowBackendError)
485 {
486     InSequence dummy;
487     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
488     expectSetIfNotExistsAsync("key1", { 0x0a, 0x0b, 0x0c });
489     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
490     expectModifyIfAck(AsyncRedisCommandDispatcherErrorCode::OUT_OF_MEMORY, false);
491     EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), BackendError);
492 }
493
494 TEST_F(SyncStorageImplTest, GetSuccessfully)
495 {
496     InSequence dummy;
497     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
498     expectGetAsync(keys);
499     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
500     expectGetAck();
501     auto map(syncStorage->get(ns, keys));
502     EXPECT_EQ(map, dataMap);
503 }
504
505 TEST_F(SyncStorageImplTest, GetWithReadinessTimeoutSuccessfully)
506 {
507     InSequence dummy;
508     expectSdlReadinessCheck(TEST_OPERATION_POLL_WAIT_TIMEOUT);
509     expectGetAsync(keys);
510     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
511     expectGetAck();
512     syncStorage->setOperationTimeout(TEST_OPERATION_WAIT_TIMEOUT);
513     auto map(syncStorage->get(ns, keys));
514     EXPECT_EQ(map, dataMap);
515 }
516
517 TEST_F(SyncStorageImplTest, GetCanThrowBackendError)
518 {
519     InSequence dummy;
520     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
521     expectGetAsync(keys);
522     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
523     expectGetAckWithError();
524     EXPECT_THROW(syncStorage->get(ns, keys), BackendError);
525 }
526
527 TEST_F(SyncStorageImplTest, RemoveSuccessfully)
528 {
529     InSequence dummy;
530     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
531     expectRemoveAsync(keys);
532     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
533     expectHandleEvents_callModifyAck();
534     syncStorage->remove(ns, keys);
535 }
536
537 TEST_F(SyncStorageImplTest, RemoveWithReadinessTimeoutSuccessfully)
538 {
539     InSequence dummy;
540     expectSdlReadinessCheck(TEST_OPERATION_POLL_WAIT_TIMEOUT);
541     expectRemoveAsync(keys);
542     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
543     expectHandleEvents_callModifyAck();
544     syncStorage->setOperationTimeout(TEST_OPERATION_WAIT_TIMEOUT);
545     syncStorage->remove(ns, keys);
546 }
547
548 TEST_F(SyncStorageImplTest, RemoveCanThrowBackendError)
549 {
550     InSequence dummy;
551     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
552     expectRemoveAsync(keys);
553     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
554     expectModifyAckWithError();
555     EXPECT_THROW(syncStorage->remove(ns, keys), BackendError);
556 }
557
558 TEST_F(SyncStorageImplTest, RemoveIfSuccessfully)
559 {
560     InSequence dummy;
561     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
562     expectRemoveIfAsync("key1", { 0x0a, 0x0b, 0x0c });
563     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
564     expectModifyIfAck(std::error_code(), true);
565     EXPECT_TRUE(syncStorage->removeIf(ns, "key1", { 0x0a, 0x0b, 0x0c }));
566 }
567
568 TEST_F(SyncStorageImplTest, RemoveIfWithReadinessTimeoutSuccessfully)
569 {
570     InSequence dummy;
571     expectSdlReadinessCheck(TEST_OPERATION_POLL_WAIT_TIMEOUT);
572     expectRemoveIfAsync("key1", { 0x0a, 0x0b, 0x0c });
573     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
574     expectModifyIfAck(std::error_code(), true);
575     syncStorage->setOperationTimeout(TEST_OPERATION_WAIT_TIMEOUT);
576     EXPECT_TRUE(syncStorage->removeIf(ns, "key1", { 0x0a, 0x0b, 0x0c }));
577 }
578
579 TEST_F(SyncStorageImplTest, RemoveIfReturnsFalseIfKeyDoesnotMatch)
580 {
581     InSequence dummy;
582     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
583     expectRemoveIfAsync("key1", { 0x0a, 0x0b, 0x0c });
584     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
585     expectModifyIfAck(std::error_code(), false);
586     EXPECT_FALSE(syncStorage->removeIf(ns, "key1", { 0x0a, 0x0b, 0x0c }));
587 }
588
589 TEST_F(SyncStorageImplTest, RemoveIfCanThrowBackendError)
590 {
591     InSequence dummy;
592     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
593     expectRemoveIfAsync("key1", { 0x0a, 0x0b, 0x0c });
594     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
595     expectModifyIfAck(AsyncRedisCommandDispatcherErrorCode::OUT_OF_MEMORY, false);
596     EXPECT_THROW(syncStorage->removeIf(ns, "key1", { 0x0a, 0x0b, 0x0c }), BackendError);
597 }
598
599 TEST_F(SyncStorageImplTest, FindKeysSuccessfully)
600 {
601     InSequence dummy;
602     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
603     expectFindKeysAsync();
604     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
605     expectFindKeysAck();
606     auto ids(syncStorage->findKeys(ns, "*"));
607     EXPECT_EQ(ids, keys);
608 }
609
610 TEST_F(SyncStorageImplTest, ListKeysSuccessfully)
611 {
612     InSequence dummy;
613     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
614     expectListKeys();
615     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
616     expectFindKeysAck();
617     auto ids(syncStorage->listKeys(ns, "*"));
618     EXPECT_EQ(ids, keys);
619 }
620
621 TEST_F(SyncStorageImplTest, FindKeysWithReadinessTimeoutSuccessfully)
622 {
623     InSequence dummy;
624     expectSdlReadinessCheck(TEST_OPERATION_POLL_WAIT_TIMEOUT);
625     expectFindKeysAsync();
626     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
627     expectFindKeysAck();
628     syncStorage->setOperationTimeout(TEST_OPERATION_WAIT_TIMEOUT);
629     auto ids(syncStorage->findKeys(ns, "*"));
630     EXPECT_EQ(ids, keys);
631 }
632
633 TEST_F(SyncStorageImplTest, FindKeysAckCanThrowBackendError)
634 {
635     InSequence dummy;
636     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
637     expectFindKeysAsync();
638     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
639     expectFindKeysAckWithError();
640     EXPECT_THROW(syncStorage->findKeys(ns, "*"), BackendError);
641 }
642
643 TEST_F(SyncStorageImplTest, RemoveAllSuccessfully)
644 {
645     InSequence dummy;
646     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
647     expectRemoveAllAsync();
648     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
649     expectHandleEvents_callModifyAck();
650     syncStorage->removeAll(ns);
651 }
652
653 TEST_F(SyncStorageImplTest, RemoveAllWithReadinessTimeoutSuccessfully)
654 {
655     InSequence dummy;
656     expectSdlReadinessCheck(TEST_OPERATION_POLL_WAIT_TIMEOUT);
657     expectRemoveAllAsync();
658     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
659     expectHandleEvents_callModifyAck();
660     syncStorage->setOperationTimeout(TEST_OPERATION_WAIT_TIMEOUT);
661     syncStorage->removeAll(ns);
662 }
663
664 TEST_F(SyncStorageImplTest, RemoveAllCanThrowBackendError)
665 {
666     InSequence dummy;
667     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
668     expectRemoveAllAsync();
669     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
670     expectModifyAckWithError();
671     EXPECT_THROW(syncStorage->removeAll(ns), BackendError);
672 }
673
674 TEST_F(SyncStorageImplTest, AllAsyncRedisStorageErrorCodesThrowCorrectException)
675 {
676     InSequence dummy;
677     std::error_code ec;
678
679     for (AsyncRedisStorage::ErrorCode arsec = AsyncRedisStorage::ErrorCode::SUCCESS; arsec < AsyncRedisStorage::ErrorCode::END_MARKER; ++arsec)
680     {
681         if (arsec != AsyncRedisStorage::ErrorCode::SUCCESS)
682         {
683             expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
684             expectSetIfNotExistsAsync("key1", { 0x0a, 0x0b, 0x0c });
685             expectPollWait(SyncStorageImpl::NO_TIMEOUT);
686         }
687
688         switch (arsec)
689         {
690             case AsyncRedisStorage::ErrorCode::SUCCESS:
691                 break;
692             case AsyncRedisStorage::ErrorCode::INVALID_NAMESPACE:
693                 expectModifyIfAck(arsec, false);
694                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), InvalidNamespace);
695                 break;
696             case AsyncRedisStorage::ErrorCode::REDIS_NOT_YET_DISCOVERED:
697                 expectModifyIfAck(arsec, false);
698                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), NotConnected);
699                 break;
700             default:
701                 FAIL() << "No mapping for AsyncRedisStorage::ErrorCode value: " << arsec;
702                 break;
703         }
704     }
705 }
706
707 TEST_F(SyncStorageImplTest, AllDispatcherErrorCodesThrowCorrectException)
708 {
709     InSequence dummy;
710     std::error_code ec;
711
712     for (AsyncRedisCommandDispatcherErrorCode aec = AsyncRedisCommandDispatcherErrorCode::SUCCESS; aec < AsyncRedisCommandDispatcherErrorCode::END_MARKER; ++aec)
713     {
714         if (aec != AsyncRedisCommandDispatcherErrorCode::SUCCESS)
715         {
716             expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
717             expectSetIfNotExistsAsync("key1", { 0x0a, 0x0b, 0x0c });
718             expectPollWait(SyncStorageImpl::NO_TIMEOUT);
719         }
720
721         switch (aec)
722         {
723             case AsyncRedisCommandDispatcherErrorCode::SUCCESS:
724                 break;
725             case AsyncRedisCommandDispatcherErrorCode::UNKNOWN_ERROR:
726                 expectModifyIfAck(aec, false);
727                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), BackendError);
728                 break;
729             case AsyncRedisCommandDispatcherErrorCode::CONNECTION_LOST:
730                 expectModifyIfAck(aec, false);
731                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), OperationInterrupted);
732                 break;
733             case AsyncRedisCommandDispatcherErrorCode::PROTOCOL_ERROR:
734                 expectModifyIfAck(aec, false);
735                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), RejectedByBackend);
736                 break;
737             case AsyncRedisCommandDispatcherErrorCode::OUT_OF_MEMORY:
738                 expectModifyIfAck(aec, false);
739                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), BackendError);
740                 break;
741             case AsyncRedisCommandDispatcherErrorCode::DATASET_LOADING:
742                 expectModifyIfAck(aec, false);
743                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), NotConnected);
744                 break;
745             case AsyncRedisCommandDispatcherErrorCode::NOT_CONNECTED:
746                 expectModifyIfAck(aec, false);
747                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), NotConnected);
748                 break;
749             case AsyncRedisCommandDispatcherErrorCode::IO_ERROR:
750                 expectModifyIfAck(aec, false);
751                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), BackendError);
752                 break;
753             case AsyncRedisCommandDispatcherErrorCode::WRITING_TO_SLAVE:
754                 expectModifyIfAck(aec, false);
755                 EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), BackendError);
756                 break;
757             default:
758                 FAIL() << "No mapping for AsyncRedisCommandDispatcherErrorCode value: " << aec;
759                 break;
760         }
761     }
762 }
763
764 TEST_F(SyncStorageImplTest, CanThrowStdExceptionIfDispatcherErrorCodeCannotBeMappedToSdlException)
765 {
766     InSequence dummy;
767     expectSdlReadinessCheck(SyncStorageImpl::NO_TIMEOUT);
768     expectSetIfNotExistsAsync("key1", { 0x0a, 0x0b, 0x0c });
769     expectPollWait(SyncStorageImpl::NO_TIMEOUT);
770     expectModifyIfAck(std::error_code(1, std::system_category()), false);
771     EXPECT_THROW(syncStorage->setIfNotExists(ns, "key1", { 0x0a, 0x0b, 0x0c }), std::range_error);
772 }