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