@@ -202,10 +202,18 @@ async fn test_storage_integration() {
202202 println ! ( "Country aggregates: {:?}" , agg_country) ;
203203 assert ! ( !agg_country. is_empty( ) ) ;
204204
205- // Verify totals match
205+ // Verify totals match (only counting entries with non-NULL country_code,
206+ // since the aggregate query filters out NULL country codes)
206207 let total_agg: i64 = agg_country. iter ( ) . map ( |a| a. visit_count ) . sum ( ) ;
207- let total_detail: i64 = analytics. iter ( ) . map ( |a| a. visit_count ) . sum ( ) ;
208- assert_eq ! ( total_agg, total_detail) ;
208+ let total_detail_with_country: i64 = analytics
209+ . iter ( )
210+ . filter ( |a| a. country_code . is_some ( ) )
211+ . map ( |a| a. visit_count )
212+ . sum ( ) ;
213+ assert_eq ! (
214+ total_agg, total_detail_with_country,
215+ "Aggregate total should match detail total for entries with country codes"
216+ ) ;
209217}
210218
211219#[ tokio:: test]
@@ -306,20 +314,41 @@ async fn test_aggregation_dimensions() {
306314 ( "9.9.9.9" , 3 ) , // Quad9 US, AS19281 (different ASN)
307315 ( "208.67.222.222" , 2 ) , // OpenDNS US, AS36692 (different ASN)
308316 ] ;
309- for ( ip_str, count) in tests {
310- for _ in 0 ..count {
311- let ip: IpAddr = ip_str. parse ( ) . unwrap ( ) ;
312- let geo = geoip. lookup ( ip) ;
317+
318+ // Track expected counts per dimension based on actual GeoIP data availability
319+ let mut expected_country_count: i64 = 0 ;
320+ let mut expected_asn_count: i64 = 0 ;
321+ let total_visits: i64 = 10 ; // 5 + 3 + 2
322+
323+ for ( ip_str, count) in & tests {
324+ let ip: IpAddr = ip_str. parse ( ) . unwrap ( ) ;
325+ let geo = geoip. lookup ( ip) ;
326+
327+ // Track which dimension data is available
328+ if geo. country_code . is_some ( ) {
329+ expected_country_count += * count as i64 ;
330+ }
331+ if geo. asn . is_some ( ) {
332+ expected_asn_count += * count as i64 ;
333+ }
334+
335+ // Reuse the same geo lookup for all iterations of this IP
336+ for _ in 0 ..* count {
313337 let rec = lynx:: analytics:: AnalyticsRecord {
314338 short_code : "multi" . to_string ( ) ,
315339 timestamp : chrono:: Utc :: now ( ) . timestamp ( ) ,
316- geo_location : geo,
340+ geo_location : geo. clone ( ) ,
317341 client_ip : Some ( ip) ,
318342 } ;
319343 agg. record ( rec) ;
320344 }
321345 }
322346
347+ println ! (
348+ "Expected counts - country: {}, asn: {}, hour: {}" ,
349+ expected_country_count, expected_asn_count, total_visits
350+ ) ;
351+
323352 // Flush to storage
324353 let entries = agg. drain ( ) ;
325354 let records: Vec < _ > = entries
@@ -339,17 +368,31 @@ async fn test_aggregation_dimensions() {
339368 . collect ( ) ;
340369 storage. upsert_analytics_batch ( records) . await . unwrap ( ) ;
341370
342- // Test different dimensions
343- for dim in & [ "country" , "asn" , "hour" ] {
344- let agg = storage
371+ // Test different dimensions with appropriate expected values
372+ // The aggregate query filters out entries with NULL values for the dimension
373+ let dimensions = vec ! [
374+ ( "country" , expected_country_count) ,
375+ ( "asn" , expected_asn_count) ,
376+ ( "hour" , total_visits) , // time_bucket is never NULL
377+ ] ;
378+
379+ for ( dim, expected) in dimensions {
380+ let agg_result = storage
345381 . get_analytics_aggregate ( "multi" , None , None , dim, 10 )
346382 . await
347383 . unwrap ( ) ;
348- println ! ( "Aggregated by {}: {:?}" , dim, agg) ;
349- assert ! ( !agg. is_empty( ) ) ;
350-
351- let total: i64 = agg. iter ( ) . map ( |a| a. visit_count ) . sum ( ) ;
352- assert_eq ! ( total, 10 , "Total should be 10 for {}" , dim) ;
384+ println ! ( "Aggregated by {}: {:?}" , dim, agg_result) ;
385+
386+ // For dimensions with expected data, verify the aggregate is non-empty and totals match
387+ if expected > 0 {
388+ assert ! ( !agg_result. is_empty( ) , "Should have aggregates for {}" , dim) ;
389+ let total: i64 = agg_result. iter ( ) . map ( |a| a. visit_count ) . sum ( ) ;
390+ assert_eq ! (
391+ total, expected,
392+ "Total for {} should match expected (got {}, expected {})" ,
393+ dim, total, expected
394+ ) ;
395+ }
353396 }
354397}
355398
0 commit comments