AtlatestRepositorysigil-wm

sigil-wm / tree / testdeadlines.c

1/* SPDX-License-Identifier: BSD-3-Clause
2 * Real Wayland loop/timers and existing expiry handlers. Protocol sends at the
3 * lock/popup/configuration boundary are replaced by observation-only fixtures. */
4#define listen socket_listen
5#include <sys/socket.h>
6#undef listen
7#define wlr_session_lock_v1_send_locked fixture_lock_send
8#define wlr_xdg_popup_destroy fixture_popup_destroy
9#define wlr_output_configuration_v1_send_failed fixture_configuration_failed
10#define wlr_output_configuration_v1_destroy fixture_configuration_destroy
11#include "../src/c/host.c"
12#include <assert.h>
13static unsigned lock_acks,popup_expired,configuration_failed;
14static struct popup *fixture_popup;
15void fixture_lock_send(struct wlr_session_lock_v1 *lock) { (void)lock; lock_acks++; }
16void fixture_popup_destroy(struct wlr_xdg_popup *popup) {
17 (void)popup; popup_expired++; wl_list_remove(&fixture_popup->link); free(fixture_popup); fixture_popup=NULL;
19void fixture_configuration_failed(struct wlr_output_configuration_v1 *configuration) {
20 (void)configuration; configuration_failed++;
22void fixture_configuration_destroy(struct wlr_output_configuration_v1 *configuration) { (void)configuration; }
23static void initialize(struct server *s) {
24 wl_list_init(&s->outputs); wl_list_init(&s->views); wl_list_init(&s->keyboards);
25 wl_list_init(&s->devices); wl_list_init(&s->pixels); wl_list_init(&s->permissions);
26 wl_list_init(&s->data_requests); wl_list_init(&s->output_controls);
27 wl_list_init(&s->pending_outputs); wl_list_init(&s->output_requests);
28 wl_list_init(&s->constraints); wl_list_init(&s->pointer_hints);
29 wl_list_init(&s->decorations); wl_list_init(&s->legacy_decorations);
30 wl_list_init(&s->inhibitors); wl_list_init(&s->popups);
31 s->generation=1;
33static void selection(void) {
34 struct server s={0}; initialize(&s);
35 uint64_t now=1000;
36 assert(native_deadline(&s,now)==0);
37 s.plan=(void *)1; s.plan_deadline=1030; assert(native_deadline(&s,now)==1030); s.plan=NULL;
38 s.scene_update_deadline=1040; assert(native_deadline(&s,now)==1040); s.scene_update_deadline=0;
39 s.lock_state=1; s.lock_deadline=1050; assert(native_deadline(&s,now)==1050); s.lock_state=0;
40 s.has_pending_motion=true; s.motion_last=1000; s.motion_period=60;
41 assert(native_deadline(&s,now)==1060); s.has_pending_motion=false;
42 s.input_write=3;
43 s.inputs[0]=(struct input){.kind=30,.deadline=UINT64_MAX};
44 s.inputs[1]=(struct input){.kind=30,.native=true,.ready=true,.order_deadline=1007};
45 s.inputs[2]=(struct input){.kind=30,.deadline=999}; /* blocked behind the bound head */
46 assert(native_deadline(&s,now)==1007);
47 s.inputs[1].completed=true; assert(native_deadline(&s,now)==0);
48 s.inputs[2]=(struct input){.kind=32,.deadline=1003}; assert(native_deadline(&s,now)==1003);
49 s.input_write=0;
50 struct permission p={.deadline=1010}; wl_list_insert(&s.permissions,&p.link);
51 assert(native_deadline(&s,now)==1010); wl_list_remove(&p.link);
52 struct data_request d={.deadline=1011}; wl_list_insert(&s.data_requests,&d.link);
53 assert(native_deadline(&s,now)==1011); wl_list_remove(&d.link);
54 struct output o={.id=7}; wl_list_insert(&s.outputs,&o.link);
55 o.scene_retry_at=1012; assert(native_deadline(&s,now)==1012); o.scene_retry_at=0;
56 struct output_control_request c={.output=7,.deadline=1012}; wl_list_insert(&s.output_controls,&c.link);
57 assert(native_deadline(&s,now)==1012); c.resolved=true;
58 assert(native_deadline(&s,now)==0); wl_list_remove(&c.link); wl_list_remove(&o.link);
59 struct output_configuration_request r={.deadline=1013}; wl_list_insert(&s.output_requests,&r.link);
60 assert(native_deadline(&s,now)==1013); s.output_revision=1;
61 assert(native_deadline(&s,now)==now); wl_list_remove(&r.link); s.output_revision=0;
62 struct pointer_hint h={.deadline=1014,.generation=1}; wl_list_insert(&s.pointer_hints,&h.link);
63 assert(native_deadline(&s,now)==1014); h.generation=0;
64 assert(native_deadline(&s,now)==now); wl_list_remove(&h.link);
65 struct popup popup={.deadline=1015}; wl_list_insert(&s.popups,&popup.link);
66 assert(native_deadline(&s,now)==1015); wl_list_remove(&popup.link);
67 atomic_store(&bridge.input_resync,true); assert(native_deadline(&s,now)==now);
68 atomic_store(&bridge.input_resync,false);
70static uint64_t deadline_start;
71static void wait_for_tick(struct server *s) {
72 uint64_t ticks=atomic_load(&bridge.timer_wakes);
73 deadline_start=now_ms();
74 while(atomic_load(&bridge.timer_wakes)==ticks) {
75 assert(now_ms()-deadline_start<500);
76 assert(dispatch_native_once(s,100)==0);
77 }
78 assert(now_ms()-deadline_start>=15 && now_ms()-deadline_start<150);
80struct repeating { struct wl_event_source *timer; unsigned count; };
81static int repeat_tick(void *data) {
82 struct repeating *repeat=data;
83 repeat->count++;
84 if(repeat->count<4) wl_event_source_timer_update(repeat->timer,8);
85 return 0;
87static void idle_admit(void *data) { ((struct server *)data)->scene_update_deadline=now_ms()+25; }
88int main(void) {
89 selection();
90 struct server s={0}; initialize(&s);
91 s.display=wl_display_create(); assert(s.display);
92 s.cursor=wlr_cursor_create(); assert(s.cursor);
93 s.scene=wlr_scene_create(); assert(s.scene);
94 s.normal=wlr_scene_tree_create(&s.scene->tree); assert(s.normal);
95 s.seat=wlr_seat_create(s.display,"deadline-test"); assert(s.seat);
96 struct wl_event_loop *loop=wl_display_get_event_loop(s.display);
97 s.timer=wl_event_loop_add_timer(loop,timer_tick,&s); assert(s.timer);
98 bridge.event_fd=eventfd(0,EFD_NONBLOCK|EFD_CLOEXEC); assert(bridge.event_fd>=0);
99 uint64_t start=now_ms();
100 assert(dispatch_native_once(&s,60)==0);
101 assert(now_ms()-start>=55 && atomic_load(&bridge.timer_wakes)==0 && s.timer_deadline==0);
102 struct repeating repeat={0}; repeat.timer=wl_event_loop_add_timer(loop,repeat_tick,&repeat);
103 wl_event_source_timer_update(repeat.timer,8);
104 while(repeat.count<4) assert(dispatch_native_once(&s,100)==0);
105 assert(atomic_load(&bridge.timer_wakes)==0); /* independent repeat timer survives */
106 wl_event_source_remove(repeat.timer);
107 wl_event_loop_add_idle(loop,idle_admit,&s);
108 wait_for_tick(&s); assert(s.scene_update_deadline==0);
109 s.scene_update_deadline=now_ms()+20; assert(rearm_deadline(&s,now_ms())==0);
110 s.scene_update_deadline=0; assert(rearm_deadline(&s,now_ms())==0);
111 uint64_t ticks=atomic_load(&bridge.timer_wakes);
112 assert(dispatch_native_once(&s,50)==0 && atomic_load(&bridge.timer_wakes)==ticks);
113 /* Bound decision expires once, then waits for its explicit reply. */
114 s.inputs[0]=(struct input){.kind=30,.notified=true,.origin=1,.deadline=now_ms()+25}; s.input_write=1;
115 wait_for_tick(&s); assert(s.inputs[0].deadline==UINT64_MAX && native_deadline(&s,now_ms())==0);
116 s.input_read=s.input_write=0;
117 /* Real permission resource is denied and destroyed at its deadline. */
118 int sockets[2]; assert(socketpair(AF_UNIX,SOCK_STREAM,0,sockets)==0);
119 struct wl_client *client=wl_client_create(s.display,sockets[0]); assert(client);
120 struct wl_resource *resource=wl_resource_create(client,&wl_callback_interface,1,0); assert(resource);
121 struct wlr_input_device device={.type=WLR_INPUT_DEVICE_KEYBOARD};
122 bridge.request_deadline=25; permission_request(&s,resource,&device);
123 wait_for_tick(&s); assert(wl_list_empty(&s.permissions));
124 struct data_request *data=calloc(1,sizeof(*data)); assert(data);
125 data->server=&s; data->token=100; data->generation=s.generation; data->deadline=now_ms()+25;
126 wl_list_insert(&s.data_requests,&data->link); s.data_request_count++; atomic_fetch_add(&bridge.objects,1);
127 wait_for_tick(&s); assert(wl_list_empty(&s.data_requests) && !s.data_request_count);
128 struct pointer_hint *hint=calloc(1,sizeof(*hint)); assert(hint);
129 hint->server=&s; hint->token=101; hint->generation=s.generation; hint->deadline=now_ms()+25;
130 wl_list_init(&hint->destroy.link); wl_list_insert(&s.pointer_hints,&hint->link);
131 s.pointer_hint_count++; atomic_fetch_add(&bridge.objects,1);
132 wait_for_tick(&s); assert(wl_list_empty(&s.pointer_hints));
133 struct output_configuration_request *request=calloc(1,sizeof(*request)); assert(request);
134 request->server=&s; request->token=102; request->deadline=now_ms()+25;
135 wl_list_insert(&s.output_requests,&request->link); s.output_request_count++; atomic_fetch_add(&bridge.objects,1);
136 wait_for_tick(&s); assert(wl_list_empty(&s.output_requests) && configuration_failed==1);
137 fixture_popup=calloc(1,sizeof(*fixture_popup)); assert(fixture_popup);
138 fixture_popup->deadline=now_ms()+25; wl_list_insert(&s.popups,&fixture_popup->link);
139 wait_for_tick(&s); assert(!fixture_popup && popup_expired==1);
140 struct wlr_output native={.enabled=true};
141 struct output output={.id=7,.native=&native,.lock_generation=1,.lock_presented=true};
142 wl_list_insert(&s.outputs,&output.link);
143 struct output_control_request *control=calloc(1,sizeof(*control)); assert(control);
144 control->server=&s; control->token=103; control->kind=1; control->output=7; control->deadline=now_ms()+25;
145 wl_list_insert(&s.output_controls,&control->link); s.output_control_count++; atomic_fetch_add(&bridge.objects,1);
146 wait_for_tick(&s); assert(wl_list_empty(&s.output_controls));
147 struct wlr_session_lock_v1 lock={0};
148 s.lock_owner=&lock; s.lock_state=1; s.lock_generation=1; s.lock_deadline=now_ms()+25;
149 lock_ack(&s); assert(s.lock_state==1 && lock_acks==0);
150 wait_for_tick(&s); assert(s.lock_state==2 && lock_acks==1);
151 s.lock_state=1; s.lock_deadline=now_ms()+25; output.lock_presented=false;
152 wait_for_tick(&s); assert(s.lock_state==1 && lock_acks==1 && s.lock_deadline==0);
153 assert(native_deadline(&s,now_ms())==0); /* presentation barrier never polls */
154 output.lock_presented=true; lock_ack(&s); assert(s.lock_state==2 && lock_acks==2);
155 s.lock_state=0; s.lock_owner=NULL; wl_list_remove(&output.link);
156 s.plan=calloc(4,sizeof(int64_t)); assert(s.plan); s.plan[0]=1; s.plan_count=4; s.plan_deadline=now_ms()+25;
157 wait_for_tick(&s); assert(!s.plan);
158 wl_client_destroy(client); close(sockets[1]);
159 wl_event_source_remove(s.timer); wlr_cursor_destroy(s.cursor);
160 wlr_scene_node_destroy(&s.scene->tree.node); wl_display_destroy(s.display); close(bridge.event_fd);
161 free_event_stream();
162 puts("DEADLINES=PASS all-sources idle-zero repeat idle-admission cancellation bound-input permissions data output requests hints popups lock-presentation plan");