xref: /aosp_15_r20/external/libtextclassifier/native/utils/flatbuffers/mutable_test.cc (revision 993b0882672172b81d12fad7a7ac0c3e5c824a12)
1*993b0882SAndroid Build Coastguard Worker /*
2*993b0882SAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*993b0882SAndroid Build Coastguard Worker  *
4*993b0882SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*993b0882SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*993b0882SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*993b0882SAndroid Build Coastguard Worker  *
8*993b0882SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*993b0882SAndroid Build Coastguard Worker  *
10*993b0882SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*993b0882SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*993b0882SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*993b0882SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*993b0882SAndroid Build Coastguard Worker  * limitations under the License.
15*993b0882SAndroid Build Coastguard Worker  */
16*993b0882SAndroid Build Coastguard Worker 
17*993b0882SAndroid Build Coastguard Worker #include "utils/flatbuffers/mutable.h"
18*993b0882SAndroid Build Coastguard Worker 
19*993b0882SAndroid Build Coastguard Worker #include <map>
20*993b0882SAndroid Build Coastguard Worker #include <memory>
21*993b0882SAndroid Build Coastguard Worker #include <string>
22*993b0882SAndroid Build Coastguard Worker 
23*993b0882SAndroid Build Coastguard Worker #include "utils/flatbuffers/flatbuffers.h"
24*993b0882SAndroid Build Coastguard Worker #include "utils/flatbuffers/flatbuffers_generated.h"
25*993b0882SAndroid Build Coastguard Worker #include "utils/flatbuffers/flatbuffers_test_generated.h"
26*993b0882SAndroid Build Coastguard Worker #include "utils/flatbuffers/test-utils.h"
27*993b0882SAndroid Build Coastguard Worker #include "gmock/gmock.h"
28*993b0882SAndroid Build Coastguard Worker #include "gtest/gtest.h"
29*993b0882SAndroid Build Coastguard Worker #include "flatbuffers/flatbuffers.h"
30*993b0882SAndroid Build Coastguard Worker #include "flatbuffers/reflection.h"
31*993b0882SAndroid Build Coastguard Worker #include "flatbuffers/reflection_generated.h"
32*993b0882SAndroid Build Coastguard Worker 
33*993b0882SAndroid Build Coastguard Worker namespace libtextclassifier3 {
34*993b0882SAndroid Build Coastguard Worker namespace {
35*993b0882SAndroid Build Coastguard Worker 
36*993b0882SAndroid Build Coastguard Worker using ::testing::ElementsAre;
37*993b0882SAndroid Build Coastguard Worker using ::testing::SizeIs;
38*993b0882SAndroid Build Coastguard Worker 
39*993b0882SAndroid Build Coastguard Worker class MutableFlatbufferTest : public testing::Test {
40*993b0882SAndroid Build Coastguard Worker  public:
MutableFlatbufferTest()41*993b0882SAndroid Build Coastguard Worker   explicit MutableFlatbufferTest()
42*993b0882SAndroid Build Coastguard Worker       : schema_(LoadTestMetadata()), builder_(schema_.get()) {}
43*993b0882SAndroid Build Coastguard Worker 
44*993b0882SAndroid Build Coastguard Worker  protected:
45*993b0882SAndroid Build Coastguard Worker   OwnedFlatbuffer<reflection::Schema, std::string> schema_;
46*993b0882SAndroid Build Coastguard Worker   MutableFlatbufferBuilder builder_;
47*993b0882SAndroid Build Coastguard Worker };
48*993b0882SAndroid Build Coastguard Worker 
TEST_F(MutableFlatbufferTest,PrimitiveFieldsAreCorrectlySet)49*993b0882SAndroid Build Coastguard Worker TEST_F(MutableFlatbufferTest, PrimitiveFieldsAreCorrectlySet) {
50*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<MutableFlatbuffer> buffer = builder_.NewRoot();
51*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer != nullptr);
52*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer->Set("an_int_field", 42));
53*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer->Set("a_long_field", int64{84}));
54*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer->Set("a_bool_field", true));
55*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer->Set("a_float_field", 1.f));
56*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer->Set("a_double_field", 1.0));
57*993b0882SAndroid Build Coastguard Worker 
58*993b0882SAndroid Build Coastguard Worker   // Try to parse with the generated code.
59*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<test::EntityDataT> entity_data =
60*993b0882SAndroid Build Coastguard Worker       LoadAndVerifyMutableFlatbuffer<test::EntityData>(buffer->Serialize());
61*993b0882SAndroid Build Coastguard Worker   ASSERT_NE(entity_data, nullptr);
62*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->an_int_field, 42);
63*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->a_long_field, 84);
64*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->a_bool_field, true);
65*993b0882SAndroid Build Coastguard Worker   EXPECT_NEAR(entity_data->a_float_field, 1.f, 1e-4);
66*993b0882SAndroid Build Coastguard Worker   EXPECT_NEAR(entity_data->a_double_field, 1.f, 1e-4);
67*993b0882SAndroid Build Coastguard Worker }
68*993b0882SAndroid Build Coastguard Worker 
TEST_F(MutableFlatbufferTest,EnumValuesCanBeSpecifiedByName)69*993b0882SAndroid Build Coastguard Worker TEST_F(MutableFlatbufferTest, EnumValuesCanBeSpecifiedByName) {
70*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<MutableFlatbuffer> buffer = builder_.NewRoot();
71*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer != nullptr);
72*993b0882SAndroid Build Coastguard Worker 
73*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(IsEnum(buffer->GetFieldOrNull("enum_value")->type()));
74*993b0882SAndroid Build Coastguard Worker 
75*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer->SetFromEnumValueName("enum_value", "VALUE_1"));
76*993b0882SAndroid Build Coastguard Worker 
77*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<test::EntityDataT> entity_data =
78*993b0882SAndroid Build Coastguard Worker       LoadAndVerifyMutableFlatbuffer<test::EntityData>(buffer->Serialize());
79*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->enum_value,
80*993b0882SAndroid Build Coastguard Worker             libtextclassifier3::test::EnumValue_VALUE_1);
81*993b0882SAndroid Build Coastguard Worker }
82*993b0882SAndroid Build Coastguard Worker 
TEST_F(MutableFlatbufferTest,HandlesUnknownFields)83*993b0882SAndroid Build Coastguard Worker TEST_F(MutableFlatbufferTest, HandlesUnknownFields) {
84*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<MutableFlatbuffer> buffer = builder_.NewRoot();
85*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer != nullptr);
86*993b0882SAndroid Build Coastguard Worker 
87*993b0882SAndroid Build Coastguard Worker   // Add a field that is not known to the (statically generated) code.
88*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer->Set("mystic", "this is an unknown field."));
89*993b0882SAndroid Build Coastguard Worker 
90*993b0882SAndroid Build Coastguard Worker   OwnedFlatbuffer<flatbuffers::Table, std::string> extra(buffer->Serialize());
91*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(extra
92*993b0882SAndroid Build Coastguard Worker                 ->GetPointer<const flatbuffers::String*>(
93*993b0882SAndroid Build Coastguard Worker                     buffer->GetFieldOrNull("mystic")->offset())
94*993b0882SAndroid Build Coastguard Worker                 ->str(),
95*993b0882SAndroid Build Coastguard Worker             "this is an unknown field.");
96*993b0882SAndroid Build Coastguard Worker }
97*993b0882SAndroid Build Coastguard Worker 
TEST_F(MutableFlatbufferTest,HandlesNestedFields)98*993b0882SAndroid Build Coastguard Worker TEST_F(MutableFlatbufferTest, HandlesNestedFields) {
99*993b0882SAndroid Build Coastguard Worker   OwnedFlatbuffer<FlatbufferFieldPath, std::string> path =
100*993b0882SAndroid Build Coastguard Worker       CreateFieldPath({"flight_number", "carrier_code"});
101*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<MutableFlatbuffer> buffer = builder_.NewRoot();
102*993b0882SAndroid Build Coastguard Worker 
103*993b0882SAndroid Build Coastguard Worker   MutableFlatbuffer* parent = nullptr;
104*993b0882SAndroid Build Coastguard Worker   reflection::Field const* field = nullptr;
105*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer->GetFieldWithParent(path.get(), &parent, &field));
106*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(parent, buffer->Mutable("flight_number"));
107*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(field,
108*993b0882SAndroid Build Coastguard Worker             buffer->Mutable("flight_number")->GetFieldOrNull("carrier_code"));
109*993b0882SAndroid Build Coastguard Worker }
110*993b0882SAndroid Build Coastguard Worker 
TEST_F(MutableFlatbufferTest,HandlesMultipleNestedFields)111*993b0882SAndroid Build Coastguard Worker TEST_F(MutableFlatbufferTest, HandlesMultipleNestedFields) {
112*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<MutableFlatbuffer> buffer = builder_.NewRoot();
113*993b0882SAndroid Build Coastguard Worker   MutableFlatbuffer* flight_info = buffer->Mutable("flight_number");
114*993b0882SAndroid Build Coastguard Worker   flight_info->Set("carrier_code", "LX");
115*993b0882SAndroid Build Coastguard Worker   flight_info->Set("flight_code", 38);
116*993b0882SAndroid Build Coastguard Worker 
117*993b0882SAndroid Build Coastguard Worker   MutableFlatbuffer* contact_info = buffer->Mutable("contact_info");
118*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(contact_info->Set("first_name", "Barack"));
119*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(contact_info->Set("last_name", "Obama"));
120*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(contact_info->Set("phone_number", "1-800-TEST"));
121*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(contact_info->Set("score", 1.f));
122*993b0882SAndroid Build Coastguard Worker 
123*993b0882SAndroid Build Coastguard Worker   // Try to parse with the generated code.
124*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<test::EntityDataT> entity_data =
125*993b0882SAndroid Build Coastguard Worker       LoadAndVerifyMutableFlatbuffer<test::EntityData>(buffer->Serialize());
126*993b0882SAndroid Build Coastguard Worker   ASSERT_NE(entity_data, nullptr);
127*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->flight_number->carrier_code, "LX");
128*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->flight_number->flight_code, 38);
129*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->contact_info->first_name, "Barack");
130*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->contact_info->last_name, "Obama");
131*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->contact_info->phone_number, "1-800-TEST");
132*993b0882SAndroid Build Coastguard Worker   EXPECT_NEAR(entity_data->contact_info->score, 1.f, 1e-4);
133*993b0882SAndroid Build Coastguard Worker }
134*993b0882SAndroid Build Coastguard Worker 
TEST_F(MutableFlatbufferTest,HandlesFieldsSetWithNamePath)135*993b0882SAndroid Build Coastguard Worker TEST_F(MutableFlatbufferTest, HandlesFieldsSetWithNamePath) {
136*993b0882SAndroid Build Coastguard Worker   FlatbufferFieldPathT path;
137*993b0882SAndroid Build Coastguard Worker   path.field.emplace_back(new FlatbufferFieldT);
138*993b0882SAndroid Build Coastguard Worker   path.field.back()->field_name = "flight_number";
139*993b0882SAndroid Build Coastguard Worker   path.field.emplace_back(new FlatbufferFieldT);
140*993b0882SAndroid Build Coastguard Worker   path.field.back()->field_name = "carrier_code";
141*993b0882SAndroid Build Coastguard Worker   flatbuffers::FlatBufferBuilder path_builder;
142*993b0882SAndroid Build Coastguard Worker   path_builder.Finish(FlatbufferFieldPath::Pack(path_builder, &path));
143*993b0882SAndroid Build Coastguard Worker 
144*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<MutableFlatbuffer> buffer = builder_.NewRoot();
145*993b0882SAndroid Build Coastguard Worker   // Test setting value using Set function.
146*993b0882SAndroid Build Coastguard Worker   buffer->Mutable("flight_number")->Set("flight_code", 38);
147*993b0882SAndroid Build Coastguard Worker   // Test setting value using FlatbufferFieldPath.
148*993b0882SAndroid Build Coastguard Worker   buffer->Set(flatbuffers::GetRoot<FlatbufferFieldPath>(
149*993b0882SAndroid Build Coastguard Worker                   path_builder.GetBufferPointer()),
150*993b0882SAndroid Build Coastguard Worker               "LX");
151*993b0882SAndroid Build Coastguard Worker 
152*993b0882SAndroid Build Coastguard Worker   // Try to parse with the generated code.
153*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<test::EntityDataT> entity_data =
154*993b0882SAndroid Build Coastguard Worker       LoadAndVerifyMutableFlatbuffer<test::EntityData>(buffer->Serialize());
155*993b0882SAndroid Build Coastguard Worker   ASSERT_NE(entity_data, nullptr);
156*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->flight_number->carrier_code, "LX");
157*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->flight_number->flight_code, 38);
158*993b0882SAndroid Build Coastguard Worker }
159*993b0882SAndroid Build Coastguard Worker 
TEST_F(MutableFlatbufferTest,HandlesFieldsSetWithOffsetPath)160*993b0882SAndroid Build Coastguard Worker TEST_F(MutableFlatbufferTest, HandlesFieldsSetWithOffsetPath) {
161*993b0882SAndroid Build Coastguard Worker   FlatbufferFieldPathT path;
162*993b0882SAndroid Build Coastguard Worker   path.field.emplace_back(new FlatbufferFieldT);
163*993b0882SAndroid Build Coastguard Worker   path.field.back()->field_offset = 14;
164*993b0882SAndroid Build Coastguard Worker   path.field.emplace_back(new FlatbufferFieldT);
165*993b0882SAndroid Build Coastguard Worker   path.field.back()->field_offset = 4;
166*993b0882SAndroid Build Coastguard Worker   flatbuffers::FlatBufferBuilder path_builder;
167*993b0882SAndroid Build Coastguard Worker   path_builder.Finish(FlatbufferFieldPath::Pack(path_builder, &path));
168*993b0882SAndroid Build Coastguard Worker 
169*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<MutableFlatbuffer> buffer = builder_.NewRoot();
170*993b0882SAndroid Build Coastguard Worker   // Test setting value using Set function.
171*993b0882SAndroid Build Coastguard Worker   buffer->Mutable("flight_number")->Set("flight_code", 38);
172*993b0882SAndroid Build Coastguard Worker   // Test setting value using FlatbufferFieldPath.
173*993b0882SAndroid Build Coastguard Worker   buffer->Set(flatbuffers::GetRoot<FlatbufferFieldPath>(
174*993b0882SAndroid Build Coastguard Worker                   path_builder.GetBufferPointer()),
175*993b0882SAndroid Build Coastguard Worker               "LX");
176*993b0882SAndroid Build Coastguard Worker 
177*993b0882SAndroid Build Coastguard Worker   // Try to parse with the generated code.
178*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<test::EntityDataT> entity_data =
179*993b0882SAndroid Build Coastguard Worker       LoadAndVerifyMutableFlatbuffer<test::EntityData>(buffer->Serialize());
180*993b0882SAndroid Build Coastguard Worker   ASSERT_NE(entity_data, nullptr);
181*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->flight_number->carrier_code, "LX");
182*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->flight_number->flight_code, 38);
183*993b0882SAndroid Build Coastguard Worker }
184*993b0882SAndroid Build Coastguard Worker 
TEST_F(MutableFlatbufferTest,PartialBuffersAreCorrectlyMerged)185*993b0882SAndroid Build Coastguard Worker TEST_F(MutableFlatbufferTest, PartialBuffersAreCorrectlyMerged) {
186*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<MutableFlatbuffer> buffer = builder_.NewRoot();
187*993b0882SAndroid Build Coastguard Worker   buffer->Set("an_int_field", 42);
188*993b0882SAndroid Build Coastguard Worker   buffer->Set("a_long_field", int64{84});
189*993b0882SAndroid Build Coastguard Worker   MutableFlatbuffer* flight_info = buffer->Mutable("flight_number");
190*993b0882SAndroid Build Coastguard Worker   flight_info->Set("carrier_code", "LX");
191*993b0882SAndroid Build Coastguard Worker   flight_info->Set("flight_code", 38);
192*993b0882SAndroid Build Coastguard Worker   auto* reminders = buffer->Repeated("reminders");
193*993b0882SAndroid Build Coastguard Worker   MutableFlatbuffer* reminder1 = reminders->Add();
194*993b0882SAndroid Build Coastguard Worker   reminder1->Set("title", "reminder1");
195*993b0882SAndroid Build Coastguard Worker   auto* reminder1_notes = reminder1->Repeated("notes");
196*993b0882SAndroid Build Coastguard Worker   reminder1_notes->Add("note1");
197*993b0882SAndroid Build Coastguard Worker   reminder1_notes->Add("note2");
198*993b0882SAndroid Build Coastguard Worker 
199*993b0882SAndroid Build Coastguard Worker   // Create message to merge.
200*993b0882SAndroid Build Coastguard Worker   test::EntityDataT additional_entity_data;
201*993b0882SAndroid Build Coastguard Worker   additional_entity_data.an_int_field = 43;
202*993b0882SAndroid Build Coastguard Worker   additional_entity_data.flight_number.reset(new test::FlightNumberInfoT);
203*993b0882SAndroid Build Coastguard Worker   additional_entity_data.flight_number->flight_code = 39;
204*993b0882SAndroid Build Coastguard Worker   additional_entity_data.contact_info.reset(new test::ContactInfoT);
205*993b0882SAndroid Build Coastguard Worker   additional_entity_data.contact_info->first_name = "Barack";
206*993b0882SAndroid Build Coastguard Worker   additional_entity_data.reminders.push_back(
207*993b0882SAndroid Build Coastguard Worker       std::unique_ptr<test::ReminderT>(new test::ReminderT));
208*993b0882SAndroid Build Coastguard Worker   additional_entity_data.reminders[0]->notes.push_back("additional note1");
209*993b0882SAndroid Build Coastguard Worker   additional_entity_data.reminders[0]->notes.push_back("additional note2");
210*993b0882SAndroid Build Coastguard Worker   additional_entity_data.numbers.push_back(9);
211*993b0882SAndroid Build Coastguard Worker   additional_entity_data.numbers.push_back(10);
212*993b0882SAndroid Build Coastguard Worker   additional_entity_data.strings.push_back("str1");
213*993b0882SAndroid Build Coastguard Worker   additional_entity_data.strings.push_back("str2");
214*993b0882SAndroid Build Coastguard Worker 
215*993b0882SAndroid Build Coastguard Worker   // Merge it.
216*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer->MergeFromSerializedFlatbuffer(
217*993b0882SAndroid Build Coastguard Worker       PackFlatbuffer<test::EntityData>(&additional_entity_data)));
218*993b0882SAndroid Build Coastguard Worker 
219*993b0882SAndroid Build Coastguard Worker   // Try to parse it with the generated code.
220*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<test::EntityDataT> entity_data =
221*993b0882SAndroid Build Coastguard Worker       LoadAndVerifyMutableFlatbuffer<test::EntityData>(buffer->Serialize());
222*993b0882SAndroid Build Coastguard Worker   ASSERT_NE(entity_data, nullptr);
223*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->an_int_field, 43);
224*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->a_long_field, 84);
225*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->flight_number->carrier_code, "LX");
226*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->flight_number->flight_code, 39);
227*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->contact_info->first_name, "Barack");
228*993b0882SAndroid Build Coastguard Worker   ASSERT_THAT(entity_data->reminders, SizeIs(2));
229*993b0882SAndroid Build Coastguard Worker   EXPECT_THAT(entity_data->reminders[1]->notes,
230*993b0882SAndroid Build Coastguard Worker               ElementsAre("additional note1", "additional note2"));
231*993b0882SAndroid Build Coastguard Worker   EXPECT_THAT(entity_data->numbers, ElementsAre(9, 10));
232*993b0882SAndroid Build Coastguard Worker   EXPECT_THAT(entity_data->strings, ElementsAre("str1", "str2"));
233*993b0882SAndroid Build Coastguard Worker }
234*993b0882SAndroid Build Coastguard Worker 
TEST_F(MutableFlatbufferTest,MergesNestedFields)235*993b0882SAndroid Build Coastguard Worker TEST_F(MutableFlatbufferTest, MergesNestedFields) {
236*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<MutableFlatbuffer> buffer = builder_.NewRoot();
237*993b0882SAndroid Build Coastguard Worker 
238*993b0882SAndroid Build Coastguard Worker   // Set a multiply nested field.
239*993b0882SAndroid Build Coastguard Worker   OwnedFlatbuffer<FlatbufferFieldPath, std::string> field_path =
240*993b0882SAndroid Build Coastguard Worker       CreateFieldPath({"nested", "nestedb", "nesteda", "nestedb", "nesteda"});
241*993b0882SAndroid Build Coastguard Worker   buffer->Mutable(field_path.get())->Set("value", "le value");
242*993b0882SAndroid Build Coastguard Worker 
243*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<test::EntityDataT> entity_data =
244*993b0882SAndroid Build Coastguard Worker       LoadAndVerifyMutableFlatbuffer<test::EntityData>(buffer->Serialize());
245*993b0882SAndroid Build Coastguard Worker   ASSERT_NE(entity_data, nullptr);
246*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->nested->nestedb->nesteda->nestedb->nesteda->value,
247*993b0882SAndroid Build Coastguard Worker             "le value");
248*993b0882SAndroid Build Coastguard Worker }
249*993b0882SAndroid Build Coastguard Worker 
TEST_F(MutableFlatbufferTest,PrimitiveAndNestedFieldsAreCorrectlyFlattened)250*993b0882SAndroid Build Coastguard Worker TEST_F(MutableFlatbufferTest, PrimitiveAndNestedFieldsAreCorrectlyFlattened) {
251*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<MutableFlatbuffer> buffer = builder_.NewRoot();
252*993b0882SAndroid Build Coastguard Worker   buffer->Set("an_int_field", 42);
253*993b0882SAndroid Build Coastguard Worker   buffer->Set("a_long_field", int64{84});
254*993b0882SAndroid Build Coastguard Worker   MutableFlatbuffer* flight_info = buffer->Mutable("flight_number");
255*993b0882SAndroid Build Coastguard Worker   flight_info->Set("carrier_code", "LX");
256*993b0882SAndroid Build Coastguard Worker   flight_info->Set("flight_code", 38);
257*993b0882SAndroid Build Coastguard Worker 
258*993b0882SAndroid Build Coastguard Worker   std::map<std::string, Variant> entity_data_map = buffer->AsFlatMap();
259*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(4, entity_data_map.size());
260*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(42, entity_data_map["an_int_field"].Value<int>());
261*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(84, entity_data_map["a_long_field"].Value<int64>());
262*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ("LX", entity_data_map["flight_number.carrier_code"]
263*993b0882SAndroid Build Coastguard Worker                       .ConstRefValue<std::string>());
264*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(38, entity_data_map["flight_number.flight_code"].Value<int>());
265*993b0882SAndroid Build Coastguard Worker }
266*993b0882SAndroid Build Coastguard Worker 
TEST_F(MutableFlatbufferTest,ToTextProtoWorks)267*993b0882SAndroid Build Coastguard Worker TEST_F(MutableFlatbufferTest, ToTextProtoWorks) {
268*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<MutableFlatbuffer> buffer = builder_.NewRoot();
269*993b0882SAndroid Build Coastguard Worker   buffer->Set("an_int_field", 42);
270*993b0882SAndroid Build Coastguard Worker   buffer->Set("a_long_field", int64{84});
271*993b0882SAndroid Build Coastguard Worker   MutableFlatbuffer* flight_info = buffer->Mutable("flight_number");
272*993b0882SAndroid Build Coastguard Worker   flight_info->Set("carrier_code", "LX");
273*993b0882SAndroid Build Coastguard Worker   flight_info->Set("flight_code", 38);
274*993b0882SAndroid Build Coastguard Worker 
275*993b0882SAndroid Build Coastguard Worker   // Add non primitive type.
276*993b0882SAndroid Build Coastguard Worker   auto reminders = buffer->Repeated("reminders");
277*993b0882SAndroid Build Coastguard Worker   auto foo_reminder = reminders->Add();
278*993b0882SAndroid Build Coastguard Worker   foo_reminder->Set("title", "foo reminder");
279*993b0882SAndroid Build Coastguard Worker   auto bar_reminder = reminders->Add();
280*993b0882SAndroid Build Coastguard Worker   bar_reminder->Set("title", "bar reminder");
281*993b0882SAndroid Build Coastguard Worker 
282*993b0882SAndroid Build Coastguard Worker   // Add primitive type.
283*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer->Repeated("numbers")->Add(static_cast<int>(111)));
284*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer->Repeated("numbers")->Add(static_cast<int>(222)));
285*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer->Repeated("numbers")->Add(static_cast<int>(333)));
286*993b0882SAndroid Build Coastguard Worker 
287*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(buffer->ToTextProto(),
288*993b0882SAndroid Build Coastguard Worker             "a_long_field: 84, an_int_field: 42, numbers:  [111, 222, 333] , "
289*993b0882SAndroid Build Coastguard Worker             "reminders:  [{title: 'foo reminder'}, {title: 'bar reminder'}] , "
290*993b0882SAndroid Build Coastguard Worker             "flight_number {flight_code: 38, carrier_code: 'LX'}");
291*993b0882SAndroid Build Coastguard Worker }
292*993b0882SAndroid Build Coastguard Worker 
TEST_F(MutableFlatbufferTest,RepeatedFieldSetThroughReflectionCanBeRead)293*993b0882SAndroid Build Coastguard Worker TEST_F(MutableFlatbufferTest, RepeatedFieldSetThroughReflectionCanBeRead) {
294*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<MutableFlatbuffer> buffer = builder_.NewRoot();
295*993b0882SAndroid Build Coastguard Worker 
296*993b0882SAndroid Build Coastguard Worker   auto reminders = buffer->Repeated("reminders");
297*993b0882SAndroid Build Coastguard Worker   {
298*993b0882SAndroid Build Coastguard Worker     auto reminder = reminders->Add();
299*993b0882SAndroid Build Coastguard Worker     reminder->Set("title", "test reminder");
300*993b0882SAndroid Build Coastguard Worker     auto notes = reminder->Repeated("notes");
301*993b0882SAndroid Build Coastguard Worker     notes->Add("note A");
302*993b0882SAndroid Build Coastguard Worker     notes->Add("note B");
303*993b0882SAndroid Build Coastguard Worker   }
304*993b0882SAndroid Build Coastguard Worker   {
305*993b0882SAndroid Build Coastguard Worker     auto reminder = reminders->Add();
306*993b0882SAndroid Build Coastguard Worker     reminder->Set("title", "test reminder 2");
307*993b0882SAndroid Build Coastguard Worker     reminder->Add("notes", "note i");
308*993b0882SAndroid Build Coastguard Worker     reminder->Add("notes", "note ii");
309*993b0882SAndroid Build Coastguard Worker     reminder->Add("notes", "note iii");
310*993b0882SAndroid Build Coastguard Worker   }
311*993b0882SAndroid Build Coastguard Worker 
312*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<test::EntityDataT> entity_data =
313*993b0882SAndroid Build Coastguard Worker       LoadAndVerifyMutableFlatbuffer<test::EntityData>(buffer->Serialize());
314*993b0882SAndroid Build Coastguard Worker   ASSERT_NE(entity_data, nullptr);
315*993b0882SAndroid Build Coastguard Worker   EXPECT_THAT(entity_data->reminders, SizeIs(2));
316*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->reminders[0]->title, "test reminder");
317*993b0882SAndroid Build Coastguard Worker   EXPECT_THAT(entity_data->reminders[0]->notes,
318*993b0882SAndroid Build Coastguard Worker               ElementsAre("note A", "note B"));
319*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->reminders[1]->title, "test reminder 2");
320*993b0882SAndroid Build Coastguard Worker   EXPECT_THAT(entity_data->reminders[1]->notes,
321*993b0882SAndroid Build Coastguard Worker               ElementsAre("note i", "note ii", "note iii"));
322*993b0882SAndroid Build Coastguard Worker }
323*993b0882SAndroid Build Coastguard Worker 
TEST_F(MutableFlatbufferTest,RepeatedFieldAddMethodWithIncompatibleValues)324*993b0882SAndroid Build Coastguard Worker TEST_F(MutableFlatbufferTest, RepeatedFieldAddMethodWithIncompatibleValues) {
325*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<MutableFlatbuffer> buffer = builder_.NewRoot();
326*993b0882SAndroid Build Coastguard Worker   EXPECT_FALSE(buffer->Repeated("numbers")->Add(static_cast<int64>(123)));
327*993b0882SAndroid Build Coastguard Worker   EXPECT_FALSE(buffer->Repeated("numbers")->Add(static_cast<int8>(9)));
328*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer->Repeated("numbers")->Add(static_cast<int>(999)));
329*993b0882SAndroid Build Coastguard Worker 
330*993b0882SAndroid Build Coastguard Worker   // Try to parse it with the generated code.
331*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<test::EntityDataT> entity_data =
332*993b0882SAndroid Build Coastguard Worker       LoadAndVerifyMutableFlatbuffer<test::EntityData>(buffer->Serialize());
333*993b0882SAndroid Build Coastguard Worker   ASSERT_NE(entity_data, nullptr);
334*993b0882SAndroid Build Coastguard Worker   ASSERT_NE(entity_data, nullptr);
335*993b0882SAndroid Build Coastguard Worker   ASSERT_EQ(entity_data->numbers.size(), 1);
336*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(entity_data->numbers[0], 999);
337*993b0882SAndroid Build Coastguard Worker }
338*993b0882SAndroid Build Coastguard Worker 
TEST_F(MutableFlatbufferTest,RepeatedFieldGetAndSizeMethods)339*993b0882SAndroid Build Coastguard Worker TEST_F(MutableFlatbufferTest, RepeatedFieldGetAndSizeMethods) {
340*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<MutableFlatbuffer> buffer = builder_.NewRoot();
341*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer->Repeated("numbers")->Add(1));
342*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer->Repeated("numbers")->Add(2));
343*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer->Repeated("numbers")->Add(3));
344*993b0882SAndroid Build Coastguard Worker 
345*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(buffer->Repeated("numbers")->Size(), 3);
346*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(buffer->Repeated("numbers")->Get<int>(0), 1);
347*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(buffer->Repeated("numbers")->Get<int>(1), 2);
348*993b0882SAndroid Build Coastguard Worker   EXPECT_EQ(buffer->Repeated("numbers")->Get<int>(2), 3);
349*993b0882SAndroid Build Coastguard Worker }
350*993b0882SAndroid Build Coastguard Worker 
TEST_F(MutableFlatbufferTest,GetsRepeatedFieldFromPath)351*993b0882SAndroid Build Coastguard Worker TEST_F(MutableFlatbufferTest, GetsRepeatedFieldFromPath) {
352*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<MutableFlatbuffer> buffer = builder_.NewRoot();
353*993b0882SAndroid Build Coastguard Worker   OwnedFlatbuffer<FlatbufferFieldPath, std::string> notes =
354*993b0882SAndroid Build Coastguard Worker       CreateFieldPath({"nested", "repeated_str"});
355*993b0882SAndroid Build Coastguard Worker 
356*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer->Repeated(notes.get())->Add("a"));
357*993b0882SAndroid Build Coastguard Worker   EXPECT_TRUE(buffer->Repeated(notes.get())->Add("test"));
358*993b0882SAndroid Build Coastguard Worker 
359*993b0882SAndroid Build Coastguard Worker   std::unique_ptr<test::EntityDataT> entity_data =
360*993b0882SAndroid Build Coastguard Worker       LoadAndVerifyMutableFlatbuffer<test::EntityData>(buffer->Serialize());
361*993b0882SAndroid Build Coastguard Worker   ASSERT_NE(entity_data, nullptr);
362*993b0882SAndroid Build Coastguard Worker   EXPECT_THAT(entity_data->nested->repeated_str, SizeIs(2));
363*993b0882SAndroid Build Coastguard Worker   EXPECT_THAT(entity_data->nested->repeated_str, ElementsAre("a", "test"));
364*993b0882SAndroid Build Coastguard Worker }
365*993b0882SAndroid Build Coastguard Worker 
366*993b0882SAndroid Build Coastguard Worker }  // namespace
367*993b0882SAndroid Build Coastguard Worker }  // namespace libtextclassifier3
368