Skip to content

Commit

Permalink
tests: Add a pre-allocation test
Browse files Browse the repository at this point in the history
I used this test when diagnosing #281 and think it would be a good
addition.

This tests file sizes when pre-allocating a file.

Expected values have been confirmed on NTFS, ReFS and FAT32.
This test currently does not work on a SMB share with the Samba server
because it reports a fixed cluster size based on a configuration option
instead of getting the correct value from the underlying file system.
ksmbd does not have the same issue, it correctly gets the values from
the file system. So far this is untested with Windows SMB shares.

This also makes `tests.py` use some helpers from `utils.py`.

Signed-off-by: Axel Gembe <[email protected]>
  • Loading branch information
EchterAgo committed Oct 11, 2023
1 parent c864cfb commit 567a9d2
Show file tree
Hide file tree
Showing 4 changed files with 561 additions and 24 deletions.
33 changes: 33 additions & 0 deletions .github/workflows/windows-build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2735,3 +2735,36 @@ jobs:



test9_regression_test:
needs: [build_windows]
timeout-minutes: 30
runs-on: windows-latest
steps:
- uses: actions/checkout@v3

- uses: actions/download-artifact@v3
with:
name: dev_build_inno

- name: get zfsexename
id: zfsinstaller
run: |
$p = Get-ChildItem | Where-Object {$_.Name -like 'OpenZFSOnWindows-*.exe'} | Select-Object -first 1
echo $p
$f = (Get-Item $p ).Name
echo $f
echo "filename=$f" | Out-File -FilePath $Env:GITHUB_OUTPUT -Encoding utf8 -Append
# https://github.com/MicrosoftDocs/windows-powershell-docs/issues/266
- name: Import root certificate
run: |
$plaintextpwd = 'password1234'
$pwd = ConvertTo-SecureString -String $plaintextpwd -Force -AsPlainText
Import-PfxCertificate -FilePath ${{github.workspace}}/contrib/windows/TestCert/test_sign_cert_pass.pfx -CertStoreLocation Cert:\LocalMachine\Root -Password $pwd
Import-PfxCertificate -FilePath ${{github.workspace}}/contrib/windows/TestCert/test_sign_cert_pass.pfx -CertStoreLocation Cert:\LocalMachine\TrustedPublisher -Password $pwd
- name: install zfs
run: 'Start-Process -FilePath "${{github.workspace}}\${{ steps.zfsinstaller.outputs.filename }}" -Wait -ArgumentList "/NORESTART /ALLUSERS /VERYSILENT /LOG=`"${{github.workspace}}\InnoSetup-Install.log`""'

- name: test
run: 'python.exe -u "${{github.workspace}}\contrib\windows\tests\regression.py" --path ${{github.workspace}}\'
144 changes: 144 additions & 0 deletions contrib/windows/tests/regression.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import argparse
import logging
import os
import pathlib
import unittest

from utils import (
ZfsContext,
Size,
setup_logging,
argparse_as_abspath,
argparse_as_zfs_abspath,
created_zpool,
preallocate_file_object,
get_sizes_from_path,
get_sizes_from_file,
get_cluster_size_from_file,
)


args: argparse.Namespace
ctx: ZfsContext


logger = setup_logging("regression", logging.INFO)
tc = unittest.TestCase()


def parse_arguments() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Process command line arguments.")

parser.add_argument("--path", type=argparse_as_abspath, required=True)

# TODO: We need to verify that the zfs path is actually usable because the default path is not
# passed to `argparse_as_zfs_abspath`.
program_files = pathlib.PureWindowsPath(os.getenv("ProgramFiles"))
default_zfs_path = program_files / "OpenZFS On Windows"
parser.add_argument(
"--zfspath",
type=argparse_as_zfs_abspath,
default=default_zfs_path,
help="Directory path of either an OpenZFS installation or build directory",
)

parser.add_argument(
"-np",
"--no_pool",
action="store_true",
default=False,
help="Don't create a zpool, run tests in path",
)

return parser.parse_args()


def test_preallocation(test_path: pathlib.Path):
"""Tests file sizes when pre-allocating a file.
Expected values have been confirmed on NTFS, ReFS and FAT32.
This test currently does not work on a SMB share with the Samba server
because it reports a fixed cluster size based on a configuration option
instead of getting the correct value from the underlying file system. ksmbd
does not have the same issue, it correctly gets the values from the file
system. So far this is untested with Windows SMB shares.
See https://github.com/openzfsonwindows/openzfs/issues/281
See https://bugzilla.samba.org/show_bug.cgi?id=7436
Args:
test_path (pathlib.Path): The path where we want to run the test
"""

fpath = test_path / "testfile.bin"

try:
with open(fpath, "wb") as test_file:
csize = get_cluster_size_from_file(test_file)
tc.assertGreaterEqual(csize, 512, f"Bad cluster size for {fpath}')

fsize = get_sizes_from_file(test_file)
tc.assertEqual(
fsize,
{"AllocationSize": 0, "EndOfFile": 0},
f"Wrong file size after creation of {fpath}",
)

preallocate_file_object(test_file, 512)

fsize = get_sizes_from_file(test_file)
tc.assertEqual(
fsize,
{"AllocationSize": csize, "EndOfFile": 0},
f"Wrong file size after preallocation of {fpath}",
)

test_file.write(b"\x55" * 117)

fsize = get_sizes_from_file(test_file)
tc.assertEqual(
fsize,
{"AllocationSize": csize, "EndOfFile": 0},
f"Wrong file size after write to preallocated file {fpath}",
)

fsize = get_sizes_from_path(fpath)
tc.assertEqual(
fsize,
{"AllocationSize": csize, "EndOfFile": 117},
f"Wrong file size after close of preallocated file {fpath}",
)
finally:
if os.path.isfile(fpath):
os.unlink(fpath)


def run_tests(test_path: pathlib.Path):
test_preallocation(test_path)


def main():
global args
global ctx

args = parse_arguments()
ctx = ZfsContext(args.zfspath)

if args.no_pool:
run_tests(args.path)
else:
test_backing_file = args.path / "test.dat"

with created_zpool(
ctx, "test", test_backing_file, 1 * Size.GIB
) as test_pool_path:
logger.info(
f'Created zpool named "test", backed by {test_backing_file}, mounted in {test_pool_path}'
)

run_tests(test_pool_path)

logger.info("PASSED")


if __name__ == "__main__":
main()
36 changes: 12 additions & 24 deletions contrib/windows/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

import logging

from utils import Size, argparse_as_abspath, allocate_file

logging.basicConfig(level=logging.DEBUG)

print("Printed immediately.")
Expand All @@ -22,18 +24,10 @@
def parse_arguments():
parser = argparse.ArgumentParser(description='Process command line '
'arguments.')
parser.add_argument('-path', type=dir_path, required=True)
parser.add_argument('-path', type=argparse_as_abspath, required=True)
return parser.parse_args()


def dir_path(path):
if os.path.isdir(path):
return path
else:
raise argparse.ArgumentTypeError(f"readable_dir:{path} is not a valid"
"path")


def get_DeviceId():
magic_number_process = subprocess.run(
["wmic", "diskdrive", "get", "DeviceId"],
Expand Down Expand Up @@ -70,12 +64,6 @@ def get_DeviceId():
return e


def allocate_file(name, size):
with open(name, 'wb') as f:
f.seek(size)
f.write(b'0')


def delete_file(name):
if os.path.exists(name):
os.remove(name)
Expand Down Expand Up @@ -199,7 +187,7 @@ def main():

print("Path:", parsed_args.path)

p = PureWindowsPath(parsed_args.path)
p = parsed_args.path

print("Path object:", p)

Expand All @@ -208,11 +196,11 @@ def main():
if p.is_absolute():

f1 = PureWindowsPath(p, "test01.dat")
allocate_file(f1, 1024*1024*1024)
allocate_file(f1, 1 * Size.GIB)
f2 = PureWindowsPath(p, "test02.dat")
allocate_file(f2, 1024*1024*1024)
allocate_file(f2, 1 * Size.GIB)
f3 = PureWindowsPath(p, "test03.dat")
allocate_file(f3, 1024*1024*1024)
allocate_file(f3, 1 * Size.GIB)

preTest()
ret = runWithPrint(["zpool", "create", "-f", "test01", tounc(f1)])
Expand Down Expand Up @@ -299,14 +287,14 @@ def main():
print("Drive letters after pool create:", get_driveletters())

f = PureWindowsPath(get_driveletters()[0][1], "test01.file")
allocate_file(f, 1024)
allocate_file(f, 1 * Size.KIB)

ret = runWithPrint(["zfs", "snapshot", "testsn01@friday"])
if ret.returncode != 0:
print("FAIL")

f = PureWindowsPath(get_driveletters()[0][1], "test02.file")
allocate_file(f, 1024)
allocate_file(f, 1 * Size.KIB)

ret = runWithPrint(["zpool", "export", "-a"])
if ret.returncode != 0:
Expand All @@ -327,15 +315,15 @@ def main():
# print("Drive letters after pool create:", get_driveletters())
#
# f = PureWindowsPath(get_driveletters()[0][1], "test01.file")
# allocate_file(f, 1024)
# allocate_file(f, 1 * Size.KIB)
#
# ret = runWithPrint(["zfs", "snapshot", "testsn02@friday"])
# if ret.returncode != 0:
# print("FAIL")
#
#
# f = PureWindowsPath(get_driveletters()[0][1], "test02.file")
# allocate_file(f, 1024)
# allocate_file(f, 1 * Size.KIB)
#
# ret = runWithPrint(["zfs", "mount", "testsn02@friday"])
# if ret.returncode != 0:
Expand Down Expand Up @@ -408,7 +396,7 @@ def main():

f = PureWindowsPath(get_driveletters()[0][1], "test01.file")
try:
allocate_file(f, 1024)
allocate_file(f, 1 * Size.KIB)
except Exception:
print("FAIL")

Expand Down
Loading

0 comments on commit 567a9d2

Please sign in to comment.