Unify process_alloc() and process_realloc() with PROCESS_ALLOC_MODE_REALLOC bit
[moveable_pool.git] / inode_test_run.c
1 #include <stdbool.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #define UCP 1
6 #include "fuzix_fs.h"
7 #include "rassert.h"
8 #include "util.h"
9
10 #define BLOCK_SIZE 0x200
11 #define BLOCK_SHIFT 9
12
13 #define INDIRECT_SIZE 0x100
14 #define INDIRECT_SHIFT 8
15
16 #define TRANSFER_SIZE 821 // a prime number somewhat near the block size
17
18 bool hash_init(int file, struct cinode *inode, int base, int limit) {
19   int count;
20   for (int ptr = base; (count = limit - ptr) > 0; ptr += count) {
21     if (count > TRANSFER_SIZE)
22       count = TRANSFER_SIZE;
23
24     uint8_t buf[TRANSFER_SIZE];
25     for (int i = 0; i < count; ++i)
26       buf[i] = (uint8_t)(file * 17 + (i + ptr) * 29);
27
28     udata.u_base = (char *)buf;
29     udata.u_count = count;
30     udata.u_offset = ptr;
31     udata.u_error = 0;
32     if (writei(inode) < count || udata.u_error)
33       return false;
34   }
35   rassert((int)inode->c_node.i_size == limit);
36   return true;
37 }
38
39 void hash_verify(int file, struct cinode *inode, int base, int limit) {
40   int count;
41   for (int ptr = base; (count = limit - ptr) > 0; ptr += count) {
42     if (count > TRANSFER_SIZE)
43       count = TRANSFER_SIZE;
44
45     uint8_t buf[TRANSFER_SIZE];
46     udata.u_base = (char *)buf;
47     udata.u_count = count;
48     udata.u_offset = ptr;
49     udata.u_error = 0;
50     rassert(readi(inode) == count && udata.u_error == 0);
51
52     for (int i = 0; i < count; ++i)
53       rassert(buf[i] == (uint8_t)(file * 17 + (i + ptr) * 29));
54   }
55 }
56
57 int main(int argc, char **argv) {
58   if (argc < 3) {
59     printf("usage: %s fs_path n_files\n", argv[0]);
60     exit(EXIT_FAILURE);
61   }
62   char *fs_path = argv[1];
63   int n_files = atoi(argv[2]);
64
65   fd_open(fs_path);
66   xfs_init(0);
67   printf("free inodes %d blocks %d\n", fs_tab[0].s_tinode, fs_tab[0].s_tfree);
68  
69   struct cinode **files = malloc(n_files * sizeof(struct cinode *));
70   rassert(files);
71   memset(files, 0, n_files * sizeof(struct cinode *));
72
73   while (true) {
74  //printf("free inodes %d blocks %d\n", fs_tab[0].s_tinode, fs_tab[0].s_tfree);
75     char buf[256];
76     switch (scanf("%s", buf)) {
77     case -1:
78       goto done;
79     case 1:
80       break;
81     default:
82       rassert(false);
83     }
84     if (strcmp(buf, "alloc") == 0) {
85       int file, size;
86       rassert(scanf("%d %d %s", &file, &size, buf) == 3);
87       rassert(file >= 0 && file < n_files);
88       rassert(size >= 0);
89       bool success;
90       if (strcmp(buf, "false") == 0)
91         success = false;
92       else if (strcmp(buf, "true") == 0)
93         success = true;
94       else
95         rassert(false);
96       printf(
97         "alloc %d %d %s\n",
98         file,
99         size,
100         success ? "true" : "false"
101       );
102       rassert(files[file] == NULL);
103       bool result;
104       files[file] = i_open(0, 0);
105       if (files[file] == NULL)
106         result = false;
107       else {
108         /* This does not implement BSD style "sticky" groups */
109         files[file]->c_node.i_uid = udata.u_euid;
110         files[file]->c_node.i_gid = udata.u_egid;
111
112         files[file]->c_node.i_mode = F_REG;   /* For the time being */
113         files[file]->c_node.i_nlink = 0;
114         files[file]->c_node.i_size = 0;
115         for (int i = 0; i < 20; ++i)
116           files[file]->c_node.i_addr[i] = 0;
117         wr_inode(files[file]);
118
119         if (!hash_init(file, files[file], 0, size)) {
120           result = false;
121           i_deref(files[file]);
122           files[file] = NULL;
123         }
124         else
125           result = true;
126       }
127       printf(
128         "... %s\n",
129         result == success ?
130           "ok" :
131           result ? "succeeded, should fail" : "failed, should succeed"
132       );
133       if (files[file] && !success) {
134         printf("... undo\n");
135         i_deref(files[file]);
136         files[file] = NULL;
137       }
138     }
139     else if (strcmp(buf, "realloc") == 0) {
140       int file, old_size, size;
141       rassert(scanf("%d %d %d %s", &file, &old_size, &size, buf) == 4);
142       rassert(file >= 0 && file < n_files);
143       rassert(old_size >= 0);
144       rassert(size >= 0);
145       bool success;
146       if (strcmp(buf, "false") == 0)
147         success = false;
148       else if (strcmp(buf, "true") == 0)
149         success = true;
150       else
151         rassert(false);
152       printf(
153         "realloc %d %d %d %s\n",
154         file,
155         old_size,
156         size,
157         success ? "true" : "false"
158       );
159       if (files[file] == NULL)
160         printf("... not allocated, ignore\n");
161       else {
162         int actual_old_size = (int)files[file]->c_node.i_size;
163         if (actual_old_size != old_size) {
164           printf(
165             "... old size %d, should be %d\n",
166             actual_old_size,
167             old_size
168           );
169           rassert(actual_old_size <= old_size);
170         }
171         bool result;
172         if (size < actual_old_size) {
173           hash_verify(file, files[file], size, actual_old_size);
174           udata.u_offset = size;
175           f_trunc(files[file]);
176           result = true;
177         }
178         else if (!hash_init(file, files[file], actual_old_size, size)) {
179           udata.u_offset = actual_old_size;
180           f_trunc(files[file]);
181           result = false;
182         }
183         else
184           result = true;
185         printf(
186           "... %s\n",
187           result == success ?
188             "ok" :
189             result ? "succeeded, should fail" : "failed, should succeed"
190         );
191         if (result && !success) {
192           printf("... undo\n");
193           udata.u_offset = actual_old_size;
194           f_trunc(files[file]);
195         }
196       }
197     }
198     else if (strcmp(buf, "free") == 0) {
199       int file, old_size;
200       rassert(scanf("%d %d", &file, &old_size) == 2);
201       rassert(file >= 0 && file < n_files);
202       rassert(old_size >= 0);
203       printf(
204         "free %d %d\n",
205         file,
206         old_size
207       );
208       if (files[file] == NULL)
209         printf("... not allocated, ignore\n");
210       else {
211         int actual_old_size = (int)files[file]->c_node.i_size;
212         if (actual_old_size != old_size) {
213           printf(
214             "... old size %d, should be %d\n",
215             actual_old_size,
216             old_size
217           );
218           rassert(actual_old_size <= old_size);
219         }
220         hash_verify(file, files[file], 0, actual_old_size);
221         i_deref(files[file]);
222         files[file] = NULL;
223         printf("... ok\n");
224       }
225     }
226     else
227       rassert(false);
228   }
229
230 done:
231   printf("free inodes %d blocks %d\n", fs_tab[0].s_tinode, fs_tab[0].s_tfree);
232  
233   printf("final state:\n");
234   for (int i = 0; i < n_files; ++i) {
235     if (files[i] == NULL)
236       printf("file %d: not allocated\n", i);
237     else {
238       int size = (int)files[i]->c_node.i_size;
239       printf("file %d: size %d\n", i, size);
240       hash_verify(i, files[i], 0, size);
241       i_deref(files[i]);
242     }
243   }
244
245   printf("free inodes %d blocks %d\n", fs_tab[0].s_tinode, fs_tab[0].s_tfree);
246
247   return 0;
248 }