| // Copyright 2019 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/profiler/chrome_unwind_info_android.h" |
| |
| #include <tuple> |
| |
| #include "base/test/gtest_util.h" |
| #include "build/build_config.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace base { |
| |
| bool operator==(const FunctionTableEntry& e1, const FunctionTableEntry& e2) { |
| return std::tie(e1.function_start_address_page_instruction_offset, |
| e1.function_offset_table_byte_index) == |
| std::tie(e2.function_start_address_page_instruction_offset, |
| e2.function_offset_table_byte_index); |
| } |
| |
| template <class T, size_t E1, size_t E2> |
| void ExpectSpanSizeAndContentsEqual(span<T, E1> actual, span<T, E2> expected) { |
| EXPECT_EQ(actual.size(), expected.size()); |
| if (actual.size() != expected.size()) { |
| return; |
| } |
| |
| for (size_t i = 0; i < actual.size(); i++) { |
| EXPECT_EQ(actual[i], expected[i]); |
| } |
| } |
| |
| TEST(ChromeUnwindInfoAndroidTest, CreateUnwindInfo) { |
| ChromeUnwindInfoHeaderAndroid header = { |
| /* page_table_byte_offset */ 64, |
| /* page_table_entries */ 1, |
| |
| /* function_table_byte_offset */ 128, |
| /* function_table_entries */ 2, |
| |
| /* function_offset_table_byte_offset */ 192, |
| /* function_offset_table_size_in_bytes */ 3, |
| |
| /* unwind_instruction_table_byte_offset */ 256, |
| /* unwind_instruction_table_size_in_bytes */ 4, |
| }; |
| |
| uint8_t data[512] = {}; |
| // Note: `CreateChromeUnwindInfoAndroid` is not expected to verify the content |
| // of each unwind table. |
| const uint32_t page_table[] = {1}; |
| const FunctionTableEntry function_table[] = {{0, 2}, {0, 3}}; |
| const uint8_t function_offset_table[] = {3, 3, 3}; |
| const uint8_t unwind_instruction_table[] = {4, 4, 4, 4}; |
| |
| ASSERT_LT(sizeof(ChromeUnwindInfoHeaderAndroid), 64ul); |
| memcpy(&data[0], &header, sizeof(ChromeUnwindInfoHeaderAndroid)); |
| |
| memcpy(&data[header.page_table_byte_offset], page_table, sizeof(page_table)); |
| memcpy(&data[header.function_table_byte_offset], function_table, |
| sizeof(function_table)); |
| memcpy(&data[header.function_offset_table_byte_offset], function_offset_table, |
| sizeof(function_offset_table)); |
| memcpy(&data[header.unwind_instruction_table_byte_offset], |
| unwind_instruction_table, sizeof(unwind_instruction_table)); |
| |
| ChromeUnwindInfoAndroid unwind_info = CreateChromeUnwindInfoAndroid(data); |
| |
| ASSERT_EQ(&data[64], |
| reinterpret_cast<const uint8_t*>(&unwind_info.page_table[0])); |
| ASSERT_EQ(&data[128], |
| reinterpret_cast<const uint8_t*>(&unwind_info.function_table[0])); |
| ASSERT_EQ(&data[192], reinterpret_cast<const uint8_t*>( |
| &unwind_info.function_offset_table[0])); |
| ASSERT_EQ(&data[256], reinterpret_cast<const uint8_t*>( |
| &unwind_info.unwind_instruction_table[0])); |
| |
| ExpectSpanSizeAndContentsEqual(unwind_info.page_table, make_span(page_table)); |
| ExpectSpanSizeAndContentsEqual(unwind_info.function_table, |
| make_span(function_table)); |
| ExpectSpanSizeAndContentsEqual(unwind_info.function_offset_table, |
| make_span(function_offset_table)); |
| ExpectSpanSizeAndContentsEqual(unwind_info.unwind_instruction_table, |
| make_span(unwind_instruction_table)); |
| } |
| |
| } // namespace base |