1########################################################################## 2# Copyright (c) 2016, ETH Zurich. 3# All rights reserved. 4# 5# This file is distributed under the terms in the attached LICENSE file. 6# If you do not find this file, copies can be found by writing to: 7# ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 8########################################################################## 9 10import re, datetime 11import debug, tests 12from common import TestCommon, TimeoutError 13from results import RowResults, PassFailResult 14 15BLK_TEST_TIMEOUT = datetime.timedelta(minutes=8) # XXX: tilsiter1 needs a bit longer (slow write speeds?) 16 17bandwidth = { 18 'tilsiter1': { 19 'read': { 20 512: 32.67, 21 1024: 50.08, 22 2048: 90.15, 23 4096: 154.21, 24 8192: 236.92, 25 16384: 318.05, 26 32768: 379.68, 27 65536: 416.99, 28 131072: 428.64, 29 262144: 439.88, 30 524288: 495.27, 31 1048576: 528.16, 32 2097152: 546.71 33 }, 34 'write': { 35 512: 5.41, 36 1024: 1.70, 37 2048: 3.32, 38 4096: 6.68, 39 8192: 26.50, 40 16384: 49.92, 41 32768: 88.74, 42 65536: 143.63, 43 131072: 212.54, 44 262144: 281.08, 45 524288: 377.55, 46 1048576: 436.48, 47 2097152: 49.25, 48 }, 49 }, 50 51 'vacherin': { 52 'read': { 53 512: 15.24, 54 1024: 15.35, 55 2048: 30.32, 56 4096: 57.29, 57 8192: 102.01, 58 16384: 167.28, 59 32768: 237.24, 60 65536: 316.74, 61 131072: 361.41, 62 262144: 405.19, 63 524288: 490.97, 64 1048576: 415.05, 65 2097152: 424.57 66 }, 67 'write': { 68 512: 15.20, 69 1024: 12.55, 70 2048: 26.87, 71 4096: 51.89, 72 8192: 93.21, 73 16384: 152.43, 74 32768: 213.55, 75 65536: 296.29, 76 131072: 365.72, 77 262144: 412.98, 78 524288: 440.78, 79 1048576: 454.21, 80 2097152: 462.02, 81 } 82 }, 83 84 'babybel1': { 85 'read': { 86 512: 43.42, 87 1024: 25.56, 88 2048: 31.16, 89 4096: 55.63, 90 8192: 85.02, 91 16384: 114.35, 92 32768: 105.40, 93 65536: 147.15, 94 131072: 414.57, 95 262144: 482.58, 96 524288: 515.73, 97 1048576: 534.20, 98 2097152: 544.49, 99 4194304: 549.79, 100 }, 101 'write': { 102 512: 42.52, 103 1024: 38.18, 104 2048: 41.29, 105 4096: 75.26, 106 8192: 221.12, 107 16384: 267.90, 108 32768: 426.09, 109 65536: 494.36, 110 131072: 516.22, 111 262144: 526.34, 112 524288: 533.67, 113 1048576: 533.67, 114 2097152: 522.25, 115 4194304: 523.27 116 }, 117 }, 118 119 'babybel2': { 120 'read': { 121 512: 43.32, 122 1024: 14.08, 123 2048: 31.10, 124 4096: 55.14, 125 8192: 83.53, 126 16384: 108.78, 127 32768: 95.90, 128 65536: 115.02, 129 131072: 159.26, 130 262144: 427.62, 131 524288: 514.74, 132 1048576: 533.14, 133 2097152: 503.16 134 }, 135 'write': { 136 512: 43.09, 137 1024: 22.52, 138 2048: 41.00, 139 4096: 75.28, 140 8192: 220.75, 141 16384: 268.17, 142 32768: 416.18, 143 65536: 497.10, 144 131072: 519.22, 145 262144: 529.46, 146 524288: 534.73, 147 1048576: 537.95, 148 2097152: 518.22, 149 }, 150 }, 151 152 'babybel3': { 153 'read': { 154 512: 43.53, 155 1024: 25.71, 156 2048: 26.38, 157 4096: 55.21, 158 8192: 83.35, 159 16384: 107.88, 160 32768: 95.66, 161 65536: 115.43, 162 131072: 159.21, 163 262144: 428.30, 164 524288: 514.24, 165 1048576: 532.87, 166 2097152: 504.82, 167 }, 168 'write': { 169 512: 42.86, 170 1024: 38.40, 171 2048: 41.43, 172 4096: 75.83, 173 8192: 225.01, 174 16384: 265.78, 175 32768: 428.13, 176 65536: 495.27, 177 131072: 513.26, 178 262144: 528.42, 179 524288: 532.61, 180 1048576: 532.61, 181 2097152: 525.31, 182 } 183 }, 184 185 'babybel4': { 186 'read': { 187 512: 43.46, 188 1024: 25.73, 189 2048: 31.17, 190 4096: 55.25, 191 8192: 83.51, 192 16384: 108.35, 193 32768: 95.72, 194 65536: 115.08, 195 131072: 159.78, 196 262144: 381.98, 197 524288: 492.54, 198 1048576: 512.53, 199 2097152: 451.34 200 }, 201 'write': { 202 512: 42.49, 203 1024: 38.40, 204 2048: 41.47, 205 4096: 76.96, 206 8192: 225.20, 207 16384: 265.51, 208 32768: 430.19, 209 65536: 496.18, 210 131072: 517.22, 211 262144: 529.46, 212 524288: 534.73, 213 1048576: 534.73, 214 2097152: 524.29 215 } 216 } 217} 218 219class BlkTests(TestCommon): 220 221 def __init__(self, options): 222 super(BlkTests, self).__init__(options) 223 224 def get_module_name(self): 225 return "ahci_test" 226 227 def boot(self, *args): 228 super(BlkTests, self).boot(*args) 229 self.set_timeout(BLK_TEST_TIMEOUT) 230 231 def get_modules(self, build, machine): 232 self.machine = machine.name 233 modules = super(BlkTests, self).get_modules(build, machine) 234 modules.add_module_arg("kaluga","add_device_db=device_db_ahcitest") 235 modules.add_module(self.get_module_name(), ["auto", self.OP]) 236 237 return modules 238 239 def get_finish_string(self): 240 return "AHCI testing completed." 241 242 def process_data(self, testdir, rawiter): 243 self.regex = re.compile(self.REGEX) 244 result = RowResults(['op', 'buffer', 'block', 'bandwidth']) 245 if not bandwidth.has_key(self.machine): 246 result.mark_failed('No data about this disk, please set the initial performance values.') 247 return result 248 249 matches = 0 250 num_fail = 0 251 for line in rawiter: 252 match = self.regex.match(line) 253 if match: 254 matches += 1 255 256 buffer_size, bs, bw = match.groups() 257 buffer_size = int(buffer_size) 258 bs = int(bs) 259 bw = float(bw) 260 operation = self.OP.lower() 261 if not bandwidth[self.machine].has_key(operation): 262 result.mark_failed('No data about this benchmark, please set the initial performance values.') 263 return result 264 if not bandwidth[self.machine][operation].has_key(bs): 265 result.mark_failed('No data for {} with bs {}.'.format(operation, bs)) 266 return result 267 268 lower_bound = bandwidth[self.machine][operation][bs] * (1 - 0.25) 269 upper_bound = bandwidth[self.machine][operation][bs] * (1 + 0.25) 270 271 result.add_row((operation, buffer_size, bs, bw)) 272 if bw <= lower_bound: 273 error = "{} for {} bytes blocks not within expected range (was {}, should be >= {}).".format(operation, bs, bw, lower_bound) 274 debug.log(error) 275 num_fail+= 1; 276 if num_fail > 1: 277 result.mark_failed(reason=error) 278 elif bw >= upper_bound: 279 error = "Achieved {} bandwidth for {} bytes blocks was better ({}) than expected ({}).".format(operation, bs, bw, upper_bound) 280 debug.log(error) 281 debug.log("This is good, if you can explain it! Adjust the bandwidth numbers in blk_tests.py and re-run the test.") 282 num_fail+= 1 283 if num_fail > 1: 284 result.mark_failed(reason=error) 285 else: 286 pass 287 288 if line.startswith("AHCI testing completed.") and matches > 0: 289 return result 290 291 result.mark_failed('Did not see end of test or got no bandwidth numbers.') 292 return result 293 294@tests.add_test 295class BlkAhciWriteBWTest(BlkTests): 296 ''' AHCI Driver Write Bandwidth Test''' 297 name = "blk_read_test" 298 OP = "read" 299 REGEX = r"\[ahci_perf_sequential\] Read sequential size (\d+) bs (\d+): (\d+\.\d+) \[MB/s\]" 300 301@tests.add_test 302class BlkAhciReadBWTest(BlkTests): 303 ''' AHCI Driver Read Bandwidth Test''' 304 name = "blk_write_test" 305 OP = "write" 306 REGEX = r"\[ahci_perf_sequential\] Write sequential size (\d+) bs (\d+): (\d+\.\d+) \[MB/s\]" 307 308@tests.add_test 309class BlkAhciVerifyTest(BlkTests): 310 ''' AHCI Driver Correctness test ''' 311 name = "blk_verify_test" 312 OP = "verify" 313 REGEX = r"\[ahci_verify_sequential\] SUCCESS \((\d+) (\d+)\)" 314 TESTS = 14 315 316 def process_data(self, testdir, rawiter): 317 self.regex = re.compile(self.REGEX) 318 319 matches = 0 320 for line in rawiter: 321 match = self.regex.match(line) 322 if match: 323 matches += 1 324 325 if matches == self.TESTS: 326 return PassFailResult(True) 327 elif matches < self.TESTS: 328 return PassFailResult(False, "Some block/buffer size checks did not report back with SUCCESS.") 329 elif matches > self.TESTS: 330 return PassFailResult(False, "Got more SUCCESS lines than expected. If you changed the test you may need to increase self.TESTS.") 331 else: 332 assert "Should not come here" 333