source: mainline/uspace/lib/label/test/label.c@ a4e78743

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a4e78743 was 09ab0a9a, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Fix vertical spacing with new Ccheck revision.

  • Property mode set to 100644
File size: 15.0 KB
Line 
1/*
2 * Copyright (c) 2017 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <label/label.h>
30#include <mem.h>
31#include <pcut/pcut.h>
32#include <stddef.h>
33#include <stdlib.h>
34
35PCUT_INIT;
36
37PCUT_TEST_SUITE(label);
38
39static errno_t label_test_get_bsize(void *, size_t *);
40static errno_t label_test_get_nblocks(void *, aoff64_t *);
41static errno_t label_test_read(void *, aoff64_t, size_t, void *);
42static errno_t label_test_write(void *, aoff64_t, size_t, const void *);
43
44label_bd_ops_t label_test_ops = {
45 .get_bsize = label_test_get_bsize,
46 .get_nblocks = label_test_get_nblocks,
47 .read = label_test_read,
48 .write = label_test_write
49};
50
51/** Pretended block device for testing */
52typedef struct {
53 char *data;
54 size_t bsize;
55 aoff64_t nblocks;
56} test_bd_t;
57
58enum {
59 test_block_size = 512,
60 test_nblocks = 1024
61};
62
63/** Create pretended block device.
64 *
65 * @param bsize Block size
66 * @param nblocks Number of blocks
67 * @param rbd Place to store pointer to new pretended block device
68 */
69static errno_t test_bd_create(size_t bsize, aoff64_t nblocks, test_bd_t **rbd)
70{
71 test_bd_t *bd;
72
73 bd = calloc(1, sizeof(test_bd_t));
74 if (bd == NULL)
75 return ENOMEM;
76
77 bd->data = calloc(bsize, nblocks);
78 if (bd->data == NULL) {
79 free(bd);
80 return ENOMEM;
81 }
82
83 bd->bsize = bsize;
84 bd->nblocks = nblocks;
85 *rbd = bd;
86
87 return EOK;
88}
89
90/** Destroy pretended block device.
91 *
92 * @param bd Pretended block device
93 */
94static void test_bd_destroy(test_bd_t *bd)
95{
96 free(bd->data);
97 free(bd);
98}
99
100/** Get block size wrapper for liblabel */
101static errno_t label_test_get_bsize(void *arg, size_t *bsize)
102{
103 test_bd_t *bd = (test_bd_t *)arg;
104
105 *bsize = bd->bsize;
106 return EOK;
107}
108
109/** Get number of blocks wrapper for liblabel */
110static errno_t label_test_get_nblocks(void *arg, aoff64_t *nblocks)
111{
112 test_bd_t *bd = (test_bd_t *)arg;
113
114 *nblocks = bd->nblocks;
115 return EOK;
116}
117
118/** Read blocks wrapper for liblabel */
119static errno_t label_test_read(void *arg, aoff64_t ba, size_t cnt, void *buf)
120{
121 test_bd_t *bd = (test_bd_t *)arg;
122
123 if (ba >= bd->nblocks)
124 return EINVAL;
125
126 memcpy(buf, bd->data + ba * bd->bsize, bd->bsize);
127 return EOK;
128}
129
130/** Write blocks wrapper for liblabel */
131static errno_t label_test_write(void *arg, aoff64_t ba, size_t cnt, const void *data)
132{
133 test_bd_t *bd = (test_bd_t *)arg;
134
135 if (ba >= bd->nblocks)
136 return EINVAL;
137
138 memcpy(bd->data + ba * bd->bsize, data, bd->bsize);
139 return EOK;
140}
141
142PCUT_TEST(open_empty)
143{
144 label_t *label;
145 label_bd_t lbd;
146 label_info_t linfo;
147 label_part_t *part;
148 test_bd_t *bd = NULL;
149 errno_t rc;
150
151 rc = test_bd_create(test_block_size, test_nblocks, &bd);
152 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
153
154 lbd.ops = &label_test_ops;
155 lbd.arg = (void *)bd;
156
157 rc = label_open(&lbd, &label);
158 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
159
160 rc = label_get_info(label, &linfo);
161 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
162
163 PCUT_ASSERT_INT_EQUALS(lt_none, linfo.ltype);
164 PCUT_ASSERT_INT_EQUALS(0, linfo.flags);
165
166 /* There should be exactly one pseudo partition */
167 part = label_part_first(label);
168 PCUT_ASSERT_NOT_NULL(part);
169
170 part = label_part_next(part);
171 PCUT_ASSERT_NULL(part);
172
173 label_close(label);
174
175 test_bd_destroy(bd);
176}
177
178PCUT_TEST(create_destroy_mbr)
179{
180 label_t *label;
181 label_bd_t lbd;
182 label_info_t linfo;
183 label_part_t *part;
184 test_bd_t *bd = NULL;
185 errno_t rc;
186
187 rc = test_bd_create(test_block_size, test_nblocks, &bd);
188 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
189
190 lbd.ops = &label_test_ops;
191 lbd.arg = (void *)bd;
192
193 rc = label_create(&lbd, lt_mbr, &label);
194 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
195
196 rc = label_get_info(label, &linfo);
197 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
198
199 PCUT_ASSERT_INT_EQUALS(lt_mbr, linfo.ltype);
200 PCUT_ASSERT_INT_EQUALS(lf_ext_supp | lf_can_create_pri |
201 lf_can_create_ext, linfo.flags);
202
203 /* There should be no partitions */
204 part = label_part_first(label);
205 PCUT_ASSERT_NULL(part);
206
207 /* Close and reopen */
208 label_close(label);
209
210 rc = label_open(&lbd, &label);
211 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
212
213 rc = label_get_info(label, &linfo);
214 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
215
216 /* Everything should still be the same */
217 PCUT_ASSERT_INT_EQUALS(lt_mbr, linfo.ltype);
218 PCUT_ASSERT_INT_EQUALS(lf_ext_supp | lf_can_create_pri |
219 lf_can_create_ext, linfo.flags);
220
221 rc = label_destroy(label);
222 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
223
224 /* There should be no label now */
225
226 rc = label_open(&lbd, &label);
227 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
228
229 rc = label_get_info(label, &linfo);
230 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
231
232 PCUT_ASSERT_INT_EQUALS(lt_none, linfo.ltype);
233 PCUT_ASSERT_INT_EQUALS(0, linfo.flags);
234
235 label_close(label);
236
237 test_bd_destroy(bd);
238}
239
240PCUT_TEST(create_destroy_gpt)
241{
242 label_t *label;
243 label_bd_t lbd;
244 label_info_t linfo;
245 label_part_t *part;
246 test_bd_t *bd = NULL;
247 errno_t rc;
248
249 rc = test_bd_create(test_block_size, test_nblocks, &bd);
250 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
251
252 lbd.ops = &label_test_ops;
253 lbd.arg = (void *)bd;
254
255 rc = label_create(&lbd, lt_gpt, &label);
256 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
257
258 rc = label_get_info(label, &linfo);
259 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
260
261 PCUT_ASSERT_INT_EQUALS(lt_gpt, linfo.ltype);
262 PCUT_ASSERT_INT_EQUALS(lf_can_create_pri | lf_ptype_uuid, linfo.flags);
263
264 /* There should be no partitions */
265 part = label_part_first(label);
266 PCUT_ASSERT_NULL(part);
267
268 /* Close and reopen */
269 label_close(label);
270
271 rc = label_open(&lbd, &label);
272 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
273
274 rc = label_get_info(label, &linfo);
275 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
276
277 /* Everything should still be the same */
278 PCUT_ASSERT_INT_EQUALS(lt_gpt, linfo.ltype);
279 PCUT_ASSERT_INT_EQUALS(lf_can_create_pri | lf_ptype_uuid, linfo.flags);
280
281 rc = label_destroy(label);
282 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
283
284 /* There should be no label now */
285
286 rc = label_open(&lbd, &label);
287 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
288
289 rc = label_get_info(label, &linfo);
290 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
291
292 PCUT_ASSERT_INT_EQUALS(lt_none, linfo.ltype);
293 PCUT_ASSERT_INT_EQUALS(0, linfo.flags);
294
295 label_close(label);
296
297 test_bd_destroy(bd);
298}
299
300PCUT_TEST(mbr_primary_part)
301{
302 label_t *label;
303 label_bd_t lbd;
304 label_info_t linfo;
305 label_part_t *part;
306 label_part_spec_t pspec;
307 label_part_info_t pinfo;
308 label_ptype_t ptype;
309 test_bd_t *bd = NULL;
310 errno_t rc;
311
312 rc = test_bd_create(test_block_size, test_nblocks, &bd);
313 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
314
315 lbd.ops = &label_test_ops;
316 lbd.arg = (void *)bd;
317
318 rc = label_create(&lbd, lt_mbr, &label);
319 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
320
321 rc = label_get_info(label, &linfo);
322 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
323
324 /* There should be no partitions */
325 part = label_part_first(label);
326 PCUT_ASSERT_NULL(part);
327
328 rc = label_suggest_ptype(label, lpc_ext4, &ptype);
329 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
330
331 memset(&pspec, 0, sizeof(pspec));
332 pspec.index = 1;
333 pspec.block0 = linfo.ablock0;
334 pspec.nblocks = linfo.anblocks;
335 pspec.hdr_blocks = 0;
336 pspec.pkind = lpk_primary;
337 pspec.ptype = ptype;
338
339 rc = label_part_create(label, &pspec, &part);
340 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
341
342 label_part_get_info(part, &pinfo);
343 PCUT_ASSERT_INT_EQUALS(1, pinfo.index);
344 PCUT_ASSERT_INT_EQUALS(lpk_primary, pinfo.pkind);
345 PCUT_ASSERT_INT_EQUALS(linfo.ablock0, pinfo.block0);
346 PCUT_ASSERT_INT_EQUALS(linfo.anblocks, pinfo.nblocks);
347
348 /* Close and reopen */
349 label_close(label);
350
351 rc = label_open(&lbd, &label);
352 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
353
354 rc = label_get_info(label, &linfo);
355 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
356
357 PCUT_ASSERT_INT_EQUALS(lt_mbr, linfo.ltype);
358 PCUT_ASSERT_INT_EQUALS(lf_ext_supp | lf_can_create_pri |
359 lf_can_create_ext | lf_can_delete_part | lf_can_modify_part,
360 linfo.flags);
361
362 part = label_part_first(label);
363 PCUT_ASSERT_NOT_NULL(part);
364 PCUT_ASSERT_NULL(label_part_next(part));
365
366 label_part_get_info(part, &pinfo);
367 PCUT_ASSERT_INT_EQUALS(1, pinfo.index);
368 PCUT_ASSERT_INT_EQUALS(lpk_primary, pinfo.pkind);
369 PCUT_ASSERT_INT_EQUALS(linfo.ablock0, pinfo.block0);
370 PCUT_ASSERT_INT_EQUALS(linfo.anblocks, pinfo.nblocks);
371
372 /* Destroy the partition */
373 rc = label_part_destroy(part);
374 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
375
376 /* Close and reopen */
377 label_close(label);
378
379 rc = label_open(&lbd, &label);
380 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
381
382 /* There should be no partitions */
383 part = label_part_first(label);
384 PCUT_ASSERT_NULL(part);
385
386 label_close(label);
387
388 test_bd_destroy(bd);
389}
390
391PCUT_TEST(mbr_logical_part)
392{
393 label_t *label;
394 label_bd_t lbd;
395 label_info_t linfo;
396 label_part_t *part, *lpart, *epart;
397 label_part_spec_t pspec;
398 label_ptype_t ptype;
399 label_part_info_t pinfo, lpinfo, epinfo;
400 test_bd_t *bd = NULL;
401 errno_t rc;
402
403 rc = test_bd_create(test_block_size, test_nblocks, &bd);
404 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
405
406 lbd.ops = &label_test_ops;
407 lbd.arg = (void *)bd;
408
409 rc = label_create(&lbd, lt_mbr, &label);
410 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
411
412 rc = label_get_info(label, &linfo);
413 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
414
415 /* There should be no partitions */
416 part = label_part_first(label);
417 PCUT_ASSERT_NULL(part);
418
419 memset(&pspec, 0, sizeof(pspec));
420 pspec.index = 1;
421 pspec.block0 = linfo.ablock0;
422 pspec.nblocks = linfo.anblocks;
423 pspec.hdr_blocks = 0;
424 pspec.pkind = lpk_extended;
425
426 rc = label_part_create(label, &pspec, &epart);
427 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
428
429 label_part_get_info(epart, &epinfo);
430 PCUT_ASSERT_INT_EQUALS(1, epinfo.index);
431 PCUT_ASSERT_INT_EQUALS(lpk_extended, epinfo.pkind);
432 PCUT_ASSERT_INT_EQUALS(linfo.ablock0, epinfo.block0);
433 PCUT_ASSERT_INT_EQUALS(linfo.anblocks, epinfo.nblocks);
434
435 /* Close and reopen */
436 label_close(label);
437
438 rc = label_open(&lbd, &label);
439 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
440
441 rc = label_get_info(label, &linfo);
442 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
443
444 PCUT_ASSERT_INT_EQUALS(lt_mbr, linfo.ltype);
445 PCUT_ASSERT_INT_EQUALS(lf_ext_supp | lf_can_create_pri |
446 lf_can_create_log | lf_can_delete_part | lf_can_modify_part,
447 linfo.flags);
448
449 epart = label_part_first(label);
450 PCUT_ASSERT_NOT_NULL(epart);
451 PCUT_ASSERT_NULL(label_part_next(epart));
452
453 label_part_get_info(epart, &epinfo);
454 PCUT_ASSERT_INT_EQUALS(1, epinfo.index);
455 PCUT_ASSERT_INT_EQUALS(lpk_extended, epinfo.pkind);
456 PCUT_ASSERT_INT_EQUALS(linfo.ablock0, epinfo.block0);
457 PCUT_ASSERT_INT_EQUALS(linfo.anblocks, epinfo.nblocks);
458
459 /* Create logical partition */
460 rc = label_suggest_ptype(label, lpc_ext4, &ptype);
461 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
462
463 memset(&pspec, 0, sizeof(pspec));
464 pspec.index = 0;
465 pspec.block0 = epinfo.block0 + 1;
466 pspec.nblocks = epinfo.nblocks - 1;
467 pspec.hdr_blocks = 1;
468 pspec.pkind = lpk_logical;
469 pspec.ptype = ptype;
470
471 rc = label_part_create(label, &pspec, &lpart);
472 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
473
474 label_part_get_info(lpart, &lpinfo);
475 PCUT_ASSERT_INT_EQUALS(5, lpinfo.index);
476 PCUT_ASSERT_INT_EQUALS(lpk_logical, lpinfo.pkind);
477 PCUT_ASSERT_INT_EQUALS(epinfo.block0 + 1, lpinfo.block0);
478 PCUT_ASSERT_INT_EQUALS(epinfo.nblocks - 1, lpinfo.nblocks);
479
480 /* Close and reopen */
481 label_close(label);
482
483 rc = label_open(&lbd, &label);
484 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
485
486 /* Find the extended and the logical partition */
487
488 epart = NULL;
489 lpart = NULL;
490
491 part = label_part_first(label);
492 while (part != NULL) {
493 label_part_get_info(part, &pinfo);
494 if (pinfo.pkind == lpk_extended) {
495 epart = part;
496 } else {
497 PCUT_ASSERT_INT_EQUALS(lpk_logical, pinfo.pkind);
498 lpart = part;
499 }
500
501 part = label_part_next(part);
502 }
503
504 PCUT_ASSERT_NOT_NULL(epart);
505 PCUT_ASSERT_NOT_NULL(lpart);
506
507 /* Destroy the logical partition */
508 rc = label_part_destroy(lpart);
509 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
510
511 /* Destroy the extended partition */
512 rc = label_part_destroy(epart);
513 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
514
515 /* Close and reopen */
516 label_close(label);
517
518 rc = label_open(&lbd, &label);
519 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
520
521 /* There should be no partitions */
522 part = label_part_first(label);
523 PCUT_ASSERT_NULL(part);
524
525 label_close(label);
526
527 test_bd_destroy(bd);
528}
529
530PCUT_TEST(gpt_part)
531{
532 label_t *label;
533 label_bd_t lbd;
534 label_info_t linfo;
535 label_part_t *part;
536 label_part_spec_t pspec;
537 label_part_info_t pinfo;
538 label_ptype_t ptype;
539 test_bd_t *bd = NULL;
540 errno_t rc;
541
542 rc = test_bd_create(test_block_size, test_nblocks, &bd);
543 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
544
545 lbd.ops = &label_test_ops;
546 lbd.arg = (void *)bd;
547
548 rc = label_create(&lbd, lt_gpt, &label);
549 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
550
551 rc = label_get_info(label, &linfo);
552 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
553
554 /* There should be no partitions */
555 part = label_part_first(label);
556 PCUT_ASSERT_NULL(part);
557
558 rc = label_suggest_ptype(label, lpc_ext4, &ptype);
559 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
560
561 memset(&pspec, 0, sizeof(pspec));
562 pspec.index = 1;
563 pspec.block0 = linfo.ablock0;
564 pspec.nblocks = linfo.anblocks;
565 pspec.hdr_blocks = 0;
566 pspec.pkind = lpk_primary;
567 pspec.ptype = ptype;
568
569 rc = label_part_create(label, &pspec, &part);
570 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
571
572 label_part_get_info(part, &pinfo);
573 PCUT_ASSERT_INT_EQUALS(1, pinfo.index);
574 PCUT_ASSERT_INT_EQUALS(lpk_primary, pinfo.pkind);
575 PCUT_ASSERT_INT_EQUALS(linfo.ablock0, pinfo.block0);
576 PCUT_ASSERT_INT_EQUALS(linfo.anblocks, pinfo.nblocks);
577
578 /* Close and reopen */
579 label_close(label);
580
581 rc = label_open(&lbd, &label);
582 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
583
584 rc = label_get_info(label, &linfo);
585 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
586
587 PCUT_ASSERT_INT_EQUALS(lt_gpt, linfo.ltype);
588 PCUT_ASSERT_INT_EQUALS(lf_can_create_pri | lf_ptype_uuid |
589 lf_can_delete_part | lf_can_modify_part, linfo.flags);
590
591 part = label_part_first(label);
592 PCUT_ASSERT_NOT_NULL(part);
593 PCUT_ASSERT_NULL(label_part_next(part));
594
595 label_part_get_info(part, &pinfo);
596 PCUT_ASSERT_INT_EQUALS(1, pinfo.index);
597 PCUT_ASSERT_INT_EQUALS(lpk_primary, pinfo.pkind);
598 PCUT_ASSERT_INT_EQUALS(linfo.ablock0, pinfo.block0);
599 PCUT_ASSERT_INT_EQUALS(linfo.anblocks, pinfo.nblocks);
600
601 /* Destroy the partition */
602 rc = label_part_destroy(part);
603 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
604
605 /* Close and reopen */
606 label_close(label);
607
608 rc = label_open(&lbd, &label);
609 PCUT_ASSERT_ERRNO_VAL(EOK, rc);
610
611 /* There should be no partitions */
612 part = label_part_first(label);
613 PCUT_ASSERT_NULL(part);
614
615 label_close(label);
616
617 test_bd_destroy(bd);
618}
619
620PCUT_EXPORT(label);
Note: See TracBrowser for help on using the repository browser.