@@ -158,3 +158,67 @@ TEST(AttributesHashMap, HashConsistencyAcrossStringTypes)
158
158
EXPECT_EQ (hash_c_str, hash_std_str_view);
159
159
#endif
160
160
}
161
+
162
+ TEST (AttributesHashMap, OverflowCardinalityLimitBehavior)
163
+ {
164
+ // Configure a very small limit to exercise overflow logic easily.
165
+ const size_t limit = 4 ; // real attributes limit
166
+ AttributesHashMapWithCustomHash<> map (limit);
167
+
168
+ // We expect to be able to insert exactly 'limit' distinct real attribute sets.
169
+ // After that, further distinct attributes should route to the overflow bucket,
170
+ // which should appear only once regardless of how many additional unique sets arrive.
171
+
172
+ // Insert distinct attributes up to the limit.
173
+ for (size_t i = 0 ; i < limit; ++i)
174
+ {
175
+ MetricAttributes attr = {{" k" , std::to_string (i)}};
176
+ map.GetOrSetDefault (attr, []() { return std::unique_ptr<Aggregation>(new DropAggregation ()); })
177
+ ->Aggregate (static_cast <int64_t >(1 ));
178
+ }
179
+
180
+ // Size should be exactly 'limit' (no overflow yet)
181
+ EXPECT_EQ (map.Size (), limit);
182
+
183
+ // Insert one more distinct attribute; this should not increase the real attributes count
184
+ MetricAttributes overflow_trigger = {{" k" , " overflow" }};
185
+ map.GetOrSetDefault (overflow_trigger,
186
+ []() { return std::unique_ptr<Aggregation>(new DropAggregation ()); })
187
+ ->Aggregate (static_cast <int64_t >(1 ));
188
+
189
+ EXPECT_EQ (map.Size (), limit);
190
+
191
+ // Insert several more unique attributes - size must remain constant (limit)
192
+ for (size_t i = 0 ; i < limit - 1 ; ++i)
193
+ {
194
+ MetricAttributes extra_attr = {{" k" , std::string (" extra" ) + std::to_string (i)}};
195
+ map.GetOrSetDefault (extra_attr,
196
+ []() { return std::unique_ptr<Aggregation>(new DropAggregation ()); })
197
+ ->Aggregate (static_cast <int64_t >(1 ));
198
+ }
199
+ EXPECT_EQ (map.Size (), limit);
200
+
201
+ // Ensure overflow key was actually created and accessible via Get
202
+ EXPECT_NE (map.Get (kOverflowAttributes ), nullptr );
203
+
204
+ // Ensure original real attributes still present
205
+ for (size_t i = 0 ; i < limit - 1 ; ++i)
206
+ {
207
+ MetricAttributes attr = {{" k" , std::to_string (i)}};
208
+ EXPECT_NE (map.Get (attr), nullptr );
6D3F
209
+ }
210
+
211
+ // Copy the hash map to a new map in non-determistic order and verify all entries are present
212
+ AttributesHashMapWithCustomHash<> map_copy (limit);
213
+ map.GetAllEnteries ([&map_copy](const MetricAttributes &attributes, Aggregation &) {
214
+ map_copy.Set (attributes, std::unique_ptr<Aggregation>(new DropAggregation ()));
215
+ return true ;
216
+ });
217
+ EXPECT_EQ (map_copy.Size (), map.Size ());
218
+ EXPECT_NE (map_copy.Get (kOverflowAttributes ), nullptr );
219
+ for (size_t i = 0 ; i < limit - 1 ; ++i)
220
+ {
221
+ MetricAttributes attr = {{" k" , std::to_string (i)}};
222
+ EXPECT_NE (map_copy.Get (attr), nullptr );
223
+ }
224
+ }
0 commit comments