Skip to content

Commit 0f6546f

Browse files
Merge pull request #36 from BTreeMap/copilot/optimize-algorithms-and-systems
Fix flaky analytics integration tests for incomplete GeoIP data
2 parents 4d29507 + 1023cdf commit 0f6546f

1 file changed

Lines changed: 59 additions & 16 deletions

File tree

‎tests/analytics_integration.rs‎

Lines changed: 59 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)