• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2023 Google LLC.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 use enums_rust_proto::{test_map_with_nested_enum, TestMapWithNestedEnum};
9 use googletest::prelude::*;
10 use map_unittest_rust_proto::{MapEnum, TestMap, TestMapWithMessages};
11 use paste::paste;
12 use protobuf::ProtoString;
13 use std::collections::HashMap;
14 use unittest_rust_proto::TestAllTypes;
15 
16 macro_rules! generate_map_primitives_tests {
17     (
18         $(($k_type:ty, $v_type:ty, $k_field:ident, $v_field:ident,
19            $k_nonzero:expr, $v_nonzero:expr $(,)?)),*
20         $(,)?
21     ) => {
22         paste! { $(
23             #[gtest]
24             fn [< test_map_ $k_field _ $v_field >]() {
25                 let mut msg = TestMap::new();
26                 assert_that!(msg.[< map_ $k_field _ $v_field >]().len(), eq(0));
27                 assert_that!(
28                     msg.[< map_ $k_field _ $v_field >](),
29                     elements_are![]
30                 );
31                 assert_that!(
32                     msg.[< map_ $k_field _ $v_field >]().keys().collect::<Vec<_>>(),
33                     elements_are![]
34                 );
35                 assert_that!(
36                     msg.[< map_ $k_field _ $v_field >]().values().collect::<Vec<_>>(),
37                     elements_are![]
38                 );
39                 let k = <$k_type>::default();
40                 let v = <$v_type>::default();
41                 assert_that!(msg.[< map_ $k_field _ $v_field _mut>]().insert(k, v), eq(true));
42                 assert_that!(msg.[< map_ $k_field _ $v_field _mut>]().insert(k, v), eq(false));
43                 assert_that!(msg.[< map_ $k_field _ $v_field >]().len(), eq(1));
44                 assert_that!(
45                     msg.[< map_ $k_field _ $v_field >](),
46                     elements_are![eq((k, v))]
47                 );
48                 assert_that!(
49                     msg.[< map_ $k_field _ $v_field >]().keys().collect::<Vec<_>>(),
50                     elements_are![eq(&k)]
51                 );
52                 assert_that!(
53                     msg.[< map_ $k_field _ $v_field >]().values().collect::<Vec<_>>(),
54                     elements_are![eq(&v)]
55                 );
56 
57                 let k2: $k_type = $k_nonzero;
58                 let v2: $v_type = $v_nonzero;
59                 assert_that!(msg.[< map_ $k_field _ $v_field _mut>]().insert(k2, v2), eq(true));
60                 assert_that!(msg.[< map_ $k_field _ $v_field >](), len(eq(2)));
61                 assert_that!(
62                     msg.[< map_ $k_field _ $v_field >](),
63                     unordered_elements_are![
64                         eq((k, v)),
65                         eq((k2, v2)),
66                     ]
67                 );
68                 assert_that!(
69                     msg.[< map_ $k_field _ $v_field >]().keys().collect::<Vec<_>>(),
70                     unordered_elements_are![eq(&k), eq(&k2)]
71                 );
72                 assert_that!(
73                     msg.[< map_ $k_field _ $v_field >]().values().collect::<Vec<_>>(),
74                     unordered_elements_are![eq(&v), eq(&v2)]
75                 );
76             }
77         )* }
78     };
79 }
80 
81 generate_map_primitives_tests!(
82     (i32, i32, int32, int32, 1, 1),
83     (i64, i64, int64, int64, 1, 1),
84     (u32, u32, uint32, uint32, 1, 1),
85     (u64, u64, uint64, uint64, 1, 1),
86     (i32, i32, sint32, sint32, 1, 1),
87     (i64, i64, sint64, sint64, 1, 1),
88     (u32, u32, fixed32, fixed32, 1, 1),
89     (u64, u64, fixed64, fixed64, 1, 1),
90     (i32, i32, sfixed32, sfixed32, 1, 1),
91     (i64, i64, sfixed64, sfixed64, 1, 1),
92     (i32, f32, int32, float, 1, 1.),
93     (i32, f64, int32, double, 1, 1.),
94     (bool, bool, bool, bool, true, true),
95     (i32, &[u8], int32, bytes, 1, b"foo"),
96     (i32, MapEnum, int32, enum, 1, MapEnum::Baz),
97 );
98 
99 #[gtest]
collect_as_hashmap()100 fn collect_as_hashmap() {
101     // Highlights conversion from protobuf map to hashmap.
102     let mut msg = TestMap::new();
103     msg.map_string_string_mut().insert("hello", "world");
104     msg.map_string_string_mut().insert("fizz", "buzz");
105     msg.map_string_string_mut().insert("boo", "blah");
106     let hashmap: HashMap<String, String> =
107         msg.map_string_string().iter().map(|(k, v)| (k.to_string(), v.to_string())).collect();
108     assert_that!(
109         hashmap,
110         unordered_elements_are![
111             (eq("hello"), eq("world")),
112             (eq("fizz"), eq("buzz")),
113             (eq("boo"), eq("blah")),
114         ]
115     );
116 }
117 
118 #[gtest]
test_string_maps()119 fn test_string_maps() {
120     let mut msg = TestMap::new();
121     msg.map_string_string_mut().insert("hello", "world");
122     msg.map_string_string_mut().insert("fizz", "buzz");
123     assert_that!(msg.map_string_string().len(), eq(2));
124     assert_that!(msg.map_string_string().get("fizz").unwrap(), eq("buzz"));
125     assert_that!(msg.map_string_string().get("not found"), eq(None));
126     msg.map_string_string_mut().clear();
127     assert_that!(msg.map_string_string().len(), eq(0));
128 }
129 
130 #[gtest]
test_nested_enum_maps()131 fn test_nested_enum_maps() {
132     // Verify that C++ thunks are generated and are with the right name for strings
133     TestMapWithNestedEnum::new()
134         .string_map_mut()
135         .insert("foo", test_map_with_nested_enum::inner_nested::NestedEnum::Foo);
136 }
137 
138 #[gtest]
test_bytes_and_string_copied()139 fn test_bytes_and_string_copied() {
140     let mut msg = TestMap::new();
141 
142     {
143         // Ensure val is dropped after inserting into the map.
144         let mut key = String::from("hello");
145         let mut val = String::from("world");
146         msg.map_string_string_mut().insert(key.as_str(), &val);
147         msg.map_int32_bytes_mut().insert(1, val.as_bytes());
148         // Validate that map keys are copied by mutating the originals.
149         key.replace_range(.., "ayo");
150         val.replace_range(.., "wOrld");
151     }
152 
153     assert_that!(msg.map_string_string_mut().get("hello").unwrap(), eq("world"));
154     assert_that!(msg.map_string_string(), unordered_elements_are![(eq("hello"), eq("world"))]);
155     assert_that!(msg.map_int32_bytes_mut().get(1).unwrap(), eq(b"world"));
156 }
157 
158 #[gtest]
test_map_setter()159 fn test_map_setter() {
160     // Set Map
161     {
162         let mut msg = TestMap::new();
163         let mut map = protobuf::Map::<ProtoString, ProtoString>::new();
164         map.as_mut().copy_from([("hello", "world"), ("fizz", "buzz")]);
165         msg.set_map_string_string(map);
166         assert_that!(
167             msg.map_string_string(),
168             unordered_elements_are![
169                 eq(("hello".into(), "world".into())),
170                 eq(("fizz".into(), "buzz".into()))
171             ]
172         );
173     }
174 
175     // Set MapView
176     {
177         let mut msg = TestMap::new();
178         let mut map = protobuf::Map::<ProtoString, ProtoString>::new();
179         map.as_mut().copy_from([("hello", "world"), ("fizz", "buzz")]);
180         msg.set_map_string_string(map.as_view());
181         assert_that!(
182             msg.map_string_string(),
183             unordered_elements_are![
184                 eq(("hello".into(), "world".into())),
185                 eq(("fizz".into(), "buzz".into()))
186             ]
187         );
188     }
189 
190     // Set MapMut
191     {
192         let mut msg = TestMap::new();
193         let mut map = protobuf::Map::<ProtoString, ProtoString>::new();
194         map.as_mut().copy_from([("hello", "world"), ("fizz", "buzz")]);
195         msg.set_map_string_string(map.as_mut());
196         assert_that!(
197             msg.map_string_string(),
198             unordered_elements_are![
199                 eq(("hello".into(), "world".into())),
200                 eq(("fizz".into(), "buzz".into()))
201             ]
202         );
203 
204         // The original map should remain unchanged.
205         assert_that!(
206             map.as_view(),
207             unordered_elements_are![
208                 eq(("hello".into(), "world".into())),
209                 eq(("fizz".into(), "buzz".into()))
210             ]
211         );
212     }
213 }
214 
215 #[test]
test_map_creation_with_message_values()216 fn test_map_creation_with_message_values() {
217     // Maps are usually created and owned by a parent message, but let's verify that
218     // we can successfully create and destroy them independently.
219     macro_rules! test_for_each_key {
220         ($($key_t:ty, $key:expr;)*) => {
221             $(
222                 let msg = TestAllTypes::new();
223                 let mut map = protobuf::Map::<$key_t, TestAllTypes>::new();
224                 map.as_mut().insert($key, msg);
225                 assert_that!(map.as_view().len(), eq(1));
226             )*
227         }
228     }
229 
230     test_for_each_key!(
231         i32, -5;
232         u32, 13u32;
233         i64, 7;
234         u64, 11u64;
235         bool, false;
236         ProtoString, "looooooooooooooooooooooooong string";
237     );
238 }
239 
240 #[test]
test_map_clearing_with_message_values()241 fn test_map_clearing_with_message_values() {
242     macro_rules! test_for_each_key {
243         ($($key_t:ty, $key:expr;)*) => {
244             $(
245                 let msg = TestAllTypes::new();
246                 let mut map = protobuf::Map::<$key_t, TestAllTypes>::new();
247                 map.as_mut().insert($key, msg);
248                 assert_that!(map.as_view().len(), eq(1));
249                 map.as_mut().clear();
250                 assert_that!(map.as_view().len(), eq(0));
251             )*
252         }
253     }
254 
255     test_for_each_key!(
256         i32, -5;
257         u32, 13u32;
258         i64, 7;
259         u64, 11u64;
260         bool, false;
261         ProtoString, "looooooooooooooooooooooooong string";
262     );
263 }
264 
265 macro_rules! generate_map_with_msg_values_tests {
266     (
267         $(($k_field:ident, $k_nonzero:expr, $k_other:expr $(,)?)),*
268         $(,)?
269     ) => {
270         paste! { $(
271             #[gtest]
272             fn [< test_map_ $k_field _all_types >]() {
273                 // We need to cover the following upb/c++ thunks:
274                 // TODO - b/323883851: Add test once Map::new is public.
275                 // * new
276                 // * free (covered implicitly by drop)
277                 // * clear, size, insert, get, remove, iter, iter_next (all covered below)
278                 let mut msg = TestMapWithMessages::new();
279                 assert_that!(msg.[< map_ $k_field _all_types >]().len(), eq(0));
280                 assert_that!(msg.[< map_ $k_field _all_types >]().get($k_nonzero), none());
281                 // this block makes sure `insert` copies/moves, not borrows.
282                 {
283                     let mut msg_val = TestAllTypes::new();
284                     msg_val.set_optional_int32(1001);
285                     assert_that!(
286                         msg
287                             .[< map_ $k_field _all_types_mut >]()
288                             .insert($k_nonzero, msg_val.as_view()),
289                         eq(true),
290                         "`insert` should return true when key was inserted."
291                     );
292                     assert_that!(
293                         msg
294                             .[< map_ $k_field _all_types_mut >]()
295                             .insert($k_nonzero, msg_val.as_view()),
296                         eq(false),
297                         "`insert` should return false when key was already present."
298 
299                     );
300                 }
301 
302                 assert_that!(
303                     msg.[< map_ $k_field _all_types >]().len(),
304                     eq(1),
305                     "`size` thunk should return correct len.");
306 
307                 assert_that!(
308                     msg.[< map_ $k_field _all_types >]().get($k_nonzero),
309                     some(anything()),
310                     "`get` should return Some when key present.");
311                 assert_that!(
312                     msg.[< map_ $k_field _all_types >]().get($k_nonzero).unwrap().optional_int32(),
313                     eq(1001));
314                 assert_that!(
315                     msg.[< map_ $k_field _all_types >]().get($k_other),
316                     none(),
317                     "`get` should return None when key missing.");
318 
319                 msg.[< map_ $k_field _all_types_mut >]().clear();
320                 assert_that!(
321                     msg.[< map_ $k_field _all_types >]().len(),
322                     eq(0),
323                     "`clear` should drop all elements.");
324 
325 
326                 assert_that!(
327                     msg.[< map_ $k_field _all_types_mut >]().insert($k_nonzero, TestAllTypes::new()),
328                     eq(true));
329                 assert_that!(
330                     msg.[< map_ $k_field _all_types_mut >]().remove($k_nonzero),
331                     eq(true),
332                     "`remove` should return true when key was present.");
333                 assert_that!(msg.[< map_ $k_field _all_types >](), empty());
334                 assert_that!(
335                     msg.[< map_ $k_field _all_types_mut >]().remove($k_nonzero),
336                     eq(false),
337                     "`remove` should return false when key was missing.");
338 
339                 // empty iter
340                 // assert_that!(
341                 //     msg.[< map_ $k_field _all_types_mut >]().iter().collect::<Vec<_>>(),
342                 //     elements_are![],
343                 //     "`iter` should work when empty."
344                 // );
345                 assert_that!(
346                     msg.[< map_ $k_field _all_types_mut >]().keys().count(),
347                     eq(0),
348                     "`iter` should work when empty."
349                 );
350                 assert_that!(
351                     msg.[< map_ $k_field _all_types_mut >]().values().count(),
352                     eq(0),
353                     "`iter` should work when empty."
354                 );
355 
356                 // single element iter
357                 assert_that!(
358                     msg.[< map_ $k_field _all_types_mut >]().insert($k_nonzero, TestAllTypes::new()),
359                     eq(true));
360                 // assert_that!(
361                 //     msg.[< map_ $k_field _all_types >]().iter().collect::<Vec<_>>(),
362                 //     unordered_elements_are![
363                 //         eq(($k_nonzero, anything())),
364                 //     ]
365                 // );
366                 assert_that!(
367                     msg.[< map_ $k_field _all_types >]().keys().collect::<Vec<_>>(),
368                     unordered_elements_are![eq(&$k_nonzero)]
369                 );
370                 assert_that!(
371                     msg.[< map_ $k_field _all_types >]().values().count(),
372                     eq(1));
373 
374 
375                 // 2 element iter
376                 assert_that!(
377                     msg
378                         .[< map_ $k_field _all_types_mut >]()
379                         .insert($k_other, TestAllTypes::new()),
380                     eq(true));
381 
382                 assert_that!(
383                     msg.[< map_ $k_field _all_types >](),
384                     len(eq(2))
385                 );
386                 assert_that!(
387                     msg.[< map_ $k_field _all_types >]().keys().collect::<Vec<_>>(),
388                     unordered_elements_are![eq(&$k_nonzero), eq(&$k_other)]
389                 );
390                 assert_that!(
391                     msg.[< map_ $k_field _all_types >]().values().count(),
392                     eq(2)
393                 );
394             }
395         )* }
396     }
397 }
398 
399 generate_map_with_msg_values_tests!(
400     (int32, 1i32, 2i32),
401     (int64, 1i64, 2i64),
402     (uint32, 1u32, 2u32),
403     (uint64, 1u64, 2u64),
404     (sint32, 1, 2),
405     (sint64, 1, 2),
406     (fixed32, 1u32, 2u32),
407     (fixed64, 1u64, 2u64),
408     (sfixed32, 1, 2),
409     (sfixed64, 1, 2),
410     (bool, true, false),
411     (string, "foo", "bar"),
412 );
413