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