Fortran · 8902 bytes Raw Blame History
1 ! ==============================================================================
2 ! Simplified test for readline buffer pooling
3 ! Tests the key buffer allocations without full readline complexity
4 ! ==============================================================================
5 program test_readline_pooling
6 use string_pool
7 use memory_dashboard
8 use iso_fortran_env, only: output_unit
9 implicit none
10
11 ! Readline buffer sizes (from readline.f90)
12 integer, parameter :: MAX_LINE_LEN = 1024
13 integer, parameter :: MAX_MENU_ITEM_LEN = 256
14
15 ! Pooled readline state type (simplified)
16 type :: readline_state_pooled_t
17 type(string_ref) :: buffer_ref ! Current input line
18 type(string_ref) :: original_buffer_ref ! Saved for history
19 type(string_ref) :: kill_buffer_ref ! Cut/paste buffer
20 type(string_ref) :: completion_buffer_ref ! Tab completion state
21 type(string_ref) :: vi_command_ref ! Vi command buffer
22 type(string_ref) :: vi_yank_ref ! Vi yank buffer
23 type(string_ref) :: search_string_ref ! Incremental search
24 type(string_ref) :: menu_prefix_ref ! Completion prefix
25 integer :: length = 0
26 integer :: cursor_pos = 0
27 logical :: initialized = .false.
28 end type readline_state_pooled_t
29
30 type(readline_state_pooled_t) :: state
31 type(string_ref) :: temp_ref
32 integer :: i, j
33 logical :: test_passed
34 integer :: total_allocs, total_deallocs, current_strings, peak_strings
35 real :: hit_rate
36 character(len=1024) :: test_input
37
38 test_passed = .true.
39
40 print *, "=== Phase 6 Readline Buffer Pooling Test ==="
41 print *, "Testing pooled memory for readline buffers"
42 print *
43
44 ! Initialize pool and dashboard
45 call pool_init()
46 call dashboard_init(verbose=.false.)
47
48 ! Test 1: Line buffer allocation
49 print *, "Test 1: Testing line buffer allocation..."
50
51 state%buffer_ref = pool_get_string(MAX_LINE_LEN)
52 call dashboard_track_allocation(MOD_READLINE, MAX_LINE_LEN, 3)
53 call pool_copy_to_ref(state%buffer_ref, "echo 'Hello World!'")
54
55 if (associated(state%buffer_ref%data)) then
56 print *, " Buffer allocated:", trim(state%buffer_ref%data)
57 if (state%buffer_ref%pool_index > 0) then
58 print *, " PASSED: Buffer from pool"
59 else
60 print *, " FAILED: Buffer not from pool"
61 test_passed = .false.
62 end if
63 end if
64
65 ! Test 2: Multiple readline buffers (simulating interactive session)
66 print *, ""
67 print *, "Test 2: Testing multiple readline buffers..."
68
69 state%original_buffer_ref = pool_get_string(MAX_LINE_LEN)
70 state%kill_buffer_ref = pool_get_string(MAX_LINE_LEN)
71 state%completion_buffer_ref = pool_get_string(MAX_LINE_LEN)
72
73 call dashboard_track_allocation(MOD_READLINE, MAX_LINE_LEN, 3)
74 call dashboard_track_allocation(MOD_READLINE, MAX_LINE_LEN, 3)
75 call dashboard_track_allocation(MOD_READLINE, MAX_LINE_LEN, 3)
76
77 call pool_copy_to_ref(state%original_buffer_ref, "ls -la /usr/bin")
78 call pool_copy_to_ref(state%kill_buffer_ref, "deleted text here")
79 call pool_copy_to_ref(state%completion_buffer_ref, "partial_comm")
80
81 print *, " Original:", trim(state%original_buffer_ref%data)
82 print *, " Kill buffer:", trim(state%kill_buffer_ref%data)
83 print *, " Completion:", trim(state%completion_buffer_ref%data)
84 print *, " PASSED: Multiple buffers allocated"
85
86 ! Test 3: Vi mode buffers
87 print *, ""
88 print *, "Test 3: Testing Vi mode buffers..."
89
90 state%vi_command_ref = pool_get_string(MAX_LINE_LEN)
91 state%vi_yank_ref = pool_get_string(MAX_LINE_LEN)
92
93 call dashboard_track_allocation(MOD_READLINE, MAX_LINE_LEN, 3)
94 call dashboard_track_allocation(MOD_READLINE, MAX_LINE_LEN, 3)
95
96 call pool_copy_to_ref(state%vi_command_ref, "dd")
97 call pool_copy_to_ref(state%vi_yank_ref, "yanked line content")
98
99 print *, " Vi command:", trim(state%vi_command_ref%data)
100 print *, " Vi yank:", trim(state%vi_yank_ref%data)
101 print *, " PASSED: Vi buffers working"
102
103 ! Test 4: Search and menu buffers
104 print *, ""
105 print *, "Test 4: Testing search and menu buffers..."
106
107 state%search_string_ref = pool_get_string(MAX_MENU_ITEM_LEN)
108 state%menu_prefix_ref = pool_get_string(MAX_MENU_ITEM_LEN)
109
110 call dashboard_track_allocation(MOD_READLINE, MAX_MENU_ITEM_LEN, 2)
111 call dashboard_track_allocation(MOD_READLINE, MAX_MENU_ITEM_LEN, 2)
112
113 call pool_copy_to_ref(state%search_string_ref, "search_term")
114 call pool_copy_to_ref(state%menu_prefix_ref, "comp")
115
116 print *, " Search:", trim(state%search_string_ref%data)
117 print *, " Menu prefix:", trim(state%menu_prefix_ref%data)
118 print *, " PASSED: Search/menu buffers working"
119
120 ! Test 5: Simulate line editing session (buffer updates)
121 print *, ""
122 print *, "Test 5: Simulating line editing with buffer updates..."
123
124 do i = 1, 100
125 ! Simulate user typing/editing
126 write(test_input, '(A,I0)') "Command iteration ", i
127
128 ! Release old buffer
129 call pool_release_string(state%buffer_ref)
130 call dashboard_track_deallocation(MOD_READLINE, MAX_LINE_LEN, 3)
131
132 ! Get new buffer for updated line
133 state%buffer_ref = pool_get_string(MAX_LINE_LEN)
134 call dashboard_track_allocation(MOD_READLINE, MAX_LINE_LEN, 3)
135 call pool_copy_to_ref(state%buffer_ref, trim(test_input))
136 end do
137
138 print *, " Last buffer:", trim(state%buffer_ref%data)
139 print *, " Completed 100 editing cycles"
140
141 ! Test 6: Stress test - rapid completion buffer allocation/deallocation
142 print *, ""
143 print *, "Test 6: Stress testing completion buffers..."
144
145 do i = 1, 500
146 temp_ref = pool_get_string(MAX_MENU_ITEM_LEN)
147 call dashboard_track_allocation(MOD_READLINE, MAX_MENU_ITEM_LEN, 2)
148 call pool_copy_to_ref(temp_ref, "completion_candidate")
149
150 ! Release immediately (simulating showing then hiding completions)
151 call pool_release_string(temp_ref)
152 call dashboard_track_deallocation(MOD_READLINE, MAX_MENU_ITEM_LEN, 2)
153 end do
154
155 print *, " Completed 500 completion cycles"
156
157 ! Clean up all buffers
158 print *, ""
159 print *, "Cleaning up all readline buffers..."
160
161 call pool_release_string(state%buffer_ref)
162 call pool_release_string(state%original_buffer_ref)
163 call pool_release_string(state%kill_buffer_ref)
164 call pool_release_string(state%completion_buffer_ref)
165 call pool_release_string(state%vi_command_ref)
166 call pool_release_string(state%vi_yank_ref)
167 call pool_release_string(state%search_string_ref)
168 call pool_release_string(state%menu_prefix_ref)
169
170 call dashboard_track_deallocation(MOD_READLINE, MAX_LINE_LEN, 3) ! buffer
171 call dashboard_track_deallocation(MOD_READLINE, MAX_LINE_LEN, 3) ! original
172 call dashboard_track_deallocation(MOD_READLINE, MAX_LINE_LEN, 3) ! kill
173 call dashboard_track_deallocation(MOD_READLINE, MAX_LINE_LEN, 3) ! completion
174 call dashboard_track_deallocation(MOD_READLINE, MAX_LINE_LEN, 3) ! vi_command
175 call dashboard_track_deallocation(MOD_READLINE, MAX_LINE_LEN, 3) ! vi_yank
176 call dashboard_track_deallocation(MOD_READLINE, MAX_MENU_ITEM_LEN, 2) ! search
177 call dashboard_track_deallocation(MOD_READLINE, MAX_MENU_ITEM_LEN, 2) ! menu_prefix
178
179 print *, " All buffers released"
180
181 ! Test 7: Check for memory leaks
182 print *, ""
183 print *, "Test 7: Checking for memory leaks..."
184 call pool_statistics(total_allocs, total_deallocs, current_strings, peak_strings, hit_rate)
185
186 print *, " Total allocations:", total_allocs
187 print *, " Total deallocations:", total_deallocs
188 print *, " Current strings:", current_strings
189 print *, " Peak strings:", peak_strings
190 print *, " Cache hit rate:", int(hit_rate * 100), "%"
191
192 if (current_strings == 0) then
193 print *, " PASSED: No memory leaks"
194 else
195 print *, " FAILED: Memory leak -", current_strings, "strings still allocated"
196 test_passed = .false.
197 end if
198
199 ! Display dashboard
200 print *, ""
201 print *, "=== Readline Module Statistics ==="
202 call dashboard_display(detailed=.false.)
203
204 ! Export statistics
205 call dashboard_export_csv("readline_pooling_test.csv")
206 print *, ""
207 print *, "Statistics exported to readline_pooling_test.csv"
208
209 ! Clean up
210 call dashboard_cleanup()
211 call pool_cleanup()
212
213 ! Summary
214 print *, ""
215 print *, "=== Test Summary ==="
216 if (test_passed .and. current_strings == 0) then
217 print *, "ALL TESTS PASSED"
218 print *, ""
219 print *, "Readline buffer pooling verified:"
220 print *, " - Line buffers (1024B) working"
221 print *, " - Vi mode buffers working"
222 print *, " - Search/menu buffers (256B) working"
223 print *, " - Line editing simulation successful"
224 print *, " - Completion stress test passed"
225 print *, " - No memory leaks detected"
226 print *, " - Cache hit rate:", int(hit_rate * 100), "%"
227 print *, ""
228 print *, "Ready to integrate pooling into readline module!"
229 else
230 print *, "SOME TESTS FAILED"
231 if (current_strings > 0) then
232 print *, " Memory leak:", current_strings, "strings not released"
233 end if
234 end if
235
236 end program test_readline_pooling