1# bad blocks with block cycles should be tested in test_relocations
2if = 'LFS_BLOCK_CYCLES == -1'
3
4[[case]] # single bad blocks
5define.LFS_BLOCK_COUNT = 256 # small bd so test runs faster
6define.LFS_ERASE_CYCLES = 0xffffffff
7define.LFS_ERASE_VALUE = [0x00, 0xff, -1]
8define.LFS_BADBLOCK_BEHAVIOR = [
9    'LFS_TESTBD_BADBLOCK_PROGERROR',
10    'LFS_TESTBD_BADBLOCK_ERASEERROR',
11    'LFS_TESTBD_BADBLOCK_READERROR',
12    'LFS_TESTBD_BADBLOCK_PROGNOOP',
13    'LFS_TESTBD_BADBLOCK_ERASENOOP',
14]
15define.NAMEMULT = 64
16define.FILEMULT = 1
17code = '''
18    for (lfs_block_t badblock = 2; badblock < LFS_BLOCK_COUNT; badblock++) {
19        lfs_testbd_setwear(&cfg, badblock-1, 0) => 0;
20        lfs_testbd_setwear(&cfg, badblock, 0xffffffff) => 0;
21
22        lfs_format(&lfs, &cfg) => 0;
23
24        lfs_mount(&lfs, &cfg) => 0;
25        for (int i = 1; i < 10; i++) {
26            for (int j = 0; j < NAMEMULT; j++) {
27                buffer[j] = '0'+i;
28            }
29            buffer[NAMEMULT] = '\0';
30            lfs_mkdir(&lfs, (char*)buffer) => 0;
31
32            buffer[NAMEMULT] = '/';
33            for (int j = 0; j < NAMEMULT; j++) {
34                buffer[j+NAMEMULT+1] = '0'+i;
35            }
36            buffer[2*NAMEMULT+1] = '\0';
37            lfs_file_open(&lfs, &file, (char*)buffer,
38                    LFS_O_WRONLY | LFS_O_CREAT) => 0;
39
40            size = NAMEMULT;
41            for (int j = 0; j < i*FILEMULT; j++) {
42                lfs_file_write(&lfs, &file, buffer, size) => size;
43            }
44
45            lfs_file_close(&lfs, &file) => 0;
46        }
47        lfs_unmount(&lfs) => 0;
48
49        lfs_mount(&lfs, &cfg) => 0;
50        for (int i = 1; i < 10; i++) {
51            for (int j = 0; j < NAMEMULT; j++) {
52                buffer[j] = '0'+i;
53            }
54            buffer[NAMEMULT] = '\0';
55            lfs_stat(&lfs, (char*)buffer, &info) => 0;
56            info.type => LFS_TYPE_DIR;
57
58            buffer[NAMEMULT] = '/';
59            for (int j = 0; j < NAMEMULT; j++) {
60                buffer[j+NAMEMULT+1] = '0'+i;
61            }
62            buffer[2*NAMEMULT+1] = '\0';
63            lfs_file_open(&lfs, &file, (char*)buffer, LFS_O_RDONLY) => 0;
64
65            size = NAMEMULT;
66            for (int j = 0; j < i*FILEMULT; j++) {
67                uint8_t rbuffer[1024];
68                lfs_file_read(&lfs, &file, rbuffer, size) => size;
69                memcmp(buffer, rbuffer, size) => 0;
70            }
71
72            lfs_file_close(&lfs, &file) => 0;
73        }
74        lfs_unmount(&lfs) => 0;
75    }
76'''
77
78[[case]] # region corruption (causes cascading failures)
79define.LFS_BLOCK_COUNT = 256 # small bd so test runs faster
80define.LFS_ERASE_CYCLES = 0xffffffff
81define.LFS_ERASE_VALUE = [0x00, 0xff, -1]
82define.LFS_BADBLOCK_BEHAVIOR = [
83    'LFS_TESTBD_BADBLOCK_PROGERROR',
84    'LFS_TESTBD_BADBLOCK_ERASEERROR',
85    'LFS_TESTBD_BADBLOCK_READERROR',
86    'LFS_TESTBD_BADBLOCK_PROGNOOP',
87    'LFS_TESTBD_BADBLOCK_ERASENOOP',
88]
89define.NAMEMULT = 64
90define.FILEMULT = 1
91code = '''
92    for (lfs_block_t i = 0; i < (LFS_BLOCK_COUNT-2)/2; i++) {
93        lfs_testbd_setwear(&cfg, i+2, 0xffffffff) => 0;
94    }
95
96    lfs_format(&lfs, &cfg) => 0;
97
98    lfs_mount(&lfs, &cfg) => 0;
99    for (int i = 1; i < 10; i++) {
100        for (int j = 0; j < NAMEMULT; j++) {
101            buffer[j] = '0'+i;
102        }
103        buffer[NAMEMULT] = '\0';
104        lfs_mkdir(&lfs, (char*)buffer) => 0;
105
106        buffer[NAMEMULT] = '/';
107        for (int j = 0; j < NAMEMULT; j++) {
108            buffer[j+NAMEMULT+1] = '0'+i;
109        }
110        buffer[2*NAMEMULT+1] = '\0';
111        lfs_file_open(&lfs, &file, (char*)buffer,
112                LFS_O_WRONLY | LFS_O_CREAT) => 0;
113
114        size = NAMEMULT;
115        for (int j = 0; j < i*FILEMULT; j++) {
116            lfs_file_write(&lfs, &file, buffer, size) => size;
117        }
118
119        lfs_file_close(&lfs, &file) => 0;
120    }
121    lfs_unmount(&lfs) => 0;
122
123    lfs_mount(&lfs, &cfg) => 0;
124    for (int i = 1; i < 10; i++) {
125        for (int j = 0; j < NAMEMULT; j++) {
126            buffer[j] = '0'+i;
127        }
128        buffer[NAMEMULT] = '\0';
129        lfs_stat(&lfs, (char*)buffer, &info) => 0;
130        info.type => LFS_TYPE_DIR;
131
132        buffer[NAMEMULT] = '/';
133        for (int j = 0; j < NAMEMULT; j++) {
134            buffer[j+NAMEMULT+1] = '0'+i;
135        }
136        buffer[2*NAMEMULT+1] = '\0';
137        lfs_file_open(&lfs, &file, (char*)buffer, LFS_O_RDONLY) => 0;
138
139        size = NAMEMULT;
140        for (int j = 0; j < i*FILEMULT; j++) {
141            uint8_t rbuffer[1024];
142            lfs_file_read(&lfs, &file, rbuffer, size) => size;
143            memcmp(buffer, rbuffer, size) => 0;
144        }
145
146        lfs_file_close(&lfs, &file) => 0;
147    }
148    lfs_unmount(&lfs) => 0;
149'''
150
151[[case]] # alternating corruption (causes cascading failures)
152define.LFS_BLOCK_COUNT = 256 # small bd so test runs faster
153define.LFS_ERASE_CYCLES = 0xffffffff
154define.LFS_ERASE_VALUE = [0x00, 0xff, -1]
155define.LFS_BADBLOCK_BEHAVIOR = [
156    'LFS_TESTBD_BADBLOCK_PROGERROR',
157    'LFS_TESTBD_BADBLOCK_ERASEERROR',
158    'LFS_TESTBD_BADBLOCK_READERROR',
159    'LFS_TESTBD_BADBLOCK_PROGNOOP',
160    'LFS_TESTBD_BADBLOCK_ERASENOOP',
161]
162define.NAMEMULT = 64
163define.FILEMULT = 1
164code = '''
165    for (lfs_block_t i = 0; i < (LFS_BLOCK_COUNT-2)/2; i++) {
166        lfs_testbd_setwear(&cfg, (2*i) + 2, 0xffffffff) => 0;
167    }
168
169    lfs_format(&lfs, &cfg) => 0;
170
171    lfs_mount(&lfs, &cfg) => 0;
172    for (int i = 1; i < 10; i++) {
173        for (int j = 0; j < NAMEMULT; j++) {
174            buffer[j] = '0'+i;
175        }
176        buffer[NAMEMULT] = '\0';
177        lfs_mkdir(&lfs, (char*)buffer) => 0;
178
179        buffer[NAMEMULT] = '/';
180        for (int j = 0; j < NAMEMULT; j++) {
181            buffer[j+NAMEMULT+1] = '0'+i;
182        }
183        buffer[2*NAMEMULT+1] = '\0';
184        lfs_file_open(&lfs, &file, (char*)buffer,
185                LFS_O_WRONLY | LFS_O_CREAT) => 0;
186
187        size = NAMEMULT;
188        for (int j = 0; j < i*FILEMULT; j++) {
189            lfs_file_write(&lfs, &file, buffer, size) => size;
190        }
191
192        lfs_file_close(&lfs, &file) => 0;
193    }
194    lfs_unmount(&lfs) => 0;
195
196    lfs_mount(&lfs, &cfg) => 0;
197    for (int i = 1; i < 10; i++) {
198        for (int j = 0; j < NAMEMULT; j++) {
199            buffer[j] = '0'+i;
200        }
201        buffer[NAMEMULT] = '\0';
202        lfs_stat(&lfs, (char*)buffer, &info) => 0;
203        info.type => LFS_TYPE_DIR;
204
205        buffer[NAMEMULT] = '/';
206        for (int j = 0; j < NAMEMULT; j++) {
207            buffer[j+NAMEMULT+1] = '0'+i;
208        }
209        buffer[2*NAMEMULT+1] = '\0';
210        lfs_file_open(&lfs, &file, (char*)buffer, LFS_O_RDONLY) => 0;
211
212        size = NAMEMULT;
213        for (int j = 0; j < i*FILEMULT; j++) {
214            uint8_t rbuffer[1024];
215            lfs_file_read(&lfs, &file, rbuffer, size) => size;
216            memcmp(buffer, rbuffer, size) => 0;
217        }
218
219        lfs_file_close(&lfs, &file) => 0;
220    }
221    lfs_unmount(&lfs) => 0;
222'''
223
224# other corner cases
225[[case]] # bad superblocks (corrupt 1 or 0)
226define.LFS_ERASE_CYCLES = 0xffffffff
227define.LFS_ERASE_VALUE = [0x00, 0xff, -1]
228define.LFS_BADBLOCK_BEHAVIOR = [
229    'LFS_TESTBD_BADBLOCK_PROGERROR',
230    'LFS_TESTBD_BADBLOCK_ERASEERROR',
231    'LFS_TESTBD_BADBLOCK_READERROR',
232    'LFS_TESTBD_BADBLOCK_PROGNOOP',
233    'LFS_TESTBD_BADBLOCK_ERASENOOP',
234]
235code = '''
236    lfs_testbd_setwear(&cfg, 0, 0xffffffff) => 0;
237    lfs_testbd_setwear(&cfg, 1, 0xffffffff) => 0;
238
239    lfs_format(&lfs, &cfg) => LFS_ERR_NOSPC;
240    lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT;
241'''
242