@@ -22,7 +22,7 @@ def test_time_inconsistencies_basic(db, fastpath, fastpath_data_time_inconsisten
2222 )
2323
2424 result = db .execute (
25- "SELECT ts, type, probe_cc, probe_asn, details FROM faulty_measurements WHERE type IN ('time_inconsistency_future', 'time_inconsistency_past') "
25+ "SELECT ts, type, probe_cc, probe_asn, details FROM faulty_measurements WHERE type LIKE 'time_inconsistency%' "
2626 )
2727 assert len (result ) > 0 , "Missing time inconsistency anomalies"
2828
@@ -64,7 +64,7 @@ def test_time_inconsistencies_no_anomalies(
6464 )
6565
6666 # No anomalies expected
67- result = db .execute ("SELECT type FROM faulty_measurements WHERE type IN ('time_inconsistency_future', 'time_inconsistency_past') " )
67+ result = db .execute ("SELECT type FROM faulty_measurements WHERE type LIKE 'time_inconsistency%' " )
6868 assert len (result ) == 0 , f"Unexpected anomalies: { len (result )} = { result } "
6969
7070
@@ -86,7 +86,7 @@ def test_time_inconsistencies_time_range_filtering(
8686 )
8787
8888 # No events expected
89- results = db .execute ("SELECT type FROM faulty_measurements WHERE type IN ('time_inconsistency_future', 'time_inconsistency_past') " )
89+ results = db .execute ("SELECT type FROM faulty_measurements WHERE type LIKE 'time_inconsistency%' " )
9090 assert len (results ) == 0 , f"Too many results: { len (results )} - { results } "
9191
9292
@@ -108,7 +108,7 @@ def test_time_inconsistencies_threshold_boundary(
108108 )
109109
110110 result = db .execute (
111- "SELECT ts, type, probe_cc, probe_asn, details FROM faulty_measurements WHERE type IN ('time_inconsistency_future', 'time_inconsistency_past') "
111+ "SELECT ts, type, probe_cc, probe_asn, details FROM faulty_measurements WHERE type LIKE 'time_inconsistency%' "
112112 )
113113 assert len (result ) > 0 , "Expected time inconsistency anomalies"
114114
@@ -119,3 +119,45 @@ def test_time_inconsistencies_threshold_boundary(
119119 assert abs (details ["diff_seconds" ]) >= future_threshold , f"invalid threshold: { details ['diff_seconds' ]} "
120120 else :
121121 assert details ["diff_seconds" ] >= past_threshold , f"invalid threshold: { details ['diff_seconds' ]} "
122+
123+
124+ def test_time_inconsistencies_future_and_past (
125+ db , fastpath , fastpath_data_time_inconsistencies , clean_faulty_measurements
126+ ):
127+ """
128+ Test that we detect both future and past time inconsistencies.
129+ """
130+ future_threshold = 3600 # 1 hour
131+ past_threshold = 3600 # 1 hour
132+
133+ time_inconsistencies .run_time_inconsistencies_analysis (
134+ clickhouse_url = db .clickhouse_url ,
135+ start_time = START_TIME ,
136+ end_time = END_TIME ,
137+ future_threshold = future_threshold ,
138+ past_threshold = past_threshold ,
139+ )
140+
141+ result = db .execute (
142+ "SELECT ts, type, probe_cc, probe_asn, details FROM faulty_measurements WHERE type LIKE 'time_inconsistency%'"
143+ )
144+
145+ future_anomalies = [row for row in result if row [1 ] == "time_inconsistency_future" ]
146+ past_anomalies = [row for row in result if row [1 ] == "time_inconsistency_past" ]
147+
148+ assert len (future_anomalies ) > 0 , "Should have at least one future anomaly"
149+ assert len (past_anomalies ) > 0 , "Should have at least one past anomaly"
150+
151+ # future anomalies should have negative diff_seconds
152+ for row in future_anomalies :
153+ _ , _ , _ , _ , details_str = row
154+ details = orjson .loads (details_str )
155+ assert details ["diff_seconds" ] < 0 , f"Unexpected diff_seconds: { details ['diff_seconds' ]} "
156+ assert abs (details ["diff_seconds" ]) >= future_threshold
157+
158+ # past anomalies should have positive diff_seconds
159+ for row in past_anomalies :
160+ _ , _ , _ , _ , details_str = row
161+ details = orjson .loads (details_str )
162+ assert details ["diff_seconds" ] > 0 , f"Unexpected diff_seconds: { details ['diff_seconds' ]} "
163+ assert details ["diff_seconds" ] >= past_threshold
0 commit comments