1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <stdint.h>
18 
19 #include <vector>
20 
21 #include <gtest/gtest.h>
22 
23 #include "MemoryCache.h"
24 #include "utils/MemoryFake.h"
25 
26 namespace unwindstack {
27 
28 class MemoryCacheTest : public ::testing::Test {
29  protected:
SetUp()30   void SetUp() override {
31     memory_ = new MemoryFake;
32     memory_cache_.reset(new MemoryCache(memory_));
33 
34     memory_->SetMemoryBlock(0x8000, 4096, 0xab);
35     memory_->SetMemoryBlock(0x9000, 4096, 0xde);
36     memory_->SetMemoryBlock(0xa000, 3000, 0x50);
37   }
38 
39   MemoryFake* memory_;
40   std::unique_ptr<MemoryCache> memory_cache_;
41 
42   constexpr static size_t kMaxCachedSize = 64;
43 };
44 
TEST_F(MemoryCacheTest,cached_read)45 TEST_F(MemoryCacheTest, cached_read) {
46   for (size_t i = 1; i <= kMaxCachedSize; i++) {
47     std::vector<uint8_t> buffer(i);
48     ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i))
49         << "Read failed at size " << i;
50     ASSERT_EQ(std::vector<uint8_t>(i, 0xab), buffer) << "Failed at size " << i;
51   }
52 
53   // Verify the cached data is used.
54   memory_->SetMemoryBlock(0x8000, 4096, 0xff);
55   for (size_t i = 1; i <= kMaxCachedSize; i++) {
56     std::vector<uint8_t> buffer(i);
57     ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i))
58         << "Read failed at size " << i;
59     ASSERT_EQ(std::vector<uint8_t>(i, 0xab), buffer) << "Failed at size " << i;
60   }
61 }
62 
TEST_F(MemoryCacheTest,no_cached_read_after_clear)63 TEST_F(MemoryCacheTest, no_cached_read_after_clear) {
64   for (size_t i = 1; i <= kMaxCachedSize; i++) {
65     std::vector<uint8_t> buffer(i);
66     ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i))
67         << "Read failed at size " << i;
68     ASSERT_EQ(std::vector<uint8_t>(i, 0xab), buffer) << "Failed at size " << i;
69   }
70 
71   // Verify the cached data is not used after a reset.
72   memory_cache_->Clear();
73   memory_->SetMemoryBlock(0x8000, 4096, 0xff);
74   for (size_t i = 1; i <= kMaxCachedSize; i++) {
75     std::vector<uint8_t> buffer(i);
76     ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i))
77         << "Read failed at size " << i;
78     ASSERT_EQ(std::vector<uint8_t>(i, 0xff), buffer) << "Failed at size " << i;
79   }
80 }
81 
TEST_F(MemoryCacheTest,cached_read_across_caches)82 TEST_F(MemoryCacheTest, cached_read_across_caches) {
83   std::vector<uint8_t> expect(16, 0xab);
84   expect.resize(32, 0xde);
85 
86   std::vector<uint8_t> buffer(32);
87   ASSERT_TRUE(memory_cache_->ReadFully(0x8ff0, buffer.data(), 32));
88   ASSERT_EQ(expect, buffer);
89 
90   // Verify the cached data is used.
91   memory_->SetMemoryBlock(0x8000, 4096, 0xff);
92   memory_->SetMemoryBlock(0x9000, 4096, 0xff);
93   ASSERT_TRUE(memory_cache_->ReadFully(0x8ff0, buffer.data(), 32));
94   ASSERT_EQ(expect, buffer);
95 }
96 
TEST_F(MemoryCacheTest,no_cache_read)97 TEST_F(MemoryCacheTest, no_cache_read) {
98   for (size_t i = kMaxCachedSize + 1; i < 2 * kMaxCachedSize; i++) {
99     std::vector<uint8_t> buffer(i);
100     ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i))
101         << "Read failed at size " << i;
102     ASSERT_EQ(std::vector<uint8_t>(i, 0xab), buffer) << "Failed at size " << i;
103   }
104 
105   // Verify the cached data is not used.
106   memory_->SetMemoryBlock(0x8000, 4096, 0xff);
107   for (size_t i = kMaxCachedSize + 1; i < 2 * kMaxCachedSize; i++) {
108     std::vector<uint8_t> buffer(i);
109     ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i))
110         << "Read failed at size " << i;
111     ASSERT_EQ(std::vector<uint8_t>(i, 0xff), buffer) << "Failed at size " << i;
112   }
113 }
114 
TEST_F(MemoryCacheTest,read_for_cache_fail)115 TEST_F(MemoryCacheTest, read_for_cache_fail) {
116   std::vector<uint8_t> buffer(kMaxCachedSize);
117   ASSERT_TRUE(memory_cache_->ReadFully(0xa010, buffer.data(), kMaxCachedSize));
118   ASSERT_EQ(std::vector<uint8_t>(kMaxCachedSize, 0x50), buffer);
119 
120   // Verify the cached data is not used.
121   memory_->SetMemoryBlock(0xa000, 3000, 0xff);
122   ASSERT_TRUE(memory_cache_->ReadFully(0xa010, buffer.data(), kMaxCachedSize));
123   ASSERT_EQ(std::vector<uint8_t>(kMaxCachedSize, 0xff), buffer);
124 }
125 
TEST_F(MemoryCacheTest,read_for_cache_fail_cross)126 TEST_F(MemoryCacheTest, read_for_cache_fail_cross) {
127   std::vector<uint8_t> expect(16, 0xde);
128   expect.resize(32, 0x50);
129 
130   std::vector<uint8_t> buffer(32);
131   ASSERT_TRUE(memory_cache_->ReadFully(0x9ff0, buffer.data(), 32));
132   ASSERT_EQ(expect, buffer);
133 
134   // Verify the cached data is not used for the second half but for the first.
135   memory_->SetMemoryBlock(0xa000, 3000, 0xff);
136   ASSERT_TRUE(memory_cache_->ReadFully(0x9ff0, buffer.data(), 32));
137   expect.resize(16);
138   expect.resize(32, 0xff);
139   ASSERT_EQ(expect, buffer);
140 }
141 
142 }  // namespace unwindstack
143