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