android_backend_unittest.py revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
1# Copyright 2014 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5"""Unittests for the android backends modules.""" 6 7import os 8import unittest 9 10from memory_inspector.backends import android_backend 11from memory_inspector.backends import prebuilts_fetcher 12from memory_inspector.unittest.mock_adb import mock_adb 13 14 15_MOCK_ADB_PATH = os.path.dirname(mock_adb.__file__) 16 17_MOCK_DEVICES_OUT = """List of devices attached 180000000000000001\tdevice 190000000000000002\tdevice 20""" 21 22_MOCK_MEMDUMP_OUT = ("""[ PID=1] 238000-33000 r-xp 0 private_unevictable=8192 private=8192 shared_app=[] """ 24 """shared_other_unevictable=147456 shared_other=147456 "/init" [v///fv0D] 2533000-35000 r--p 2a000 private_unevictable=4096 private=4096 shared_app=[] """ 26 """shared_other_unevictable=4096 shared_other=4096 "/init" [Aw==] 2735000-37000 rw-p 2c000 private_unevictable=8192 private=8192 shared_app=[] """ 28 """shared_other_unevictable=0 shared_other=0 "/init" [Aw==] 2937000-6d000 rw-p 0 private_unevictable=221184 private=221184 shared_app=[] """ 30 """shared_other_unevictable=0 shared_other=0 "[heap]" [////////Pw==] 31400c5000-400c7000 rw-p 0 private_unevictable=0 private=0 shared_app=[] """ 32 """shared_other_unevictable=0 shared_other=0 "" [AA==] 33400f4000-400f5000 r--p 0 private_unevictable=4096 private=4096 shared_app=[] """ 34 """shared_other_unevictable=0 shared_other=0 "" [AQ==] 3540127000-40147000 rw-s 0 private_unevictable=4096 private=4096 shared_app=[] """ 36 """shared_other_unevictable=32768 shared_other=32768 "/X" [/////w==] 37be8b7000-be8d8000 rw-p 8 private_unevictable=8192 private=8192 shared_app=[] """ 38 """shared_other_unevictable=4096 shared_other=12288 "[stack]" [//8=] 39ffff00ffff0000-ffff00ffff1000 r-xp 0 private_unevictable=0 private=0 """ 40 """shared_app=[] shared_other_unevictable=0 shared_other=0 "[vectors]" []""" 41) 42 43_MOCK_HEAP_DUMP_OUT = """{ 44 "total_allocated": 8192, 45 "num_allocs": 2, 46 "num_stacks": 2, 47 "allocs": { 48 "a1000": {"l": 100, "f": 0, "s": "a"}, 49 "a2000": {"l": 100, "f": 0, "s": "a"}, 50 "b1000": {"l": 1000, "f": 0, "s": "b"}, 51 "b2000": {"l": 1000, "f": 0, "s": "b"}, 52 "b3000": {"l": 1000, "f": 0, "s": "b"}}, 53 "stacks": { 54 "a": {"l": 200, "f": [10, 20, 30, 40]}, 55 "b": {"l": 3000, "f": [50, 60, 70]}} 56 }""" 57 58_MOCK_PS_EXT_OUT = """ 59{ 60 "time": { "ticks": 1000100, "rate": 100}, 61 "mem": { 62 "MemTotal:": 998092, "MemFree:": 34904, 63 "Buffers:": 24620, "Cached:": 498916 }, 64 "cpu": [{"usr": 32205, "sys": 49826, "idle": 7096196}], 65 "processes": { 66 "1": { 67 "name": "foo", "n_threads": 42, "start_time": 1000000, "user_time": 82, 68 "sys_time": 445, "min_faults": 0, "maj_faults": 0, "vm_rss": 528}, 69 "2": { 70 "name": "bar", "n_threads": 142, "start_time": 1, "user_time": 82, 71 "sys_time": 445, "min_faults": 0, "maj_faults": 0, "vm_rss": 528}} 72} 73""" 74 75 76class AndroidBackendTest(unittest.TestCase): 77 def setUp(self): 78 prebuilts_fetcher.in_test_harness = True 79 self._mock_adb = mock_adb.MockAdb() 80 planned_adb_responses = { 81 'devices': _MOCK_DEVICES_OUT, 82 'shell getprop ro.product.model': 'Mock device', 83 'shell getprop ro.build.type': 'userdebug', 84 'shell getprop ro.build.id': 'ZZ007', 85 'shell getprop ro.product.cpu.abi': 'armeabi', 86 'root': 'adbd is already running as root', 87 'shell /data/local/tmp/ps_ext': _MOCK_PS_EXT_OUT, 88 'shell /data/local/tmp/memdump': _MOCK_MEMDUMP_OUT, 89 'shell /data/local/tmp/heap_dump': _MOCK_HEAP_DUMP_OUT, 90 'shell test -e "/data/local/tmp/heap': '0', 91 } 92 for (cmd, response) in planned_adb_responses.iteritems(): 93 self._mock_adb.PrepareResponse(cmd, response) 94 self._mock_adb.Start() 95 96 def runTest(self): 97 ab = android_backend.AndroidBackend() 98 99 # Test settings load/store logic and setup the mock adb path. 100 self.assertTrue('adb_path' in ab.settings.expected_keys) 101 ab.settings['adb_path'] = _MOCK_ADB_PATH 102 self.assertEqual(ab.settings['adb_path'], _MOCK_ADB_PATH) 103 104 # Test device enumeration. 105 devices = list(ab.EnumerateDevices()) 106 self.assertEqual(len(devices), 2) 107 self.assertEqual(devices[0].name, 'Mock device ZZ007') 108 self.assertEqual(devices[0].id, '0000000000000001') 109 self.assertEqual(devices[1].name, 'Mock device ZZ007') 110 self.assertEqual(devices[1].id, '0000000000000002') 111 112 # Initialize device (checks that sha1 are checked in). 113 device = devices[0] 114 device.Initialize() 115 116 # Test process enumeration. 117 processes = list(device.ListProcesses()) 118 self.assertEqual(len(processes), 2) 119 self.assertEqual(processes[0].pid, 1) 120 self.assertEqual(processes[0].name, 'foo') 121 self.assertEqual(processes[1].pid, 2) 122 self.assertEqual(processes[1].name, 'bar') 123 124 # Test process stats. 125 stats = processes[0].GetStats() 126 self.assertEqual(stats.threads, 42) 127 self.assertEqual(stats.cpu_usage, 0) 128 self.assertEqual(stats.run_time, 1) 129 self.assertEqual(stats.vm_rss, 528) 130 self.assertEqual(stats.page_faults, 0) 131 132 # Test memdump parsing. 133 mmaps = processes[0].DumpMemoryMaps() 134 self.assertEqual(len(mmaps), 9) 135 self.assertIsNone(mmaps.Lookup(0)) 136 self.assertIsNone(mmaps.Lookup(7999)) 137 self.assertIsNotNone(mmaps.Lookup(0x8000)) 138 self.assertIsNotNone(mmaps.Lookup(0x32FFF)) 139 self.assertIsNotNone(mmaps.Lookup(0x33000)) 140 self.assertIsNone(mmaps.Lookup(0x6d000)) 141 self.assertIsNotNone(mmaps.Lookup(0xffff00ffff0000)) 142 self.assertIsNone(mmaps.Lookup(0xffff0000)) 143 144 entry = mmaps.Lookup(0xbe8b7000) 145 self.assertIsNotNone(entry) 146 self.assertEqual(entry.start, 0xbe8b7000) 147 self.assertEqual(entry.end, 0xbe8d7fff) 148 self.assertEqual(entry.mapped_offset, 0x8) 149 self.assertEqual(entry.prot_flags, 'rw-p') 150 self.assertEqual(entry.priv_dirty_bytes, 8192) 151 self.assertEqual(entry.priv_clean_bytes, 0) 152 self.assertEqual(entry.shared_dirty_bytes, 4096) 153 self.assertEqual(entry.shared_clean_bytes, 8192) 154 for i in xrange(16): 155 self.assertTrue(entry.IsPageResident(i)) 156 for i in xrange(16, 33): 157 self.assertFalse(entry.IsPageResident(i)) 158 159 # Test heap_dump parsing. 160 heap = processes[0].DumpNativeHeap() 161 self.assertEqual(len(heap.allocations), 5) 162 163 for alloc in heap.allocations: 164 self.assertTrue(alloc.size == 100 or alloc.size == 1000) 165 if alloc.size == 100: 166 self.assertEqual(alloc.size, 100) 167 self.assertEqual(alloc.stack_trace.depth, 4) 168 self.assertEqual([x.address for x in alloc.stack_trace.frames], 169 [10, 20, 30, 40]) 170 elif alloc.size == 1000: 171 self.assertEqual(alloc.size, 1000) 172 self.assertEqual(alloc.stack_trace.depth, 3) 173 self.assertEqual([x.address for x in alloc.stack_trace.frames], 174 [50, 60, 70]) 175 176 def tearDown(self): 177 self._mock_adb.Stop() 178