Merge branch 'sprandom-tests' of https://github.com/tomas-winkler-sndk/fio
* 'sprandom-tests' of https://github.com/tomas-winkler-sndk/fio:
tests: add sprandom test cases
diff --git a/t/run-fio-tests.py b/t/run-fio-tests.py
index b486329..363f205 100755
--- a/t/run-fio-tests.py
+++ b/t/run-fio-tests.py
@@ -1123,6 +1123,14 @@
'success': SUCCESS_DEFAULT,
'requirements': [Requirements.linux],
},
+ {
+ 'test_id': 1019,
+ 'test_class': FioExeTest,
+ 'exe': 't/sprandom.py',
+ 'parameters': ['-f', '{fio_path}'],
+ 'success': SUCCESS_DEFAULT,
+ 'requirements': [Requirements.linux, Requirements.libaio],
+ },
]
diff --git a/t/sprandom.py b/t/sprandom.py
new file mode 100755
index 0000000..e1b3a5e
--- /dev/null
+++ b/t/sprandom.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (c) 2025 Sandisk Corporation or its affiliates
+
+"""
+sprandom.py
+-----------
+Tests for fio's sprandom feature.
+
+USAGE:
+ python t/sprandom.py [-f fio-executable]
+
+This script is also invoked by t/run-fio-tests.py.
+"""
+
+import sys
+import argparse
+import time
+from pathlib import Path
+
+from fiotestlib import FioJobCmdTest, run_fio_tests
+from fiotestcommon import SUCCESS_DEFAULT, SUCCESS_NONZERO
+
+SPRANDOM_OPT_LIST = [
+ 'spr_op',
+ 'spr_num_regions',
+ 'size',
+ 'norandommap',
+ 'random_generator',
+ 'rw',
+]
+
+class FioSPrandomTest(FioJobCmdTest):
+ """fio sprandom test wrapper."""
+
+ def setup(self, parameters):
+ """Setup fio arguments for the test."""
+ bs = parameters.get("bs", "4k")
+ fio_args = [
+ "--name=sprandom",
+ "--ioengine=libaio",
+ "--filename=sprandom_testfile",
+ f"--bs={bs}",
+ f"--blockalign={bs}",
+ "--direct=1",
+ "--iodepth=16",
+ "--sprandom=1",
+ ]
+
+ # Add variable parameters if provided
+
+ for opt in SPRANDOM_OPT_LIST:
+ if opt in self.fio_opts:
+ option = f"--{opt}={self.fio_opts[opt]}"
+ fio_args.append(option)
+ if "rw" not in self.fio_opts:
+ fio_args.append("--rw=randwrite")
+
+ super().setup(fio_args)
+
+
+TEST_LIST = [
+ {
+ "test_id": 1,
+ "fio_opts": {
+ "spr_op": "0.10",
+ "spr_num_regions": "50",
+ "size": "32M",
+ },
+ "success": SUCCESS_DEFAULT,
+ "test_class": FioSPrandomTest,
+ },
+ {
+ "test_id": 2,
+ "fio_opts": {
+ "spr_op": "0.25",
+ "spr_num_regions": "100",
+ "size": "64M",
+ },
+ "success": SUCCESS_DEFAULT,
+ "test_class": FioSPrandomTest,
+ },
+ {
+ "test_id": 3,
+ "fio_opts": {
+ "spr_op": "0.50",
+ "spr_num_regions": "200",
+ "size": "128M",
+ "random_generator": "tausworthe",
+ },
+ "success": SUCCESS_NONZERO,
+ "test_class": FioSPrandomTest,
+ },
+ {
+ "test_id": 4,
+ "fio_opts": {
+ "spr_op": "0.75",
+ "spr_num_regions": "400",
+ "size": "256M",
+ "norandommap": "0"
+ },
+ "bs": "16K",
+ "success": SUCCESS_NONZERO,
+ "test_class": FioSPrandomTest,
+ },
+ {
+ "test_id": 4,
+ "fio_opts": {
+ "spr_op": "0.75",
+ "spr_num_regions": "400",
+ "size": "256M",
+ "rw": "randread",
+ },
+ "bs": "16K",
+ "success": SUCCESS_NONZERO,
+ "test_class": FioSPrandomTest,
+ },
+]
+
+
+def parse_args():
+ """Parse command-line arguments."""
+ parser = argparse.ArgumentParser()
+ parser.add_argument("-f", "--fio",
+ help="path to fio executable (default: fio in PATH)")
+ parser.add_argument('-s', '--skip', nargs='+', type=int,
+ help='list of test(s) to skip')
+ parser.add_argument('-a', '--artifact-root', help='artifact root directory')
+ parser.add_argument('-o', '--run-only', nargs='+', type=int,
+ help='list of test(s) to run, skipping all others')
+
+ return parser.parse_args()
+
+
+def main():
+ """Run sprandom tests."""
+ args = parse_args()
+
+ fio_path = str(Path(args.fio).absolute()) if args.fio else "fio"
+ artifact_root = args.artifact_root if args.artifact_root else \
+ f"sprandom-test-{time.strftime('%Y%m%d-%H%M%S')}"
+ Path(artifact_root).mkdir(parents=True, exist_ok=True)
+ print(f"Artifact directory is {str(Path(artifact_root).absolute())}")
+
+ test_env = {
+ "fio_path": fio_path,
+ "fio_root": str(Path(__file__).absolute().parent.parent),
+ "artifact_root": artifact_root,
+ "basename": "sprandom"
+ }
+
+ _, failed, _ = run_fio_tests(TEST_LIST, test_env, args)
+ sys.exit(failed)
+
+
+if __name__ == "__main__":
+ main()