RTC Toolkit 5.0.0
Loading...
Searching...
No Matches
repositoryIfTestSuite.hpp
Go to the documentation of this file.
1
13#ifndef RTCTK_COMPONENTFRAMEWORK_TEST_REPOSITORYIFTESTSUITE_HPP
14#define RTCTK_COMPONENTFRAMEWORK_TEST_REPOSITORYIFTESTSUITE_HPP
15
18
19#include <gmock/gmock.h>
20#include <gtest/gtest.h>
21
22#include <fmt/format.h>
23
24#include <exception>
25#include <future>
26#include <type_traits>
27
28#pragma GCC diagnostic push
29// Do not generate compiler warnings for deprecated API methods invoked in unit tests.
30#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
31
33
34static std::shared_ptr<RepositoryIf> MakeRepository();
35
36template <typename T>
37class RepositoryIfTestSuite : public testing::Test {
38public:
39 void SetUp() override {
40 repo = MakeRepository();
41 dp_paths.clear();
42 for (unsigned i = 0; i < 10; i++) {
43 std::string name = fmt::format("/test/datapoint_{:0>2}", i);
44 dp_paths.push_back(DataPointPath(name));
45 }
46 }
47
48 void TearDown() override {
49 for (const auto& path : dp_paths) {
50 if (repo->DataPointExists(path)) {
51 repo->DeleteDataPoint(path);
52 }
53 }
54 dp_paths.clear();
55 }
56
58 if constexpr (std::is_same_v<T, std::byte>) {
59 return std::byte{43};
60 } else if constexpr (std::is_same_v<T, RtcBinary>) {
61 return {std::byte{42}, std::byte{43}};
62 } else if constexpr (std::is_same_v<T, RtcBool>) {
63 return false;
64 } else if constexpr (std::is_same_v<T, RtcString>) {
65 return "foo";
66 } else if constexpr (std::is_same_v<T, RtcMatrixBool>) {
67 return {1, 3, {false, true, false}};
68 } else if constexpr (std::is_same_v<T, RtcVectorBool>) {
69 return {false, false, false};
70 } else if constexpr (std::is_same_v<T, RtcMatrixString>) {
71 return {1, 2, {"foo", "bar"}};
72 } else if constexpr (std::is_same_v<T, RtcVectorString>) {
73 return {"goo", "gar"};
74 } else if constexpr (std::is_arithmetic_v<T>) {
75 return 42;
76 } else if constexpr (IS_MATRIX_BUFFER_TYPE<T>) {
77 return {1, 2, {42, 44}};
78 } else {
79 return {42, 43};
80 }
81 }
82
84 // Make sure the values and shapes are different for the test value returned by this method
85 // compared to those that are in MakeSomeTestValue.
86 if constexpr (std::is_same_v<T, std::byte>) {
87 return std::byte{43};
88 } else if constexpr (std::is_same_v<T, RtcBinary>) {
89 return {std::byte{43}, std::byte{44}, std::byte{45}};
90 } else if constexpr (std::is_same_v<T, RtcBool>) {
91 return true;
92 } else if constexpr (std::is_same_v<T, RtcString>) {
93 return "barfoo";
94 } else if constexpr (std::is_same_v<T, RtcMatrixBool>) {
95 return {2, 2, {true, false, true, false}};
96 } else if constexpr (std::is_same_v<T, RtcVectorBool>) {
97 return {true, true, true, true};
98 } else if constexpr (std::is_same_v<T, RtcMatrixString>) {
99 return {1, 3, {"foo", "bar", "baz"}};
100 } else if constexpr (std::is_same_v<T, RtcVectorString>) {
101 return {"goo", "gar", "gaz"};
102 } else if constexpr (std::is_arithmetic_v<T>) {
103 return 43;
104 } else if constexpr (IS_MATRIX_BUFFER_TYPE<T>) {
105 return {1, 3, {43, 44, 45}};
106 } else {
107 return {43, 44, 45};
108 }
109 }
110
111 template <typename U>
112 size_t GetExpectedSize(const U& value) {
113 if constexpr (std::is_same_v<U, std::byte>) {
114 return sizeof(value);
115 } else if constexpr (std::is_arithmetic_v<U>) {
116 return sizeof(value);
117 } else {
118 auto val = MakeSomeTestValue();
119 return val.size();
120 }
121 }
122
123protected:
124 std::vector<DataPointPath> dp_paths;
125 std::shared_ptr<RepositoryIf> repo;
126};
127
129
130template <typename T>
132
133// Define the fundamental type-set of datapoint types that must be supported for basic operations.
134using TypeSetForBasicOperation = ::testing::Types<RtcBool,
135 RtcInt8,
136 RtcInt16,
137 RtcInt32,
138 RtcInt64,
139 RtcUInt8,
140 RtcUInt16,
141 RtcUInt32,
142 RtcUInt64,
143 RtcFloat,
144 RtcDouble,
145 RtcString,
146 RtcBinary,
171
172// define different test sets
174
176 auto path = this->dp_paths[0];
177 auto& repo = *this->repo;
178 auto create_value = this->MakeSomeTestValue();
180
181 EXPECT_NO_THROW({ repo.DataPointExists(path); });
182
183 ASSERT_FALSE(repo.DataPointExists(path));
184
185 repo.CreateDataPoint(path, create_value);
186 ASSERT_TRUE(repo.DataPointExists(path));
187
188 repo.ReadDataPoint(path, read_value);
190
191 repo.DeleteDataPoint(path);
192 ASSERT_FALSE(repo.DataPointExists(path));
193
194 // creating again to test that recreating a previously deleted datapoint also works
195 repo.CreateDataPoint(path, create_value);
196 ASSERT_TRUE(repo.DataPointExists(path));
197}
198
200 auto path = this->dp_paths[0];
201 auto& repo = *this->repo;
202 auto create_value = this->MakeSomeTestValue();
203 auto write_value = this->MakeOtherTestValue();
205
206 repo.CreateDataPoint(path, create_value);
207
208 repo.WriteDataPoint(path, write_value);
209 repo.ReadDataPoint(path, read_value);
211
212 // writing again to test a subsequent write
213 repo.WriteDataPoint(path, create_value);
214 repo.ReadDataPoint(path, read_value);
216}
217
219 auto path = this->dp_paths[0];
220 auto& repo = *this->repo;
221 const auto create_value = this->MakeSomeTestValue();
222 const auto write_value = this->MakeOtherTestValue();
224
225 repo.CreateDataPoint(path, create_value);
226
227 repo.WriteDataPoint(path, write_value);
228 repo.ReadDataPoint(path, read_value);
230
231 // writing again to test a subsequent write
232 repo.WriteDataPoint(path, create_value);
233 repo.ReadDataPoint(path, read_value);
235}
236
238 auto path = this->dp_paths[0];
239 RepositoryIf& repo = *this->repo;
240 auto create_value = this->MakeSomeTestValue();
241 auto write_value = this->MakeOtherTestValue();
242
243 repo.CreateDataPoint(path, create_value);
244 repo.SetDataPoint(path, write_value);
245
247}
248
250 auto path = this->dp_paths[0];
251 auto& repo = *this->repo;
252 auto create_value = this->MakeSomeTestValue();
253
254 repo.CreateDataPoint(path, create_value);
255
256 const auto& type = repo.GetDataPointType(path);
257
258 EXPECT_EQ(type, typeid(TypeParam));
259}
260
262 auto path = this->dp_paths[0];
263 auto& repo = *this->repo;
264 auto create_value = this->MakeSomeTestValue();
265 auto create_value_size = this->GetExpectedSize(create_value);
266
267 repo.CreateDataPoint(path, create_value);
268 ASSERT_EQ(repo.GetDataPointSize(path), create_value_size);
269}
270
272 auto path = this->dp_paths[0];
273 auto& repo = *this->repo;
274 auto create_value = this->MakeSomeTestValue();
275
276 repo.CreateDataPoint(path, create_value);
277 auto shape = repo.GetDataPointShape(path);
278
279 if constexpr (std::is_same_v<TypeParam, std::byte>) {
280 ASSERT_TRUE(shape.empty());
281 } else if constexpr (std::is_arithmetic_v<TypeParam>) {
282 ASSERT_TRUE(shape.empty());
283 } else if constexpr (IS_MATRIX_BUFFER_TYPE<TypeParam>) {
284 ASSERT_EQ(shape.size(), 2);
285 ASSERT_EQ(shape[0], create_value.GetNrows());
286 ASSERT_EQ(shape[1], create_value.GetNcols());
287 } else if constexpr (IS_VECTOR_TYPE<TypeParam>) {
288 ASSERT_EQ(shape.size(), 1);
289 ASSERT_EQ(shape[0], create_value.size());
290 } else if constexpr (std::is_same_v<TypeParam, RtcString>) {
291 ASSERT_EQ(shape.size(), 1);
292 ASSERT_EQ(shape[0], create_value.size());
293 } else {
294 FAIL() << "Should never enter here. There is a bug in the test code.";
295 }
296}
297
299 auto path = this->dp_paths[0];
300 auto& repo = *this->repo;
301
302 {
303 auto create_value = this->MakeSomeTestValue();
304 auto write_value = this->MakeOtherTestValue();
306 bool exists = false;
307
309 req.CreateDataPoint(path, create_value);
310 req.DataPointExists(path, exists);
311 req.WriteDataPoint(path, write_value);
312 req.ReadDataPoint(path, read_value);
313 repo.SendRequest(req).Wait();
314
315 ASSERT_EQ(exists, true);
317 }
318
319 {
320 bool exists = false;
322
323 req.DeleteDataPoint(path);
324 req.DataPointExists(path, exists);
325 repo.SendRequest(req).Wait();
326
327 ASSERT_EQ(exists, false);
328 }
329}
330
332 auto path = this->dp_paths[0];
333 auto& repo = *this->repo;
334
335 {
336 const auto create_value = this->MakeSomeTestValue();
337 const auto write_value = this->MakeOtherTestValue();
339 bool exists = false;
340
342 req.CreateDataPoint(path, create_value);
343 req.DataPointExists(path, exists);
344 req.WriteDataPoint(path, write_value);
345 req.ReadDataPoint(path, read_value);
346 repo.SendRequest(req).Wait();
347
348 ASSERT_EQ(exists, true);
350 }
351
352 {
353 bool exists = false;
355
356 req.DeleteDataPoint(path);
357 req.DataPointExists(path, exists);
358 repo.SendRequest(req).Wait();
359
360 ASSERT_EQ(exists, false);
361 }
362}
363
365 auto& repo = *this->repo;
366 auto path_1 = this->dp_paths[0];
367 auto path_2 = this->dp_paths[1];
368 auto create_value_1 = this->MakeSomeTestValue();
369 auto create_value_2 = this->MakeOtherTestValue();
370 auto write_value_1 = create_value_2; // NOLINT(performance-unnecessary-copy-initialization)
371 auto write_value_2 = create_value_1; // NOLINT(performance-unnecessary-copy-initialization)
374
375 {
379 repo.SendRequest(req).Wait();
380 }
381
382 repo.WriteDataPoints(path_1, write_value_1, path_2, write_value_2);
383
384 {
388 repo.SendRequest(req).Wait();
389 }
390
393}
394
396 auto& repo = *this->repo;
397 auto path_1 = this->dp_paths[0];
398 auto path_2 = this->dp_paths[1];
399 auto create_value_1 = this->MakeSomeTestValue();
400 auto create_value_2 = this->MakeOtherTestValue();
403
404 {
408 repo.SendRequest(req).Wait();
409 }
410
411 repo.ReadDataPoints(path_1, read_value_1, path_2, read_value_2);
412
415}
416
418
419template <typename T>
421public:
423 if constexpr (std::is_same_v<T, RtcBinary>) {
424 return T(5000, std::byte{43});
425 } else if constexpr (std::is_same_v<T, RtcString>) {
426 return std::string(5000, 'c');
427 } else if constexpr (std::is_same_v<T, RtcMatrixString>) {
428 return T(500, 500, std::vector<std::string>(500 * 500, std::string("foo")));
429 } else if constexpr (std::is_same_v<T, RtcVectorString>) {
430 return T(5000, std::string("foo"));
431 } else if constexpr (IS_MATRIX_BUFFER_TYPE<T>) {
432 return {500, 500, std::vector<typename T::value_type>(500 * 500, 42)};
433 } else if constexpr (IS_VECTOR_TYPE<T>) {
434 return T(5000, 42);
435 } else {
436 return T(5000);
437 }
438 }
439
441 if constexpr (std::is_same_v<T, RtcBinary>) {
442 return {5000};
443 } else if constexpr (std::is_same_v<T, RtcString>) {
444 return {5000};
445 } else if constexpr (std::is_same_v<T, RtcMatrixString>) {
446 return {500, 500};
447 } else if constexpr (std::is_same_v<T, RtcVectorString>) {
448 return {5000};
449 } else if constexpr (IS_MATRIX_BUFFER_TYPE<T>) {
450 return {500, 500};
451 } else if constexpr (IS_VECTOR_TYPE<T>) {
452 return {5000};
453 } else {
454 return {5000};
455 }
456 }
457
459 if constexpr (std::is_same_v<T, RtcBinary>) {
460 return T(2, std::byte{42});
461 } else if constexpr (std::is_same_v<T, RtcString>) {
462 return std::string(2, 'b');
463 } else if constexpr (std::is_same_v<T, RtcMatrixString>) {
464 return T(2, 2, std::vector<std::string>(2 * 2, std::string("goo")));
465 } else if constexpr (std::is_same_v<T, RtcVectorString>) {
466 return T(2, std::string("goo"));
467 } else if constexpr (IS_MATRIX_BUFFER_TYPE<T>) {
468 return {2, 2, std::vector<typename T::value_type>(2 * 2, 43)};
469 } else if constexpr (IS_VECTOR_TYPE<T>) {
470 return T(2, 43);
471 } else {
472 return T(2);
473 }
474 }
475
477 if constexpr (std::is_same_v<T, RtcBinary>) {
478 return {2};
479 } else if constexpr (std::is_same_v<T, RtcString>) {
480 return {2};
481 } else if constexpr (std::is_same_v<T, RtcMatrixString>) {
482 return {2, 2};
483 } else if constexpr (std::is_same_v<T, RtcVectorString>) {
484 return {2};
485 } else if constexpr (IS_MATRIX_BUFFER_TYPE<T>) {
486 return {2, 2};
487 } else if constexpr (IS_VECTOR_TYPE<T>) {
488 return {2};
489 } else {
490 return {2};
491 }
492 }
493};
494
495using TypeSetAdvancedOperation = ::testing::Types<RtcString,
496 RtcBinary,
521
523
525 auto path = this->dp_paths[0];
526 auto& repo = *this->repo;
527 auto create_value = this->MakeSomeTestValue();
528 auto write_value = this->MakeOtherTestValue();
529
530 repo.CreateDataPoint(path, create_value);
531 auto create_shape = repo.GetDataPointShape(path);
532 repo.WriteDataPoint(path, write_value);
533 auto write_shape = repo.GetDataPointShape(path);
534
536}
537
539 auto path = this->dp_paths[0];
540 auto& repo = *this->repo;
541
542 auto create_value = this->MakeLargeTestValue();
544
546 req.CreateDataPoint(path, create_value);
547 req.ReadDataPoint(path, read_value);
548 repo.SendRequest(req).Wait();
549
551}
552
554 auto path = this->dp_paths[0];
555 auto& repo = *this->repo;
556
557 auto create_value = this->MakeSmallTestValue();
558 auto write_value = this->MakeLargeTestValue();
559 auto expected_shape = this->ExpectedLargeTestValueShape();
561
562 auto val = this->MakeLargeTestValue();
564
566 req.CreateDataPoint(path, create_value);
567 req.WriteDataPoint(path, write_value);
568 req.ReadDataPoint(path, read_value);
569 repo.SendRequest(req).Wait();
571
572 auto shape = repo.GetDataPointShape(path);
574}
575
577 auto path = this->dp_paths[0];
578 auto& repo = *this->repo;
579
580 auto create_value = this->MakeLargeTestValue();
581 auto write_value = this->MakeSmallTestValue();
582 auto expected_shape = this->ExpectedSmallTestValueShape();
584
586 req.CreateDataPoint(path, create_value);
587 req.WriteDataPoint(path, write_value);
588 req.ReadDataPoint(path, read_value);
589 repo.SendRequest(req).Wait();
591
592 auto shape = repo.GetDataPointShape(path);
594}
595
597 auto path = this->dp_paths[0];
598 auto& repo = *this->repo;
599
605
606 if constexpr (std::is_same_v<TypeParam, RtcBinary>) {
607 create_value.resize(1, std::byte{42});
608 expected_shape = {0};
609 } else if constexpr (std::is_same_v<TypeParam, RtcMatrixString>) {
610 create_value.resize(1, 1, "foo");
611 expected_shape = {0, 0};
612 } else if constexpr (std::is_same_v<TypeParam, RtcVectorString>) {
613 create_value.resize(1, "foo");
614 expected_shape = {0};
615 } else if constexpr (std::is_same_v<TypeParam, RtcString>) {
616 create_value = std::string(1, 'c');
617 expected_shape = {0};
618 } else if constexpr (IS_MATRIX_BUFFER_TYPE<TypeParam>) {
619 create_value.resize(1, 1, 42);
620 expected_shape = {0, 0};
621 } else if constexpr (IS_VECTOR_TYPE<TypeParam>) {
622 create_value.resize(1, 42);
623 expected_shape = {0};
624 } else {
625 FAIL() << "Should never enter here. There is a bug in the test code.";
626 }
627
629 req.CreateDataPoint(path, create_value);
630 req.ReadDataPoint(path, read_value_1);
631 req.WriteDataPoint(path, write_value);
632 req.ReadDataPoint(path, read_value_2);
633 repo.SendRequest(req).Wait();
636
637 auto shape = repo.GetDataPointShape(path);
639}
640
642 auto path = this->dp_paths[0];
643 auto& repo = *this->repo;
644
649
650 if constexpr (std::is_same_v<TypeParam, RtcBinary>) {
651 create_value.resize(5000, std::byte{42});
652 expected_shape = {0};
653 } else if constexpr (std::is_same_v<TypeParam, RtcMatrixString>) {
654 create_value.resize(500, 500, "foo");
655 expected_shape = {0, 0};
656 } else if constexpr (std::is_same_v<TypeParam, RtcVectorString>) {
657 create_value.resize(5000, "foo");
658 expected_shape = {0};
659 } else if constexpr (std::is_same_v<TypeParam, RtcString>) {
660 create_value = std::string(5000, 'c');
661 expected_shape = {0};
662 } else if constexpr (IS_MATRIX_BUFFER_TYPE<TypeParam>) {
663 create_value.resize(500, 500, 42);
664 expected_shape = {0, 0};
665 } else if constexpr (IS_VECTOR_TYPE<TypeParam>) {
666 create_value.resize(5000, 42);
667 expected_shape = {0};
668 } else {
669 FAIL() << "Should never enter here. There is a bug in the test code.";
670 }
671
673 req.CreateDataPoint(path, create_value);
674 req.WriteDataPoint(path, write_value);
675 req.ReadDataPoint(path, read_value);
676 repo.SendRequest(req).Wait();
678
679 auto shape = repo.GetDataPointShape(path);
681}
682
684 auto path = this->dp_paths[0];
685 auto& repo = *this->repo;
686
691
692 if constexpr (std::is_same_v<TypeParam, RtcString>) {
693 create_value = "0123456789abcdef";
694 write_value = "abcd";
695 result_value = "abcd456789abcdef";
696 } else if constexpr (std::is_same_v<TypeParam, RtcBinary>) {
697 // clang-format off
698 create_value = {std::byte{1}, std::byte{2}, std::byte{3}, std::byte{4},
699 std::byte{5}, std::byte{6}, std::byte{7}, std::byte{8},
700 std::byte{9}, std::byte{10}, std::byte{11}, std::byte{12},
701 std::byte{13}, std::byte{14}, std::byte{15}, std::byte{16}};
702 write_value = {std::byte{12}, std::byte{13}, std::byte{14}, std::byte{15}};
703 result_value = {std::byte{12}, std::byte{13}, std::byte{14}, std::byte{15},
704 std::byte{5}, std::byte{6}, std::byte{7}, std::byte{8},
705 std::byte{9}, std::byte{10}, std::byte{11}, std::byte{12},
706 std::byte{13}, std::byte{14}, std::byte{15}, std::byte{16}};
707 // clang-format on
708 } else if constexpr (std::is_same_v<TypeParam, RtcMatrixBool>) {
709 // clang-format off
710 create_value = {4, 4, {false, false, false, false,
711 false, false, false, false,
712 false, false, false, false,
713 false, false, false, false}};
714 write_value = {1, 4, {true, true, true, true}};
715 result_value = {4, 4, {true, true, true, true,
716 false, false, false, false,
717 false, false, false, false,
718 false, false, false, false}};
719 // clang-format on
720 } else if constexpr (std::is_same_v<TypeParam, RtcMatrixString>) {
721 // clang-format off
722 create_value = {4, 4, {"1", "2", "3", "4",
723 "5", "6", "7", "8",
724 "9", "10", "11", "12",
725 "13", "14", "15", "16"}};
726 write_value = {1, 4, {"12", "13", "14", "15"}};
727 result_value = {4, 4, {"12", "13", "14", "15",
728 "5", "6", "7", "8",
729 "9", "10", "11", "12",
730 "13", "14", "15", "16"}};
731 // clang-format on
732 } else if constexpr (std::is_same_v<TypeParam, RtcVectorBool>) {
733 // clang-format off
734 create_value = {false, false, false, false, false, false, false, false,
735 false, false, false, false, false, false, false, false};
736 write_value = {true, true, true, true};
737 result_value = {true, true, true, true, false, false, false, false,
738 false, false, false, false, false, false, false, false};
739 // clang-format on
740 } else if constexpr (std::is_same_v<TypeParam, RtcVectorString>) {
741 // clang-format off
742 create_value = {"1", "2", "3", "4", "5", "6", "7", "8",
743 "9", "10", "11", "12", "13", "14", "15", "16"};
744 write_value = {"12", "13", "14", "15"};
745 result_value = {"12", "13", "14", "15", "5", "6", "7", "8",
746 "9", "10", "11", "12", "13", "14", "15", "16"};
747 // clang-format on
748 } else if constexpr (IS_MATRIX_BUFFER_TYPE<TypeParam>) {
749 // clang-format off
750 create_value = {4, 4, {1, 2, 3, 4,
751 5, 6, 7, 8,
752 9, 10, 11, 12,
753 13, 14, 15, 16}};
754 write_value = {1, 4, {12, 13, 14, 15}};
755 result_value = {4, 4, {12, 13, 14, 15,
756 5, 6, 7, 8,
757 9, 10, 11, 12,
758 13, 14, 15, 16}};
759 // clang-format on
760 } else if constexpr (IS_VECTOR_TYPE<TypeParam>) {
761 create_value = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
762 write_value = {12, 13, 14, 15};
763 result_value = {12, 13, 14, 15, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
764 } else {
765 FAIL() << "Should never enter here. There is a bug in the test code.";
766 }
767
769 req.CreateDataPoint(path, create_value);
770 req.PartialWriteDataPoint(path, write_value, 0, 4, 0);
771 req.ReadDataPoint(path, read_value);
772 repo.SendRequest(req).Wait();
773
775}
776
778 auto path = this->dp_paths[0];
779 auto& repo = *this->repo;
780
784
785 if constexpr (std::is_same_v<TypeParam, RtcString>) {
786 create_value = "0123456789abcdef";
787 result_value = "0123";
788 read_value.resize(result_value.size());
789 } else if constexpr (std::is_same_v<TypeParam, RtcBinary>) {
790 // clang-format off
791 create_value = {std::byte{1}, std::byte{2}, std::byte{3}, std::byte{4},
792 std::byte{5}, std::byte{6}, std::byte{7}, std::byte{8},
793 std::byte{9}, std::byte{10}, std::byte{11}, std::byte{12},
794 std::byte{13}, std::byte{14}, std::byte{15}, std::byte{16}};
795 result_value = {std::byte{1}, std::byte{2}, std::byte{3}, std::byte{4}};
796 read_value.resize(result_value.size());
797 // clang-format on
798 } else if constexpr (std::is_same_v<TypeParam, RtcMatrixBool>) {
799 // clang-format off
800 create_value = {4, 4, {true, true, false, false,
801 false, false, true, false,
802 false, false, false, true,
803 false, false, false, false}};
804 result_value = {1, 4, {true, true, false, false}};
805 read_value.resize(result_value.GetNrows(), result_value.GetNcols());
806 // clang-format on
807 } else if constexpr (std::is_same_v<TypeParam, RtcMatrixString>) {
808 // clang-format off
809 create_value = {4, 4, {"1", "2", "3", "4",
810 "5", "6", "7", "8",
811 "9", "10", "11", "12",
812 "13", "14", "15", "16"}};
813 result_value = {1, 4, {"1", "2", "3", "4"}};
814 read_value.resize(result_value.GetNrows(), result_value.GetNcols());
815 // clang-format on
816 } else if constexpr (std::is_same_v<TypeParam, RtcVectorBool>) {
817 // clang-format off
818 create_value = {true, false, true, false, true, false, true, false,
819 true, false, true, false, true, false, true, false};
820 result_value = {true, false, true, false};
821 read_value.resize(result_value.size());
822 // clang-format on
823 } else if constexpr (std::is_same_v<TypeParam, RtcVectorString>) {
824 create_value = {
825 "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"};
826 result_value = {"1", "2", "3", "4"};
827 read_value.resize(result_value.size());
828 } else if constexpr (IS_MATRIX_BUFFER_TYPE<TypeParam>) {
829 // clang-format off
830 create_value = {4, 4, {1, 2, 3, 4,
831 5, 6, 7, 8,
832 9, 10, 11, 12,
833 13, 14, 15, 16}};
834 result_value = {1, 4, {1, 2, 3, 4}};
835 read_value.resize(result_value.GetNrows(), result_value.GetNcols());
836 // clang-format on
837 } else if constexpr (IS_VECTOR_TYPE<TypeParam>) {
838 create_value = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
839 result_value = {1, 2, 3, 4};
840 read_value.resize(result_value.size());
841 } else {
842 FAIL() << "Should never enter here. There is a bug in the test code.";
843 }
844
846 req.CreateDataPoint(path, create_value);
847 req.PartialReadDataPoint(path, read_value, 0, 4, 0);
848 repo.SendRequest(req).Wait();
849
851}
852
853template <typename T>
854struct TypeMap {};
855
856template <>
859 using SpanType = gsl::span<char>;
860};
861
862template <typename T, typename A>
867
868template <typename T, typename A>
869struct TypeMap<std::vector<T, A>> {
870 using BufferType = std::vector<T, A>;
871 using SpanType = gsl::span<T>;
872};
873
874template <typename A>
875struct TypeMap<std::vector<bool, A>> {
876 using BufferType = boost::container::vector<bool, A>;
877 using SpanType = gsl::span<bool>;
878};
879
880template <typename A>
882 using BufferType = boost::container::vector<bool, A>;
884};
885
887 auto path = this->dp_paths[0];
888 auto& repo = *this->repo;
889
890 using BufferType = typename TypeMap<TypeParam>::BufferType;
891 BufferType create_value;
892 BufferType write_value;
893 BufferType read_value;
894
895 if constexpr (std::is_same_v<TypeParam, RtcString>) {
896 create_value = "abcd";
897 write_value = "1234";
898 read_value.resize(create_value.size());
899 } else if constexpr (std::is_same_v<TypeParam, RtcBinary>) {
900 create_value = {std::byte{1}, std::byte{2}, std::byte{3}, std::byte{4}};
901 write_value = {std::byte{11}, std::byte{12}, std::byte{13}, std::byte{14}};
902 read_value.resize(create_value.size());
903 } else if constexpr (std::is_same_v<TypeParam, RtcMatrixBool>) {
904 create_value = {true, true, false, false};
905 write_value = {false, false, true, true};
906 read_value.resize(create_value.size());
907 } else if constexpr (std::is_same_v<TypeParam, RtcMatrixString>) {
908 create_value = {2, 2, {"aa", "bb", "cc", "dd"}};
909 write_value = {2, 2, {"00", "11", "22", "33"}};
910 read_value.resize(create_value.GetNrows(), create_value.GetNcols());
911 } else if constexpr (IS_MATRIX_BUFFER_TYPE<TypeParam>) {
912 create_value = {2, 2, {1, 2, 3, 4}};
913 write_value = {2, 2, {11, 12, 13, 14}};
914 read_value.resize(create_value.GetNrows(), create_value.GetNcols());
915 } else if constexpr (std::is_same_v<TypeParam, RtcVectorBool>) {
916 create_value = {true, false, true, false};
917 write_value = {false, true, false, true};
918 read_value.resize(create_value.size());
919 } else if constexpr (std::is_same_v<TypeParam, RtcVectorString>) {
920 create_value = {"aa", "bb", "cc", "dd"};
921 write_value = {"00", "11", "22", "33"};
922 read_value.resize(create_value.size());
923 } else if constexpr (IS_VECTOR_TYPE<TypeParam>) {
924 create_value = {1, 2, 3, 4};
925 write_value = {11, 12, 13, 14};
926 read_value.resize(create_value.size());
927 } else {
928 FAIL() << "Should never enter here. There is a bug in the test code.";
929 }
930
931 using SpanT = typename TypeMap<TypeParam>::SpanType;
935
936 if constexpr (std::is_same_v<TypeParam, RtcMatrixBool>) {
939 read_span = SpanT(2, 2, read_value);
940 } else {
944 }
945
946 repo.CreateDataPoint(path, create_span);
947 ASSERT_EQ(repo.GetDataPointType(path), typeid(TypeParam));
948
949 repo.ReadDataPoint(path, read_span);
951
952 repo.WriteDataPoint(path, write_span);
953 repo.ReadDataPoint(path, read_span);
955
956 if constexpr (std::is_same_v<TypeParam, RtcString>) {
957 // For a string datapoints we check that we can also create and write to them using
958 // read-only string views. The std::string_view can be thought of as a read-only span.
959 auto path2 = this->dp_paths[1];
960 std::string_view create_view = create_value;
961 std::string_view write_view = write_value;
962
963 repo.CreateDataPoint(path2, create_view);
964 ASSERT_EQ(repo.GetDataPointType(path2), typeid(TypeParam));
965
966 repo.ReadDataPoint(path2, read_value);
968
969 repo.WriteDataPoint(path2, write_view);
970 repo.ReadDataPoint(path2, read_value);
972 }
973}
974
976 auto path = this->dp_paths[0];
977 auto& repo = *this->repo;
978
979 if constexpr (std::is_same_v<TypeParam, RtcString> or IS_VECTOR_TYPE<TypeParam>) {
980 using ArrayType = std::array<typename TypeParam::value_type, 4>;
984 if constexpr (std::is_same_v<TypeParam, RtcString>) {
985 create_array = {'a', 'b', 'c', 'd'};
986 write_array = {'1', '2', '3', '4'};
987 } else if constexpr (std::is_same_v<TypeParam, RtcBinary>) {
988 create_array = {std::byte{1}, std::byte{2}, std::byte{3}, std::byte{4}};
989 write_array = {std::byte{11}, std::byte{12}, std::byte{13}, std::byte{14}};
990 } else if constexpr (std::is_same_v<TypeParam, RtcVectorBool>) {
991 create_array = {true, false, true, false};
992 write_array = {false, true, false, true};
993 } else if constexpr (std::is_same_v<TypeParam, RtcVectorString>) {
994 create_array = {"aa", "bb", "cc", "dd"};
995 write_array = {"00", "11", "22", "33"};
996 } else {
997 create_array = {1, 2, 3, 4};
998 write_array = {11, 12, 13, 14};
999 }
1000
1001 repo.CreateDataPoint(path, create_array);
1002 ASSERT_EQ(repo.GetDataPointType(path), typeid(TypeParam));
1003
1004 repo.ReadDataPoint(path, read_array);
1006
1007 repo.WriteDataPoint(path, write_array);
1008 repo.ReadDataPoint(path, read_array);
1010
1011 } else if constexpr (IS_MATRIX_BUFFER_TYPE<TypeParam>) {
1012 using Row = std::array<typename TypeParam::value_type, 2>;
1013 using MatrixType = std::array<Row, 2>;
1017 if constexpr (std::is_same_v<TypeParam, RtcMatrixBool>) {
1018 create_array = {Row{true, false}, Row{true, false}};
1019 write_array = {Row{false, true}, Row{false, true}};
1020 } else if constexpr (std::is_same_v<TypeParam, RtcMatrixString>) {
1021 create_array = {Row{"aa", "bb"}, Row{"cc", "dd"}};
1022 write_array = {Row{"00", "11"}, Row{"22", "33"}};
1023 } else {
1024 create_array = {Row{1, 2}, Row{3, 4}};
1025 write_array = {Row{11, 12}, Row{13, 14}};
1026 }
1027
1028 repo.CreateDataPoint(path, create_array);
1029 ASSERT_EQ(repo.GetDataPointType(path), typeid(TypeParam));
1030
1031 repo.ReadDataPoint(path, read_array);
1033
1034 repo.WriteDataPoint(path, write_array);
1035 repo.ReadDataPoint(path, read_array);
1037
1038 } else {
1039 FAIL() << "Should never enter here. There is a bug in the test code.";
1040 }
1041}
1042
1044 using testing::ElementsAreArray;
1045 auto path = this->dp_paths[0];
1046 auto& repo = *this->repo;
1047
1048 if constexpr (std::is_same_v<TypeParam, RtcString> or IS_VECTOR_TYPE<TypeParam>) {
1049 using ValueType = typename TypeParam::value_type;
1053 if constexpr (std::is_same_v<TypeParam, RtcString>) {
1054 create_array[0] = 'a';
1055 create_array[1] = 'b';
1056 create_array[2] = 'c';
1057 create_array[3] = 'd';
1058 write_array[0] = '1';
1059 write_array[1] = '2';
1060 write_array[2] = '3';
1061 write_array[3] = '4';
1062 } else if constexpr (std::is_same_v<TypeParam, RtcBinary>) {
1063 create_array[0] = std::byte{1};
1064 create_array[1] = std::byte{2};
1065 create_array[2] = std::byte{3};
1066 create_array[3] = std::byte{4};
1067 write_array[0] = std::byte{11};
1068 write_array[1] = std::byte{12};
1069 write_array[2] = std::byte{13};
1070 write_array[3] = std::byte{14};
1071 } else if constexpr (std::is_same_v<TypeParam, RtcVectorBool>) {
1072 create_array[0] = true;
1073 create_array[1] = false;
1074 create_array[2] = false;
1075 create_array[3] = true;
1076 write_array[0] = false;
1077 write_array[1] = true;
1078 write_array[2] = true;
1079 write_array[3] = false;
1080 } else if constexpr (std::is_same_v<TypeParam, RtcVectorString>) {
1081 create_array[0] = "aa";
1082 create_array[1] = "bb";
1083 create_array[2] = "cc";
1084 create_array[3] = "dd";
1085 write_array[0] = "00";
1086 write_array[1] = "11";
1087 write_array[2] = "22";
1088 write_array[3] = "33";
1089 } else {
1090 create_array[0] = 1;
1091 create_array[1] = 2;
1092 create_array[2] = 3;
1093 create_array[3] = 4;
1094 write_array[0] = 11;
1095 write_array[1] = 12;
1096 write_array[2] = 13;
1097 write_array[3] = 14;
1098 }
1099
1100 repo.CreateDataPoint(path, create_array);
1101 ASSERT_EQ(repo.GetDataPointType(path), typeid(TypeParam));
1102
1103 repo.ReadDataPoint(path, read_array);
1104 gsl::span<ValueType, 4> create_span(std::begin(create_array), std::end(create_array));
1106
1107 repo.WriteDataPoint(path, write_array);
1108 repo.ReadDataPoint(path, read_array);
1109 gsl::span<ValueType, 4> write_span(std::begin(write_array), std::end(write_array));
1111
1112 } else if constexpr (IS_MATRIX_BUFFER_TYPE<TypeParam>) {
1113 using ValueType = typename TypeParam::value_type;
1114 ValueType create_array[2][2];
1115 ValueType write_array[2][2];
1116 ValueType read_array[2][2];
1117 if constexpr (std::is_same_v<TypeParam, RtcMatrixBool>) {
1118 create_array[0][0] = true;
1119 create_array[0][1] = false;
1120 create_array[1][0] = false;
1121 create_array[1][1] = true;
1122 write_array[0][0] = false;
1123 write_array[0][1] = true;
1124 write_array[1][0] = true;
1125 write_array[1][1] = false;
1126 } else if constexpr (std::is_same_v<TypeParam, RtcMatrixString>) {
1127 create_array[0][0] = "aa";
1128 create_array[0][1] = "bb";
1129 create_array[1][0] = "cc";
1130 create_array[1][1] = "dd";
1131 write_array[0][0] = "00";
1132 write_array[0][1] = "11";
1133 write_array[1][0] = "22";
1134 write_array[1][1] = "33";
1135 } else {
1136 create_array[0][0] = 1;
1137 create_array[0][1] = 2;
1138 create_array[1][0] = 3;
1139 create_array[1][1] = 4;
1140 write_array[0][0] = 11;
1141 write_array[0][1] = 12;
1142 write_array[1][0] = 13;
1143 write_array[1][1] = 14;
1144 }
1145 gsl::span<ValueType, 2 * 2> read_span(&read_array[0][0], 2 * 2);
1146
1147 repo.CreateDataPoint(path, create_array);
1148 ASSERT_EQ(repo.GetDataPointType(path), typeid(TypeParam));
1149
1150 repo.ReadDataPoint(path, read_array);
1151 gsl::span<ValueType, 2 * 2> create_span(&create_array[0][0], 2 * 2);
1153
1154 repo.WriteDataPoint(path, write_array);
1155 repo.ReadDataPoint(path, read_array);
1156 gsl::span<ValueType, 2 * 2> write_span(&write_array[0][0], 2 * 2);
1158
1159 } else {
1160 FAIL() << "Should never enter here. There is a bug in the test code.";
1161 }
1162}
1163
1165
1166class Callbacks : public testing::Test {
1167public:
1168 void SetUp() override {
1169 repo = MakeRepository();
1170 path1 = "/foo"_dppath;
1171 path2 = "/bar"_dppath;
1172 link1 = "/link1"_dppath;
1173 link2 = "/link2"_dppath;
1174 }
1175
1176 void TearDown() override {
1177 if (repo->DataPointExists(link1)) {
1178 repo->DeleteDataPoint(link1);
1179 }
1180 if (repo->DataPointExists(link2)) {
1181 repo->DeleteDataPoint(link2);
1182 }
1183 if (repo->DataPointExists(path1)) {
1184 repo->DeleteDataPoint(path1);
1185 }
1186 if (repo->DataPointExists(path2)) {
1187 repo->DeleteDataPoint(path2);
1188 }
1189 }
1190
1191 template <typename T = RtcInt64>
1192 void SetupDataPoints(const T& initial_value = 0) {
1196 repo->SendRequest(req).Wait();
1197 }
1198
1199protected:
1200 std::shared_ptr<RepositoryIf> repo;
1205};
1206
1222
1225
1226 EXPECT_CALL(callbacks, CreateCallback(path1)).Times(1);
1227 EXPECT_CALL(callbacks, CreateCallback(path2)).Times(1);
1228
1229 auto cb = std::bind(&MockCallbacks::CreateCallback, &callbacks, std::placeholders::_1);
1230
1231 int value1 = 1;
1232 int value2 = 2;
1234 req.CreateDataPoint(path1, value1, std::nullopt, cb);
1235 req.CreateDataPoint(path2, value2, std::nullopt, cb);
1236 repo->SendRequest(req).Wait();
1237}
1238
1241
1242 EXPECT_CALL(callbacks, DeleteCallback(path1)).Times(1);
1243 EXPECT_CALL(callbacks, DeleteCallback(path2)).Times(1);
1244
1245 auto cb = std::bind(&MockCallbacks::DeleteCallback, &callbacks, std::placeholders::_1);
1246
1247 SetupDataPoints();
1248
1250 req.DeleteDataPoint(path1, cb);
1251 req.DeleteDataPoint(path2, cb);
1252 repo->SendRequest(req).Wait();
1253}
1254
1257 bool exists_1, exists_2;
1258
1259 EXPECT_CALL(callbacks, ExistsCallback(path1)).Times(1);
1260 EXPECT_CALL(callbacks, ExistsCallback(path2)).Times(1);
1261
1262 auto cb = std::bind(&MockCallbacks::ExistsCallback, &callbacks, std::placeholders::_1);
1263
1265 req.DataPointExists(path1, exists_1, cb);
1266 req.DataPointExists(path2, exists_2, cb);
1267 repo->SendRequest(req).Wait();
1268}
1269
1272 std::pair<RepositoryIf::PathList, RepositoryIf::PathList> children_1, children_2;
1273
1274 EXPECT_CALL(callbacks, GetChildrenCallback(path1)).Times(1);
1275 EXPECT_CALL(callbacks, GetChildrenCallback(path2)).Times(1);
1276
1277 auto cb = std::bind(&MockCallbacks::GetChildrenCallback, &callbacks, std::placeholders::_1);
1278
1280 req.GetChildren(path1, children_1, true, cb);
1281 req.GetChildren(path2, children_2, false, cb);
1282 repo->SendRequest(req).Wait();
1283}
1284
1287 RtcInt64 buffer1 = 1;
1288 RtcInt64 buffer2 = 2;
1289
1290 EXPECT_CALL(callbacks, WriteCallback(path1)).Times(1);
1291 EXPECT_CALL(callbacks, WriteCallback(path2)).Times(1);
1292
1293 auto cb = std::bind(&MockCallbacks::WriteCallback, &callbacks, std::placeholders::_1);
1294
1295 SetupDataPoints();
1296
1298 req.WriteDataPoint(path1, buffer1, std::nullopt, cb);
1299 req.WriteDataPoint(path2, buffer2, std::nullopt, cb);
1300 repo->SendRequest(req).Wait();
1301}
1302
1306
1307 EXPECT_CALL(callbacks, ReadCallback(path1)).Times(1);
1308 EXPECT_CALL(callbacks, ReadCallback(path2)).Times(1);
1309
1310 auto cb = std::bind(&MockCallbacks::ReadCallback, &callbacks, std::placeholders::_1);
1311
1312 SetupDataPoints();
1313
1315 req.ReadDataPoint(path1, buffer1, std::nullopt, cb);
1316 req.ReadDataPoint(path2, buffer2, std::nullopt, cb);
1317 repo->SendRequest(req).Wait();
1318}
1319
1322 RtcVectorInt64 buffer1{1, 2};
1323 RtcVectorInt64 buffer2{3, 4};
1324
1325 EXPECT_CALL(callbacks, PartialWriteCallback(path1)).Times(1);
1326 EXPECT_CALL(callbacks, PartialWriteCallback(path2)).Times(1);
1327
1328 auto cb = std::bind(&MockCallbacks::PartialWriteCallback, &callbacks, std::placeholders::_1);
1329
1330 SetupDataPoints(RtcVectorInt64{0, 0});
1331
1333 req.PartialWriteDataPoint(path1, buffer1, 0, 2, 0, std::nullopt, cb);
1334 req.PartialWriteDataPoint(path2, buffer2, 0, 2, 0, std::nullopt, cb);
1335 repo->SendRequest(req).Wait();
1336}
1337
1340 RtcVectorInt64 buffer1{0, 0};
1341 RtcVectorInt64 buffer2{0, 0};
1342
1343 EXPECT_CALL(callbacks, PartialReadCallback(path1)).Times(1);
1344 EXPECT_CALL(callbacks, PartialReadCallback(path2)).Times(1);
1345
1346 auto cb = std::bind(&MockCallbacks::PartialReadCallback, &callbacks, std::placeholders::_1);
1347
1348 SetupDataPoints(RtcVectorInt64{1, 2});
1349
1351 req.PartialReadDataPoint(path1, buffer1, 0, 2, 0, std::nullopt, cb);
1352 req.PartialReadDataPoint(path2, buffer2, 0, 2, 0, std::nullopt, cb);
1353 repo->SendRequest(req).Wait();
1354}
1355
1359 metadata1["comment"] = std::string{"foo"};
1360 metadata2["comment"] = std::string{"bar"};
1361
1364
1365 auto cb = std::bind(&MockCallbacks::WriteMetaDataCallback, &callbacks, std::placeholders::_1);
1366
1367 SetupDataPoints();
1368
1370 req.WriteMetaData(path1, metadata1, cb);
1371 req.WriteMetaData(path2, metadata2, cb);
1372 repo->SendRequest(req).Wait();
1373}
1374
1378
1379 EXPECT_CALL(callbacks, ReadMetaDataCallback(path1)).Times(1);
1380 EXPECT_CALL(callbacks, ReadMetaDataCallback(path2)).Times(1);
1381
1382 auto cb = std::bind(&MockCallbacks::ReadMetaDataCallback, &callbacks, std::placeholders::_1);
1383
1384 SetupDataPoints();
1385
1387 req.ReadMetaData(path1, metadata1, cb);
1388 req.ReadMetaData(path2, metadata2, cb);
1389 repo->SendRequest(req).Wait();
1390}
1391
1394
1397
1398 auto cb = std::bind(&MockCallbacks::CreateSymlinkCallback, &callbacks, std::placeholders::_1);
1399
1400 SetupDataPoints();
1401
1403 req.CreateSymlink(path1, "/link1"_dppath, cb);
1404 req.CreateSymlink(path2, "/link2"_dppath, cb);
1405 repo->SendRequest(req).Wait();
1406}
1407
1410
1413
1414 auto cb = std::bind(&MockCallbacks::UpdateSymlinkCallback, &callbacks, std::placeholders::_1);
1415
1416 SetupDataPoints();
1417
1419 req.CreateSymlink(path1, "/link1"_dppath);
1420 req.CreateSymlink(path2, "/link2"_dppath);
1421 // The update swaps the targets of the two links.
1422 req.UpdateSymlink(path2, "/link1"_dppath, cb);
1423 req.UpdateSymlink(path1, "/link2"_dppath, cb);
1424 repo->SendRequest(req).Wait();
1425}
1426
1428 // Send a second CreateDataPoint request within the callback and make sure it completes,
1429 // i.e it does not deadlock.
1431
1432 // Since the second request is executed within the callback cb1, the order of the callbacks is
1433 // defined by the following sequence.
1434 testing::InSequence seq;
1435 EXPECT_CALL(callbacks, CreateCallback(path1)).Times(1);
1436 EXPECT_CALL(callbacks, CreateCallback(path2)).Times(1);
1437
1438 auto cb2 = std::bind(&MockCallbacks::CreateCallback, &callbacks, std::placeholders::_1);
1439
1440 auto cb1 = [&](const DataPointPath& path) {
1441 callbacks.CreateCallback(path);
1442 int value2 = 2;
1444 req2.CreateDataPoint(path2, value2, std::nullopt, cb2);
1445 repo->SendRequest(req2).Wait();
1446 };
1447
1448 int value1 = 1;
1450 req1.CreateDataPoint(path1, value1, std::nullopt, cb1);
1451 repo->SendRequest(req1).Wait();
1452}
1453
1455 // Send a second DeleteDataPoint request within the callback and make sure it completes,
1456 // i.e it does not deadlock.
1458
1459 // Since the second request is executed within the callback cb1, the order of the callbacks is
1460 // defined by the following sequence.
1461 testing::InSequence seq;
1462 EXPECT_CALL(callbacks, DeleteCallback(path1)).Times(1);
1463 EXPECT_CALL(callbacks, DeleteCallback(path2)).Times(1);
1464
1465 auto cb2 = std::bind(&MockCallbacks::DeleteCallback, &callbacks, std::placeholders::_1);
1466
1467 auto cb1 = [&](const DataPointPath& path) {
1468 callbacks.DeleteCallback(path);
1470 req2.DeleteDataPoint(path2, cb2);
1471 repo->SendRequest(req2).Wait();
1472 };
1473
1474 SetupDataPoints();
1475
1477 req1.DeleteDataPoint(path1, cb1);
1478 repo->SendRequest(req1).Wait();
1479}
1480
1482 // Send a second DataPointExists request within the callback and make sure it completes,
1483 // i.e it does not deadlock.
1485 bool result1, result2;
1486
1487 // Since the second request is executed within the callback cb1, the order of the callbacks is
1488 // defined by the following sequence.
1489 testing::InSequence seq;
1490 EXPECT_CALL(callbacks, ExistsCallback(path1)).Times(1);
1491 EXPECT_CALL(callbacks, ExistsCallback(path2)).Times(1);
1492
1493 auto cb2 = std::bind(&MockCallbacks::ExistsCallback, &callbacks, std::placeholders::_1);
1494
1495 auto cb1 = [&](const DataPointPath& path) {
1496 callbacks.ExistsCallback(path);
1499 repo->SendRequest(req2).Wait();
1500 };
1501
1502 SetupDataPoints();
1503
1506 repo->SendRequest(req1).Wait();
1507}
1508
1510 // Send a second GetChildren request within the callback and make sure it completes,
1511 // i.e it does not deadlock.
1514 std::pair<PathList, PathList> result1, result2;
1515
1516 // Since the second request is executed within the callback cb1, the order of the callbacks is
1517 // defined by the following sequence.
1518 testing::InSequence seq;
1519 EXPECT_CALL(callbacks, GetChildrenCallback(path1)).Times(1);
1520 EXPECT_CALL(callbacks, GetChildrenCallback(path2)).Times(1);
1521
1522 auto cb2 = std::bind(&MockCallbacks::GetChildrenCallback, &callbacks, std::placeholders::_1);
1523
1524 auto cb1 = [&](const DataPointPath& path) {
1525 callbacks.GetChildrenCallback(path);
1527 req2.GetChildren(path2, result2, false, cb2);
1528 repo->SendRequest(req2).Wait();
1529 };
1530
1531 SetupDataPoints();
1532
1534 req1.GetChildren(path1, result1, true, cb1);
1535 repo->SendRequest(req1).Wait();
1536}
1537
1539 // Send a second WriteDataPoint request within the callback and make sure it completes,
1540 // i.e it does not deadlock.
1542 RtcInt64 buffer1 = 1;
1543 RtcInt64 buffer2 = 2;
1544
1545 // Since the second request is executed within the callback cb1, the order of the callbacks is
1546 // defined by the following sequence.
1547 testing::InSequence seq;
1548 EXPECT_CALL(callbacks, WriteCallback(path1)).Times(1);
1549 EXPECT_CALL(callbacks, WriteCallback(path2)).Times(1);
1550
1551 auto cb2 = std::bind(&MockCallbacks::WriteCallback, &callbacks, std::placeholders::_1);
1552
1553 auto cb1 = [&](const DataPointPath& path) {
1554 callbacks.WriteCallback(path);
1556 req2.WriteDataPoint(path2, buffer2, std::nullopt, cb2);
1557 repo->SendRequest(req2).Wait();
1558 };
1559
1560 SetupDataPoints();
1561
1563 req1.WriteDataPoint(path1, buffer1, std::nullopt, cb1);
1564 repo->SendRequest(req1).Wait();
1565}
1566
1568 // Send a second ReadDataPoint request within the callback and make sure it completes,
1569 // i.e it does not deadlock.
1572
1573 // Since the second request is executed within the callback cb1, the order of the callbacks is
1574 // defined by the following sequence.
1575 testing::InSequence seq;
1576 EXPECT_CALL(callbacks, ReadCallback(path1)).Times(1);
1577 EXPECT_CALL(callbacks, ReadCallback(path2)).Times(1);
1578
1579 auto cb2 = std::bind(&MockCallbacks::ReadCallback, &callbacks, std::placeholders::_1);
1580
1581 auto cb1 = [&](const DataPointPath& path) {
1582 callbacks.ReadCallback(path);
1584 req2.ReadDataPoint(path2, result2, std::nullopt, cb2);
1585 repo->SendRequest(req2).Wait();
1586 };
1587
1588 SetupDataPoints();
1589
1591 req1.ReadDataPoint(path1, result1, std::nullopt, cb1);
1592 repo->SendRequest(req1).Wait();
1593}
1594
1596 // Send a second PartialWriteDataPoint request within the callback and make sure it completes,
1597 // i.e it does not deadlock.
1599 RtcVectorInt64 buffer1{1, 2};
1600 RtcVectorInt64 buffer2{3, 4};
1601
1602 // Since the second request is executed within the callback cb1, the order of the callbacks is
1603 // defined by the following sequence.
1604 testing::InSequence seq;
1605 EXPECT_CALL(callbacks, WriteCallback(path1)).Times(1);
1606 EXPECT_CALL(callbacks, WriteCallback(path2)).Times(1);
1607
1608 auto cb2 = std::bind(&MockCallbacks::WriteCallback, &callbacks, std::placeholders::_1);
1609
1610 auto cb1 = [&](const DataPointPath& path) {
1611 callbacks.WriteCallback(path);
1613 req2.PartialWriteDataPoint(path2, buffer2, 0, 2, 0, std::nullopt, cb2);
1614 repo->SendRequest(req2).Wait();
1615 };
1616
1617 SetupDataPoints(RtcVectorInt64{0, 0});
1618
1620 req1.PartialWriteDataPoint(path1, buffer1, 0, 2, 0, std::nullopt, cb1);
1621 repo->SendRequest(req1).Wait();
1622}
1623
1625 // Send a second PartialReadDataPoint request within the callback and make sure it completes,
1626 // i.e it does not deadlock.
1628 RtcVectorInt64 result1{0, 0};
1629 RtcVectorInt64 result2{0, 0};
1630
1631 // Since the second request is executed within the callback cb1, the order of the callbacks is
1632 // defined by the following sequence.
1633 testing::InSequence seq;
1634 EXPECT_CALL(callbacks, ReadCallback(path1)).Times(1);
1635 EXPECT_CALL(callbacks, ReadCallback(path2)).Times(1);
1636
1637 auto cb2 = std::bind(&MockCallbacks::ReadCallback, &callbacks, std::placeholders::_1);
1638
1639 auto cb1 = [&](const DataPointPath& path) {
1640 callbacks.ReadCallback(path);
1642 req2.PartialReadDataPoint(path2, result2, 0, 2, 0, std::nullopt, cb2);
1643 repo->SendRequest(req2).Wait();
1644 };
1645
1646 SetupDataPoints(RtcVectorInt64{1, 2});
1647
1649 req1.PartialReadDataPoint(path1, result1, 0, 2, 0, std::nullopt, cb1);
1650 repo->SendRequest(req1).Wait();
1651}
1652
1654 // Send a second WriteMetaData request within the callback and make sure it completes,
1655 // i.e it does not deadlock.
1658 metadata1["comment"] = std::string{"foo"};
1659 metadata2["comment"] = std::string{"bar"};
1660
1661 // Since the second request is executed within the callback cb1, the order of the callbacks is
1662 // defined by the following sequence.
1663 testing::InSequence seq;
1664 EXPECT_CALL(callbacks, WriteCallback(path1)).Times(1);
1665 EXPECT_CALL(callbacks, WriteCallback(path2)).Times(1);
1666
1667 auto cb2 = std::bind(&MockCallbacks::WriteCallback, &callbacks, std::placeholders::_1);
1668
1669 auto cb1 = [&](const DataPointPath& path) {
1670 callbacks.WriteCallback(path);
1673 repo->SendRequest(req2).Wait();
1674 };
1675
1676 SetupDataPoints();
1677
1680 repo->SendRequest(req1).Wait();
1681}
1682
1684 // Send a second ReadMetaData request within the callback and make sure it completes,
1685 // i.e it does not deadlock.
1688
1689 // Since the second request is executed within the callback cb1, the order of the callbacks is
1690 // defined by the following sequence.
1691 testing::InSequence seq;
1692 EXPECT_CALL(callbacks, ReadCallback(path1)).Times(1);
1693 EXPECT_CALL(callbacks, ReadCallback(path2)).Times(1);
1694
1695 auto cb2 = std::bind(&MockCallbacks::ReadCallback, &callbacks, std::placeholders::_1);
1696
1697 auto cb1 = [&](const DataPointPath& path) {
1698 callbacks.ReadCallback(path);
1700 req2.ReadMetaData(path2, result2, cb2);
1701 repo->SendRequest(req2).Wait();
1702 };
1703
1704 SetupDataPoints();
1705
1707 req1.ReadMetaData(path1, result1, cb1);
1708 repo->SendRequest(req1).Wait();
1709}
1710
1712 // Send a second CreateSymlink request within the callback and make sure it completes,
1713 // i.e it does not deadlock.
1715
1716 // Since the second request is executed within the callback cb1, the order of the callbacks is
1717 // defined by the following sequence.
1718 testing::InSequence seq;
1721
1722 auto cb2 = std::bind(&MockCallbacks::CreateSymlinkCallback, &callbacks, std::placeholders::_1);
1723
1724 auto cb1 = [&](const DataPointPath& path) {
1725 callbacks.CreateSymlinkCallback(path);
1727 req2.CreateSymlink(path2, "/link2"_dppath, cb2);
1728 repo->SendRequest(req2).Wait();
1729 };
1730
1731 SetupDataPoints();
1732
1734 req1.CreateSymlink(path1, "/link1"_dppath, cb1);
1735 repo->SendRequest(req1).Wait();
1736}
1737
1739 // Send a second UpdateSymlink request within the callback and make sure it completes,
1740 // i.e it does not deadlock.
1743
1744 // Since the second request is executed within the callback cb1, the order of the callbacks is
1745 // defined by the following sequence.
1746 testing::InSequence seq;
1749
1750 auto cb2 = std::bind(&MockCallbacks::UpdateSymlinkCallback, &callbacks, std::placeholders::_1);
1751
1752 auto cb1 = [&](const DataPointPath& path) {
1753 callbacks.UpdateSymlinkCallback(path);
1755 req2.UpdateSymlink(path2, "/link1"_dppath, cb2);
1756 repo->SendRequest(req2).Wait();
1757 };
1758
1759 SetupDataPoints();
1761 req0.CreateSymlink(path1, "/link1"_dppath);
1762 req0.CreateSymlink(path2, "/link2"_dppath);
1763 repo->SendRequest(req0).Wait();
1764
1766 // The updates will swap the targets of the two links.
1767 req1.UpdateSymlink(path1, "/link2"_dppath, cb1);
1768 repo->SendRequest(req1).Wait();
1769}
1770
1772
1773class GetChildren : public testing::Test {
1774public:
1775 void SetUp() override {
1776 repo = MakeRepository();
1777 repo->CreateDataPoint("/topdir/datapoint1"_dppath, 0);
1778 repo->CreateDataPoint("/topdir/subdir1/datapoint2"_dppath, 0);
1779 repo->CreateDataPoint("/topdir/subdir1/datapoint3"_dppath, 0);
1780 repo->CreateDataPoint("/topdir/subdir2/datapoint4"_dppath, 0);
1781 repo->CreateDataPoint("/topdir/subdir21/datapoint5"_dppath, 0);
1782 }
1783
1784 void TearDown() override {
1785 if (repo->DataPointExists("/topdir/datapoint1"_dppath)) {
1786 repo->DeleteDataPoint("/topdir/datapoint1"_dppath);
1787 }
1788 if (repo->DataPointExists("/topdir/subdir1/datapoint2"_dppath)) {
1789 repo->DeleteDataPoint("/topdir/subdir1/datapoint2"_dppath);
1790 }
1791 if (repo->DataPointExists("/topdir/subdir1/datapoint2"_dppath)) {
1792 repo->DeleteDataPoint("/topdir/subdir1/datapoint2"_dppath);
1793 }
1794 if (repo->DataPointExists("/topdir/subdir1/datapoint3"_dppath)) {
1795 repo->DeleteDataPoint("/topdir/subdir1/datapoint3"_dppath);
1796 }
1797 if (repo->DataPointExists("/topdir/subdir2/datapoint4"_dppath)) {
1798 repo->DeleteDataPoint("/topdir/subdir2/datapoint4"_dppath);
1799 }
1800 if (repo->DataPointExists("/topdir/subdir21/datapoint5"_dppath)) {
1801 repo->DeleteDataPoint("/topdir/subdir21/datapoint5"_dppath);
1802 }
1803 }
1804
1805protected:
1806 std::shared_ptr<RepositoryIf> repo;
1807};
1808
1810 auto [dps, paths] = repo->GetChildren("/"_dppath);
1811 ASSERT_TRUE(dps.empty());
1812 ASSERT_EQ(paths.size(), 1);
1813 ASSERT_EQ(paths[0], "/topdir"_dppath);
1814}
1815
1817 auto [dps, paths] = repo->GetChildren("/topdir"_dppath);
1818 ASSERT_EQ(paths.size(), RtcVectorString::size_type(3));
1819 std::sort(paths.begin(), paths.end());
1820 EXPECT_EQ(paths[0], "/topdir/subdir1"_dppath);
1821 EXPECT_EQ(paths[1], "/topdir/subdir2"_dppath);
1822 EXPECT_EQ(paths[2], "/topdir/subdir21"_dppath);
1823 ASSERT_EQ(dps.size(), RtcVectorString::size_type(1));
1824 EXPECT_EQ(dps[0], "/topdir/datapoint1"_dppath);
1825}
1826
1828 auto [dps, paths] = repo->GetChildren("/topdir/subdir1"_dppath);
1829 ASSERT_TRUE(paths.empty());
1830 ASSERT_EQ(dps.size(), RtcVectorString::size_type(2));
1831 std::sort(dps.begin(), dps.end());
1832 EXPECT_EQ(dps[0], "/topdir/subdir1/datapoint2"_dppath);
1833 EXPECT_EQ(dps[1], "/topdir/subdir1/datapoint3"_dppath);
1834}
1835
1837 auto [dps, paths] = repo->GetChildren("/topdir/subdir2"_dppath);
1838 ASSERT_TRUE(paths.empty());
1839 ASSERT_EQ(dps.size(), RtcVectorString::size_type(1));
1840 std::sort(dps.begin(), dps.end());
1841 EXPECT_EQ(dps[0], "/topdir/subdir2/datapoint4"_dppath);
1842}
1843
1845 auto [dps, paths] = repo->GetChildren("/topdir/datapoint1"_dppath);
1846 ASSERT_TRUE(paths.empty());
1847 ASSERT_TRUE(dps.empty());
1848}
1849
1851 auto [dps, paths] = repo->GetChildren("/does/not/exist"_dppath);
1852 ASSERT_TRUE(paths.empty());
1853 ASSERT_TRUE(dps.empty());
1854}
1855
1857 auto [dps, paths] = repo->GetChildren("/"_dppath, true);
1858
1859 std::sort(dps.begin(), dps.end());
1860 ASSERT_EQ(dps.size(), 5);
1861 EXPECT_EQ(dps[0], "/topdir/datapoint1"_dppath);
1862 EXPECT_EQ(dps[1], "/topdir/subdir1/datapoint2"_dppath);
1863 EXPECT_EQ(dps[2], "/topdir/subdir1/datapoint3"_dppath);
1864 EXPECT_EQ(dps[3], "/topdir/subdir2/datapoint4"_dppath);
1865 EXPECT_EQ(dps[4], "/topdir/subdir21/datapoint5"_dppath);
1866
1867 std::sort(paths.begin(), paths.end());
1868 ASSERT_EQ(paths.size(), 4);
1869 EXPECT_EQ(paths[0], "/topdir"_dppath);
1870 EXPECT_EQ(paths[1], "/topdir/subdir1"_dppath);
1871 EXPECT_EQ(paths[2], "/topdir/subdir2"_dppath);
1872 EXPECT_EQ(paths[3], "/topdir/subdir21"_dppath);
1873}
1874
1876 repo->DeleteDataPoint("/"_dppath, true);
1877
1878 auto [dps, paths] = repo->GetChildren("/"_dppath, true);
1879 EXPECT_EQ(dps.size(), 0);
1880 EXPECT_EQ(paths.size(), 0);
1881}
1882
1884 repo->DeleteDataPoint("/topdir"_dppath, true);
1885
1886 auto [dps, paths] = repo->GetChildren("/"_dppath, true);
1887 EXPECT_EQ(dps.size(), 0);
1888 EXPECT_EQ(paths.size(), 0);
1889}
1890
1892 repo->DeleteDataPoint("/topdir/subdir2"_dppath, true);
1893
1894 auto [dps, paths] = repo->GetChildren("/"_dppath, true);
1895
1896 std::sort(dps.begin(), dps.end());
1897 ASSERT_EQ(dps.size(), 4);
1898 EXPECT_EQ(dps[0], "/topdir/datapoint1"_dppath);
1899 EXPECT_EQ(dps[1], "/topdir/subdir1/datapoint2"_dppath);
1900 EXPECT_EQ(dps[2], "/topdir/subdir1/datapoint3"_dppath);
1901 EXPECT_EQ(dps[3], "/topdir/subdir21/datapoint5"_dppath);
1902
1903 std::sort(paths.begin(), paths.end());
1904 EXPECT_EQ(paths.size(), 3);
1905 EXPECT_EQ(paths[0], "/topdir"_dppath);
1906 EXPECT_EQ(paths[1], "/topdir/subdir1"_dppath);
1907 EXPECT_EQ(paths[2], "/topdir/subdir21"_dppath);
1908}
1909
1911
1912class Metadata : public testing::Test {
1913public:
1914 void SetUp() override {
1915 repo = MakeRepository();
1916 path = "/foo"_dppath;
1917 }
1918
1919 void TearDown() override {
1920 if (repo->DataPointExists(path)) {
1921 repo->DeleteDataPoint(path);
1922 }
1923 }
1924
1925protected:
1926 std::shared_ptr<RepositoryIf> repo;
1928};
1929
1932 int initial_value = 0;
1933
1935 md["timestamp"] = t_start;
1936 md["comment"] = std::string{"some comment"};
1937 md["units"] = std::string{"bar"};
1938
1941 req.CreateDataPoint(path, initial_value, md);
1942 req.ReadMetaData(path, md_read);
1943 repo->SendRequest(req).Wait();
1944
1945 ASSERT_TRUE(md_read.Contains("type"));
1946 ASSERT_TRUE(md_read.Contains("shape"));
1947 ASSERT_TRUE(md_read.Contains("timestamp"));
1948 ASSERT_TRUE(md_read.Contains("comment"));
1949 ASSERT_TRUE(md_read.Contains("units"));
1950
1951 EXPECT_TRUE(md_read["type"].Cast<const std::type_info&>() == typeid(int));
1954 EXPECT_EQ(md_read["comment"].Cast<std::string>(), std::string{"some comment"});
1955 EXPECT_EQ(md_read["units"].Cast<std::string>(), std::string{"bar"});
1956}
1957
1960 int initial_value = 0;
1961
1963 md["timestamp"] = t_start;
1964 md["comment"] = std::string{"some comment"};
1965 md["units"] = std::string{"bar"};
1966
1969 req.CreateDataPoint(path, initial_value);
1970 req.WriteDataPoint(path, initial_value, md);
1971 req.ReadMetaData(path, md_read);
1972 repo->SendRequest(req).Wait();
1973
1974 ASSERT_TRUE(md_read.Contains("timestamp"));
1975 ASSERT_TRUE(md_read.Contains("comment"));
1976 ASSERT_TRUE(md_read.Contains("units"));
1977
1979 EXPECT_EQ(md_read["comment"].Cast<std::string>(), std::string{"some comment"});
1980 EXPECT_EQ(md_read["units"].Cast<std::string>(), std::string{"bar"});
1981}
1982
1985 int initial_value = 0;
1986 int read_value = 1;
1987
1989 md["timestamp"] = t_start;
1990 md["comment"] = std::string{"some comment"};
1991 md["units"] = std::string{"bar"};
1992
1995 req.CreateDataPoint(path, initial_value, md);
1996 req.ReadDataPoint(path, read_value, md_read);
1997 repo->SendRequest(req).Wait();
1998
1999 ASSERT_TRUE(md_read.Contains("type"));
2000 ASSERT_TRUE(md_read.Contains("shape"));
2001 ASSERT_TRUE(md_read.Contains("timestamp"));
2002 ASSERT_TRUE(md_read.Contains("comment"));
2003 ASSERT_TRUE(md_read.Contains("units"));
2004
2006 EXPECT_EQ(md_read["comment"].Cast<std::string>(), std::string{"some comment"});
2007 EXPECT_EQ(md_read["units"].Cast<std::string>(), std::string{"bar"});
2008 EXPECT_TRUE(md_read["type"].Cast<const std::type_info&>() == typeid(int));
2010}
2011
2013 int initial_value = 0;
2014
2016 md["comment"] = std::string{"some comment"};
2017 md["units"] = std::string{"bar"};
2018
2021 req.CreateDataPoint(path, initial_value);
2022 req.WriteMetaData(path, md);
2023 req.ReadMetaData(path, md_read);
2024 repo->SendRequest(req).Wait();
2025
2026 ASSERT_TRUE(md_read.Contains("comment"));
2027 ASSERT_TRUE(md_read.Contains("units"));
2028
2029 EXPECT_EQ(md_read["comment"].Cast<std::string>(), std::string{"some comment"});
2030 EXPECT_EQ(md_read["units"].Cast<std::string>(), std::string{"bar"});
2031}
2032
2034 {
2037
2038 int initial_value = 0;
2040 req.CreateDataPoint(path, initial_value);
2041 req.ReadMetaData(path, metadata_read);
2042 repo->SendRequest(req).Wait();
2043
2044 ASSERT_TRUE(metadata_read.Contains("timestamp"));
2046 }
2047
2048 {
2051
2052 int new_value = 4;
2054 req.WriteDataPoint(path, new_value);
2055 req.ReadMetaData(path, metadata_read);
2056 repo->SendRequest(req).Wait();
2057
2058 ASSERT_TRUE(metadata_read.Contains("timestamp"));
2060 }
2061}
2062
2064 {
2066
2067 int initial_value = 0;
2069 req.CreateDataPoint(path, initial_value);
2070 req.ReadMetaData(path, metadata_read);
2071 repo->SendRequest(req).Wait();
2072
2073 ASSERT_TRUE(metadata_read.Contains("sequence_id"));
2074 EXPECT_EQ(metadata_read["sequence_id"].Cast<RtcUInt64>(), 0);
2075 }
2076
2077 {
2079
2080 int new_value = 4;
2082 req.WriteDataPoint(path, new_value);
2083 req.ReadMetaData(path, metadata_read);
2084 repo->SendRequest(req).Wait();
2085
2086 ASSERT_TRUE(metadata_read.Contains("sequence_id"));
2087 EXPECT_EQ(metadata_read["sequence_id"].Cast<RtcUInt64>(), 1);
2088 }
2089}
2090
2092 // First setup the datapoint and write to it two times, making sure the resultant sequence ID
2093 // is 2. Then make sure we can successfully read the datapoint and get the correct value.
2094 {
2095 int int_create = 3;
2096 int int_write1 = 4;
2097 int int_write2 = 5;
2098 RepositoryIf::MetaData metadata;
2099
2101 req.CreateDataPoint("/foo"_dppath, int_create);
2102 req.WriteDataPoint("/foo"_dppath, int_write1);
2103 req.WriteDataPoint("/foo"_dppath, int_write2);
2104 req.ReadMetaData("/foo"_dppath, metadata);
2105 repo->SendRequest(req).Wait();
2106
2107 ASSERT_EQ(metadata["sequence_id"].Cast<RtcUInt64>(), 2);
2108 }
2109
2110 {
2111 int int_read;
2112 RepositoryIf::MetaData metadata = {{"sequence_id", static_cast<RtcUInt64>(2)}};
2114 req.ReadDataPoint("/foo"_dppath, int_read, metadata);
2115 repo->SendRequest(req).Wait();
2116 EXPECT_EQ(int_read, 5);
2117 }
2118}
2119
2121 // First setup the datapoint and write to it two times, making sure the resultant sequence ID
2122 // is 2. Then make check that an exception is thrown if a ReadDataPoint request is made with
2123 // a different sequence ID.
2124 {
2125 int int_create = 3;
2126 int int_write1 = 4;
2127 int int_write2 = 5;
2128 RepositoryIf::MetaData metadata;
2129
2131 req.CreateDataPoint("/foo"_dppath, int_create);
2132 req.WriteDataPoint("/foo"_dppath, int_write1);
2133 req.WriteDataPoint("/foo"_dppath, int_write2);
2134 req.ReadMetaData("/foo"_dppath, metadata);
2135 repo->SendRequest(req).Wait();
2136
2137 ASSERT_EQ(metadata["sequence_id"].Cast<RtcUInt64>(), 2);
2138 }
2139
2140 {
2141 int int_read;
2142 RepositoryIf::MetaData metadata = {{"sequence_id", static_cast<RtcUInt64>(342)}};
2144 req.ReadDataPoint("/foo"_dppath, int_read, metadata);
2145 EXPECT_THROW({ repo->SendRequest(req).Wait(); }, RtctkException);
2146 }
2147}
2148
2150 {
2151 int int_create = 0;
2152 RepositoryIf::MetaData metadata;
2153 metadata["min"] = static_cast<int>(-3);
2154 metadata["max"] = static_cast<int>(3);
2155 metadata["text"] = std::string{"This is a custom text description."};
2158 req.CreateDataPoint(path, int_create, metadata);
2159 req.ReadMetaData(path, metadata_read);
2160 repo->SendRequest(req).Wait();
2161 ASSERT_TRUE(metadata_read.Contains("min"));
2162 ASSERT_TRUE(metadata_read.Contains("max"));
2163 EXPECT_EQ(metadata_read["min"].Cast<int>(), -3);
2164 EXPECT_EQ(metadata_read["max"].Cast<int>(), 3);
2165 EXPECT_EQ(metadata_read["text"].Cast<std::string>(), metadata["text"].Cast<std::string>());
2166 }
2167
2168 {
2169 RepositoryIf::MetaData metadata;
2170 metadata["min"] = static_cast<int>(-5);
2171 metadata["max"] = static_cast<int>(5);
2172 metadata["text"] = std::string{"This is another description."};
2175 req.WriteMetaData(path, metadata);
2176 req.ReadMetaData(path, metadata_read);
2177 repo->SendRequest(req).Wait();
2178 ASSERT_TRUE(metadata_read.Contains("min"));
2179 ASSERT_TRUE(metadata_read.Contains("max"));
2180 EXPECT_EQ(metadata_read["min"].Cast<int>(), -5);
2181 EXPECT_EQ(metadata_read["max"].Cast<int>(), 5);
2182 EXPECT_EQ(metadata_read["text"].Cast<std::string>(), metadata["text"].Cast<std::string>());
2183 }
2184
2185 {
2186 int int_write = 3;
2187 RepositoryIf::MetaData metadata;
2188 metadata["min"] = static_cast<int>(-7);
2189 metadata["max"] = static_cast<int>(7);
2190 metadata["text"] = std::string{"This is a description."};
2193 req.WriteDataPoint(path, int_write, metadata);
2194 req.ReadMetaData(path, metadata_read);
2195 repo->SendRequest(req).Wait();
2196 ASSERT_TRUE(metadata_read.Contains("min"));
2197 ASSERT_TRUE(metadata_read.Contains("max"));
2198 EXPECT_EQ(metadata_read["min"].Cast<int>(), -7);
2199 EXPECT_EQ(metadata_read["max"].Cast<int>(), 7);
2200 EXPECT_EQ(metadata_read["text"].Cast<std::string>(), metadata["text"].Cast<std::string>());
2201 }
2202
2203 {
2204 int int_write = 3;
2205 int int_read = 0;
2206 RepositoryIf::MetaData metadata;
2207 metadata["min"] = static_cast<int>(-9);
2208 metadata["max"] = static_cast<int>(9);
2209 metadata["text"] = std::string{"A description.\nBut on two lines."};
2212 req.WriteDataPoint(path, int_write, metadata);
2214 repo->SendRequest(req).Wait();
2215 ASSERT_TRUE(metadata_read.Contains("min"));
2216 ASSERT_TRUE(metadata_read.Contains("max"));
2217 EXPECT_EQ(metadata_read["min"].Cast<int>(), -9);
2218 EXPECT_EQ(metadata_read["max"].Cast<int>(), 9);
2219 EXPECT_EQ(metadata_read["text"].Cast<std::string>(), metadata["text"].Cast<std::string>());
2220 }
2221}
2222
2224
2225class Symlinks : public testing::Test {
2226public:
2227 void SetUp() override {
2228 repo = MakeRepository();
2229 path = "/foo"_dppath;
2230 }
2231
2232 void TearDown() override {
2233 if (repo->DataPointExists(path)) {
2234 repo->DeleteDataPoint(path);
2235 }
2236 if (repo->DataPointExists("/links/foo"_dppath)) {
2237 repo->DeleteDataPoint("/links/foo"_dppath);
2238 }
2239 if (repo->DataPointExists("/links/bar"_dppath)) {
2240 repo->DeleteDataPoint("/links/bar"_dppath);
2241 }
2242 }
2243
2244protected:
2245 std::shared_ptr<RepositoryIf> repo;
2247};
2248
2250 int int_create = 0;
2251 int int_read = 0;
2252 int int_read_2 = 0;
2253 int int_write = 4;
2254 bool foo_exists = false;
2255 bool bar_exists = false;
2256 bool foo_exists_later = false;
2257 bool bar_exists_later = false;
2258
2259 repo->CreateDataPoint(path, int_create);
2260
2262 req.CreateSymlink(path, "/links/foo1"_dppath);
2263 req.CreateSymlink(path, "/links/bar"_dppath);
2264 req.DataPointExists("/links/foo1"_dppath, foo_exists);
2265 req.DataPointExists("/links/bar"_dppath, bar_exists);
2266 req.ReadDataPoint("/links/foo1"_dppath, int_read);
2267 req.WriteDataPoint("/links/bar"_dppath, int_write);
2268 req.ReadDataPoint("/links/foo1"_dppath, int_read_2);
2269 req.DeleteDataPoint("/links/foo1"_dppath);
2270 req.DeleteDataPoint("/links/bar"_dppath);
2271 req.DataPointExists("/links/foo1"_dppath, foo_exists_later);
2272 req.DataPointExists("/links/bar"_dppath, bar_exists_later);
2273 repo->SendRequest(req).Wait();
2274
2277 EXPECT_EQ(int_read, 0);
2281}
2282
2284 int int_create = 0;
2285 int int_read = 0;
2286 int int_read_2 = 0;
2287 int int_write = 4;
2291 bool exists = 0;
2292 std::set<DataPointPath> links_2;
2293
2295 repo->CreateDataPoint(path, int_create);
2296 req.CreateSymlink(path, "/links/foo"_dppath);
2297 req.CreateSymlink(path, "/links/bar"_dppath);
2298 req.ReadMetaData(path, md_dp);
2299 req.ReadMetaData("/links/foo"_dppath, md_link);
2300 req.ReadDataPoint("/links/foo"_dppath, int_read);
2301 req.WriteDataPoint("/links/bar"_dppath, int_write);
2302 req.ReadDataPoint("/links/foo"_dppath, int_read_2);
2303 req.DeleteDataPoint("/links/foo"_dppath);
2304 req.DeleteDataPoint("/links/bar"_dppath);
2305 req.ReadMetaData(path, md_dp_later);
2306 req.DataPointExists(path, exists);
2307 repo->SendRequest(req).Wait();
2308
2309 EXPECT_FALSE(md_dp.Contains("symlink_target"));
2310 EXPECT_TRUE(md_link.Contains("symlink_target"));
2311 EXPECT_EQ(md_link["symlink_target"].Cast<DataPointPath>(), DataPointPath{"/foo"});
2312
2313 ASSERT_TRUE(md_dp.Contains("symlinks")); // symlinks-key present if datapoint has symlinks
2314 EXPECT_EQ(md_dp["symlinks"].Cast<std::set<DataPointPath>>(),
2315 std::set<DataPointPath>({"/links/foo"_dppath, "/links/bar"_dppath}));
2316 EXPECT_FALSE(md_link.Contains("symlinks")); // symlinks-key not present for symlinks
2317
2318 EXPECT_EQ(int_read, 0);
2320 EXPECT_FALSE(md_dp_later.Contains("symlinks")); // symlinks-key no longer there
2322}
2323
2325 DataPointPath link_path = "/links/foo"_dppath;
2326 int int_create = 0;
2327 bool link_exists_1 = false;
2328 bool link_exists_2 = true;
2329
2331 req.CreateDataPoint(path, int_create);
2332 req.CreateSymlink(path, link_path);
2333 req.DataPointExists(link_path, link_exists_1);
2334 req.DeleteDataPoint(link_path);
2335 req.DataPointExists(link_path, link_exists_2);
2336 repo->SendRequest(req).Wait();
2337
2340}
2341
2343 DataPointPath link_path = "/links/foo"_dppath;
2344 int int_create = 0;
2345 int int_read = 1;
2346 bool link_exists = false;
2348
2350 req.CreateDataPoint(path, int_create);
2351 req.CreateSymlink(path, link_path);
2352 req.DeleteDataPoint(path);
2353 req.DataPointExists(link_path, link_exists);
2354 repo->SendRequest(req).Wait();
2355
2356 // the link still exists
2358
2359 // but we are unable to access the underlying datapoint
2361 { repo->ReadDataPoint(link_path, int_read); }, RepositoryIf::DataPointDoesNotExist);
2362}
2363
2365
2366class ExceptionInterface : public testing::Test {
2367public:
2368 void SetUp() override {
2369 repo = MakeRepository();
2370 path = "/foo"_dppath;
2371 link_path = "/links/foo"_dppath;
2372 link_path2 = "/links/bar"_dppath;
2373 }
2374
2375 void TearDown() override {
2376 if (repo->DataPointExists(link_path)) {
2377 repo->DeleteDataPoint(link_path);
2378 }
2379 if (repo->DataPointExists(link_path2)) {
2380 repo->DeleteDataPoint(link_path2);
2381 }
2382 if (repo->DataPointExists(path)) {
2383 repo->DeleteDataPoint(path);
2384 }
2385 }
2386
2387protected:
2388 std::shared_ptr<RepositoryIf> repo;
2392};
2393
2394// TODO: This test is no longer compilable. Decide what to do.
2395/*
2396TEST_F(ExceptionInterface, CreateDataPointThrowsForUnsupportedDataType) {
2397 struct UnsupportedDataType {};
2398 UnsupportedDataType value;
2399
2400 ASSERT_FALSE(repo->DataPointExists(path));
2401
2402 EXPECT_ANY_THROW({ repo->CreateDataPoint(path, value); });
2403}
2404*/
2405
2407 auto create_value = 42;
2408
2409 ASSERT_FALSE(repo->DataPointExists(path));
2410
2411 repo->CreateDataPoint(path, create_value);
2412 ASSERT_TRUE(repo->DataPointExists(path));
2413
2415 { repo->CreateDataPoint(path, create_value); }, RepositoryIf::DataPointAlreadyExists);
2416}
2417
2419 ASSERT_FALSE(repo->DataPointExists(path));
2420
2421 EXPECT_THROW({ repo->DeleteDataPoint(path); }, RepositoryIf::DataPointDoesNotExist);
2422}
2423
2425 ASSERT_FALSE(repo->DataPointExists(path));
2426
2427 EXPECT_THROW({ repo->WriteDataPoint(path, 14); }, RepositoryIf::DataPointDoesNotExist);
2428}
2429
2431 RtcInt64 int_buffer = 14;
2432 repo->CreateDataPoint(path, int_buffer);
2433
2434 RtcFloat float_buffer = 14.0;
2435 EXPECT_THROW({ repo->WriteDataPoint(path, float_buffer); }, RepositoryIf::IncompatibleType);
2436}
2437
2439 RtcInt64 int_buffer = 14;
2440 repo->CreateDataPoint(path, int_buffer);
2441
2442 RtcVectorInt64 vec_buffer = {15, 16};
2443 EXPECT_THROW({ repo->WriteDataPoint(path, vec_buffer); }, RepositoryIf::IncompatibleType);
2444
2445 RtcMatrixInt64 mat_buffer = {2, 2, {1, 2, 3, 4}};
2446 EXPECT_THROW({ repo->WriteDataPoint(path, mat_buffer); }, RepositoryIf::IncompatibleType);
2447}
2448
2457
2459 RtcInt64 int_buffer = 14;
2460 repo->CreateDataPoint(path, int_buffer);
2461
2463 EXPECT_THROW({ repo->ReadDataPoint(path, vec_buffer); }, RepositoryIf::IncompatibleType);
2464
2466 EXPECT_THROW({ repo->ReadDataPoint(path, mat_buffer); }, RepositoryIf::IncompatibleType);
2467}
2468
2471 repo->CreateDataPoint(path, write_buffer);
2472
2473 gsl::span<RtcInt64> read_buffer(write_buffer);
2474 auto too_small_read_buffer = read_buffer.subspan(0, 5);
2476 { repo->ReadDataPoint(path, too_small_read_buffer); }, RepositoryIf::BufferTooSmall);
2477}
2478
2481 repo->CreateDataPoint(path, write_buffer);
2482
2483 RtcVectorInt64 vec_buffer = {1, 2, 3, 4};
2485 req.PartialWriteDataPoint(path, vec_buffer, 0, 4, 8);
2486 EXPECT_THROW({ repo->SendRequest(req).Wait(); }, RepositoryIf::AccessOutOfBounds);
2487}
2488
2492 repo->CreateDataPoint(path, write_buffer);
2493
2495 req.PartialReadDataPoint(path, read_buffer, 0, 15, 0);
2496 EXPECT_THROW({ repo->SendRequest(req).Wait(); }, RepositoryIf::AccessOutOfBounds);
2497}
2498
2502
2506
2510
2514
2518
2520 ASSERT_FALSE(repo->DataPointExists(path));
2521
2522 RepositoryIf::MetaData metadata;
2524 req.WriteMetaData(path, metadata);
2525 EXPECT_THROW({ repo->SendRequest(req).Wait(); }, RepositoryIf::DataPointDoesNotExist);
2526}
2527
2529 ASSERT_FALSE(repo->DataPointExists(path));
2530
2531 struct UnsupportedMetaDataType {};
2532
2534 {
2536 RepositoryIf::MetaData metadata;
2537 metadata["min"] = std::make_any<UnsupportedMetaDataType>(new_value);
2538 int initial_value = 12;
2540 req.CreateDataPoint(path, initial_value, metadata);
2541 repo->SendRequest(req).Wait();
2542 },
2544}
2545
2547 ASSERT_FALSE(repo->DataPointExists(path));
2548
2549 repo->CreateDataPoint(path, 12);
2550
2551 struct UnsupportedMetaDataType {};
2552
2554 {
2556 RepositoryIf::MetaData metadata;
2557 metadata["min"] = std::make_any<UnsupportedMetaDataType>(new_value);
2559 req.WriteMetaData(path, metadata);
2560 repo->SendRequest(req).Wait();
2561 },
2563}
2564
2566 ASSERT_FALSE(repo->DataPointExists(path));
2567
2568 RepositoryIf::MetaData metadata;
2570 req.ReadMetaData(path, metadata);
2571 EXPECT_THROW({ repo->SendRequest(req).Wait(); }, RepositoryIf::DataPointDoesNotExist);
2572}
2573
2575 ASSERT_FALSE(repo->DataPointExists(path));
2576
2578 req.CreateSymlink(path, link_path);
2579 EXPECT_THROW({ repo->SendRequest(req).Wait(); }, RepositoryIf::DataPointDoesNotExist);
2580}
2581
2582// TODO we did not conclude our discussion regarding links to links, for now they are disallowed
2584 ASSERT_FALSE(repo->DataPointExists(path));
2585 repo->CreateDataPoint(path, 42);
2586
2587 {
2589 req.CreateSymlink(path, link_path);
2590 repo->SendRequest(req).Wait();
2591 }
2592
2594 req.CreateSymlink(link_path, link_path2);
2595 EXPECT_THROW({ repo->SendRequest(req).Wait(); }, RepositoryIf::OperationNotAllowed);
2596}
2597
2599 ASSERT_FALSE(repo->DataPointExists(path));
2600 repo->CreateDataPoint(path, 42);
2601
2603 req.UpdateSymlink(path, link_path);
2604 EXPECT_THROW({ repo->SendRequest(req).Wait(); }, RepositoryIf::DataPointDoesNotExist);
2605}
2606
2608 ASSERT_FALSE(repo->DataPointExists(path));
2609 repo->CreateDataPoint(path, 42);
2610
2611 {
2613 req.CreateSymlink(path, link_path);
2614 repo->SendRequest(req).Wait();
2615 }
2616
2617 {
2619 req.UpdateSymlink("/bar"_dppath, link_path);
2620 EXPECT_THROW({ repo->SendRequest(req).Wait(); }, RepositoryIf::DataPointDoesNotExist);
2621 }
2622}
2623
2625 ASSERT_FALSE(repo->DataPointExists(path));
2626 repo->CreateDataPoint(path, 42);
2627
2628 {
2630 req.CreateSymlink(path, link_path);
2631 req.CreateSymlink(path, link_path2);
2632 repo->SendRequest(req).Wait();
2633 }
2634
2635 {
2637 req.UpdateSymlink(link_path2, link_path);
2638 EXPECT_THROW({ repo->SendRequest(req).Wait(); }, RepositoryIf::OperationNotAllowed);
2639 }
2640}
2641
2643 {
2644 int initial_value = 0;
2646 req.CreateDataPoint(path, initial_value);
2647 req.CreateSymlink(path, link_path);
2648 req.DeleteDataPoint(path);
2649 repo->SendRequest(req).Wait();
2650 }
2651
2652 {
2653 int write_value = 0;
2655 req.WriteDataPoint(link_path, write_value);
2656 EXPECT_THROW({ repo->SendRequest(req).Wait(); }, RepositoryIf::DataPointDoesNotExist);
2657 }
2658}
2659
2661 int buffer = 0;
2662
2663 {
2665 req.CreateDataPoint(path, buffer);
2666 req.CreateSymlink(path, link_path);
2667 req.DeleteDataPoint(path);
2668 repo->SendRequest(req).Wait();
2669 }
2670
2671 {
2673 req.ReadDataPoint(link_path, buffer);
2674 EXPECT_THROW({ repo->SendRequest(req).Wait(); }, RepositoryIf::DataPointDoesNotExist);
2675 }
2676}
2677
2679 bool exists = false;
2680 RtcInt64 value = 42;
2681
2683 req.DataPointExists(path, exists);
2684 req.WriteDataPoint(path, value);
2685 req.ReadDataPoint(path, value);
2686 req.DataPointExists(path, exists);
2687 try {
2688 repo->SendRequest(req).Wait();
2689 FAIL() << "Call did not throw";
2690 } catch (const RepositoryIf::MultipleRequestsFailed& ex) {
2691 auto info = ex.GetInfo();
2692 ASSERT_EQ(info.size(), 4);
2693
2698
2699 EXPECT_EQ(info[0].exception, nullptr);
2700 ASSERT_NE(info[1].exception, nullptr);
2701 ASSERT_NE(info[2].exception, nullptr);
2702 EXPECT_EQ(info[3].exception, nullptr);
2703
2704 EXPECT_THROW(std::rethrow_exception(info[1].exception),
2706 EXPECT_THROW(std::rethrow_exception(info[2].exception),
2708
2709 // std::cout << ex.what(); // just to show that what() is available as wel
2710
2711 } catch (...) {
2712 FAIL() << "Incorrect exception type";
2713 }
2714}
2715
2717
2718class MassiveParallelAccess : public testing::Test {
2719public:
2720 void SetUp() override {
2721 repo = MakeRepository();
2722 for (unsigned i = 0; i < 500; i++) {
2723 std::string name = fmt::format("/test/datapoint_{:0>2}", i);
2724 dp_paths.push_back(DataPointPath(name));
2725 }
2726 }
2727
2728 void TearDown() override {
2729 for (const auto& path : dp_paths) {
2730 if (repo->DataPointExists(path)) {
2731 repo->DeleteDataPoint(path);
2732 }
2733 }
2734 }
2735
2736protected:
2737 std::shared_ptr<RepositoryIf> repo;
2738 std::vector<DataPointPath> dp_paths;
2739};
2740
2742 // parallel creation
2743 {
2744 std::vector<std::future<void>> futures;
2745
2746 for (unsigned i = 0; i < dp_paths.size(); i++) {
2747 futures.push_back(std::async(std::launch::async, [this, idx = i] {
2748 repo->CreateDataPoint(dp_paths[idx], idx);
2749 }));
2750 }
2751
2752 for (auto& f : futures) {
2753 ASSERT_NO_THROW({ f.get(); });
2754 }
2755 }
2756
2757 // parallel exists
2758 {
2759 std::vector<std::future<bool>> futures;
2760
2761 for (unsigned i = 0; i < dp_paths.size(); i++) {
2762 futures.push_back(std::async(std::launch::async, [this, idx = i] {
2763 return repo->DataPointExists(dp_paths[idx]);
2764 }));
2765 }
2766
2767 for (auto& f : futures) {
2768 bool result = false;
2769 ASSERT_NO_THROW({ result = f.get(); });
2770 ASSERT_TRUE(result);
2771 }
2772 }
2773
2774 // parallel set
2775 {
2776 std::vector<std::future<void>> futures;
2777
2778 for (unsigned i = 0; i < dp_paths.size(); i++) {
2779 futures.push_back(std::async(std::launch::async, [this, idx = i] {
2780 repo->SetDataPoint<unsigned>(dp_paths[idx], idx + 1);
2781 }));
2782 }
2783
2784 for (auto& f : futures) {
2785 ASSERT_NO_THROW({ f.get(); });
2786 }
2787 }
2788
2789 // parallel get
2790 {
2791 std::vector<std::future<unsigned>> futures;
2792
2793 for (unsigned i = 0; i < dp_paths.size(); i++) {
2794 futures.push_back(std::async(std::launch::async, [this, idx = i] {
2795 return repo->GetDataPoint<unsigned>(dp_paths[idx]);
2796 }));
2797 }
2798
2799 for (unsigned i = 0; i < dp_paths.size(); i++) {
2800 unsigned result = 0;
2801 ASSERT_NO_THROW({ result = futures.at(i).get(); });
2802 EXPECT_EQ(result, i + 1);
2803 }
2804 }
2805
2806 // parallel deletion
2807 {
2808 std::vector<std::future<void>> futures;
2809
2810 for (unsigned i = 0; i < dp_paths.size(); i++) {
2811 futures.push_back(std::async(
2812 std::launch::async, [this, idx = i] { repo->DeleteDataPoint(dp_paths[idx]); }));
2813 }
2814
2815 for (auto& f : futures) {
2816 ASSERT_NO_THROW({ f.get(); });
2817 }
2818 }
2819
2820 // parallel exists
2821 {
2822 std::vector<std::future<bool>> futures;
2823
2824 for (unsigned i = 0; i < dp_paths.size(); i++) {
2825 futures.push_back(std::async(std::launch::async, [this, idx = i] {
2826 return repo->DataPointExists(dp_paths[idx]);
2827 }));
2828 }
2829
2830 for (auto& f : futures) {
2831 bool result = true;
2832 ASSERT_NO_THROW({ result = f.get(); });
2833 ASSERT_FALSE(result);
2834 }
2835 }
2836}
2837
2839 auto path = dp_paths[0];
2840 unsigned create_value = 42;
2841 repo->CreateDataPoint(path, create_value);
2842
2843 {
2844 std::vector<std::future<unsigned>> futures;
2845
2846 for (unsigned i = 0; i < 500; i++) {
2847 futures.push_back(
2848 std::async(std::launch::async, [&] { return repo->GetDataPoint<unsigned>(path); }));
2849 }
2850
2851 for (auto& f : futures) {
2852 auto result = 0;
2853 ASSERT_NO_THROW({ result = f.get(); });
2854 EXPECT_EQ(result, create_value);
2855 }
2856 }
2857}
2858
2860 auto path = dp_paths[0];
2861 unsigned create_value = 42;
2862 repo->CreateDataPoint(path, create_value);
2863
2864 {
2865 std::vector<std::future<void>> futures;
2866
2867 for (unsigned i = 0; i < 500; i++) {
2868 futures.push_back(
2869 std::async(std::launch::async, [&] { repo->SetDataPoint<unsigned>(path, 43); }));
2870 }
2871
2872 for (auto& f : futures) {
2873 ASSERT_NO_THROW({ f.get(); });
2874 }
2875 }
2876
2877 unsigned result;
2880 req.ReadDataPoint(path, result, md);
2881 repo->SendRequest(req).Wait();
2882
2883 EXPECT_EQ(result, 43);
2884 EXPECT_EQ(md["sequence_id"].Cast<RtcUInt64>(), 500);
2885}
2886
2888 auto path = dp_paths[0];
2889 unsigned create_value = 42;
2890 repo->CreateDataPoint(path, create_value);
2891
2892 {
2893 std::vector<std::future<void>> futures;
2894
2895 for (unsigned i = 0; i < 50; i++) {
2896 futures.push_back(std::async(std::launch::async, [&] {
2897 unsigned buffer = 43;
2899 for (unsigned j = 0; j < 10; j++) {
2900 req.WriteDataPoint(path, buffer);
2901 }
2902 repo->SendRequest(req).Wait();
2903 }));
2904 }
2905
2906 for (auto& f : futures) {
2907 ASSERT_NO_THROW({ f.get(); });
2908 }
2909 }
2910
2911 unsigned result;
2914 req.ReadDataPoint(path, result, md);
2915 repo->SendRequest(req).Wait();
2916
2917 EXPECT_EQ(result, 43);
2918 EXPECT_EQ(md["sequence_id"].Cast<RtcUInt64>(), 500);
2919}
2920
2922 auto path = dp_paths[0];
2923 unsigned create_value = 42;
2924 repo->CreateDataPoint(path, create_value);
2925
2926 {
2927 std::vector<std::future<unsigned>> futures;
2928
2929 for (unsigned i = 0; i < 50; i++) {
2930 futures.push_back(std::async(std::launch::async, [&] {
2931 unsigned buffer = 0;
2933 req.ReadDataPoint(path, buffer);
2934 req.ReadDataPoint(path, buffer);
2935 req.ReadDataPoint(path, buffer);
2936 req.ReadDataPoint(path, buffer);
2937 req.ReadDataPoint(path, buffer);
2938 req.ReadDataPoint(path, buffer);
2939 req.ReadDataPoint(path, buffer);
2940 req.ReadDataPoint(path, buffer);
2941 req.ReadDataPoint(path, buffer);
2942 req.ReadDataPoint(path, buffer);
2943 repo->SendRequest(req).Wait();
2944 return buffer;
2945 }));
2946 }
2947
2948 for (auto& f : futures) {
2949 unsigned result = 0;
2950 ASSERT_NO_THROW({ result = f.get(); });
2951 EXPECT_EQ(result, 42);
2952 }
2953 }
2954}
2955
2956} // namespace rtctk::componentFramework::test
2957
2958#pragma GCC diagnostic pop
2959
2960#endif // RTCTK_COMPONENTFRAMEWORK_TEST_REPOSITORYIFTESTSUITE_HPP
This class provides a wrapper for a data point path.
Definition dataPointPath.hpp:74
A buffer class representing 2D matrix data.
Definition matrixBuffer.hpp:28
A span referencing a 2D matrix buffer.
Definition matrixSpan.hpp:35
An object representing one or more asynchronous I/O requests to a repository.
Definition repositoryIf.hpp:683
void DataPointExists(const DataPointPath &path, bool &result, const CallbackType &callback=nullptr) const
Definition repositoryIf.cpp:300
void DeleteDataPoint(const DataPointPath &path, const CallbackType &callback=nullptr)
Definition repositoryIf.cpp:295
void ReadDataPoint(const DataPointPath &path, T &buffer, std::optional< std::reference_wrapper< MetaData > > metadata=std::nullopt, const CallbackType &callback=nullptr) const
Definition repositoryIf.ipp:1395
void GetChildren(const DataPointPath &path, std::pair< PathList, PathList > &result, bool recurse=false, const CallbackType &callback=nullptr) const
Add request to query the child datapoints and paths for a given parent path.
void PartialWriteDataPoint(const DataPointPath &path, const T &buffer, size_t first, size_t last, size_t d_first, std::optional< std::reference_wrapper< const MetaData > > metadata=std::nullopt, const CallbackType &callback=nullptr)
Definition repositoryIf.ipp:1597
void PartialReadDataPoint(const DataPointPath &path, T &buffer, size_t first, size_t last, size_t d_first, std::optional< std::reference_wrapper< MetaData > > metadata=std::nullopt, const CallbackType &callback=nullptr) const
Add request to partially read a datapoint.
Definition repositoryIf.ipp:1526
void ReadMetaData(const DataPointPath &path, MetaData &metadata, const CallbackType &callback=nullptr) const
Definition repositoryIf.cpp:314
void CreateSymlink(const DataPointPath &dp, const DataPointPath &link, const CallbackType &callback=nullptr)
Definition repositoryIf.cpp:326
void CreateDataPoint(const DataPointPath &path, const T &initial_value, std::optional< std::reference_wrapper< const MetaData > > metadata=std::nullopt, const CallbackType &callback=nullptr)
Add a request to create a new datapoint.
Definition repositoryIf.ipp:1338
void WriteDataPoint(const DataPointPath &path, const T &buffer, std::optional< std::reference_wrapper< const MetaData > > metadata=std::nullopt, const CallbackType &callback=nullptr)
Definition repositoryIf.ipp:1471
void UpdateSymlink(const DataPointPath &dp, const DataPointPath &link, const CallbackType &callback=nullptr)
Definition repositoryIf.cpp:332
void WriteMetaData(const DataPointPath &path, const MetaData &metadata, const CallbackType &callback=nullptr)
Definition repositoryIf.cpp:320
Exception indicating that an unsupported type was used for the metadata value.
Definition repositoryIf.hpp:490
Class for passing/receiving metadata to/from the repository.
Definition repositoryIf.hpp:195
Abstract interface providing basic read and write facilities to a repository.
Definition repositoryIf.hpp:104
Clock::time_point Timestamp
Definition repositoryIf.hpp:111
T GetDataPoint(const DataPointPath &path) const
Fetches a datapoint from the repository.
Definition repositoryIf.ipp:1711
void CreateDataPoint(const DataPointPath &path)
Creates a new datapoint in the repository.
Definition repositoryIf.ipp:1696
void SetDataPoint(const DataPointPath &path, const T &value)
Sets a datapoint in the repository.
Definition repositoryIf.ipp:1720
std::vector< DataPointPath > PathList
Definition repositoryIf.hpp:109
The RtctkException class is the base class for all Rtctk exceptions.
Definition exceptions.hpp:211
Definition repositoryIfTestSuite.hpp:420
T MakeLargeTestValue()
Definition repositoryIfTestSuite.hpp:422
T MakeSmallTestValue()
Definition repositoryIfTestSuite.hpp:458
RtcVectorUInt64 ExpectedSmallTestValueShape()
Definition repositoryIfTestSuite.hpp:476
RtcVectorUInt64 ExpectedLargeTestValueShape()
Definition repositoryIfTestSuite.hpp:440
Definition repositoryIfTestSuite.hpp:1166
void TearDown() override
Definition repositoryIfTestSuite.hpp:1176
DataPointPath link1
Definition repositoryIfTestSuite.hpp:1203
DataPointPath path1
Definition repositoryIfTestSuite.hpp:1201
DataPointPath link2
Definition repositoryIfTestSuite.hpp:1204
void SetupDataPoints(const T &initial_value=0)
Definition repositoryIfTestSuite.hpp:1192
DataPointPath path2
Definition repositoryIfTestSuite.hpp:1202
std::shared_ptr< RepositoryIf > repo
Definition repositoryIfTestSuite.hpp:1200
void SetUp() override
Definition repositoryIfTestSuite.hpp:1168
Definition repositoryIfTestSuite.hpp:2366
std::shared_ptr< RepositoryIf > repo
Definition repositoryIfTestSuite.hpp:2388
void TearDown() override
Definition repositoryIfTestSuite.hpp:2375
DataPointPath link_path
Definition repositoryIfTestSuite.hpp:2390
void SetUp() override
Definition repositoryIfTestSuite.hpp:2368
DataPointPath link_path2
Definition repositoryIfTestSuite.hpp:2391
DataPointPath path
Definition repositoryIfTestSuite.hpp:2389
Definition repositoryIfTestSuite.hpp:1773
void TearDown() override
Definition repositoryIfTestSuite.hpp:1784
std::shared_ptr< RepositoryIf > repo
Definition repositoryIfTestSuite.hpp:1806
void SetUp() override
Definition repositoryIfTestSuite.hpp:1775
Definition repositoryIfTestSuite.hpp:2718
void TearDown() override
Definition repositoryIfTestSuite.hpp:2728
std::shared_ptr< RepositoryIf > repo
Definition repositoryIfTestSuite.hpp:2737
std::vector< DataPointPath > dp_paths
Definition repositoryIfTestSuite.hpp:2738
void SetUp() override
Definition repositoryIfTestSuite.hpp:2720
Definition repositoryIfTestSuite.hpp:1912
void TearDown() override
Definition repositoryIfTestSuite.hpp:1919
DataPointPath path
Definition repositoryIfTestSuite.hpp:1927
std::shared_ptr< RepositoryIf > repo
Definition repositoryIfTestSuite.hpp:1926
void SetUp() override
Definition repositoryIfTestSuite.hpp:1914
Definition repositoryIfTestSuite.hpp:1207
MOCK_METHOD(void, ReadMetaDataCallback,(const DataPointPath &path))
MOCK_METHOD(void, PartialReadCallback,(const DataPointPath &path))
MOCK_METHOD(void, DeleteCallback,(const DataPointPath &path))
MOCK_METHOD(void, ExistsCallback,(const DataPointPath &path))
MOCK_METHOD(void, CreateSymlinkCallback,(const DataPointPath &path))
MOCK_METHOD(void, CreateCallback,(const DataPointPath &path))
MOCK_METHOD(void, GetChildrenCallback,(const DataPointPath &path))
MOCK_METHOD(void, ReadCallback,(const DataPointPath &path))
MOCK_METHOD(void, WriteCallback,(const DataPointPath &path))
MOCK_METHOD(void, UpdateSymlinkCallback,(const DataPointPath &path))
MOCK_METHOD(void, PartialWriteCallback,(const DataPointPath &path))
MOCK_METHOD(void, WriteMetaDataCallback,(const DataPointPath &path))
Definition repositoryIfTestSuite.hpp:37
std::vector< DataPointPath > dp_paths
Definition repositoryIfTestSuite.hpp:124
T MakeSomeTestValue()
Definition repositoryIfTestSuite.hpp:57
void SetUp() override
Definition repositoryIfTestSuite.hpp:39
std::shared_ptr< RepositoryIf > repo
Definition repositoryIfTestSuite.hpp:125
size_t GetExpectedSize(const U &value)
Definition repositoryIfTestSuite.hpp:112
void TearDown() override
Definition repositoryIfTestSuite.hpp:48
T MakeOtherTestValue()
Definition repositoryIfTestSuite.hpp:83
Definition fakeClock.cpp:15
TYPED_TEST_SUITE(BasicOperation, TypeSetForBasicOperation)
::testing::Types< RtcBool, RtcInt8, RtcInt16, RtcInt32, RtcInt64, RtcUInt8, RtcUInt16, RtcUInt32, RtcUInt64, RtcFloat, RtcDouble, RtcString, RtcBinary, RtcVectorBool, RtcVectorInt8, RtcVectorInt16, RtcVectorInt32, RtcVectorInt64, RtcVectorUInt8, RtcVectorUInt16, RtcVectorUInt32, RtcVectorUInt64, RtcVectorFloat, RtcVectorDouble, RtcVectorString, RtcMatrixBool, RtcMatrixInt8, RtcMatrixInt16, RtcMatrixInt32, RtcMatrixInt64, RtcMatrixUInt8, RtcMatrixUInt16, RtcMatrixUInt32, RtcMatrixUInt64, RtcMatrixFloat, RtcMatrixDouble, RtcMatrixString > TypeSetForBasicOperation
Definition repositoryIfTestSuite.hpp:134
TYPED_TEST(BasicOperation, DataPointCreationAndDeletion)
Definition repositoryIfTestSuite.hpp:175
::testing::Types< RtcString, RtcBinary, RtcVectorBool, RtcVectorInt8, RtcVectorInt16, RtcVectorInt32, RtcVectorInt64, RtcVectorUInt8, RtcVectorUInt16, RtcVectorUInt32, RtcVectorUInt64, RtcVectorFloat, RtcVectorDouble, RtcVectorString, RtcMatrixBool, RtcMatrixInt8, RtcMatrixInt16, RtcMatrixInt32, RtcMatrixInt64, RtcMatrixUInt8, RtcMatrixUInt16, RtcMatrixUInt32, RtcMatrixUInt64, RtcMatrixFloat, RtcMatrixDouble, RtcMatrixString > TypeSetAdvancedOperation
Definition repositoryIfTestSuite.hpp:495
TEST_F(Callbacks, CreateDataPointCallback)
Definition repositoryIfTestSuite.hpp:1223
RepositoryIf::PathList PathList
Definition oldbAdapterLegacy.cpp:322
elt::mal::future< std::string > InjectReqRepEvent(StateMachineEngine &engine)
Definition malEventInjector.hpp:23
uint64_t RtcUInt64
Definition repositoryIf.hpp:61
RtcMatrix< RtcInt8 > RtcMatrixInt8
Definition repositoryIf.hpp:79
uint8_t RtcUInt8
Definition repositoryIf.hpp:58
int64_t RtcInt64
Definition repositoryIf.hpp:57
float RtcFloat
Definition repositoryIf.hpp:62
RtcMatrix< RtcInt32 > RtcMatrixInt32
Definition repositoryIf.hpp:81
RtcMatrix< RtcInt64 > RtcMatrixInt64
Definition repositoryIf.hpp:82
RtcMatrix< RtcUInt64 > RtcMatrixUInt64
Definition repositoryIf.hpp:86
RtcVector< RtcUInt32 > RtcVectorUInt32
Definition repositoryIf.hpp:73
RtcMatrix< RtcUInt8 > RtcMatrixUInt8
Definition repositoryIf.hpp:83
RtcMatrix< RtcFloat > RtcMatrixFloat
Definition repositoryIf.hpp:87
RtcVector< RtcDouble > RtcVectorDouble
Definition repositoryIf.hpp:76
std::string RtcString
Definition repositoryIf.hpp:64
RtcMatrix< RtcInt16 > RtcMatrixInt16
Definition repositoryIf.hpp:80
int8_t RtcInt8
Definition repositoryIf.hpp:54
uint32_t RtcUInt32
Definition repositoryIf.hpp:60
RtcMatrix< RtcDouble > RtcMatrixDouble
Definition repositoryIf.hpp:88
bool RtcBool
Definition repositoryIf.hpp:53
int16_t RtcInt16
Definition repositoryIf.hpp:55
RtcVector< RtcUInt16 > RtcVectorUInt16
Definition repositoryIf.hpp:72
RtcVector< RtcInt16 > RtcVectorInt16
Definition repositoryIf.hpp:68
RtcMatrix< RtcBool > RtcMatrixBool
Definition repositoryIf.hpp:78
RtcVector< RtcFloat > RtcVectorFloat
Definition repositoryIf.hpp:75
RtcVector< RtcInt8 > RtcVectorInt8
Definition repositoryIf.hpp:67
uint16_t RtcUInt16
Definition repositoryIf.hpp:59
RtcVector< RtcBool > RtcVectorBool
Definition repositoryIf.hpp:66
int32_t RtcInt32
Definition repositoryIf.hpp:56
RtcVector< RtcUInt64 > RtcVectorUInt64
Definition repositoryIf.hpp:74
RtcVector< RtcString > RtcVectorString
Definition repositoryIf.hpp:77
RtcVector< RtcInt32 > RtcVectorInt32
Definition repositoryIf.hpp:69
std::vector< std::byte > RtcBinary
Definition repositoryIf.hpp:65
RtcVector< RtcUInt8 > RtcVectorUInt8
Definition repositoryIf.hpp:71
RtcMatrix< RtcUInt16 > RtcMatrixUInt16
Definition repositoryIf.hpp:84
RtcVector< RtcInt64 > RtcVectorInt64
Definition repositoryIf.hpp:70
RtcMatrix< RtcUInt32 > RtcMatrixUInt32
Definition repositoryIf.hpp:85
double RtcDouble
Definition repositoryIf.hpp:63
Header file for RepositoryIf and related base classes.
boost::container::vector< bool, A > BufferType
Definition repositoryIfTestSuite.hpp:882
gsl::span< char > SpanType
Definition repositoryIfTestSuite.hpp:859
RtcString BufferType
Definition repositoryIfTestSuite.hpp:858
std::vector< T, A > BufferType
Definition repositoryIfTestSuite.hpp:870
gsl::span< T > SpanType
Definition repositoryIfTestSuite.hpp:871
boost::container::vector< bool, A > BufferType
Definition repositoryIfTestSuite.hpp:876
gsl::span< bool > SpanType
Definition repositoryIfTestSuite.hpp:877
Definition repositoryIfTestSuite.hpp:854
Provides useful mechanisms to test various type traits.