summaryrefslogtreecommitdiff
path: root/usr/src/test/zfs-tests
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/test/zfs-tests')
-rw-r--r--usr/src/test/zfs-tests/include/commands.cfg1
-rw-r--r--usr/src/test/zfs-tests/include/libtest.shlib4
-rw-r--r--usr/src/test/zfs-tests/runfiles/delphix.run7
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/Makefile42
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/channel_common.kshlib100
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/Makefile68
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/cleanup.ksh19
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/nvlist_to_lua.c304
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/setup.ksh21
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.ksh30
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.out1
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.zcp25
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.err4
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.ksh30
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.zcp16
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.integer_illegal.ksh41
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.integer_overflow.ksh32
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.language_functions_neg.ksh52
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.language_functions_pos.ksh42
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.ksh30
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.out1
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.zcp280
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.memory_limit.ksh74
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_neg.ksh24
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_neg.zcp769
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_pos.ksh23
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_pos.zcp71
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.nvlist_to_lua.ksh30
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive.zcp31
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive_neg.ksh24
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive_pos.ksh23
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.return_nvlist_neg.ksh65
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.return_nvlist_pos.ksh59
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.return_recursive_table.ksh33
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.return_recursive_table.zcp21
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.timeout.ksh56
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.timeout.zcp22
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/Makefile45
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/cleanup.ksh19
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/setup.ksh21
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.destroy_fs.ksh45
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.destroy_snap.ksh44
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_count_and_limit.ksh89
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.ksh40
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.out4
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.zcp65
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_mountpoint.ksh88
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_neg.ksh43
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.ksh52
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.out5
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.zcp100
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.ksh45
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.out5
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.zcp73
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_type.ksh54
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_userquota.ksh80
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_written.ksh57
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_children.ksh125
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_clones.ksh117
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_snapshots.ksh116
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_system_props.ksh54
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.parse_args_neg.ksh48
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_conflict.ksh55
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_conflict.zcp23
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_multiple.ksh71
-rw-r--r--usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_simple.ksh47
-rw-r--r--usr/src/test/zfs-tests/tests/functional/cli_user/misc/zfs_channel_001_neg.ksh45
67 files changed, 4148 insertions, 2 deletions
diff --git a/usr/src/test/zfs-tests/include/commands.cfg b/usr/src/test/zfs-tests/include/commands.cfg
index 462f0e55e3..6d87b7ebeb 100644
--- a/usr/src/test/zfs-tests/include/commands.cfg
+++ b/usr/src/test/zfs-tests/include/commands.cfg
@@ -102,6 +102,7 @@ export USR_BIN_FILES='awk
svcs
sync
tail
+ tee
timeout
touch
tr
diff --git a/usr/src/test/zfs-tests/include/libtest.shlib b/usr/src/test/zfs-tests/include/libtest.shlib
index 3a3c1c466d..f5b9d7c32e 100644
--- a/usr/src/test/zfs-tests/include/libtest.shlib
+++ b/usr/src/test/zfs-tests/include/libtest.shlib
@@ -195,12 +195,12 @@ function default_container_volume_setup
# Create a snapshot on a filesystem or volume. Defaultly create a snapshot on
# filesystem
#
-# $1 Existing filesystem or volume name. Default, $TESTFS
+# $1 Existing filesystem or volume name. Default, $TESTPOOL/$TESTFS
# $2 snapshot name. Default, $TESTSNAP
#
function create_snapshot
{
- typeset fs_vol=${1:-$TESTFS}
+ typeset fs_vol=${1:-$TESTPOOL/$TESTFS}
typeset snap=${2:-$TESTSNAP}
[[ -z $fs_vol ]] && log_fail "Filesystem or volume's name is undefined."
diff --git a/usr/src/test/zfs-tests/runfiles/delphix.run b/usr/src/test/zfs-tests/runfiles/delphix.run
index aaeb65de38..444add0b96 100644
--- a/usr/src/test/zfs-tests/runfiles/delphix.run
+++ b/usr/src/test/zfs-tests/runfiles/delphix.run
@@ -83,6 +83,12 @@ tests = ['case_all_values', 'norm_all_values',
'mixed_none_lookup', 'mixed_none_lookup_ci', 'mixed_none_delete',
'mixed_formd_lookup', 'mixed_formd_lookup_ci', 'mixed_formd_delete']
+[/opt/zfs-tests/tests/functional/channel_program/lua_core]
+autotests = 1
+
+[/opt/zfs-tests/tests/functional/channel_program/synctask_core]
+autotests = 1
+
[/opt/zfs-tests/tests/functional/checksum]
tests = ['run_edonr_test', 'run_sha2_test', 'run_skein_test']
pre =
@@ -317,6 +323,7 @@ tests = ['zdb_001_neg', 'zfs_001_neg', 'zfs_allow_001_neg',
'zfs_rollback_001_neg', 'zfs_send_001_neg', 'zfs_set_001_neg',
'zfs_share_001_neg', 'zfs_snapshot_001_neg', 'zfs_unallow_001_neg',
'zfs_unmount_001_neg', 'zfs_unshare_001_neg', 'zfs_upgrade_001_neg',
+ 'zfs_channel_001_neg',
'zpool_001_neg', 'zpool_add_001_neg', 'zpool_attach_001_neg',
'zpool_clear_001_neg', 'zpool_create_001_neg', 'zpool_destroy_001_neg',
'zpool_detach_001_neg', 'zpool_export_001_neg', 'zpool_get_001_neg',
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/Makefile b/usr/src/test/zfs-tests/tests/functional/channel_program/Makefile
new file mode 100644
index 0000000000..e6c251094f
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/Makefile
@@ -0,0 +1,42 @@
+#
+# 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 (c) 2016 by Delphix. All rights reserved.
+#
+
+.PARALLEL: $(SUBDIRS)
+
+include $(SRC)/Makefile.master
+
+ROOTOPTPKG = $(ROOT)/opt/zfs-tests
+TESTDIR = $(ROOTOPTPKG)/tests/functional/channel_program
+
+PROGS = channel_common.kshlib
+
+CMDS = $(PROGS:%=$(TESTDIR)/%)
+$(CMDS) := FILEMODE = 0555
+
+all lint clean clobber:
+
+install: $(CMDS)
+
+$(CMDS): $(TESTDIR)
+
+$(TESTDIR):
+ $(INS.dir)
+
+$(TESTDIR)/%: %
+ $(INS.file)
+
+SUBDIRS = lua_core synctask_core
+
+include $(SRC)/test/Makefile.com
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/channel_common.kshlib b/usr/src/test/zfs-tests/tests/functional/channel_program/channel_common.kshlib
new file mode 100644
index 0000000000..f3097940f9
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/channel_common.kshlib
@@ -0,0 +1,100 @@
+#!/bin/ksh
+#
+# 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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+ZCP_ROOT=$STF_SUITE/tests/functional/channel_program
+
+# <exitcode> <expected error string> <zfs program args>
+# e.g. log_program 0 $POOL foo.zcp arg1 arg2
+function log_program
+{
+ typeset expectexit=$1
+ shift
+ typeset expecterror=$1
+ shift
+ typeset cmdargs=$@ tmpout=$(mktemp) tmperr=$(mktemp) tmpin=$(mktemp)
+
+ # Expected output/error filename is the same as the .zcp name
+ typeset basename
+ if [[ $2 != "-" ]]; then
+ basename=${2%.*}
+ fi
+
+ log_note "running: zfs program $cmdargs:"
+
+ tee $tmpin | zfs program $cmdargs >$tmpout 2>$tmperr
+ typeset ret=$?
+
+ log_note "input:\n$(cat $tmpin)"
+ log_note "output:\n$(cat $tmpout)"
+ log_note "error:\n$(cat $tmperr)"
+ # verify correct return value
+ if [[ $ret -ne $expectexit ]]; then
+ log_fail "return mismatch: expected $expectexit, got $ret"
+ fi
+
+ #
+ # Check the output or reported error for successful or error returns,
+ # respectively.
+ if [[ -f "$basename.out" ]] && [[ $expectexit -eq 0 ]]; then
+
+ outdiff=$(diff "$basename.out" "$tmpout")
+ [[ $? -ne 0 ]] && log_fail "Output mismatch. Expected:\n" \
+ "$(cat $basename.out)\nBut got:$(cat $tmpout)\n" \
+ "Diff:\n$outdiff"
+
+ elif [[ -f "$basename.err" ]] && [[ $expectexit -ne 0 ]]; then
+
+ outdiff=$(diff "$basename.err" "$tmperr")
+ [[ $? -ne 0 ]] && log_fail "Error mismatch. Expected:\n" \
+ "$(cat $basename.err)\nBut got:$(cat $tmpout)\n" \
+ "Diff:\n$outdiff"
+
+ elif [[ -n $expecterror ]] && [[ $expectexit -ne 0 ]]; then
+
+ grep -q "$expecterror" $tmperr || \
+ log_fail "Error mismatch. Expected to contain:\n" \
+ "$expecterror\nBut got:$(cat $tmpout)\n"
+
+ elif [[ $expectexit -ne 0 ]]; then
+ #
+ # If there's no expected output, error reporting is allowed to
+ # vary, but ensure that we didn't fail silently.
+ #
+ [[ -z "$(cat $tmperr)" ]] && \
+ log_fail "error with no stderr output"
+ fi
+
+ rm $tmpout $tmperr
+}
+
+function log_must_program
+{
+ log_program 0 "" "$@"
+}
+
+function log_mustnot_program
+{
+ log_program 1 "" "$@"
+}
+
+function log_mustnot_checkerror_program
+{
+ typeset expecterror=$1
+ shift
+ log_program 1 "$expecterror" "$@"
+}
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/Makefile b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/Makefile
new file mode 100644
index 0000000000..21f3ff6c39
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/Makefile
@@ -0,0 +1,68 @@
+#
+# 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 (c) 2016 by Delphix. All rights reserved.
+#
+
+include $(SRC)/cmd/Makefile.cmd
+
+ROOTOPTPKG = $(ROOT)/opt/zfs-tests
+TESTDIR = $(ROOTOPTPKG)/tests/functional/channel_program/lua_core
+
+KSHFILES :sh= ls *.ksh
+KSHPROGS = $(KSHFILES:%.ksh=%)
+SRCS :sh= ls *.c
+CPROGS = $(SRCS:%.c=%.exe)
+PROGS = $(KSHPROGS) $(CPROGS)
+FILES :sh= ls *.zcp *.out *.err
+LDLIBS = $(LDLIBS.cmd)
+LDLIBS += -lzfs_core -lnvpair
+C99MODE = -xc99=%all
+
+INSTPROGS = $(PROGS:%=$(TESTDIR)/%)
+INSTFILES = $(FILES:%=$(TESTDIR)/%)
+
+OBJS = $(SRCS:%.c=%.o)
+
+$(INSTPROGS) := FILEMODE = 0555
+$(INSTFILES) := FILEMODE = 0444
+
+all lint: $(CPROGS)
+ echo SRCS: $(SRCS)
+ echo PROGS: $(PROGS)
+
+install: $(INSTPROGS) $(INSTFILES)
+
+$(INSTPROGS): $(TESTDIR)
+$(INSTFILES): $(TESTDIR)
+
+$(TESTDIR):
+ $(INS.dir)
+
+$(TESTDIR)/%: %.ksh
+ $(INS.rename)
+
+$(TESTDIR)/%: %
+ $(INS.file)
+
+%.o: ../%.c
+ $(COMPILE.c) $<
+
+%.exe: %.o
+ $(LINK.c) $< -o $@ $(LDLIBS)
+ $(POST_PROCESS)
+
+clobber: clean
+ -$(RM) $(PROGS)
+
+clean:
+ -$(RM) $(OBJS)
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/cleanup.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/cleanup.ksh
new file mode 100644
index 0000000000..f442da2236
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/cleanup.ksh
@@ -0,0 +1,19 @@
+#!/usr/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/nvlist_to_lua.c b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/nvlist_to_lua.c
new file mode 100644
index 0000000000..c66a7df3c8
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/nvlist_to_lua.c
@@ -0,0 +1,304 @@
+/*
+ * CDDL HEADER START
+ *
+ * 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.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2016 by Delphix. All rights reserved.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <libzfs_core.h>
+#include <sys/nvpair.h>
+
+nvlist_t *nvl;
+const char *pool;
+boolean_t unexpected_failures;
+
+static boolean_t
+nvlist_equal(nvlist_t *nvla, nvlist_t *nvlb)
+{
+ if (fnvlist_num_pairs(nvla) != fnvlist_num_pairs(nvlb))
+ return (B_FALSE);
+ /*
+ * The nvlists have the same number of pairs and keys are unique, so
+ * if every key in A is also in B and assigned to the same value, the
+ * lists are identical.
+ */
+ for (nvpair_t *pair = nvlist_next_nvpair(nvla, NULL);
+ pair != NULL; pair = nvlist_next_nvpair(nvla, pair)) {
+ char *key = nvpair_name(pair);
+
+ if (!nvlist_exists(nvlb, key))
+ return (B_FALSE);
+
+ if (nvpair_type(pair) !=
+ nvpair_type(fnvlist_lookup_nvpair(nvlb, key)))
+ return (B_FALSE);
+
+ switch (nvpair_type(pair)) {
+ case DATA_TYPE_BOOLEAN_VALUE:
+ if (fnvpair_value_boolean_value(pair) !=
+ fnvlist_lookup_boolean_value(nvlb, key)) {
+ return (B_FALSE);
+ }
+ break;
+ case DATA_TYPE_STRING:
+ if (strcmp(fnvpair_value_string(pair),
+ fnvlist_lookup_string(nvlb, key))) {
+ return (B_FALSE);
+ }
+ break;
+ case DATA_TYPE_INT64:
+ if (fnvpair_value_int64(pair) !=
+ fnvlist_lookup_int64(nvlb, key)) {
+ return (B_FALSE);
+ }
+ break;
+ case DATA_TYPE_NVLIST:
+ if (!nvlist_equal(fnvpair_value_nvlist(pair),
+ fnvlist_lookup_nvlist(nvlb, key))) {
+ return (B_FALSE);
+ }
+ break;
+ default:
+ (void) printf("Unexpected type for nvlist_equal\n");
+ return (B_FALSE);
+ }
+ }
+ return (B_TRUE);
+}
+
+static void
+test(const char *testname, boolean_t expect_success, boolean_t expect_match)
+{
+ char *progstr = "input = ...; return {output=input}";
+
+ nvlist_t *outnvl;
+
+ (void) printf("\nrunning test '%s'; input:\n", testname);
+ dump_nvlist(nvl, 4);
+
+ int err = lzc_channel_program(pool, progstr,
+ 10 * 1000 * 1000, 10 * 1024 * 1024, nvl, &outnvl);
+
+ (void) printf("lzc_channel_program returned %u\n", err);
+ dump_nvlist(outnvl, 5);
+
+ if (err == 0 && expect_match) {
+ /*
+ * Verify that outnvl is the same as input nvl, if we expect
+ * them to be. The input and output will never match if the
+ * input contains an array (since arrays are converted to lua
+ * tables), so this is only asserted for some test cases.
+ */
+ nvlist_t *real_outnvl = fnvlist_lookup_nvlist(outnvl, "return");
+ real_outnvl = fnvlist_lookup_nvlist(real_outnvl, "output");
+ if (!nvlist_equal(nvl, real_outnvl)) {
+ unexpected_failures = B_TRUE;
+ (void) printf("unexpected input/output mismatch for "
+ "case: %s\n", testname);
+ }
+ }
+ if (err != 0 && expect_success) {
+ unexpected_failures = B_TRUE;
+ (void) printf("unexpected FAIL of case: %s\n", testname);
+ }
+
+ fnvlist_free(nvl);
+ nvl = fnvlist_alloc();
+}
+
+static void
+run_tests(void)
+{
+ const char *key = "key";
+
+ /* Note: maximum nvlist key length is 32KB */
+ int len = 1024 * 31;
+ char *bigstring = malloc(len);
+ for (int i = 0; i < len; i++)
+ bigstring[i] = 'a' + i % 26;
+ bigstring[len - 1] = '\0';
+
+ nvl = fnvlist_alloc();
+
+ fnvlist_add_boolean(nvl, key);
+ test("boolean", B_TRUE, B_FALSE);
+
+ fnvlist_add_boolean_value(nvl, key, B_TRUE);
+ test("boolean_value", B_FALSE, B_FALSE);
+
+ fnvlist_add_byte(nvl, key, 1);
+ test("byte", B_FALSE, B_FALSE);
+
+ fnvlist_add_int8(nvl, key, 1);
+ test("int8", B_FALSE, B_FALSE);
+
+ fnvlist_add_uint8(nvl, key, 1);
+ test("uint8", B_FALSE, B_FALSE);
+
+ fnvlist_add_int16(nvl, key, 1);
+ test("int16", B_FALSE, B_FALSE);
+
+ fnvlist_add_uint16(nvl, key, 1);
+ test("uint16", B_FALSE, B_FALSE);
+
+ fnvlist_add_int32(nvl, key, 1);
+ test("int32", B_FALSE, B_FALSE);
+
+ fnvlist_add_uint32(nvl, key, 1);
+ test("uint32", B_FALSE, B_FALSE);
+
+ fnvlist_add_int64(nvl, key, 1);
+ test("int64", B_TRUE, B_TRUE);
+
+ fnvlist_add_uint64(nvl, key, 1);
+ test("uint64", B_FALSE, B_FALSE);
+
+ fnvlist_add_string(nvl, key, "1");
+ test("string", B_TRUE, B_TRUE);
+
+
+ {
+ nvlist_t *val = fnvlist_alloc();
+ fnvlist_add_string(val, "subkey", "subvalue");
+ fnvlist_add_nvlist(nvl, key, val);
+ fnvlist_free(val);
+ test("nvlist", B_TRUE, B_TRUE);
+ }
+ {
+ boolean_t val[2] = { B_FALSE, B_TRUE };
+ fnvlist_add_boolean_array(nvl, key, val, 2);
+ test("boolean_array", B_FALSE, B_FALSE);
+ }
+ {
+ uchar_t val[2] = { 0, 1 };
+ fnvlist_add_byte_array(nvl, key, val, 2);
+ test("byte_array", B_FALSE, B_FALSE);
+ }
+ {
+ int8_t val[2] = { 0, 1 };
+ fnvlist_add_int8_array(nvl, key, val, 2);
+ test("int8_array", B_FALSE, B_FALSE);
+ }
+ {
+ uint8_t val[2] = { 0, 1 };
+ fnvlist_add_uint8_array(nvl, key, val, 2);
+ test("uint8_array", B_FALSE, B_FALSE);
+ }
+ {
+ int16_t val[2] = { 0, 1 };
+ fnvlist_add_int16_array(nvl, key, val, 2);
+ test("int16_array", B_FALSE, B_FALSE);
+ }
+ {
+ uint16_t val[2] = { 0, 1 };
+ fnvlist_add_uint16_array(nvl, key, val, 2);
+ test("uint16_array", B_FALSE, B_FALSE);
+ }
+ {
+ int32_t val[2] = { 0, 1 };
+ fnvlist_add_int32_array(nvl, key, val, 2);
+ test("int32_array", B_FALSE, B_FALSE);
+ }
+ {
+ uint32_t val[2] = { 0, 1 };
+ fnvlist_add_uint32_array(nvl, key, val, 2);
+ test("uint32_array", B_FALSE, B_FALSE);
+ }
+ {
+ int64_t val[2] = { 0, 1 };
+ fnvlist_add_int64_array(nvl, key, val, 2);
+ test("int64_array", B_TRUE, B_FALSE);
+ }
+ {
+ uint64_t val[2] = { 0, 1 };
+ fnvlist_add_uint64_array(nvl, key, val, 2);
+ test("uint64_array", B_FALSE, B_FALSE);
+ }
+ {
+ char *const val[2] = { "0", "1" };
+ fnvlist_add_string_array(nvl, key, val, 2);
+ test("string_array", B_TRUE, B_FALSE);
+ }
+ {
+ nvlist_t *val[2];
+ val[0] = fnvlist_alloc();
+ fnvlist_add_string(val[0], "subkey", "subvalue");
+ val[1] = fnvlist_alloc();
+ fnvlist_add_string(val[1], "subkey2", "subvalue2");
+ fnvlist_add_nvlist_array(nvl, key, val, 2);
+ fnvlist_free(val[0]);
+ fnvlist_free(val[1]);
+ test("nvlist_array", B_FALSE, B_FALSE);
+ }
+ {
+ fnvlist_add_string(nvl, bigstring, "1");
+ test("large_key", B_TRUE, B_TRUE);
+ }
+ {
+ fnvlist_add_string(nvl, key, bigstring);
+ test("large_value", B_TRUE, B_TRUE);
+ }
+ {
+ for (int i = 0; i < 1024; i++) {
+ char buf[32];
+ (void) snprintf(buf, sizeof (buf), "key-%u", i);
+ fnvlist_add_int64(nvl, buf, i);
+ }
+ test("many_keys", B_TRUE, B_TRUE);
+ }
+ {
+ for (int i = 0; i < 10; i++) {
+ nvlist_t *newval = fnvlist_alloc();
+ fnvlist_add_nvlist(newval, "key", nvl);
+ fnvlist_free(nvl);
+ nvl = newval;
+ }
+ test("deeply_nested_pos", B_TRUE, B_TRUE);
+ }
+ {
+ for (int i = 0; i < 90; i++) {
+ nvlist_t *newval = fnvlist_alloc();
+ fnvlist_add_nvlist(newval, "key", nvl);
+ fnvlist_free(nvl);
+ nvl = newval;
+ }
+ test("deeply_nested_neg", B_FALSE, B_FALSE);
+ }
+
+ free(bigstring);
+ fnvlist_free(nvl);
+}
+
+int
+main(int argc, const char *argv[])
+{
+ (void) libzfs_core_init();
+
+ if (argc != 2) {
+ (void) printf("usage: %s <pool>\n",
+ argv[0]);
+ exit(2);
+ }
+ pool = argv[1];
+
+ run_tests();
+
+ libzfs_core_fini();
+ return (unexpected_failures);
+}
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/setup.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/setup.ksh
new file mode 100644
index 0000000000..171fd40e41
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/setup.ksh
@@ -0,0 +1,21 @@
+#!/usr/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup ${DISK}
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.ksh
new file mode 100644
index 0000000000..6ec5610639
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.ksh
@@ -0,0 +1,30 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Passing arguments to lua programs should work correctly.
+#
+
+verify_runnable "global"
+
+log_assert "Passing arguments to lua programs should work correctly."
+
+log_must_program $TESTPOOL $ZCP_ROOT/lua_core/tst.args_to_lua.zcp foo bar
+
+log_pass "Passing arguments to lua programs should work correctly."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.out b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.out
new file mode 100644
index 0000000000..84191f8f80
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.out
@@ -0,0 +1 @@
+Channel program fully executed with no return value.
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.zcp b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.zcp
new file mode 100644
index 0000000000..f6f14e5222
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.zcp
@@ -0,0 +1,25 @@
+--
+-- 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 (c) 2016 by Delphix. All rights reserved.
+--
+
+-- This program should be invoked as "zfs program <pool> <prog> foo bar"
+
+arg = ...
+argv = arg["argv"]
+
+assert(#argv == 2)
+assert(argv[1] == "foo")
+assert(argv[2] == "bar")
+
+return
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.err b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.err
new file mode 100644
index 0000000000..fd67d09f73
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.err
@@ -0,0 +1,4 @@
+Channel program execution failed:
+[string "channel program"]:16: attempt to divide by zero
+stack traceback:
+ [string "channel program"]:16: in main chunk
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.ksh
new file mode 100644
index 0000000000..2587c594da
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.ksh
@@ -0,0 +1,30 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Divide by zero should fail gracefully.
+#
+
+verify_runnable "global"
+
+log_assert "Divide by zero should fail gracefully."
+
+log_mustnot_program $TESTPOOL $ZCP_ROOT/lua_core/tst.divide_by_zero.zcp
+
+log_pass "Divide by zero should fail gracefully."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.zcp b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.zcp
new file mode 100644
index 0000000000..bd882d493b
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.zcp
@@ -0,0 +1,16 @@
+--
+-- 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 (c) 2016 by Delphix. All rights reserved.
+--
+
+return 1 / 0
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.integer_illegal.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.integer_illegal.ksh
new file mode 100644
index 0000000000..c34f2afd9e
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.integer_illegal.ksh
@@ -0,0 +1,41 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Constructing integers that are doubles, too large, or too
+# small should fail gracefully.
+#
+
+verify_runnable "global"
+
+log_assert "constructing illegal integer values should fail gracefully"
+
+set -A args "1.0" \
+ "1.5" \
+ "-1.5"
+
+typeset -i i=0
+while (( i < ${#args[*]} )); do
+ log_mustnot_checkerror_program "malformed number" $TESTPOOL - <<-EOF
+ return ${args[i]}
+ EOF
+ ((i = i + 1))
+done
+
+log_pass "constructing illegal integer values should fail gracefully"
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.integer_overflow.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.integer_overflow.ksh
new file mode 100644
index 0000000000..c129bae51b
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.integer_overflow.ksh
@@ -0,0 +1,32 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Overflowing a 64-bit integer should wrap around.
+#
+
+verify_runnable "global"
+
+log_assert "overflowing a 64-bit integer should wrap around"
+
+log_must_program $TESTPOOL - <<-EOF
+ assert(18446744073709551615 + 1 == (-18446744073709551616))
+EOF
+
+log_pass "overflowing a 64-bit integer should wrap around"
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.language_functions_neg.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.language_functions_neg.ksh
new file mode 100644
index 0000000000..0125d76c70
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.language_functions_neg.ksh
@@ -0,0 +1,52 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Try channel programs with various lua runtime issues.
+# the program should fail, but the system should not crash.
+# Issues include:
+# * syntax errors
+# * misuse of language constructs (e.g. indexing non-tables)
+# * the error() function
+# * the assert() function
+#
+
+verify_runnable "global"
+
+set -A args "{]" \
+ "retrn 1" \
+ "abc = nil; abc.deref" \
+ "abc = nil; abc()" \
+ "error(0)" \
+ "error(\"string\")" \
+ "error(true)" \
+ "error({})" \
+ "assert(false)"
+
+log_assert "Runtime errors in lua scripts fail as expected."
+
+typeset -i i=0
+while (( i < ${#args[*]} )); do
+ log_mustnot_checkerror_program "execution failed" $TESTPOOL - <<-EOF
+ ${args[i]}
+ EOF
+ ((i = i + 1))
+done
+
+log_pass "Runtime errors in lua scripts fail as expected."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.language_functions_pos.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.language_functions_pos.ksh
new file mode 100644
index 0000000000..924d8e2c69
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.language_functions_pos.ksh
@@ -0,0 +1,42 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Try very simple programs that interact with the core lua
+# runtime rather than ZFS functions, just to make sure the
+# runtime is hooked up correctly.
+#
+
+verify_runnable "global"
+
+set -A args "" \
+ "assert(true)" \
+ "x = 1 + 1"
+
+log_assert "Simple lua scripts pass."
+
+typeset -i i=0
+while (( i < ${#args[*]} )); do
+ log_must_program $TESTPOOL - <<-EOF
+ ${args[i]}
+ EOF
+ ((i = i + 1))
+done
+
+log_pass "Simple lua scripts pass."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.ksh
new file mode 100644
index 0000000000..21ab69adb1
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.ksh
@@ -0,0 +1,30 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Running a large program file should work correctly.
+#
+
+verify_runnable "global"
+
+log_assert "Running a large program file should work correctly."
+
+log_must_program $TESTPOOL $ZCP_ROOT/lua_core/tst.large_prog.zcp
+
+log_pass "Running a large program file should work correctly."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.out b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.out
new file mode 100644
index 0000000000..84191f8f80
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.out
@@ -0,0 +1 @@
+Channel program fully executed with no return value.
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.zcp b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.zcp
new file mode 100644
index 0000000000..add6897334
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.zcp
@@ -0,0 +1,280 @@
+--
+-- 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 (c) 2016 by Delphix. All rights reserved.
+--
+
+-- /sbin/zfs initially allocates 1KB for the channel program file. This
+-- program file is larger than that, to test the reallocation and
+-- passing of a large channel string to the kernel.
+-- This file is at least 16KB long.
+
+--[[
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+]]
+
+return
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.memory_limit.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.memory_limit.ksh
new file mode 100644
index 0000000000..dbac583872
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.memory_limit.ksh
@@ -0,0 +1,74 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+
+#
+# DESCRIPTION:
+# Passing memory limit options to channel programs should work correctly.
+# Programs that exceed these limits should fail gracefully.
+
+
+verify_runnable "global"
+
+log_mustnot_checkerror_program "Memory limit exhausted" \
+ -t 100000000 $TESTPOOL - <<-EOF
+ a = {};
+ i = 0;
+ while true do
+ i = i + 1
+ a[i] = "Here is the " .. i .. "th entry of a"
+ end;
+ return a
+EOF
+
+log_assert "memory limit options work"
+log_mustnot_checkerror_program "Memory limit exhausted" \
+ -m 100000 -t 100000000 $TESTPOOL - <<-EOF
+ a = {};
+ i = 0;
+ while true do
+ i = i + 1
+ a[i] = "Here is the " .. i .. "th entry of a"
+ end;
+ return a
+EOF
+
+log_must_program -m 100000 $TESTPOOL - <<-EOF
+ s = "teststring"
+ s = s .. s .. s .. s
+ return s
+EOF
+
+log_assert "very small memory limits fail correctly"
+log_mustnot_checkerror_program "Memory limit exhausted" -m 1 $TESTPOOL - <<-EOF
+ s = "teststring"
+ s = s .. s .. s .. s
+ return s
+EOF
+
+log_mustnot_checkerror_program "Invalid memory limit" \
+ -m 1000000000000 $TESTPOOL - <<-EOF
+ return 1;
+EOF
+
+log_mustnot_checkerror_program "Invalid memory limit" \
+ -m 9223372036854775808 $TESTPOOL - <<-EOF
+ return 1;
+EOF
+
+log_pass "Memory limits work correctly."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_neg.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_neg.ksh
new file mode 100644
index 0000000000..9ec8f248d1
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_neg.ksh
@@ -0,0 +1,24 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+verify_runnable "global"
+
+log_mustnot_checkerror_program "too many C levels" \
+ $TESTPOOL $ZCP_ROOT/lua_core/tst.nested_neg.zcp
+
+log_pass "Too many nested lua statements fail cleanly."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_neg.zcp b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_neg.zcp
new file mode 100644
index 0000000000..c41c714f27
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_neg.zcp
@@ -0,0 +1,769 @@
+--
+-- 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 (c) 2016 by Delphix. All rights reserved.
+--
+
+-- This program contains deeply nested LUA statements, such that the LUA
+-- parser can not process it, given the limited size of the C stack.
+
+i = 0
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+return i
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_pos.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_pos.ksh
new file mode 100644
index 0000000000..0c8b8dd8d0
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_pos.ksh
@@ -0,0 +1,23 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+verify_runnable "global"
+
+log_must_program $TESTPOOL $ZCP_ROOT/lua_core/tst.nested_pos.zcp
+
+log_pass "Nested lua statements work correctly."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_pos.zcp b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_pos.zcp
new file mode 100644
index 0000000000..02af95d99d
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_pos.zcp
@@ -0,0 +1,71 @@
+--
+-- 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 (c) 2016 by Delphix. All rights reserved.
+--
+
+-- This program should work with LUAI_MAXCCALLS=20
+
+i = 0
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+
+return i
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.nvlist_to_lua.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.nvlist_to_lua.ksh
new file mode 100644
index 0000000000..8575933cc9
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.nvlist_to_lua.ksh
@@ -0,0 +1,30 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+verify_runnable "global"
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# run C program which tests passing different nvlists to lua
+#
+
+log_assert "nvlist arguments can be passed to LUA."
+
+log_must $ZCP_ROOT/lua_core/nvlist_to_lua.exe $TESTPOOL
+
+log_pass "nvlist arguments can be passed to LUA."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive.zcp b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive.zcp
new file mode 100644
index 0000000000..9a13c1e7dc
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive.zcp
@@ -0,0 +1,31 @@
+--
+-- 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 (c) 2016 by Delphix. All rights reserved.
+--
+
+-- Test recursion in LUA. Deep recursion should work because it does
+-- not use the C stack. The LUA stack is is allocated from the kernel's
+-- heap, up to the specified memory limit.
+
+arg = ...
+argv = arg["argv"]
+
+function f (x)
+ if (x == 0) then
+ return x
+ end
+ return f(x-1) + 1
+end
+
+r = f(argv[1])
+return r
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive_neg.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive_neg.ksh
new file mode 100644
index 0000000000..c75048ae7d
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive_neg.ksh
@@ -0,0 +1,24 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+verify_runnable "global"
+
+log_mustnot_checkerror_program "Memory limit exhausted" \
+ $TESTPOOL $ZCP_ROOT/lua_core/tst.recursive.zcp 10000000
+
+log_pass "Nearly-infinite recursive LUA calls fail cleanly."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive_pos.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive_pos.ksh
new file mode 100644
index 0000000000..18d5d0f1ee
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive_pos.ksh
@@ -0,0 +1,23 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+verify_runnable "global"
+
+log_must_program $TESTPOOL $ZCP_ROOT/lua_core/tst.recursive.zcp 10000
+
+log_pass "Deeply recursive LUA calls succeed."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.return_nvlist_neg.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.return_nvlist_neg.ksh
new file mode 100644
index 0000000000..b5626e549d
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.return_nvlist_neg.ksh
@@ -0,0 +1,65 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+verify_runnable "global"
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Try returning various values that lua allows you to construct,
+# but that cannot be represented as nvlists and therefore should
+# cause the script to fail (but not panic). Try sending the values
+# back to userland from both "return" and "error()".
+#
+
+verify_runnable "both"
+
+set -A args 'function() return 1 end' \
+ '{[{}]=true}' \
+ '{[function() return 1 end]=0}' \
+ 'assert' \
+ '0, assert' \
+ 'true, {[{}]=0}' \
+ '{val=true}, {val=false}' \
+ '{1, 2, 3}, {[4]=5}' \
+ 'nil, true, 1, "test", {}, {val=true}' \
+ '{[false]=true, ["false"]=false}' \
+ '{[true]=false, ["true"]=true}' \
+ '{[0]=true, ["0"]=false}' \
+ '{0,0,0,["1"]=0}' \
+ '{0,0,0,["2"]=0}' \
+ '{0,0,0,["3"]=0}'
+
+typeset -i last_index=$((${#args[*]} - 1))
+for i in $(seq 0 $last_index); do
+ log_note "running program: ${args[i]}"
+ log_mustnot_checkerror_program "execution failed" $TESTPOOL - <<-EOF
+ return ${args[i]}
+ EOF
+ ((i = i + 1))
+done
+
+for i in $(seq 0 $last_index); do
+ log_note "running program: ${args[i]}"
+ log_mustnot_checkerror_program "execution failed" $TESTPOOL - <<-EOF
+ error(${args[i]})
+ EOF
+ ((i = i + 1))
+done
+
+log_pass "Returning lua constructs that cannot be converted to " \
+ "nvlists fails as expected."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.return_nvlist_pos.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.return_nvlist_pos.ksh
new file mode 100644
index 0000000000..dce2601132
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.return_nvlist_pos.ksh
@@ -0,0 +1,59 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+verify_runnable "global"
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Try returning various lua values that should be converted
+# to nvlists. Also, try to pass them to error().
+#
+
+verify_runnable "global"
+
+set -A args "" \
+ "nil" \
+ "true" \
+ "1" \
+ "\"test\"" \
+ "{}" \
+ "{val=0}" \
+ "{{1, {2, 3}, {val1={val2=true}}}, {test=\"yes\"}}" \
+ "EINVAL"
+
+log_assert "Returning valid lua constructs works."
+
+typeset -i i=0
+while (( i < ${#args[*]} )); do
+ log_note "running program: return ${args[i]}"
+ log_must_program $TESTPOOL - <<-EOF
+ return ${args[i]}
+ EOF
+ ((i = i + 1))
+done
+
+typeset -i i=0
+while (( i < ${#args[*]} )); do
+ log_note "running program: error(${args[i]})"
+ log_mustnot_checkerror_program "in function 'error'" $TESTPOOL - <<-EOF
+ error(${args[i]})
+ EOF
+ ((i = i + 1))
+done
+
+log_pass "Returning valid lua constructs works."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.return_recursive_table.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.return_recursive_table.ksh
new file mode 100644
index 0000000000..78009dbbe5
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.return_recursive_table.ksh
@@ -0,0 +1,33 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+verify_runnable "global"
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Returning a recursive table should fail gracefully
+#
+
+verify_runnable "both"
+
+log_assert "Returning a recursive table should fail gracefully."
+
+log_mustnot_checkerror_program "Maximum table depth" \
+ $TESTPOOL $ZCP_ROOT/lua_core/tst.return_recursive_table.zcp
+
+log_pass "Returning a recursive table should fail gracefully."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.return_recursive_table.zcp b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.return_recursive_table.zcp
new file mode 100644
index 0000000000..21e6c60d8e
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.return_recursive_table.zcp
@@ -0,0 +1,21 @@
+--
+-- 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 (c) 2016 by Delphix. All rights reserved.
+--
+
+-- This program returns a self-referential data structure.
+
+a = {}
+a["key"] = "val"
+a["self"] = a
+return a
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.timeout.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.timeout.ksh
new file mode 100644
index 0000000000..e735139010
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.timeout.ksh
@@ -0,0 +1,56 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+verify_runnable "global"
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Passing the instruction limit option to channel programs should work
+# correctly. Programs that exceed these instruction limits should fail
+# gracefully.
+#
+
+verify_runnable "both"
+
+log_assert "Timeouts work correctly."
+
+log_mustnot_checkerror_program "Channel program timed out" \
+ $TESTPOOL $ZCP_ROOT/lua_core/tst.timeout.zcp
+
+function test_instr_limit
+{
+ typeset lim=$1
+ instrs_run=$(dtrace -q \
+ -n 'zfs_ioc_channel_program:entry{x=0}' \
+ -n 'zfs_ioc_channel_program:return{printf("%d", x)}' \
+ -n 'zcp_lua_counthook:entry{x+=100}' \
+ -c "zfs program -t $lim $TESTPOOL $ZCP_ROOT/lua_core/tst.timeout.zcp")
+ if [[ $instrs_run -lt $(( $lim - 100 )) ]]; then
+ log_fail "Runtime (${instrs_run} instr) < limit (${lim} - 100 instr)"
+ elif [[ $instrs_run -gt $(( $lim + 100 )) ]]; then
+ log_fail "Runtime (${instrs_run} instr) > limit (${lim} + 100 instr)"
+ fi
+}
+
+test_instr_limit 1000
+test_instr_limit 10000
+test_instr_limit 100000
+test_instr_limit 1000000
+test_instr_limit 2000000
+
+log_pass "Timeouts work correctly."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.timeout.zcp b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.timeout.zcp
new file mode 100644
index 0000000000..d74b1a73c2
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/lua_core/tst.timeout.zcp
@@ -0,0 +1,22 @@
+--
+-- 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 (c) 2016 by Delphix. All rights reserved.
+--
+
+-- This program runs forever (until timed out).
+
+i = 1;
+while true do
+ i = i + 1
+end;
+return i
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/Makefile b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/Makefile
new file mode 100644
index 0000000000..2034d39599
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/Makefile
@@ -0,0 +1,45 @@
+#
+# 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 (c) 2016 by Delphix. All rights reserved.
+#
+
+include $(SRC)/Makefile.master
+
+ROOTOPTPKG = $(ROOT)/opt/zfs-tests
+TESTDIR = $(ROOTOPTPKG)/tests/functional/channel_program/synctask_core
+
+KSHFILES :sh= ls *.ksh
+PROGS = $(KSHFILES:.ksh=)
+FILES :sh= ls *.zcp *.out *.err 2>/dev/null; true
+
+INSTPROGS = $(PROGS:%=$(TESTDIR)/%)
+INSTFILES = $(FILES:%=$(TESTDIR)/%)
+
+$(INSTPROGS) := FILEMODE = 0555
+$(INSTFILES) := FILEMODE = 0444
+
+all lint clean clobber:
+
+install: $(INSTPROGS) $(INSTFILES)
+
+$(INSTPROGS): $(TESTDIR)
+$(INSTFILES): $(TESTDIR)
+
+$(TESTDIR):
+ $(INS.dir)
+
+$(TESTDIR)/%: %.ksh
+ $(INS.rename)
+
+$(TESTDIR)/%: %
+ $(INS.file)
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/cleanup.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/cleanup.ksh
new file mode 100644
index 0000000000..f442da2236
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/cleanup.ksh
@@ -0,0 +1,19 @@
+#!/usr/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/setup.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/setup.ksh
new file mode 100644
index 0000000000..171fd40e41
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/setup.ksh
@@ -0,0 +1,21 @@
+#!/usr/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup ${DISK}
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.destroy_fs.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.destroy_fs.ksh
new file mode 100644
index 0000000000..c9a2e64b7b
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.destroy_fs.ksh
@@ -0,0 +1,45 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+verify_runnable "global"
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+fs=$TESTPOOL/$TESTFS/testchild
+
+function cleanup
+{
+ datasetexists $fs && log_must zfs destroy $fs
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+log_must zfs unmount $fs
+
+log_must datasetexists $fs
+
+log_must_program $TESTPOOL - $fs <<-EOF
+ arg = ...
+ fs = arg["argv"][1]
+ err = zfs.sync.destroy(fs)
+ msg = "destroying " .. fs .. " err=" .. err
+ return msg
+EOF
+
+log_mustnot datasetexists $fs
+
+log_pass "Destroying filesystem with channel program works."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.destroy_snap.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.destroy_snap.ksh
new file mode 100644
index 0000000000..d74b47a1dc
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.destroy_snap.ksh
@@ -0,0 +1,44 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+verify_runnable "global"
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+snap=$TESTPOOL/$TESTFS@$TESTSNAP
+
+function cleanup
+{
+ datasetexists $snap && log_must zfs destroy $snap
+}
+
+log_onexit cleanup
+
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP
+
+log_must snapexists $snap
+
+log_must_program $TESTPOOL - $snap <<-EOF
+ arg = ...
+ snap = arg["argv"][1]
+ err = zfs.sync.destroy(snap)
+ msg = "destroying " .. snap .. " err=" .. err
+ return msg
+EOF
+
+log_mustnot snapexists $snap
+
+log_pass "Destroying snapshot with channel program works."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_count_and_limit.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_count_and_limit.ksh
new file mode 100644
index 0000000000..eb559103be
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_count_and_limit.ksh
@@ -0,0 +1,89 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+
+#
+# DESCRIPTION:
+# Getting filesystem and snapshot count/limit props should work correctly.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/testchild
+snap=$fs@$TESTSNAP
+
+function cleanup
+{
+ datasetexists $fs && log_must zfs destroy -R $fs
+ log_must rm -rf $fs/foo
+ log_must rm -rf $fs/bar
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+log_must zfs create $fs/foo
+create_snapshot $fs $TESTSNAP
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, src = zfs.get_prop("$fs", "snapshot_limit")
+ assert(ans == -1)
+ assert(src == 'default')
+
+ ans, src = zfs.get_prop("$fs", "snapshot_count")
+ assert(ans == nil)
+ assert(src == nil)
+EOF
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, src = zfs.get_prop("$fs", "filesystem_limit")
+ assert(ans == -1)
+ assert(src == 'default')
+
+ ans, src = zfs.get_prop("$fs", "filesystem_count")
+ assert(ans == nil)
+ assert(src == nil)
+EOF
+
+log_must zfs set snapshot_limit=10 $fs
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, src = zfs.get_prop("$fs", "snapshot_limit")
+ assert(ans == 10)
+ assert(src == '$fs')
+
+ ans, src = zfs.get_prop("$fs", "snapshot_count")
+ assert(ans == 1)
+ assert(src == nil)
+EOF
+
+log_must zfs set filesystem_limit=8 $fs
+
+log_must zfs create $fs/bar
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, src = zfs.get_prop("$fs", "filesystem_limit")
+ assert(ans == 8)
+ assert(src == '$fs')
+
+ ans, src = zfs.get_prop("$fs", "filesystem_count")
+ assert(ans == 2)
+ assert(src == nil)
+EOF
+
+log_pass "Getting filesystem and snapshot count/limit props should work correctly."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.ksh
new file mode 100644
index 0000000000..5fbe18e48b
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.ksh
@@ -0,0 +1,40 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Getting index props should work correctly.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+snap=$fs@$TESTSNAP
+function cleanup
+{
+ datasetexists $fs && log_must zfs destroy -R $fs
+}
+
+log_onexit cleanup
+
+log_must zfs create -o version=5 $fs
+create_snapshot $fs $TESTSNAP
+
+log_must_program $TESTPOOL $ZCP_ROOT/synctask_core/tst.get_index_props.zcp $fs $snap
+
+log_pass "Getting index props should work correctly."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.out b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.out
new file mode 100644
index 0000000000..40c58b4b3a
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.out
@@ -0,0 +1,4 @@
+Channel program fully executed with return value:
+ return:
+ 1:
+ 2:
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.zcp b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.zcp
new file mode 100644
index 0000000000..64105cd9b2
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.zcp
@@ -0,0 +1,65 @@
+--
+-- 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 (c) 2016 by Delphix. All rights reserved.
+--
+
+arg = ...
+fs = arg["argv"][1]
+snap = arg["argv"][2]
+
+props = {}
+
+-- prop filesystem snapshot
+props['redundant_metadata'] = {{'all', 'default'}, {nil, nil}}
+props['sync'] = {{'standard', 'default'}, {nil, nil}}
+props['checksum'] = {{'on', 'default'}, {nil, nil}}
+props['dedup'] = {{'off', 'default'}, {nil, nil}}
+props['compression'] = {{'off', 'default'}, {nil, nil}}
+props['snapdir'] = {{'hidden', 'default'}, {nil, nil}}
+props['aclmode'] = {{'discard', 'default'}, {nil, nil}}
+props['aclinherit'] = {{'restricted','default'}, {nil, nil}}
+props['copies'] = {{'1', 'default'}, {nil, nil}}
+props['primarycache'] = {{'all', 'default'}, {'all', 'default'}}
+props['secondarycache'] = {{'all', 'default'}, {'all', 'default'}}
+props['logbias'] = {{'latency', 'default'}, {nil, nil}}
+props['atime'] = {{'on', 'default'}, {nil, nil}}
+props['devices'] = {{'on', 'default'}, {'on', 'default'}}
+props['exec'] = {{'on', 'default'}, {'on', 'default'}}
+props['setuid'] = {{'on', 'default'}, {'on', 'default'}}
+props['readonly'] = {{'off', 'default'}, {nil, nil}}
+props['zoned'] = {{'off', 'default'}, {nil, nil}}
+props['vscan'] = {{'off', 'default'}, {nil, nil}}
+props['nbmand'] = {{'off', 'default'}, {'off', 'default'}}
+props['version'] = {{'5', nil}, {'5', nil}}
+props['canmount'] = {{'on', 'default'}, {nil, nil}}
+props['mounted'] = {{nil, nil}, {nil, nil}}
+props['defer_destroy'] = {{nil, nil}, {'off', nil}}
+props['normalization'] = {{'none', nil}, {'none', nil}}
+props['casesensitivity'] = {{'sensitive', nil}, {'sensitive', nil}}
+props['utf8only'] = {{'off', nil}, {'off', nil}}
+
+fs_fails = {}
+snap_fails = {}
+for prop, expected in pairs(props) do
+ ans, src = zfs.get_prop(fs, prop)
+ if ((ans ~= expected[1][1]) or (src ~= expected[1][2])) then
+ fs_fails[prop] = {ans, src}
+ end
+
+ ans, src = zfs.get_prop(snap, prop)
+ if ((ans ~= expected[2][1]) or (src ~= expected[2][2])) then
+ snap_fails[prop] = {ans, src}
+ end
+end
+
+return {fs_fails, snap_fails}
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_mountpoint.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_mountpoint.ksh
new file mode 100644
index 0000000000..77555a7e03
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_mountpoint.ksh
@@ -0,0 +1,88 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Getting dataset mountpoint should work correctly.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/testmount
+snap=$fs@$TESTSNAP
+clone=$TESTPOOL/$TESTCLONE
+mnt1=/$fs/mnt1
+mnt2=/$fs/mnt2
+
+function cleanup
+{
+ datasetexists $clone && log_must zfs destroy $clone
+ datasetexists $fs && log_must zfs destroy -R $fs
+ log_must rm -rf $mnt1
+ log_must rm -rf $mnt2
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+create_snapshot $fs $TESTSNAP
+create_clone $snap $clone
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, src = zfs.get_prop("$fs", "mountpoint")
+ assert(ans == '/$fs')
+ assert(src == 'default')
+EOF
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, src = zfs.get_prop("$snap", "mountpoint")
+ assert(ans == nil)
+ assert(src == nil)
+EOF
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, src = zfs.get_prop("$clone", "mountpoint")
+ assert(ans == '/$clone')
+ assert(src == 'default')
+EOF
+
+log_must mkdir $mnt1
+log_must mkdir $mnt2
+
+log_must zfs set mountpoint=$mnt1 $fs
+log_must zfs set mountpoint=$mnt2 $clone
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, src = zfs.get_prop("$fs", "mountpoint")
+ assert(ans == '$mnt1')
+ assert(src == '$fs')
+EOF
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, src = zfs.get_prop("$snap", "mountpoint")
+ assert(ans == nil)
+ assert(src == nil)
+EOF
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, src = zfs.get_prop("$clone", "mountpoint")
+ assert(ans == '$mnt2')
+ assert(src == '$clone')
+EOF
+
+log_pass "Getting dataset mountpoint should work correctly."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_neg.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_neg.ksh
new file mode 100644
index 0000000000..b1a7b8ac82
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_neg.ksh
@@ -0,0 +1,43 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Getting failures should work correctly.
+#
+
+verify_runnable "global"
+fs=$TESTPOOL/$TESTFS/testchild
+function cleanup
+{
+ datasetexists $fs && log_must zfs destroy $fs
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+
+log_mustnot_program $TESTPOOL - <<-EOF
+ ans, setpoint = zfs.get_prop("$fs", "notaprop")
+EOF
+
+log_mustnot_program $TESTPOOL - <<-EOF
+ ans, setpoint = zfs.get_prop("notadataset", "type")
+EOF
+
+log_pass "Getting failures should work correctly."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.ksh
new file mode 100644
index 0000000000..a78873114e
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.ksh
@@ -0,0 +1,52 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Getting number props should work correctly on filesystems,
+# snapshots and volumes.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+snap=$fs@$TESTSNAP
+vol=$TESTPOOL/$TESTVOL
+
+function cleanup
+{
+ datasetexists $fs && log_must zfs destroy -R $fs
+ datasetexists $vol && log_must zfs destroy $vol
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+create_snapshot $fs $TESTSNAP
+log_must zfs create -V $VOLSIZE $TESTPOOL/$TESTVOL
+
+#
+# Set snapshot_limit and filesystem_limit for the filesystem so that the
+# snapshot_count and filesystem_count properties return a value.
+#
+log_must zfs set snapshot_limit=10 filesystem_limit=10 $fs
+log_must zfs set snapshot_limit=10 $vol
+
+log_must_program $TESTPOOL $ZCP_ROOT/synctask_core/tst.get_number_props.zcp $fs $snap $vol
+
+log_pass "Getting number props should work correctly."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.out b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.out
new file mode 100644
index 0000000000..be68500097
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.out
@@ -0,0 +1,5 @@
+Channel program fully executed with return value:
+ return:
+ 1:
+ 2:
+ 3:
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.zcp b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.zcp
new file mode 100644
index 0000000000..6bf23bbb89
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.zcp
@@ -0,0 +1,100 @@
+--
+-- 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 (c) 2016 by Delphix. All rights reserved.
+--
+
+arg = ...
+fs = arg["argv"][1]
+snap = arg["argv"][2]
+vol = arg["argv"][3]
+
+props = {}
+
+-- The values indicate whether or not a property should be returned,
+-- not the value of the property. A better approach might be to compare
+-- their values to the output of 'zfs get <prop>'
+
+-- prop filesystem snapshot volume
+props['used'] = {{true, nil}, {true, nil}, {true, nil}}
+props['available'] = {{true, nil}, {nil, nil}, {true, nil}}
+props['referenced'] = {{true, nil}, {true, nil}, {true, nil}}
+props['compressratio'] = {{true, nil}, {true, nil}, {true, nil}}
+props['refcompressratio'] = {{true, nil}, {true, nil}, {true, nil}}
+props['volblocksize'] = {{nil, nil}, {nil, nil}, {true, nil}}
+props['usedbysnapshots'] = {{true, nil}, {nil, nil}, {true, nil}}
+props['usedbydataset'] = {{true, nil}, {nil, nil}, {true, nil}}
+props['usedbychildren'] = {{true, nil}, {nil, nil}, {true, nil}}
+props['usedbyrefreservation'] = {{true, nil}, {nil, nil}, {true, nil}}
+props['userrefs'] = {{nil, nil}, {true, nil}, {nil, nil}}
+props['written'] = {{true, nil}, {true, nil}, {true, nil}}
+props['logicalused'] = {{true, nil}, {nil, nil}, {true, nil}}
+props['logicalreferenced'] = {{true, nil}, {true, nil}, {true, nil}}
+props['quota'] = {{true, 'default'}, {nil, nil}, {nil, nil}}
+props['reservation'] = {{true, 'default'}, {nil, nil}, {true, 'default'}}
+props['volsize'] = {{nil, nil}, {nil, nil}, {true, vol}}
+props['refquota'] = {{true, 'default'}, {nil, nil}, {nil, nil}}
+props['refreservation'] = {{true, 'default'}, {nil, nil}, {true, vol}}
+props['filesystem_limit'] = {{true, fs}, {nil, nil}, {nil, nil}}
+props['snapshot_limit'] = {{true, fs}, {nil, nil}, {true, vol}}
+props['filesystem_count'] = {{true, nil}, {nil, nil}, {nil, nil}}
+props['snapshot_count'] = {{true, nil}, {nil, nil}, {true, nil}}
+props['recordsize'] = {{true, 'default'}, {nil, nil}, {nil, nil}}
+props['creation'] = {{true, nil}, {true, nil}, {true, nil}}
+-- hidden props
+props['createtxg'] = {{true, nil}, {true, nil}, {true, nil}}
+props['numclones'] = {{nil, nil}, {true, nil}, {nil, nil}}
+props['guid'] = {{true, nil}, {true, nil}, {true, nil}}
+props['useraccounting'] = {{true, nil}, {true, nil}, {true, nil}}
+props['unique'] = {{true, nil}, {true, nil}, {true, nil}}
+props['objsetid'] = {{true, nil}, {true, nil}, {true, nil}}
+props['inconsistent'] = {{true, nil}, {true, nil}, {true, nil}}
+
+
+fs_fails = {}
+snap_fails = {}
+vol_fails = {}
+
+function match(n, ans, src, expected)
+ if ((expected[n][1] == nil) and (ans ~= nil)) then
+ return false
+ end
+
+ if ((expected[n][1] == true) and (ans == nil)) then
+ return false
+ end
+
+ if (expected[n][2] ~= src) then
+ return false
+ end
+
+ return true
+end
+
+for prop, expected in pairs(props) do
+ ans, src = zfs.get_prop(fs, prop)
+ if not (match(1, ans, src, expected)) then
+ fs_fails[prop] = {ans, src}
+ end
+
+ ans, src = zfs.get_prop(snap, prop)
+ if not (match(2, ans, src, expected)) then
+ snap_fails[prop] = {ans, src}
+ end
+
+ ans, src = zfs.get_prop(vol, prop)
+ if not (match(3, ans, src, expected)) then
+ vol_fails[prop] = {ans, src}
+ end
+end
+
+return {fs_fails, snap_fails, vol_fails}
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.ksh
new file mode 100644
index 0000000000..b7d784489a
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.ksh
@@ -0,0 +1,45 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Getting string props should work correctly.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/testchild
+snap=$fs@$TESTSNAP
+clone=$TESTPOOL/$TESTCLONE
+
+
+function cleanup
+{
+ datasetexists $clone && log_must zfs destroy $clone
+ datasetexists $fs && log_must zfs destroy -R $fs
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+create_snapshot $fs $TESTSNAP
+create_clone $snap $clone
+
+log_must_program $TESTPOOL $ZCP_ROOT/synctask_core/tst.get_string_props.zcp $fs $snap $clone
+
+log_pass "Getting string props should work correctly."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.out b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.out
new file mode 100644
index 0000000000..be68500097
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.out
@@ -0,0 +1,5 @@
+Channel program fully executed with return value:
+ return:
+ 1:
+ 2:
+ 3:
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.zcp b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.zcp
new file mode 100644
index 0000000000..899bdc0336
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.zcp
@@ -0,0 +1,73 @@
+--
+-- 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 (c) 2016 by Delphix. All rights reserved.
+--
+
+arg = ...
+fs = arg["argv"][1]
+snap = arg["argv"][2]
+clone = arg["argv"][3]
+
+props = {}
+
+-- prop filesystem snapshot clone
+props['origin'] = {{nil, nil}, {nil, nil}, {snap, nil}}
+props['clones'] = {{nil, nil}, {{clone}, nil}, {nil, nil}}
+props['mountpoint'] = {{'/' .. fs, 'default'}, {nil, nil}, {'/' .. clone, 'default'}}
+props['sharenfs'] = {{'off', 'default'}, {nil, nil}, {'off', 'default'}}
+props['type'] = {{'filesystem', nil}, {'snapshot', nil}, {'filesystem', nil}}
+props['sharesmb'] = {{'off', 'default'}, {nil, nil}, {'off', 'default'}}
+props['mlslabel'] = {{'none', 'default'}, {'none', 'default'}, {'none', 'default'}}
+props['receive_resume_token'] = {{nil, nil}, {nil, nil}, {nil, nil}}
+-- hidden props
+props['name'] = {{fs, nil}, {snap, nil}, {clone, nil}}
+props['iscsioptions'] = {{nil, nil}, {nil, nil}, {nil, nil}}
+props['prevsnap'] = {{snap, nil}, {nil, nil}, {snap, nil}}
+
+
+fs_fails = {}
+snap_fails = {}
+clone_fails = {}
+
+
+function list_match(t1, t2)
+ if t1 == t2 then return true end
+ return (t1[1] == t2[1])
+end
+
+function match(n, prop, ans, src, expected)
+ if ((prop == 'clones') or (prop == 'redact_snaps')) then
+ return (list_match(ans, expected[n][1]) and (src == expected[n][2]))
+ else
+ return ((ans == expected[n][1]) and (src == expected[n][2]))
+ end
+end
+
+for prop, expected in pairs(props) do
+ ans, src = zfs.get_prop(fs, prop)
+ if not (match(1, prop, ans, src, expected)) then
+ fs_fails[prop] = {ans, src}
+ end
+
+ ans, src = zfs.get_prop(snap, prop)
+ if not (match(2, prop, ans, src, expected)) then
+ snap_fails[prop] = {ans, src}
+ end
+
+ ans, src = zfs.get_prop(clone, prop)
+ if not (match(3, prop, ans, src, expected)) then
+ clone_fails[prop] = {ans, src}
+ end
+end
+
+return {fs_fails, snap_fails, clone_fails}
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_type.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_type.ksh
new file mode 100644
index 0000000000..f52eda75a0
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_type.ksh
@@ -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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+
+#
+# DESCRIPTION:
+# Getting type should work correctly.
+#
+
+verify_runnable "global"
+fs=$TESTPOOL/$TESTFS/testchild
+snap=$fs@$TESTSNAP
+vol=$TESTPOOL/$TESTVOL
+function cleanup
+{
+ datasetexists $snap && log_must zfs destroy $snap
+ datasetexists $fs && log_must zfs destroy $fs
+ datasetexists $vol && log_must zfs destroy $vol
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+create_snapshot $fs $TESTSNAP
+log_must zfs create -V $VOLSIZE $vol
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, setpoint = zfs.get_prop("$fs", "type")
+ assert(ans == "filesystem")
+
+ ans, setpoint = zfs.get_prop("$snap", "type")
+ assert(ans == "snapshot")
+
+ ans, setpoint = zfs.get_prop("$vol", "type")
+ assert(ans == "volume")
+EOF
+
+
+log_pass "Getting type should work correctly."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_userquota.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_userquota.ksh
new file mode 100644
index 0000000000..a101544203
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_userquota.ksh
@@ -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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+. $STF_SUITE/tests/functional/userquota/userquota_common.kshlib
+
+#
+# DESCRIPTION:
+# "Getting {user,group}{quota,used}, should work correctly."
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+fs1=$TESTPOOL/$TESTFS/nextchild
+userid='123'
+groupid='456'
+
+function cleanup
+{
+ datasetexists $fs && log_must zfs destroy $fs
+ datasetexists $fs1 && log_must zfs destroy $fs1
+}
+
+log_onexit cleanup
+
+log_must zfs create -o userquota@$userid=$UQUOTA_SIZE \
+ -o groupquota@$groupid=$GQUOTA_SIZE $fs
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, setpoint = zfs.get_prop("$fs", "userquota@$userid")
+ assert(ans == $UQUOTA_SIZE)
+ assert(setpoint == "$fs")
+
+ ans, setpoint = zfs.get_prop("$fs", "userused@$userid")
+ assert(ans == 0)
+ assert(setpoint == "$fs")
+
+ ans, setpoint = zfs.get_prop("$fs", "groupquota@$groupid")
+ assert(ans == $GQUOTA_SIZE)
+ assert(setpoint == "$fs")
+
+ ans, setpoint = zfs.get_prop("$fs", "groupused@$groupid")
+ assert(ans == 0)
+ assert(setpoint == "$fs")
+EOF
+
+log_must zfs create $fs1
+log_must_program $TESTPOOL - <<-EOF
+ ans, setpoint = zfs.get_prop("$fs1", "userquota@$userid")
+ assert(ans == nil)
+ assert(setpoint == nil)
+
+ ans, setpoint = zfs.get_prop("$fs1", "userused@$userid")
+ assert(ans == 0)
+ assert(setpoint == "$fs1")
+
+ ans, setpoint = zfs.get_prop("$fs1", "groupquota@$groupid")
+ assert(ans == nil)
+ assert(setpoint == nil)
+
+ ans, setpoint = zfs.get_prop("$fs1", "groupused@$groupid")
+ assert(ans == 0)
+ assert(setpoint == "$fs1")
+EOF
+
+log_pass "Getting {user,group}{quota,used}, should work correctly."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_written.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_written.ksh
new file mode 100644
index 0000000000..7f94aea246
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_written.ksh
@@ -0,0 +1,57 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+
+#
+# DESCRIPTION:
+# Getting written@ props should work correctly.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/testchild
+snap=$fs@$TESTSNAP
+dir=/$fs/dir
+
+function cleanup
+{
+ datasetexists $fs && log_must zfs destroy -R $fs
+ log_must rm -rf $dir
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+create_snapshot $fs $TESTSNAP
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, setpoint = zfs.get_prop("$fs", "written@$TESTSNAP")
+ assert(ans == 0)
+
+EOF
+
+log_must mkdir $dir
+sync
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, setpoint = zfs.get_prop("$fs", "written@$TESTSNAP")
+ assert(ans > 0)
+
+EOF
+
+log_pass "Getting written@ props should work correctly."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_children.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_children.ksh
new file mode 100644
index 0000000000..2afd2e47d9
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_children.ksh
@@ -0,0 +1,125 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Listing zfs children should work correctly.
+#
+
+verify_runnable "global"
+
+log_assert "Listing zfs children should work correctly."
+
+TESTCHILD=$TESTPOOL/$TESTFS/testchild
+TESTCHILD1=$TESTCHILD-1
+TESTCHILD2=$TESTCHILD-2
+TESTCHILD3=$TESTCHILD-3
+
+function cleanup
+{
+ datasetexists $TESTCHILD && log_must zfs destroy $TESTCHILD
+ datasetexists $TESTCHILD1 && log_must zfs destroy $TESTCHILD1
+ datasetexists $TESTCHILD2 && log_must zfs destroy $TESTCHILD2
+ datasetexists $TESTCHILD3 && log_must zfs destroy $TESTCHILD3
+}
+
+log_onexit cleanup
+
+# 0 children handled correctly
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for s in zfs.list.children("$TESTPOOL/$TESTFS") do
+ n = n + 1
+ end
+ assert(n == 0)
+ return 0
+EOF
+
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for s in zfs.list.children("$TESTPOOL") do
+ assert(s == "$TESTPOOL/$TESTFS")
+ n = n + 1
+ end
+ assert(n == 1)
+ return 0
+EOF
+
+# Create a child fs
+log_must zfs create $TESTCHILD
+
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for s in zfs.list.children("$TESTPOOL/$TESTFS") do
+ assert(s == "$TESTCHILD")
+ n = n + 1
+ end
+ assert(n == 1)
+ return 0
+EOF
+
+log_must zfs create $TESTCHILD1
+log_must zfs create $TESTCHILD2
+log_must zfs create $TESTCHILD3
+
+# All children appear exactly once
+log_must_program $TESTPOOL - <<-EOF
+ a = {}
+ a["$TESTCHILD"] = false
+ a["$TESTCHILD1"] = false
+ a["$TESTCHILD2"] = false
+ a["$TESTCHILD3"] = false
+ n = 0
+ for s in zfs.list.children("$TESTPOOL/$TESTFS") do
+ assert(not a[s])
+ a[s] = true
+ n = n + 1
+ end
+ assert(n == 4)
+ assert(a["$TESTCHILD"] and
+ a["$TESTCHILD1"] and
+ a["$TESTCHILD2"] and
+ a["$TESTCHILD3"])
+ return 0
+EOF
+
+# Bad input
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.children("$TESTPOOL/not-a-fs")
+ return 0
+EOF
+
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.children("not-a-pool/$TESTFS")
+ return 0
+EOF
+
+# Can't look in a different pool than the one specified on command line
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.children("rpool")
+ return 0
+EOF
+
+create_snapshot
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.children("$TESTPOOL/$TESTFS@$TESTSNAP")
+ return 0
+EOF
+destroy_snapshot
+
+log_pass "Listing zfs children should work correctly."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_clones.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_clones.ksh
new file mode 100644
index 0000000000..ef2bd5ac0f
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_clones.ksh
@@ -0,0 +1,117 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Listing zfs clones should work correctly.
+#
+
+verify_runnable "global"
+
+log_assert "Listing zfs clones should work correctly."
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS@$TESTSNAP && \
+ log_must zfs destroy -R $TESTPOOL/$TESTFS@$TESTSNAP
+}
+
+log_onexit cleanup
+
+# Take snapshot to test with ($TESTSNAP)
+create_snapshot
+
+# 0 clones handled correctly
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for s in zfs.list.clones("$TESTPOOL/$TESTFS@$TESTSNAP") do
+ n = n + 1
+ end
+ assert(n == 0)
+ return 0
+EOF
+
+# Create a clone ($TESTCLONE)
+create_clone
+
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for s in zfs.list.clones("$TESTPOOL/$TESTFS@$TESTSNAP") do
+ assert(s == "$TESTPOOL/$TESTCLONE")
+ n = n + 1
+ end
+ assert(n == 1)
+ return 0
+EOF
+
+TESTCLONE1=${TESTCLONE}-1
+TESTCLONE2=${TESTCLONE}-2
+TESTCLONE3=${TESTCLONE}-3
+create_clone $TESTPOOL/$TESTFS@$TESTSNAP $TESTPOOL/$TESTCLONE1
+create_clone $TESTPOOL/$TESTFS@$TESTSNAP $TESTPOOL/$TESTCLONE2
+create_clone $TESTPOOL/$TESTFS@$TESTSNAP $TESTPOOL/$TESTCLONE3
+
+# All clones appear exactly once
+log_must_program $TESTPOOL - <<-EOF
+ a = {}
+ a["$TESTPOOL/$TESTCLONE"] = false
+ a["$TESTPOOL/$TESTCLONE1"] = false
+ a["$TESTPOOL/$TESTCLONE2"] = false
+ a["$TESTPOOL/$TESTCLONE3"] = false
+ n = 0
+ for s in zfs.list.clones("$TESTPOOL/$TESTFS@$TESTSNAP") do
+ assert(not a[s])
+ a[s] = true
+ n = n + 1
+ end
+ assert(n == 4)
+ assert(a["$TESTPOOL/$TESTCLONE"] and
+ a["$TESTPOOL/$TESTCLONE1"] and
+ a["$TESTPOOL/$TESTCLONE2"] and
+ a["$TESTPOOL/$TESTCLONE3"])
+ return 0
+EOF
+
+# Bad input
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.clones("$TESTPOOL/not-a-fs@$TESTSNAP")
+ return 0
+EOF
+
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.clones("$TESTPOOL/$TESTFS@not-a-snap")
+ return 0
+EOF
+
+# Can't look in a different pool than the one specified on command line
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.clones("rpool")
+ return 0
+EOF
+
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.clones("not-a-pool/$TESTFS@$TESTSNAP")
+ return 0
+EOF
+
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.clones("$TESTPOOL/$TESTFS")
+ return 0
+EOF
+
+log_pass "Listing zfs clones should work correctly."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_snapshots.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_snapshots.ksh
new file mode 100644
index 0000000000..8cd78c513a
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_snapshots.ksh
@@ -0,0 +1,116 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Listing zfs snapshots should work correctly.
+#
+
+verify_runnable "global"
+
+log_assert "Listing zfs snapshots should work correctly."
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS@$TESTSNAP && \
+ log_must zfs destroy $TESTPOOL/$TESTFS@$TESTSNAP
+ datasetexists $TESTPOOL/$TESTFS@$TESTSNAP1 && \
+ log_must zfs destroy $TESTPOOL/$TESTFS@$TESTSNAP1
+ datasetexists $TESTPOOL/$TESTFS@$TESTSNAP2 && \
+ log_must zfs destroy $TESTPOOL/$TESTFS@$TESTSNAP2
+ datasetexists $TESTPOOL/$TESTFS@$TESTSNAP3 && \
+ log_must zfs destroy $TESTPOOL/$TESTFS@$TESTSNAP3
+}
+
+log_onexit cleanup
+
+# 0 snapshots handled correctly
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for s in zfs.list.snapshots("$TESTPOOL/$TESTFS") do
+ zfs.debug("ERROR: found snapshot " .. s)
+ n = n + 1
+ end
+ assert(n == 0)
+ return 0
+EOF
+
+# Take a snapshot, make sure it appears
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP
+
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for s in zfs.list.snapshots("$TESTPOOL/$TESTFS") do
+ assert(s == "$TESTPOOL/$TESTFS@$TESTSNAP")
+ n = n + 1
+ end
+ assert(n == 1)
+ return 0
+EOF
+
+TESTSNAP1=${TESTSNAP}-1
+TESTSNAP2=${TESTSNAP}-2
+TESTSNAP3=${TESTSNAP}-3
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP1
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP2
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP3
+
+# All snapshots appear exactly once
+log_must_program $TESTPOOL - <<-EOF
+ a = {}
+ a["$TESTPOOL/$TESTFS@$TESTSNAP"] = false
+ a["$TESTPOOL/$TESTFS@$TESTSNAP1"] = false
+ a["$TESTPOOL/$TESTFS@$TESTSNAP2"] = false
+ a["$TESTPOOL/$TESTFS@$TESTSNAP3"] = false
+ n = 0
+ for s in zfs.list.snapshots("$TESTPOOL/$TESTFS") do
+ assert(not a[s])
+ a[s] = true
+ n = n + 1
+ end
+ assert(n == 4)
+ assert(a["$TESTPOOL/$TESTFS@$TESTSNAP"] and
+ a["$TESTPOOL/$TESTFS@$TESTSNAP1"] and
+ a["$TESTPOOL/$TESTFS@$TESTSNAP2"] and
+ a["$TESTPOOL/$TESTFS@$TESTSNAP3"])
+ return 0
+EOF
+
+# Bad input
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.snapshots("$TESTPOOL/not-a-fs")
+ return 0
+EOF
+
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.snapshots("not-a-pool/$TESTFS")
+ return 0
+EOF
+
+# Can't look in a different pool than the one specified on command line
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.snapshots("rpool")
+ return 0
+EOF
+
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.snapshots("$TESTPOOL/${TESTFS}@$TESTSNAP")
+ return 0
+EOF
+
+log_pass "Listing zfs snapshots should work correctly."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_system_props.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_system_props.ksh
new file mode 100644
index 0000000000..cc0be6d908
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_system_props.ksh
@@ -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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+
+#
+# DESCRIPTION:
+# Listing system properties should succeed
+#
+
+verify_runnable "global"
+fs=$TESTPOOL/$TESTFS/testchild
+snap=$fs@$TESTSNAP
+vol=$TESTPOOL/$TESTVOL
+function cleanup
+{
+ datasetexists $snap && log_must zfs destroy $snap
+ datasetexists $fs && log_must zfs destroy $fs
+ datasetexists $vol && log_must zfs destroy $vol
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+create_snapshot $fs $TESTSNAP
+log_must zfs create -V $VOLSIZE $vol
+
+log_must_program $TESTPOOL - <<-EOF
+ zfs.list.system_properties("$fs")
+EOF
+
+log_must_program $TESTPOOL - <<-EOF
+ zfs.list.system_properties("$snap")
+EOF
+
+log_must_program $TESTPOOL - <<-EOF
+ zfs.list.system_properties("$vol")
+EOF
+
+log_pass "Listing system properties should succeed."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.parse_args_neg.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.parse_args_neg.ksh
new file mode 100644
index 0000000000..8c57bef4b0
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.parse_args_neg.ksh
@@ -0,0 +1,48 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Try calling zfs.sync.destroy with various arguments that are not
+# valid. The script should fail.
+#
+
+verify_runnable "global"
+
+set -A progs "zfs.sync.destroy(\"foo\", \"bar\")" \
+ "zfs.sync.destroy(\"foo\", 12345)" \
+ "zfs.sync.destroy(12345)" \
+ "zfs.sync.destroy()" \
+ "zfs.sync.destroy{\"foo\", bar=true}" \
+ "zfs.sync.destroy{\"foo\", defer=12345}" \
+ "zfs.sync.destroy{\"foo\", defer=true, 12345}" \
+ "zfs.sync.destroy{\"foo\", defer=true, bar=12345}" \
+ "zfs.sync.destroy{\"foo\", bar=true, defer=true}" \
+ "zfs.sync.destroy{defer=true}" \
+ "zfs.sync.destroy{12345, defer=true}"
+
+
+typeset -i i=0
+while (( i < ${#progs[*]} )); do
+ log_note "running program: ${progs[i]}"
+ # output should contain the usage message, which starts with "destroy{"
+ echo ${progs[i]} | log_mustnot_checkerror_program "destroy{" $TESTPOOL -
+ ((i = i + 1))
+done
+
+log_pass "Invalid arguments to zfs.sync.destroy generate errors."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_conflict.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_conflict.ksh
new file mode 100644
index 0000000000..d5d377b771
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_conflict.ksh
@@ -0,0 +1,55 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Attempting to promote a clone when it shares a snapshot name with
+# its parent filesystem should fail and return the name of the
+# conflicting snapshot.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+clone=$TESTPOOL/$TESTFS/testchild_clone
+snap=promote_conflict_snap
+
+function cleanup
+{
+ for to_destroy in $fs $clone; do
+ datasetexists $to_destroy && log_must zfs destroy -R $to_destroy
+ done
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+log_must zfs snapshot $fs@$snap
+log_must zfs clone $fs@$snap $clone
+log_must zfs snapshot $clone@$snap
+
+#
+# This channel program is expected to return successfully, but fail to execute
+# the promote command since the snapshot names collide. It returns the error
+# code and description, which should be EEXIST (17) and the name of the
+# conflicting snapshot.
+#
+log_must_program $TESTPOOL \
+ $ZCP_ROOT/synctask_core/tst.promote_conflict.zcp $clone
+
+log_pass "Promoting a clone with a conflicting snapshot fails."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_conflict.zcp b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_conflict.zcp
new file mode 100644
index 0000000000..287328a40d
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_conflict.zcp
@@ -0,0 +1,23 @@
+--
+-- 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 (c) 2016 by Delphix. All rights reserved.
+--
+
+-- This program should be invoked as "zfs program <pool> <prog> <clone>"
+
+args = ...
+argv = args["argv"]
+err, desc = zfs.sync.promote(argv[1])
+assert(err == EEXIST)
+assert(#desc == 1)
+assert(desc[1] == "promote_conflict_snap")
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_multiple.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_multiple.ksh
new file mode 100644
index 0000000000..13ed119ece
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_multiple.ksh
@@ -0,0 +1,71 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Multiple interacting promotions in a single txg should succeed.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+clone1=$TESTPOOL/$TESTFS/testchild_clone1
+clone2=$TESTPOOL/$TESTFS/testchild_clone2
+snap1=$fs@testchild_snap1
+snap2=$clone1@testchild_snap2
+
+function cleanup
+{
+ for to_destroy in $fs $clone1 $clone2; do
+ datasetexists $to_destroy && log_must zfs destroy -R $to_destroy
+ done
+}
+
+log_onexit cleanup
+
+#
+# Create a chain of clones and snapshots:
+#
+# snap1 -----------> fs
+# \--> snap2 --> clone1
+# \---> clone2
+#
+# Then promote clone2 twice, resulting in:
+#
+# snap1 --> snap2 --> clone2
+# \ \---> clone1
+# \------------> fs
+#
+# We then attempt to destroy clone1, which should succeed since it no
+# longer has any dependents.
+#
+log_must zfs create $fs
+log_must zfs snapshot $snap1
+log_must zfs clone $snap1 $clone1
+log_must zfs snapshot $snap2
+log_must zfs clone $snap2 $clone2
+
+log_must zfs unmount -f $clone1
+
+log_must_program $TESTPOOL - <<-EOF
+ assert(zfs.sync.promote("$clone2") == 0)
+ assert(zfs.sync.promote("$clone2") == 0)
+ assert(zfs.sync.destroy("$clone1") == 0)
+EOF
+
+log_pass "Multiple promotes and destroying a demoted fs in one txg works."
diff --git a/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_simple.ksh b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_simple.ksh
new file mode 100644
index 0000000000..4d1ac5974a
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_simple.ksh
@@ -0,0 +1,47 @@
+#!/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Promoting a clone should work correctly.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+clone=$TESTPOOL/$TESTFS/testchild_clone
+snap=$fs@$TESTSNAP
+
+function cleanup
+{
+ for to_destroy in $fs $clone; do
+ datasetexists $to_destroy && log_must zfs destroy -R $to_destroy
+ done
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+log_must zfs snapshot $snap
+log_must zfs clone $snap $clone
+
+log_must_program $TESTPOOL - <<-EOF
+ assert(zfs.sync.promote("$clone") == 0)
+EOF
+
+log_pass "Promoting a clone with a channel program works."
diff --git a/usr/src/test/zfs-tests/tests/functional/cli_user/misc/zfs_channel_001_neg.ksh b/usr/src/test/zfs-tests/tests/functional/cli_user/misc/zfs_channel_001_neg.ksh
new file mode 100644
index 0000000000..242860502b
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/cli_user/misc/zfs_channel_001_neg.ksh
@@ -0,0 +1,45 @@
+#!/usr/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# zfs program returns an error when run as a user
+#
+# STRATEGY:
+# 1. Attempt to start a channel program on a pool
+# 2. Verify the command fails
+#
+
+verify_runnable "global"
+
+
+log_mustnot eval "echo return 0 | zfs program $TESTPOOL -"
+
+log_pass "zfs program returns an error when run as a user"