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	    log_fail "unexpected failure getting stdout from '${cmd[@]}'"
63	datasetexists "$TESTPOOL/$TESTFS1" ||
64	    log_fail "$TESTPOOL/$TESTFS1 unexpectedly created by '${cmd[@]}'"
65	while IFS=$'\t' read -A toks; do
66		log_note "verifying ${toks[@]}"
67		case ${toks[0]} in
68		create_ancestors)
69			case "$create_ancestors" in
70			needed)
71				log_must test "${toks[1]}" == "$ds"
72				create_ancestors="found ${toks[1]}"
73				;;
74			found*)
75				log_fail "multiple ancestor creation" \
76				    "$create_ancestors and ${toks[1]}"
77				;;
78			"")
79				log_fail "unexpected create_ancestors"
80				;;
81			*)
82				log_fail "impossible error: fix the test"
83				;;
84			esac
85			;;
86		create)
87			log_must test "${#toks[@]}" -eq 2
88			log_must test "${toks[1]}" == "$ds"
89			found_create="yes, I found create"
90			;;
91		property)
92			log_must test "${#toks[@]}" -eq 3
93			typeset prop=${toks[1]}
94			typeset val=${toks[2]}
95			if [[ -z "${exp[$prop]}" ]]; then
96				log_fail "unexpectedly got property '$prop'"
97			fi
98			# We may not know the exact value a property will take
99			# on.  This is the case for at least refreservation.
100			if [[ ${exp[$prop]} != "*" ]]; then
101				log_must test "${exp[$prop]}" == "$val"
102			fi
103			unset exp[$prop]
104			;;
105		*)
106			log_fail "Unexpected line ${toks[@]}"
107			;;
108		esac
109	done <<<"$out"
110
111	log_must test "$found_create" == "yes, I found create"
112	log_must test "extra props: ${!exp[@]}" == "extra props: "
113
114	case "$create_ancestors" in
115	"")
116		log_must_busy zfs destroy "$ds"
117		;;
118	"found $ds")
119		log_must_busy zfs destroy -r "$(echo "$ds" | cut -d/ -f1-2)"
120		;;
121	needed)
122		log_fail "Expected but did not find create_ancestors"
123		;;
124	*)
125		log_fail "Unexpected value for create_ancestors:" \
126		    "$create_ancestors"
127		;;
128	esac
129}
130
131function cleanup
132{
133	datasetexists "$TESTPOOL/$TESTFS1" && \
134		destroy_dataset "$TESTPOOL/$TESTFS1" -r
135}
136log_onexit cleanup
137
138log_assert "zfs create -v creates datasets verbosely"
139
140# Parseable output should be parseable.
141typeset -A expect
142expect=([compression]=on)
143dry_create_parseable expect -o compression=on "$TESTPOOL/$TESTFS1"
144
145# Ancestor creation with -p should emit relevant line
146expect=([compression]=on)
147dry_create_parseable expect -p -o compression=on "$TESTPOOL/$TESTFS1"
148expect=([compression]=on)
149dry_create_parseable expect -p -o compression=on "$TESTPOOL/$TESTFS1/$TESTVOL"
150
151# Sparse volumes should not get a gratuitous refreservation
152expect=([volblocksize]=4096 [volsize]=$((1024 * 1024 * 10)))
153dry_create_parseable expect -b 4k -V 10m -s "$TESTPOOL/$TESTFS1"
154
155# Non-sparse volumes should have refreservation
156expect=(
157    [volblocksize]=4096
158    [volsize]=$((1024 * 1024 * 10))
159    [refreservation]="*"
160)
161dry_create_parseable expect -b 4k -V 10m "$TESTPOOL/$TESTFS1"
162
163log_pass "zfs create -v creates datasets verbosely"
164