Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T05:35:39.846Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

module_list.rs

218 lines · 6.6 KB · rust
1#![expect(clippy::result_large_err)]
2use crate::{
3    debugger_panel::DebugPanel,
4    persistence::DebuggerPaneItem,
5    tests::{active_debug_session_panel, init_test, init_test_workspace, start_debug_session},
6};
7use dap::{
8    StoppedEvent,
9    requests::{Initialize, Modules},
10};
11use gpui::{BackgroundExecutor, TestAppContext, VisualTestContext};
12use project::{FakeFs, Project};
13use std::sync::{
14    Arc,
15    atomic::{AtomicBool, AtomicI32, Ordering},
16};
17use util::path;
18
19#[gpui::test]
20async fn test_module_list(executor: BackgroundExecutor, cx: &mut TestAppContext) {
21    init_test(cx);
22
23    let fs = FakeFs::new(executor.clone());
24
25    let project = Project::test(fs, [path!("/project").as_ref()], cx).await;
26    let workspace = init_test_workspace(&project, cx).await;
27    workspace
28        .update(cx, |workspace, window, cx| {
29            workspace.focus_panel::<DebugPanel>(window, cx);
30        })
31        .unwrap();
32    let cx = &mut VisualTestContext::from_window(*workspace, cx);
33
34    let session = start_debug_session(&workspace, cx, |client| {
35        client.on_request::<Initialize, _>(move |_, _| {
36            Ok(dap::Capabilities {
37                supports_modules_request: Some(true),
38                ..Default::default()
39            })
40        });
41    })
42    .unwrap();
43
44    let client = session.update(cx, |session, _| session.adapter_client().unwrap());
45
46    let called_modules = Arc::new(AtomicBool::new(false));
47    let modules = vec![
48        dap::Module {
49            id: dap::ModuleId::Number(1),
50            name: "First Module".into(),
51            address_range: None,
52            date_time_stamp: None,
53            path: None,
54            symbol_file_path: None,
55            symbol_status: None,
56            version: None,
57            is_optimized: None,
58            is_user_code: None,
59        },
60        dap::Module {
61            id: dap::ModuleId::Number(2),
62            name: "Second Module".into(),
63            address_range: None,
64            date_time_stamp: None,
65            path: None,
66            symbol_file_path: None,
67            symbol_status: None,
68            version: None,
69            is_optimized: None,
70            is_user_code: None,
71        },
72    ];
73
74    client.on_request::<Modules, _>({
75        let called_modules = called_modules.clone();
76        let modules_request_count = AtomicI32::new(0);
77        let modules = modules.clone();
78        move |_, _| {
79            modules_request_count.fetch_add(1, Ordering::SeqCst);
80            assert_eq!(
81                1,
82                modules_request_count.load(Ordering::SeqCst),
83                "This request should only be called once from the host"
84            );
85            called_modules.store(true, Ordering::SeqCst);
86
87            Ok(dap::ModulesResponse {
88                modules: modules.clone(),
89                total_modules: Some(2u64),
90            })
91        }
92    });
93
94    client
95        .fake_event(dap::messages::Events::Stopped(StoppedEvent {
96            reason: dap::StoppedEventReason::Pause,
97            description: None,
98            thread_id: Some(1),
99            preserve_focus_hint: None,
100            text: None,
101            all_threads_stopped: None,
102            hit_breakpoint_ids: None,
103        }))
104        .await;
105
106    cx.run_until_parked();
107
108    let running_state =
109        active_debug_session_panel(workspace, cx).update_in(cx, |item, window, cx| {
110            cx.focus_self(window);
111            item.running_state().clone()
112        });
113
114    running_state.update_in(cx, |this, window, cx| {
115        this.activate_item(DebuggerPaneItem::Modules, window, cx);
116        cx.refresh_windows();
117    });
118
119    cx.run_until_parked();
120
121    assert!(
122        called_modules.load(std::sync::atomic::Ordering::SeqCst),
123        "Request Modules should be called because a user clicked on the module list"
124    );
125
126    active_debug_session_panel(workspace, cx).update(cx, |_, cx| {
127        let actual_modules = running_state.update(cx, |state, cx| {
128            state.module_list().update(cx, |list, cx| list.modules(cx))
129        });
130
131        assert_eq!(modules, actual_modules);
132    });
133
134    // Test all module events now
135    // New Module
136    // Changed
137    // Removed
138
139    let new_module = dap::Module {
140        id: dap::ModuleId::Number(3),
141        name: "Third Module".into(),
142        address_range: None,
143        date_time_stamp: None,
144        path: None,
145        symbol_file_path: None,
146        symbol_status: None,
147        version: None,
148        is_optimized: None,
149        is_user_code: None,
150    };
151
152    client
153        .fake_event(dap::messages::Events::Module(dap::ModuleEvent {
154            reason: dap::ModuleEventReason::New,
155            module: new_module.clone(),
156        }))
157        .await;
158
159    cx.run_until_parked();
160
161    active_debug_session_panel(workspace, cx).update(cx, |_, cx| {
162        let actual_modules = running_state.update(cx, |state, cx| {
163            state.module_list().update(cx, |list, cx| list.modules(cx))
164        });
165        assert_eq!(actual_modules.len(), 3);
166        assert!(actual_modules.contains(&new_module));
167    });
168
169    let changed_module = dap::Module {
170        id: dap::ModuleId::Number(2),
171        name: "Modified Second Module".into(),
172        address_range: None,
173        date_time_stamp: None,
174        path: None,
175        symbol_file_path: None,
176        symbol_status: None,
177        version: None,
178        is_optimized: None,
179        is_user_code: None,
180    };
181
182    client
183        .fake_event(dap::messages::Events::Module(dap::ModuleEvent {
184            reason: dap::ModuleEventReason::Changed,
185            module: changed_module.clone(),
186        }))
187        .await;
188
189    cx.run_until_parked();
190
191    active_debug_session_panel(workspace, cx).update(cx, |_, cx| {
192        let actual_modules = running_state.update(cx, |state, cx| {
193            state.module_list().update(cx, |list, cx| list.modules(cx))
194        });
195
196        assert_eq!(actual_modules.len(), 3);
197        assert!(actual_modules.contains(&changed_module));
198    });
199
200    client
201        .fake_event(dap::messages::Events::Module(dap::ModuleEvent {
202            reason: dap::ModuleEventReason::Removed,
203            module: changed_module.clone(),
204        }))
205        .await;
206
207    cx.run_until_parked();
208
209    active_debug_session_panel(workspace, cx).update(cx, |_, cx| {
210        let actual_modules = running_state.update(cx, |state, cx| {
211            state.module_list().update(cx, |list, cx| list.modules(cx))
212        });
213
214        assert_eq!(actual_modules.len(), 2);
215        assert!(!actual_modules.contains(&changed_module));
216    });
217}
218
Served at tenant.openagents/omega Member data and write actions are omitted.