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