Recent changes (master)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The following changes since commit 0f754a3af30fe6f308ce1c0f95bf1a6f99b3177a:

  t/zbd: add test case to confirm no max_open_zones limit check (2025-01-22 11:08:37 -0500)

are available in the Git repository at:

  git://git.kernel.dk/fio.git master

for you to fetch changes up to 46559adef82f7d0a0712ac31b20d98fa6b0bd7af:

  t/run-fio-tests: add client/server test script (2025-01-23 12:57:42 -0500)

----------------------------------------------------------------
Vincent Fu (7):
      client: rename job_opt_object to global_opt_object
      json: allow empty string values
      client: separate global options from multiple servers
      t/fiotestlib: improve JSON decoding
      ci: install kill binary for Debian platforms
      t/client-server: basic client/server test script
      t/run-fio-tests: add client/server test script

 ci/actions-install.sh               |   1 +
 client.c                            |  42 ++-
 client.h                            |   1 +
 json.c                              |   3 -
 t/client_server.py                  | 505 ++++++++++++++++++++++++++++++++++++
 t/client_server/test01.fio          |  14 +
 t/client_server/test04-noglobal.fio |  20 ++
 t/client_server/test07-slat.fio     |   7 +
 t/client_server/test08-clat.fio     |   7 +
 t/client_server/test09-lat.fio      |   7 +
 t/client_server/test10-noclat.fio   |   7 +
 t/client_server/test11-alllat.fio   |   9 +
 t/fiotestlib.py                     |  17 +-
 t/run-fio-tests.py                  |   8 +
 14 files changed, 628 insertions(+), 20 deletions(-)
 create mode 100755 t/client_server.py
 create mode 100644 t/client_server/test01.fio
 create mode 100644 t/client_server/test04-noglobal.fio
 create mode 100644 t/client_server/test07-slat.fio
 create mode 100644 t/client_server/test08-clat.fio
 create mode 100644 t/client_server/test09-lat.fio
 create mode 100644 t/client_server/test10-noclat.fio
 create mode 100644 t/client_server/test11-alllat.fio

---

Diff of recent changes:

diff --git a/ci/actions-install.sh b/ci/actions-install.sh
index 5a32ec91..ad352317 100755
--- a/ci/actions-install.sh
+++ b/ci/actions-install.sh
@@ -89,6 +89,7 @@ DPKGCFG
             bison
             build-essential
             flex
+            procps
             zlib1g-dev
         )
     fi
diff --git a/client.c b/client.c
index d6d54663..923b092e 100644
--- a/client.c
+++ b/client.c
@@ -61,7 +61,8 @@ int sum_stat_clients;
 static int sum_stat_nr;
 static struct buf_output allclients;
 static struct json_object *root = NULL;
-static struct json_object *job_opt_object = NULL;
+static struct json_object *global_opt_object = NULL;
+static struct json_array *global_opt_array = NULL;
 static struct json_array *clients_array = NULL;
 static struct json_array *du_array = NULL;
 
@@ -189,8 +190,13 @@ static void fio_client_json_init(void)
 	json_object_add_value_int(root, "timestamp", time_p);
 	json_object_add_value_string(root, "time", time_buf);
 
-	job_opt_object = json_create_object();
-	json_object_add_value_object(root, "global options", job_opt_object);
+	if (nr_clients == 1) {
+		global_opt_object = json_create_object();
+		json_object_add_value_object(root, "global options", global_opt_object);
+	} else {
+		global_opt_array = json_create_array();
+		json_object_add_value_array(root, "global options", global_opt_array);
+	}
 	clients_array = json_create_array();
 	json_object_add_value_array(root, "client_stats", clients_array);
 	du_array = json_create_array();
@@ -215,7 +221,8 @@ static void fio_client_json_fini(void)
 
 	json_free_object(root);
 	root = NULL;
-	job_opt_object = NULL;
+	global_opt_object = NULL;
+	global_opt_array = NULL;
 	clients_array = NULL;
 	du_array = NULL;
 }
@@ -1116,11 +1123,13 @@ static void handle_ts(struct fio_client *client, struct fio_net_cmd *cmd)
 		opt_list = &client->opt_lists[p->ts.thread_number - 1];
 
 	tsobj = show_thread_status(&p->ts, &p->rs, opt_list, &client->buf);
-	client->did_stat = true;
 	if (tsobj) {
 		json_object_add_client_info(tsobj, client);
 		json_array_add_value_object(clients_array, tsobj);
+		if (!client->did_stat && client->global_opts)
+			json_array_add_value_object(global_opt_array, client->global_opts);
 	}
+	client->did_stat = true;
 
 	if (sum_stat_clients <= 1)
 		return;
@@ -1171,12 +1180,31 @@ static void handle_job_opt(struct fio_client *client, struct fio_net_cmd *cmd)
 	pdu->groupid = le32_to_cpu(pdu->groupid);
 
 	if (pdu->global) {
-		if (!job_opt_object)
+		struct json_object *global_opts;
+
+		if (!global_opt_object && !global_opt_array)
 			return;
 
-		json_object_add_value_string(job_opt_object,
+		/*
+		 * If we have only one server connection, add it to the single
+		 * global option dictionary. When we have connections to
+		 * multiple servers, add the global option to the
+		 * server-specific dictionary.
+		 */
+		if (global_opt_object) {
+			global_opts = global_opt_object;
+		} else {
+			if (!client->global_opts) {
+				client->global_opts = json_create_object();
+				json_object_add_client_info(client->global_opts, client);
+			}
+			global_opts = client->global_opts;
+		}
+
+		json_object_add_value_string(global_opts,
 					     (const char *)pdu->name,
 					     (const char *)pdu->value);
+		return;
 	} else if (client->opt_lists) {
 		struct flist_head *opt_list = &client->opt_lists[pdu->groupid];
 		struct print_option *p;
diff --git a/client.h b/client.h
index d77b6076..11fc661a 100644
--- a/client.h
+++ b/client.h
@@ -42,6 +42,7 @@ struct fio_client {
 	char *name;
 
 	struct flist_head *opt_lists;
+	struct json_object *global_opts;
 
 	int state;
 
diff --git a/json.c b/json.c
index cd3d5d74..6375b3c2 100644
--- a/json.c
+++ b/json.c
@@ -56,9 +56,6 @@ static char *strdup_escape(const char *str)
 	char *p, *ret;
 	int escapes;
 
-	if (!strlen(str))
-		return NULL;
-
 	escapes = 0;
 	while ((input = strpbrk(input, "\\\"")) != NULL) {
 		escapes++;
diff --git a/t/client_server.py b/t/client_server.py
new file mode 100755
index 00000000..88f5297f
--- /dev/null
+++ b/t/client_server.py
@@ -0,0 +1,505 @@
+#!/usr/bin/env python3
+"""
+# client_server.py
+#
+# Test fio's client/server mode.
+#
+# USAGE
+# see python3 client_server.py --help
+#
+# EXAMPLES
+# python3 t/client_server.py
+# python3 t/client_server.py -f ./fio
+#
+# REQUIREMENTS
+# Python 3.6
+#
+# This will start fio server instances listening on the interfaces below and
+# will break if any ports are already occupied.
+#
+#
+"""
+import os
+import sys
+import time
+import locale
+import logging
+import argparse
+import tempfile
+import subprocess
+import configparser
+from pathlib import Path
+from fiotestlib import FioJobCmdTest, run_fio_tests
+
+
+SERVER_LIST = [
+            ",8765",
+            ",8766",
+            ",8767",
+            ",8768",
+        ]
+
+PIDFILE_LIST = []
+
+class ClientServerTest(FioJobCmdTest):
+    """
+    Client/sever test class.
+    """
+
+    def setup(self, parameters):
+        """Setup a test."""
+
+        fio_args = [
+            f"--output={self.filenames['output']}",
+            f"--output-format={self.fio_opts['output-format']}",
+        ]
+        for server in self.fio_opts['servers']:
+            option = f"--client={server['client']}"
+            fio_args.append(option)
+            fio_args.append(server['jobfile'])
+
+        super().setup(fio_args)
+
+
+
+class ClientServerTestGlobalSingle(ClientServerTest):
+    """
+    Client/sever test class.
+    One server connection only.
+    The job file may or may not have a global section.
+    """
+
+    def check_result(self):
+        super().check_result()
+
+        config = configparser.ConfigParser(allow_no_value=True)
+        config.read(self.fio_opts['servers'][0]['jobfile'])
+
+        if not config.has_section('global'):
+            if len(self.json_data['global options']) > 0:
+                self.failure_reason = f"{self.failure_reason} non-empty 'global options' dictionary found with no global section in job file."
+                self.passed = False
+            return
+
+        if len(self.json_data['global options']) == 0:
+            self.failure_reason = f"{self.failure_reason} empty 'global options' dictionary found with no global section in job file."
+            self.passed = False
+
+        # Now make sure job file global section matches 'global options'
+        # in JSON output
+        job_file_global = dict(config['global'])
+        for key, value in job_file_global.items():
+            if value is None:
+                job_file_global[key] = ""
+        if job_file_global != self.json_data['global options']:
+            self.failure_reason = f"{self.failure_reason} 'global options' dictionary does not match global section in job file."
+            self.passed = False
+
+
+class ClientServerTestGlobalMultiple(ClientServerTest):
+    """
+    Client/sever test class.
+    Multiple server connections.
+    Job files may or may not have a global section.
+    """
+
+    def check_result(self):
+        super().check_result()
+
+        #
+        # For each job file, check if it has a global section
+        # If so, make sure the 'global options' array has
+        # as element for it.
+        # At the end, make sure the total number of elements matches the number
+        # of job files with global sections.
+        #
+
+        global_sections = 0
+        for server in self.fio_opts['servers']:
+            config = configparser.ConfigParser(allow_no_value=True)
+            config.read(server['jobfile'])
+
+            if not config.has_section('global'):
+                continue
+
+            global_sections += 1
+
+            # this can only parse one server spec format
+            [hostname, port] = server['client'].split(',')
+
+            match = None
+            for global_opts in self.json_data['global options']:
+                if 'hostname' not in global_opts:
+                    continue
+                if 'port' not in global_opts:
+                    continue
+                if global_opts['hostname'] == hostname and int(global_opts['port']) == int(port):
+                    match = global_opts
+                    break
+
+            if not match:
+                self.failure_reason = f"{self.failure_reason} matching 'global options' element not found for {hostname}, {port}."
+                self.passed = False
+                continue
+
+            del match['hostname']
+            del match['port']
+
+            # Now make sure job file global section matches 'global options'
+            # in JSON output
+            job_file_global = dict(config['global'])
+            for key, value in job_file_global.items():
+                if value is None:
+                    job_file_global[key] = ""
+            if job_file_global != match:
+                self.failure_reason += " 'global options' dictionary does not match global section in job file."
+                self.passed = False
+            else:
+                logging.debug("Job file global section matches 'global options' array element %s", server['client'])
+
+        if global_sections != len(self.json_data['global options']):
+            self.failure_reason = f"{self.failure_reason} mismatched number of elements in 'global options' array."
+            self.passed = False
+        else:
+            logging.debug("%d elements in global options array as expected", global_sections)
+
+
+class ClientServerTestAllClientsLat(ClientServerTest):
+    """
+    Client/sever test class.
+    Make sure the "All clients" job has latency percentile data.
+    Assumes that a job named 'test' is run with no global section.
+    Only check read data.
+    """
+
+    def check_result(self):
+        super().check_result()
+
+        config = configparser.ConfigParser(allow_no_value=True)
+        config.read(self.fio_opts['servers'][0]['jobfile'])
+
+        lats = { 'clat': True, 'lat': False, 'slat': False }
+        for key in lats:
+            opt = f"{key}_percentiles"
+            if opt in config.options('test'):
+                lats[key] = config.getboolean('test', opt)
+                logging.debug("%s set to %s", opt, lats[key])
+
+        all_clients = None
+        client_stats = self.json_data['client_stats']
+        for client in client_stats:
+            if client['jobname'] == "All clients":
+                all_clients = client
+                break
+
+        if not all_clients:
+            self.failure_reason = f"{self.failure_reason} Could not find 'All clients' output"
+            self.passed = False
+
+        for key, value in lats.items():
+            if value:
+                if 'percentile' not in all_clients['read'][f"{key}_ns"]:
+                    self.failure_reason += f" {key} percentiles not found"
+                    self.passed = False
+                    break
+
+                logging.debug("%s percentiles found as expected", key)
+            else:
+                if 'percentile' in all_clients['read'][f"{key}_ns"]:
+                    self.failure_reason += f" {key} percentiles found unexpectedly"
+                    self.passed = False
+                    break
+
+                logging.debug("%s percentiles appropriately not found", key)
+
+
+
+TEST_LIST = [
+    {   # Smoke test
+        "test_id": 1,
+        "fio_opts": {
+            "output-format": "json",
+            "servers": [
+                    {
+                        "client" : 0, # index into the SERVER_LIST array
+                        "jobfile": "test01.fio",
+                    },
+                ]
+            },
+        "test_class": ClientServerTest,
+    },
+    {   # try another client
+        "test_id": 2,
+        "fio_opts": {
+            "output-format": "json",
+            "servers": [
+                    {
+                        "client" : 1,
+                        "jobfile": "test01.fio",
+                    },
+                ]
+            },
+        "test_class": ClientServerTest,
+    },
+    {   # single client global section
+        "test_id": 3,
+        "fio_opts": {
+            "output-format": "json",
+            "servers": [
+                    {
+                        "client" : 2,
+                        "jobfile": "test01.fio",
+                    },
+                ]
+            },
+        "test_class": ClientServerTestGlobalSingle,
+    },
+    {   # single client no global section
+        "test_id": 4,
+        "fio_opts": {
+            "output-format": "json",
+            "servers": [
+                    {
+                        "client" : 3,
+                        "jobfile": "test04-noglobal.fio",
+                    },
+                ]
+            },
+        "test_class": ClientServerTestGlobalSingle,
+    },
+    {   # multiple clients, some with global, some without
+        "test_id": 5,
+        "fio_opts": {
+            "output-format": "json",
+            "servers": [
+                    {
+                        "client" : 0,
+                        "jobfile": "test04-noglobal.fio",
+                    },
+                    {
+                        "client" : 1,
+                        "jobfile": "test01.fio",
+                    },
+                    {
+                        "client" : 2,
+                        "jobfile": "test04-noglobal.fio",
+                    },
+                    {
+                        "client" : 3,
+                        "jobfile": "test01.fio",
+                    },
+                ]
+            },
+        "test_class": ClientServerTestGlobalMultiple,
+    },
+    {   # multiple clients, all with global sections
+        "test_id": 6,
+        "fio_opts": {
+            "output-format": "json",
+            "servers": [
+                    {
+                        "client" : 0,
+                        "jobfile": "test01.fio",
+                    },
+                    {
+                        "client" : 1,
+                        "jobfile": "test01.fio",
+                    },
+                    {
+                        "client" : 2,
+                        "jobfile": "test01.fio",
+                    },
+                    {
+                        "client" : 3,
+                        "jobfile": "test01.fio",
+                    },
+                ]
+            },
+        "test_class": ClientServerTestGlobalMultiple,
+    },
+    {   # Enable submission latency
+        "test_id": 7,
+        "fio_opts": {
+            "output-format": "json",
+            "servers": [
+                    {
+                        "client" : 0,
+                        "jobfile": "test07-slat.fio",
+                    },
+                    {
+                        "client" : 1,
+                        "jobfile": "test07-slat.fio",
+                    },
+                ]
+            },
+        "test_class": ClientServerTestAllClientsLat,
+    },
+    {   # Enable completion latency
+        "test_id": 8,
+        "fio_opts": {
+            "output-format": "json",
+            "servers": [
+                    {
+                        "client" : 0,
+                        "jobfile": "test08-clat.fio",
+                    },
+                    {
+                        "client" : 1,
+                        "jobfile": "test08-clat.fio",
+                    },
+                ]
+            },
+        "test_class": ClientServerTestAllClientsLat,
+    },
+    {   # Enable total latency
+        "test_id": 9,
+        "fio_opts": {
+            "output-format": "json",
+            "servers": [
+                    {
+                        "client" : 0,
+                        "jobfile": "test09-lat.fio",
+                    },
+                    {
+                        "client" : 1,
+                        "jobfile": "test09-lat.fio",
+                    },
+                ]
+            },
+        "test_class": ClientServerTestAllClientsLat,
+    },
+    {   # Disable completion latency
+        "test_id": 10,
+        "fio_opts": {
+            "output-format": "json",
+            "servers": [
+                    {
+                        "client" : 0,
+                        "jobfile": "test10-noclat.fio",
+                    },
+                    {
+                        "client" : 1,
+                        "jobfile": "test10-noclat.fio",
+                    },
+                ]
+            },
+        "test_class": ClientServerTestAllClientsLat,
+    },
+    {   # Enable submission, completion, total latency
+        "test_id": 11,
+        "fio_opts": {
+            "output-format": "json",
+            "servers": [
+                    {
+                        "client" : 0,
+                        "jobfile": "test11-alllat.fio",
+                    },
+                    {
+                        "client" : 1,
+                        "jobfile": "test11-alllat.fio",
+                    },
+                ]
+            },
+        "test_class": ClientServerTestAllClientsLat,
+    },
+]
+
+
+def parse_args():
+    """Parse command-line arguments."""
+
+    parser = argparse.ArgumentParser()
+    parser.add_argument('-d', '--debug', help='Enable debug messages', action='store_true')
+    parser.add_argument('-f', '--fio', help='path to file executable (e.g., ./fio)')
+    parser.add_argument('-a', '--artifact-root', help='artifact root directory')
+    parser.add_argument('-s', '--skip', nargs='+', type=int,
+                        help='list of test(s) to skip')
+    parser.add_argument('-o', '--run-only', nargs='+', type=int,
+                        help='list of test(s) to run, skipping all others')
+    args = parser.parse_args()
+
+    return args
+
+
+def start_servers(fio_path, servers=SERVER_LIST):
+    """Start servers for our tests."""
+
+    for server in servers:
+        tmpfile = tempfile.mktemp()
+        cmd = [fio_path, f"--server={server}", f"--daemonize={tmpfile}"]
+        cmd_result = subprocess.run(cmd, capture_output=True, check=False,
+                                   encoding=locale.getpreferredencoding())
+        if cmd_result.returncode != 0:
+            logging.error("Unable to start server on %s: %s", server, cmd_result.stderr)
+            return False
+
+        logging.debug("Started server %s", server)
+        PIDFILE_LIST.append(tmpfile)
+
+    return True
+
+
+def stop_servers(pidfiles=PIDFILE_LIST):
+    """Stop running fio server invocations."""
+
+    for pidfile in pidfiles:
+        with open(pidfile, "r", encoding=locale.getpreferredencoding()) as file:
+            pid = file.read().strip()
+
+        cmd = ["kill", f"{pid}"]
+        cmd_result = subprocess.run(cmd, capture_output=True, check=False,
+                                   encoding=locale.getpreferredencoding())
+        if cmd_result.returncode != 0:
+            logging.error("Unable to kill server with PID %s: %s", pid, cmd_result.stderr)
+            return False
+        logging.debug("Sent stop signal to PID %s", pid)
+
+    return True
+
+
+def main():
+    """Run tests for fio's client/server mode."""
+
+    args = parse_args()
+
+    if args.debug:
+        logging.basicConfig(level=logging.DEBUG)
+    else:
+        logging.basicConfig(level=logging.INFO)
+
+    artifact_root = args.artifact_root if args.artifact_root else \
+        f"client_server-test-{time.strftime('%Y%m%d-%H%M%S')}"
+    os.mkdir(artifact_root)
+    print(f"Artifact directory is {artifact_root}")
+
+    if args.fio:
+        fio_path = str(Path(args.fio).absolute())
+    else:
+        fio_path = os.path.join(os.path.dirname(__file__), '../fio')
+    print(f"fio path is {fio_path}")
+
+    if not start_servers(fio_path):
+        sys.exit(1)
+    print("Servers started")
+
+    job_path = os.path.join(os.path.dirname(__file__), "client_server")
+    for test in TEST_LIST:
+        opts = test['fio_opts']
+        for server in opts['servers']:
+            server['client'] = SERVER_LIST[server['client']]
+            server['jobfile'] = os.path.join(job_path, server['jobfile'])
+
+    test_env = {
+              'fio_path': fio_path,
+              'fio_root': str(Path(__file__).absolute().parent.parent),
+              'artifact_root': artifact_root,
+              'basename': 'client_server',
+              }
+
+    _, failed, _ = run_fio_tests(TEST_LIST, test_env, args)
+
+    stop_servers()
+    sys.exit(failed)
+
+if __name__ == '__main__':
+    main()
diff --git a/t/client_server/test01.fio b/t/client_server/test01.fio
new file mode 100644
index 00000000..98927f56
--- /dev/null
+++ b/t/client_server/test01.fio
@@ -0,0 +1,14 @@
+[global]
+ioengine=null
+time_based
+runtime=3s
+filesize=1T
+
+[test1]
+description=test1
+
+[test2]
+description=test2
+
+[test3]
+description=test3
diff --git a/t/client_server/test04-noglobal.fio b/t/client_server/test04-noglobal.fio
new file mode 100644
index 00000000..1353f889
--- /dev/null
+++ b/t/client_server/test04-noglobal.fio
@@ -0,0 +1,20 @@
+[test1]
+description=test1
+ioengine=null
+time_based
+runtime=3s
+filesize=1T
+
+[test2]
+description=test2
+ioengine=null
+time_based
+runtime=3s
+filesize=1T
+
+[test3]
+description=test3
+ioengine=null
+time_based
+runtime=3s
+filesize=1T
diff --git a/t/client_server/test07-slat.fio b/t/client_server/test07-slat.fio
new file mode 100644
index 00000000..595c66b3
--- /dev/null
+++ b/t/client_server/test07-slat.fio
@@ -0,0 +1,7 @@
+[test]
+ioengine=null
+iodepth=2
+filesize=1T
+time_based
+runtime=3s
+slat_percentiles=1
diff --git a/t/client_server/test08-clat.fio b/t/client_server/test08-clat.fio
new file mode 100644
index 00000000..ef6ea512
--- /dev/null
+++ b/t/client_server/test08-clat.fio
@@ -0,0 +1,7 @@
+[test]
+ioengine=null
+iodepth=2
+filesize=1T
+time_based
+runtime=3s
+clat_percentiles=1
diff --git a/t/client_server/test09-lat.fio b/t/client_server/test09-lat.fio
new file mode 100644
index 00000000..87ef9093
--- /dev/null
+++ b/t/client_server/test09-lat.fio
@@ -0,0 +1,7 @@
+[test]
+ioengine=null
+iodepth=2
+filesize=1T
+time_based
+runtime=3s
+lat_percentiles=1
diff --git a/t/client_server/test10-noclat.fio b/t/client_server/test10-noclat.fio
new file mode 100644
index 00000000..a27213e6
--- /dev/null
+++ b/t/client_server/test10-noclat.fio
@@ -0,0 +1,7 @@
+[test]
+ioengine=null
+iodepth=2
+filesize=1T
+time_based
+runtime=3s
+clat_percentiles=0
diff --git a/t/client_server/test11-alllat.fio b/t/client_server/test11-alllat.fio
new file mode 100644
index 00000000..3404c2db
--- /dev/null
+++ b/t/client_server/test11-alllat.fio
@@ -0,0 +1,9 @@
+[test]
+ioengine=null
+iodepth=2
+filesize=1T
+time_based
+runtime=3s
+slat_percentiles=1
+clat_percentiles=1
+lat_percentiles=1
diff --git a/t/fiotestlib.py b/t/fiotestlib.py
index 466e482d..61adca14 100755
--- a/t/fiotestlib.py
+++ b/t/fiotestlib.py
@@ -322,19 +322,16 @@ class FioJobCmdTest(FioExeTest):
         #
         # Sometimes fio informational messages are included at the top of the
         # JSON output, especially under Windows. Try to decode output as JSON
-        # data, lopping off up to the first four lines
+        # data, skipping everything until the first {
         #
         lines = file_data.splitlines()
-        for i in range(5):
-            file_data = '\n'.join(lines[i:])
-            try:
-                self.json_data = json.loads(file_data)
-            except json.JSONDecodeError:
-                continue
-            else:
-                return True
+        file_data = '\n'.join(lines[lines.index("{"):])
+        try:
+            self.json_data = json.loads(file_data)
+        except json.JSONDecodeError:
+            return False
 
-        return False
+        return True
 
     @staticmethod
     def check_empty(job):
diff --git a/t/run-fio-tests.py b/t/run-fio-tests.py
index 384b6871..4ab670de 100755
--- a/t/run-fio-tests.py
+++ b/t/run-fio-tests.py
@@ -1081,6 +1081,14 @@ TEST_LIST = [
         'success':          SUCCESS_DEFAULT,
         'requirements':     [Requirements.linux, Requirements.nvmecdev],
     },
+    {
+        'test_id':          1016,
+        'test_class':       FioExeTest,
+        'exe':              't/client_server.py',
+        'parameters':       ['-f', '{fio_path}'],
+        'success':          SUCCESS_DEFAULT,
+        'requirements':     [Requirements.linux],
+    },
 ]
 
 




[Index of Archives]     [Linux Kernel]     [Linux SCSI]     [Linux IDE]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux