1#
2# CDDL HEADER START
3#
4# The contents of this file are subject to the terms of the
5# Common Development and Distribution License (the "License").
6# You may not use this file except in compliance with the License.
7#
8# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9# or http://www.opensolaris.org/os/licensing.
10# See the License for the specific language governing permissions
11# and limitations under the License.
12#
13# When distributing Covered Code, include this CDDL HEADER in each
14# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15# If applicable, add the following below this CDDL HEADER, with the
16# fields enclosed by brackets "[]" replaced with your own identifying
17# information: Portions Copyright [yyyy] [name of copyright owner]
18#
19# CDDL HEADER END
20#
21
22#
23# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24# Use is subject to license terms.
25#
26
27#
28# Copyright (c) 2014, 2016 by Delphix. All rights reserved.
29#
30
31. $STF_SUITE/include/libtest.shlib
32
33set -A VALID_NAME_CHAR a b c d e f g h i j k l m n o p q r s t u v w x y z \
34    0 1 2 3 4 5 6 7 8 9 ':' '-' '.' '_'
35set -A INVALID_NAME_CHAR A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
36    '`' '~' '!' '@' '#' '$' '%' '^' '&' '(' ')' '+' '=' '|' "\\" '{' '[' ']' \
37    '}' ';' '"' '<' ',' '>' '?' '/' ' '
38set -A ALL_CHAR ${VALID_NAME_CHAR[*]} ${INVALID_NAME_CHAR[*]}
39
40#
41# Firstly, set the property value to dataset. Then checking if the property
42# value is equal with the expected value, according to the expected result.
43#
44# $1 property value
45# $2 property name
46# $3 dataset
47# $4 expected result
48#
49function set_n_check_prop
50{
51	typeset expect_value=$1
52	typeset prop=$2
53	typeset dataset=$3
54	typeset expect_result=${4:-true}
55
56	typeset old_value=""
57	typeset cur_value=""
58
59	[[ -n $prop ]] && old_value=$(get_prop $prop $dataset)
60
61	if [[ $expect_result == true ]]; then
62		[[ -z $prop || -z $dataset ]] && \
63			log_fail "property or dataset isn't defined."
64
65		log_must zfs set $prop=$expect_value $dataset
66		if [[ $expect_value == "gzip-6" ]]; then
67			expect_value="gzip"
68		fi
69
70		[[ -n $prop ]] && cur_value=$(get_prop $prop $dataset)
71
72		case $prop in
73			reservation|reserv|quota )
74				if [[ $expect_value == "none" ]]; then
75					[[ $cur_value != "0" ]] && \
76						log_fail "The '$dataset' '$prop' value \
77						'$cur_value' is not expected."
78				elif [[ $cur_value != $expect_value ]]; then
79					log_fail "The '$dataset' '$prop' value '$cur_value' \
80					does not equal the expected value '$expect_value'."
81				fi
82				;;
83			* )
84				if [[ $cur_value != $expect_value ]]; then
85					log_fail "The '$dataset' '$prop' value '$cur_value' \
86					does not equal the expected value '$expect_value'."
87				fi
88				;;
89		esac
90
91	else
92		log_mustnot zfs set $prop=$expect_value $dataset
93
94		[[ -n $prop ]] && cur_value=$(get_prop $prop $dataset)
95
96		wait_freeing
97
98		if [[ "$expect_value" != "" && "$cur_value" != "$old_value" ]];
99		then
100			log_fail "The '$dataset' '$prop' value '$cur_value' \
101				should equal with '$old_value'."
102		fi
103	fi
104}
105
106#
107# Cleanup all the user properties of the pool and the dataset reside it.
108#
109# $1 pool name
110#
111function cleanup_user_prop
112{
113	typeset pool=$1
114	typeset dtst=$(zfs list -H -r -o name -t filesystem,volume $pool)
115
116	typeset user_prop
117	for dt in $dtst; do
118		user_prop=$(zfs get -H -o property all $dtst | grep ":")
119
120		typeset prop
121		for prop in $user_prop; do
122			zfs inherit $prop $dt
123			(($? != 0)) && log_must zfs inherit $prop $dt
124		done
125	done
126}
127
128#
129# Random select character from the specified character set and combine into a
130# random string
131#
132# $1 character set name
133# $2 String length
134#
135function random_string
136{
137	typeset char_set=${1:-VALID_NAME_CHAR}
138	typeset -i len=${2:-5}
139
140	eval typeset -i count=\${#$char_set[@]}
141
142	# No consumers want an empty string.
143	((len == 0)) && len=3
144
145	typeset str
146	typeset -i i=0
147	while ((i < len)); do
148		typeset -i ind
149		((ind = RANDOM % count))
150		eval str=\${str}\${$char_set[\$ind]}
151
152		((i += 1))
153	done
154
155	echo "$str"
156}
157
158#
159# Get valid user defined property name
160#
161# $1 user defined property name length
162#
163function valid_user_property
164{
165	typeset -i sumlen=${1:-10}
166	((sumlen < 2 )) && sumlen=2
167	typeset -i len
168	((len = RANDOM % sumlen))
169	typeset part1 part2
170
171	while true; do
172		part1="$(random_string VALID_NAME_CHAR $len)"
173		if [[ "$part1" == "-"* ]]; then
174			continue
175		fi
176		break
177	done
178	((len = sumlen - (len + 1)))
179
180	while true; do
181		part2="$(random_string VALID_NAME_CHAR $len)"
182		if [[ -z $part1 && -z $part2 ]]; then
183			continue
184		fi
185		break
186	done
187
188	echo "${part1}:${part2}"
189}
190
191#
192# Get invalid user defined property name
193#
194# $1 user defined property name length
195#
196function invalid_user_property
197{
198	typeset -i sumlen=${1:-10}
199	((sumlen == 0)) && sumlen=1
200	typeset -i len
201	((len = RANDOM % sumlen))
202
203	typeset part1 part2
204	while true; do
205		part1="$(random_string VALID_NAME_CHAR $len)"
206		((len = sumlen - len))
207		part2="$(random_string INVALID_NAME_CHAR $len)"
208
209		# Avoid $part1 is *:* and $part2 is "=*"
210		if [[ "$part1" == *":"* && "$part2" == "="* ]]; then
211			continue
212		fi
213		break
214	done
215
216	echo "${part1}${part2}"
217}
218
219#
220# Get user property value
221#
222# $1 user defined property name length
223#
224function user_property_value
225{
226	typeset -i len=${1:-100}
227
228	typeset value=$(random_string ALL_CHAR $len)
229
230	echo "$value"
231}
232
233#
234# Check if the user property is identical to the expected value.
235#
236# $1 dataset
237# $2 user property
238# $3 expected value
239#
240function check_user_prop
241{
242	typeset dtst=$1
243	typeset user_prop="$2"
244	typeset expect_value="$3"
245	typeset value=$(zfs get -p -H -o value "$user_prop" $dtst 2>&1)
246
247	if [[ "$expect_value" == "$value" ]]; then
248		return 0
249	else
250		return 1
251	fi
252}
253
254#
255# Get source of the dataset
256#
257function get_source
258{
259	typeset prop=$1
260	typeset dataset=$2
261	typeset source
262
263	source=$(zfs get -H -o source $prop $dataset)
264        if (($? != 0)); then
265                log_fail "Unable to get $prop source for dataset $dataset"
266        fi
267
268	echo "$source"
269}
270
271#
272# Verify property $2 is set from source $4 on dataset $1 and has value $3.
273#
274# $1 checked dataset
275# $2 user property
276# $3 property value
277# $4 source
278#
279# Returns: 0 if both expected source and value match, 1 otherwise
280#
281function check_prop_source
282{
283        typeset dataset="$1"
284        typeset prop="$2"
285        typeset value="$3"
286        typeset source="$4"
287        typeset chk_value=$(get_prop "$prop" "$dataset")
288        typeset chk_source=$(get_source "$prop" "$dataset")
289
290	if [[ "$chk_value" != "$value" || "$chk_source" != "$source" ]]
291	then
292		log_note "expected (value '$value', source '$source'), got \
293			(value '$chk_value', source '$chk_source')"
294		return 1
295	else
296		return 0
297	fi
298}
299
300#
301# Verify target dataset $1 inherit property $2 from dataset $3.
302#
303# $1 checked dataset
304# $2 property
305# $3 inherited dataset
306#
307# Returns: 0 if property has expected value and is inherited, 1 otherwise
308#
309function check_prop_inherit
310{
311        typeset checked_dtst="$1"
312        typeset prop="$2"
313        typeset inherited_dtst="$3"
314        typeset inherited_value=$(get_prop "$prop" "$inherited_dtst")
315        typeset value=$(get_prop "$prop" "$checked_dtst")
316        typeset source=$(get_source "$prop" "$checked_dtst")
317
318        if [[ "$value" != "$inherited_value" || \
319            "$source" != "inherited from $inherited_dtst" ]]
320        then
321                return 1
322        else
323                return 0
324        fi
325}
326
327#
328# Verify property $2 received value on dataset $1 has value $3
329#
330# $1 checked dataset
331# $2 property name
332# $3 checked value
333#
334# Returns: 0 if property has expected value and is received, 1 otherwise
335#
336function check_prop_received
337{
338        typeset dataset="$1"
339        typeset prop="$2"
340        typeset value="$3"
341
342        received=$(zfs get -H -o received "$prop" "$dataset")
343        if (($? != 0)); then
344                log_fail "Unable to get $prop received value for dataset " \
345                    "$dataset"
346        fi
347        if [[ "$received" == "$value" ]]
348        then
349                return 0
350        else
351                return 1
352        fi
353}
354
355#
356# Verify user property $2 is not set on dataset $1
357#
358# $1 checked dataset
359# $2 property name
360#
361# Returns: 0 if property is missing (not set), 1 otherwise
362#
363function check_prop_missing
364{
365        typeset dataset="$1"
366        typeset prop="$2"
367
368        value=$(zfs get -H -o value "$prop" "$dataset")
369        if (($? != 0)); then
370                log_fail "Unable to get $prop value for dataset $dataset"
371        fi
372        if [[ "-" == "$value" ]]
373        then
374                return 0
375        else
376                return 1
377        fi
378}
379