1# There are already a number of tests that test general operations under
2# power-loss (see the reentrant attribute). These tests are for explicitly
3# testing specific corner cases.
4
5# only a revision count
6[cases.test_powerloss_only_rev]
7code = '''
8    lfs_t lfs;
9    lfs_format(&lfs, cfg) => 0;
10
11    lfs_mount(&lfs, cfg) => 0;
12    lfs_mkdir(&lfs, "notebook") => 0;
13    lfs_file_t file;
14    lfs_file_open(&lfs, &file, "notebook/paper",
15            LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
16    char buffer[256];
17    strcpy(buffer, "hello");
18    lfs_size_t size = strlen("hello");
19    for (int i = 0; i < 5; i++) {
20        lfs_file_write(&lfs, &file, buffer, size) => size;
21        lfs_file_sync(&lfs, &file) => 0;
22    }
23    lfs_file_close(&lfs, &file) => 0;
24
25    char rbuffer[256];
26    lfs_file_open(&lfs, &file, "notebook/paper", LFS_O_RDONLY) => 0;
27    for (int i = 0; i < 5; i++) {
28        lfs_file_read(&lfs, &file, rbuffer, size) => size;
29        assert(memcmp(rbuffer, buffer, size) == 0);
30    }
31    lfs_file_close(&lfs, &file) => 0;
32    lfs_unmount(&lfs) => 0;
33
34    // get pair/rev count
35    lfs_mount(&lfs, cfg) => 0;
36    lfs_dir_t dir;
37    lfs_dir_open(&lfs, &dir, "notebook") => 0;
38    lfs_block_t pair[2] = {dir.m.pair[0], dir.m.pair[1]};
39    uint32_t rev = dir.m.rev;
40    lfs_dir_close(&lfs, &dir) => 0;
41    lfs_unmount(&lfs) => 0;
42
43    // write just the revision count
44    uint8_t bbuffer[BLOCK_SIZE];
45    cfg->read(cfg, pair[1], 0, bbuffer, BLOCK_SIZE) => 0;
46
47    memcpy(bbuffer, &(uint32_t){lfs_tole32(rev+1)}, sizeof(uint32_t));
48
49    cfg->erase(cfg, pair[1]) => 0;
50    cfg->prog(cfg, pair[1], 0, bbuffer, BLOCK_SIZE) => 0;
51
52    lfs_mount(&lfs, cfg) => 0;
53
54    // can read?
55    lfs_file_open(&lfs, &file, "notebook/paper", LFS_O_RDONLY) => 0;
56    for (int i = 0; i < 5; i++) {
57        lfs_file_read(&lfs, &file, rbuffer, size) => size;
58        assert(memcmp(rbuffer, buffer, size) == 0);
59    }
60    lfs_file_close(&lfs, &file) => 0;
61
62    // can write?
63    lfs_file_open(&lfs, &file, "notebook/paper",
64            LFS_O_WRONLY | LFS_O_APPEND) => 0;
65    strcpy(buffer, "goodbye");
66    size = strlen("goodbye");
67    for (int i = 0; i < 5; i++) {
68        lfs_file_write(&lfs, &file, buffer, size) => size;
69        lfs_file_sync(&lfs, &file) => 0;
70    }
71    lfs_file_close(&lfs, &file) => 0;
72
73    lfs_file_open(&lfs, &file, "notebook/paper", LFS_O_RDONLY) => 0;
74    strcpy(buffer, "hello");
75    size = strlen("hello");
76    for (int i = 0; i < 5; i++) {
77        lfs_file_read(&lfs, &file, rbuffer, size) => size;
78        assert(memcmp(rbuffer, buffer, size) == 0);
79    }
80    strcpy(buffer, "goodbye");
81    size = strlen("goodbye");
82    for (int i = 0; i < 5; i++) {
83        lfs_file_read(&lfs, &file, rbuffer, size) => size;
84        assert(memcmp(rbuffer, buffer, size) == 0);
85    }
86    lfs_file_close(&lfs, &file) => 0;
87
88    lfs_unmount(&lfs) => 0;
89'''
90
91# partial prog, may not be byte in order!
92[cases.test_powerloss_partial_prog]
93if = '''
94    PROG_SIZE < BLOCK_SIZE
95        && (DISK_VERSION == 0 || DISK_VERSION >= 0x00020001)
96'''
97defines.BYTE_OFF = ["0", "PROG_SIZE-1", "PROG_SIZE/2"]
98defines.BYTE_VALUE = [0x33, 0xcc]
99in = "lfs.c"
100code = '''
101    lfs_t lfs;
102    lfs_format(&lfs, cfg) => 0;
103
104    lfs_mount(&lfs, cfg) => 0;
105    lfs_mkdir(&lfs, "notebook") => 0;
106    lfs_file_t file;
107    lfs_file_open(&lfs, &file, "notebook/paper",
108            LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
109    char buffer[256];
110    strcpy(buffer, "hello");
111    lfs_size_t size = strlen("hello");
112    for (int i = 0; i < 5; i++) {
113        lfs_file_write(&lfs, &file, buffer, size) => size;
114        lfs_file_sync(&lfs, &file) => 0;
115    }
116    lfs_file_close(&lfs, &file) => 0;
117
118    char rbuffer[256];
119    lfs_file_open(&lfs, &file, "notebook/paper", LFS_O_RDONLY) => 0;
120    for (int i = 0; i < 5; i++) {
121        lfs_file_read(&lfs, &file, rbuffer, size) => size;
122        assert(memcmp(rbuffer, buffer, size) == 0);
123    }
124    lfs_file_close(&lfs, &file) => 0;
125    lfs_unmount(&lfs) => 0;
126
127    // imitate a partial prog, value should not matter, if littlefs
128    // doesn't notice the partial prog testbd will assert
129
130    // get offset to next prog
131    lfs_mount(&lfs, cfg) => 0;
132    lfs_dir_t dir;
133    lfs_dir_open(&lfs, &dir, "notebook") => 0;
134    lfs_block_t block = dir.m.pair[0];
135    lfs_off_t off = dir.m.off;
136    lfs_dir_close(&lfs, &dir) => 0;
137    lfs_unmount(&lfs) => 0;
138
139    // tweak byte
140    uint8_t bbuffer[BLOCK_SIZE];
141    cfg->read(cfg, block, 0, bbuffer, BLOCK_SIZE) => 0;
142
143    bbuffer[off + BYTE_OFF] = BYTE_VALUE;
144
145    cfg->erase(cfg, block) => 0;
146    cfg->prog(cfg, block, 0, bbuffer, BLOCK_SIZE) => 0;
147
148    lfs_mount(&lfs, cfg) => 0;
149
150    // can read?
151    lfs_file_open(&lfs, &file, "notebook/paper", LFS_O_RDONLY) => 0;
152    for (int i = 0; i < 5; i++) {
153        lfs_file_read(&lfs, &file, rbuffer, size) => size;
154        assert(memcmp(rbuffer, buffer, size) == 0);
155    }
156    lfs_file_close(&lfs, &file) => 0;
157
158    // can write?
159    lfs_file_open(&lfs, &file, "notebook/paper",
160            LFS_O_WRONLY | LFS_O_APPEND) => 0;
161    strcpy(buffer, "goodbye");
162    size = strlen("goodbye");
163    for (int i = 0; i < 5; i++) {
164        lfs_file_write(&lfs, &file, buffer, size) => size;
165        lfs_file_sync(&lfs, &file) => 0;
166    }
167    lfs_file_close(&lfs, &file) => 0;
168
169    lfs_file_open(&lfs, &file, "notebook/paper", LFS_O_RDONLY) => 0;
170    strcpy(buffer, "hello");
171    size = strlen("hello");
172    for (int i = 0; i < 5; i++) {
173        lfs_file_read(&lfs, &file, rbuffer, size) => size;
174        assert(memcmp(rbuffer, buffer, size) == 0);
175    }
176    strcpy(buffer, "goodbye");
177    size = strlen("goodbye");
178    for (int i = 0; i < 5; i++) {
179        lfs_file_read(&lfs, &file, rbuffer, size) => size;
180        assert(memcmp(rbuffer, buffer, size) == 0);
181    }
182    lfs_file_close(&lfs, &file) => 0;
183
184    lfs_unmount(&lfs) => 0;
185'''
186