machine_manager_unittest.py revision 5ea9f006b5de0d882d5b51da243806b7cac69938
1#!/usr/bin/python 2 3# Copyright 2012 Google Inc. All Rights Reserved. 4 5"""Unittest for machine_manager.""" 6import os.path 7import time 8import hashlib 9 10import mock 11import unittest 12 13import label 14import lock_machine 15import machine_manager 16import image_checksummer 17 18from benchmark import Benchmark 19from benchmark_run import MockBenchmarkRun 20from utils import command_executer 21from utils import logger 22 23class MyMachineManager(machine_manager.MachineManager): 24 25 def __init__(self, chromeos_root): 26 super(MyMachineManager, self).__init__(chromeos_root, 0, "average", 27 lock_machine.Machine.LOCKS_DIR) 28 29 def _TryToLockMachine(self, cros_machine): 30 self._machines.append(cros_machine) 31 cros_machine.checksum = "" 32 33 def AddMachine(self, machine_name): 34 with self._lock: 35 for m in self._all_machines: 36 assert m.name != machine_name, "Tried to double-add %s" % machine_name 37 cm = machine_manager.MockCrosMachine(machine_name, self.chromeos_root, 38 "average") 39 assert cm.machine_checksum, ("Could not find checksum for machine %s" % 40 machine_name) 41 self._all_machines.append(cm) 42 43CHROMEOS_ROOT = "/tmp/chromeos-root" 44MACHINE_NAMES = ["lumpy1", "lumpy2", "lumpy3", "daisy1", "daisy2"] 45LABEL_LUMPY = label.MockLabel("lumpy", "lumpy_chromeos_image", CHROMEOS_ROOT, "lumpy", 46 ["lumpy1", "lumpy2", "lumpy3", "lumpy4"], 47 "", "", False, "") 48LABEL_MIX = label.MockLabel("mix", "chromeos_image", CHROMEOS_ROOT, "mix", 49 ["daisy1", "daisy2", "lumpy3", "lumpy4"], 50 "", "", False, "") 51 52 53class MachineManagerTest(unittest.TestCase): 54 55 mock_cmd_exec = mock.Mock(spec=command_executer.CommandExecuter) 56 57 mock_logger = mock.Mock(spec=logger.Logger) 58 59 mock_lumpy1 = mock.Mock(spec=machine_manager.CrosMachine) 60 mock_lumpy2 = mock.Mock(spec=machine_manager.CrosMachine) 61 mock_lumpy3 = mock.Mock(spec=machine_manager.CrosMachine) 62 mock_daisy1 = mock.Mock(spec=machine_manager.CrosMachine) 63 mock_daisy2 = mock.Mock(spec=machine_manager.CrosMachine) 64 65 @mock.patch.object (os.path, 'isdir') 66 def setUp(self, mock_isdir): 67 68 mock_isdir.return_value = True 69 self.mm = machine_manager.MachineManager("/usr/local/chromeos", 0, 70 "average", 71 lock_machine.Machine.LOCKS_DIR, 72 self.mock_cmd_exec, 73 self.mock_logger) 74 75 self.mock_lumpy1.name = 'lumpy1' 76 self.mock_lumpy2.name = 'lumpy2' 77 self.mock_lumpy3.name = 'lumpy3' 78 self.mock_daisy1.name = 'daisy1' 79 self.mock_daisy2.name = 'daisy2' 80 self.mock_lumpy1.machine_checksum = 'lumpy123' 81 self.mock_lumpy2.machine_checksum = 'lumpy123' 82 self.mock_lumpy3.machine_checksum = 'lumpy123' 83 self.mock_daisy1.machine_checksum = 'daisy12' 84 self.mock_daisy2.machine_checksum = 'daisy12' 85 self.mock_lumpy1.checksum_string = 'lumpy_checksum_str' 86 self.mock_lumpy2.checksum_string = 'lumpy_checksum_str' 87 self.mock_lumpy3.checksum_string = 'lumpy_checksum_str' 88 self.mock_daisy1.checksum_string = 'daisy_checksum_str' 89 self.mock_daisy2.checksum_string = 'daisy_checksum_str' 90 self.mock_lumpy1.cpuinfo = "lumpy_cpu_info" 91 self.mock_lumpy2.cpuinfo = "lumpy_cpu_info" 92 self.mock_lumpy3.cpuinfo = "lumpy_cpu_info" 93 self.mock_daisy1.cpuinfo = "daisy_cpu_info" 94 self.mock_daisy2.cpuinfo = "daisy_cpu_info" 95 self.mm._all_machines.append(self.mock_daisy1) 96 self.mm._all_machines.append(self.mock_daisy2) 97 self.mm._all_machines.append(self.mock_lumpy1) 98 self.mm._all_machines.append(self.mock_lumpy2) 99 self.mm._all_machines.append(self.mock_lumpy3) 100 101 102 def testGetMachines(self): 103 manager = MyMachineManager(CHROMEOS_ROOT) 104 for m in MACHINE_NAMES: 105 manager.AddMachine(m) 106 names = [m.name for m in manager.GetMachines(LABEL_LUMPY)] 107 self.assertEqual(names, ["lumpy1", "lumpy2", "lumpy3"]) 108 109 def testGetAvailableMachines(self): 110 manager = MyMachineManager(CHROMEOS_ROOT) 111 for m in MACHINE_NAMES: 112 manager.AddMachine(m) 113 for m in manager._all_machines: 114 if int(m.name[-1]) % 2: 115 manager._TryToLockMachine(m) 116 names = [m.name for m in manager.GetAvailableMachines(LABEL_LUMPY)] 117 self.assertEqual(names, ["lumpy1", "lumpy3"]) 118 119 @mock.patch.object(time, 'sleep') 120 @mock.patch.object(command_executer.CommandExecuter, 'RunCommand') 121 @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommand') 122 @mock.patch.object(image_checksummer.ImageChecksummer, 'Checksum') 123 def test_image_machine(self, mock_checksummer, mock_run_croscmd, 124 mock_run_cmd, mock_sleep): 125 126 def FakeMD5Checksum(input_str): 127 return "machine_fake_md5_checksum" 128 129 self.fake_logger_count = 0 130 self.fake_logger_msgs = [] 131 132 def FakeLogOutput(msg): 133 self.fake_logger_count += 1 134 self.fake_logger_msgs.append(msg) 135 136 def ResetValues(): 137 self.fake_logger_count = 0 138 self.fake_logger_msgs = [] 139 mock_run_cmd.reset_mock() 140 mock_run_croscmd.reset_mock() 141 mock_checksummer.reset_mock() 142 mock_sleep.reset_mock() 143 machine.checksum = "fake_md5_checksum" 144 self.mm.checksum = None 145 self.mm.num_reimages = 0 146 147 self.mock_cmd_exec.CrosRunCommand = mock_run_croscmd 148 self.mock_cmd_exec.RunCommand = mock_run_cmd 149 150 self.mm.logger.LogOutput = FakeLogOutput 151 machine = self.mock_lumpy1 152 machine._GetMD5Checksum = FakeMD5Checksum 153 machine.checksum = "fake_md5_checksum" 154 mock_checksummer.return_value = "fake_md5_checksum" 155 self.mock_cmd_exec.log_level = "verbose" 156 157 # Test 1: label.image_type == "local" 158 LABEL_LUMPY.image_type = "local" 159 self.mm.ImageMachine(machine, LABEL_LUMPY) 160 self.assertEqual(mock_run_cmd.call_count, 0) 161 self.assertEqual(mock_run_croscmd.call_count, 0) 162 self.assertEqual(mock_checksummer.call_count, 1) 163 164 #Test 2: label.image_type == "trybot" 165 ResetValues() 166 LABEL_LUMPY.image_type = "trybot" 167 mock_run_cmd.return_value = 0 168 self.mm.ImageMachine(machine, LABEL_LUMPY) 169 self.assertEqual(mock_run_cmd.call_count, 1) 170 self.assertEqual(mock_run_croscmd.call_count, 0) 171 self.assertEqual(mock_checksummer.call_count, 0) 172 image_call_args_str = mock_run_cmd.call_args[0][0] 173 image_call_args = image_call_args_str.split(' ') 174 self.assertEqual(image_call_args[0], 'python') 175 self.assertEqual(image_call_args[1].split('/')[-1], 'image_chromeos.pyc') 176 image_call_args = image_call_args[2:] 177 self.assertEqual(image_call_args, 178 [ '--chromeos_root=/tmp/chromeos-root', 179 '--image=lumpy_chromeos_image', 180 '--image_args=', '--remote=lumpy1', 181 '--logging_level=average', '--board=lumpy']) 182 183 # Test 3: label.image_type is neither local nor trybot; retval from 184 # RunCommand is 1, i.e. image_chromeos fails... 185 ResetValues() 186 LABEL_LUMPY.image_type = "other" 187 mock_run_cmd.return_value = 1 188 try: 189 self.mm.ImageMachine(machine, LABEL_LUMPY) 190 except: 191 self.assertEqual(mock_checksummer.call_count, 0) 192 self.assertEqual(mock_run_cmd.call_count, 2) 193 self.assertEqual(mock_run_croscmd.call_count, 1) 194 self.assertEqual(mock_sleep.call_count, 1) 195 image_call_args_str = mock_run_cmd.call_args[0][0] 196 image_call_args = image_call_args_str.split(' ') 197 self.assertEqual(image_call_args[0], 'python') 198 self.assertEqual(image_call_args[1].split('/')[-1], 'image_chromeos.pyc') 199 image_call_args = image_call_args[2:] 200 self.assertEqual(image_call_args, 201 [ '--chromeos_root=/tmp/chromeos-root', 202 '--image=lumpy_chromeos_image', 203 '--image_args=', '--remote=lumpy1', 204 '--logging_level=average', '--board=lumpy']) 205 self.assertEqual(mock_run_croscmd.call_args[0][0], 'reboot && exit') 206 207 # Test 4: Everything works properly. Trybot image type. 208 ResetValues() 209 LABEL_LUMPY.image_type = 'trybot' 210 mock_run_cmd.return_value = 0 211 self.mm.ImageMachine(machine, LABEL_LUMPY) 212 self.assertEqual(mock_checksummer.call_count, 0) 213 self.assertEqual(mock_run_cmd.call_count, 1) 214 self.assertEqual(mock_run_croscmd.call_count, 0) 215 self.assertEqual(mock_sleep.call_count, 0) 216 image_call_args_str = mock_run_cmd.call_args[0][0] 217 image_call_args = image_call_args_str.split(' ') 218 self.assertEqual(image_call_args[0], 'python') 219 self.assertEqual(image_call_args[1].split('/')[-1], 'image_chromeos.pyc') 220 image_call_args = image_call_args[2:] 221 self.assertEqual(image_call_args, 222 [ '--chromeos_root=/tmp/chromeos-root', 223 '--image=lumpy_chromeos_image', 224 '--image_args=', '--remote=lumpy1', 225 '--logging_level=average', '--board=lumpy']) 226 227 228 def test_compute_common_checksum(self): 229 230 self.mm.machine_checksum = {} 231 self.mm.ComputeCommonCheckSum(LABEL_LUMPY) 232 self.assertEqual(self.mm.machine_checksum['lumpy'], 'lumpy123') 233 self.assertEqual(len(self.mm.machine_checksum), 1) 234 235 self.mm.machine_checksum = {} 236 self.mm.ComputeCommonCheckSum(LABEL_MIX) 237 self.assertEqual(len(self.mm.machine_checksum), 1) 238 self.assertEqual(self.mm.machine_checksum['mix'], 'daisy12') 239 240 241 def test_compute_common_checksum_string(self): 242 self.mm.machine_checksum_string = {} 243 self.mm.ComputeCommonCheckSumString(LABEL_LUMPY) 244 self.assertEqual(len(self.mm.machine_checksum_string), 1) 245 self.assertEqual(self.mm.machine_checksum_string['lumpy'], 246 'lumpy_checksum_str') 247 248 self.mm.machine_checksum_string = {} 249 self.mm.ComputeCommonCheckSumString(LABEL_MIX) 250 self.assertEqual(len(self.mm.machine_checksum_string), 1) 251 self.assertEqual(self.mm.machine_checksum_string['mix'], 252 'daisy_checksum_str') 253 254 255 @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommand') 256 def test_try_to_lock_machine(self, mock_cros_runcmd): 257 258 self.assertRaises(self.mm._TryToLockMachine, None) 259 260 mock_cros_runcmd.return_value = [0, "false_lock_checksum", ""] 261 self.mock_cmd_exec.CrosRunCommand = mock_cros_runcmd 262 self.mm._machines = [] 263 self.mm._TryToLockMachine(self.mock_lumpy1) 264 self.assertEqual(len(self.mm._machines), 1) 265 self.assertEqual(self.mm._machines[0], self.mock_lumpy1) 266 self.assertEqual(self.mock_lumpy1.checksum, "false_lock_checksum") 267 self.assertEqual(mock_cros_runcmd.call_count, 1) 268 cmd_str = mock_cros_runcmd.call_args[0][0] 269 self.assertEqual(cmd_str, 'cat /usr/local/osimage_checksum_file') 270 args_dict = mock_cros_runcmd.call_args[1] 271 self.assertEqual(len(args_dict), 3) 272 self.assertEqual(args_dict['machine'], self.mock_lumpy1.name) 273 self.assertEqual(args_dict['chromeos_root'], '/usr/local/chromeos') 274 self.assertTrue(args_dict['return_output']) 275 276 277 @mock.patch.object(machine_manager, 'CrosMachine') 278 def test_add_machine(self, mock_machine): 279 280 mock_machine.machine_checksum = 'daisy123' 281 self.assertEqual (len(self.mm._all_machines), 5) 282 self.mm.AddMachine('daisy3') 283 self.assertEqual (len(self.mm._all_machines), 6) 284 285 self.assertRaises(Exception, self.mm.AddMachine, 'lumpy1') 286 287 288 def test_remove_machine(self): 289 self.mm._machines = self.mm._all_machines 290 self.assertTrue(self.mock_lumpy2 in self.mm._machines) 291 self.mm.RemoveMachine(self.mock_lumpy2.name) 292 self.assertFalse(self.mock_lumpy2 in self.mm._machines) 293 294 295 def test_force_same_image_to_all_machines(self): 296 self.image_log = [] 297 298 def FakeImageMachine(machine, label_arg): 299 image = label_arg.chromeos_image 300 self.image_log.append("Pushed %s onto %s" % (image, machine.name)) 301 302 def FakeSetUpChecksumInfo(): 303 pass 304 305 self.mm.ImageMachine = FakeImageMachine 306 self.mock_lumpy1.SetUpChecksumInfo = FakeSetUpChecksumInfo 307 self.mock_lumpy2.SetUpChecksumInfo = FakeSetUpChecksumInfo 308 self.mock_lumpy3.SetUpChecksumInfo = FakeSetUpChecksumInfo 309 310 self.mm.ForceSameImageToAllMachines(LABEL_LUMPY) 311 self.assertEqual(len(self.image_log), 3) 312 self.assertEqual(self.image_log[0], 313 'Pushed lumpy_chromeos_image onto lumpy1') 314 self.assertEqual(self.image_log[1], 315 'Pushed lumpy_chromeos_image onto lumpy2') 316 self.assertEqual(self.image_log[2], 317 'Pushed lumpy_chromeos_image onto lumpy3') 318 319 320 321 @mock.patch.object(image_checksummer.ImageChecksummer, 'Checksum') 322 @mock.patch.object(hashlib,'md5') 323 def test_acquire_machine(self, mock_md5, mock_checksum): 324 325 self.msgs = [] 326 self.log_fatal_msgs = [] 327 328 def FakeLock(machine): 329 self.msgs.append("Tried to lock %s" % machine.name) 330 331 def FakeLogFatal(msg): 332 self.log_fatal_msgs.append(msg) 333 334 self.mm._TryToLockMachine = FakeLock 335 self.mm.logger.LogFatal = FakeLogFatal 336 337 mock_md5.return_value = "123456" 338 mock_checksum.return_value = "fake_md5_checksum" 339 340 self.mm._machines = self.mm._all_machines 341 self.mock_lumpy1.locked = True 342 self.mock_lumpy2.locked = True 343 self.mock_lumpy3.locked = False 344 self.mock_lumpy3.checksum = "fake_md5_checksum" 345 self.mock_daisy1.locked = True 346 self.mock_daisy2.locked = False 347 self.mock_daisy2.checksum = "fake_md5_checksum" 348 349 # Test 1. Basic test. Acquire lumpy3. 350 m = self.mm.AcquireMachine(LABEL_LUMPY.chromeos_image, LABEL_LUMPY, True) 351 self.assertEqual(m, self.mock_lumpy3) 352 self.assertTrue(self.mock_lumpy3.locked) 353 self.assertEqual(mock_checksum.call_count, 1) 354 self.assertEqual(mock_md5.call_count, 0) 355 self.assertEqual(self.msgs, ['Tried to lock lumpy1', 356 'Tried to lock lumpy2', 357 'Tried to lock lumpy3']) 358 359 # Test: Not all machines are the same, throw = True 360 self.assertRaises (machine_manager.NonMatchingMachines, 361 self.mm.AcquireMachine, 362 LABEL_MIX.chromeos_image, LABEL_MIX, True) 363 364 # Test 3. Not all machines are the same, throw = False 365 self.assertEqual(len(self.log_fatal_msgs), 0) 366 m = self.mm.AcquireMachine(LABEL_MIX.chromeos_image, LABEL_MIX, False) 367 self.assertEqual(len(self.log_fatal_msgs), 1) 368 self.assertEqual(self.log_fatal_msgs[0], 369 '-- not all the machines are identical') 370 371 # Test the second return statment (machine is unlocked, has no checksum) 372 save_locked = self.mock_lumpy1.locked 373 self.mock_lumpy1.locked = False 374 self.mock_lumpy1.checksum = None 375 m = self.mm.AcquireMachine(LABEL_LUMPY.chromeos_image, LABEL_LUMPY, True) 376 self.assertEqual(m, self.mock_lumpy1) 377 self.assertTrue(self.mock_lumpy1.locked) 378 379 # Test the third return statement: 380 # - machine is unlocked 381 # - checksums don't match 382 # - current time minus release time is > 20. 383 self.mock_lumpy1.locked = False 384 self.mock_lumpy1.checksum = "123" 385 self.mock_lumpy1.released_time = time.time() - 8 386 m = self.mm.AcquireMachine(LABEL_LUMPY.chromeos_image, LABEL_LUMPY, True) 387 self.assertEqual(m, self.mock_lumpy1) 388 self.assertTrue(self.mock_lumpy1.locked) 389 390 # Test all machines are already locked. 391 m = self.mm.AcquireMachine(LABEL_LUMPY.chromeos_image, LABEL_LUMPY, True) 392 self.assertIsNone(m) 393 394 # Restore values of mock_lumpy1, so other tests succeed. 395 self.mock_lumpy1.locked = save_locked 396 self.mock_lumpy1.checksum = "123" 397 398 399 def test_get_available_machines(self): 400 self.mm._machines = self.mm._all_machines 401 402 machine_list = self.mm.GetAvailableMachines() 403 self.assertEqual(machine_list, self.mm._all_machines) 404 405 machine_list = self.mm.GetAvailableMachines(LABEL_MIX) 406 self.assertEqual(machine_list, [self.mock_daisy1, self.mock_daisy2, 407 self.mock_lumpy3]) 408 409 machine_list = self.mm.GetAvailableMachines(LABEL_LUMPY) 410 self.assertEqual(machine_list, [self.mock_lumpy1, self.mock_lumpy2, 411 self.mock_lumpy3]) 412 413 414 def test_get_machines(self): 415 machine_list = self.mm.GetMachines() 416 self.assertEqual(machine_list, self.mm._all_machines) 417 418 machine_list = self.mm.GetMachines(LABEL_MIX) 419 self.assertEqual(machine_list, [self.mock_daisy1, self.mock_daisy2, 420 self.mock_lumpy3]) 421 422 machine_list = self.mm.GetMachines(LABEL_LUMPY) 423 self.assertEqual(machine_list, [self.mock_lumpy1, self.mock_lumpy2, 424 self.mock_lumpy3]) 425 426 427 def test_release_machines(self): 428 429 self.mm._machines = [self.mock_lumpy1, self.mock_daisy2] 430 431 self.mock_lumpy1.locked = True 432 self.mock_daisy2.locked = True 433 434 self.assertTrue(self.mock_lumpy1.locked) 435 self.mm.ReleaseMachine(self.mock_lumpy1) 436 self.assertFalse(self.mock_lumpy1.locked) 437 self.assertEqual(self.mock_lumpy1.status, "Available") 438 439 self.assertTrue(self.mock_daisy2.locked) 440 self.mm.ReleaseMachine(self.mock_daisy2) 441 self.assertFalse(self.mock_daisy2.locked) 442 self.assertEqual(self.mock_daisy2.status, "Available") 443 444 # Test double-relase... 445 self.assertRaises(AssertionError, self.mm.ReleaseMachine, self.mock_lumpy1) 446 447 448 def test_cleanup(self): 449 self.mock_logger.reset_mock() 450 self.mm.Cleanup() 451 self.assertEqual(self.mock_logger.call_count, 0) 452 453 454 OUTPUT_STR = 'Machine Status:\nMachine Thread Lock Status Checksum \nlumpy1 test run True PENDING 123 \n\nlumpy3 test run False PENDING 123 \n\ndaisy2 test run True PENDING 678 ' 455 456 457 def test_as_string(self): 458 459 mock_logger = mock.Mock(spec=logger.Logger) 460 461 bench = Benchmark("page_cycler.netsim.top_10", # name 462 "page_cycler.netsim.top_10", # test_name 463 "", # test_args 464 1, # iteratins 465 False, # rm_chroot_tmp 466 "", # perf_args 467 suite="telemetry_Crosperf") # suite 468 469 test_run = MockBenchmarkRun("test run", 470 bench, 471 LABEL_LUMPY, 472 1, 473 [], 474 self.mm, 475 mock_logger, 476 "verbose", 477 "") 478 479 self.mm._machines = [self.mock_lumpy1, self.mock_lumpy2, self.mock_lumpy3, 480 self.mock_daisy1, self.mock_daisy2] 481 482 self.mock_lumpy1.test_run = test_run 483 self.mock_lumpy2.test_run = test_run 484 self.mock_lumpy3.test_run = test_run 485 self.mock_daisy1.test_run = test_run 486 self.mock_daisy2.test_run = test_run 487 488 self.mock_lumpy1.locked = True 489 self.mock_lumpy2.locked = False 490 self.mock_lumpy3.locked = False 491 self.mock_daisy1.locked = False 492 self.mock_daisy2.locked = True 493 494 self.mock_lumpy1.checksum = "123" 495 self.mock_lumpy3.checksum = "123" 496 self.mock_daisy2.checksum = "678" 497 498 output = self.mm.AsString() 499 self.assertEqual(output, self.OUTPUT_STR) 500 501 502 def test_get_all_cpu_info(self): 503 info = self.mm.GetAllCPUInfo([LABEL_LUMPY, LABEL_MIX]) 504 self.assertEqual(info, 505 'lumpy\n-------------------\nlumpy_cpu_info\n\n\nmix\n-' 506 '------------------\ndaisy_cpu_info\n\n\n') 507 508 509 510MEMINFO_STRING = """MemTotal: 3990332 kB 511MemFree: 2608396 kB 512Buffers: 147168 kB 513Cached: 811560 kB 514SwapCached: 0 kB 515Active: 503480 kB 516Inactive: 628572 kB 517Active(anon): 174532 kB 518Inactive(anon): 88576 kB 519Active(file): 328948 kB 520Inactive(file): 539996 kB 521Unevictable: 0 kB 522Mlocked: 0 kB 523SwapTotal: 5845212 kB 524SwapFree: 5845212 kB 525Dirty: 9384 kB 526Writeback: 0 kB 527AnonPages: 173408 kB 528Mapped: 146268 kB 529Shmem: 89676 kB 530Slab: 188260 kB 531SReclaimable: 169208 kB 532SUnreclaim: 19052 kB 533KernelStack: 2032 kB 534PageTables: 7120 kB 535NFS_Unstable: 0 kB 536Bounce: 0 kB 537WritebackTmp: 0 kB 538CommitLimit: 7840376 kB 539Committed_AS: 1082032 kB 540VmallocTotal: 34359738367 kB 541VmallocUsed: 364980 kB 542VmallocChunk: 34359369407 kB 543DirectMap4k: 45824 kB 544DirectMap2M: 4096000 kB 545""" 546 547CPUINFO_STRING = """processor: 0 548vendor_id: GenuineIntel 549cpu family: 6 550model: 42 551model name: Intel(R) Celeron(R) CPU 867 @ 1.30GHz 552stepping: 7 553microcode: 0x25 554cpu MHz: 1300.000 555cache size: 2048 KB 556physical id: 0 557siblings: 2 558core id: 0 559cpu cores: 2 560apicid: 0 561initial apicid: 0 562fpu: yes 563fpu_exception: yes 564cpuid level: 13 565wp: yes 566flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer xsave lahf_lm arat epb xsaveopt pln pts dts tpr_shadow vnmi flexpriority ept vpid 567bogomips: 2594.17 568clflush size: 64 569cache_alignment: 64 570address sizes: 36 bits physical, 48 bits virtual 571power management: 572 573processor: 1 574vendor_id: GenuineIntel 575cpu family: 6 576model: 42 577model name: Intel(R) Celeron(R) CPU 867 @ 1.30GHz 578stepping: 7 579microcode: 0x25 580cpu MHz: 1300.000 581cache size: 2048 KB 582physical id: 0 583siblings: 2 584core id: 1 585cpu cores: 2 586apicid: 2 587initial apicid: 2 588fpu: yes 589fpu_exception: yes 590cpuid level: 13 591wp: yes 592flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer xsave lahf_lm arat epb xsaveopt pln pts dts tpr_shadow vnmi flexpriority ept vpid 593bogomips: 2594.17 594clflush size: 64 595cache_alignment: 64 596address sizes: 36 bits physical, 48 bits virtual 597power management: 598""" 599 600CHECKSUM_STRING = "processor: 0vendor_id: GenuineIntelcpu family: 6model: 42model name: Intel(R) Celeron(R) CPU 867 @ 1.30GHzstepping: 7microcode: 0x25cache size: 2048 KBphysical id: 0siblings: 2core id: 0cpu cores: 2apicid: 0initial apicid: 0fpu: yesfpu_exception: yescpuid level: 13wp: yesflags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer xsave lahf_lm arat epb xsaveopt pln pts dts tpr_shadow vnmi flexpriority ept vpidclflush size: 64cache_alignment: 64address sizes: 36 bits physical, 48 bits virtualpower management:processor: 1vendor_id: GenuineIntelcpu family: 6model: 42model name: Intel(R) Celeron(R) CPU 867 @ 1.30GHzstepping: 7microcode: 0x25cache size: 2048 KBphysical id: 0siblings: 2core id: 1cpu cores: 2apicid: 2initial apicid: 2fpu: yesfpu_exception: yescpuid level: 13wp: yesflags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer xsave lahf_lm arat epb xsaveopt pln pts dts tpr_shadow vnmi flexpriority ept vpidclflush size: 64cache_alignment: 64address sizes: 36 bits physical, 48 bits virtualpower management: 4194304" 601 602DUMP_VPD_STRING = """ 603"PBA_SN"="Pba.txt" 604"Product_S/N"="HT4L91SC300208" 605"serial_number"="HT4L91SC300208Z" 606"System_UUID"="12153006-1755-4f66-b410-c43758a71127" 607"shipping_country"="US" 608"initial_locale"="en-US" 609"keyboard_layout"="xkb:us::eng" 610"initial_timezone"="America/Los_Angeles" 611"MACAddress"="" 612"System_UUID"="29dd9c61-7fa1-4c83-b89a-502e7eb08afe" 613"ubind_attribute"="0c433ce7585f486730b682bb05626a12ce2d896e9b57665387f8ce2ccfdcc56d2e2f1483" 614"gbind_attribute"="7e9a851324088e269319347c6abb8d1572ec31022fa07e28998229afe8acb45c35a89b9d" 615"ActivateDate"="2013-38" 616""" 617 618 619IFCONFIG_STRING = """ 620eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 621 inet 172.17.129.247 netmask 255.255.254.0 broadcast 172.17.129.255 622 inet6 2620:0:1000:3002:143:fed4:3ff6:279d prefixlen 64 scopeid 0x0<global> 623 inet6 2620:0:1000:3002:4459:1399:1f02:9e4c prefixlen 64 scopeid 0x0<global> 624 inet6 2620:0:1000:3002:d9e4:87b:d4ec:9a0e prefixlen 64 scopeid 0x0<global> 625 inet6 2620:0:1000:3002:7d45:23f1:ea8a:9604 prefixlen 64 scopeid 0x0<global> 626 inet6 2620:0:1000:3002:250:b6ff:fe63:db65 prefixlen 64 scopeid 0x0<global> 627 inet6 fe80::250:b6ff:fe63:db65 prefixlen 64 scopeid 0x20<link> 628 ether 00:50:b6:63:db:65 txqueuelen 1000 (Ethernet) 629 RX packets 9817166 bytes 10865181708 (10.1 GiB) 630 RX errors 194 dropped 0 overruns 0 frame 194 631 TX packets 0 bytes 2265811903 (2.1 GiB) 632 TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 633 634eth1: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 635 ether e8:03:9a:9c:50:3d txqueuelen 1000 (Ethernet) 636 RX packets 0 bytes 0 (0.0 B) 637 RX errors 0 dropped 0 overruns 0 frame 0 638 TX packets 0 bytes 0 (0.0 B) 639 TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 640 641lo: flags=73<UP,LOOPBACK,RUNNING> mtu 16436 642 inet 127.0.0.1 netmask 255.0.0.0 643 inet6 ::1 prefixlen 128 scopeid 0x10<host> 644 loop txqueuelen 0 (Local Loopback) 645 RX packets 981004 bytes 1127468524 (1.0 GiB) 646 RX errors 0 dropped 0 overruns 0 frame 0 647 TX packets 981004 bytes 1127468524 (1.0 GiB) 648 TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 649 650wlan0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 651 ether 44:6d:57:20:4a:c5 txqueuelen 1000 (Ethernet) 652 RX packets 0 bytes 0 (0.0 B) 653 RX errors 0 dropped 0 overruns 0 frame 0 654 TX packets 0 bytes 0 (0.0 B) 655 TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 656""" 657 658 659class CrosMachineTest(unittest.TestCase): 660 661 mock_cmd_exec = mock.Mock(spec=command_executer.CommandExecuter) 662 663 @mock.patch.object(machine_manager.CrosMachine, 'SetUpChecksumInfo') 664 def test_init(self, mock_setup): 665 666 cm = machine_manager.CrosMachine("daisy.cros", "/usr/local/chromeos", 667 "average", self.mock_cmd_exec) 668 self.assertEqual(mock_setup.call_count, 1) 669 self.assertEqual(cm.chromeos_root, "/usr/local/chromeos") 670 self.assertEqual(cm.log_level, "average") 671 672 673 @mock.patch.object(machine_manager.CrosMachine, 'IsReachable') 674 @mock.patch.object(machine_manager.CrosMachine, '_GetMemoryInfo') 675 @mock.patch.object(machine_manager.CrosMachine, '_GetCPUInfo') 676 @mock.patch.object(machine_manager.CrosMachine, 677 '_ComputeMachineChecksumString') 678 @mock.patch.object(machine_manager.CrosMachine, '_GetMachineID') 679 @mock.patch.object(machine_manager.CrosMachine, '_GetMD5Checksum') 680 def test_setup_checksum_info(self, mock_md5sum, mock_machineid, 681 mock_checkstring, mock_cpuinfo, mock_meminfo, 682 mock_isreachable): 683 684 # Test 1. Machine is not reachable; SetUpChecksumInfo is called via 685 # __init__. 686 mock_isreachable.return_value = False 687 mock_md5sum.return_value = "md5_checksum" 688 cm = machine_manager.CrosMachine("daisy.cros", "/usr/local/chromeos", 689 "average", self.mock_cmd_exec) 690 cm.checksum_string = "This is a checksum string." 691 cm.machine_id = "machine_id1" 692 self.assertEqual(mock_isreachable.call_count, 1) 693 self.assertIsNone(cm.machine_checksum) 694 self.assertEqual(mock_meminfo.call_count, 0) 695 696 # Test 2. Machine is reachable. Call explicitly. 697 mock_isreachable.return_value = True 698 cm.checksum_string = "This is a checksum string." 699 cm.machine_id = "machine_id1" 700 cm.SetUpChecksumInfo() 701 self.assertEqual(mock_isreachable.call_count, 2) 702 self.assertEqual(mock_meminfo.call_count, 1) 703 self.assertEqual(mock_cpuinfo.call_count, 1) 704 self.assertEqual(mock_checkstring.call_count, 1) 705 self.assertEqual(mock_machineid.call_count, 1) 706 self.assertEqual(mock_md5sum.call_count, 2) 707 self.assertEqual(cm.machine_checksum, "md5_checksum") 708 self.assertEqual(cm.machine_id_checksum, "md5_checksum") 709 self.assertEqual(mock_md5sum.call_args_list[0][0][0], 710 "This is a checksum string.") 711 self.assertEqual(mock_md5sum.call_args_list[1][0][0], 712 "machine_id1") 713 714 @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommand') 715 @mock.patch.object(machine_manager.CrosMachine, "SetUpChecksumInfo") 716 def test_is_reachable(self, mock_setup, mock_run_cmd): 717 718 cm = machine_manager.CrosMachine("daisy.cros", "/usr/local/chromeos", 719 "average", self.mock_cmd_exec) 720 self.mock_cmd_exec.CrosRunCommand = mock_run_cmd 721 722 # Test 1. CrosRunCommand returns 1 (fail) 723 mock_run_cmd.return_value = 1 724 result = cm.IsReachable() 725 self.assertFalse(result) 726 self.assertEqual(mock_setup.call_count, 1) 727 self.assertEqual(mock_run_cmd.call_count, 1) 728 729 # Test 2. CrosRunCommand returns 0 (success) 730 mock_run_cmd.return_value = 0 731 result = cm.IsReachable() 732 self.assertTrue(result) 733 self.assertEqual(mock_run_cmd.call_count, 2) 734 first_args = mock_run_cmd.call_args_list[0] 735 second_args = mock_run_cmd.call_args_list[1] 736 self.assertEqual (first_args[0], second_args[0]) 737 self.assertEqual (first_args[1], second_args[1]) 738 self.assertEqual (len(first_args[0]), 1) 739 self.assertEqual (len(first_args[1]), 2) 740 self.assertEqual (first_args[0][0], 'ls') 741 args_dict = first_args[1] 742 self.assertEqual (args_dict['machine'], 'daisy.cros') 743 self.assertEqual (args_dict['chromeos_root'], '/usr/local/chromeos') 744 745 746 @mock.patch.object(machine_manager.CrosMachine, "SetUpChecksumInfo") 747 def test_parse_memory_info(self, mock_setup): 748 cm = machine_manager.CrosMachine("daisy.cros", "/usr/local/chromeos", 749 "average", self.mock_cmd_exec) 750 cm.meminfo = MEMINFO_STRING 751 cm._ParseMemoryInfo() 752 self.assertEqual(cm.phys_kbytes, 4194304) 753 754 755 @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommand') 756 @mock.patch.object(machine_manager.CrosMachine, "SetUpChecksumInfo") 757 def test_get_memory_info(self, mock_setup, mock_run_cmd): 758 cm = machine_manager.CrosMachine("daisy.cros", "/usr/local/chromeos", 759 "average", self.mock_cmd_exec) 760 self.mock_cmd_exec.CrosRunCommand = mock_run_cmd 761 mock_run_cmd.return_value = [0, MEMINFO_STRING, ""] 762 cm._GetMemoryInfo() 763 self.assertEqual(mock_run_cmd.call_count, 1) 764 call_args = mock_run_cmd.call_args_list[0] 765 self.assertEqual(call_args[0][0], "cat /proc/meminfo") 766 args_dict = call_args[1] 767 self.assertEqual(args_dict['username'], 'root') 768 self.assertEqual(args_dict['machine'], 'daisy.cros') 769 self.assertEqual(args_dict['chromeos_root'], '/usr/local/chromeos') 770 self.assertEqual(args_dict['return_output'], True) 771 self.assertEqual(cm.meminfo, MEMINFO_STRING) 772 self.assertEqual(cm.phys_kbytes, 4194304) 773 774 mock_run_cmd.return_value = [1, MEMINFO_STRING, ""] 775 self.assertRaises (cm._GetMemoryInfo) 776 777 778 @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommand') 779 @mock.patch.object(machine_manager.CrosMachine, "SetUpChecksumInfo") 780 def test_get_cpu_info(self, mock_setup, mock_run_cmd): 781 cm = machine_manager.CrosMachine("daisy.cros", "/usr/local/chromeos", 782 "average", self.mock_cmd_exec) 783 self.mock_cmd_exec.CrosRunCommand = mock_run_cmd 784 mock_run_cmd.return_value = [0, CPUINFO_STRING, ""] 785 cm._GetCPUInfo() 786 self.assertEqual(mock_run_cmd.call_count, 1) 787 call_args = mock_run_cmd.call_args_list[0] 788 self.assertEqual(call_args[0][0], "cat /proc/cpuinfo") 789 args_dict = call_args[1] 790 self.assertEqual(args_dict['username'], 'root') 791 self.assertEqual(args_dict['machine'], 'daisy.cros') 792 self.assertEqual(args_dict['chromeos_root'], '/usr/local/chromeos') 793 self.assertEqual(args_dict['return_output'], True) 794 self.assertEqual(cm.cpuinfo, CPUINFO_STRING) 795 796 797 @mock.patch.object(machine_manager.CrosMachine, "SetUpChecksumInfo") 798 def test_compute_machine_checksum_string(self, mock_setup): 799 cm = machine_manager.CrosMachine("daisy.cros", "/usr/local/chromeos", 800 "average", self.mock_cmd_exec) 801 cm.cpuinfo = CPUINFO_STRING 802 cm.meminfo = MEMINFO_STRING 803 cm._ParseMemoryInfo() 804 cm._ComputeMachineChecksumString() 805 self.assertEqual(cm.checksum_string, CHECKSUM_STRING) 806 807 808 @mock.patch.object(machine_manager.CrosMachine, "SetUpChecksumInfo") 809 def test_get_md5_checksum(self, mock_setup): 810 cm = machine_manager.CrosMachine("daisy.cros", "/usr/local/chromeos", 811 "average", self.mock_cmd_exec) 812 temp_str = "abcde" 813 checksum_str = cm._GetMD5Checksum(temp_str) 814 self.assertEqual(checksum_str, "ab56b4d92b40713acc5af89985d4b786") 815 816 temp_str = "" 817 checksum_str = cm._GetMD5Checksum(temp_str) 818 self.assertEqual(checksum_str, "") 819 820 821 @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommand') 822 @mock.patch.object(machine_manager.CrosMachine, "SetUpChecksumInfo") 823 def test_get_machine_id(self, mock_setup, mock_run_cmd): 824 cm = machine_manager.CrosMachine("daisy.cros", "/usr/local/chromeos", 825 "average", self.mock_cmd_exec) 826 self.mock_cmd_exec.CrosRunCommand = mock_run_cmd 827 mock_run_cmd.return_value = [0, DUMP_VPD_STRING, ""] 828 829 cm._GetMachineID() 830 self.assertEqual(cm.machine_id, '"Product_S/N"="HT4L91SC300208"') 831 832 mock_run_cmd.return_value = [0, IFCONFIG_STRING, ""] 833 cm._GetMachineID() 834 self.assertEqual(cm.machine_id, " ether 00:50:b6:63:db:65 txqueuelen 1000 (Ethernet)_ ether e8:03:9a:9c:50:3d txqueuelen 1000 (Ethernet)_ ether 44:6d:57:20:4a:c5 txqueuelen 1000 (Ethernet)") 835 836 mock_run_cmd.return_value = [0, "invalid hardware config", ""] 837 self.assertRaises(cm._GetMachineID) 838 839 840 841if __name__ == "__main__": 842 unittest.main() 843