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