machine_manager_unittest.py revision e627fd61c2edba668eb2af8221892286b13f05a3
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, 'CrosRunCommand') 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), 3) 256 self.assertEqual(args_dict['machine'], self.mock_lumpy1.name) 257 self.assertEqual(args_dict['chromeos_root'], '/usr/local/chromeos') 258 self.assertTrue(args_dict['return_output']) 259 260 261 @mock.patch.object(machine_manager, 'CrosMachine') 262 def test_add_machine(self, mock_machine): 263 264 mock_machine.machine_checksum = 'daisy123' 265 self.assertEqual (len(self.mm._all_machines), 5) 266 self.mm.AddMachine('daisy3') 267 self.assertEqual (len(self.mm._all_machines), 6) 268 269 self.assertRaises(Exception, self.mm.AddMachine, 'lumpy1') 270 271 272 def test_remove_machine(self): 273 self.mm._machines = self.mm._all_machines 274 self.assertTrue(self.mock_lumpy2 in self.mm._machines) 275 self.mm.RemoveMachine(self.mock_lumpy2.name) 276 self.assertFalse(self.mock_lumpy2 in self.mm._machines) 277 278 279 def test_force_same_image_to_all_machines(self): 280 self.image_log = [] 281 282 def FakeImageMachine(machine, label_arg): 283 image = label_arg.chromeos_image 284 self.image_log.append("Pushed %s onto %s" % (image, machine.name)) 285 286 def FakeSetUpChecksumInfo(): 287 pass 288 289 self.mm.ImageMachine = FakeImageMachine 290 self.mock_lumpy1.SetUpChecksumInfo = FakeSetUpChecksumInfo 291 self.mock_lumpy2.SetUpChecksumInfo = FakeSetUpChecksumInfo 292 self.mock_lumpy3.SetUpChecksumInfo = FakeSetUpChecksumInfo 293 294 self.mm.ForceSameImageToAllMachines(LABEL_LUMPY) 295 self.assertEqual(len(self.image_log), 3) 296 self.assertEqual(self.image_log[0], 297 'Pushed lumpy_chromeos_image onto lumpy1') 298 self.assertEqual(self.image_log[1], 299 'Pushed lumpy_chromeos_image onto lumpy2') 300 self.assertEqual(self.image_log[2], 301 'Pushed lumpy_chromeos_image onto lumpy3') 302 303 304 305 @mock.patch.object(image_checksummer.ImageChecksummer, 'Checksum') 306 @mock.patch.object(hashlib,'md5') 307 def test_acquire_machine(self, mock_md5, mock_checksum): 308 309 self.msgs = [] 310 self.log_fatal_msgs = [] 311 312 def FakeLock(machine): 313 self.msgs.append("Tried to lock %s" % machine.name) 314 315 def FakeLogFatal(msg): 316 self.log_fatal_msgs.append(msg) 317 318 self.mm._TryToLockMachine = FakeLock 319 self.mm.logger.LogFatal = FakeLogFatal 320 321 mock_md5.return_value = "123456" 322 mock_checksum.return_value = "fake_md5_checksum" 323 324 self.mm._machines = self.mm._all_machines 325 self.mock_lumpy1.locked = True 326 self.mock_lumpy2.locked = True 327 self.mock_lumpy3.locked = False 328 self.mock_lumpy3.checksum = "fake_md5_checksum" 329 self.mock_daisy1.locked = True 330 self.mock_daisy2.locked = False 331 self.mock_daisy2.checksum = "fake_md5_checksum" 332 333 self.mock_lumpy1.released_time = time.time() 334 self.mock_lumpy2.released_time = time.time() 335 self.mock_lumpy3.released_time = time.time() 336 self.mock_daisy1.released_time = time.time() 337 self.mock_daisy2.released_time = time.time() 338 339 # Test 1. Basic test. Acquire lumpy3. 340 self.mm.AcquireMachine(LABEL_LUMPY) 341 m = self.mock_lumpy1 342 self.assertEqual(m, self.mock_lumpy1) 343 self.assertTrue(self.mock_lumpy1.locked) 344 self.assertEqual(mock_md5.call_count, 0) 345 self.assertEqual(self.msgs, ['Tried to lock lumpy1', 346 'Tried to lock lumpy2', 347 'Tried to lock lumpy3']) 348 349 # Test the second return statment (machine is unlocked, has no checksum) 350 save_locked = self.mock_lumpy1.locked 351 self.mock_lumpy1.locked = False 352 self.mock_lumpy1.checksum = None 353 m = self.mm.AcquireMachine(LABEL_LUMPY) 354 self.assertEqual(m, self.mock_lumpy1) 355 self.assertTrue(self.mock_lumpy1.locked) 356 357 # Test the third return statement: 358 # - machine is unlocked 359 # - checksums don't match 360 # - current time minus release time is > 20. 361 self.mock_lumpy1.locked = False 362 self.mock_lumpy1.checksum = "123" 363 self.mock_lumpy1.released_time = time.time() - 8 364 m = self.mm.AcquireMachine(LABEL_LUMPY) 365 self.assertEqual(m, self.mock_lumpy1) 366 self.assertTrue(self.mock_lumpy1.locked) 367 368 # Test all machines are already locked. 369 m = self.mm.AcquireMachine(LABEL_LUMPY) 370 self.assertIsNone(m) 371 372 # Restore values of mock_lumpy1, so other tests succeed. 373 self.mock_lumpy1.locked = save_locked 374 self.mock_lumpy1.checksum = "123" 375 376 377 def test_get_available_machines(self): 378 self.mm._machines = self.mm._all_machines 379 380 machine_list = self.mm.GetAvailableMachines() 381 self.assertEqual(machine_list, self.mm._all_machines) 382 383 machine_list = self.mm.GetAvailableMachines(LABEL_MIX) 384 self.assertEqual(machine_list, [self.mock_daisy1, self.mock_daisy2, 385 self.mock_lumpy3]) 386 387 machine_list = self.mm.GetAvailableMachines(LABEL_LUMPY) 388 self.assertEqual(machine_list, [self.mock_lumpy1, self.mock_lumpy2, 389 self.mock_lumpy3]) 390 391 392 def test_get_machines(self): 393 machine_list = self.mm.GetMachines() 394 self.assertEqual(machine_list, self.mm._all_machines) 395 396 machine_list = self.mm.GetMachines(LABEL_MIX) 397 self.assertEqual(machine_list, [self.mock_daisy1, self.mock_daisy2, 398 self.mock_lumpy3]) 399 400 machine_list = self.mm.GetMachines(LABEL_LUMPY) 401 self.assertEqual(machine_list, [self.mock_lumpy1, self.mock_lumpy2, 402 self.mock_lumpy3]) 403 404 405 def test_release_machines(self): 406 407 self.mm._machines = [self.mock_lumpy1, self.mock_daisy2] 408 409 self.mock_lumpy1.locked = True 410 self.mock_daisy2.locked = True 411 412 self.assertTrue(self.mock_lumpy1.locked) 413 self.mm.ReleaseMachine(self.mock_lumpy1) 414 self.assertFalse(self.mock_lumpy1.locked) 415 self.assertEqual(self.mock_lumpy1.status, "Available") 416 417 self.assertTrue(self.mock_daisy2.locked) 418 self.mm.ReleaseMachine(self.mock_daisy2) 419 self.assertFalse(self.mock_daisy2.locked) 420 self.assertEqual(self.mock_daisy2.status, "Available") 421 422 # Test double-relase... 423 self.assertRaises(AssertionError, self.mm.ReleaseMachine, self.mock_lumpy1) 424 425 426 def test_cleanup(self): 427 self.mock_logger.reset_mock() 428 self.mm.Cleanup() 429 self.assertEqual(self.mock_logger.call_count, 0) 430 431 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 ' 432 433 def test_as_string(self): 434 435 mock_logger = mock.Mock(spec=logger.Logger) 436 437 bench = Benchmark("page_cycler.netsim.top_10", # name 438 "page_cycler.netsim.top_10", # test_name 439 "", # test_args 440 1, # iteratins 441 False, # rm_chroot_tmp 442 "", # perf_args 443 suite="telemetry_Crosperf") # suite 444 445 test_run = MockBenchmarkRun("test run", 446 bench, 447 LABEL_LUMPY, 448 1, 449 [], 450 self.mm, 451 mock_logger, 452 "verbose", 453 "") 454 455 self.mm._machines = [self.mock_lumpy1, self.mock_lumpy2, self.mock_lumpy3, 456 self.mock_daisy1, self.mock_daisy2] 457 458 self.mock_lumpy1.test_run = test_run 459 self.mock_lumpy2.test_run = test_run 460 self.mock_lumpy3.test_run = test_run 461 self.mock_daisy1.test_run = test_run 462 self.mock_daisy2.test_run = test_run 463 464 self.mock_lumpy1.locked = True 465 self.mock_lumpy2.locked = False 466 self.mock_lumpy3.locked = False 467 self.mock_daisy1.locked = False 468 self.mock_daisy2.locked = True 469 470 self.mock_lumpy1.checksum = "123" 471 self.mock_lumpy2.checksum = "123" 472 self.mock_lumpy3.checksum = "123" 473 self.mock_daisy1.checksum = "678" 474 self.mock_daisy2.checksum = "678" 475 476 output = self.mm.AsString() 477 self.assertEqual(output, self.OUTPUT_STR) 478 479 480 def test_get_all_cpu_info(self): 481 info = self.mm.GetAllCPUInfo([LABEL_LUMPY, LABEL_MIX]) 482 self.assertEqual(info, 483 'lumpy\n-------------------\nlumpy_cpu_info\n\n\nmix\n-' 484 '------------------\ndaisy_cpu_info\n\n\n') 485 486 487 488MEMINFO_STRING = """MemTotal: 3990332 kB 489MemFree: 2608396 kB 490Buffers: 147168 kB 491Cached: 811560 kB 492SwapCached: 0 kB 493Active: 503480 kB 494Inactive: 628572 kB 495Active(anon): 174532 kB 496Inactive(anon): 88576 kB 497Active(file): 328948 kB 498Inactive(file): 539996 kB 499Unevictable: 0 kB 500Mlocked: 0 kB 501SwapTotal: 5845212 kB 502SwapFree: 5845212 kB 503Dirty: 9384 kB 504Writeback: 0 kB 505AnonPages: 173408 kB 506Mapped: 146268 kB 507Shmem: 89676 kB 508Slab: 188260 kB 509SReclaimable: 169208 kB 510SUnreclaim: 19052 kB 511KernelStack: 2032 kB 512PageTables: 7120 kB 513NFS_Unstable: 0 kB 514Bounce: 0 kB 515WritebackTmp: 0 kB 516CommitLimit: 7840376 kB 517Committed_AS: 1082032 kB 518VmallocTotal: 34359738367 kB 519VmallocUsed: 364980 kB 520VmallocChunk: 34359369407 kB 521DirectMap4k: 45824 kB 522DirectMap2M: 4096000 kB 523""" 524 525CPUINFO_STRING = """processor: 0 526vendor_id: GenuineIntel 527cpu family: 6 528model: 42 529model name: Intel(R) Celeron(R) CPU 867 @ 1.30GHz 530stepping: 7 531microcode: 0x25 532cpu MHz: 1300.000 533cache size: 2048 KB 534physical id: 0 535siblings: 2 536core id: 0 537cpu cores: 2 538apicid: 0 539initial apicid: 0 540fpu: yes 541fpu_exception: yes 542cpuid level: 13 543wp: yes 544flags: 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 545bogomips: 2594.17 546clflush size: 64 547cache_alignment: 64 548address sizes: 36 bits physical, 48 bits virtual 549power management: 550 551processor: 1 552vendor_id: GenuineIntel 553cpu family: 6 554model: 42 555model name: Intel(R) Celeron(R) CPU 867 @ 1.30GHz 556stepping: 7 557microcode: 0x25 558cpu MHz: 1300.000 559cache size: 2048 KB 560physical id: 0 561siblings: 2 562core id: 1 563cpu cores: 2 564apicid: 2 565initial apicid: 2 566fpu: yes 567fpu_exception: yes 568cpuid level: 13 569wp: yes 570flags: 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 571bogomips: 2594.17 572clflush size: 64 573cache_alignment: 64 574address sizes: 36 bits physical, 48 bits virtual 575power management: 576""" 577 578CHECKSUM_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" 579 580DUMP_VPD_STRING = """ 581"PBA_SN"="Pba.txt" 582"Product_S/N"="HT4L91SC300208" 583"serial_number"="HT4L91SC300208Z" 584"System_UUID"="12153006-1755-4f66-b410-c43758a71127" 585"shipping_country"="US" 586"initial_locale"="en-US" 587"keyboard_layout"="xkb:us::eng" 588"initial_timezone"="America/Los_Angeles" 589"MACAddress"="" 590"System_UUID"="29dd9c61-7fa1-4c83-b89a-502e7eb08afe" 591"ubind_attribute"="0c433ce7585f486730b682bb05626a12ce2d896e9b57665387f8ce2ccfdcc56d2e2f1483" 592"gbind_attribute"="7e9a851324088e269319347c6abb8d1572ec31022fa07e28998229afe8acb45c35a89b9d" 593"ActivateDate"="2013-38" 594""" 595 596 597IFCONFIG_STRING = """ 598eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 599 inet 172.17.129.247 netmask 255.255.254.0 broadcast 172.17.129.255 600 inet6 2620:0:1000:3002:143:fed4:3ff6:279d prefixlen 64 scopeid 0x0<global> 601 inet6 2620:0:1000:3002:4459:1399:1f02:9e4c prefixlen 64 scopeid 0x0<global> 602 inet6 2620:0:1000:3002:d9e4:87b:d4ec:9a0e prefixlen 64 scopeid 0x0<global> 603 inet6 2620:0:1000:3002:7d45:23f1:ea8a:9604 prefixlen 64 scopeid 0x0<global> 604 inet6 2620:0:1000:3002:250:b6ff:fe63:db65 prefixlen 64 scopeid 0x0<global> 605 inet6 fe80::250:b6ff:fe63:db65 prefixlen 64 scopeid 0x20<link> 606 ether 00:50:b6:63:db:65 txqueuelen 1000 (Ethernet) 607 RX packets 9817166 bytes 10865181708 (10.1 GiB) 608 RX errors 194 dropped 0 overruns 0 frame 194 609 TX packets 0 bytes 2265811903 (2.1 GiB) 610 TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 611 612eth1: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 613 ether e8:03:9a:9c:50:3d txqueuelen 1000 (Ethernet) 614 RX packets 0 bytes 0 (0.0 B) 615 RX errors 0 dropped 0 overruns 0 frame 0 616 TX packets 0 bytes 0 (0.0 B) 617 TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 618 619lo: flags=73<UP,LOOPBACK,RUNNING> mtu 16436 620 inet 127.0.0.1 netmask 255.0.0.0 621 inet6 ::1 prefixlen 128 scopeid 0x10<host> 622 loop txqueuelen 0 (Local Loopback) 623 RX packets 981004 bytes 1127468524 (1.0 GiB) 624 RX errors 0 dropped 0 overruns 0 frame 0 625 TX packets 981004 bytes 1127468524 (1.0 GiB) 626 TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 627 628wlan0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 629 ether 44:6d:57:20:4a:c5 txqueuelen 1000 (Ethernet) 630 RX packets 0 bytes 0 (0.0 B) 631 RX errors 0 dropped 0 overruns 0 frame 0 632 TX packets 0 bytes 0 (0.0 B) 633 TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 634""" 635 636 637class CrosMachineTest(unittest.TestCase): 638 639 mock_cmd_exec = mock.Mock(spec=command_executer.CommandExecuter) 640 641 @mock.patch.object(machine_manager.CrosMachine, 'SetUpChecksumInfo') 642 def test_init(self, mock_setup): 643 644 cm = machine_manager.CrosMachine("daisy.cros", "/usr/local/chromeos", 645 "average", self.mock_cmd_exec) 646 self.assertEqual(mock_setup.call_count, 1) 647 self.assertEqual(cm.chromeos_root, "/usr/local/chromeos") 648 self.assertEqual(cm.log_level, "average") 649 650 651 @mock.patch.object(machine_manager.CrosMachine, 'IsReachable') 652 @mock.patch.object(machine_manager.CrosMachine, '_GetMemoryInfo') 653 @mock.patch.object(machine_manager.CrosMachine, '_GetCPUInfo') 654 @mock.patch.object(machine_manager.CrosMachine, 655 '_ComputeMachineChecksumString') 656 @mock.patch.object(machine_manager.CrosMachine, '_GetMachineID') 657 @mock.patch.object(machine_manager.CrosMachine, '_GetMD5Checksum') 658 def test_setup_checksum_info(self, mock_md5sum, mock_machineid, 659 mock_checkstring, mock_cpuinfo, mock_meminfo, 660 mock_isreachable): 661 662 # Test 1. Machine is not reachable; SetUpChecksumInfo is called via 663 # __init__. 664 mock_isreachable.return_value = False 665 mock_md5sum.return_value = "md5_checksum" 666 cm = machine_manager.CrosMachine("daisy.cros", "/usr/local/chromeos", 667 "average", self.mock_cmd_exec) 668 cm.checksum_string = "This is a checksum string." 669 cm.machine_id = "machine_id1" 670 self.assertEqual(mock_isreachable.call_count, 1) 671 self.assertIsNone(cm.machine_checksum) 672 self.assertEqual(mock_meminfo.call_count, 0) 673 674 # Test 2. Machine is reachable. Call explicitly. 675 mock_isreachable.return_value = True 676 cm.checksum_string = "This is a checksum string." 677 cm.machine_id = "machine_id1" 678 cm.SetUpChecksumInfo() 679 self.assertEqual(mock_isreachable.call_count, 2) 680 self.assertEqual(mock_meminfo.call_count, 1) 681 self.assertEqual(mock_cpuinfo.call_count, 1) 682 self.assertEqual(mock_checkstring.call_count, 1) 683 self.assertEqual(mock_machineid.call_count, 1) 684 self.assertEqual(mock_md5sum.call_count, 2) 685 self.assertEqual(cm.machine_checksum, "md5_checksum") 686 self.assertEqual(cm.machine_id_checksum, "md5_checksum") 687 self.assertEqual(mock_md5sum.call_args_list[0][0][0], 688 "This is a checksum string.") 689 self.assertEqual(mock_md5sum.call_args_list[1][0][0], 690 "machine_id1") 691 692 @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommand') 693 @mock.patch.object(machine_manager.CrosMachine, "SetUpChecksumInfo") 694 def test_is_reachable(self, mock_setup, mock_run_cmd): 695 696 cm = machine_manager.CrosMachine("daisy.cros", "/usr/local/chromeos", 697 "average", self.mock_cmd_exec) 698 self.mock_cmd_exec.CrosRunCommand = mock_run_cmd 699 700 # Test 1. CrosRunCommand returns 1 (fail) 701 mock_run_cmd.return_value = 1 702 result = cm.IsReachable() 703 self.assertFalse(result) 704 self.assertEqual(mock_setup.call_count, 1) 705 self.assertEqual(mock_run_cmd.call_count, 1) 706 707 # Test 2. CrosRunCommand returns 0 (success) 708 mock_run_cmd.return_value = 0 709 result = cm.IsReachable() 710 self.assertTrue(result) 711 self.assertEqual(mock_run_cmd.call_count, 2) 712 first_args = mock_run_cmd.call_args_list[0] 713 second_args = mock_run_cmd.call_args_list[1] 714 self.assertEqual (first_args[0], second_args[0]) 715 self.assertEqual (first_args[1], second_args[1]) 716 self.assertEqual (len(first_args[0]), 1) 717 self.assertEqual (len(first_args[1]), 2) 718 self.assertEqual (first_args[0][0], 'ls') 719 args_dict = first_args[1] 720 self.assertEqual (args_dict['machine'], 'daisy.cros') 721 self.assertEqual (args_dict['chromeos_root'], '/usr/local/chromeos') 722 723 724 @mock.patch.object(machine_manager.CrosMachine, "SetUpChecksumInfo") 725 def test_parse_memory_info(self, mock_setup): 726 cm = machine_manager.CrosMachine("daisy.cros", "/usr/local/chromeos", 727 "average", self.mock_cmd_exec) 728 cm.meminfo = MEMINFO_STRING 729 cm._ParseMemoryInfo() 730 self.assertEqual(cm.phys_kbytes, 4194304) 731 732 733 @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommand') 734 @mock.patch.object(machine_manager.CrosMachine, "SetUpChecksumInfo") 735 def test_get_memory_info(self, mock_setup, mock_run_cmd): 736 cm = machine_manager.CrosMachine("daisy.cros", "/usr/local/chromeos", 737 "average", self.mock_cmd_exec) 738 self.mock_cmd_exec.CrosRunCommand = mock_run_cmd 739 mock_run_cmd.return_value = [0, MEMINFO_STRING, ""] 740 cm._GetMemoryInfo() 741 self.assertEqual(mock_run_cmd.call_count, 1) 742 call_args = mock_run_cmd.call_args_list[0] 743 self.assertEqual(call_args[0][0], "cat /proc/meminfo") 744 args_dict = call_args[1] 745 self.assertEqual(args_dict['machine'], 'daisy.cros') 746 self.assertEqual(args_dict['chromeos_root'], '/usr/local/chromeos') 747 self.assertEqual(args_dict['return_output'], True) 748 self.assertEqual(cm.meminfo, MEMINFO_STRING) 749 self.assertEqual(cm.phys_kbytes, 4194304) 750 751 mock_run_cmd.return_value = [1, MEMINFO_STRING, ""] 752 self.assertRaises (cm._GetMemoryInfo) 753 754 755 @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommand') 756 @mock.patch.object(machine_manager.CrosMachine, "SetUpChecksumInfo") 757 def test_get_cpu_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, CPUINFO_STRING, ""] 762 cm._GetCPUInfo() 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/cpuinfo") 766 args_dict = call_args[1] 767 self.assertEqual(args_dict['machine'], 'daisy.cros') 768 self.assertEqual(args_dict['chromeos_root'], '/usr/local/chromeos') 769 self.assertEqual(args_dict['return_output'], True) 770 self.assertEqual(cm.cpuinfo, CPUINFO_STRING) 771 772 773 @mock.patch.object(machine_manager.CrosMachine, "SetUpChecksumInfo") 774 def test_compute_machine_checksum_string(self, mock_setup): 775 cm = machine_manager.CrosMachine("daisy.cros", "/usr/local/chromeos", 776 "average", self.mock_cmd_exec) 777 cm.cpuinfo = CPUINFO_STRING 778 cm.meminfo = MEMINFO_STRING 779 cm._ParseMemoryInfo() 780 cm._ComputeMachineChecksumString() 781 self.assertEqual(cm.checksum_string, CHECKSUM_STRING) 782 783 784 @mock.patch.object(machine_manager.CrosMachine, "SetUpChecksumInfo") 785 def test_get_md5_checksum(self, mock_setup): 786 cm = machine_manager.CrosMachine("daisy.cros", "/usr/local/chromeos", 787 "average", self.mock_cmd_exec) 788 temp_str = "abcde" 789 checksum_str = cm._GetMD5Checksum(temp_str) 790 self.assertEqual(checksum_str, "ab56b4d92b40713acc5af89985d4b786") 791 792 temp_str = "" 793 checksum_str = cm._GetMD5Checksum(temp_str) 794 self.assertEqual(checksum_str, "") 795 796 797 @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommand') 798 @mock.patch.object(machine_manager.CrosMachine, "SetUpChecksumInfo") 799 def test_get_machine_id(self, mock_setup, mock_run_cmd): 800 cm = machine_manager.CrosMachine("daisy.cros", "/usr/local/chromeos", 801 "average", self.mock_cmd_exec) 802 self.mock_cmd_exec.CrosRunCommand = mock_run_cmd 803 mock_run_cmd.return_value = [0, DUMP_VPD_STRING, ""] 804 805 cm._GetMachineID() 806 self.assertEqual(cm.machine_id, '"Product_S/N"="HT4L91SC300208"') 807 808 mock_run_cmd.return_value = [0, IFCONFIG_STRING, ""] 809 cm._GetMachineID() 810 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)") 811 812 mock_run_cmd.return_value = [0, "invalid hardware config", ""] 813 self.assertRaises(cm._GetMachineID) 814 815 816 817if __name__ == "__main__": 818 unittest.main() 819