Skip to content

Commit 80f53d6

Browse files
committed
Add test for OOO events, and remove from bench
1 parent a784419 commit 80f53d6

4 files changed

Lines changed: 94 additions & 14 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ clap = { version = "4.5.50", features = ["derive"] }
1212
anyhow = "1.0"
1313
log = "0.4"
1414
env_logger = "0.11.8"
15+
libc = "0.2"
1516

1617
[dev-dependencies]
1718
criterion = { version = "0.7", features = ["html_reports"] }

benches/benchmarks.rs

Lines changed: 63 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,84 @@ use mouse_scroll_daemon::{AnxiousParams, AnxiousState, apply_anxious_scroll, pro
44
use std::hint::black_box;
55
use std::time::{Duration, SystemTime, UNIX_EPOCH};
66

7+
// Helper function to create InputEvent with specific timestamp
8+
// This replicates the internal logic from evdev crate
9+
fn create_input_event_with_timestamp(
10+
event_type: EventType,
11+
code: u16,
12+
value: i32,
13+
timestamp: SystemTime,
14+
) -> InputEvent {
15+
let (sign, dur) = match timestamp.duration_since(UNIX_EPOCH) {
16+
Ok(dur) => (1, dur),
17+
Err(e) => (-1, e.duration()),
18+
};
19+
20+
let raw = libc::input_event {
21+
time: libc::timeval {
22+
tv_sec: dur.as_secs() as libc::time_t * sign,
23+
tv_usec: dur.subsec_micros() as libc::suseconds_t,
24+
},
25+
type_: event_type.0,
26+
code,
27+
value,
28+
};
29+
InputEvent::from(raw)
30+
}
31+
732
// Helper function to create AnxiousState with a specific timestamp
833
fn create_anxious_state_with_time(prev_time: SystemTime) -> AnxiousState {
934
AnxiousState { prev_time }
1035
}
1136

1237
fn create_test_events() -> Vec<InputEvent> {
38+
let base_time = UNIX_EPOCH + Duration::from_secs(1000000000);
1339
vec![
14-
// High-res wheel events (these get processed) - with proper timestamps
15-
InputEvent::new_now(
16-
EventType::RELATIVE.0,
40+
// High-res wheel events (these get processed) - simulate realistic scroll sequence
41+
create_input_event_with_timestamp(
42+
EventType::RELATIVE,
1743
RelativeAxisCode::REL_WHEEL_HI_RES.0,
1844
120,
45+
base_time + Duration::from_millis(0),
1946
),
20-
InputEvent::new_now(
21-
EventType::RELATIVE.0,
47+
create_input_event_with_timestamp(
48+
EventType::RELATIVE,
2249
RelativeAxisCode::REL_WHEEL_HI_RES.0,
2350
240,
51+
base_time + Duration::from_millis(10),
2452
),
25-
InputEvent::new_now(
26-
EventType::RELATIVE.0,
53+
create_input_event_with_timestamp(
54+
EventType::RELATIVE,
2755
RelativeAxisCode::REL_WHEEL_HI_RES.0,
2856
360,
57+
base_time + Duration::from_millis(20),
2958
),
3059
// Regular wheel events (these get dropped)
31-
InputEvent::new_now(EventType::RELATIVE.0, RelativeAxisCode::REL_WHEEL.0, 1),
32-
InputEvent::new_now(EventType::RELATIVE.0, RelativeAxisCode::REL_WHEEL.0, -1),
60+
create_input_event_with_timestamp(
61+
EventType::RELATIVE,
62+
RelativeAxisCode::REL_WHEEL.0,
63+
1,
64+
base_time + Duration::from_millis(30),
65+
),
66+
create_input_event_with_timestamp(
67+
EventType::RELATIVE,
68+
RelativeAxisCode::REL_WHEEL.0,
69+
-1,
70+
base_time + Duration::from_millis(40),
71+
),
3372
// Other events (these get passed through)
34-
InputEvent::new_now(EventType::RELATIVE.0, RelativeAxisCode::REL_X.0, 10),
35-
InputEvent::new_now(EventType::RELATIVE.0, RelativeAxisCode::REL_Y.0, 5),
73+
create_input_event_with_timestamp(
74+
EventType::RELATIVE,
75+
RelativeAxisCode::REL_X.0,
76+
10,
77+
base_time + Duration::from_millis(50),
78+
),
79+
create_input_event_with_timestamp(
80+
EventType::RELATIVE,
81+
RelativeAxisCode::REL_Y.0,
82+
5,
83+
base_time + Duration::from_millis(60),
84+
),
3685
]
3786
}
3887

@@ -131,10 +180,10 @@ fn benchmark_event_processing(c: &mut Criterion) {
131180
.take(size)
132181
.collect::<Vec<_>>();
133182
let params = AnxiousParams::default();
183+
let base_time = UNIX_EPOCH + Duration::from_secs(1000000000);
134184

135185
b.iter(|| {
136-
// Create a simple state that won't cause timestamp issues
137-
let base_time = UNIX_EPOCH + Duration::from_secs(1000000000);
186+
// Create a state with a timestamp before the events to ensure proper ordering
138187
let mut state_clone = create_anxious_state_with_time(base_time);
139188

140189
// Use the actual process_events function - this is the real hot path
@@ -154,6 +203,7 @@ fn benchmark_event_processing(c: &mut Criterion) {
154203
let base_time = UNIX_EPOCH + Duration::from_secs(1000000000);
155204

156205
b.iter(|| {
206+
// Create a state with a timestamp before the events to ensure proper ordering
157207
let mut state_clone = create_anxious_state_with_time(base_time);
158208
// Use the actual process_events function with proper timestamps
159209
black_box(process_events(

src/lib.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,14 @@ pub fn apply_anxious_scroll(
5050
anxious_params: &AnxiousParams,
5151
anxious_state: &mut AnxiousState,
5252
) -> i32 {
53-
let elapsed_time = timestamp.duration_since(anxious_state.prev_time).unwrap();
53+
let elapsed_time = match timestamp.duration_since(anxious_state.prev_time) {
54+
Ok(duration) => duration,
55+
Err(_) => {
56+
// If timestamp is earlier than prev_time (clock adjustment, out-of-order events, etc.),
57+
// use a slow scroll duration (1 second) to treat it as a gentle scroll
58+
std::time::Duration::from_millis(1000)
59+
}
60+
};
5461
anxious_state.prev_time = timestamp;
5562

5663
let vel = value.abs() / elapsed_time.as_millis() as f32;
@@ -173,6 +180,27 @@ mod tests {
173180
assert!(result > 0);
174181
}
175182

183+
#[test]
184+
fn test_out_of_order_events() {
185+
let params = AnxiousParams::default();
186+
let base_time = UNIX_EPOCH + Duration::from_secs(1000000000);
187+
let mut state = create_test_state_with_time(base_time + Duration::from_millis(100));
188+
189+
// Test with out-of-order event (timestamp earlier than prev_time)
190+
let result = apply_anxious_scroll(
191+
120.0,
192+
base_time + Duration::from_millis(50), // Earlier than prev_time
193+
&params,
194+
&mut state,
195+
);
196+
// Should not panic and should return a reasonable value
197+
// The fallback duration (1000ms) should result in slow scroll behavior
198+
assert!(result > 0);
199+
// With 1000ms duration, this should behave like a slow scroll (low sensitivity)
200+
assert!(result < 2000); // Should be reasonable for slow scroll
201+
}
202+
203+
176204
#[test]
177205
fn test_parameter_configurations() {
178206
let base_time = UNIX_EPOCH + Duration::from_secs(1000000000);

0 commit comments

Comments
 (0)