summaryrefslogtreecommitdiff
path: root/source3/script/tests/test_aio_ratelimit.sh
blob: fec749c6616f67c624328fe9abddfc4580606a92 (plain)
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#!/usr/bin/env bash
#
# Test VFS module aio_ratelimit

SELF=$(basename "$0")

if [ $# -lt 5 ]; then
	echo Usage: "${SELF}" SERVERCONFFILE SMBCLIENT \
		SERVER LOCAL_PATH SHARENAME
	exit 1
fi

CONF="$1"
SMBCLIENT="$2"
SERVER="$3"
LOCAL_PATH="$4"
SHARE="$5"

# Do not let deprecated option warnings muck this up
SAMBA_DEPRECATED_SUPPRESS=1
export SAMBA_DEPRECATED_SUPPRESS

incdir="$(dirname "$0")/../../../testprogs/blackbox"
. $incdir/subunit.sh

failed=0

# Prepare
cd $SELFTEST_TMPDIR || exit 1

# Test 1: Basic rate limiting
test_aio_ratelimit_basic()
{
	local testfile="${FUNCNAME[0]}"
	local src="${LOCAL_PATH}/${testfile}-src"
	local dst="${testfile}-dst"
	local tgt="${testfile}-tgt"

	# Small file to avoid timeout
	dd if=/dev/urandom of="${src}" bs=10K count=1
	stat "$src"

	SECONDS=0

	# Write
	CLI_FORCE_INTERACTIVE=1 ${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} \
		-U${USER}%${PASSWORD} -c "put ${src} ${dst}"
	ret=$?
	if [ $ret != 0 ]; then
		printf "failed to write file: %s\n" "${ret}"
		return 1
	fi

	# Read 20 times to trigger rate limiting
	count=1
	while [ $count -le 20 ]; do
		CLI_FORCE_INTERACTIVE=1 \
			${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} \
			-U${USER}%${PASSWORD} -c "get ${dst} ${tgt}"
		ret=$?
		if [ $ret != 0 ]; then
			printf "failed to read file: %s\n" "${ret}"
			return 1
		fi
		(( count++ ))
	done

	# Expect rate-limiting delay
	if [ ${SECONDS} -lt 1 ]; then
		printf "no rate-limiting delay observed: elapsed-secs=%d\n" "${SECONDS}"
		return 1
	fi

	# Delete
	CLI_FORCE_INTERACTIVE=1 ${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} \
	    -U${USER}%${PASSWORD} -c "del ${dst}"
	ret=$?
	if [ $ret != 0 ]; then
		printf "failed to delete file: %s\n" "${ret}"
		return 1
	fi

	# Cleanups
	rm -f "${src}" "${tgt}"
}

# Test 2: Burst behavior - initial reads should be fast
test_aio_ratelimit_burst()
{
	local testfile="${FUNCNAME[0]}"
	local src="${LOCAL_PATH}/${testfile}-src"
	local dst="${testfile}-dst"
	local tgt="${testfile}-tgt"

	# Small file
	dd if=/dev/urandom of="${src}" bs=5K count=1
	stat "$src"

	# Write
	CLI_FORCE_INTERACTIVE=1 ${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} \
		-U${USER}%${PASSWORD} -c "put ${src} ${dst}"
	ret=$?
	if [ $ret != 0 ]; then
		printf "failed to write file: %s\n" "${ret}"
		return 1
	fi

	# First 3 reads should be fast (using burst)
	SECONDS=0
	count=1
	while [ $count -le 3 ]; do
		CLI_FORCE_INTERACTIVE=1 \
			${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} \
			-U${USER}%${PASSWORD} -c "get ${dst} ${tgt}"
		ret=$?
		if [ $ret != 0 ]; then
			printf "failed to read file: %s\n" "${ret}"
			return 1
		fi
		(( count++ ))
	done

	# Should complete quickly (burst capacity)
	if [ ${SECONDS} -gt 1 ]; then
		printf "burst reads too slow: elapsed-secs=%d\n" "${SECONDS}"
		return 1
	fi

	# Delete
	CLI_FORCE_INTERACTIVE=1 ${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} \
	    -U${USER}%${PASSWORD} -c "del ${dst}"

	# Cleanups
	rm -f "${src}" "${tgt}"
}

# Test 3: Recovery after idle
test_aio_ratelimit_recovery()
{
	local testfile="${FUNCNAME[0]}"
	local src="${LOCAL_PATH}/${testfile}-src"
	local dst="${testfile}-dst"
	local tgt="${testfile}-tgt"

	# Small file
	dd if=/dev/urandom of="${src}" bs=5K count=1
	stat "$src"

	# Write
	CLI_FORCE_INTERACTIVE=1 ${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} \
		-U${USER}%${PASSWORD} -c "put ${src} ${dst}"
	ret=$?
	if [ $ret != 0 ]; then
		printf "failed to write file: %s\n" "${ret}"
		return 1
	fi

	# Exhaust burst with 5 rapid reads
	count=1
	while [ $count -le 5 ]; do
		CLI_FORCE_INTERACTIVE=1 \
			${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} \
			-U${USER}%${PASSWORD} -c "get ${dst} ${tgt}" > /dev/null 2>&1
		(( count++ ))
	done

	# Wait for tokens to refill
	sleep 2

	# Read again - should be reasonably fast (tokens refilled)
	SECONDS=0
	CLI_FORCE_INTERACTIVE=1 \
		${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} \
		-U${USER}%${PASSWORD} -c "get ${dst} ${tgt}"
	ret=$?
	if [ $ret != 0 ]; then
		printf "failed to read after recovery: %s\n" "${ret}"
		return 1
	fi

	# Should complete quickly (tokens recovered)
	if [ ${SECONDS} -gt 1 ]; then
		printf "recovery too slow: elapsed-secs=%d\n" "${SECONDS}"
		return 1
	fi

	# Delete
	CLI_FORCE_INTERACTIVE=1 ${SMBCLIENT} //${SERVER}/${SHARE} ${CONF} \
	    -U${USER}%${PASSWORD} -c "del ${dst}"

	# Cleanups
	rm -f "${src}" "${tgt}"
}

# Actual tests
testit "test_aio_ratelimit_basic" \
	test_aio_ratelimit_basic ||
	failed=$(expr $failed + 1)

testit "test_aio_ratelimit_burst" \
	test_aio_ratelimit_burst ||
	failed=$(expr $failed + 1)

testit "test_aio_ratelimit_recovery" \
	test_aio_ratelimit_recovery ||
	failed=$(expr $failed + 1)

testok $0 $failed