xref: /freebsd/contrib/processor-trace/libipt/test/src/ptunit-section.c (revision 2e3507c25e42292b45a5482e116d278f5515d04d)
1 /*
2  * Copyright (c) 2013-2019, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *  * Redistributions of source code must retain the above copyright notice,
8  *    this list of conditions and the following disclaimer.
9  *  * Redistributions in binary form must reproduce the above copyright notice,
10  *    this list of conditions and the following disclaimer in the documentation
11  *    and/or other materials provided with the distribution.
12  *  * Neither the name of Intel Corporation nor the names of its contributors
13  *    may be used to endorse or promote products derived from this software
14  *    without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "ptunit_threads.h"
30 #include "ptunit_mkfile.h"
31 
32 #include "pt_section.h"
33 #include "pt_block_cache.h"
34 
35 #include "intel-pt.h"
36 
37 #include <stdlib.h>
38 #include <stdio.h>
39 
40 
41 
42 struct pt_image_section_cache {
43 	int map;
44 };
45 
46 extern int pt_iscache_notify_map(struct pt_image_section_cache *iscache,
47 				 struct pt_section *section);
48 extern int pt_iscache_notify_resize(struct pt_image_section_cache *iscache,
49 				    struct pt_section *section, uint64_t size);
50 
51 int pt_iscache_notify_map(struct pt_image_section_cache *iscache,
52 			  struct pt_section *section)
53 {
54 	if (!iscache)
55 		return -pte_internal;
56 
57 	if (iscache->map <= 0)
58 		return iscache->map;
59 
60 	/* Avoid recursion. */
61 	iscache->map = 0;
62 
63 	return pt_section_map_share(section);
64 }
65 
66 int pt_iscache_notify_resize(struct pt_image_section_cache *iscache,
67 			     struct pt_section *section, uint64_t size)
68 {
69 	uint64_t memsize;
70 	int errcode;
71 
72 	if (!iscache)
73 		return -pte_internal;
74 
75 	if (iscache->map <= 0)
76 		return iscache->map;
77 
78 	/* Avoid recursion. */
79 	iscache->map = 0;
80 
81 	errcode = pt_section_memsize(section, &memsize);
82 	if (errcode < 0)
83 		return errcode;
84 
85 	if (size != memsize)
86 		return -pte_internal;
87 
88 	return pt_section_map_share(section);
89 }
90 
91 struct pt_block_cache *pt_bcache_alloc(uint64_t nentries)
92 {
93 	struct pt_block_cache *bcache;
94 
95 	if (!nentries || (UINT32_MAX < nentries))
96 		return NULL;
97 
98 	/* The cache is not really used by tests.  It suffices to allocate only
99 	 * the cache struct with the single default entry.
100 	 *
101 	 * We still set the number of entries to the requested size.
102 	 */
103 	bcache = malloc(sizeof(*bcache));
104 	if (bcache)
105 		bcache->nentries = (uint32_t) nentries;
106 
107 	return bcache;
108 }
109 
110 void pt_bcache_free(struct pt_block_cache *bcache)
111 {
112 	free(bcache);
113 }
114 
115 /* A test fixture providing a temporary file and an initially NULL section. */
116 struct section_fixture {
117 	/* Threading support. */
118 	struct ptunit_thrd_fixture thrd;
119 
120 	/* A temporary file name. */
121 	char *name;
122 
123 	/* That file opened for writing. */
124 	FILE *file;
125 
126 	/* The section. */
127 	struct pt_section *section;
128 
129 	/* The test fixture initialization and finalization functions. */
130 	struct ptunit_result (*init)(struct section_fixture *);
131 	struct ptunit_result (*fini)(struct section_fixture *);
132 };
133 
134 enum {
135 #if defined(FEATURE_THREADS)
136 
137 	num_threads	= 4,
138 
139 #endif /* defined(FEATURE_THREADS) */
140 
141 	num_work	= 0x4000
142 };
143 
144 static struct ptunit_result sfix_write_aux(struct section_fixture *sfix,
145 					   const uint8_t *buffer, size_t size)
146 {
147 	size_t written;
148 
149 	written = fwrite(buffer, 1, size, sfix->file);
150 	ptu_uint_eq(written, size);
151 
152 	fflush(sfix->file);
153 
154 	return ptu_passed();
155 }
156 
157 #define sfix_write(sfix, buffer)				\
158 	ptu_check(sfix_write_aux, sfix, buffer, sizeof(buffer))
159 
160 static struct ptunit_result create(struct section_fixture *sfix)
161 {
162 	const char *name;
163 	uint8_t bytes[] = { 0xcc, 0xcc, 0xcc, 0xcc, 0xcc };
164 	uint64_t offset, size;
165 	int errcode;
166 
167 	sfix_write(sfix, bytes);
168 
169 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
170 	ptu_int_eq(errcode, 0);
171 	ptu_ptr(sfix->section);
172 
173 	name = pt_section_filename(sfix->section);
174 	ptu_str_eq(name, sfix->name);
175 
176 	offset = pt_section_offset(sfix->section);
177 	ptu_uint_eq(offset, 0x1ull);
178 
179 	size = pt_section_size(sfix->section);
180 	ptu_uint_eq(size, 0x3ull);
181 
182 	return ptu_passed();
183 }
184 
185 static struct ptunit_result create_bad_offset(struct section_fixture *sfix)
186 {
187 	int errcode;
188 
189 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x10ull, 0x0ull);
190 	ptu_int_eq(errcode, -pte_invalid);
191 
192 	return ptu_passed();
193 }
194 
195 static struct ptunit_result create_truncated(struct section_fixture *sfix)
196 {
197 	const char *name;
198 	uint8_t bytes[] = { 0xcc, 0xcc, 0xcc, 0xcc, 0xcc };
199 	uint64_t offset, size;
200 	int errcode;
201 
202 	sfix_write(sfix, bytes);
203 
204 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, UINT64_MAX);
205 	ptu_int_eq(errcode, 0);
206 	ptu_ptr(sfix->section);
207 
208 	name = pt_section_filename(sfix->section);
209 	ptu_str_eq(name, sfix->name);
210 
211 	offset = pt_section_offset(sfix->section);
212 	ptu_uint_eq(offset, 0x1ull);
213 
214 	size = pt_section_size(sfix->section);
215 	ptu_uint_eq(size, sizeof(bytes) - 1);
216 
217 	return ptu_passed();
218 }
219 
220 static struct ptunit_result create_empty(struct section_fixture *sfix)
221 {
222 	int errcode;
223 
224 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x0ull, 0x10ull);
225 	ptu_int_eq(errcode, -pte_invalid);
226 	ptu_null(sfix->section);
227 
228 	return ptu_passed();
229 }
230 
231 static struct ptunit_result filename_null(void)
232 {
233 	const char *name;
234 
235 	name = pt_section_filename(NULL);
236 	ptu_null(name);
237 
238 	return ptu_passed();
239 }
240 
241 static struct ptunit_result size_null(void)
242 {
243 	uint64_t size;
244 
245 	size = pt_section_size(NULL);
246 	ptu_uint_eq(size, 0ull);
247 
248 	return ptu_passed();
249 }
250 
251 static struct ptunit_result memsize_null(struct section_fixture *sfix)
252 {
253 	uint64_t size;
254 	int errcode;
255 
256 	errcode = pt_section_memsize(NULL, &size);
257 	ptu_int_eq(errcode, -pte_internal);
258 
259 	errcode = pt_section_memsize(sfix->section, NULL);
260 	ptu_int_eq(errcode, -pte_internal);
261 
262 	errcode = pt_section_memsize(NULL, NULL);
263 	ptu_int_eq(errcode, -pte_internal);
264 
265 	return ptu_passed();
266 }
267 
268 static struct ptunit_result offset_null(void)
269 {
270 	uint64_t offset;
271 
272 	offset = pt_section_offset(NULL);
273 	ptu_uint_eq(offset, 0ull);
274 
275 	return ptu_passed();
276 }
277 
278 static struct ptunit_result get_null(void)
279 {
280 	int errcode;
281 
282 	errcode = pt_section_get(NULL);
283 	ptu_int_eq(errcode, -pte_internal);
284 
285 	return ptu_passed();
286 }
287 
288 static struct ptunit_result put_null(void)
289 {
290 	int errcode;
291 
292 	errcode = pt_section_put(NULL);
293 	ptu_int_eq(errcode, -pte_internal);
294 
295 	return ptu_passed();
296 }
297 
298 static struct ptunit_result attach_null(void)
299 {
300 	struct pt_image_section_cache iscache;
301 	struct pt_section section;
302 	int errcode;
303 
304 	errcode = pt_section_attach(NULL, &iscache);
305 	ptu_int_eq(errcode, -pte_internal);
306 
307 	errcode = pt_section_attach(&section, NULL);
308 	ptu_int_eq(errcode, -pte_internal);
309 
310 	errcode = pt_section_attach(NULL, NULL);
311 	ptu_int_eq(errcode, -pte_internal);
312 
313 	return ptu_passed();
314 }
315 
316 static struct ptunit_result detach_null(void)
317 {
318 	struct pt_image_section_cache iscache;
319 	struct pt_section section;
320 	int errcode;
321 
322 	errcode = pt_section_detach(NULL, &iscache);
323 	ptu_int_eq(errcode, -pte_internal);
324 
325 	errcode = pt_section_detach(&section, NULL);
326 	ptu_int_eq(errcode, -pte_internal);
327 
328 	errcode = pt_section_detach(NULL, NULL);
329 	ptu_int_eq(errcode, -pte_internal);
330 
331 	return ptu_passed();
332 }
333 
334 static struct ptunit_result map_null(void)
335 {
336 	int errcode;
337 
338 	errcode = pt_section_map(NULL);
339 	ptu_int_eq(errcode, -pte_internal);
340 
341 	return ptu_passed();
342 }
343 
344 static struct ptunit_result unmap_null(void)
345 {
346 	int errcode;
347 
348 	errcode = pt_section_unmap(NULL);
349 	ptu_int_eq(errcode, -pte_internal);
350 
351 	return ptu_passed();
352 }
353 
354 static struct ptunit_result cache_null(void)
355 {
356 	struct pt_block_cache *bcache;
357 
358 	bcache = pt_section_bcache(NULL);
359 	ptu_null(bcache);
360 
361 	return ptu_passed();
362 }
363 
364 static struct ptunit_result get_overflow(struct section_fixture *sfix)
365 {
366 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
367 	int errcode;
368 
369 	sfix_write(sfix, bytes);
370 
371 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
372 	ptu_int_eq(errcode, 0);
373 	ptu_ptr(sfix->section);
374 
375 	sfix->section->ucount = UINT16_MAX;
376 
377 	errcode = pt_section_get(sfix->section);
378 	ptu_int_eq(errcode, -pte_overflow);
379 
380 	sfix->section->ucount = 1;
381 
382 	return ptu_passed();
383 }
384 
385 static struct ptunit_result attach_overflow(struct section_fixture *sfix)
386 {
387 	struct pt_image_section_cache iscache;
388 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
389 	int errcode;
390 
391 	sfix_write(sfix, bytes);
392 
393 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
394 	ptu_int_eq(errcode, 0);
395 	ptu_ptr(sfix->section);
396 
397 	sfix->section->acount = UINT16_MAX;
398 
399 	errcode = pt_section_attach(sfix->section, &iscache);
400 	ptu_int_eq(errcode, -pte_overflow);
401 
402 	sfix->section->acount = 0;
403 
404 	return ptu_passed();
405 }
406 
407 static struct ptunit_result attach_bad_ucount(struct section_fixture *sfix)
408 {
409 	struct pt_image_section_cache iscache;
410 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
411 	int errcode;
412 
413 	sfix_write(sfix, bytes);
414 
415 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
416 	ptu_int_eq(errcode, 0);
417 	ptu_ptr(sfix->section);
418 
419 	sfix->section->acount = 2;
420 
421 	errcode = pt_section_attach(sfix->section, &iscache);
422 	ptu_int_eq(errcode, -pte_internal);
423 
424 	sfix->section->acount = 0;
425 
426 	return ptu_passed();
427 }
428 
429 static struct ptunit_result map_change(struct section_fixture *sfix)
430 {
431 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
432 	int errcode;
433 
434 	sfix_write(sfix, bytes);
435 
436 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
437 	ptu_int_eq(errcode, 0);
438 	ptu_ptr(sfix->section);
439 
440 	sfix_write(sfix, bytes);
441 
442 	errcode = pt_section_map(sfix->section);
443 	ptu_int_eq(errcode, -pte_bad_image);
444 
445 	return ptu_passed();
446 }
447 
448 static struct ptunit_result map_put(struct section_fixture *sfix)
449 {
450 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
451 	int errcode;
452 
453 	sfix_write(sfix, bytes);
454 
455 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
456 	ptu_int_eq(errcode, 0);
457 	ptu_ptr(sfix->section);
458 
459 	errcode = pt_section_map(sfix->section);
460 	ptu_int_eq(errcode, 0);
461 
462 	errcode = pt_section_put(sfix->section);
463 	ptu_int_eq(errcode, -pte_internal);
464 
465 	errcode = pt_section_unmap(sfix->section);
466 	ptu_int_eq(errcode, 0);
467 
468 	return ptu_passed();
469 }
470 
471 static struct ptunit_result unmap_nomap(struct section_fixture *sfix)
472 {
473 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
474 	int errcode;
475 
476 	sfix_write(sfix, bytes);
477 
478 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
479 	ptu_int_eq(errcode, 0);
480 	ptu_ptr(sfix->section);
481 
482 	errcode = pt_section_unmap(sfix->section);
483 	ptu_int_eq(errcode, -pte_nomap);
484 
485 	return ptu_passed();
486 }
487 
488 static struct ptunit_result map_overflow(struct section_fixture *sfix)
489 {
490 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
491 	int errcode;
492 
493 	sfix_write(sfix, bytes);
494 
495 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
496 	ptu_int_eq(errcode, 0);
497 	ptu_ptr(sfix->section);
498 
499 	sfix->section->mcount = UINT16_MAX;
500 
501 	errcode = pt_section_map(sfix->section);
502 	ptu_int_eq(errcode, -pte_overflow);
503 
504 	sfix->section->mcount = 0;
505 
506 	return ptu_passed();
507 }
508 
509 static struct ptunit_result get_put(struct section_fixture *sfix)
510 {
511 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
512 	int errcode;
513 
514 	sfix_write(sfix, bytes);
515 
516 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
517 	ptu_int_eq(errcode, 0);
518 	ptu_ptr(sfix->section);
519 
520 	errcode = pt_section_get(sfix->section);
521 	ptu_int_eq(errcode, 0);
522 
523 	errcode = pt_section_get(sfix->section);
524 	ptu_int_eq(errcode, 0);
525 
526 	errcode = pt_section_put(sfix->section);
527 	ptu_int_eq(errcode, 0);
528 
529 	errcode = pt_section_put(sfix->section);
530 	ptu_int_eq(errcode, 0);
531 
532 	return ptu_passed();
533 }
534 
535 static struct ptunit_result attach_detach(struct section_fixture *sfix)
536 {
537 	struct pt_image_section_cache iscache;
538 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
539 	int errcode;
540 
541 	sfix_write(sfix, bytes);
542 
543 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
544 	ptu_int_eq(errcode, 0);
545 	ptu_ptr(sfix->section);
546 
547 	sfix->section->ucount += 2;
548 
549 	errcode = pt_section_attach(sfix->section, &iscache);
550 	ptu_int_eq(errcode, 0);
551 
552 	errcode = pt_section_attach(sfix->section, &iscache);
553 	ptu_int_eq(errcode, 0);
554 
555 	errcode = pt_section_detach(sfix->section, &iscache);
556 	ptu_int_eq(errcode, 0);
557 
558 	errcode = pt_section_detach(sfix->section, &iscache);
559 	ptu_int_eq(errcode, 0);
560 
561 	sfix->section->ucount -= 2;
562 
563 	return ptu_passed();
564 }
565 
566 static struct ptunit_result attach_bad_iscache(struct section_fixture *sfix)
567 {
568 	struct pt_image_section_cache iscache, bad;
569 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
570 	int errcode;
571 
572 	sfix_write(sfix, bytes);
573 
574 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
575 	ptu_int_eq(errcode, 0);
576 	ptu_ptr(sfix->section);
577 
578 	sfix->section->ucount += 2;
579 
580 	errcode = pt_section_attach(sfix->section, &iscache);
581 	ptu_int_eq(errcode, 0);
582 
583 	errcode = pt_section_attach(sfix->section, &bad);
584 	ptu_int_eq(errcode, -pte_internal);
585 
586 	errcode = pt_section_detach(sfix->section, &iscache);
587 	ptu_int_eq(errcode, 0);
588 
589 	sfix->section->ucount -= 2;
590 
591 	return ptu_passed();
592 }
593 
594 static struct ptunit_result detach_bad_iscache(struct section_fixture *sfix)
595 {
596 	struct pt_image_section_cache iscache, bad;
597 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
598 	int errcode;
599 
600 	sfix_write(sfix, bytes);
601 
602 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
603 	ptu_int_eq(errcode, 0);
604 	ptu_ptr(sfix->section);
605 
606 	errcode = pt_section_attach(sfix->section, &iscache);
607 	ptu_int_eq(errcode, 0);
608 
609 	errcode = pt_section_detach(sfix->section, &bad);
610 	ptu_int_eq(errcode, -pte_internal);
611 
612 	errcode = pt_section_detach(sfix->section, &iscache);
613 	ptu_int_eq(errcode, 0);
614 
615 	return ptu_passed();
616 }
617 
618 static struct ptunit_result map_unmap(struct section_fixture *sfix)
619 {
620 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
621 	int errcode;
622 
623 	sfix_write(sfix, bytes);
624 
625 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
626 	ptu_int_eq(errcode, 0);
627 	ptu_ptr(sfix->section);
628 
629 	errcode = pt_section_map(sfix->section);
630 	ptu_int_eq(errcode, 0);
631 
632 	errcode = pt_section_map(sfix->section);
633 	ptu_int_eq(errcode, 0);
634 
635 	errcode = pt_section_unmap(sfix->section);
636 	ptu_int_eq(errcode, 0);
637 
638 	errcode = pt_section_unmap(sfix->section);
639 	ptu_int_eq(errcode, 0);
640 
641 	return ptu_passed();
642 }
643 
644 static struct ptunit_result attach_map(struct section_fixture *sfix)
645 {
646 	struct pt_image_section_cache iscache;
647 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
648 	int errcode;
649 
650 	iscache.map = 0;
651 
652 	sfix_write(sfix, bytes);
653 
654 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
655 	ptu_int_eq(errcode, 0);
656 	ptu_ptr(sfix->section);
657 
658 	errcode = pt_section_attach(sfix->section, &iscache);
659 	ptu_int_eq(errcode, 0);
660 
661 	errcode = pt_section_map(sfix->section);
662 	ptu_int_eq(errcode, 0);
663 
664 	errcode = pt_section_map(sfix->section);
665 	ptu_int_eq(errcode, 0);
666 
667 	ptu_uint_eq(sfix->section->mcount, 2);
668 
669 	errcode = pt_section_unmap(sfix->section);
670 	ptu_int_eq(errcode, 0);
671 
672 	errcode = pt_section_unmap(sfix->section);
673 	ptu_int_eq(errcode, 0);
674 
675 	errcode = pt_section_detach(sfix->section, &iscache);
676 	ptu_int_eq(errcode, 0);
677 
678 	return ptu_passed();
679 }
680 
681 static struct ptunit_result attach_bad_map(struct section_fixture *sfix)
682 {
683 	struct pt_image_section_cache iscache;
684 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
685 	int errcode;
686 
687 	iscache.map = -pte_eos;
688 
689 	sfix_write(sfix, bytes);
690 
691 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
692 	ptu_int_eq(errcode, 0);
693 	ptu_ptr(sfix->section);
694 
695 	errcode = pt_section_attach(sfix->section, &iscache);
696 	ptu_int_eq(errcode, 0);
697 
698 	errcode = pt_section_map(sfix->section);
699 	ptu_int_eq(errcode, -pte_eos);
700 
701 	errcode = pt_section_detach(sfix->section, &iscache);
702 	ptu_int_eq(errcode, 0);
703 
704 	return ptu_passed();
705 }
706 
707 static struct ptunit_result attach_map_overflow(struct section_fixture *sfix)
708 {
709 	struct pt_image_section_cache iscache;
710 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
711 	int errcode;
712 
713 	iscache.map = 1;
714 
715 	sfix_write(sfix, bytes);
716 
717 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
718 	ptu_int_eq(errcode, 0);
719 	ptu_ptr(sfix->section);
720 
721 	errcode = pt_section_attach(sfix->section, &iscache);
722 	ptu_int_eq(errcode, 0);
723 
724 	sfix->section->mcount = UINT16_MAX - 1;
725 
726 	errcode = pt_section_map(sfix->section);
727 	ptu_int_eq(errcode, -pte_overflow);
728 
729 	errcode = pt_section_detach(sfix->section, &iscache);
730 	ptu_int_eq(errcode, 0);
731 
732 	return ptu_passed();
733 }
734 
735 static struct ptunit_result read(struct section_fixture *sfix)
736 {
737 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
738 	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
739 	int status;
740 
741 	sfix_write(sfix, bytes);
742 
743 	status = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
744 	ptu_int_eq(status, 0);
745 	ptu_ptr(sfix->section);
746 
747 	status = pt_section_map(sfix->section);
748 	ptu_int_eq(status, 0);
749 
750 	status = pt_section_read(sfix->section, buffer, 2, 0x0ull);
751 	ptu_int_eq(status, 2);
752 	ptu_uint_eq(buffer[0], bytes[1]);
753 	ptu_uint_eq(buffer[1], bytes[2]);
754 	ptu_uint_eq(buffer[2], 0xcc);
755 
756 	status = pt_section_unmap(sfix->section);
757 	ptu_int_eq(status, 0);
758 
759 	return ptu_passed();
760 }
761 
762 static struct ptunit_result read_null(struct section_fixture *sfix)
763 {
764 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
765 	uint8_t buffer[] = { 0xcc };
766 	int status;
767 
768 	sfix_write(sfix, bytes);
769 
770 	status = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
771 	ptu_int_eq(status, 0);
772 	ptu_ptr(sfix->section);
773 
774 	status = pt_section_map(sfix->section);
775 	ptu_int_eq(status, 0);
776 
777 	status = pt_section_read(sfix->section, NULL, 1, 0x0ull);
778 	ptu_int_eq(status, -pte_internal);
779 	ptu_uint_eq(buffer[0], 0xcc);
780 
781 	status = pt_section_read(NULL, buffer, 1, 0x0ull);
782 	ptu_int_eq(status, -pte_internal);
783 	ptu_uint_eq(buffer[0], 0xcc);
784 
785 	status = pt_section_unmap(sfix->section);
786 	ptu_int_eq(status, 0);
787 
788 	return ptu_passed();
789 }
790 
791 static struct ptunit_result read_offset(struct section_fixture *sfix)
792 {
793 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
794 	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
795 	int status;
796 
797 	sfix_write(sfix, bytes);
798 
799 	status = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
800 	ptu_int_eq(status, 0);
801 	ptu_ptr(sfix->section);
802 
803 	status = pt_section_map(sfix->section);
804 	ptu_int_eq(status, 0);
805 
806 	status = pt_section_read(sfix->section, buffer, 2, 0x1ull);
807 	ptu_int_eq(status, 2);
808 	ptu_uint_eq(buffer[0], bytes[2]);
809 	ptu_uint_eq(buffer[1], bytes[3]);
810 	ptu_uint_eq(buffer[2], 0xcc);
811 
812 	status = pt_section_unmap(sfix->section);
813 	ptu_int_eq(status, 0);
814 
815 	return ptu_passed();
816 }
817 
818 static struct ptunit_result read_truncated(struct section_fixture *sfix)
819 {
820 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc, 0xcc };
821 	int status;
822 
823 	sfix_write(sfix, bytes);
824 
825 	status = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
826 	ptu_int_eq(status, 0);
827 	ptu_ptr(sfix->section);
828 
829 	status = pt_section_map(sfix->section);
830 	ptu_int_eq(status, 0);
831 
832 	status = pt_section_read(sfix->section, buffer, 2, 0x2ull);
833 	ptu_int_eq(status, 1);
834 	ptu_uint_eq(buffer[0], bytes[3]);
835 	ptu_uint_eq(buffer[1], 0xcc);
836 
837 	status = pt_section_unmap(sfix->section);
838 	ptu_int_eq(status, 0);
839 
840 	return ptu_passed();
841 }
842 
843 static struct ptunit_result read_from_truncated(struct section_fixture *sfix)
844 {
845 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc, 0xcc };
846 	int status;
847 
848 	sfix_write(sfix, bytes);
849 
850 	status = pt_mk_section(&sfix->section, sfix->name, 0x2ull, 0x10ull);
851 	ptu_int_eq(status, 0);
852 	ptu_ptr(sfix->section);
853 
854 	status = pt_section_map(sfix->section);
855 	ptu_int_eq(status, 0);
856 
857 	status = pt_section_read(sfix->section, buffer, 2, 0x1ull);
858 	ptu_int_eq(status, 1);
859 	ptu_uint_eq(buffer[0], bytes[3]);
860 	ptu_uint_eq(buffer[1], 0xcc);
861 
862 	status = pt_section_unmap(sfix->section);
863 	ptu_int_eq(status, 0);
864 
865 	return ptu_passed();
866 }
867 
868 static struct ptunit_result read_nomem(struct section_fixture *sfix)
869 {
870 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc };
871 	int status;
872 
873 	sfix_write(sfix, bytes);
874 
875 	status = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
876 	ptu_int_eq(status, 0);
877 	ptu_ptr(sfix->section);
878 
879 	status = pt_section_map(sfix->section);
880 	ptu_int_eq(status, 0);
881 
882 	status = pt_section_read(sfix->section, buffer, 1, 0x3ull);
883 	ptu_int_eq(status, -pte_nomap);
884 	ptu_uint_eq(buffer[0], 0xcc);
885 
886 	status = pt_section_unmap(sfix->section);
887 	ptu_int_eq(status, 0);
888 
889 	return ptu_passed();
890 }
891 
892 static struct ptunit_result read_overflow(struct section_fixture *sfix)
893 {
894 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc };
895 	int status;
896 
897 	sfix_write(sfix, bytes);
898 
899 	status = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
900 	ptu_int_eq(status, 0);
901 	ptu_ptr(sfix->section);
902 
903 	status = pt_section_map(sfix->section);
904 	ptu_int_eq(status, 0);
905 
906 	status = pt_section_read(sfix->section, buffer, 1,
907 				 0xffffffffffff0000ull);
908 	ptu_int_eq(status, -pte_nomap);
909 	ptu_uint_eq(buffer[0], 0xcc);
910 
911 	status = pt_section_unmap(sfix->section);
912 	ptu_int_eq(status, 0);
913 
914 	return ptu_passed();
915 }
916 
917 static struct ptunit_result read_overflow_32bit(struct section_fixture *sfix)
918 {
919 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc };
920 	int status;
921 
922 	sfix_write(sfix, bytes);
923 
924 	status = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
925 	ptu_int_eq(status, 0);
926 	ptu_ptr(sfix->section);
927 
928 	status = pt_section_map(sfix->section);
929 	ptu_int_eq(status, 0);
930 
931 	status = pt_section_read(sfix->section, buffer, 1,
932 				 0xff00000000ull);
933 	ptu_int_eq(status, -pte_nomap);
934 	ptu_uint_eq(buffer[0], 0xcc);
935 
936 	status = pt_section_unmap(sfix->section);
937 	ptu_int_eq(status, 0);
938 
939 	return ptu_passed();
940 }
941 
942 static struct ptunit_result read_nomap(struct section_fixture *sfix)
943 {
944 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc };
945 	int status;
946 
947 	sfix_write(sfix, bytes);
948 
949 	status = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
950 	ptu_int_eq(status, 0);
951 	ptu_ptr(sfix->section);
952 
953 	status = pt_section_read(sfix->section, buffer, 1, 0x0ull);
954 	ptu_int_eq(status, -pte_nomap);
955 	ptu_uint_eq(buffer[0], 0xcc);
956 
957 	return ptu_passed();
958 }
959 
960 static struct ptunit_result read_unmap_map(struct section_fixture *sfix)
961 {
962 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
963 	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
964 	int status;
965 
966 	sfix_write(sfix, bytes);
967 
968 	status = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
969 	ptu_int_eq(status, 0);
970 	ptu_ptr(sfix->section);
971 
972 	status = pt_section_map(sfix->section);
973 	ptu_int_eq(status, 0);
974 
975 	status = pt_section_read(sfix->section, buffer, 2, 0x0ull);
976 	ptu_int_eq(status, 2);
977 	ptu_uint_eq(buffer[0], bytes[1]);
978 	ptu_uint_eq(buffer[1], bytes[2]);
979 	ptu_uint_eq(buffer[2], 0xcc);
980 
981 	memset(buffer, 0xcc, sizeof(buffer));
982 
983 	status = pt_section_unmap(sfix->section);
984 	ptu_int_eq(status, 0);
985 
986 	status = pt_section_read(sfix->section, buffer, 2, 0x0ull);
987 	ptu_int_eq(status, -pte_nomap);
988 	ptu_uint_eq(buffer[0], 0xcc);
989 	ptu_uint_eq(buffer[1], 0xcc);
990 	ptu_uint_eq(buffer[2], 0xcc);
991 
992 	status = pt_section_map(sfix->section);
993 	ptu_int_eq(status, 0);
994 
995 	status = pt_section_read(sfix->section, buffer, 2, 0x0ull);
996 	ptu_int_eq(status, 2);
997 	ptu_uint_eq(buffer[0], bytes[1]);
998 	ptu_uint_eq(buffer[1], bytes[2]);
999 	ptu_uint_eq(buffer[2], 0xcc);
1000 
1001 	status = pt_section_unmap(sfix->section);
1002 	ptu_int_eq(status, 0);
1003 
1004 	return ptu_passed();
1005 }
1006 
1007 static int worker_read(void *arg)
1008 {
1009 	struct section_fixture *sfix;
1010 	int it, errcode;
1011 
1012 	sfix = arg;
1013 	if (!sfix)
1014 		return -pte_internal;
1015 
1016 	for (it = 0; it < num_work; ++it) {
1017 		uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1018 		int read;
1019 
1020 		errcode = pt_section_get(sfix->section);
1021 		if (errcode < 0)
1022 			return errcode;
1023 
1024 		errcode = pt_section_map(sfix->section);
1025 		if (errcode < 0)
1026 			goto out_put;
1027 
1028 		read = pt_section_read(sfix->section, buffer, 2, 0x0ull);
1029 		if (read < 0)
1030 			goto out_unmap;
1031 
1032 		errcode = -pte_invalid;
1033 		if ((read != 2) || (buffer[0] != 0x2) || (buffer[1] != 0x4))
1034 			goto out_unmap;
1035 
1036 		errcode = pt_section_unmap(sfix->section);
1037 		if (errcode < 0)
1038 			goto out_put;
1039 
1040 		errcode = pt_section_put(sfix->section);
1041 		if (errcode < 0)
1042 			return errcode;
1043 	}
1044 
1045 	return 0;
1046 
1047 out_unmap:
1048 	(void) pt_section_unmap(sfix->section);
1049 
1050 out_put:
1051 	(void) pt_section_put(sfix->section);
1052 	return errcode;
1053 }
1054 
1055 static int worker_bcache(void *arg)
1056 {
1057 	struct section_fixture *sfix;
1058 	int it, errcode;
1059 
1060 	sfix = arg;
1061 	if (!sfix)
1062 		return -pte_internal;
1063 
1064 	errcode = pt_section_get(sfix->section);
1065 	if (errcode < 0)
1066 		return errcode;
1067 
1068 	for (it = 0; it < num_work; ++it) {
1069 		struct pt_block_cache *bcache;
1070 
1071 		errcode = pt_section_map(sfix->section);
1072 		if (errcode < 0)
1073 			goto out_put;
1074 
1075 		errcode = pt_section_request_bcache(sfix->section);
1076 		if (errcode < 0)
1077 			goto out_unmap;
1078 
1079 		bcache = pt_section_bcache(sfix->section);
1080 		if (!bcache) {
1081 			errcode = -pte_nomem;
1082 			goto out_unmap;
1083 		}
1084 
1085 		errcode = pt_section_unmap(sfix->section);
1086 		if (errcode < 0)
1087 			goto out_put;
1088 	}
1089 
1090 	return pt_section_put(sfix->section);
1091 
1092 out_unmap:
1093 	(void) pt_section_unmap(sfix->section);
1094 
1095 out_put:
1096 	(void) pt_section_put(sfix->section);
1097 	return errcode;
1098 }
1099 
1100 static struct ptunit_result stress(struct section_fixture *sfix,
1101 				   int (*worker)(void *))
1102 {
1103 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
1104 	int errcode;
1105 
1106 	sfix_write(sfix, bytes);
1107 
1108 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
1109 	ptu_int_eq(errcode, 0);
1110 	ptu_ptr(sfix->section);
1111 
1112 #if defined(FEATURE_THREADS)
1113 	{
1114 		int thrd;
1115 
1116 		for (thrd = 0; thrd < num_threads; ++thrd)
1117 			ptu_test(ptunit_thrd_create, &sfix->thrd, worker, sfix);
1118 	}
1119 #endif /* defined(FEATURE_THREADS) */
1120 
1121 	errcode = worker(sfix);
1122 	ptu_int_eq(errcode, 0);
1123 
1124 	return ptu_passed();
1125 }
1126 
1127 static struct ptunit_result init_no_bcache(struct section_fixture *sfix)
1128 {
1129 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
1130 	struct pt_block_cache *bcache;
1131 	int errcode;
1132 
1133 	sfix_write(sfix, bytes);
1134 
1135 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
1136 	ptu_int_eq(errcode, 0);
1137 	ptu_ptr(sfix->section);
1138 
1139 	errcode = pt_section_map(sfix->section);
1140 	ptu_int_eq(errcode, 0);
1141 
1142 	bcache = pt_section_bcache(sfix->section);
1143 	ptu_null(bcache);
1144 
1145 	errcode = pt_section_unmap(sfix->section);
1146 	ptu_int_eq(errcode, 0);
1147 
1148 	return ptu_passed();
1149 }
1150 
1151 static struct ptunit_result bcache_alloc_free(struct section_fixture *sfix)
1152 {
1153 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
1154 	struct pt_block_cache *bcache;
1155 	int errcode;
1156 
1157 	sfix_write(sfix, bytes);
1158 
1159 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
1160 	ptu_int_eq(errcode, 0);
1161 	ptu_ptr(sfix->section);
1162 
1163 	errcode = pt_section_map(sfix->section);
1164 	ptu_int_eq(errcode, 0);
1165 
1166 	errcode = pt_section_alloc_bcache(sfix->section);
1167 	ptu_int_eq(errcode, 0);
1168 
1169 	bcache = pt_section_bcache(sfix->section);
1170 	ptu_ptr(bcache);
1171 	ptu_uint_eq(bcache->nentries, sfix->section->size);
1172 
1173 	errcode = pt_section_unmap(sfix->section);
1174 	ptu_int_eq(errcode, 0);
1175 
1176 	bcache = pt_section_bcache(sfix->section);
1177 	ptu_null(bcache);
1178 
1179 	return ptu_passed();
1180 }
1181 
1182 static struct ptunit_result bcache_alloc_twice(struct section_fixture *sfix)
1183 {
1184 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
1185 	int errcode;
1186 
1187 	sfix_write(sfix, bytes);
1188 
1189 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
1190 	ptu_int_eq(errcode, 0);
1191 	ptu_ptr(sfix->section);
1192 
1193 	errcode = pt_section_map(sfix->section);
1194 	ptu_int_eq(errcode, 0);
1195 
1196 	errcode = pt_section_alloc_bcache(sfix->section);
1197 	ptu_int_eq(errcode, 0);
1198 
1199 	errcode = pt_section_alloc_bcache(sfix->section);
1200 	ptu_int_eq(errcode, 0);
1201 
1202 	errcode = pt_section_unmap(sfix->section);
1203 	ptu_int_eq(errcode, 0);
1204 
1205 	return ptu_passed();
1206 }
1207 
1208 static struct ptunit_result bcache_alloc_nomap(struct section_fixture *sfix)
1209 {
1210 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
1211 	int errcode;
1212 
1213 	sfix_write(sfix, bytes);
1214 
1215 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
1216 	ptu_int_eq(errcode, 0);
1217 	ptu_ptr(sfix->section);
1218 
1219 	errcode = pt_section_alloc_bcache(sfix->section);
1220 	ptu_int_eq(errcode, -pte_internal);
1221 
1222 	return ptu_passed();
1223 }
1224 
1225 static struct ptunit_result memsize_nomap(struct section_fixture *sfix)
1226 {
1227 	uint64_t memsize;
1228 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
1229 	int errcode;
1230 
1231 	sfix_write(sfix, bytes);
1232 
1233 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
1234 	ptu_int_eq(errcode, 0);
1235 	ptu_ptr(sfix->section);
1236 
1237 	errcode = pt_section_memsize(sfix->section, &memsize);
1238 	ptu_int_eq(errcode, 0);
1239 	ptu_uint_eq(memsize, 0ull);
1240 
1241 	return ptu_passed();
1242 }
1243 
1244 static struct ptunit_result memsize_unmap(struct section_fixture *sfix)
1245 {
1246 	uint64_t memsize;
1247 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
1248 	int errcode;
1249 
1250 	sfix_write(sfix, bytes);
1251 
1252 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
1253 	ptu_int_eq(errcode, 0);
1254 	ptu_ptr(sfix->section);
1255 
1256 	errcode = pt_section_map(sfix->section);
1257 	ptu_int_eq(errcode, 0);
1258 
1259 	errcode = pt_section_unmap(sfix->section);
1260 	ptu_int_eq(errcode, 0);
1261 
1262 	errcode = pt_section_memsize(sfix->section, &memsize);
1263 	ptu_int_eq(errcode, 0);
1264 	ptu_uint_eq(memsize, 0ull);
1265 
1266 	return ptu_passed();
1267 }
1268 
1269 static struct ptunit_result memsize_map_nobcache(struct section_fixture *sfix)
1270 {
1271 	uint64_t memsize;
1272 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
1273 	int errcode;
1274 
1275 	sfix_write(sfix, bytes);
1276 
1277 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
1278 	ptu_int_eq(errcode, 0);
1279 	ptu_ptr(sfix->section);
1280 
1281 	errcode = pt_section_map(sfix->section);
1282 	ptu_int_eq(errcode, 0);
1283 
1284 	memsize = 0xfefefefefefefefeull;
1285 
1286 	errcode = pt_section_memsize(sfix->section, &memsize);
1287 	ptu_int_eq(errcode, 0);
1288 	ptu_uint_ge(memsize, 0ull);
1289 	ptu_uint_le(memsize, 0x2000ull);
1290 
1291 	errcode = pt_section_unmap(sfix->section);
1292 	ptu_int_eq(errcode, 0);
1293 
1294 	return ptu_passed();
1295 }
1296 
1297 static struct ptunit_result memsize_map_bcache(struct section_fixture *sfix)
1298 {
1299 	uint64_t memsize;
1300 	uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 };
1301 	int errcode;
1302 
1303 	sfix_write(sfix, bytes);
1304 
1305 	errcode = pt_mk_section(&sfix->section, sfix->name, 0x1ull, 0x3ull);
1306 	ptu_int_eq(errcode, 0);
1307 	ptu_ptr(sfix->section);
1308 
1309 	errcode = pt_section_map(sfix->section);
1310 	ptu_int_eq(errcode, 0);
1311 
1312 	errcode = pt_section_alloc_bcache(sfix->section);
1313 	ptu_int_eq(errcode, 0);
1314 
1315 	errcode = pt_section_memsize(sfix->section, &memsize);
1316 	ptu_int_eq(errcode, 0);
1317 	ptu_uint_ge(memsize,
1318 		    sfix->section->size * sizeof(struct pt_bcache_entry));
1319 
1320 	errcode = pt_section_unmap(sfix->section);
1321 	ptu_int_eq(errcode, 0);
1322 
1323 	return ptu_passed();
1324 }
1325 
1326 static struct ptunit_result sfix_init(struct section_fixture *sfix)
1327 {
1328 	int errcode;
1329 
1330 	sfix->section = NULL;
1331 	sfix->file = NULL;
1332 	sfix->name = NULL;
1333 
1334 	errcode = ptunit_mkfile(&sfix->file, &sfix->name, "wb");
1335 	ptu_int_eq(errcode, 0);
1336 
1337 	ptu_test(ptunit_thrd_init, &sfix->thrd);
1338 
1339 	return ptu_passed();
1340 }
1341 
1342 static struct ptunit_result sfix_fini(struct section_fixture *sfix)
1343 {
1344 	char *filename;
1345 	FILE *file;
1346 	int thrd, errcode;
1347 
1348 	ptu_test(ptunit_thrd_fini, &sfix->thrd);
1349 
1350 	if (sfix->section) {
1351 		pt_section_put(sfix->section);
1352 		sfix->section = NULL;
1353 	}
1354 
1355 	filename = sfix->name;
1356 	file = sfix->file;
1357 	sfix->name = NULL;
1358 	sfix->file = NULL;
1359 
1360 	/* Try removing the file while we still have it open to avoid races
1361 	 * with others re-using the temporary filename.
1362 	 *
1363 	 * On some systems that may not be possible and we can choose between:
1364 	 *
1365 	 *   - guaranteed leaking files or
1366 	 *   - running the risk of removing someone elses file
1367 	 *
1368 	 * We choose the latter.  Assuming those systems behave consistently,
1369 	 * removing someone elses file should only succeed if it isn't open at
1370 	 * the moment we try removing it.  Given that this is a temporary file,
1371 	 * we should be able to rule out accidental name clashes with
1372 	 * non-termporary files.
1373 	 */
1374 	if (filename && file) {
1375 		errcode = remove(filename);
1376 		if (!errcode) {
1377 			free(filename);
1378 			filename = NULL;
1379 		}
1380 	}
1381 
1382 	if (file)
1383 		fclose(file);
1384 
1385 	if (filename) {
1386 		(void) remove(filename);
1387 		free(filename);
1388 	}
1389 
1390 	for (thrd = 0; thrd < sfix->thrd.nthreads; ++thrd)
1391 		ptu_int_eq(sfix->thrd.result[thrd], 0);
1392 
1393 	return ptu_passed();
1394 }
1395 
1396 int main(int argc, char **argv)
1397 {
1398 	struct section_fixture sfix;
1399 	struct ptunit_suite suite;
1400 
1401 	sfix.init = sfix_init;
1402 	sfix.fini = sfix_fini;
1403 
1404 	suite = ptunit_mk_suite(argc, argv);
1405 
1406 	ptu_run_f(suite, create, sfix);
1407 	ptu_run_f(suite, create_bad_offset, sfix);
1408 	ptu_run_f(suite, create_truncated, sfix);
1409 	ptu_run_f(suite, create_empty, sfix);
1410 
1411 	ptu_run(suite, filename_null);
1412 	ptu_run(suite, offset_null);
1413 	ptu_run(suite, size_null);
1414 	ptu_run(suite, get_null);
1415 	ptu_run(suite, put_null);
1416 	ptu_run(suite, attach_null);
1417 	ptu_run(suite, detach_null);
1418 	ptu_run(suite, map_null);
1419 	ptu_run(suite, unmap_null);
1420 	ptu_run(suite, cache_null);
1421 
1422 	ptu_run_f(suite, get_overflow, sfix);
1423 	ptu_run_f(suite, attach_overflow, sfix);
1424 	ptu_run_f(suite, attach_bad_ucount, sfix);
1425 	ptu_run_f(suite, map_change, sfix);
1426 	ptu_run_f(suite, map_put, sfix);
1427 	ptu_run_f(suite, unmap_nomap, sfix);
1428 	ptu_run_f(suite, map_overflow, sfix);
1429 	ptu_run_f(suite, get_put, sfix);
1430 	ptu_run_f(suite, attach_detach, sfix);
1431 	ptu_run_f(suite, attach_bad_iscache, sfix);
1432 	ptu_run_f(suite, detach_bad_iscache, sfix);
1433 	ptu_run_f(suite, map_unmap, sfix);
1434 	ptu_run_f(suite, attach_map, sfix);
1435 	ptu_run_f(suite, attach_bad_map, sfix);
1436 	ptu_run_f(suite, attach_map_overflow, sfix);
1437 	ptu_run_f(suite, read, sfix);
1438 	ptu_run_f(suite, read_null, sfix);
1439 	ptu_run_f(suite, read_offset, sfix);
1440 	ptu_run_f(suite, read_truncated, sfix);
1441 	ptu_run_f(suite, read_from_truncated, sfix);
1442 	ptu_run_f(suite, read_nomem, sfix);
1443 	ptu_run_f(suite, read_overflow, sfix);
1444 	ptu_run_f(suite, read_overflow_32bit, sfix);
1445 	ptu_run_f(suite, read_nomap, sfix);
1446 	ptu_run_f(suite, read_unmap_map, sfix);
1447 
1448 	ptu_run_f(suite, init_no_bcache, sfix);
1449 	ptu_run_f(suite, bcache_alloc_free, sfix);
1450 	ptu_run_f(suite, bcache_alloc_twice, sfix);
1451 	ptu_run_f(suite, bcache_alloc_nomap, sfix);
1452 
1453 	ptu_run_f(suite, memsize_null, sfix);
1454 	ptu_run_f(suite, memsize_nomap, sfix);
1455 	ptu_run_f(suite, memsize_unmap, sfix);
1456 	ptu_run_f(suite, memsize_map_nobcache, sfix);
1457 	ptu_run_f(suite, memsize_map_bcache, sfix);
1458 
1459 	ptu_run_fp(suite, stress, sfix, worker_bcache);
1460 	ptu_run_fp(suite, stress, sfix, worker_read);
1461 
1462 	return ptunit_report(&suite);
1463 }
1464