3 # Copyright (c) 2015 Google, Inc.
4 # Copyright (c) 2015 Linaro, Ltd.
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions are met:
9 # 1. Redistributions of source code must retain the above copyright notice,
10 # this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright notice,
12 # this list of conditions and the following disclaimer in the documentation
13 # and/or other materials provided with the distribution.
14 # 3. Neither the name of the copyright holder nor the names of its
15 # contributors may be used to endorse or promote products derived from this
16 # software without specific prior written permission.
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 from __future__ import print_function
36 dict = {'ping': '2', 'transfer': '3', 'sink': '4'}
43 print('Usage: looptest TEST SIZE ITERATIONS PATH\n\n'
44 ' Run TEST for a number of ITERATIONS with operation data SIZE bytes\n'
45 ' TEST may be \'ping\' \'transfer\' or \'sink\'\n'
46 ' SIZE indicates the size of transfer <= greybus max payload bytes\n'
47 ' ITERATIONS indicates the number of times to execute TEST at SIZE bytes\n'
48 ' Note if ITERATIONS is set to zero then this utility will\n'
49 ' initiate an infinite (non terminating) test and exit\n'
50 ' without logging any metrics data\n'
51 ' PATH indicates the sysfs path for the loopback greybus entries e.g.\n'
52 ' /sys/bus/greybus/devices/endo0:1:1:1:1/\n'
54 ' looptest transfer 128 10000\n'
55 ' looptest ping 0 128\n'
56 ' looptest sink 2030 32768\n'
57 .format(sys.argv[0]), file=sys.stderr)
61 def read_sysfs_int(path):
68 print("I/O error({0}): {1}".format(e.errno, e.strerror))
69 print("Invalid path %s" % path)
71 def write_sysfs_val(path, val):
77 print("I/O error({0}): {1}".format(e.errno, e.strerror))
78 print("Invalid path %s" % path)
80 def log_csv(test_name, size, iteration_max, sys_pfx):
81 # file name will test_name_size_iteration_max.csv
82 # every time the same test with the same parameters is run we will then
83 # append to the same CSV with datestamp - representing each test dataset
84 fname = test_name + '_' + size + '_' + str(iteration_max) + '.csv'
88 date = str(datetime.datetime.now())
89 error = read_sysfs_int(sys_pfx + 'error')
90 request_min = read_sysfs_int(sys_pfx + 'requests_per_second_min')
91 request_max = read_sysfs_int(sys_pfx + 'requests_per_second_max')
92 request_avg = read_sysfs_int(sys_pfx + 'requests_per_second_avg')
93 latency_min = read_sysfs_int(sys_pfx + 'latency_min')
94 latency_max = read_sysfs_int(sys_pfx + 'latency_max')
95 latency_avg = read_sysfs_int(sys_pfx + 'latency_avg')
96 throughput_min = read_sysfs_int(sys_pfx + 'throughput_min')
97 throughput_max = read_sysfs_int(sys_pfx + 'throughput_max')
98 throughput_avg = read_sysfs_int(sys_pfx + 'throughput_avg')
101 request_jitter = request_max - request_min
102 latency_jitter = latency_max - latency_min
103 throughput_jitter = throughput_max - throughput_min
105 # append data set to file
106 with open(fname, 'a') as csvf:
107 row = csv.writer(csvf, delimiter=",", quotechar="'",
108 quoting=csv.QUOTE_MINIMAL)
109 row.writerow([date, test_name, size, iteration_max, error,
110 request_min, request_max, request_avg, request_jitter,
111 latency_min, latency_max, latency_avg, latency_jitter,
112 throughput_min, throughput_max, throughput_avg, throughput_jitter])
114 print("I/O error({0}): {1}".format(e.errno, e.strerror))
116 def loopback_run(test_name, size, iteration_max, sys_pfx):
117 test_id = dict[test_name]
119 # Terminate any currently running test
120 write_sysfs_val(sys_pfx + 'type', '0')
121 # Set parameter for no wait between messages
122 write_sysfs_val(sys_pfx + 'ms_wait', '0')
124 write_sysfs_val(sys_pfx + 'size', size)
126 write_sysfs_val(sys_pfx + 'iteration_max', str(iteration_max))
127 # Initiate by setting loopback operation type
128 write_sysfs_val(sys_pfx + 'type', test_id)
131 if iteration_max == 0:
132 print ("Infinite test initiated CSV won't be logged\n")
138 # get current count bail out if it hasn't changed
139 iteration_count = read_sysfs_int(sys_pfx + 'iteration_count')
140 if previous == iteration_count:
143 elif iteration_count == iteration_max:
145 previous = iteration_count
147 print('%02d%% complete %d of %d ' %
148 (100 * iteration_count / iteration_max,
149 iteration_count, iteration_max))
152 print ('\nError executing test\n')
154 log_csv(test_name, size, iteration_max, sys_pfx)
155 except ValueError as ve:
156 print("Error: %s " % format(e.strerror), file=sys.stderr)
160 if len(sys.argv) < 5:
163 if sys.argv[1] in dict.keys():
164 loopback_run(sys.argv[1], sys.argv[2], int(sys.argv[3]), sys.argv[4])
167 if __name__ == '__main__':