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