xref: /aosp_15_r20/external/federated-compute/fcp/secagg/shared/secagg_vector_test.cc (revision 14675a029014e728ec732f129a32e299b2da0601)
1 /*
2  * Copyright 2018 Google LLC
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "fcp/secagg/shared/secagg_vector.h"
18 
19 #include <cstdint>
20 #include <utility>
21 #include <vector>
22 
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 #include "fcp/secagg/shared/math.h"
26 
27 namespace fcp {
28 namespace secagg {
29 namespace {
30 
31 using ::testing::ElementsAreArray;
32 using ::testing::Eq;
33 using SecAggVectorTest = ::testing::TestWithParam<bool>;
34 
35 static std::array<uint64_t, 20> kArbitraryModuli{5,
36                                                  39,
37                                                  485,
38                                                  2400,
39                                                  14901,
40                                                  51813,
41                                                  532021,
42                                                  13916946,
43                                                  39549497,
44                                                  548811945,
45                                                  590549014,
46                                                  48296031686,
47                                                  156712951284,
48                                                  2636861836189,
49                                                  14673852658160,
50                                                  92971495438615,
51                                                  304436005557271,
52                                                  14046234330484262,
53                                                  38067457113486645,
54                                                  175631339105057682};
55 
TEST_P(SecAggVectorTest,GettersReturnAppropriateValuesOnConstructedVector)56 TEST_P(SecAggVectorTest, GettersReturnAppropriateValuesOnConstructedVector) {
57   std::vector<uint64_t> raw_vector = {4, 5};
58   uint64_t modulus = 256;
59   SecAggVector vector(raw_vector, modulus, GetParam());
60   EXPECT_THAT(modulus, Eq(vector.modulus()));
61   EXPECT_THAT(8, Eq(vector.bit_width()));
62   EXPECT_THAT(raw_vector.size(), Eq(vector.num_elements()));
63   EXPECT_THAT(raw_vector, Eq(vector.GetAsUint64Vector()));
64 }
65 
TEST_P(SecAggVectorTest,ConstructorDoesNotDieOnInputsCloseToModulusBound)66 TEST_P(SecAggVectorTest, ConstructorDoesNotDieOnInputsCloseToModulusBound) {
67   std::vector<uint64_t> raw_vector = {0, 3};
68   SecAggVector vector(raw_vector, 4, GetParam());
69 }
70 
TEST_P(SecAggVectorTest,ConstructorDiesOnInputEqualsModulus)71 TEST_P(SecAggVectorTest, ConstructorDiesOnInputEqualsModulus) {
72   std::vector<uint64_t> raw_vector = {4};
73   EXPECT_DEATH(SecAggVector vector(raw_vector, 4, GetParam()),
74                "The span does not have the appropriate modulus");
75 }
76 
TEST_P(SecAggVectorTest,ConstructorDiesOnInputBiggerThanMaxModulus)77 TEST_P(SecAggVectorTest, ConstructorDiesOnInputBiggerThanMaxModulus) {
78   std::vector<uint64_t> raw_vector = {SecAggVector::kMaxModulus};
79   EXPECT_DEATH(
80       SecAggVector vector(raw_vector, SecAggVector::kMaxModulus, GetParam()),
81       "The span does not have the appropriate modulus");
82 }
83 
TEST_P(SecAggVectorTest,ConstructorDiesOnNegativeModulus)84 TEST_P(SecAggVectorTest, ConstructorDiesOnNegativeModulus) {
85   std::vector<uint64_t> raw_vector = {4};
86   EXPECT_DEATH(SecAggVector vector(raw_vector, -2, GetParam()),
87                "The specified modulus is not valid");
88 }
89 
TEST_P(SecAggVectorTest,ConstructorDiesOnModulusZero)90 TEST_P(SecAggVectorTest, ConstructorDiesOnModulusZero) {
91   std::vector<uint64_t> raw_vector = {4};
92   EXPECT_DEATH(SecAggVector vector(raw_vector, 0, GetParam()),
93                "The specified modulus is not valid");
94 }
95 
TEST_P(SecAggVectorTest,ConstructorDiesOnModulusOne)96 TEST_P(SecAggVectorTest, ConstructorDiesOnModulusOne) {
97   std::vector<uint64_t> raw_vector = {4};
98   EXPECT_DEATH(SecAggVector vector(raw_vector, 1, GetParam()),
99                "The specified modulus is not valid");
100 }
101 
TEST_P(SecAggVectorTest,ConstructorDiesOnModulusTooLarge)102 TEST_P(SecAggVectorTest, ConstructorDiesOnModulusTooLarge) {
103   std::vector<uint64_t> raw_vector = {4};
104   EXPECT_DEATH(SecAggVector vector(raw_vector, SecAggVector::kMaxModulus + 1,
105                                    GetParam()),
106                "The specified modulus is not valid");
107 }
108 
TEST_P(SecAggVectorTest,StringConstructorSucceedsOnValidInputs)109 TEST_P(SecAggVectorTest, StringConstructorSucceedsOnValidInputs) {
110   std::string packed_bytes(3, '\0');
111   SecAggVector vector(packed_bytes, 4, 12, GetParam());
112 
113   // empty vector
114   std::string packed_bytes2 = "";
115   SecAggVector vector2(packed_bytes2, 32, 0, GetParam());
116 
117   // lines up with byte boundary
118   std::string packed_bytes3(4, '\0');
119   SecAggVector vector3(packed_bytes3, 1ULL << 16, 2, GetParam());
120 }
121 
TEST_P(SecAggVectorTest,StringConstructorDiesOnNegativeModulus)122 TEST_P(SecAggVectorTest, StringConstructorDiesOnNegativeModulus) {
123   std::string packed_bytes(3, '\0');
124   EXPECT_DEATH(SecAggVector vector(packed_bytes, -2, 4, GetParam()),
125                "The specified modulus is not valid");
126 }
127 
TEST_P(SecAggVectorTest,StringConstructorDiesOnModulusZero)128 TEST_P(SecAggVectorTest, StringConstructorDiesOnModulusZero) {
129   std::string packed_bytes(3, '\0');
130   EXPECT_DEATH(SecAggVector vector(packed_bytes, 0, 4, GetParam()),
131                "The specified modulus is not valid");
132 }
133 
TEST_P(SecAggVectorTest,StringConstructorDiesOnModulusOne)134 TEST_P(SecAggVectorTest, StringConstructorDiesOnModulusOne) {
135   std::string packed_bytes(3, '\0');
136   EXPECT_DEATH(SecAggVector vector(packed_bytes, 1, 4, GetParam()),
137                "The specified modulus is not valid");
138 }
139 
TEST_P(SecAggVectorTest,StringConstructorDiesOnModulusTooLarge)140 TEST_P(SecAggVectorTest, StringConstructorDiesOnModulusTooLarge) {
141   std::string packed_bytes(3, '\0');
142   EXPECT_DEATH(SecAggVector vector(packed_bytes, SecAggVector::kMaxModulus + 1,
143                                    4, GetParam()),
144                "The specified modulus is not valid");
145 }
146 
TEST_P(SecAggVectorTest,StringConstructorDiesOnTooShortString)147 TEST_P(SecAggVectorTest, StringConstructorDiesOnTooShortString) {
148   int num_elements = 4;
149   uint64_t modulus = 16;
150   int bit_width = 4;
151   int expected_length = DivideRoundUp(num_elements * bit_width, 8);
152 
153   std::string packed_bytes(expected_length - 1, '\0');
154   EXPECT_DEATH(SecAggVector vector(packed_bytes, modulus, 4, GetParam()),
155                "The supplied string is not the right size");
156 }
157 
TEST_P(SecAggVectorTest,StringConstructorDiesOnTooLongString)158 TEST_P(SecAggVectorTest, StringConstructorDiesOnTooLongString) {
159   int num_elements = 4;
160   uint64_t modulus = 16;
161   int bit_width = 4;
162   int expected_length = DivideRoundUp(num_elements * bit_width, 8);
163 
164   std::string packed_bytes(expected_length + 1, '\0');
165   EXPECT_DEATH(SecAggVector vector(packed_bytes, modulus, 4, GetParam()),
166                "The supplied string is not the right size");
167 }
168 
TEST_P(SecAggVectorTest,PackedVectorHasCorrectSize)169 TEST_P(SecAggVectorTest, PackedVectorHasCorrectSize) {
170   std::vector<uint64_t> raw_vector = {0, 1, 2, 3, 4};
171   uint64_t modulus = 32;
172   int bit_width = 5;
173   SecAggVector vector(raw_vector, modulus, GetParam());
174   std::string packed_bytes = vector.GetAsPackedBytes();
175   int expected_length = DivideRoundUp(raw_vector.size() * bit_width, 8);
176   EXPECT_THAT(expected_length, Eq(packed_bytes.size()));
177 
178   // empty vector
179   std::vector<uint64_t> empty_raw_vector = {};
180   modulus = 32;
181   bit_width = 5;
182   SecAggVector vector2(empty_raw_vector, modulus, GetParam());
183   packed_bytes = vector2.GetAsPackedBytes();
184   expected_length = 0;
185   EXPECT_THAT(expected_length, Eq(packed_bytes.size()));
186 
187   // packed_bytes lines up with byte boundary
188   modulus = 1ULL << 16;
189   bit_width = 16;
190   SecAggVector vector3(raw_vector, modulus, GetParam());
191   packed_bytes = vector3.GetAsPackedBytes();
192   expected_length = DivideRoundUp(raw_vector.size() * bit_width, 8);
193   EXPECT_THAT(expected_length, Eq(packed_bytes.size()));
194 
195   // max bit_width
196   modulus = 1ULL << 62;
197   bit_width = 62;
198   SecAggVector vector4(raw_vector, modulus, GetParam());
199   packed_bytes = vector4.GetAsPackedBytes();
200   expected_length = DivideRoundUp(raw_vector.size() * bit_width, 8);
201   EXPECT_THAT(expected_length, Eq(packed_bytes.size()));
202 }
203 
TEST_P(SecAggVectorTest,PackedVectorUnpacksToSameValues)204 TEST_P(SecAggVectorTest, PackedVectorUnpacksToSameValues) {
205   std::vector<uint64_t> raw_vector = {};
206   uint64_t modulus = 32;
207   SecAggVector vector(raw_vector, modulus, GetParam());
208   std::string packed_bytes = vector.GetAsPackedBytes();
209   SecAggVector unpacked_vector(packed_bytes, modulus, raw_vector.size(),
210                                GetParam());
211   EXPECT_THAT(raw_vector, Eq(unpacked_vector.GetAsUint64Vector()));
212 
213   // bit_width 1
214   raw_vector = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0};
215   modulus = 2;
216   SecAggVector vector2(raw_vector, modulus, GetParam());
217   packed_bytes = vector2.GetAsPackedBytes();
218   SecAggVector unpacked_vector2(packed_bytes, modulus, raw_vector.size(),
219                                 GetParam());
220   EXPECT_THAT(raw_vector, Eq(unpacked_vector2.GetAsUint64Vector()));
221 
222   // bit_width lines up with byte boundary
223   raw_vector = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
224   modulus = 1ULL << 16;
225   SecAggVector vector3(raw_vector, modulus, GetParam());
226   packed_bytes = vector3.GetAsPackedBytes();
227   SecAggVector unpacked_vector3(packed_bytes, modulus, raw_vector.size(),
228                                 GetParam());
229   EXPECT_THAT(raw_vector, Eq(unpacked_vector3.GetAsUint64Vector()));
230 
231   // bit_width one less than with byte boundary
232   raw_vector = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
233   modulus = 1ULL << 15;
234   SecAggVector vector4(raw_vector, modulus, GetParam());
235   packed_bytes = vector4.GetAsPackedBytes();
236   SecAggVector unpacked_vector4(packed_bytes, modulus, raw_vector.size(),
237                                 GetParam());
238   EXPECT_THAT(raw_vector, Eq(unpacked_vector4.GetAsUint64Vector()));
239 
240   // bit_width one greater than byte boundary
241   raw_vector = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
242   modulus = 1ULL << 17;
243   SecAggVector vector5(raw_vector, modulus, GetParam());
244   packed_bytes = vector5.GetAsPackedBytes();
245   SecAggVector unpacked_vector5(packed_bytes, modulus, raw_vector.size(),
246                                 GetParam());
247   EXPECT_THAT(raw_vector, Eq(unpacked_vector5.GetAsUint64Vector()));
248 
249   // bit_width relatively prime to byte boundary
250   raw_vector.clear();
251   raw_vector.resize(100, 1L);
252   modulus = 1ULL << 19;
253   SecAggVector vector6(raw_vector, modulus, GetParam());
254   packed_bytes = vector6.GetAsPackedBytes();
255   SecAggVector unpacked_vector6(packed_bytes, modulus, raw_vector.size(),
256                                 GetParam());
257   EXPECT_THAT(raw_vector, Eq(unpacked_vector6.GetAsUint64Vector()));
258 
259   // max bit_width, where each array entry has its lowest bit set
260   modulus = 1ULL << 62;
261   SecAggVector vector7(raw_vector, modulus, GetParam());
262   packed_bytes = vector7.GetAsPackedBytes();
263   SecAggVector unpacked_vector7(packed_bytes, modulus, raw_vector.size(),
264                                 GetParam());
265   EXPECT_THAT(raw_vector, Eq(unpacked_vector7.GetAsUint64Vector()));
266 
267   // max bit_width, where each array entry has its highest bit set
268   uint64_t val = SecAggVector::kMaxModulus - 1;
269   raw_vector.clear();
270   raw_vector.resize(100, val);
271   modulus = 1ULL << 62;
272   SecAggVector vector8(raw_vector, modulus, GetParam());
273   packed_bytes = vector8.GetAsPackedBytes();
274   SecAggVector unpacked_vector8(packed_bytes, modulus, raw_vector.size(),
275                                 GetParam());
276   EXPECT_THAT(raw_vector, Eq(unpacked_vector8.GetAsUint64Vector()));
277 
278   // small non power-of-2 modulus
279   raw_vector = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
280   modulus = 11;
281   SecAggVector vector9(raw_vector, modulus, GetParam());
282   packed_bytes = vector9.GetAsPackedBytes();
283   SecAggVector unpacked_vector9(packed_bytes, modulus, raw_vector.size(),
284                                 GetParam());
285   EXPECT_THAT(raw_vector, Eq(unpacked_vector9.GetAsUint64Vector()));
286 
287   // large non power-of-2 modulus
288   raw_vector = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 2636861836188};
289   modulus = 2636861836189;
290   SecAggVector vector10(raw_vector, modulus, GetParam());
291   packed_bytes = vector10.GetAsPackedBytes();
292   SecAggVector unpacked_vector10(packed_bytes, modulus, raw_vector.size(),
293                                  GetParam());
294   EXPECT_THAT(raw_vector, Eq(unpacked_vector10.GetAsUint64Vector()));
295 }
296 
TEST_P(SecAggVectorTest,PackedVectorUnpacksToSameValuesExhaustive_PowerOf2)297 TEST_P(SecAggVectorTest, PackedVectorUnpacksToSameValuesExhaustive_PowerOf2) {
298   for (auto i = 1; i < absl::bit_width(SecAggVector::kMaxModulus - 1); ++i) {
299     for (auto j = 0; j < 1024; ++j) {
300       for (auto val : {1ULL, 1ULL << (i - 1), (1ULL << (i - 1)) - 1,
301                        i & ~((1ULL << i) - 1)}) {
302         auto bit_width = i;
303         uint64_t modulus = 1ULL << bit_width;
304         std::vector<uint64_t> raw_vector(j, val);
305         SecAggVector vector(raw_vector, modulus, GetParam());
306         const auto& packed_bytes = vector.GetAsPackedBytes();
307         SecAggVector unpacked_vector(packed_bytes, modulus, raw_vector.size(),
308                                      GetParam());
309         EXPECT_THAT(raw_vector, Eq(unpacked_vector.GetAsUint64Vector()));
310       }
311     }
312   }
313 }
314 
TEST_P(SecAggVectorTest,PackedVectorUnpacksToSameValuesExhaustive_Arbitrary)315 TEST_P(SecAggVectorTest, PackedVectorUnpacksToSameValuesExhaustive_Arbitrary) {
316   for (auto modulus : kArbitraryModuli) {
317     for (auto j = 0; j < 1024; ++j) {
318       for (uint64_t val :
319            {static_cast<uint64_t>(0UL), static_cast<uint64_t>(1UL),
320             static_cast<uint64_t>((modulus >> 1) - 1),
321             static_cast<uint64_t>(modulus >> 1),
322             static_cast<uint64_t>((modulus >> 1) + 1),
323             static_cast<uint64_t>(modulus - 1)}) {
324         std::vector<uint64_t> raw_vector(j, val);
325         SecAggVector vector(raw_vector, modulus, GetParam());
326         const auto& packed_bytes = vector.GetAsPackedBytes();
327         SecAggVector unpacked_vector(packed_bytes, modulus, raw_vector.size(),
328                                      GetParam());
329         EXPECT_THAT(raw_vector, Eq(unpacked_vector.GetAsUint64Vector()));
330       }
331     }
332   }
333 }
334 
TEST_P(SecAggVectorTest,VerifyPackingExample1)335 TEST_P(SecAggVectorTest, VerifyPackingExample1) {
336   std::vector<uint64_t> correct_unpacked = {1, 3, 7, 15};
337   char correct_packed_array[] = {static_cast<char>(0b01100001),
338                                  static_cast<char>(0b10011100),
339                                  static_cast<char>(0b00000111)};
340   std::string correct_packed(correct_packed_array, 3);
341   uint64_t modulus = 32;
342 
343   SecAggVector from_unpacked_vector(correct_unpacked, modulus, GetParam());
344   const std::string& packed_bytes = from_unpacked_vector.GetAsPackedBytes();
345   EXPECT_THAT(correct_packed, Eq(packed_bytes));
346 
347   SecAggVector from_packed_vector(correct_packed, modulus,
348                                   correct_unpacked.size(), GetParam());
349   EXPECT_THAT(correct_unpacked, Eq(from_packed_vector.GetAsUint64Vector()));
350 }
351 
TEST_P(SecAggVectorTest,VerifyPackingExample2)352 TEST_P(SecAggVectorTest, VerifyPackingExample2) {
353   std::vector<uint64_t> correct_unpacked = {13, 17, 19};
354   char correct_packed_array[] = {
355       static_cast<char>(0b00001101), static_cast<char>(0b00100010),
356       static_cast<char>(0b01001100), static_cast<char>(0b00000000)};
357   std::string correct_packed(correct_packed_array, 4);
358   uint64_t modulus = 512;
359 
360   SecAggVector from_unpacked_vector(correct_unpacked, modulus, GetParam());
361   const std::string& packed_bytes = from_unpacked_vector.GetAsPackedBytes();
362   EXPECT_THAT(correct_packed, Eq(packed_bytes));
363 
364   SecAggVector from_packed_vector(correct_packed, modulus,
365                                   correct_unpacked.size(), GetParam());
366   EXPECT_THAT(correct_unpacked, Eq(from_packed_vector.GetAsUint64Vector()));
367 }
368 
TEST_P(SecAggVectorTest,MoveConstructor)369 TEST_P(SecAggVectorTest, MoveConstructor) {
370   std::vector<uint64_t> raw_vector = {0, 3};
371   SecAggVector vector(raw_vector, 4, GetParam());
372   SecAggVector other(std::move(vector));
373   EXPECT_THAT(other.GetAsUint64Vector(), Eq(raw_vector));
374 }
375 
TEST_P(SecAggVectorTest,MoveAssignment)376 TEST_P(SecAggVectorTest, MoveAssignment) {
377   std::vector<uint64_t> raw_vector = {0, 3};
378   SecAggVector vector(raw_vector, 4, GetParam());
379   SecAggVector other = std::move(vector);
380   EXPECT_THAT(other.GetAsUint64Vector(), Eq(raw_vector));
381 }
382 
TEST_P(SecAggVectorTest,VerifyGetAsPackedBytesDiesAfterMoving)383 TEST_P(SecAggVectorTest, VerifyGetAsPackedBytesDiesAfterMoving) {
384   std::vector<uint64_t> raw_vector = {0, 3};
385   SecAggVector vector(raw_vector, 4, GetParam());
386   SecAggVector other = std::move(vector);
387 
388   ASSERT_DEATH(auto i = vector.GetAsPackedBytes(),  // NOLINT
389                "SecAggVector has no value");
390 }
391 
TEST_P(SecAggVectorTest,VerifyGetAsUint64VectorDiesAfterMoving)392 TEST_P(SecAggVectorTest, VerifyGetAsUint64VectorDiesAfterMoving) {
393   std::vector<uint64_t> raw_vector = {0, 3};
394   SecAggVector vector(raw_vector, 4, GetParam());
395   SecAggVector other = std::move(vector);
396 
397   ASSERT_DEATH(auto vec = vector.GetAsUint64Vector(),  // NOLINT
398                "SecAggVector has no value");
399 }
400 
TEST(SecAggVectorTest,VerifyTakePackedBytesDiesAfterMoving)401 TEST(SecAggVectorTest, VerifyTakePackedBytesDiesAfterMoving) {
402   std::vector<uint64_t> raw_vector = {0, 3};
403   SecAggVector vector(raw_vector, 4);
404   SecAggVector other = std::move(vector);
405 
406   ASSERT_DEATH(auto i = std::move(vector).TakePackedBytes(),  // NOLINT
407                "SecAggVector has no value");
408 }
409 
410 INSTANTIATE_TEST_SUITE_P(Branchless, SecAggVectorTest, ::testing::Bool(),
411                          ::testing::PrintToStringParamName());
412 
TEST(SecAggUnpackedVectorTest,VerifyBasicOperations)413 TEST(SecAggUnpackedVectorTest, VerifyBasicOperations) {
414   SecAggUnpackedVector vector(100, 32);
415   EXPECT_THAT(vector.num_elements(), Eq(100));
416   EXPECT_THAT(vector.modulus(), Eq(32));
417 
418   SecAggUnpackedVector vector2({1, 2, 3}, 32);
419   EXPECT_THAT(vector2.num_elements(), Eq(3));
420   EXPECT_THAT(vector2.modulus(), Eq(32));
421   EXPECT_THAT(vector2.size(), Eq(3));
422   EXPECT_THAT(vector2[1], Eq(2));
423 }
424 
TEST(SecAggUnpackedVectorTest,VerifyMoveConstructor)425 TEST(SecAggUnpackedVectorTest, VerifyMoveConstructor) {
426   SecAggUnpackedVector vector({1, 2, 3}, 32);
427   SecAggUnpackedVector vector2(std::move(vector));
428   EXPECT_THAT(vector.modulus(), Eq(0));  // NOLINT
429   EXPECT_THAT(vector2.num_elements(), Eq(3));
430   EXPECT_THAT(vector2.modulus(), Eq(32));
431   EXPECT_THAT(vector2[2], Eq(3));
432 }
433 
TEST(SecAggUnpackedVectorTest,VerifyConstructorFromSecAggVector)434 TEST(SecAggUnpackedVectorTest, VerifyConstructorFromSecAggVector) {
435   std::vector<uint64_t> raw_vector = {1, 2, 3};
436   SecAggVector vector(raw_vector, 32);
437   SecAggUnpackedVector vector2(vector);
438   EXPECT_THAT(vector2.num_elements(), Eq(3));
439   EXPECT_THAT(vector2.modulus(), Eq(32));
440   EXPECT_THAT(vector2[2], Eq(3));
441 }
442 
TEST(SecAggUnpackedVectorTest,VerifyMoveAssignment)443 TEST(SecAggUnpackedVectorTest, VerifyMoveAssignment) {
444   SecAggUnpackedVector vector({1, 2, 3}, 32);
445   SecAggUnpackedVector vector2 = std::move(vector);
446   EXPECT_THAT(vector.modulus(), Eq(0));  // NOLINT
447   EXPECT_THAT(vector2.num_elements(), Eq(3));
448   EXPECT_THAT(vector2.modulus(), Eq(32));
449   EXPECT_THAT(vector2[0], Eq(1));
450 }
451 
TEST(SecAggUnpackedVectorTest,AddSecAggVectorMap)452 TEST(SecAggUnpackedVectorTest, AddSecAggVectorMap) {
453   auto unpacked_map = std::make_unique<SecAggUnpackedVectorMap>();
454   unpacked_map->emplace("foobar", SecAggUnpackedVector({0, 10, 20, 30}, 32));
455 
456   auto packed_map = std::make_unique<SecAggVectorMap>();
457   packed_map->emplace("foobar", SecAggVector({5, 5, 5, 5}, 32));
458 
459   unpacked_map->Add(*packed_map);
460   EXPECT_THAT(unpacked_map->size(), Eq(1));
461   EXPECT_THAT(unpacked_map->at("foobar"), ElementsAreArray({5, 15, 25, 3}));
462 }
463 
TEST(SecAggUnpackedVectorTest,AddUnpackedSecAggVectorMaps)464 TEST(SecAggUnpackedVectorTest, AddUnpackedSecAggVectorMaps) {
465   SecAggUnpackedVectorMap unpacked_map_1, unpacked_map_2;
466   unpacked_map_1.emplace("foobar", SecAggUnpackedVector({0, 10, 20, 30}, 32));
467   unpacked_map_2.emplace("foobar", SecAggUnpackedVector({5, 5, 5, 5}, 32));
468 
469   auto result =
470       SecAggUnpackedVectorMap::AddMaps(unpacked_map_1, unpacked_map_2);
471   EXPECT_THAT(result->size(), Eq(1));
472   EXPECT_THAT(result->at("foobar"), ElementsAreArray({5, 15, 25, 3}));
473 }
474 
475 }  // namespace
476 }  // namespace secagg
477 }  // namespace fcp
478