1 /*
2 * Copyright 2008, Axel Dörfler, axeld@pinc-software.de.
3 * This file may be used under the terms of the MIT License.
4 */
5
6
7 #include <dirent.h>
8 #include <unistd.h>
9 #include <stdio.h>
10 #include <string.h>
11
12 #include <Entry.h>
13 #include <File.h>
14 #include <fs_attr.h>
15 #include <TypeConstants.h>
16
17
18 const char* kTempFile = "/tmp/bfs_attribute_iterator_test";
19
20 bool gVerbose;
21
22
23 bool
is_marker(const char * name)24 is_marker(const char* name)
25 {
26 return strstr(name, ":marker") != NULL;
27 }
28
29
30 int32
attribute_index(const char * name)31 attribute_index(const char* name)
32 {
33 int32 number;
34 if (sscanf(name, "test:%ld", &number) == 1)
35 return number;
36
37 return 0;
38 }
39
40
41 void
add_attributes(BFile & file,int32 start,int32 count)42 add_attributes(BFile& file, int32 start, int32 count)
43 {
44 for (int32 index = start; index < start + count; index++) {
45 char name[B_ATTR_NAME_LENGTH];
46 snprintf(name, sizeof(name), "test:%ld", index);
47 file.WriteAttr(name, B_INT32_TYPE, 0, &index, sizeof(int32));
48 }
49 }
50
51
52 void
remove_attributes(BFile & file,int32 start,int32 count)53 remove_attributes(BFile& file, int32 start, int32 count)
54 {
55 for (int32 index = start; index < start + count; index++) {
56 char name[B_ATTR_NAME_LENGTH];
57 snprintf(name, sizeof(name), "test:%ld", index);
58 file.RemoveAttr(name);
59 }
60 }
61
62
63 void
add_marker_attribute(BFile & file,int32 index)64 add_marker_attribute(BFile& file, int32 index)
65 {
66 char name[B_ATTR_NAME_LENGTH];
67 snprintf(name, sizeof(name), "test:%ld:marker", index);
68 file.WriteAttr(name, B_INT32_TYPE, 0, &index, sizeof(int32));
69 }
70
71
72 void
remove_marker_attribute(BFile & file,int32 index)73 remove_marker_attribute(BFile& file, int32 index)
74 {
75 char name[B_ATTR_NAME_LENGTH];
76 snprintf(name, sizeof(name), "test:%ld:marker", index);
77 file.RemoveAttr(name);
78 }
79
80
81 void
test_remove_attributes(BFile & file,int32 start,int32 count,int32 removeAt,int32 removeIndex1,int32 removeIndex2)82 test_remove_attributes(BFile& file, int32 start, int32 count, int32 removeAt,
83 int32 removeIndex1, int32 removeIndex2)
84 {
85 int fd = file.Dup();
86 if (fd < 0)
87 return;
88
89 int32 index = 0;
90 bool seen[4096] = {0};
91
92 if (gVerbose)
93 printf("test removeAt %ld\n", removeAt);
94
95 DIR* dir = fs_fopen_attr_dir(fd);
96 while (struct dirent* entry = fs_read_attr_dir(dir)) {
97 if (gVerbose)
98 printf(" %ld. %s\n", index, entry->d_name);
99 if (index == removeAt) {
100 if (removeIndex1 > 0)
101 remove_marker_attribute(file, removeIndex1);
102 if (removeIndex2 > 0)
103 remove_marker_attribute(file, removeIndex2);
104 }
105 index++;
106
107 if (is_marker(entry->d_name))
108 continue;
109
110 int32 attributeIndex = attribute_index(entry->d_name);
111 if (attributeIndex > 0) {
112 if (seen[attributeIndex]) {
113 printf("attribute index %ld already listed!\n", attributeIndex);
114 exit(1);
115 } else
116 seen[attributeIndex] = true;
117 }
118 }
119
120 fs_close_attr_dir(dir);
121 close(fd);
122
123 for (int32 i = start; i < start + count; i++) {
124 if (!seen[i]) {
125 printf("attribute index %ld not listed, saw only %ld/%ld!\n", i,
126 index, count);
127 exit(1);
128 }
129 }
130 }
131
132
133 void
test_add_attributes(BFile & file,int32 start,int32 count,int32 addAt,int32 addIndex1,int32 addIndex2)134 test_add_attributes(BFile& file, int32 start, int32 count, int32 addAt,
135 int32 addIndex1, int32 addIndex2)
136 {
137 int fd = file.Dup();
138 if (fd < 0)
139 return;
140
141 int32 index = 0;
142 bool seen[4096] = {0};
143
144 if (gVerbose)
145 printf("test addAt %ld\n", addAt);
146
147 DIR* dir = fs_fopen_attr_dir(fd);
148 while (struct dirent* entry = fs_read_attr_dir(dir)) {
149 if (gVerbose)
150 printf(" %ld. %s\n", index, entry->d_name);
151 if (index == addAt) {
152 if (addIndex1 > 0)
153 add_marker_attribute(file, addIndex1);
154 if (addIndex2 > 0)
155 add_marker_attribute(file, addIndex2);
156 }
157 index++;
158
159 if (is_marker(entry->d_name))
160 continue;
161
162 int32 attributeIndex = attribute_index(entry->d_name);
163 if (attributeIndex > 0) {
164 if (seen[attributeIndex]) {
165 printf("attribute index %ld already listed!\n", attributeIndex);
166 exit(1);
167 } else
168 seen[attributeIndex] = true;
169 }
170 }
171
172 fs_close_attr_dir(dir);
173 close(fd);
174
175 for (int32 i = start; i < start + count; i++) {
176 if (!seen[i]) {
177 printf("attribute index %ld not listed, saw only %ld/%ld!\n", i,
178 index, count);
179 exit(1);
180 }
181 }
182 }
183
184
185 int
main(int argc,char ** argv)186 main(int argc, char** argv)
187 {
188 if (argc > 1 && !strcmp(argv[1], "-v"))
189 gVerbose = true;
190
191 BFile file;
192 status_t status = file.SetTo(kTempFile, B_CREATE_FILE | B_READ_WRITE);
193 if (status != B_OK) {
194 fprintf(stderr, "Could not create temporary file: %s\n",
195 strerror(status));
196 return 1;
197 }
198
199 puts("--------- Remove Tests ----------");
200
201 // remove test, many attributes
202
203 puts("Test 1...");
204
205 for (int32 count = 5; count <= 100; count += 5) {
206 add_attributes(file, 1, count);
207 add_marker_attribute(file, count);
208 add_attributes(file, count + 1, count);
209
210 test_remove_attributes(file, 1, count,
211 count & 1 ? count - 1 : count + 1, count, -1);
212
213 remove_attributes(file, 1, count * 2);
214 }
215
216 // remove test, all positions
217
218 puts("Test 2...");
219
220 for (int32 i = 1; i < 100; i++) {
221 add_attributes(file, 1, 50);
222 add_marker_attribute(file, 51);
223 add_attributes(file, 51, 50);
224
225 test_remove_attributes(file, 1, 100, i, 51, -1);
226
227 remove_attributes(file, 1, 100);
228 }
229
230 // remove test, all positions, remove many
231
232 puts("Test 3...");
233
234 for (int32 i = 1; i < 100; i++) {
235 add_attributes(file, 1, 33);
236 add_marker_attribute(file, 33);
237 add_attributes(file, 34, 34);
238 add_marker_attribute(file, 67);
239 add_attributes(file, 68, 33);
240
241 test_remove_attributes(file, 1, 100, i, 33, 67);
242
243 remove_attributes(file, 1, 100);
244 }
245
246 puts("--------- Add Tests ----------");
247
248 // add test, many attributes
249
250 puts("Test 4...");
251
252 for (int32 count = 10; count <= 200; count += 10) {
253 add_attributes(file, 1, count);
254
255 int32 half = count / 2;
256
257 test_add_attributes(file, 1, count,
258 half & 1 ? half - 1 : half + 1, half - 2, half + 2);
259
260 remove_attributes(file, 1, count);
261 }
262
263 // add test, all iterator positions
264
265 puts("Test 5...");
266
267 for (int32 i = 1; i < 100; i++) {
268 add_attributes(file, 1, 100);
269
270 test_add_attributes(file, 1, 100, i, 50, -1);
271
272 remove_attributes(file, 1, 100);
273 }
274
275 // add test, all attribute positions
276
277 puts("Test 6...");
278
279 for (int32 i = 1; i < 100; i++) {
280 add_attributes(file, 1, 100);
281
282 test_add_attributes(file, 1, 100, 50, i, -1);
283
284 remove_attributes(file, 1, 100);
285 }
286
287 // add test, many attributes
288
289 puts("Test 7...");
290
291 for (int32 i = 1; i < 100; i++) {
292 add_attributes(file, 1, 100);
293
294 test_add_attributes(file, 1, 100, i, 33, 67);
295
296 remove_attributes(file, 1, 100);
297 }
298
299 // add test, many attributes
300
301 puts("Test 8...");
302
303 for (int32 i = 1; i < 100; i++) {
304 add_attributes(file, 1, 100);
305
306 test_add_attributes(file, 1, 100, 50, i - 1, i + 1);
307
308 remove_attributes(file, 1, 100);
309 }
310
311 BEntry entry;
312 if (entry.SetTo(kTempFile) == B_OK)
313 entry.Remove();
314
315 return 0;
316 }
317