]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*- |
2 | * BSD LICENSE | |
3 | * | |
4 | * Copyright (c) Intel Corporation. | |
5 | * All rights reserved. | |
6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
10 | * | |
11 | * * Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * * Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in | |
15 | * the documentation and/or other materials provided with the | |
16 | * distribution. | |
17 | * * Neither the name of Intel Corporation nor the names of its | |
18 | * contributors may be used to endorse or promote products derived | |
19 | * from this software without specific prior written permission. | |
20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | |
33 | ||
34 | #include <stdlib.h> | |
35 | #include <unistd.h> | |
36 | #include <errno.h> | |
37 | #include <stdio.h> | |
38 | ||
39 | #include "CUnit/Basic.h" | |
40 | ||
41 | #include "lib/test_env.c" | |
42 | ||
43 | #include "spdk_cunit.h" | |
44 | #include "blobfs.c" | |
45 | #include "tree.c" | |
46 | ||
47 | #include "lib/blob/bs_dev_common.c" | |
48 | ||
49 | struct spdk_filesystem *g_fs; | |
50 | struct spdk_file *g_file; | |
51 | int g_fserrno; | |
52 | ||
53 | static void | |
54 | fs_op_complete(void *ctx, int fserrno) | |
55 | { | |
56 | g_fserrno = fserrno; | |
57 | } | |
58 | ||
59 | static void | |
60 | fs_op_with_handle_complete(void *ctx, struct spdk_filesystem *fs, int fserrno) | |
61 | { | |
62 | g_fs = fs; | |
63 | g_fserrno = fserrno; | |
64 | } | |
65 | ||
66 | static void | |
67 | fs_init(void) | |
68 | { | |
69 | struct spdk_filesystem *fs; | |
70 | struct spdk_bs_dev dev; | |
71 | ||
72 | init_dev(&dev); | |
73 | spdk_allocate_thread(); | |
74 | ||
75 | spdk_fs_init(&dev, NULL, fs_op_with_handle_complete, NULL); | |
76 | CU_ASSERT(g_fs != NULL); | |
77 | CU_ASSERT(g_fserrno == 0); | |
78 | fs = g_fs; | |
79 | ||
80 | spdk_fs_unload(fs, fs_op_complete, NULL); | |
81 | CU_ASSERT(g_fserrno == 0); | |
82 | ||
83 | spdk_free_thread(); | |
84 | } | |
85 | ||
86 | static void | |
87 | create_cb(void *ctx, int fserrno) | |
88 | { | |
89 | g_fserrno = fserrno; | |
90 | } | |
91 | ||
92 | static void | |
93 | open_cb(void *ctx, struct spdk_file *f, int fserrno) | |
94 | { | |
95 | g_fserrno = fserrno; | |
96 | g_file = f; | |
97 | } | |
98 | ||
99 | static void | |
100 | delete_cb(void *ctx, int fserrno) | |
101 | { | |
102 | g_fserrno = fserrno; | |
103 | } | |
104 | ||
105 | static void | |
106 | fs_open(void) | |
107 | { | |
108 | struct spdk_filesystem *fs; | |
109 | spdk_fs_iter iter; | |
110 | struct spdk_bs_dev dev; | |
111 | struct spdk_file *file; | |
112 | ||
113 | init_dev(&dev); | |
114 | spdk_allocate_thread(); | |
115 | ||
116 | spdk_fs_init(&dev, NULL, fs_op_with_handle_complete, NULL); | |
117 | CU_ASSERT(g_fs != NULL); | |
118 | CU_ASSERT(g_fserrno == 0); | |
119 | fs = g_fs; | |
120 | ||
121 | g_fserrno = 0; | |
122 | spdk_fs_open_file_async(fs, "file1", 0, open_cb, NULL); | |
123 | CU_ASSERT(g_fserrno == -ENOENT); | |
124 | ||
125 | g_file = NULL; | |
126 | g_fserrno = 1; | |
127 | spdk_fs_open_file_async(fs, "file1", SPDK_BLOBFS_OPEN_CREATE, open_cb, NULL); | |
128 | CU_ASSERT(g_fserrno == 0); | |
129 | SPDK_CU_ASSERT_FATAL(g_file != NULL); | |
130 | CU_ASSERT(!strcmp("file1", g_file->name)); | |
131 | CU_ASSERT(g_file->ref_count == 1); | |
132 | ||
133 | iter = spdk_fs_iter_first(fs); | |
134 | CU_ASSERT(iter != NULL); | |
135 | file = spdk_fs_iter_get_file(iter); | |
136 | SPDK_CU_ASSERT_FATAL(file != NULL); | |
137 | CU_ASSERT(!strcmp("file1", file->name)); | |
138 | iter = spdk_fs_iter_next(iter); | |
139 | CU_ASSERT(iter == NULL); | |
140 | ||
141 | g_fserrno = 0; | |
142 | /* Delete should fail, since we have an open reference. */ | |
143 | spdk_fs_delete_file_async(fs, "file1", delete_cb, NULL); | |
144 | CU_ASSERT(g_fserrno == -EBUSY); | |
145 | CU_ASSERT(!TAILQ_EMPTY(&fs->files)); | |
146 | ||
147 | g_fserrno = 1; | |
148 | spdk_file_close_async(g_file, fs_op_complete, NULL); | |
149 | CU_ASSERT(g_fserrno == 0); | |
150 | CU_ASSERT(g_file->ref_count == 0); | |
151 | ||
152 | g_fserrno = 0; | |
153 | spdk_file_close_async(g_file, fs_op_complete, NULL); | |
154 | CU_ASSERT(g_fserrno == -EBADF); | |
155 | CU_ASSERT(g_file->ref_count == 0); | |
156 | ||
157 | g_fserrno = 1; | |
158 | spdk_fs_delete_file_async(fs, "file1", delete_cb, NULL); | |
159 | CU_ASSERT(g_fserrno == 0); | |
160 | CU_ASSERT(TAILQ_EMPTY(&fs->files)); | |
161 | ||
162 | spdk_fs_unload(fs, fs_op_complete, NULL); | |
163 | CU_ASSERT(g_fserrno == 0); | |
164 | ||
165 | spdk_free_thread(); | |
166 | } | |
167 | ||
168 | static void | |
169 | fs_truncate(void) | |
170 | { | |
171 | struct spdk_filesystem *fs; | |
172 | struct spdk_bs_dev dev; | |
173 | ||
174 | init_dev(&dev); | |
175 | spdk_allocate_thread(); | |
176 | ||
177 | spdk_fs_init(&dev, NULL, fs_op_with_handle_complete, NULL); | |
178 | SPDK_CU_ASSERT_FATAL(g_fs != NULL); | |
179 | CU_ASSERT(g_fserrno == 0); | |
180 | fs = g_fs; | |
181 | ||
182 | g_file = NULL; | |
183 | g_fserrno = 1; | |
184 | spdk_fs_open_file_async(fs, "file1", SPDK_BLOBFS_OPEN_CREATE, open_cb, NULL); | |
185 | CU_ASSERT(g_fserrno == 0); | |
186 | SPDK_CU_ASSERT_FATAL(g_file != NULL); | |
187 | ||
188 | g_fserrno = 1; | |
189 | spdk_file_truncate_async(g_file, 18 * 1024 * 1024 + 1, fs_op_complete, NULL); | |
190 | CU_ASSERT(g_fserrno == 0); | |
191 | CU_ASSERT(g_file->length == 18 * 1024 * 1024 + 1); | |
192 | ||
193 | g_fserrno = 1; | |
194 | spdk_file_truncate_async(g_file, 1, fs_op_complete, NULL); | |
195 | CU_ASSERT(g_fserrno == 0); | |
196 | CU_ASSERT(g_file->length == 1); | |
197 | ||
198 | g_fserrno = 1; | |
199 | spdk_file_truncate_async(g_file, 18 * 1024 * 1024 + 1, fs_op_complete, NULL); | |
200 | CU_ASSERT(g_fserrno == 0); | |
201 | CU_ASSERT(g_file->length == 18 * 1024 * 1024 + 1); | |
202 | ||
203 | g_fserrno = 1; | |
204 | spdk_file_close_async(g_file, fs_op_complete, NULL); | |
205 | CU_ASSERT(g_fserrno == 0); | |
206 | CU_ASSERT(g_file->ref_count == 0); | |
207 | ||
208 | g_fserrno = 1; | |
209 | spdk_fs_delete_file_async(fs, "file1", delete_cb, NULL); | |
210 | CU_ASSERT(g_fserrno == 0); | |
211 | CU_ASSERT(TAILQ_EMPTY(&fs->files)); | |
212 | ||
213 | spdk_fs_unload(fs, fs_op_complete, NULL); | |
214 | CU_ASSERT(g_fserrno == 0); | |
215 | ||
216 | spdk_free_thread(); | |
217 | } | |
218 | ||
219 | static void | |
220 | fs_rename(void) | |
221 | { | |
222 | struct spdk_filesystem *fs; | |
223 | struct spdk_file *file, *file2; | |
224 | struct spdk_bs_dev dev; | |
225 | ||
226 | init_dev(&dev); | |
227 | spdk_allocate_thread(); | |
228 | ||
229 | spdk_fs_init(&dev, NULL, fs_op_with_handle_complete, NULL); | |
230 | SPDK_CU_ASSERT_FATAL(g_fs != NULL); | |
231 | CU_ASSERT(g_fserrno == 0); | |
232 | fs = g_fs; | |
233 | ||
234 | g_fserrno = 1; | |
235 | spdk_fs_create_file_async(fs, "file1", create_cb, NULL); | |
236 | CU_ASSERT(g_fserrno == 0); | |
237 | ||
238 | g_file = NULL; | |
239 | g_fserrno = 1; | |
240 | spdk_fs_open_file_async(fs, "file1", 0, open_cb, NULL); | |
241 | CU_ASSERT(g_fserrno == 0); | |
242 | SPDK_CU_ASSERT_FATAL(g_file != NULL); | |
243 | CU_ASSERT(g_file->ref_count == 1); | |
244 | ||
245 | file = g_file; | |
246 | g_file = NULL; | |
247 | g_fserrno = 1; | |
248 | spdk_file_close_async(file, fs_op_complete, NULL); | |
249 | CU_ASSERT(g_fserrno == 0); | |
250 | SPDK_CU_ASSERT_FATAL(file->ref_count == 0); | |
251 | ||
252 | g_file = NULL; | |
253 | g_fserrno = 1; | |
254 | spdk_fs_open_file_async(fs, "file2", SPDK_BLOBFS_OPEN_CREATE, open_cb, NULL); | |
255 | CU_ASSERT(g_fserrno == 0); | |
256 | SPDK_CU_ASSERT_FATAL(g_file != NULL); | |
257 | CU_ASSERT(g_file->ref_count == 1); | |
258 | ||
259 | file2 = g_file; | |
260 | g_file = NULL; | |
261 | g_fserrno = 1; | |
262 | spdk_file_close_async(file2, fs_op_complete, NULL); | |
263 | CU_ASSERT(g_fserrno == 0); | |
264 | SPDK_CU_ASSERT_FATAL(file2->ref_count == 0); | |
265 | ||
266 | /* | |
267 | * Do a 3-way rename. This should delete the old "file2", then rename | |
268 | * "file1" to "file2". | |
269 | */ | |
270 | g_fserrno = 1; | |
271 | spdk_fs_rename_file_async(fs, "file1", "file2", fs_op_complete, NULL); | |
272 | CU_ASSERT(g_fserrno == 0); | |
273 | CU_ASSERT(file->ref_count == 0); | |
274 | CU_ASSERT(!strcmp(file->name, "file2")); | |
275 | CU_ASSERT(TAILQ_FIRST(&fs->files) == file); | |
276 | CU_ASSERT(TAILQ_NEXT(file, tailq) == NULL); | |
277 | ||
278 | g_fserrno = 0; | |
279 | spdk_fs_delete_file_async(fs, "file1", delete_cb, NULL); | |
280 | CU_ASSERT(g_fserrno == -ENOENT); | |
281 | CU_ASSERT(!TAILQ_EMPTY(&fs->files)); | |
282 | ||
283 | g_fserrno = 1; | |
284 | spdk_fs_delete_file_async(fs, "file2", delete_cb, NULL); | |
285 | CU_ASSERT(g_fserrno == 0); | |
286 | CU_ASSERT(TAILQ_EMPTY(&fs->files)); | |
287 | ||
288 | spdk_fs_unload(fs, fs_op_complete, NULL); | |
289 | CU_ASSERT(g_fserrno == 0); | |
290 | ||
291 | spdk_free_thread(); | |
292 | } | |
293 | ||
294 | static void | |
295 | tree_find_buffer_ut(void) | |
296 | { | |
297 | struct cache_tree *root; | |
298 | struct cache_tree *level1_0; | |
299 | struct cache_tree *level0_0_0; | |
300 | struct cache_tree *level0_0_12; | |
301 | struct cache_buffer *leaf_0_0_4; | |
302 | struct cache_buffer *leaf_0_12_8; | |
303 | struct cache_buffer *leaf_9_23_15; | |
304 | struct cache_buffer *buffer; | |
305 | ||
306 | level1_0 = calloc(1, sizeof(struct cache_tree)); | |
307 | SPDK_CU_ASSERT_FATAL(level1_0 != NULL); | |
308 | level0_0_0 = calloc(1, sizeof(struct cache_tree)); | |
309 | SPDK_CU_ASSERT_FATAL(level0_0_0 != NULL); | |
310 | level0_0_12 = calloc(1, sizeof(struct cache_tree)); | |
311 | SPDK_CU_ASSERT_FATAL(level0_0_12 != NULL); | |
312 | leaf_0_0_4 = calloc(1, sizeof(struct cache_buffer)); | |
313 | SPDK_CU_ASSERT_FATAL(leaf_0_0_4 != NULL); | |
314 | leaf_0_12_8 = calloc(1, sizeof(struct cache_buffer)); | |
315 | SPDK_CU_ASSERT_FATAL(leaf_0_12_8 != NULL); | |
316 | leaf_9_23_15 = calloc(1, sizeof(struct cache_buffer)); | |
317 | SPDK_CU_ASSERT_FATAL(leaf_9_23_15 != NULL); | |
318 | ||
319 | level1_0->level = 1; | |
320 | level0_0_0->level = 0; | |
321 | level0_0_12->level = 0; | |
322 | ||
323 | leaf_0_0_4->offset = CACHE_BUFFER_SIZE * 4; | |
324 | level0_0_0->u.buffer[4] = leaf_0_0_4; | |
325 | level0_0_0->present_mask |= (1ULL << 4); | |
326 | ||
327 | leaf_0_12_8->offset = CACHE_TREE_LEVEL_SIZE(1) * 12 + CACHE_BUFFER_SIZE * 8; | |
328 | level0_0_12->u.buffer[8] = leaf_0_12_8; | |
329 | level0_0_12->present_mask |= (1ULL << 8); | |
330 | ||
331 | level1_0->u.tree[0] = level0_0_0; | |
332 | level1_0->present_mask |= (1ULL << 0); | |
333 | level1_0->u.tree[12] = level0_0_12; | |
334 | level1_0->present_mask |= (1ULL << 12); | |
335 | ||
336 | buffer = spdk_tree_find_buffer(NULL, 0); | |
337 | CU_ASSERT(buffer == NULL); | |
338 | ||
339 | buffer = spdk_tree_find_buffer(level0_0_0, 0); | |
340 | CU_ASSERT(buffer == NULL); | |
341 | ||
342 | buffer = spdk_tree_find_buffer(level0_0_0, CACHE_TREE_LEVEL_SIZE(0) + 1); | |
343 | CU_ASSERT(buffer == NULL); | |
344 | ||
345 | buffer = spdk_tree_find_buffer(level0_0_0, leaf_0_0_4->offset); | |
346 | CU_ASSERT(buffer == leaf_0_0_4); | |
347 | ||
348 | buffer = spdk_tree_find_buffer(level1_0, leaf_0_0_4->offset); | |
349 | CU_ASSERT(buffer == leaf_0_0_4); | |
350 | ||
351 | buffer = spdk_tree_find_buffer(level1_0, leaf_0_12_8->offset); | |
352 | CU_ASSERT(buffer == leaf_0_12_8); | |
353 | ||
354 | buffer = spdk_tree_find_buffer(level1_0, leaf_0_12_8->offset + CACHE_BUFFER_SIZE - 1); | |
355 | CU_ASSERT(buffer == leaf_0_12_8); | |
356 | ||
357 | buffer = spdk_tree_find_buffer(level1_0, leaf_0_12_8->offset - 1); | |
358 | CU_ASSERT(buffer == NULL); | |
359 | ||
360 | leaf_9_23_15->offset = CACHE_TREE_LEVEL_SIZE(2) * 9 + | |
361 | CACHE_TREE_LEVEL_SIZE(1) * 23 + | |
362 | CACHE_BUFFER_SIZE * 15; | |
363 | root = spdk_tree_insert_buffer(level1_0, leaf_9_23_15); | |
364 | CU_ASSERT(root != level1_0); | |
365 | buffer = spdk_tree_find_buffer(root, leaf_9_23_15->offset); | |
366 | CU_ASSERT(buffer == leaf_9_23_15); | |
367 | spdk_tree_free_buffers(root); | |
368 | free(root); | |
369 | } | |
370 | ||
371 | int main(int argc, char **argv) | |
372 | { | |
373 | CU_pSuite suite = NULL; | |
374 | unsigned int num_failures; | |
375 | ||
376 | if (CU_initialize_registry() != CUE_SUCCESS) { | |
377 | return CU_get_error(); | |
378 | } | |
379 | ||
380 | suite = CU_add_suite("blobfs", NULL, NULL); | |
381 | if (suite == NULL) { | |
382 | CU_cleanup_registry(); | |
383 | return CU_get_error(); | |
384 | } | |
385 | ||
386 | if ( | |
387 | CU_add_test(suite, "fs_init", fs_init) == NULL || | |
388 | CU_add_test(suite, "fs_open", fs_open) == NULL || | |
389 | CU_add_test(suite, "fs_truncate", fs_truncate) == NULL || | |
390 | CU_add_test(suite, "fs_rename", fs_rename) == NULL || | |
391 | CU_add_test(suite, "tree_find_buffer", tree_find_buffer_ut) == NULL | |
392 | ) { | |
393 | CU_cleanup_registry(); | |
394 | return CU_get_error(); | |
395 | } | |
396 | ||
397 | g_dev_buffer = calloc(1, DEV_BUFFER_SIZE); | |
398 | CU_basic_set_mode(CU_BRM_VERBOSE); | |
399 | CU_basic_run_tests(); | |
400 | num_failures = CU_get_number_of_failures(); | |
401 | CU_cleanup_registry(); | |
402 | free(g_dev_buffer); | |
403 | return num_failures; | |
404 | } |