blob: b1ed9f125d2661eedd48829dc90abd3b77d89032 [file] [log] [blame]
Rolf Badorekef2bf512019-08-20 11:17:15 +03001/*
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
Timo Tietavainena0745d22019-11-28 09:55:22 +020017/*
18 * This source code is part of the near-RT RIC (RAN Intelligent Controller)
19 * platform project (RICP).
20*/
21
Rolf Badorekef2bf512019-08-20 11:17:15 +030022#include <gtest/gtest.h>
23#include <gmock/gmock.h>
24#include <memory>
25#include <boost/property_tree/ptree.hpp>
26#include <boost/property_tree/json_parser.hpp>
27#include "private/configurationreader.hpp"
28#include "private/createlogger.hpp"
29#include "private/logger.hpp"
30#include "private/tst/databaseconfigurationmock.hpp"
31#include "private/tst/gettopsrcdir.hpp"
32#include "private/tst/namespaceconfigurationsmock.hpp"
33#include "private/tst/systemmock.hpp"
34
35using namespace shareddatalayer;
36using namespace shareddatalayer::tst;
37using namespace testing;
38
39namespace
40{
41 class ConfigurationReaderBaseTest: public testing::Test
42 {
43 public:
44 const std::string someKnownInputSource;
45 const Directories noDirectories;
46 DatabaseConfigurationMock databaseConfigurationMock;
47 NamespaceConfigurationsMock namespaceConfigurationsMock;
48 std::unique_ptr<ConfigurationReader> configurationReader;
49 SystemMock systemMock;
50 std::shared_ptr<Logger> logger;
51
52 ConfigurationReaderBaseTest(std::string inputSourceName):
53 someKnownInputSource(inputSourceName),
54 logger(createLogger(SDL_LOG_PREFIX))
55 {
56 EXPECT_CALL(databaseConfigurationMock, isEmpty()).WillRepeatedly(Return(true));
57 EXPECT_CALL(namespaceConfigurationsMock, isEmpty()).WillRepeatedly(Return(true));
58 }
59
60 void expectDbTypeConfigurationCheckAndApply(const std::string& type)
61 {
62 EXPECT_CALL(databaseConfigurationMock, checkAndApplyDbType(type));
63 }
64
65 void expectDBServerAddressConfigurationCheckAndApply(const std::string& address)
66 {
67 EXPECT_CALL(databaseConfigurationMock, checkAndApplyServerAddress(address));
68 }
69
Rolf Badorek2dcf9402019-10-01 18:33:58 +030070 void expectSentinelAddressConfigurationCheckAndApply(const std::string& address)
71 {
72 EXPECT_CALL(databaseConfigurationMock, checkAndApplySentinelAddress(address));
73 }
74
75 void expectSentinelMasterNameConfigurationCheckAndApply(const std::string& address)
76 {
77 EXPECT_CALL(databaseConfigurationMock, checkAndApplySentinelMasterName(address));
78 }
79
Rolf Badorekef2bf512019-08-20 11:17:15 +030080 void expectDatabaseConfigurationIsEmpty_returnFalse()
81 {
82 EXPECT_CALL(databaseConfigurationMock, isEmpty()).
83 WillOnce(Return(false));
84 }
85
86 void tryToReadDatabaseConfigurationToNonEmptyContainer()
87 {
88 expectDatabaseConfigurationIsEmpty_returnFalse();
89 configurationReader->readDatabaseConfiguration(databaseConfigurationMock);
90 }
91
92 void expectNamespaceConfigurationIsEmpty_returnFalse()
93 {
94 EXPECT_CALL(namespaceConfigurationsMock, isEmpty()).
95 WillOnce(Return(false));
96 }
97
98 void tryToReadNamespaceConfigurationToNonEmptyContainer()
99 {
100 expectNamespaceConfigurationIsEmpty_returnFalse();
101 configurationReader->readNamespaceConfigurations(namespaceConfigurationsMock);
102 }
103
104 void expectAddNamespaceConfiguration(const std::string& namespacePrefix, bool useDbBackend,
105 bool enableNotifications)
106 {
107 NamespaceConfiguration expectedNamespaceConfiguration{namespacePrefix, useDbBackend,
108 enableNotifications,
109 someKnownInputSource};
110 EXPECT_CALL(namespaceConfigurationsMock, addNamespaceConfiguration(expectedNamespaceConfiguration));
111 }
112
113 void expectGetEnvironmentString(const char* returnValue)
114 {
115 EXPECT_CALL(systemMock, getenv(_))
116 .WillOnce(Return(returnValue));
117 }
118
119 void initializeReaderWithoutDirectories()
120 {
121 configurationReader.reset(new ConfigurationReader(noDirectories, systemMock, logger));
122 }
123
124 void initializeReaderWithSDLconfigFileDirectory()
125 {
126 configurationReader.reset(new ConfigurationReader({getTopSrcDir() + "/conf"}, systemMock, logger));
127 }
128 };
129
130 class ConfigurationReaderSDLConfigFileTest: public ConfigurationReaderBaseTest
131 {
132 public:
133
134 ConfigurationReaderSDLConfigFileTest():
135 ConfigurationReaderBaseTest("ConfFileFromSDLrepo")
136 {
137 expectGetEnvironmentString(nullptr);
138 initializeReaderWithSDLconfigFileDirectory();
139 }
140 };
141
142 class ConfigurationReaderInputStreamTest: public ConfigurationReaderBaseTest
143 {
144 public:
145
146 ConfigurationReaderInputStreamTest():
147 ConfigurationReaderBaseTest("<istream>")
148 {
149 expectGetEnvironmentString(nullptr);
150 initializeReaderWithoutDirectories();
151 }
152
153 void readConfigurationAndExpectJsonParserException(const std::istringstream& is)
154 {
155 const std::string expectedError("error in SDL configuration <istream> at line 7: expected ':'");
156
157 EXPECT_THROW( {
158 try
159 {
160 configurationReader->readConfigurationFromInputStream(is);
161 configurationReader->readDatabaseConfiguration(databaseConfigurationMock);
162 configurationReader->readNamespaceConfigurations(namespaceConfigurationsMock);
163 }
164 catch (const std::exception& e)
165 {
166 EXPECT_EQ(expectedError, e.what());
167 throw;
168 }
169 }, Exception);
170 }
171
172 void readConfigurationAndExpectBadValueException(const std::istringstream& is,
173 const std::string& param)
174 {
175 std::ostringstream os;
176 os << "Configuration error in " << someKnownInputSource << ": "
177 << "invalid \"" << param << "\": \"bad-value\"";
178
179 EXPECT_THROW( {
180 try
181 {
182 configurationReader->readConfigurationFromInputStream(is);
183 configurationReader->readDatabaseConfiguration(databaseConfigurationMock);
184 configurationReader->readNamespaceConfigurations(namespaceConfigurationsMock);
185 }
186 catch (const std::exception& e)
187 {
188 EXPECT_EQ(os.str(), e.what());
189 throw;
190 }
191 }, Exception);
192 }
193
194 void readConfigurationAndExpectDbTypeException(const std::istringstream& is)
195 {
196 std::ostringstream os;
197 os << "Configuration error in " << someKnownInputSource << ": some error";
198
199 EXPECT_CALL(databaseConfigurationMock, checkAndApplyDbType(_))
200 .WillOnce(Throw(Exception("some error")));
201
202 EXPECT_THROW( {
203 try
204 {
205 configurationReader->readConfigurationFromInputStream(is);
206 configurationReader->readDatabaseConfiguration(databaseConfigurationMock);
207 }
208 catch (const std::exception& e)
209 {
210 EXPECT_EQ(os.str(), e.what());
211 throw;
212 }
213 }, Exception);
214 }
215
216 void readConfigurationAndExpectAddressException(const std::istringstream& is,
217 const std::string& addressValue)
218 {
219 std::ostringstream os;
220 os << "Configuration error in " << someKnownInputSource << ": "
221 << "invalid \"address\": \"" << addressValue << "\" some error";
222
223 EXPECT_CALL(databaseConfigurationMock, checkAndApplyServerAddress(_))
224 .WillOnce(Throw(Exception("some error")));
225
226 EXPECT_THROW( {
227 try
228 {
229 configurationReader->readConfigurationFromInputStream(is);
230 configurationReader->readDatabaseConfiguration(databaseConfigurationMock);
231 }
232 catch (const std::exception& e)
233 {
234 EXPECT_EQ(os.str(), e.what());
235 throw;
236 }
237 }, Exception);
238 }
239
240 void readConfigurationAndExpectMissingParameterException(const std::istringstream& is, const std::string& param)
241 {
242 std::ostringstream os;
243 os << "Configuration error in " << someKnownInputSource << ": "
244 << "missing \"" << param << "\"";
245
246 EXPECT_THROW( {
247 try
248 {
249 configurationReader->readConfigurationFromInputStream(is);
250 configurationReader->readDatabaseConfiguration(databaseConfigurationMock);
251 configurationReader->readNamespaceConfigurations(namespaceConfigurationsMock);
252 }
253 catch (const std::exception& e)
254 {
255 EXPECT_EQ(os.str(), e.what());
256 throw;
257 }
258 }, Exception);
259 }
260
261 void readConfigurationAndExpectNamespacePrefixValidationException(const std::istringstream& is,
262 const std::string& namespacePrefix)
263 {
264 std::ostringstream os;
265 os << "Configuration error in " << someKnownInputSource << ": "
266 << "\"namespacePrefix\": \"" << namespacePrefix << "\""
267 << " contains some of these disallowed characters: ,{}";
268
269 EXPECT_THROW( {
270 try
271 {
272 configurationReader->readConfigurationFromInputStream(is);
273 configurationReader->readNamespaceConfigurations(namespaceConfigurationsMock);
274 }
275 catch (const std::exception& e)
276 {
277 EXPECT_EQ(os.str(), e.what() );
278 throw;
279 }
280 }, Exception);
281 }
282
283 void readConfigurationAndExpectEnableNotificationsValidationException(const std::istringstream& is)
284 {
285 std::ostringstream os;
286 os << "Configuration error in " << someKnownInputSource << ": "
287 << "\"enableNotifications\" cannot be true, when \"useDbBackend\" is false";
288
289 EXPECT_THROW( {
290 try
291 {
292 configurationReader->readConfigurationFromInputStream(is);
293 configurationReader->readNamespaceConfigurations(namespaceConfigurationsMock);
294 }
295 catch (const std::exception& e)
296 {
297 EXPECT_EQ(os.str(), e.what() );
298 throw;
299 }
300 }, Exception);
301 }
302
303 };
304}
305
306TEST_F(ConfigurationReaderInputStreamTest, CanReadJSONDatabaseConfiguration)
307{
308 InSequence dummy;
309 std::istringstream is(R"JSON(
310 {
311 "database":
312 {
313 "type": "redis-standalone",
314 "servers":
315 [
316 {
317 "address": "someKnownDbAddress:65535"
318 }
319 ]
320 }
321 })JSON");
322 expectDbTypeConfigurationCheckAndApply("redis-standalone");
323 expectDBServerAddressConfigurationCheckAndApply("someKnownDbAddress:65535");
324 configurationReader->readConfigurationFromInputStream(is);
325 configurationReader->readDatabaseConfiguration(databaseConfigurationMock);
326}
327
328TEST_F(ConfigurationReaderInputStreamTest, CanReadJSONDatabaseConfigurationWithMultipleServerAddresses)
329{
330 InSequence dummy;
331 std::istringstream is(R"JSON(
332 {
333 "database":
334 {
335 "type": "redis-cluster",
336 "servers":
337 [
338 {
339 "address": "10.20.30.40:50000"
340 },
341 {
342 "address": "10.20.30.50:50001"
343 }
344 ]
345 }
346 })JSON");
347
348 expectDbTypeConfigurationCheckAndApply("redis-cluster");
349 expectDBServerAddressConfigurationCheckAndApply("10.20.30.40:50000");
350 expectDBServerAddressConfigurationCheckAndApply("10.20.30.50:50001");
351 configurationReader->readConfigurationFromInputStream(is);
352 configurationReader->readDatabaseConfiguration(databaseConfigurationMock);
353}
354
355TEST_F(ConfigurationReaderInputStreamTest, CanReadJSONDatabaseConfigurationWithMultipleReadOperations)
356{
357 InSequence dummy;
358 std::istringstream isOne(R"JSON(
359 {
360 "database":
361 {
362 "type": "redis-cluster",
363 "servers":
364 [
365 {
366 "address": "10.20.30.40:50000"
367 }
368 ]
369 }
370 })JSON");
371 std::istringstream isTwo(R"JSON(
372 {
373 "database":
374 {
375 "type": "redis-cluster",
376 "servers":
377 [
378 {
379 "address": "10.20.30.50:50001"
380 }
381 ]
382 }
383 })JSON");
384
385 expectDbTypeConfigurationCheckAndApply("redis-cluster");
386 expectDBServerAddressConfigurationCheckAndApply("10.20.30.40:50000");
387 expectDbTypeConfigurationCheckAndApply("redis-cluster");
388 expectDBServerAddressConfigurationCheckAndApply("10.20.30.50:50001");
389 configurationReader->readConfigurationFromInputStream(isOne);
390 configurationReader->readDatabaseConfiguration(databaseConfigurationMock);
391 configurationReader->readConfigurationFromInputStream(isTwo);
392 configurationReader->readDatabaseConfiguration(databaseConfigurationMock);
393}
394
395TEST_F(ConfigurationReaderInputStreamTest, CanCatchAndThrowMisingMandatoryDatabaseTypeParameter)
396{
397 InSequence dummy;
398 std::istringstream is(R"JSON(
399 {
400 "database":
401 {
402 "servers":
403 [
404 {
405 "address": "10.20.30.50:50001"
406 }
407 ]
408 }
409 })JSON");
410
411 readConfigurationAndExpectMissingParameterException(is, "type");
412}
413
414TEST_F(ConfigurationReaderInputStreamTest, CanCatchAndThrowMisingMandatoryDatabaseServersArray)
415{
416 InSequence dummy;
417 std::istringstream is(R"JSON(
418 {
419 "database":
420 {
421 "type": "redis-standalone"
422 }
423 })JSON");
424
425 expectDbTypeConfigurationCheckAndApply("redis-standalone");
426 readConfigurationAndExpectMissingParameterException(is, "servers");
427}
428
429TEST_F(ConfigurationReaderInputStreamTest, CanCatchAndThrowMisingMandatoryDatabaseServerAddressParameter)
430{
431 InSequence dummy;
432 std::istringstream is(R"JSON(
433 {
434 "database":
435 {
436 "type": "redis-standalone",
437 "servers":
438 [
439 {
440 }
441 ]
442 }
443 })JSON");
444
445 expectDbTypeConfigurationCheckAndApply("redis-standalone");
446 readConfigurationAndExpectMissingParameterException(is, "address");
447}
448
449TEST_F(ConfigurationReaderInputStreamTest, CanCatchAndThrowDatabaseConfigurationDbTypeError)
450{
451 InSequence dummy;
452 std::istringstream is(R"JSON(
453 {
454 "database":
455 {
456 "type": "someBadType",
457 "servers":
458 [
459 {
460 "address": "10.20.30.50:50001"
461 }
462 ]
463 }
464 })JSON");
465
466 readConfigurationAndExpectDbTypeException(is);
467}
468
469TEST_F(ConfigurationReaderInputStreamTest, CanCatchAndThrowDatabaseConfigurationAddressError)
470{
471 InSequence dummy;
472 std::istringstream is(R"JSON(
473 {
474 "database":
475 {
476 "type": "redis-standalone",
477 "servers":
478 [
479 {
480 "address": "someBadAddress"
481 }
482 ]
483 }
484 })JSON");
485
486 expectDbTypeConfigurationCheckAndApply("redis-standalone");
487 readConfigurationAndExpectAddressException(is, "someBadAddress");
488}
489
490TEST_F(ConfigurationReaderInputStreamTest, CanHandleJSONWithoutAnyConfiguration)
491{
492 InSequence dummy;
493 std::istringstream is(R"JSON(
494 {
495 })JSON");
496
497 EXPECT_CALL(databaseConfigurationMock, checkAndApplyServerAddress(_))
498 .Times(0);
499 EXPECT_CALL(namespaceConfigurationsMock, addNamespaceConfiguration(_))
500 .Times(0);
501 configurationReader->readConfigurationFromInputStream(is);
502}
503
504TEST_F(ConfigurationReaderInputStreamTest, CanReadJSONSharedDataLayerConfiguration)
505{
506 InSequence dummy;
507 std::istringstream is(R"JSON(
508 {
509 "sharedDataLayer":
510 [
511 {
512 "namespacePrefix": "someKnownNamespacePrefix",
513 "useDbBackend": true,
514 "enableNotifications": true
515 },
516 {
517 "namespacePrefix": "anotherKnownNamespace",
518 "useDbBackend": false,
519 "enableNotifications": false
520 }
521 ]
522 })JSON");
523
524 expectAddNamespaceConfiguration("anotherKnownNamespace", false, false);
525 expectAddNamespaceConfiguration("someKnownNamespacePrefix", true, true);
526 configurationReader->readConfigurationFromInputStream(is);
527 configurationReader->readNamespaceConfigurations(namespaceConfigurationsMock);
528}
529
530TEST_F(ConfigurationReaderInputStreamTest, CanReadJSONSharedDataLayerConfigurationWithMultipleReadOperations)
531{
532 InSequence dummy;
533 std::istringstream isOne(R"JSON(
534 {
535 "sharedDataLayer":
536 [
537 {
538 "namespacePrefix": "someKnownNamespacePrefix",
539 "useDbBackend": true,
540 "enableNotifications": true
541 }
542 ]
543 })JSON");
544
545 std::istringstream isTwo(R"JSON(
546 {
547 "sharedDataLayer":
548 [
549 {
550 "namespacePrefix": "anotherKnownNamespace",
551 "useDbBackend": false,
552 "enableNotifications": false
553 }
554 ]
555 })JSON");
556
557 expectAddNamespaceConfiguration("someKnownNamespacePrefix", true, true);
558 expectAddNamespaceConfiguration("anotherKnownNamespace", false, false);
559 configurationReader->readConfigurationFromInputStream(isOne);
560 configurationReader->readNamespaceConfigurations(namespaceConfigurationsMock);
561 configurationReader->readConfigurationFromInputStream(isTwo);
562 configurationReader->readNamespaceConfigurations(namespaceConfigurationsMock);
563}
564
565TEST_F(ConfigurationReaderInputStreamTest, CanReadJSONSharedDataLayerConfigurationWithEmptyNamespacePrefixValue)
566{
567 InSequence dummy;
568 std::istringstream is(R"JSON(
569 {
570 "sharedDataLayer":
571 [
572 {
573 "namespacePrefix": "",
574 "useDbBackend": false,
575 "enableNotifications": false
576 }
577 ]
578 })JSON");
579
580 expectAddNamespaceConfiguration("", false, false);
581 configurationReader->readConfigurationFromInputStream(is);
582 configurationReader->readNamespaceConfigurations(namespaceConfigurationsMock);
583}
584
585TEST_F(ConfigurationReaderInputStreamTest, CanCatchAndThrowJSONSyntaxError)
586{
587 InSequence dummy;
588 std::istringstream is(R"JSON(
589 {
590 "sharedDataLayer":
591 [
592 {
593 "abc"
594 }
595 ]
596 })JSON");
597
598 readConfigurationAndExpectJsonParserException(is);
599}
600
601TEST_F(ConfigurationReaderInputStreamTest, CanCatchAndThrowParameterUseDbBackendBadValue)
602{
603 InSequence dummy;
604 std::istringstream is(R"JSON(
605 {
606 "sharedDataLayer":
607 [
608 {
609 "namespacePrefix": "someKnownNamespacePrefix",
610 "useDbBackend": "bad-value",
611 "enableNotifications": false
612 }
613 ]
614 })JSON");
615
616 readConfigurationAndExpectBadValueException(is, "useDbBackend");
617}
618
619TEST_F(ConfigurationReaderInputStreamTest, CanCatchAndThrowParameterEnableNotificationsBadValue)
620{
621 InSequence dummy;
622 std::istringstream is(R"JSON(
623 {
624 "sharedDataLayer":
625 [
626 {
627 "namespacePrefix": "someKnownNamespacePrefix",
628 "useDbBackend": true,
629 "enableNotifications": "bad-value"
630 }
631 ]
632 })JSON");
633
634 readConfigurationAndExpectBadValueException(is, "enableNotifications");
635}
636
637TEST_F(ConfigurationReaderInputStreamTest, CanCatchAndThrowMisingMandatoryNamespacePrefixParameter)
638{
639 InSequence dummy;
640 std::istringstream is(R"JSON(
641 {
642 "sharedDataLayer":
643 [
644 {
645 "useDbBackend": true,
646 "enableNotifications": true
647 }
648 ]
649 })JSON");
650
651 readConfigurationAndExpectMissingParameterException(is, "namespacePrefix");
652}
653
654TEST_F(ConfigurationReaderInputStreamTest, CanCatchAndThrowMisingMandatoryUseDbBackendParameter)
655{
656 InSequence dummy;
657 std::istringstream is(R"JSON(
658 {
659 "sharedDataLayer":
660 [
661 {
662 "namespacePrefix": "someKnownNamespacePrefix",
663 "enableNotifications": true
664 }
665 ]
666 })JSON");
667
668 readConfigurationAndExpectMissingParameterException(is, "useDbBackend");
669}
670
671TEST_F(ConfigurationReaderInputStreamTest, CanCatchAndThrowMisingMandatoryEnableNotificationsParameter)
672{
673 InSequence dummy;
674 std::istringstream is(R"JSON(
675 {
676 "sharedDataLayer":
677 [
678 {
679 "namespacePrefix": "someKnownNamespacePrefix",
680 "useDbBackend": true
681 }
682 ]
683 })JSON");
684
685 readConfigurationAndExpectMissingParameterException(is, "enableNotifications");
686}
687
688TEST_F(ConfigurationReaderInputStreamTest, CanThrowValidationErrorForNamespacePrefixWithDisallowedCharacters)
689{
690 InSequence dummy;
691 std::istringstream is(R"JSON(
692 {
693 "sharedDataLayer":
694 [
695 {
696 "namespacePrefix": "a,b{c}",
697 "useDbBackend": true,
698 "enableNotifications": true
699 }
700 ]
701 })JSON");
702
703 readConfigurationAndExpectNamespacePrefixValidationException(is, "a,b{c}");
704}
705
706TEST_F(ConfigurationReaderInputStreamTest, CanThrowValidationErrorForEnableNotificationsWithNoDbBackend)
707{
708 InSequence dummy;
709 std::istringstream is(R"JSON(
710 {
711 "sharedDataLayer":
712 [
713 {
714 "namespacePrefix": "someKnownNamespacePrefix",
715 "useDbBackend": false,
716 "enableNotifications": true
717 }
718 ]
719 })JSON");
720
721 readConfigurationAndExpectEnableNotificationsValidationException(is);
722}
723
724TEST_F(ConfigurationReaderInputStreamTest, WillNotReadDatabaseConfigurationToNonEmptyContainer)
725{
726 EXPECT_EXIT(tryToReadDatabaseConfigurationToNonEmptyContainer(),
727 KilledBySignal(SIGABRT), "ABORT.*configurationreader\\.cpp");
728}
729
730TEST_F(ConfigurationReaderInputStreamTest, WillNotReadNamespaceConfigurationToNonEmptyContainer)
731{
732 EXPECT_EXIT(tryToReadNamespaceConfigurationToNonEmptyContainer(),
733 KilledBySignal(SIGABRT), "ABORT.*configurationreader\\.cpp");
734}
735
736class ConfigurationReaderEnvironmentVariableTest: public ConfigurationReaderBaseTest
737{
738public:
739 std::string dbHostEnvVariableValue;
740 std::string dbPortEnvVariableValue;
Rolf Badorek2dcf9402019-10-01 18:33:58 +0300741 std::string sentinelPortEnvVariableValue;
742 std::string sentinelMasterNameEnvVariableValue;
Rolf Badorekef2bf512019-08-20 11:17:15 +0300743 std::istringstream is{R"JSON(
744 {
745 "database":
746 {
747 "type": "redis-cluster",
748 "servers":
749 [
750 {
751 "address": "10.20.30.40:50000"
752 },
753 {
754 "address": "10.20.30.50:50001"
755 }
756 ]
757 }
758 })JSON"};
759
760 ConfigurationReaderEnvironmentVariableTest():
761 ConfigurationReaderBaseTest(DB_HOST_ENV_VAR_NAME)
762 {
763 }
764
765 void readEnvironmentConfigurationAndExpectConfigurationErrorException()
766 {
767 std::ostringstream os;
768 os << "Configuration error in " << someKnownInputSource << ": some error";
769
770 EXPECT_CALL(databaseConfigurationMock, checkAndApplyDbType(_))
771 .WillOnce(Throw(Exception("some error")));
772
773 EXPECT_THROW( {
774 try
775 {
776 EXPECT_CALL(systemMock, getenv(_))
Rolf Badorek2dcf9402019-10-01 18:33:58 +0300777 .Times(4)
Rolf Badorekef2bf512019-08-20 11:17:15 +0300778 .WillOnce(Return(dbHostEnvVariableValue.c_str()))
779 .WillOnce(Return(nullptr));
780 initializeReaderWithoutDirectories();
781 configurationReader->readDatabaseConfiguration(databaseConfigurationMock);
782 }
783 catch (const std::exception& e)
784 {
785 EXPECT_EQ(os.str(), e.what());
786 throw;
787 }
788 }, Exception);
789 }
790};
791
792TEST_F(ConfigurationReaderEnvironmentVariableTest, EnvironmentConfigurationCanOverrideJSONDatabaseConfiguration)
793{
794 InSequence dummy;
795 dbHostEnvVariableValue = "unknownAddress.local";
796 expectGetEnvironmentString(dbHostEnvVariableValue.c_str());
797 dbPortEnvVariableValue = "12345";
798 expectGetEnvironmentString(dbPortEnvVariableValue.c_str());
Rolf Badorek2dcf9402019-10-01 18:33:58 +0300799 expectGetEnvironmentString(nullptr); //SENTINEL_PORT_ENV_VAR_NAME
800 expectGetEnvironmentString(nullptr); //SENTINEL_MASTER_NAME_ENV_VAR_NAME
Rolf Badorekef2bf512019-08-20 11:17:15 +0300801
802 expectDbTypeConfigurationCheckAndApply("redis-standalone");
803 expectDBServerAddressConfigurationCheckAndApply("unknownAddress.local:12345");
804 initializeReaderWithSDLconfigFileDirectory();
805 configurationReader->readConfigurationFromInputStream(is);
806 configurationReader->readDatabaseConfiguration(databaseConfigurationMock);
807}
808
809TEST_F(ConfigurationReaderEnvironmentVariableTest, EnvironmentConfigurationWithoutPortIsAccepted)
810{
811 InSequence dummy;
812 dbHostEnvVariableValue = "server.local";
813 expectGetEnvironmentString(dbHostEnvVariableValue.c_str());
Rolf Badorek2dcf9402019-10-01 18:33:58 +0300814 expectGetEnvironmentString(nullptr); //DB_PORT_ENV_VAR_NAME
815 expectGetEnvironmentString(nullptr); //SENTINEL_PORT_ENV_VAR_NAME
816 expectGetEnvironmentString(nullptr); //SENTINEL_MASTER_NAME_ENV_VAR_NAME
Rolf Badorekef2bf512019-08-20 11:17:15 +0300817
818 expectDbTypeConfigurationCheckAndApply("redis-standalone");
819 expectDBServerAddressConfigurationCheckAndApply("server.local");
820 initializeReaderWithoutDirectories();
821 configurationReader->readDatabaseConfiguration(databaseConfigurationMock);
822}
823
824TEST_F(ConfigurationReaderEnvironmentVariableTest, EmptyEnvironmentVariableThrows)
825{
826 dbHostEnvVariableValue = "";
827 readEnvironmentConfigurationAndExpectConfigurationErrorException();
828}
829
830TEST_F(ConfigurationReaderEnvironmentVariableTest, IllegalCharacterInEnvironmentVariableThrows)
831{
832 dbHostEnvVariableValue = "@";
833 readEnvironmentConfigurationAndExpectConfigurationErrorException();
834}
835
836TEST_F(ConfigurationReaderEnvironmentVariableTest, EnvironmentConfigurationAcceptIPv6Address)
837{
838 InSequence dummy;
839 dbHostEnvVariableValue = "[2001::123]:12345";
840 expectGetEnvironmentString(dbHostEnvVariableValue.c_str());
Rolf Badorek2dcf9402019-10-01 18:33:58 +0300841 expectGetEnvironmentString(nullptr); //DB_PORT_ENV_VAR_NAME
842 expectGetEnvironmentString(nullptr); //SENTINEL_PORT_ENV_VAR_NAME
843 expectGetEnvironmentString(nullptr); //SENTINEL_MASTER_NAME_ENV_VAR_NAME
Rolf Badorekef2bf512019-08-20 11:17:15 +0300844
845 expectDbTypeConfigurationCheckAndApply("redis-standalone");
846 expectDBServerAddressConfigurationCheckAndApply("[2001::123]:12345");
847 initializeReaderWithoutDirectories();
848 configurationReader->readDatabaseConfiguration(databaseConfigurationMock);
849}
Rolf Badorek2dcf9402019-10-01 18:33:58 +0300850
851TEST_F(ConfigurationReaderEnvironmentVariableTest, EnvironmentConfigurationWithSentinel)
852{
853 InSequence dummy;
854 dbHostEnvVariableValue = "sentinelAddress.local";
855 expectGetEnvironmentString(dbHostEnvVariableValue.c_str());
856 dbPortEnvVariableValue = "1111";
857 expectGetEnvironmentString(dbPortEnvVariableValue.c_str());
858 sentinelPortEnvVariableValue = "2222";
859 expectGetEnvironmentString(sentinelPortEnvVariableValue.c_str());
860 sentinelMasterNameEnvVariableValue = "mymaster";
861 expectGetEnvironmentString(sentinelMasterNameEnvVariableValue.c_str());
862
863 expectDbTypeConfigurationCheckAndApply("redis-sentinel");
864 expectSentinelAddressConfigurationCheckAndApply("sentinelAddress.local:2222");
865 expectSentinelMasterNameConfigurationCheckAndApply(sentinelMasterNameEnvVariableValue);
866 initializeReaderWithoutDirectories();
867 configurationReader->readDatabaseConfiguration(databaseConfigurationMock);
868}