1723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris/*
2723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * Copyright (C) 2016 The Android Open Source Project
3723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris *
4723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * Licensed under the Apache License, Version 2.0 (the "License");
5723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * you may not use this file except in compliance with the License.
6723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * You may obtain a copy of the License at
7723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris *
8723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris *      http://www.apache.org/licenses/LICENSE-2.0
9723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris *
10723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * Unless required by applicable law or agreed to in writing, software
11723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * distributed under the License is distributed on an "AS IS" BASIS,
12723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * See the License for the specific language governing permissions and
14723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * limitations under the License.
15723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris */
16723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
17f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris#include <string>
18f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris#include <vector>
19f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris
20723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris#include <android-base/test_utils.h>
21723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris#include <android-base/file.h>
22723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris#include <gtest/gtest.h>
23723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
24d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/Memory.h>
25d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris
26d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferrisnamespace unwindstack {
27723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
28723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisclass MemoryFileTest : public ::testing::Test {
29723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris protected:
30723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  void SetUp() override {
31723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    tf_ = new TemporaryFile;
32723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
33723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
34723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  void TearDown() override {
35723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    delete tf_;
36723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
37723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
38723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  void WriteTestData() {
39723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    ASSERT_TRUE(android::base::WriteStringToFd("0123456789abcdefghijklmnopqrstuvxyz", tf_->fd));
40723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
41723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
42723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  MemoryFileAtOffset memory_;
43723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
44723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  TemporaryFile* tf_ = nullptr;
45723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris};
46723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
47f447c8eb205d899085968a0a8dfae861ef56a589Christopher FerrisTEST_F(MemoryFileTest, init_offset_0) {
48723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  WriteTestData();
49723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
50723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  ASSERT_TRUE(memory_.Init(tf_->path, 0));
51723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  std::vector<char> buffer(11);
52ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_TRUE(memory_.ReadFully(0, buffer.data(), 10));
53723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  buffer[10] = '\0';
54723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  ASSERT_STREQ("0123456789", buffer.data());
55723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
56723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
57f447c8eb205d899085968a0a8dfae861ef56a589Christopher FerrisTEST_F(MemoryFileTest, init_offset_non_zero) {
58723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  WriteTestData();
59723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
60723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  ASSERT_TRUE(memory_.Init(tf_->path, 10));
61723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  std::vector<char> buffer(11);
62ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_TRUE(memory_.ReadFully(0, buffer.data(), 10));
63723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  buffer[10] = '\0';
64723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  ASSERT_STREQ("abcdefghij", buffer.data());
65723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
66723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
67f447c8eb205d899085968a0a8dfae861ef56a589Christopher FerrisTEST_F(MemoryFileTest, init_offset_non_zero_larger_than_pagesize) {
68723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  size_t pagesize = getpagesize();
69723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  std::string large_string;
70723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  for (size_t i = 0; i < pagesize; i++) {
71723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    large_string += '1';
72723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
73723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  large_string += "012345678901234abcdefgh";
74723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  ASSERT_TRUE(android::base::WriteStringToFd(large_string, tf_->fd));
75723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
76723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  ASSERT_TRUE(memory_.Init(tf_->path, pagesize + 15));
77723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  std::vector<char> buffer(9);
78ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_TRUE(memory_.ReadFully(0, buffer.data(), 8));
79723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  buffer[8] = '\0';
80723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  ASSERT_STREQ("abcdefgh", buffer.data());
81723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
82723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
83f447c8eb205d899085968a0a8dfae861ef56a589Christopher FerrisTEST_F(MemoryFileTest, init_offset_pagesize_aligned) {
84723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  size_t pagesize = getpagesize();
85723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  std::string data;
86723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  for (size_t i = 0; i < 2 * pagesize; i++) {
87723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    data += static_cast<char>((i / pagesize) + '0');
88723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    data += static_cast<char>((i % 10) + '0');
89723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
90723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  ASSERT_TRUE(android::base::WriteStringToFd(data, tf_->fd));
913958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris
92723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  ASSERT_TRUE(memory_.Init(tf_->path, 2 * pagesize));
93723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  std::vector<char> buffer(11);
94ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_TRUE(memory_.ReadFully(0, buffer.data(), 10));
95723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  buffer[10] = '\0';
96723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  std::string expected_str;
97723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  for (size_t i = 0; i < 5; i++) {
98723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    expected_str += '1';
99723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    expected_str += static_cast<char>(((i + pagesize) % 10) + '0');
100723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
101723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  ASSERT_STREQ(expected_str.c_str(), buffer.data());
102723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
103723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
104f447c8eb205d899085968a0a8dfae861ef56a589Christopher FerrisTEST_F(MemoryFileTest, init_offset_pagesize_aligned_plus_extra) {
105723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  size_t pagesize = getpagesize();
106723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  std::string data;
107723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  for (size_t i = 0; i < 2 * pagesize; i++) {
108723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    data += static_cast<char>((i / pagesize) + '0');
109723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    data += static_cast<char>((i % 10) + '0');
110723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
111723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  ASSERT_TRUE(android::base::WriteStringToFd(data, tf_->fd));
1123958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris
113723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  ASSERT_TRUE(memory_.Init(tf_->path, 2 * pagesize + 10));
114723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  std::vector<char> buffer(11);
115ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_TRUE(memory_.ReadFully(0, buffer.data(), 10));
116723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  buffer[10] = '\0';
117723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  std::string expected_str;
118723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  for (size_t i = 0; i < 5; i++) {
119723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    expected_str += '1';
120723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    expected_str += static_cast<char>(((i + pagesize + 5) % 10) + '0');
121723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
122723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  ASSERT_STREQ(expected_str.c_str(), buffer.data());
123723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
124723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
125f447c8eb205d899085968a0a8dfae861ef56a589Christopher FerrisTEST_F(MemoryFileTest, init_offset_greater_than_filesize) {
126f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris  size_t pagesize = getpagesize();
127f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris  std::string data;
128f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris  uint64_t file_size = 2 * pagesize + pagesize / 2;
129f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris  for (size_t i = 0; i < file_size; i++) {
130f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris    data += static_cast<char>((i / pagesize) + '0');
131f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris  }
132f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris  ASSERT_TRUE(android::base::WriteStringToFd(data, tf_->fd));
133f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris
134f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris  // Check offset > file size fails and aligned_offset > file size.
135f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris  ASSERT_FALSE(memory_.Init(tf_->path, file_size + 2 * pagesize));
136f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris  // Check offset == filesize fails.
137f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris  ASSERT_FALSE(memory_.Init(tf_->path, file_size));
138f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris  // Check aligned_offset < filesize, but offset > filesize fails.
139f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris  ASSERT_FALSE(memory_.Init(tf_->path, 2 * pagesize + pagesize / 2 + pagesize / 4));
140f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris}
141f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris
142723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher FerrisTEST_F(MemoryFileTest, read_error) {
143723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  std::string data;
144723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  for (size_t i = 0; i < 5000; i++) {
145723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris    data += static_cast<char>((i % 10) + '0');
146723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  }
147723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  ASSERT_TRUE(android::base::WriteStringToFd(data, tf_->fd));
148723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
149723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  std::vector<char> buffer(100);
150723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
151723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  // Read before init.
152ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_FALSE(memory_.ReadFully(0, buffer.data(), 10));
153723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
154723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris  ASSERT_TRUE(memory_.Init(tf_->path, 0));
155723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
156ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_FALSE(memory_.ReadFully(10000, buffer.data(), 10));
157ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_FALSE(memory_.ReadFully(5000, buffer.data(), 10));
158ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_FALSE(memory_.ReadFully(4990, buffer.data(), 11));
159ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_TRUE(memory_.ReadFully(4990, buffer.data(), 10));
160ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_FALSE(memory_.ReadFully(4999, buffer.data(), 2));
161ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_TRUE(memory_.ReadFully(4999, buffer.data(), 1));
162723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris
163f447c8eb205d899085968a0a8dfae861ef56a589Christopher Ferris  // Check that overflow fails properly.
164ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_FALSE(memory_.ReadFully(UINT64_MAX - 100, buffer.data(), 200));
165723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris}
1663958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris
1673958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher FerrisTEST_F(MemoryFileTest, read_past_file_within_mapping) {
1683958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  size_t pagesize = getpagesize();
1693958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris
1703958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  ASSERT_TRUE(pagesize > 100);
1713958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  std::vector<uint8_t> buffer(pagesize - 100);
1723958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  for (size_t i = 0; i < pagesize - 100; i++) {
1733958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris    buffer[i] = static_cast<uint8_t>((i % 0x5e) + 0x20);
1743958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  }
1753958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size()));
1763958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris
1773958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  ASSERT_TRUE(memory_.Init(tf_->path, 0));
1783958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris
1793958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  for (size_t i = 0; i < 100; i++) {
1803958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris    uint8_t value;
181ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao    ASSERT_FALSE(memory_.ReadFully(buffer.size() + i, &value, 1))
182ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao        << "Should have failed at value " << i;
1833958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  }
1843958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris}
1853958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris
1863958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher FerrisTEST_F(MemoryFileTest, map_partial_offset_aligned) {
1873958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  size_t pagesize = getpagesize();
1883958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  std::vector<uint8_t> buffer(pagesize * 10);
1893958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  for (size_t i = 0; i < pagesize * 10; i++) {
1903958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris    buffer[i] = i / pagesize + 1;
1913958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  }
1923958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size()));
1933958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris
1943958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  // Map in only two pages of the data, and after the first page.
1953958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  ASSERT_TRUE(memory_.Init(tf_->path, pagesize, pagesize * 2));
1963958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris
1973958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  std::vector<uint8_t> read_buffer(pagesize * 2);
1983958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  // Make sure that reading after mapped data is a failure.
199ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_FALSE(memory_.ReadFully(pagesize * 2, read_buffer.data(), 1));
200ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_TRUE(memory_.ReadFully(0, read_buffer.data(), pagesize * 2));
2013958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  for (size_t i = 0; i < pagesize; i++) {
2023958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris    ASSERT_EQ(2, read_buffer[i]) << "Failed at byte " << i;
2033958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  }
2043958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  for (size_t i = pagesize; i < pagesize * 2; i++) {
2053958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris    ASSERT_EQ(3, read_buffer[i]) << "Failed at byte " << i;
2063958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  }
2073958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris}
2083958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris
2093958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher FerrisTEST_F(MemoryFileTest, map_partial_offset_unaligned) {
2103958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  size_t pagesize = getpagesize();
2113958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  ASSERT_TRUE(pagesize > 0x100);
2123958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  std::vector<uint8_t> buffer(pagesize * 10);
2133958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  for (size_t i = 0; i < buffer.size(); i++) {
2143958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris    buffer[i] = i / pagesize + 1;
2153958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  }
2163958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size()));
2173958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris
2183958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  // Map in only two pages of the data, and after the first page.
2193958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  ASSERT_TRUE(memory_.Init(tf_->path, pagesize + 0x100, pagesize * 2));
2203958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris
2213958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  std::vector<uint8_t> read_buffer(pagesize * 2);
2223958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  // Make sure that reading after mapped data is a failure.
223ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_FALSE(memory_.ReadFully(pagesize * 2, read_buffer.data(), 1));
224ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_TRUE(memory_.ReadFully(0, read_buffer.data(), pagesize * 2));
2253958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  for (size_t i = 0; i < pagesize - 0x100; i++) {
2263958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris    ASSERT_EQ(2, read_buffer[i]) << "Failed at byte " << i;
2273958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  }
2283958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  for (size_t i = pagesize - 0x100; i < 2 * pagesize - 0x100; i++) {
2293958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris    ASSERT_EQ(3, read_buffer[i]) << "Failed at byte " << i;
2303958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  }
2313958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  for (size_t i = 2 * pagesize - 0x100; i < pagesize * 2; i++) {
2323958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris    ASSERT_EQ(4, read_buffer[i]) << "Failed at byte " << i;
2333958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  }
2343958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris}
2353958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris
2363958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher FerrisTEST_F(MemoryFileTest, map_overflow) {
2373958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  size_t pagesize = getpagesize();
2383958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  ASSERT_TRUE(pagesize > 0x100);
2393958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  std::vector<uint8_t> buffer(pagesize * 10);
2403958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  for (size_t i = 0; i < buffer.size(); i++) {
2413958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris    buffer[i] = i / pagesize + 1;
2423958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  }
2433958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size()));
2443958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris
2453958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  // Map in only two pages of the data, and after the first page.
2463958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  ASSERT_TRUE(memory_.Init(tf_->path, pagesize + 0x100, UINT64_MAX));
2473958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris
2483958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  std::vector<uint8_t> read_buffer(pagesize * 10);
249ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_FALSE(memory_.ReadFully(pagesize * 9 - 0x100 + 1, read_buffer.data(), 1));
250ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_TRUE(memory_.ReadFully(0, read_buffer.data(), pagesize * 9 - 0x100));
2513958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris}
2523958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris
2533958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher FerrisTEST_F(MemoryFileTest, init_reinit) {
2543958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  size_t pagesize = getpagesize();
2553958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  std::vector<uint8_t> buffer(pagesize * 2);
2563958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  for (size_t i = 0; i < buffer.size(); i++) {
2573958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris    buffer[i] = i / pagesize + 1;
2583958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  }
2593958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size()));
2603958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris
2613958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  ASSERT_TRUE(memory_.Init(tf_->path, 0));
2623958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  std::vector<uint8_t> read_buffer(buffer.size());
263ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_TRUE(memory_.ReadFully(0, read_buffer.data(), pagesize));
2643958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  for (size_t i = 0; i < pagesize; i++) {
2653958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris    ASSERT_EQ(1, read_buffer[i]) << "Failed at byte " << i;
2663958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  }
2673958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris
2683958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  // Now reinit.
2693958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  ASSERT_TRUE(memory_.Init(tf_->path, pagesize));
270ef35aa5d40b6404baf702a58527f1cd3a9f42f19Josh Gao  ASSERT_TRUE(memory_.ReadFully(0, read_buffer.data(), pagesize));
2713958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  for (size_t i = 0; i < pagesize; i++) {
2723958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris    ASSERT_EQ(2, read_buffer[i]) << "Failed at byte " << i;
2733958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris  }
2743958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris}
275d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris
276d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris}  // namespace unwindstack
277