1#!/bin/ksh -p
2#
3# This file and its contents are supplied under the terms of the
4# Common Development and Distribution License ("CDDL"), version 1.0.
5# You may only use this file in accordance with the terms of version
6# 1.0 of the CDDL.
7#
8# A full copy of the text of the CDDL should have accompanied this
9# source.  A copy of the CDDL is also available via the Internet at
10# http://www.illumos.org/license/CDDL.
11#
12
13#
14# Copyright 2019 Joyent, Inc.
15#
16
17. $STF_SUITE/include/libtest.shlib
18. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
19
20#
21# DESCRIPTION:
22# zfs create -P without -n should be verbose about dataset creation.
23#
24# STRATEGY:
25# 1. Attempt to create a file system and a volume using various properties
26#    and -P
27# 2. Exercise the combination of -p and -P.
28#
29
30verify_runnable "both"
31
32#
33# Verifies that non dry-run commands with parseable output
34# - succeed
35# - create datasets
36# - generate parseable output on stdout
37# - output matches expectations
38#
39function dry_create_parseable
40{
41	typeset -n exp=$1
42	shift
43	typeset -a cmd=(zfs create -P "$@")
44	typeset ds=${cmd[${#cmd[@]} - 1]}
45	typeset out
46	typeset -a toks
47	typeset -a props
48	typeset found_create=false
49	typeset create_ancestors=
50	typeset opt
51
52	# Parse the arguments to see if -p was used.
53	while getopts :PV:b:ospv opt; do
54		case $opt in
55		p)	create_ancestors=needed ;;
56		*)	continue ;;
57		esac
58	done
59
60	log_note "$0: ${cmd[@]}"
61	out=$("${cmd[@]}")
62	(( $? == 0 )) ||
63	    log_fail "unexpected failure getting stdout from '${cmd[@]}'"
64	datasetexists "$TESTPOOL/$TESTFS1" ||
65	    log_fail "$TESTPOOL/$TESTFS1 unexpectedly created by '${cmd[@]}'"
66	echo "$out" | while IFS=$'\t' read -A toks; do
67		log_note "verifying ${toks[@]}"
68		case ${toks[0]} in
69		create_ancestors)
70			case "$create_ancestors" in
71			needed)
72				log_must test "${toks[1]}" == "$ds"
73				create_ancestors="found ${toks[1]}"
74				;;
75			found*)
76				log_fail "multiple ancestor creation" \
77				    "$create_ancestors and ${toks[1]}"
78				;;
79			"")
80				log_fail "unexpected create_ancestors"
81				;;
82			*)
83				log_fail "impossible error: fix the test"
84				;;
85			esac
86			;;
87		create)
88			log_must test "${#toks[@]}" -eq 2
89			log_must test "${toks[1]}" == "$ds"
90			found_create="yes, I found create"
91			;;
92		property)
93			log_must test "${#toks[@]}" -eq 3
94			typeset prop=${toks[1]}
95			typeset val=${toks[2]}
96			if [[ -z "${exp[$prop]}" ]]; then
97				log_fail "unexpectedly got property '$prop'"
98			fi
99			# We may not know the exact value a property will take
100			# on.  This is the case for at least refreservation.
101			if [[ ${exp[$prop]} != "*" ]]; then
102				log_must test "${exp[$prop]}" == "$val"
103			fi
104			unset exp[$prop]
105			;;
106		*)
107			log_fail "Unexpected line ${toks[@]}"
108			;;
109		esac
110	done
111
112	log_must test "$found_create" == "yes, I found create"
113	log_must test "extra props: ${!exp[@]}" == "extra props: "
114
115	case "$create_ancestors" in
116	"")
117		log_must_busy zfs destroy "$ds"
118		;;
119	"found $ds")
120		log_must_busy zfs destroy -r "$(echo "$ds" | cut -d/ -f1-2)"
121		;;
122	needed)
123		log_fail "Expected but did not find create_ancestors"
124		;;
125	*)
126		log_fail "Unexpected value for create_ancestors:" \
127		    "$create_ancestors"
128		;;
129	esac
130}
131
132function cleanup
133{
134	if datasetexists "$TESTPOOL/$TESTFS1"; then
135		log_must_busy zfs destroy -r "$TESTPOOL/$TESTFS1"
136	fi
137}
138log_onexit cleanup
139
140log_assert "zfs create -v creates datasets verbosely"
141
142# Parseable output should be parseable.
143typeset -A expect
144expect=([compression]=on)
145dry_create_parseable expect -o compression=on "$TESTPOOL/$TESTFS1"
146
147# Ancestor creation with -p should emit relevant line
148expect=([compression]=on)
149dry_create_parseable expect -p -o compression=on "$TESTPOOL/$TESTFS1"
150expect=([compression]=on)
151dry_create_parseable expect -p -o compression=on "$TESTPOOL/$TESTFS1/$TESTVOL"
152
153# Sparse volumes should not get a gratuitous refreservation
154expect=([volblocksize]=4096 [volsize]=$((1024 * 1024 * 10)))
155dry_create_parseable expect -b 4k -V 10m -s "$TESTPOOL/$TESTFS1"
156
157# Non-sparse volumes should have refreservation
158expect=(
159    [volblocksize]=4096
160    [volsize]=$((1024 * 1024 * 10))
161    [refreservation]="*"
162)
163dry_create_parseable expect -b 4k -V 10m "$TESTPOOL/$TESTFS1"
164
165log_pass "zfs create -v creates datasets verbosely"
166