userver: /data/code/userver/libraries/proto-structs/tests/oneof_test.cpp Source File
Loading...
Searching...
No Matches
oneof_test.cpp
1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
3
4#include <chrono>
5#include <optional>
6#include <unordered_map>
7#include <vector>
8
9#include <userver/proto-structs/any.hpp>
10#include <userver/proto-structs/io/std/chrono/duration.hpp>
11#include <userver/proto-structs/io/userver/utils/box.hpp>
12#include <userver/proto-structs/io/userver/utils/strong_typedef.hpp>
13#include <userver/proto-structs/oneof.hpp>
14#include <userver/utils/box.hpp>
15#include <userver/utils/strong_typedef.hpp>
16
17#include "messages.pb.h"
19
20USERVER_NAMESPACE_BEGIN
21
22namespace proto_structs::tests {
23
24enum TestEnum { kValue0 = 0, kValue1 = 1, kValue2 = 2 };
25
26using RawOneof = proto_structs::Oneof<int32_t, int32_t, std::string, TestEnum, structs::Simple>;
27
28struct CustomOneof : RawOneof {};
29
30void CheckAlternativeSet(const RawOneof& oneof, std::size_t set_index) {
31 ASSERT_EQ(oneof.GetIndex(), set_index);
32
33 bool found = false;
34
35 for (std::size_t i = 0; i < RawOneof::kSize; ++i) {
36 if (i != set_index) {
37 ASSERT_FALSE(oneof.Contains(i));
38 } else {
39 ASSERT_TRUE(oneof.Contains(i));
40 found = true;
41 }
42 }
43
44 ASSERT_EQ(oneof.ContainsAny(), found);
45
46 if (found) {
47 ASSERT_TRUE(oneof);
48 } else {
49 ASSERT_FALSE(oneof);
50 }
51}
52
53TEST(OneofTest, Traits) {
54 struct Tag {};
55
56 static_assert(traits::Oneof<RawOneof>);
57 static_assert(traits::Oneof<const volatile RawOneof>);
58 static_assert(traits::Oneof<CustomOneof>);
59 static_assert(traits::Oneof<const volatile CustomOneof>);
60
61 static_assert(RawOneof::kSize == 5);
62 static_assert(CustomOneof::kSize == 5);
63
64 static_assert(!traits::Oneof<RawOneof&>);
65 static_assert(!traits::Oneof<CustomOneof&>);
66 static_assert(!traits::Oneof<int32_t>);
67 static_assert(!traits::Oneof<std::pair<int32_t, int32_t>>);
68
69 static_assert(std::is_same_v<int32_t, OneofAlternativeType<0, RawOneof>>);
70 static_assert(std::is_same_v<int32_t, OneofAlternativeType<1, RawOneof>>);
71 static_assert(std::is_same_v<std::string, OneofAlternativeType<2, RawOneof>>);
72 static_assert(std::is_same_v<TestEnum, OneofAlternativeType<3, RawOneof>>);
73 static_assert(std::is_same_v<structs::Simple, OneofAlternativeType<4, RawOneof>>);
74
75 static_assert(std::is_same_v<int32_t, OneofAlternativeType<0, CustomOneof>>);
76 static_assert(std::is_same_v<int32_t, OneofAlternativeType<1, CustomOneof>>);
77 static_assert(std::is_same_v<std::string, OneofAlternativeType<2, CustomOneof>>);
78 static_assert(std::is_same_v<TestEnum, OneofAlternativeType<3, CustomOneof>>);
79 static_assert(std::is_same_v<structs::Simple, OneofAlternativeType<4, CustomOneof>>);
80}
81
82TEST(OneofTest, Ctor) {
83 RawOneof default_oneof;
84
85 CheckAlternativeSet(default_oneof, kOneofNpos);
86
87 RawOneof oneof(std::in_place_index<2>, "hello world");
88
89 CheckAlternativeSet(oneof, 2);
90 EXPECT_EQ(oneof.Get<2>(), "hello world");
91
92 RawOneof oneof_copy(oneof);
93
94 CheckAlternativeSet(oneof_copy, 2);
95 EXPECT_EQ(oneof_copy.Get<2>(), "hello world");
96
97 oneof.Get<2>() = "test1";
98 oneof_copy = oneof;
99
100 CheckAlternativeSet(oneof_copy, 2);
101 EXPECT_EQ(oneof_copy.Get<2>(), "test1");
102
103 oneof.Get<2>() = "test2";
104 RawOneof oneof_move(std::move(oneof));
105
106 CheckAlternativeSet(oneof_move, 2);
107 EXPECT_EQ(oneof_move.Get<2>(), "test2");
108
109 oneof_copy = std::move(oneof_move);
110
111 CheckAlternativeSet(oneof_copy, 2);
112 EXPECT_EQ(oneof_copy.Get<2>(), "test2");
113}
114
115TEST(OneofTest, GetSetEmplace) {
116 RawOneof oneof;
117
118 oneof.Set<0>(0);
119
120 CheckAlternativeSet(oneof, 0);
121 EXPECT_EQ(oneof.Get<0>(), 0);
122 EXPECT_THAT(
123 [&oneof]() { static_cast<void>(oneof.Get<1>()); },
124 ::testing::ThrowsMessage<OneofAccessError>(::testing::HasSubstr("index = 1"))
125 );
126
127 oneof.Set<0>(42);
128
129 CheckAlternativeSet(oneof, 0);
130 EXPECT_EQ(oneof.Get<0>(), 42);
131
132 EXPECT_EQ(oneof.Emplace<1>(1001), 1001);
133 CheckAlternativeSet(oneof, 1);
134 EXPECT_EQ(oneof.Get<1>(), 1001);
135
136 ++oneof.Get<1>();
137
138 CheckAlternativeSet(oneof, 1);
139 EXPECT_EQ(oneof.Get<1>(), 1002);
140
141 oneof.Set<2>("hello world");
142
143 CheckAlternativeSet(oneof, 2);
144 EXPECT_EQ(oneof.Get<2>(), "hello world");
145
146 std::string str = "some string";
147
148 EXPECT_EQ(oneof.Emplace<2>(str.begin() + 5, str.end()), "string");
149 CheckAlternativeSet(oneof, 2);
150
151 str += "!";
152 oneof.Set<2>(std::move(str));
153
154 CheckAlternativeSet(oneof, 2);
155 EXPECT_EQ(oneof.Get<2>(), "some string!");
156
157 oneof.Set<3>(kValue1);
158
159 CheckAlternativeSet(oneof, 3);
160 EXPECT_EQ(oneof.Get<3>(), kValue1);
161
162 oneof.Set<4>({.f1 = 11});
163
164 CheckAlternativeSet(oneof, 4);
165 EXPECT_EQ(std::move(oneof).Get<4>().f1, 11);
166
167 oneof.GetMutable<0>() = 6;
168
169 CheckAlternativeSet(oneof, 0);
170 EXPECT_EQ(oneof.Get<0>(), 6);
171}
172
173TEST(OneofTest, Clear) {
174 RawOneof oneof;
175
176 EXPECT_NO_THROW(oneof.ClearOneof());
177 CheckAlternativeSet(oneof, kOneofNpos);
178
179 oneof.Set<0>(1);
180
181 EXPECT_NO_THROW(oneof.Clear(1));
182 CheckAlternativeSet(oneof, 0);
183 EXPECT_EQ(oneof.Get<0>(), 1);
184
185 EXPECT_NO_THROW(oneof.Clear(0));
186 CheckAlternativeSet(oneof, kOneofNpos);
187
188 oneof.Set<1>(2);
189
190 EXPECT_NO_THROW(oneof.ClearOneof());
191 CheckAlternativeSet(oneof, kOneofNpos);
192}
193
194} // namespace proto_structs::tests
195
196USERVER_NAMESPACE_END