t/nvmept_trim: increase transfer size for some tests
[fio.git] / t / sgunmap-test.py
1 #!/usr/bin/python2.7
2 # Note: this script is python2 and python 3 compatible.
3 #
4 # sgunmap-test.py
5 #
6 # Limited functonality test for trim workloads using fio's sg ioengine
7 # This checks only the three sets of reported iodepths
8 #
9 # !!!WARNING!!!
10 # This script carries out destructive tests. Be sure that
11 # there is no data you want to keep on the supplied devices.
12 #
13 # USAGE
14 # sgunmap-test.py char-device block-device fio-executable
15 #
16 # EXAMPLE
17 # t/sgunmap-test.py /dev/sg1 /dev/sdb ./fio
18 #
19 # REQUIREMENTS
20 # Python 2.6+
21 #
22 # TEST MATRIX
23 # For both char-dev and block-dev these are the expected
24 # submit/complete IO depths
25 #
26 #                       blockdev                chardev
27 #                       iodepth                 iodepth
28 # R QD1                 sub/comp: 1-4=100%      sub/comp: 1-4=100%
29 # W QD1                 sub/comp: 1-4=100%      sub/comp: 1-4=100%
30 # T QD1                 sub/comp: 1-4=100%      sub/comp: 1-4=100%
31 #
32 # R QD16, batch8        sub/comp: 1-4=100%      sub/comp: 1-4=100%
33 # W QD16, batch8        sub/comp: 1-4=100%      sub/comp: 1-4=100%
34 # T QD16, batch8        sub/comp: 1-4=100%      sub/comp: 5-8=100%
35 #
36 # R QD16, batch16       sub/comp: 1-4=100%      sub/comp: 1-4=100%
37 # W QD16, batch16       sub/comp: 1-4=100%      sub/comp: 1-4=100%
38 # T QD16, batch16       sub/comp: 1-4=100%      sub/comp: 9-16=100%
39 #
40
41 from __future__ import absolute_import
42 from __future__ import print_function
43 import sys
44 import json
45 import argparse
46 import traceback
47 import subprocess
48
49
50 def parse_args():
51     parser = argparse.ArgumentParser()
52     parser.add_argument('chardev',
53                         help='character device target (e.g., /dev/sg0)')
54     parser.add_argument('blockdev',
55                         help='block device target (e.g., /dev/sda)')
56     parser.add_argument('fio',
57                         help='path to fio executable (e.g., ./fio)')
58     args = parser.parse_args()
59
60     return args
61
62 #
63 # With block devices,
64 #     iodepth = 1 always
65 #     submit = complete = 1-4 always
66 # With character devices,
67 # RW
68 #     iodepth = qd
69 #     submit = 1-4
70 #     complete = 1-4 except for the IOs in flight
71 #                when the job is ending
72 # T
73 #     iodepth = qd
74 #     submit = qdbatch
75 #     complete = qdbatch except for the IOs in flight
76 #                when the job is ending
77 #
78
79
80 def check(jsondata, parameters, block, qd, qdbatch, rw):
81     iodepth = jsondata['iodepth_level']
82     submit = jsondata['iodepth_submit']
83     complete = jsondata['iodepth_complete']
84
85     try:
86         if block:
87             assert iodepth['1'] == 100.0
88             assert submit['4'] == 100.0
89             assert complete['4'] == 100.0
90         elif 'read' in rw or 'write' in rw:
91             assert iodepth[str(qd)] > 99.9
92             assert submit['4'] == 100.0
93             assert complete['4'] > 99.9
94         else:
95             if qdbatch <= 4:
96                 batchkey = '4'
97             elif qdbatch > 64:
98                 batchkey = '>=64'
99             else:
100                 batchkey = str(qdbatch)
101             if qd >= 64:
102                 qdkey = ">=64"
103             else:
104                 qdkey = str(qd)
105             assert iodepth[qdkey] > 99
106             assert submit[batchkey] == 100.0
107             assert complete[batchkey] > 99
108     except AssertionError:
109         print("Assertion failed")
110         traceback.print_exc()
111         print(jsondata)
112         return
113
114     print("**********passed*********")
115
116
117 def runalltests(args, qd, batch):
118     block = False
119     for dev in [args.chardev, args.blockdev]:
120         for rw in ["randread", "randwrite", "randtrim"]:
121             parameters = ["--name=test",
122                            "--time_based",
123                            "--runtime=30s",
124                            "--output-format=json",
125                            "--ioengine=sg",
126                            "--rw={0}".format(rw),
127                            "--filename={0}".format(dev),
128                            "--iodepth={0}".format(qd),
129                            "--iodepth_batch={0}".format(batch)]
130
131             print(parameters)
132             output = subprocess.check_output([args.fio] + parameters)
133             jsondata = json.loads(output)
134             jobdata = jsondata['jobs'][0]
135             check(jobdata, parameters, block, qd, batch, rw)
136         block = True
137
138
139 def runcdevtrimtest(args, qd, batch):
140     parameters = ["--name=test",
141                    "--time_based",
142                    "--runtime=30s",
143                    "--output-format=json",
144                    "--ioengine=sg",
145                    "--rw=randtrim",
146                    "--filename={0}".format(args.chardev),
147                    "--iodepth={0}".format(qd),
148                    "--iodepth_batch={0}".format(batch)]
149
150     print(parameters)
151     output = subprocess.check_output([args.fio] + parameters)
152     jsondata = json.loads(output)
153     jobdata = jsondata['jobs'][0]
154     check(jobdata, parameters, False, qd, batch, "randtrim")
155
156
157 if __name__ == '__main__':
158     args = parse_args()
159
160     runcdevtrimtest(args, 32, 2)
161     runcdevtrimtest(args, 32, 4)
162     runcdevtrimtest(args, 32, 8)
163     runcdevtrimtest(args, 64, 4)
164     runcdevtrimtest(args, 64, 8)
165     runcdevtrimtest(args, 64, 16)
166     runcdevtrimtest(args, 128, 8)
167     runcdevtrimtest(args, 128, 16)
168     runcdevtrimtest(args, 128, 32)
169
170     runalltests(args, 1, 1)
171     runalltests(args, 16, 2)
172     runalltests(args, 16, 16)