[v3,2/2] shared/012: Add tests for filename casefolding feature
diff mbox series

Message ID 20190610173541.20511-2-krisman@collabora.com
State New
Headers show
Series
  • [v3,1/2] common/casefold: Add infrastructure to test filename casefold feature
Related show

Commit Message

Gabriel Krisman Bertazi June 10, 2019, 5:35 p.m. UTC
From: "Lakshmipathi.G" <lakshmipathi.ganapathi@collabora.co.uk>

This new test implements verification for the per-directory
case-insensitive feature, as supported by the reference implementation
in Ext4.

Signed-off-by: Lakshmipathi.G <lakshmipathi.ganapathi@collabora.co.uk>
Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.com>
  [Rewrite to support feature design]
  [Refactor to simplify implementation]
---
 tests/shared/012     | 508 +++++++++++++++++++++++++++++++++++++++++++
 tests/shared/012.out |  16 ++
 tests/shared/group   |   1 +
 3 files changed, 525 insertions(+)
 create mode 100755 tests/shared/012
 create mode 100644 tests/shared/012.out

Comments

Theodore Y. Ts'o June 11, 2019, 12:15 p.m. UTC | #1
On Mon, Jun 10, 2019 at 01:35:41PM -0400, Gabriel Krisman Bertazi wrote:
> From: "Lakshmipathi.G" <lakshmipathi.ganapathi@collabora.co.uk>
> 
> This new test implements verification for the per-directory
> case-insensitive feature, as supported by the reference implementation
> in Ext4.
> 
> Signed-off-by: Lakshmipathi.G <lakshmipathi.ganapathi@collabora.co.uk>
> Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.com>
>   [Rewrite to support feature design]
>   [Refactor to simplify implementation]

I tried out this test, and it's apparently failing for me using
e2fsprogs 1.45.2; it looks like it's a whitespace issue?

shared/012		[08:14:07][  146.388509] run fstests shared/012 at 2019-06-11 08:14:07
 [08:14:08]- output mismatch (see /results/ext4/results-4k/shared/012.out.bad)
    --- tests/shared/012.out	2019-06-10 00:02:54.000000000 -0400
    +++ /results/ext4/results-4k/shared/012.out.bad	2019-06-11 08:14:08.487418272 -0400
    @@ -1,8 +1,8 @@
     QA output created by 012
    -SCRATCH_MNT/basic           Extents, Casefold
    -SCRATCH_MNT/basic           Extents
    -SCRATCH_MNT/casefold_flag_removal Extents, Casefold
    -SCRATCH_MNT/casefold_flag_removal Extents, Casefold
    +SCRATCH_MNT/basic                   Extents, Casefold
    +SCRATCH_MNT/basic                   Extents
    ...
    (Run 'diff -u /root/xfstests/tests/shared/012.out /results/ext4/results-4k/shared/012.out.bad'  to see the entire diff)
Ran: shared/012
Failures: shared/012
Failed 1 of 1 tests
Xunit report: /results/ext4/results-4k/result.xml

root@kvm-xfstests:~# diff -u /root/xfstests/tests/shared/012.out /results/ext4/results-4k/shared/012.out.bad
--- /root/xfstests/tests/shared/012.out	2019-06-10 00:02:54.000000000 -0400
+++ /results/ext4/results-4k/shared/012.out.bad	2019-06-11 08:14:08.487418272 -0400
@@ -1,8 +1,8 @@
 QA output created by 012
-SCRATCH_MNT/basic           Extents, Casefold
-SCRATCH_MNT/basic           Extents
-SCRATCH_MNT/casefold_flag_removal Extents, Casefold
-SCRATCH_MNT/casefold_flag_removal Extents, Casefold
+SCRATCH_MNT/basic                   Extents, Casefold
+SCRATCH_MNT/basic                   Extents
+SCRATCH_MNT/casefold_flag_removal   Extents, Casefold
+SCRATCH_MNT/casefold_flag_removal   Extents, Casefold
 SCRATCH_MNT/flag_inheritance/d1/d2/d3 Extents, Casefold
 SCRATCH_MNT/symlink/ind1/TARGET
 mv: cannot stat 'SCRATCH_MNT/rename/rename': No such file or directory
Gabriel Krisman Bertazi June 12, 2019, 5:01 a.m. UTC | #2
"Theodore Ts'o" <tytso@mit.edu> writes:

> On Mon, Jun 10, 2019 at 01:35:41PM -0400, Gabriel Krisman Bertazi wrote:
>> From: "Lakshmipathi.G" <lakshmipathi.ganapathi@collabora.co.uk>
>> 
>> This new test implements verification for the per-directory
>> case-insensitive feature, as supported by the reference implementation
>> in Ext4.
>> 
>> Signed-off-by: Lakshmipathi.G <lakshmipathi.ganapathi@collabora.co.uk>
>> Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.com>
>>   [Rewrite to support feature design]
>>   [Refactor to simplify implementation]
>
> I tried out this test, and it's apparently failing for me using
> e2fsprogs 1.45.2; it looks like it's a whitespace issue?

Hi Ted,

Yes, definitely just whitespace.  But i don't understand why you are
getting this behavior.  I tried both with the master branch of e2fsprogs
and the tagged commit of v1.45.2 and on both occasions the test succeed
in my system.  For sure I can use filter_spaces but I'm puzzled why I
can't reproduce this.

>
> shared/012		[08:14:07][  146.388509] run fstests shared/012 at 2019-06-11 08:14:07
>  [08:14:08]- output mismatch (see /results/ext4/results-4k/shared/012.out.bad)
>     --- tests/shared/012.out	2019-06-10 00:02:54.000000000 -0400
>     +++ /results/ext4/results-4k/shared/012.out.bad	2019-06-11 08:14:08.487418272 -0400
>     @@ -1,8 +1,8 @@
>      QA output created by 012
>     -SCRATCH_MNT/basic           Extents, Casefold
>     -SCRATCH_MNT/basic           Extents
>     -SCRATCH_MNT/casefold_flag_removal Extents, Casefold
>     -SCRATCH_MNT/casefold_flag_removal Extents, Casefold
>     +SCRATCH_MNT/basic                   Extents, Casefold
>     +SCRATCH_MNT/basic                   Extents
>     ...
>     (Run 'diff -u /root/xfstests/tests/shared/012.out /results/ext4/results-4k/shared/012.out.bad'  to see the entire diff)
> Ran: shared/012
> Failures: shared/012
> Failed 1 of 1 tests
> Xunit report: /results/ext4/results-4k/result.xml
>
> root@kvm-xfstests:~# diff -u /root/xfstests/tests/shared/012.out /results/ext4/results-4k/shared/012.out.bad
> --- /root/xfstests/tests/shared/012.out	2019-06-10 00:02:54.000000000 -0400
> +++ /results/ext4/results-4k/shared/012.out.bad	2019-06-11 08:14:08.487418272 -0400
> @@ -1,8 +1,8 @@
>  QA output created by 012
> -SCRATCH_MNT/basic           Extents, Casefold
> -SCRATCH_MNT/basic           Extents
> -SCRATCH_MNT/casefold_flag_removal Extents, Casefold
> -SCRATCH_MNT/casefold_flag_removal Extents, Casefold
> +SCRATCH_MNT/basic                   Extents, Casefold
> +SCRATCH_MNT/basic                   Extents
> +SCRATCH_MNT/casefold_flag_removal   Extents, Casefold
> +SCRATCH_MNT/casefold_flag_removal   Extents, Casefold
>  SCRATCH_MNT/flag_inheritance/d1/d2/d3 Extents, Casefold
>  SCRATCH_MNT/symlink/ind1/TARGET
>  mv: cannot stat 'SCRATCH_MNT/rename/rename': No such file or directory
Theodore Y. Ts'o June 12, 2019, 12:32 p.m. UTC | #3
On Wed, Jun 12, 2019 at 01:01:46AM -0400, Gabriel Krisman Bertazi wrote:
> > I tried out this test, and it's apparently failing for me using
> > e2fsprogs 1.45.2; it looks like it's a whitespace issue?
> 
> Hi Ted,
> 
> Yes, definitely just whitespace.  But i don't understand why you are
> getting this behavior.  I tried both with the master branch of e2fsprogs
> and the tagged commit of v1.45.2 and on both occasions the test succeed
> in my system.  For sure I can use filter_spaces but I'm puzzled why I
> can't reproduce this.

That's wierd.  The kvm-xfstests appliance VM that's uploaded to

https://mirrors.edge.kernel.org/pub/linux/kernel/people/tytso/kvm-xfstests/

shows the problem.  With your patch applied to the xfstests-dev
directory after checking out xfstests-bld (see [1] for more
information if you haven't used kvm-xfstests before), it's reproducible via:

kvm-xfstests -I ../out_dir/root_fs.img.amd64 --update-xfstests-tar -c 4k shared/012

[1] https://github.com/tytso/xfstests-bld/blob/master/Documentation/kvm-quickstart.md

						- Ted
Gabriel Krisman Bertazi June 12, 2019, 6:32 p.m. UTC | #4
"Theodore Ts'o" <tytso@mit.edu> writes:

> On Wed, Jun 12, 2019 at 01:01:46AM -0400, Gabriel Krisman Bertazi wrote:
>> > I tried out this test, and it's apparently failing for me using
>> > e2fsprogs 1.45.2; it looks like it's a whitespace issue?
>> 
>> Hi Ted,
>> 
>> Yes, definitely just whitespace.  But i don't understand why you are
>> getting this behavior.  I tried both with the master branch of e2fsprogs
>> and the tagged commit of v1.45.2 and on both occasions the test succeed
>> in my system.  For sure I can use filter_spaces but I'm puzzled why I
>> can't reproduce this.
>
> That's wierd.  The kvm-xfstests appliance VM that's uploaded to
>
> https://mirrors.edge.kernel.org/pub/linux/kernel/people/tytso/kvm-xfstests/
>
> shows the problem.  With your patch applied to the xfstests-dev
> directory after checking out xfstests-bld (see [1] for more
> information if you haven't used kvm-xfstests before), it's reproducible via:
>
> kvm-xfstests -I ../out_dir/root_fs.img.amd64 --update-xfstests-tar -c 4k shared/012
>
> [1] https://github.com/tytso/xfstests-bld/blob/master/Documentation/kvm-quickstart.md

Hi,

Thanks for the tip.  With my setup, I still can't reproduce it, but I
was able to trigger it with xfstests-bld.  I'll send a follow up patch
that makes the result deterministic, making it work for every scenario.
Later, I'll take a look to see what is missing on my setup to make it
trigger.

Patch
diff mbox series

diff --git a/tests/shared/012 b/tests/shared/012
new file mode 100755
index 000000000000..d7e9cb43f524
--- /dev/null
+++ b/tests/shared/012
@@ -0,0 +1,508 @@ 
+# SPDX-License-Identifier: GPL-2.0+
+#!/bin/bash
+# FSQA Test No. 012
+#
+# Test the basic functionality of filesystems with case-insensitive
+# support.
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+status=1 # failure is thea default
+
+. ./common/rc
+. ./common/filter
+. ./common/casefold
+. ./common/attr
+
+_supported_os Linux
+_require_scratch_nocheck
+_require_scratch_casefold
+_require_check_dmesg
+_require_attrs
+
+sdev=$(_short_dev ${SCRATCH_DEV})
+
+filename1="file.txt"
+filename2="FILE.TXT"
+
+pt_file1=$(echo -e "coração")
+pt_file2=$(echo -e "corac\xcc\xa7\xc3\xa3o" | tr a-z A-Z)
+
+fr_file2=$(echo -e "french_caf\xc3\xa9.txt")
+fr_file1=$(echo -e "french_cafe\xcc\x81.txt")
+
+ar_file1=$(echo -e "arabic_\xdb\x92\xd9\x94.txt")
+ar_file2=$(echo -e "arabic_\xdb\x93.txt" | tr a-z A-Z)
+
+jp_file1=$(echo -e "japanese_\xe3\x82\xb2.txt")
+jp_file2=$(echo -e "japanese_\xe3\x82\xb1\xe3\x82\x99.txt")
+
+# '\xc3\x00' is an invalid sequence. Despite that, the sequences
+# below could match, if we ignored the error.  But we don't want
+# to be greedy at normalization, so at the first error we treat
+# the entire sequence as an opaque blob.  Therefore, these two
+# must NOT match.
+blob_file1=$(echo -e "corac\xcc\xa7\xc3")
+blob_file2=$(echo -e "coraç\xc3")
+
+# Test helpers
+basic_create_lookup()
+{
+	local basedir=${1}
+	local exact=${2}
+	local lookup=${3}
+
+	touch "${basedir}/${exact}"
+	[ -f "${basedir}/${lookup}" ] || \
+		echo "lookup of ${exact} using ${lookup} failed"
+	_casefold_check_exact_name "${basedir}" "${exact}" || \
+		echo "Created file ${exact} with wrong name."
+}
+
+# CI search should fail.
+bad_basic_create_lookup()
+{
+	local basedir=${1}
+	local exact=${2}
+	local lookup=${3}
+
+	touch "${basedir}/${exact}"
+	[ -f "${basedir}/${lookup}" ] && \
+		echo "Lookup of ${exact} using ${lookup} should fail"
+}
+
+# Testcases
+test_casefold_lookup()
+{
+	local basedir=${SCRATCH_MNT}/casefold_lookup
+
+	mkdir -p ${basedir}
+	_casefold_set_attr ${basedir}
+
+	basic_create_lookup "${basedir}" "${filename1}" "${filename2}"
+	basic_create_lookup "${basedir}" "${pt_file1}" "${pt_file2}"
+	basic_create_lookup "${basedir}" "${fr_file1}" "${fr_file2}"
+	basic_create_lookup "${basedir}" "${ar_file1}" "${ar_file2}"
+	basic_create_lookup "${basedir}" "${jp_file1}" "${jp_file2}"
+}
+
+test_bad_casefold_lookup()
+{
+	local basedir=${SCRATCH_MNT}/casefold_lookup
+
+	mkdir -p ${basedir}
+
+	bad_basic_create_lookup ${basedir} ${blob_file1} ${blob_file2}
+}
+
+do_create_and_remove()
+{
+	local basedir=${1}
+	local exact=${2}
+	local casefold=${3}
+
+	basic_create_lookup ${basedir} ${exact} ${casefold}
+	rm -f ${basedir}/${exact}
+	[ -f ${basedir}/${exact} ] && \
+		echo "File ${exact} was not removed using exact name"
+
+	basic_create_lookup ${basedir} ${exact} ${casefold}
+	rm -f ${basedir}/${casefold}
+	[ -f ${basedir}/${exact} ] && \
+		echo "File ${exact} was not removed using inexact name"
+}
+
+# remove and recreate
+test_create_and_remove()
+{
+	local basedir=${SCRATCH_MNT}/create_and_remove
+	mkdir -p ${basedir}
+
+	_casefold_set_attr ${basedir}
+	do_create_and_remove "${basedir}" "${pt_file1}" "${pt_file2}"
+	do_create_and_remove "${basedir}" "${jp_file1}" "${jp_file2}"
+	do_create_and_remove "${basedir}" "${ar_file1}" "${ar_file2}"
+	do_create_and_remove "${basedir}" "${fr_file1}" "${fr_file2}"
+}
+
+test_casefold_flag_basic()
+{
+	local basedir=${SCRATCH_MNT}/basic
+
+	mkdir -p ${basedir}
+	_casefold_set_attr ${basedir}
+	_casefold_lsattr_dir ${basedir} | _filter_scratch
+
+	_casefold_unset_attr ${basedir}
+	_casefold_lsattr_dir ${basedir} | _filter_scratch
+}
+
+test_casefold_flag_removal()
+{
+	local basedir=${SCRATCH_MNT}/casefold_flag_removal
+
+	mkdir -p ${basedir}
+	_casefold_set_attr ${basedir}
+	_casefold_lsattr_dir ${basedir} | _filter_scratch
+
+	# Try to remove +F attribute on non empty directory
+	touch ${basedir}/${filename1}
+	_casefold_unset_attr ${basedir} &>/dev/null
+	_casefold_lsattr_dir ${basedir} | _filter_scratch
+}
+
+# Test Inheritance of casefold flag
+test_casefold_flag_inheritance()
+{
+	local basedir=${SCRATCH_MNT}/flag_inheritance
+	local dirpath1="d1/d2/d3"
+	local dirpath2="D1/D2/D3"
+
+	mkdir -p ${basedir}
+	_casefold_set_attr ${basedir}
+
+	mkdir -p ${basedir}/${dirpath1}
+	_casefold_lsattr_dir ${basedir}/${dirpath1} | _filter_scratch
+
+	[ -d ${basedir}/${dirpath2} ] || \
+		echo "Directory CI Lookup failed."
+	_casefold_check_exact_name "${basedir}" "${dirpath1}" || \
+		echo "Created directory with wrong name."
+
+	touch ${basedir}/${dirpath2}/${filename1}
+	[ -f ${basedir}/${dirpath1}/${filename2} ] || \
+		echo "Couldn't create file on casefolded parent."
+}
+
+# Test nesting of sensitive directory inside insensitive directory.
+test_nesting_sensitive_insensitive_tree_simple()
+{
+	local basedir=${SCRATCH_MNT}/sd1
+
+	mkdir -p ${basedir}
+	_casefold_set_attr ${basedir}
+
+	mkdir -p ${basedir}/sd1
+	_casefold_set_attr ${basedir}/sd1
+
+	mkdir ${basedir}/sd1/sd2
+	_casefold_unset_attr ${basedir}/sd1/sd2
+
+	touch ${basedir}/sd1/sd2/${filename1}
+	[ -f ${basedir}/sd1/sd2/${filename1} ] || \
+		echo "Exact nested file lookup failed."
+	[ -f ${basedir}/sd1/SD2/${filename1} ] || \
+		echo "Nested file lookup failed."
+	[ -f ${basedir}/sd1/SD2/${filename2} ] && \
+		echo "Wrong file lookup passed, should have fail."
+}
+
+test_nesting_sensitive_insensitive_tree_complex()
+{
+	# Test nested-directories
+	local basedir=${SCRATCH_MNT}/nesting
+
+	mkdir -p ${basedir}
+	_casefold_set_attr ${basedir}
+
+	mkdir ${basedir}/nd1
+	_casefold_set_attr ${basedir}/nd1
+	mkdir ${basedir}/nd1/nd2
+	_casefold_unset_attr ${basedir}/nd1/nd2
+	mkdir ${basedir}/nd1/nd2/nd3
+	_casefold_set_attr ${basedir}/nd1/nd2/nd3
+	mkdir ${basedir}/nd1/nd2/nd3/nd4
+	_casefold_unset_attr ${basedir}/nd1/nd2/nd3/nd4
+	mkdir ${basedir}/nd1/nd2/nd3/nd4/nd5
+	_casefold_set_attr ${basedir}/nd1/nd2/nd3/nd4/nd5
+
+	[ -d ${basedir}/ND1/ND2/nd3/ND4/nd5 ] || \
+		echo "Nest-dir Lookup failed."
+	[ -d ${basedir}/nd1/nd2/nd3/nd4/ND5 ] && \
+		echo "ND5: Nest-dir Lookup passed, it should fail."
+	[ -d ${basedir}/nd1/nd2/nd3/ND4/nd5 ] || \
+		echo "Nest-dir Lookup failed."
+	[ -d ${basedir}/nd1/nd2/ND3/nd4/ND5 ] && \
+		echo "ND3: Nest-dir Lookup passed, it should fail."
+}
+
+test_symlink_with_inexact_name()
+{
+	local basedir=${SCRATCH_MNT}/symlink
+
+	mkdir -p ${basedir}
+	_casefold_set_attr ${basedir}
+
+	mkdir ${basedir}/ind1
+	mkdir ${basedir}/ind2
+	_casefold_set_attr ${basedir}/ind1
+	touch ${basedir}/ind1/target
+
+	ln -s ${basedir}/ind1/TARGET ${basedir}/ind2/link
+	[ -L ${basedir}/ind2/link ] || echo "Not a symlink."
+	readlink -e ${basedir}/ind2/link | _filter_scratch
+}
+
+do_test_name_preserve()
+{
+	local basedir=${1}
+	local exact=${2}
+	local casefold=${3}
+
+	touch ${basedir}/${exact}
+	rm ${basedir}/${exact}
+
+	touch ${basedir}/${casefold}
+	_casefold_check_exact_name ${basedir} ${casefold} ||
+		echo "${casefold} was not created with exact name"
+}
+
+# Name-preserving tests
+# We create a file with a name, delete it and create again with an
+# equivalent name.  If the negative dentry wasn't invalidated, the
+# file might be created using $1 instead of $2.
+test_name_preserve()
+{
+	local basedir=${SCRATCH_MNT}/test_name_preserve
+
+	mkdir -p ${basedir}
+	_casefold_set_attr ${basedir}
+
+	do_test_name_preserve "${basedir}" "${pt_file1}" "${pt_file2}"
+	do_test_name_preserve "${basedir}" "${jp_file1}" "${jp_file2}"
+	do_test_name_preserve "${basedir}" "${ar_file1}" "${ar_file2}"
+	do_test_name_preserve "${basedir}" "${fr_file1}" "${fr_file2}"
+}
+
+do_test_dir_name_preserve()
+{
+	local basedir=${1}
+	local exact=${2}
+	local casefold=${3}
+
+	mkdir ${basedir}/${exact}
+	rmdir ${basedir}/${exact}
+
+	mkdir ${basedir}/${casefold}
+	_casefold_check_exact_name ${basedir} ${casefold} ||
+		echo "${casefold} was not created with exact name"
+}
+
+test_dir_name_preserve()
+{
+	local basedir=${SCRATCH_MNT}/"dir-test_name_preserve"
+
+	mkdir -p ${basedir}
+	_casefold_set_attr ${basedir}
+
+	do_test_dir_name_preserve "${basedir}" "${pt_file1}" "${pt_file2}"
+	do_test_dir_name_preserve "${basedir}" "${jp_file1}" "${jp_file2}"
+	do_test_dir_name_preserve "${basedir}" "${ar_file1}" "${ar_file2}"
+	do_test_dir_name_preserve "${basedir}" "${fr_file1}" "${fr_file2}"
+}
+
+test_name_reuse()
+{
+	local basedir=${SCRATCH_MNT}/reuse
+	local reuse1=fileX
+	local reuse2=FILEX
+
+	mkdir ${basedir}
+	_casefold_set_attr ${basedir}
+
+	touch ${basedir}/${reuse1}
+	rm -f ${basedir}/${reuse1} || echo "File lookup failed."
+	touch ${basedir}/${reuse2}
+	_casefold_check_exact_name "${basedir}" "${reuse2}" || \
+		echo "File created with wrong name"
+	_casefold_check_exact_name "${basedir}" "${reuse1}" && \
+		echo "File created with the old name"
+}
+
+test_create_with_same_name()
+{
+	local basedir=${SCRATCH_MNT}/same_name
+
+	mkdir ${basedir}
+	_casefold_set_attr ${basedir}
+
+	mkdir -p ${basedir}/same1/same1
+	touch ${basedir}/SAME1/sAME1/sAMe1
+	touch -c ${basedir}/SAME1/sAME1/same1 ||
+		echo "Would create a new file instead of using old one"
+}
+
+test_file_rename()
+{
+	local basedir=${SCRATCH_MNT}/rename
+
+	mkdir -p ${basedir}
+	_casefold_set_attr ${basedir}
+
+	# Move to an equivalent name should not work
+	mv ${basedir}/rename ${basedir}/rename 2>&1 | \
+		_filter_scratch
+
+	_casefold_check_exact_name ${basedir} "rename" || \
+		echo "Name shouldn't change."
+}
+
+# Test openfd with casefold.
+# 1. Delete a file after gettings its fd.
+# 2. Then create new dir with same name
+test_casefold_openfd()
+{
+	local basedir=${SCRATCH_MNT}/openfd
+	local ofd1="openfd"
+	local ofd2="OPENFD"
+
+	mkdir -p ${basedir}
+	_casefold_set_attr ${basedir}
+
+	exec 3<> ${basedir}/${ofd1}
+	rm -rf ${basedir}/${ofd1}
+	mkdir ${basedir}/${ofd2}
+	[ -d ${basedir}/${ofd2} ] || echo "Not a directory"
+	_casefold_check_exact_name ${basedir} "${ofd2}" ||
+		echo "openfd file was created using old name"
+	rm -rf ${basedir}/${ofd2}
+	exec 3>&-
+}
+
+# Test openfd with casefold.
+# 1. Delete a file after gettings its fd.
+# 2. Then create new file with same name
+# 3. Read from open-fd and write into new file.
+test_casefold_openfd2()
+{
+	local basedir=${SCRATCH_MNT}/openfd2
+	local ofd1="openfd"
+	local ofd2="OPENFD"
+
+	mkdir ${basedir}
+	_casefold_set_attr ${basedir}
+
+	date > ${basedir}/${ofd1}
+	exec 3<> ${basedir}/${ofd1}
+	rm -rf ${basedir}/${ofd1}
+	touch ${basedir}/${ofd1}
+	[ -f ${basedir}/${ofd2} ] || echo "Not a file"
+	read data <&3
+	echo $data >> ${basedir}/${ofd1}
+	exec 3>&-
+}
+
+test_hard_link_lookups()
+{
+	local basedir=${SCRATCH_MNT}/hard_link
+
+	mkdir ${basedir}
+	_casefold_set_attr ${basedir}
+
+	touch ${basedir}/h1
+	ln ${basedir}/H1 ${SCRATCH_MNT}/h1
+	cnt=`stat -c %h ${basedir}/h1`
+	[ $cnt -eq 1 ] && echo "Unable to create hardlink"
+
+	# Create hardlink for casefold dir file and inside regular dir.
+	touch ${SCRATCH_MNT}/h2
+	ln ${SCRATCH_MNT}/h2 ${basedir}/H2
+	cnt=`stat -c %h ${basedir}/h2`
+	[ $cnt -eq 1 ] && echo "Unable to create hardlink"
+}
+
+test_xattrs_lookups()
+{
+	local basedir=${SCRATCH_MNT}/xattrs
+
+	mkdir ${basedir}
+	_casefold_set_attr ${basedir}
+
+	mkdir -p ${basedir}/x
+
+	${SETFATTR_PROG} -n user.foo -v bar ${basedir}/x
+	${GETFATTR_PROG} --absolute-names -n user.foo \
+		${basedir}/x | _filter_scratch
+
+	touch ${basedir}/x/f1
+	${SETFATTR_PROG} -n user.foo -v bar ${basedir}/x/f1
+	${GETFATTR_PROG} --absolute-names -n user.foo \
+		${basedir}/x/f1 | _filter_scratch
+}
+
+test_lookup_large_directory()
+{
+	local basedir=${SCRATCH_MNT}/large
+
+	mkdir -p ${basedir}
+	_casefold_set_attr ${basedir}
+
+	touch $(seq -f "${basedir}/file%g" 0 2000)
+
+	# We really want to spawn a single process here, to speed up the
+	# test, but we don't want the output of 2k files, except for
+	# errors.
+	cat $(seq -f "${basedir}/FILE%g" 0 2000) || \
+		echo "Case on large dir failed"
+}
+
+test_strict_mode_invalid_filename()
+{
+	local basedir=${SCRATCH_MNT}/strict
+
+	mkdir -p ${basedir}
+	_casefold_set_attr ${basedir}
+
+	# These creation commands should fail, since we are on strict
+	# mode.
+	touch "${basedir}/${blob_file1}" 2>&1 | _filter_scratch
+	touch "${basedir}/${blob_file2}" 2>&1 | _filter_scratch
+}
+
+#############
+# Run tests #
+#############
+
+_scratch_mkfs_casefold >>$seqres.full 2>&1
+
+_scratch_mount
+
+_check_dmesg_for \
+	"\(${sdev}\): Using encoding defined by superblock: utf8" || \
+	_fail "Could not mount with encoding: utf8"
+
+test_casefold_flag_basic
+test_casefold_lookup
+test_bad_casefold_lookup
+test_create_and_remove
+test_casefold_flag_removal
+test_casefold_flag_inheritance
+test_nesting_sensitive_insensitive_tree_simple
+test_nesting_sensitive_insensitive_tree_complex
+test_symlink_with_inexact_name
+test_name_preserve
+test_dir_name_preserve
+test_name_reuse
+test_create_with_same_name
+test_file_rename
+test_casefold_openfd
+test_casefold_openfd2
+test_hard_link_lookups
+test_xattrs_lookups
+test_lookup_large_directory
+
+_scratch_unmount
+_check_scratch_fs
+
+# Test Strict Mode
+_scratch_mkfs_casefold_strict >>$seqres.full 2>&1
+_scratch_mount
+
+test_strict_mode_invalid_filename
+
+_scratch_unmount
+_check_scratch_fs
+
+status=0
+exit
diff --git a/tests/shared/012.out b/tests/shared/012.out
new file mode 100644
index 000000000000..2951be901f7c
--- /dev/null
+++ b/tests/shared/012.out
@@ -0,0 +1,16 @@ 
+QA output created by 012
+SCRATCH_MNT/basic           Extents, Casefold
+SCRATCH_MNT/basic           Extents
+SCRATCH_MNT/casefold_flag_removal Extents, Casefold
+SCRATCH_MNT/casefold_flag_removal Extents, Casefold
+SCRATCH_MNT/flag_inheritance/d1/d2/d3 Extents, Casefold
+SCRATCH_MNT/symlink/ind1/TARGET
+mv: cannot stat 'SCRATCH_MNT/rename/rename': No such file or directory
+# file: SCRATCH_MNT/xattrs/x
+user.foo="bar"
+
+# file: SCRATCH_MNT/xattrs/x/f1
+user.foo="bar"
+
+touch: setting times of 'SCRATCH_MNT/strict/corac'$'\314\247\303': Invalid argument
+touch: setting times of 'SCRATCH_MNT/strict/cora'$'\303\247\303': Invalid argument
diff --git a/tests/shared/group b/tests/shared/group
index b091d9111359..53b4a356695d 100644
--- a/tests/shared/group
+++ b/tests/shared/group
@@ -14,6 +14,7 @@ 
 009 auto stress dedupe
 010 auto stress dedupe
 011 auto quick
+012 auto quick casefold
 032 mkfs auto quick
 272 auto enospc rw
 289 auto quick