~hww3/illumos-joyent

a629ded1d7b2e67c2028ccbc5ba9099328cc4e1b — LOLi 5 years ago 32a71e4
11962 Port ZoL zfs diff tests to illumos
Portions contributed by: Tony Hutter <hutter2@llnl.gov>
Portions contributed by: Tom Caputi <tcaputi@datto.com>
Portions contributed by: Jason King <jason.king@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Andy Fiddaman <omnios@citrus-it.co.uk>
Approved by: Dan McDonald <danmcd@joyent.com>
M usr/src/pkg/manifests/system-test-zfstest.mf => usr/src/pkg/manifests/system-test-zfstest.mf +14 -0
@@ 53,6 53,7 @@ dir path=opt/zfs-tests/tests/functional/cli_root/zfs_clone
dir path=opt/zfs-tests/tests/functional/cli_root/zfs_copies
dir path=opt/zfs-tests/tests/functional/cli_root/zfs_create
dir path=opt/zfs-tests/tests/functional/cli_root/zfs_destroy
dir path=opt/zfs-tests/tests/functional/cli_root/zfs_diff
dir path=opt/zfs-tests/tests/functional/cli_root/zfs_get
dir path=opt/zfs-tests/tests/functional/cli_root/zfs_inherit
dir path=opt/zfs-tests/tests/functional/cli_root/zfs_load-key


@@ 891,6 892,19 @@ file \
file \
    path=opt/zfs-tests/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib \
    mode=0444
file path=opt/zfs-tests/tests/functional/cli_root/zfs_diff/cleanup mode=0555
file path=opt/zfs-tests/tests/functional/cli_root/zfs_diff/setup mode=0555
file path=opt/zfs-tests/tests/functional/cli_root/zfs_diff/socket mode=0555
file path=opt/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_changes \
    mode=0555
file path=opt/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_cliargs \
    mode=0555
file path=opt/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_encrypted \
    mode=0555
file path=opt/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_timestamp \
    mode=0555
file path=opt/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_types \
    mode=0555
file path=opt/zfs-tests/tests/functional/cli_root/zfs_get/cleanup mode=0555
file path=opt/zfs-tests/tests/functional/cli_root/zfs_get/setup mode=0555
file path=opt/zfs-tests/tests/functional/cli_root/zfs_get/zfs_get_001_pos \

M usr/src/test/zfs-tests/runfiles/delphix.run => usr/src/test/zfs-tests/runfiles/delphix.run +5 -0
@@ 144,6 144,11 @@ tests = ['zfs_destroy_001_pos', 'zfs_destroy_002_pos', 'zfs_destroy_003_pos',
    'zfs_destroy_013_neg', 'zfs_destroy_014_pos', 'zfs_destroy_015_pos',
    'zfs_destroy_016_pos']

[/opt/zfs-tests/tests/functional/cli_root/zfs_diff]
tests = ['zfs_diff_changes', 'zfs_diff_cliargs', 'zfs_diff_timestamp',
    'zfs_diff_types', 'zfs_diff_encrypted']
tags = ['functional', 'cli_root', 'zfs_diff']

[/opt/zfs-tests/tests/functional/cli_root/zfs_get]
tests = ['zfs_get_001_pos', 'zfs_get_002_pos', 'zfs_get_003_pos',
    'zfs_get_004_pos', 'zfs_get_005_neg', 'zfs_get_006_neg', 'zfs_get_007_neg',

M usr/src/test/zfs-tests/runfiles/omnios.run => usr/src/test/zfs-tests/runfiles/omnios.run +5 -0
@@ 144,6 144,11 @@ tests = ['zfs_destroy_001_pos', 'zfs_destroy_002_pos', 'zfs_destroy_003_pos',
    'zfs_destroy_013_neg', 'zfs_destroy_014_pos', 'zfs_destroy_015_pos',
    'zfs_destroy_016_pos']

[/opt/zfs-tests/tests/functional/cli_root/zfs_diff]
tests = ['zfs_diff_changes', 'zfs_diff_cliargs', 'zfs_diff_timestamp',
    'zfs_diff_types', 'zfs_diff_encrypted']
tags = ['functional', 'cli_root', 'zfs_diff']

[/opt/zfs-tests/tests/functional/cli_root/zfs_get]
tests = ['zfs_get_001_pos', 'zfs_get_002_pos', 'zfs_get_003_pos',
    'zfs_get_004_pos', 'zfs_get_005_neg', 'zfs_get_006_neg', 'zfs_get_007_neg',

M usr/src/test/zfs-tests/runfiles/openindiana.run => usr/src/test/zfs-tests/runfiles/openindiana.run +5 -0
@@ 144,6 144,11 @@ tests = ['zfs_destroy_001_pos', 'zfs_destroy_002_pos', 'zfs_destroy_003_pos',
    'zfs_destroy_013_neg', 'zfs_destroy_014_pos', 'zfs_destroy_015_pos',
    'zfs_destroy_016_pos']

[/opt/zfs-tests/tests/functional/cli_root/zfs_diff]
tests = ['zfs_diff_changes', 'zfs_diff_cliargs', 'zfs_diff_timestamp',
    'zfs_diff_types', 'zfs_diff_encrypted']
tags = ['functional', 'cli_root', 'zfs_diff']

[/opt/zfs-tests/tests/functional/cli_root/zfs_get]
tests = ['zfs_get_001_pos', 'zfs_get_002_pos', 'zfs_get_003_pos',
    'zfs_get_004_pos', 'zfs_get_005_neg', 'zfs_get_006_neg', 'zfs_get_007_neg',

M usr/src/test/zfs-tests/runfiles/smartos.run => usr/src/test/zfs-tests/runfiles/smartos.run +5 -0
@@ 106,6 106,11 @@ tests = ['zfs_destroy_001_pos', 'zfs_destroy_002_pos', 'zfs_destroy_003_pos',
    'zfs_destroy_013_neg', 'zfs_destroy_014_pos', 'zfs_destroy_015_pos',
    'zfs_destroy_016_pos']

[/opt/zfs-tests/tests/functional/cli_root/zfs_diff]
tests = ['zfs_diff_changes', 'zfs_diff_cliargs', 'zfs_diff_timestamp',
    'zfs_diff_types', 'zfs_diff_encrypted']
tags = ['functional', 'cli_root', 'zfs_diff']

[/opt/zfs-tests/tests/functional/cli_root/zfs_get]
tests = ['zfs_get_001_pos', 'zfs_get_002_pos', 'zfs_get_003_pos',
    'zfs_get_004_pos', 'zfs_get_005_neg', 'zfs_get_006_neg', 'zfs_get_007_neg',

A usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/Makefile => usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/Makefile +44 -0
@@ 0,0 1,44 @@
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source.  A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#

#
# Copyright 2019 Joyent, Inc.
#

include $(SRC)/Makefile.master

ROOTOPTPKG = $(ROOT)/opt/zfs-tests
TARGETDIR = $(ROOTOPTPKG)/tests/functional/cli_root/zfs_diff

PROG = socket
OBJS = $(PROG:%=%.o)
SRCS = $(OBJS:%.o=%.c)

include $(SRC)/cmd/Makefile.cmd

$(TARGETDIR)/$(PROG) :=	FILEMODE = 0555

CPPFLAGS = -D__EXTENSIONS__
LDLIBS = -lsocket

$(PROG): $(OBJS)
	$(LINK.c) $(OBJS) -o $@ $(LDLIBS)
	$(POST_PROCESS)

install: $(TARGETDIR)/$(PROG)

clobber: clean
	-$(RM) $(PROG)

clean:
	-$(RM) $(OBJS)

include $(SRC)/test/zfs-tests/Makefile.com

A usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/cleanup.ksh => usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/cleanup.ksh +19 -0
@@ 0,0 1,19 @@
#!/bin/ksh -p
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source.  A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#

#
# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
#

. $STF_SUITE/include/libtest.shlib

default_cleanup

A usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/setup.ksh => usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/setup.ksh +21 -0
@@ 0,0 1,21 @@
#!/bin/ksh -p
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source.  A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#

#
# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
#

. $STF_SUITE/include/libtest.shlib

DISK=${DISKS%% *}

default_volume_setup $DISK

A usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/socket.c => usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/socket.c +59 -0
@@ 0,0 1,59 @@
/*
 * This file and its contents are supplied under the terms of the
 * Common Development and Distribution License ("CDDL"), version 1.0.
 * You may only use this file in accordance with the terms of version
 * 1.0 of the CDDL.
 *
 * A full copy of the text of the CDDL should have accompanied this
 * source.  A copy of the CDDL is also available via the Internet at
 * http://www.illumos.org/license/CDDL.
 */

/*
 * Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
 * Copyright 2019 Joyent, Inc.
 */

#include <fcntl.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* ARGSUSED */
int
main(int argc, char *argv[])
{
	struct sockaddr_un sock;
	int fd;
	char *path;
	size_t size;
	if (argc != 2) {
		fprintf(stderr, "usage: %s /path/to/socket\n", argv[0]);
		exit(1);
	}
	path = argv[1];
	size =  sizeof (sock.sun_path);
	(void) strncpy(sock.sun_path, (char *)path, size - 1);
	sock.sun_path[size - 1] = '\0';

	sock.sun_family = AF_UNIX;
	if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) {
		perror("socket");
		return (1);
	}
	if (bind(fd, (struct sockaddr *)&sock, sizeof (struct sockaddr_un))) {
		perror("bind");
		return (1);
	}
	if (close(fd)) {
		perror("close");
		return (1);
	}
	return (0);
}

A usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_changes.ksh => usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_changes.ksh +96 -0
@@ 0,0 1,96 @@
#!/bin/ksh -p
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source.  A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#

#
# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
#

. $STF_SUITE/include/libtest.shlib

#
# DESCRIPTION:
# 'zfs diff' should display changes correctly.
#
# STRATEGY:
# 1. Create a filesystem with both files and directories, then snapshot it
# 2. Generate different types of changes and verify 'zfs diff' displays them
#

verify_runnable "both"

function cleanup
{
	log_must zfs destroy -r "$DATASET"
	rm -f "$FILEDIFF"
}

#
# Verify object $path has $change type
# Valid types are:
# * - (The path has been removed)
# * + (The path has been created)
# * M (The path has been modified)
# * R (The path has been renamed)
#
function verify_object_change # <path> <change>
{
	path="$1"
	change="$2"

	log_must eval "zfs diff -F $TESTSNAP1 $TESTSNAP2 > $FILEDIFF"
	diffchg="$(nawk -v path="$path" '$NF == path { print $1 }' < $FILEDIFF)"
	if [[ "$diffchg" != "$change" ]]; then
		log_fail "Unexpected change for $path ('$diffchg' != '$change')"
	else
		log_note "Object $path change is displayed correctly: '$change'"
	fi
}

log_assert "'zfs diff' should display changes correctly."
log_onexit cleanup

DATASET="$TESTPOOL/$TESTFS/fs"
TESTSNAP1="$DATASET@snap1"
TESTSNAP2="$DATASET@snap2"
FILEDIFF="$TESTDIR/zfs-diff.txt"

# 1. Create a filesystem with both files and directories, then snapshot it
log_must zfs create $DATASET
MNTPOINT="$(get_prop mountpoint $DATASET)"
log_must touch "$MNTPOINT/fremoved"
log_must touch "$MNTPOINT/frenamed"
log_must touch "$MNTPOINT/fmodified"
log_must mkdir "$MNTPOINT/dremoved"
log_must mkdir "$MNTPOINT/drenamed"
log_must mkdir "$MNTPOINT/dmodified"
log_must zfs snapshot "$TESTSNAP1"

# 2. Generate different types of changes and verify 'zfs diff' displays them
log_must rm -f "$MNTPOINT/fremoved"
log_must mv "$MNTPOINT/frenamed" "$MNTPOINT/frenamed.new"
log_must touch "$MNTPOINT/fmodified"
log_must rmdir "$MNTPOINT/dremoved"
log_must mv "$MNTPOINT/drenamed" "$MNTPOINT/drenamed.new"
log_must touch "$MNTPOINT/dmodified/file"
log_must touch "$MNTPOINT/fcreated"
log_must mkdir "$MNTPOINT/dcreated"
log_must zfs snapshot "$TESTSNAP2"
verify_object_change "$MNTPOINT/fremoved" "-"
verify_object_change "$MNTPOINT/frenamed.new" "R"
verify_object_change "$MNTPOINT/fmodified" "M"
verify_object_change "$MNTPOINT/fcreated" "+"
verify_object_change "$MNTPOINT/dremoved" "-"
verify_object_change "$MNTPOINT/drenamed.new" "R"
verify_object_change "$MNTPOINT/dmodified" "M"
verify_object_change "$MNTPOINT/dcreated" "+"

log_pass "'zfs diff' displays changes correctly."

A usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_cliargs.ksh => usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_cliargs.ksh +80 -0
@@ 0,0 1,80 @@
#!/bin/ksh -p
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source.  A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#

#
# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
#

. $STF_SUITE/include/libtest.shlib

#
# DESCRIPTION:
# 'zfs diff' should only work with supported options.
#
# STRATEGY:
# 1. Create two snapshots
# 2. Verify every supported option is accepted
# 3. Verify supported options raise an error with unsupported arguments
# 4. Verify other unsupported options raise an error
#

verify_runnable "both"

function cleanup
{
	for snap in $TESTSNAP1 $TESTSNAP2; do
		if snapexists "$snap"; then
			log_must zfs destroy "$snap"
		fi
	done
}

log_assert "'zfs diff' should only work with supported options."
log_onexit cleanup

typeset goodopts=("" "-F" "-H" "-t" "-FH" "-Ft" "-Ht" "-FHt")
typeset badopts=("-f" "-h" "-h" "-T" "-Fx" "-Ho" "-tT" "-")

DATASET="$TESTPOOL/$TESTFS"
TESTSNAP1="$DATASET@snap1"
TESTSNAP2="$DATASET@snap2"

# 1. Create two snapshots
log_must zfs snapshot "$TESTSNAP1"
log_must zfs snapshot "$TESTSNAP2"

# 2. Verify every supported option is accepted
for opt in ${goodopts[@]}
do
	log_must zfs diff $opt "$TESTSNAP1"
	log_must zfs diff $opt "$TESTSNAP1" "$DATASET"
	log_must zfs diff $opt "$TESTSNAP1" "$TESTSNAP2"
done

# 3. Verify supported options raise an error with unsupported arguments
for opt in ${goodopts[@]}
do
	log_mustnot zfs diff $opt
	log_mustnot zfs diff $opt "$DATASET"
	log_mustnot zfs diff $opt "$DATASET@noexists"
	log_mustnot zfs diff $opt "$DATASET" "$TESTSNAP1"
	log_mustnot zfs diff $opt "$TESTSNAP2" "$TESTSNAP1"
done

# 4. Verify other unsupported options raise an error
for opt in ${badopts[@]}
do
	log_mustnot zfs diff $opt "$TESTSNAP1" "$DATASET"
	log_mustnot zfs diff $opt "$TESTSNAP1" "$TESTSNAP2"
done

log_pass "'zfs diff' only works with supported options."

A usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_encrypted.ksh => usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_encrypted.ksh +54 -0
@@ 0,0 1,54 @@
#!/bin/ksh -p
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source.  A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#

#
# Copyright 2018, Datto Inc.
#

. $STF_SUITE/include/libtest.shlib

#
# DESCRIPTION:
# 'zfs diff' should work with encrypted datasets
#
# STRATEGY:
# 1. Create an encrypted dataset
# 2. Create two snapshots of the dataset
# 3. Perform 'zfs diff -Ft' and verify no errors occur
# 4. Perform the same test on a dataset with large dnodes
#

verify_runnable "both"

function cleanup
{
	datasetexists $TESTPOOL/$TESTFS1 && \
		log_must zfs destroy -r $TESTPOOL/$TESTFS1
}

log_assert "'zfs diff' should work with encrypted datasets"
log_onexit cleanup

# 1. Create an encrypted dataset
log_must eval "echo 'password' | zfs create -o encryption=on \
	-o keyformat=passphrase $TESTPOOL/$TESTFS1"
MNTPOINT="$(get_prop mountpoint $TESTPOOL/$TESTFS1)"

# 2. Create two snapshots of the dataset
log_must zfs snapshot $TESTPOOL/$TESTFS1@snap1
log_must touch "$MNTPOINT/file"
log_must zfs snapshot $TESTPOOL/$TESTFS1@snap2

# 3. Perform 'zfs diff' and verify no errors occur
log_must zfs diff -Ft $TESTPOOL/$TESTFS1@snap1 $TESTPOOL/$TESTFS1@snap2

log_pass "'zfs diff' works with encrypted datasets"

A usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_timestamp.ksh => usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_timestamp.ksh +100 -0
@@ 0,0 1,100 @@
#!/bin/ksh -p
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source.  A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#

#
# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
#

. $STF_SUITE/include/libtest.shlib

#
# DESCRIPTION:
# 'zfs diff -t' should display inode change time correctly.
#
# STRATEGY:
# 1. Create a snapshot
# 2. Create some files with a random delay and snapshot the filesystem again
# 3. Verify 'zfs diff -t' correctly display timestamps
#

verify_runnable "both"

function cleanup
{
	for snap in $TESTSNAP1 $TESTSNAP2; do
		if snapexists "$snap"; then
			log_must zfs destroy "$snap"
		fi
	done
	find "$MNTPOINT" -type f -delete
	rm -f "$FILEDIFF"
}

#
# Creates $count files in $fspath. Waits a random delay between each file.
#
function create_random # <fspath> <count>
{
	fspath="$1"
	typeset -i count="$2"
	typeset -i i=0

	while (( i < count )); do
		log_must touch "$fspath/file$i"
		sleep $(random 3)
		(( i = i + 1 ))
	done
}

log_assert "'zfs diff -t' should display inode change time correctly."
log_onexit cleanup

DATASET="$TESTPOOL/$TESTFS"
TESTSNAP1="$DATASET@snap1"
TESTSNAP2="$DATASET@snap2"
MNTPOINT="$(get_prop mountpoint $DATASET)"
FILEDIFF="$TESTDIR/zfs-diff.txt"
FILENUM=5

# 1. Create a snapshot
log_must zfs snapshot "$TESTSNAP1"

# 2. Create some files with a random delay and snapshot the filesystem again
create_random "$MNTPOINT" $FILENUM
log_must zfs snapshot "$TESTSNAP2"

# 3. Verify 'zfs diff -t' correctly display timestamps
typeset -i count=0
log_must eval "zfs diff -t $TESTSNAP1 $TESTSNAP2 > $FILEDIFF"
nawk '{print substr($1,1,index($1,".")-1)" "$NF}' < "$FILEDIFF" | while read line
do
	read ctime file <<< "$line"

	# If path from 'zfs diff' is not a file (could be xattr object) skip it
	if [[ ! -f "$file" ]]; then
		continue;
	fi

	filetime="$(stat -c '%Z' $file)"
	if [[ "$filetime" != "$ctime" ]]; then
		log_fail "Unexpected ctime for file $file ($filetime != $ctime)"
	else
		log_note "Correct ctime read on $file: $ctime"
	fi

	(( i = i + 1 ))
done
if [[ $i != $FILENUM ]]; then
	log_fail "Wrong number of files verified ($i != $FILENUM)"
fi

log_pass "'zfs diff -t' displays inode change time correctly."

A usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_types.ksh => usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_types.ksh +126 -0
@@ 0,0 1,126 @@
#!/bin/ksh -p
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source.  A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#

#
# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
# Copyright 2019 Joyent, Inc.
#

. $STF_SUITE/include/libtest.shlib

#
# DESCRIPTION:
# 'zfs diff -F' shows different object types correctly.
#
# STRATEGY:
# 1. Prepare a dataset
# 2. Create different objects and verify 'zfs diff -F' shows the correct type
#

verify_runnable "both"

function cleanup
{
	log_must zfs destroy -r "$DATASET"
	rm -f "$FILEDIFF"
}

#
# Verify object at $path is of type $symbol using 'zfs diff -F'
# Valid types are:
# * B (Block device)
# * C (Character device)
# * / (Directory)
# * > (Door)
# * | (Named pipe)
# * @ (Symbolic link)
# * P (Event port)
# * = (Socket)
# * F (Regular file)
#
function verify_object_class # <path> <symbol>
{
	path="$1"
	symbol="$2"

	log_must eval "zfs diff -F $TESTSNAP1 $TESTSNAP2 > $FILEDIFF"
	diffsym="$(nawk -v path="$path" '$NF == path { print $2 }' < $FILEDIFF)"
	if [[ "$diffsym" != "$symbol" ]]; then
		log_fail "Unexpected type for $path ('$diffsym' != '$symbol')"
	else
		log_note "Object $path type is correctly displayed as '$symbol'"
	fi

	log_must zfs destroy "$TESTSNAP1"
	log_must zfs destroy "$TESTSNAP2"
}

log_assert "'zfs diff -F' should show different object types correctly."
log_onexit cleanup

DATASET="$TESTPOOL/$TESTFS/fs"
TESTSNAP1="$DATASET@snap1"
TESTSNAP2="$DATASET@snap2"
FILEDIFF="$TESTDIR/zfs-diff.txt"
MAJOR=$(stat -c %t /dev/null)
MINOR=$(stat -c %T /dev/null)

# 1. Prepare a dataset
log_must zfs create $DATASET
MNTPOINT="$(get_prop mountpoint $DATASET)"
log_must zfs set devices=on $DATASET
log_must zfs set xattr=on $DATASET

# 2. Create different objects and verify 'zfs diff -F' shows the correct type
# 2. F (Regular file)
log_must zfs snapshot "$TESTSNAP1"
log_must touch "$MNTPOINT/file"
log_must zfs snapshot "$TESTSNAP2"
verify_object_class "$MNTPOINT/file" "F"

# 2. @ (Symbolic link)
log_must zfs snapshot "$TESTSNAP1"
log_must ln -s "$MNTPOINT/file" "$MNTPOINT/link"
log_must zfs snapshot "$TESTSNAP2"
verify_object_class "$MNTPOINT/link" "@"

# 2. B (Block device)
log_must zfs snapshot "$TESTSNAP1"
log_must mknod "$MNTPOINT/bdev" b $MAJOR $MINOR
log_must zfs snapshot "$TESTSNAP2"
verify_object_class "$MNTPOINT/bdev" "B"

# 2. C (Character device)
log_must zfs snapshot "$TESTSNAP1"
log_must mknod "$MNTPOINT/cdev" c $MAJOR $MINOR
log_must zfs snapshot "$TESTSNAP2"
verify_object_class "$MNTPOINT/cdev" "C"

# 2. | (Named pipe)
log_must zfs snapshot "$TESTSNAP1"
log_must mknod "$MNTPOINT/fifo" p
log_must zfs snapshot "$TESTSNAP2"
verify_object_class "$MNTPOINT/fifo" "|"

# 2. / (Directory)
log_must zfs snapshot "$TESTSNAP1"
log_must mkdir "$MNTPOINT/dir"
log_must zfs snapshot "$TESTSNAP2"
verify_object_class "$MNTPOINT/dir" "/"

# 2. = (Socket)
log_must zfs snapshot "$TESTSNAP1"
log_must $STF_SUITE/tests/functional/cli_root/zfs_diff/socket "$MNTPOINT/sock"
log_must zfs snapshot "$TESTSNAP2"
verify_object_class "$MNTPOINT/sock" "="

log_pass "'zfs diff -F' shows different object types correctly."