xref: /haiku/src/tests/add-ons/kernel/file_systems/bfs/bfs_attribute_iterator_test.cpp (revision 90e8094e1e3a3454c65b6eca432c271b99ca1739)
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