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