1 /* This FileX test concentrates on the available clusters after file seek and write operation. */
2 /* A fix-me is in this file. */
3
4 #ifndef FX_STANDALONE_ENABLE
5 #include "tx_api.h"
6 #endif
7 #include "fx_api.h"
8 #include "fx_utility.h"
9 #include "fx_ram_driver_test.h"
10 #include "fx_fault_tolerant.h"
11 #include <stdio.h>
12
13 #define DEMO_STACK_SIZE 4096
14 #define CACHE_SIZE 128*128
15 #ifdef FX_ENABLE_FAULT_TOLERANT
16 #define FAULT_TOLERANT_SIZE FX_FAULT_TOLERANT_MINIMAL_BUFFER_SIZE
17 #else
18 #define FAULT_TOLERANT_SIZE 0
19 #endif
20
21
22 /* Define the ThreadX and FileX object control blocks... */
23
24 #ifndef FX_STANDALONE_ENABLE
25 static TX_THREAD ftest_0;
26 #endif
27 static FX_MEDIA ram_disk;
28 static FX_FILE my_file;
29
30 /* Define the counters used in the test application... */
31
32 struct step
33 {
34 ULONG offset;
35 UINT seek;
36 UINT size;
37 };
38
39 #ifndef FX_STANDALONE_ENABLE
40 static UCHAR *ram_disk_memory;
41 static UCHAR *cache_buffer;
42 #else
43 static UCHAR cache_buffer[CACHE_SIZE];
44 #endif
45 static UCHAR test_buffer[4096];
46 #ifdef FX_ENABLE_FAULT_TOLERANT
47 static UCHAR fault_tolerant_buffer[FAULT_TOLERANT_SIZE];
48 #endif /* FX_ENABLE_FAULT_TOLERANT */
49 static struct step steps[] =
50 {
51 {0, FX_SEEK_FORWARD, 1136},
52 {4 * sizeof(test_buffer), FX_SEEK_FORWARD, sizeof(test_buffer)},
53 {112, FX_SEEK_END, sizeof(test_buffer)},
54 {(2 * sizeof(test_buffer)), FX_SEEK_BACK, sizeof(test_buffer)},
55 };
56
57 /* Define thread prototypes. */
58
59 void filex_file_write_available_cluster_application_define(void *first_unused_memory);
60 static void ftest_0_entry(ULONG thread_input);
61
62 VOID _fx_ram_driver(FX_MEDIA *media_ptr);
63 void test_control_return(UINT status);
64
65
66
67 /* Define what the initial system looks like. */
68
69 #ifdef CTEST
test_application_define(void * first_unused_memory)70 void test_application_define(void *first_unused_memory)
71 #else
72 void filex_file_write_available_cluster_application_define(void *first_unused_memory)
73 #endif
74 {
75
76 #ifndef FX_STANDALONE_ENABLE
77 UCHAR *pointer;
78
79
80 /* Setup the working pointer. */
81 pointer = (UCHAR *) first_unused_memory;
82
83 /* Create the main thread. */
84 tx_thread_create(&ftest_0, "thread 0", ftest_0_entry, 0,
85 pointer, DEMO_STACK_SIZE,
86 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
87
88 pointer = pointer + DEMO_STACK_SIZE;
89
90 /* Setup memory for the RAM disk and the sector cache. */
91 cache_buffer = pointer;
92 pointer = pointer + CACHE_SIZE;
93 ram_disk_memory = pointer;
94
95 #endif
96
97 /* Initialize the FileX system. */
98 fx_system_initialize();
99 #ifdef FX_STANDALONE_ENABLE
100 ftest_0_entry(0);
101 #endif
102 }
103
104
105
106 /* Define the test threads. */
107
ftest_0_entry(ULONG thread_input)108 static void ftest_0_entry(ULONG thread_input)
109 {
110
111 UINT status;
112 #ifdef FX_ENABLE_FAULT_TOLERANT
113 UINT enable_fault_tolerant_this_time = 0;
114 UINT do_it_again = 0;
115 ULONG actual;
116 #endif /* FX_ENABLE_FAULT_TOLERANT */
117
118 ULONG used_clusters;
119 ULONG total_bytes;
120 ULONG total_clusters;
121 ULONG i, j;
122
123 FX_PARAMETER_NOT_USED(thread_input);
124
125 /* Print out some test information banners. */
126 printf("FileX Test: File write available cluster test......................");
127
128 #ifdef FX_ENABLE_FAULT_TOLERANT
129 TEST_START:
130 #endif /* FX_ENABLE_FAULT_TOLERANT */
131
132 /* Format the media. This needs to be done before opening it! */
133 status = fx_media_format(&ram_disk,
134 _fx_ram_driver, // Driver entry
135 ram_disk_memory, // RAM disk memory pointer
136 cache_buffer, // Media buffer pointer
137 CACHE_SIZE, // Media buffer size
138 "MY_RAM_DISK", // Volume Name
139 1, // Number of FATs
140 32, // Directory Entries
141 0, // Hidden sectors
142 512, // Total sectors
143 512, // Sector size
144 8, // Sectors per cluster
145 1, // Heads
146 1); // Sectors per track
147 status += fx_media_open(&ram_disk, "RAM DISK", _fx_ram_driver, ram_disk_memory, cache_buffer, CACHE_SIZE);
148 return_if_fail( status == FX_SUCCESS);
149
150 #ifdef FX_ENABLE_FAULT_TOLERANT
151 if ( enable_fault_tolerant_this_time)
152 {
153 /* Enable the Fault-tolerant feature. */
154 status = fx_fault_tolerant_enable(&ram_disk, fault_tolerant_buffer, FAULT_TOLERANT_SIZE);
155 return_if_fail( status == FX_SUCCESS);
156 }
157 #endif /* FX_ENABLE_FAULT_TOLERANT */
158
159 /* Create a file called TEST.TXT in the root directory. */
160 status = fx_file_create(&ram_disk, "TEST.TXT");
161 return_if_fail( status == FX_SUCCESS);
162
163 /* Open the test file. */
164 status = fx_file_open(&ram_disk, &my_file, "TEST.TXT", FX_OPEN_FOR_WRITE);
165 return_if_fail( status == FX_SUCCESS);
166
167 total_clusters = ram_disk.fx_media_available_clusters;
168
169 /* Run test steps. */
170 total_bytes = 9216;
171 for (j = 0; j < 100; j++)
172 {
173 i = j & 0x03;
174 fx_file_relative_seek (&my_file, steps[i].offset, steps[i].seek);
175 fx_file_write (&my_file, test_buffer, steps[i].size);
176
177 if (i == 3)
178 {
179
180 /* Check available clusters. */
181 used_clusters = total_bytes / 4096 + 1;
182 return_if_fail( total_clusters == ram_disk.fx_media_available_clusters + used_clusters);
183
184 /* Increase 8080 bytes each round. */
185 total_bytes += 8080;
186 }
187 }
188 #ifdef FX_ENABLE_FAULT_TOLERANT
189 if ( enable_fault_tolerant_this_time)
190 {
191 /* Make IO error while looking for copy_head_cluster by _fx_utility_FAT_entry_read. */
192 _fx_utility_fat_entry_read_error_request = 1;
193 status = fx_file_relative_seek( &my_file, steps[0].offset, steps[0].seek);
194 status += fx_file_write( &my_file, test_buffer, steps[0].size);
195 return_if_fail( status == FX_IO_ERROR);
196
197 /* Make IO error while looking for copy_tail_cluster by _fx_utility_FAT_entry_read. */
198 _fx_utility_fat_entry_read_error_request = 94;
199 status = fx_file_relative_seek( &my_file, steps[3].offset, steps[3].seek);
200 status += fx_file_write( &my_file, test_buffer, steps[3].size);
201 return_if_fail( status == FX_IO_ERROR);
202
203 /* Make IO error while copying sectors in replaced clusters at the back in fx_file_write.c.*/
204 _fx_ram_driver_io_error_request = 17;
205 status = fx_file_relative_seek( &my_file, steps[3].offset, steps[3].seek);
206 status += fx_file_write( &my_file, test_buffer, steps[3].size);
207 return_if_fail( status == FX_IO_ERROR);
208
209 /* Make IO error while writing back the current logical sector at Line 1599 in fx_file_write.c. */
210 _fx_ram_driver_io_error_request = 18;
211 status = fx_file_relative_seek( &my_file, steps[3].offset, steps[3].seek);
212 status += fx_file_write( &my_file, test_buffer, steps[3].size);
213 return_if_fail( status == FX_IO_ERROR);
214
215 #if !defined(FX_ENABLE_FAULT_TOLERANT) && !defined(FX_DISABLE_CACHE)
216 /*Make IO error while copying sectors in replaced clusters at the front in fx_file_write.c.*/
217 _fx_ram_driver_io_error_request = 3;
218 status = fx_file_relative_seek( &my_file, steps[3].offset, steps[3].seek);
219 status += fx_file_write( &my_file, test_buffer, steps[3].size);
220 return_if_fail( status == FX_IO_ERROR);
221 #endif
222
223 /* Make IO error while writing back the current logical sector at Line 1215 in fx_file_write.c. */
224 _fx_ram_driver_io_error_request = 4;
225 status = fx_file_relative_seek( &my_file, steps[3].offset, steps[3].seek);
226 status += fx_file_write( &my_file, test_buffer, steps[3].size);
227 return_if_fail( status == FX_IO_ERROR);
228
229 /* Make IO error while getting the cluster next to the copy tail. */
230 _fx_utility_fat_entry_read_error_request = 75;
231 status = fx_file_relative_seek( &my_file, steps[3].offset, steps[3].seek);
232 status += fx_file_write( &my_file, test_buffer, steps[3].size);
233
234 /* Make IO error while _fx_file_write is calling _fx_fault_tolerant_set_FAT__chain. */
235 _fx_ram_driver_io_error_request = 1;
236 status = fx_file_relative_seek( &my_file, steps[0].offset, steps[0].seek);
237 status += fx_file_write( &my_file, test_buffer, steps[0].size);
238 return_if_fail( status == FX_IO_ERROR);
239
240 /* Backup original data. */
241 actual = my_file.fx_file_first_physical_cluster;
242
243 /* Please fix me:
244 * The following code is determing to cover a branch in fx_file_write.c, which need to get three condition:
245 * 1. fx_file_total_clusters - fx_file_current_relative_cluster > 0
246 * 2. fx_file_current_logical_offset >= fx_media_bytes_per_sector
247 * 3. fx_file_current_relative_sector >= fx_media_sectors_per_cluster - 1
248 *
249 * In other words, it need to set fx_file_current_logical_offset at the end of a cluster which is in the middle of a file.
250 * I manually modify FILE_STRUCT and satify the condition for coverage. Should this branch be removed?
251 */
252 /* Produce wrong first_physical_cluster. */
253 status = fx_file_relative_seek( &my_file, steps[0].offset, steps[0].seek);
254 my_file.fx_file_first_physical_cluster = 0;
255 status += fx_file_write( &my_file, test_buffer, steps[0].size);
256 return_if_fail( status == FX_NOT_FOUND);
257
258 status = fx_file_relative_seek( &my_file, steps[0].offset, steps[0].seek);
259 my_file.fx_file_first_physical_cluster = ram_disk.fx_media_fat_reserved;
260 status += fx_file_write( &my_file, test_buffer, steps[0].size);
261 return_if_fail( status == FX_NOT_FOUND);
262
263 /* Restore data we just modified. */
264 my_file.fx_file_first_physical_cluster = actual;
265
266 if ( do_it_again)
267 {
268 goto EXTRA_TEST;
269 }
270
271 /* Attempt to cover the branch that offset is at the end of a sector but not the end of a file. */
272 /* No head cluster need to be replaced. */
273 status = fx_file_relative_seek( &my_file, steps[2].offset, steps[2].seek);
274 my_file.fx_file_current_logical_offset = 512;
275 status += fx_file_write( &my_file, test_buffer, steps[2].size);
276
277 /* Attempt to cover the branch that offset is at the end of a cluster but not the end of a file. */
278 /* No head cluster need to be replaced. */
279 status = fx_file_relative_seek( &my_file, steps[2].offset, steps[2].seek);
280 my_file.fx_file_current_logical_offset = 512;
281 my_file.fx_file_current_relative_sector = 7;
282 my_file.fx_file_total_clusters = 50;
283 status += fx_file_write( &my_file, test_buffer, steps[2].size);
284
285 /* Close the file. */
286 status = fx_file_close(&my_file);
287 status += fx_media_close( &ram_disk);
288 return_if_fail( status == FX_SUCCESS);
289 do_it_again = 1;
290 goto TEST_START;
291
292 EXTRA_TEST:
293 /* Covered the branch dealing with the condition that offset is at the end of a cluster but not the end of a file. */
294 /* Head cluster need to be replaced is existed. */
295 status = fx_file_relative_seek( &my_file, steps[2].offset, steps[2].seek);
296 my_file.fx_file_current_logical_offset = 512;
297 my_file.fx_file_current_relative_sector = 7;
298 status += fx_file_write( &my_file, test_buffer, steps[2].size);
299
300 }
301 #endif
302
303 /* Close the file. */
304 status = fx_file_close(&my_file);
305 status += fx_media_close( &ram_disk);
306 return_if_fail( status == FX_SUCCESS);
307
308 #ifdef FX_ENABLE_FAULT_TOLERANT
309 if ( enable_fault_tolerant_this_time == 0)
310 {
311 enable_fault_tolerant_this_time = 1;
312 goto TEST_START;
313 }
314 #endif
315
316 #if defined(FX_ENABLE_FAULT_TOLERANT) && !defined(FX_DISABLE_CACHE)
317 FX_CACHED_SECTOR cache_entry;
318
319 ram_disk.fx_media_sector_cache_hashed = 0;
320 ram_disk.fx_media_memory_buffer = test_buffer;
321 ram_disk.fx_media_sector_cache_end = test_buffer;
322 ram_disk.fx_media_fault_tolerant_enabled = 1;
323 ram_disk.fx_media_fault_tolerant_state |= FX_FAULT_TOLERANT_STATE_STARTED;
324 ram_disk.fx_media_sector_cache_list_ptr = &cache_entry;
325 ram_disk.fx_media_sector_cache_size = 1;
326 cache_entry.fx_cached_sector_memory_buffer = NULL;
327 cache_entry.fx_cached_sector_next_used = NULL;
328
329 _fx_utility_logical_sector_write(&ram_disk, (ULONG64)3, test_buffer, 0, FX_DATA_SECTOR);
330
331 #endif /* defined(FX_ENABLE_FAULT_TOLERANT) && !defined(FX_DISABLE_CACHE) */
332
333 printf("SUCCESS!\n");
334 test_control_return(0);
335 }
336
337