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