File: pcbuf.c

package info (click to toggle)
fio 3.41-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,012 kB
  • sloc: ansic: 82,290; python: 9,862; sh: 6,067; makefile: 813; yacc: 204; lex: 184
file content (116 lines) | stat: -rw-r--r-- 2,773 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/**
 * SPDX-License-Identifier: GPL-2.0 only
 *
 * Copyright (c) 2025 Sandisk Corporation or its affiliates.
 */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#include "../unittest.h"
#include "pcbuf.h"

#define TEST_CAPACITY 8  /* Small capacity for wrap-around testing */

static void test_pcbuf_basic_ops(void)
{
	struct pc_buf *cb = pcb_alloc(TEST_CAPACITY);
	uint64_t i;

	CU_ASSERT_PTR_NOT_NULL(cb);

	CU_ASSERT_TRUE(pcb_is_empty(cb));
	CU_ASSERT_FALSE(pcb_is_full(cb));
	CU_ASSERT_EQUAL(pcb_committed_size(cb), 0);
	CU_ASSERT_EQUAL(pcb_staged_size(cb), 0);
	CU_ASSERT_TRUE(pcb_space_available(cb));

	/* Stage data up to capacity-1 (since 1 slot is reserved) */
	for (i = 0; i < TEST_CAPACITY - 1; ++i) {
		CU_ASSERT_TRUE(pcb_push_staged(cb, i + 100));
	}

	/* Next push should fail (buffer full) */
	CU_ASSERT_FALSE(pcb_push_staged(cb, 999));

	CU_ASSERT_EQUAL(pcb_staged_size(cb), TEST_CAPACITY - 1);
	CU_ASSERT_EQUAL(pcb_committed_size(cb), 0);
	CU_ASSERT_TRUE(pcb_is_empty(cb));
	CU_ASSERT_TRUE(pcb_is_full(cb));

	/* Commit staged data */
	pcb_commit(cb);

	CU_ASSERT_EQUAL(pcb_committed_size(cb), TEST_CAPACITY - 1);
	CU_ASSERT_EQUAL(pcb_staged_size(cb), 0);
	CU_ASSERT_FALSE(pcb_is_empty(cb));

	/* Pop all committed data */
	for (i = 0; i < TEST_CAPACITY - 1; ++i) {
		uint64_t val;
		CU_ASSERT_TRUE(pcb_pop(cb, &val));
		CU_ASSERT_EQUAL(val, i + 100);
	}

	/* Buffer should now be empty again */
	CU_ASSERT_TRUE(pcb_is_empty(cb));
	CU_ASSERT_FALSE(pcb_is_full(cb));
	CU_ASSERT_TRUE(pcb_space_available(cb));

	free(cb);
}

static void test_pcbuf_wraparound(void)
{
	struct pc_buf *cb = pcb_alloc(TEST_CAPACITY);
	uint64_t expected[] = {201, 202, 203, 204, 205, 999};
	size_t num_expected = sizeof(expected)/sizeof(expected[0]);
	uint64_t val;
	uint64_t i;

	CU_ASSERT_PTR_NOT_NULL(cb);

	/* Stage up to near capacity and commit */
	for (i = 0; i < TEST_CAPACITY - 2; ++i)
		CU_ASSERT_TRUE(pcb_push_staged(cb, i + 200));

	pcb_commit(cb);

	/* Pop one item to move read_tail forward */
	CU_ASSERT_TRUE(pcb_pop(cb, &val));
	CU_ASSERT_EQUAL(val, 200);

	/* Now stage one more item to cause wraparound */
	CU_ASSERT_TRUE(pcb_push_staged(cb, 999));
	pcb_commit(cb);

	/* Pop remaining items, ensure correctness */
	for (i = 0; i < num_expected; ++i) {
		CU_ASSERT_TRUE(pcb_pop(cb, &val));
		CU_ASSERT_EQUAL(val, expected[i]);
	}

	CU_ASSERT_TRUE(pcb_is_empty(cb));
	free(cb);
}

static struct fio_unittest_entry tests[] = {
	{
		.name   = "pcbuf/basic_ops",
		.fn     = test_pcbuf_basic_ops,
	},
	{
		.name   = "pcbuf/wraparound",
		.fn     = test_pcbuf_wraparound,
	},
	{
		.name   = NULL,
	},
};

CU_ErrorCode fio_unittest_lib_pcbuf(void)
{
	return fio_unittest_add_suite("pcbuf.h", NULL, NULL, tests);
}