You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
184 lines
6.0 KiB
184 lines
6.0 KiB
#!/usr/bin/env python
|
|
#
|
|
# Copyright (C) 2018 The Android Open Source Project
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
"""Tests for the native_heapdump_viewer script."""
|
|
|
|
import native_heapdump_viewer
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
|
|
class NativeHeapdumpViewerTest(unittest.TestCase):
|
|
_tmp_file_name = None
|
|
|
|
def CreateTmpFile(self, contents):
|
|
fd, self._tmp_file_name = tempfile.mkstemp()
|
|
os.write(fd, contents.encode())
|
|
os.close(fd)
|
|
return self._tmp_file_name
|
|
|
|
def tearDown(self):
|
|
if self._tmp_file_name:
|
|
try:
|
|
os.unlink(self._tmp_file_name)
|
|
except Exception:
|
|
print("Failed to delete %s" % (heap))
|
|
|
|
class GetNumFieldValidTest(NativeHeapdumpViewerTest):
|
|
_map_data = """
|
|
MAPS
|
|
1000-10000 r-xp 00000000 fd:00 495 /data/does_not_exist.so
|
|
END
|
|
"""
|
|
|
|
_heap_num_field_valid_version10 = """
|
|
Android Native Heap Dump v1.0
|
|
|
|
Total memory: 33800
|
|
Allocation records: 13
|
|
Backtrace size: 16
|
|
|
|
z 1 sz 1000 num 4 bt 1000 2000 3000
|
|
z 1 sz 2000 num 6 bt 1100 2100 3100
|
|
z 0 sz 1200 num 1 bt 1200 2200 3200
|
|
z 0 sz 8300 num 2 bt 1300 2300 3300
|
|
"""
|
|
|
|
_heap_num_field_invalid_version10 = """
|
|
Android Native Heap Dump v1.0
|
|
|
|
Total memory: 12500
|
|
Allocation records: 4
|
|
Backtrace size: 16
|
|
|
|
z 1 sz 1000 num 16 bt 1000 2000 3000
|
|
z 1 sz 2000 num 16 bt 1100 2100 3100
|
|
z 0 sz 1200 num 16 bt 1200 2200 3200
|
|
z 0 sz 8300 num 16 bt 1300 2300 3300
|
|
"""
|
|
|
|
_heap_data = """
|
|
|
|
Total memory: 200000
|
|
Allocation records: 64
|
|
Backtrace size: 16
|
|
|
|
z 1 sz 1000 num 16 bt 1000 2000 3000
|
|
z 1 sz 2000 num 16 bt 1100 2100 3100
|
|
z 0 sz 1200 num 16 bt 1200 2200 3200
|
|
z 0 sz 8300 num 16 bt 1300 2300 3300
|
|
"""
|
|
|
|
def test_version10_valid(self):
|
|
heap = self.CreateTmpFile(self._heap_num_field_valid_version10 + self._map_data)
|
|
self.assertTrue(native_heapdump_viewer.GetNumFieldValid(heap))
|
|
|
|
def test_version10_invalid(self):
|
|
heap = self.CreateTmpFile(self._heap_num_field_invalid_version10 + self._map_data)
|
|
self.assertFalse(native_heapdump_viewer.GetNumFieldValid(heap))
|
|
|
|
def test_version11_valid(self):
|
|
heap = self.CreateTmpFile("Android Native Heap Dump v1.1" + self._heap_data + self._map_data)
|
|
self.assertTrue(native_heapdump_viewer.GetNumFieldValid(heap))
|
|
|
|
def test_version12_valid(self):
|
|
heap = self.CreateTmpFile("Android Native Heap Dump v1.2" + self._heap_data + self._map_data)
|
|
self.assertTrue(native_heapdump_viewer.GetNumFieldValid(heap))
|
|
|
|
class ParseNativeHeapTest(NativeHeapdumpViewerTest):
|
|
_backtrace_data = """
|
|
z 1 sz 1000 num 4 bt 1000 2000 3000
|
|
z 0 sz 8300 num 5 bt 1300 2300 3300
|
|
"""
|
|
|
|
|
|
def test_backtrace_num_field_valid(self):
|
|
heap = self.CreateTmpFile(self._backtrace_data)
|
|
backtraces, mapppings = native_heapdump_viewer.ParseNativeHeap(heap, False, True, "")
|
|
self.assertTrue(backtraces)
|
|
self.assertEqual(2, len(backtraces))
|
|
|
|
self.assertFalse(backtraces[0].is_zygote)
|
|
self.assertEqual(1000, backtraces[0].size)
|
|
self.assertEqual(4, backtraces[0].num_allocs)
|
|
self.assertEqual([0x1000, 0x2000, 0x3000], backtraces[0].frames)
|
|
|
|
self.assertTrue(backtraces[1].is_zygote)
|
|
self.assertEqual(8300, backtraces[1].size)
|
|
self.assertEqual(5, backtraces[1].num_allocs)
|
|
self.assertEqual([0x1300, 0x2300, 0x3300], backtraces[1].frames)
|
|
|
|
def test_backtrace_num_field_invalid(self):
|
|
heap = self.CreateTmpFile(self._backtrace_data)
|
|
backtraces, mapppings = native_heapdump_viewer.ParseNativeHeap(heap, False, False, "")
|
|
self.assertTrue(backtraces)
|
|
self.assertEqual(2, len(backtraces))
|
|
|
|
self.assertFalse(backtraces[0].is_zygote)
|
|
self.assertEqual(1000, backtraces[0].size)
|
|
self.assertEqual(1, backtraces[0].num_allocs)
|
|
self.assertEqual([0x1000, 0x2000, 0x3000], backtraces[0].frames)
|
|
|
|
self.assertTrue(backtraces[1].is_zygote)
|
|
self.assertEqual(8300, backtraces[1].size)
|
|
self.assertEqual(1, backtraces[1].num_allocs)
|
|
self.assertEqual([0x1300, 0x2300, 0x3300], backtraces[1].frames)
|
|
|
|
def test_backtrace_reverse_field_valid(self):
|
|
heap = self.CreateTmpFile(self._backtrace_data)
|
|
backtraces, mapppings = native_heapdump_viewer.ParseNativeHeap(heap, True, True, "")
|
|
self.assertTrue(backtraces)
|
|
self.assertEqual(2, len(backtraces))
|
|
|
|
self.assertFalse(backtraces[0].is_zygote)
|
|
self.assertEqual(1000, backtraces[0].size)
|
|
self.assertEqual(4, backtraces[0].num_allocs)
|
|
self.assertEqual([0x3000, 0x2000, 0x1000], backtraces[0].frames)
|
|
|
|
self.assertTrue(backtraces[1].is_zygote)
|
|
self.assertEqual(8300, backtraces[1].size)
|
|
self.assertEqual(5, backtraces[1].num_allocs)
|
|
self.assertEqual([0x3300, 0x2300, 0x1300], backtraces[1].frames)
|
|
|
|
def test_mappings(self):
|
|
map_data = """
|
|
MAPS
|
|
1000-4000 r-xp 00000000 fd:00 495 /system/lib64/libc.so
|
|
6000-8000 r-xp 00000000 fd:00 495
|
|
a000-f000 r-xp 0000b000 fd:00 495 /system/lib64/libutils.so
|
|
END
|
|
"""
|
|
|
|
heap = self.CreateTmpFile(map_data)
|
|
backtraces, mappings = native_heapdump_viewer.ParseNativeHeap(heap, True, True, "")
|
|
|
|
self.assertTrue(mappings)
|
|
self.assertEqual(2, len(mappings))
|
|
|
|
self.assertEqual(0x1000, mappings[0].start)
|
|
self.assertEqual(0x4000, mappings[0].end)
|
|
self.assertEqual(0, mappings[0].offset)
|
|
self.assertEqual("/system/lib64/libc.so", mappings[0].name)
|
|
|
|
self.assertEqual(0xa000, mappings[1].start)
|
|
self.assertEqual(0xf000, mappings[1].end)
|
|
self.assertEqual(0xb000, mappings[1].offset)
|
|
self.assertEqual("/system/lib64/libutils.so", mappings[1].name)
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main(verbosity=2)
|