xref: /aosp_15_r20/system/unwinding/libunwindstack/tests/MemoryXzTest.cpp (revision eb293b8f56ee8303637c5595cfcdeef8039e85c6)
1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker  * Copyright (C) 2021 The Android Open Source Project
3*eb293b8fSAndroid Build Coastguard Worker  *
4*eb293b8fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*eb293b8fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*eb293b8fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*eb293b8fSAndroid Build Coastguard Worker  *
8*eb293b8fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*eb293b8fSAndroid Build Coastguard Worker  *
10*eb293b8fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*eb293b8fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*eb293b8fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*eb293b8fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*eb293b8fSAndroid Build Coastguard Worker  * limitations under the License.
15*eb293b8fSAndroid Build Coastguard Worker  */
16*eb293b8fSAndroid Build Coastguard Worker 
17*eb293b8fSAndroid Build Coastguard Worker #include <android-base/file.h>
18*eb293b8fSAndroid Build Coastguard Worker 
19*eb293b8fSAndroid Build Coastguard Worker #include <gtest/gtest.h>
20*eb293b8fSAndroid Build Coastguard Worker 
21*eb293b8fSAndroid Build Coastguard Worker #include <MemoryBuffer.h>
22*eb293b8fSAndroid Build Coastguard Worker #include <MemoryXz.h>
23*eb293b8fSAndroid Build Coastguard Worker 
24*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
25*eb293b8fSAndroid Build Coastguard Worker 
26*eb293b8fSAndroid Build Coastguard Worker class MemoryXzTest : public ::testing::Test {
27*eb293b8fSAndroid Build Coastguard Worker  protected:
SetUp()28*eb293b8fSAndroid Build Coastguard Worker   void SetUp() override { expected_content_ = ReadFile("boot_arm.oat.gnu_debugdata"); }
29*eb293b8fSAndroid Build Coastguard Worker 
ReadFile(const char * filename)30*eb293b8fSAndroid Build Coastguard Worker   static std::unique_ptr<MemoryBuffer> ReadFile(const char* filename) {
31*eb293b8fSAndroid Build Coastguard Worker     std::string dir = android::base::GetExecutableDirectory() + "/tests/files/";
32*eb293b8fSAndroid Build Coastguard Worker     std::string data;  // NB: It is actually binary data.
33*eb293b8fSAndroid Build Coastguard Worker     EXPECT_TRUE(android::base::ReadFileToString(dir + filename, &data)) << filename;
34*eb293b8fSAndroid Build Coastguard Worker     EXPECT_GT(data.size(), 0u);
35*eb293b8fSAndroid Build Coastguard Worker     auto memory = std::make_unique<MemoryBuffer>(data.size());
36*eb293b8fSAndroid Build Coastguard Worker     EXPECT_EQ(data.size(), memory->Size());
37*eb293b8fSAndroid Build Coastguard Worker     memcpy(memory->GetPtr(0), data.data(), data.size());
38*eb293b8fSAndroid Build Coastguard Worker     return memory;
39*eb293b8fSAndroid Build Coastguard Worker   }
40*eb293b8fSAndroid Build Coastguard Worker 
VerifyContent(MemoryXz & xz,uint64_t offset,uint64_t size)41*eb293b8fSAndroid Build Coastguard Worker   void VerifyContent(MemoryXz& xz, uint64_t offset, uint64_t size) {
42*eb293b8fSAndroid Build Coastguard Worker     EXPECT_EQ(xz.Size(), expected_content_->Size());
43*eb293b8fSAndroid Build Coastguard Worker     EXPECT_LE(offset + size, expected_content_->Size());
44*eb293b8fSAndroid Build Coastguard Worker     std::vector<uint8_t> seen_content(size);
45*eb293b8fSAndroid Build Coastguard Worker     xz.ReadFully(offset, seen_content.data(), size);
46*eb293b8fSAndroid Build Coastguard Worker     EXPECT_EQ(memcmp(seen_content.data(), expected_content_->GetPtr(offset), size), 0);
47*eb293b8fSAndroid Build Coastguard Worker   }
48*eb293b8fSAndroid Build Coastguard Worker 
49*eb293b8fSAndroid Build Coastguard Worker   std::unique_ptr<MemoryBuffer> expected_content_;
50*eb293b8fSAndroid Build Coastguard Worker };
51*eb293b8fSAndroid Build Coastguard Worker 
52*eb293b8fSAndroid Build Coastguard Worker // Test the expected random-accessible format.
TEST_F(MemoryXzTest,Decompress)53*eb293b8fSAndroid Build Coastguard Worker TEST_F(MemoryXzTest, Decompress) {
54*eb293b8fSAndroid Build Coastguard Worker   auto compressed = ReadFile("boot_arm.oat.gnu_debugdata.xz");
55*eb293b8fSAndroid Build Coastguard Worker   MemoryXz xz(compressed.get(), 0, compressed->Size(), "boot_arm.oat");
56*eb293b8fSAndroid Build Coastguard Worker   EXPECT_TRUE(xz.Init());
57*eb293b8fSAndroid Build Coastguard Worker   EXPECT_GT(xz.BlockCount(), 1u);
58*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(xz.BlockSize(), 16 * 1024u);
59*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(xz.MemoryUsage(), 0u);
60*eb293b8fSAndroid Build Coastguard Worker   VerifyContent(xz, 0, expected_content_->Size());
61*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(xz.MemoryUsage(), xz.Size());
62*eb293b8fSAndroid Build Coastguard Worker }
63*eb293b8fSAndroid Build Coastguard Worker 
64*eb293b8fSAndroid Build Coastguard Worker // Test one big monolithic compressed block.
TEST_F(MemoryXzTest,DecompressOneBlock)65*eb293b8fSAndroid Build Coastguard Worker TEST_F(MemoryXzTest, DecompressOneBlock) {
66*eb293b8fSAndroid Build Coastguard Worker   auto compressed = ReadFile("boot_arm.oat.gnu_debugdata.xz.one-block");
67*eb293b8fSAndroid Build Coastguard Worker   MemoryXz xz(compressed.get(), 0, compressed->Size(), "boot_arm.oat");
68*eb293b8fSAndroid Build Coastguard Worker   EXPECT_TRUE(xz.Init());
69*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(xz.BlockCount(), 1u);
70*eb293b8fSAndroid Build Coastguard Worker   EXPECT_GT(xz.BlockSize(), xz.Size());
71*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(xz.MemoryUsage(), 0u);
72*eb293b8fSAndroid Build Coastguard Worker   VerifyContent(xz, 0, expected_content_->Size());
73*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(xz.MemoryUsage(), xz.Size());
74*eb293b8fSAndroid Build Coastguard Worker }
75*eb293b8fSAndroid Build Coastguard Worker 
76*eb293b8fSAndroid Build Coastguard Worker // Test fallback (non-consistent block sizes).
TEST_F(MemoryXzTest,DecompressOddSizes)77*eb293b8fSAndroid Build Coastguard Worker TEST_F(MemoryXzTest, DecompressOddSizes) {
78*eb293b8fSAndroid Build Coastguard Worker   auto compressed = ReadFile("boot_arm.oat.gnu_debugdata.xz.odd-sizes");
79*eb293b8fSAndroid Build Coastguard Worker   MemoryXz xz(compressed.get(), 0, compressed->Size(), "boot_arm.oat");
80*eb293b8fSAndroid Build Coastguard Worker   EXPECT_TRUE(xz.Init());
81*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(xz.BlockCount(), 1u);
82*eb293b8fSAndroid Build Coastguard Worker   EXPECT_GT(xz.BlockSize(), xz.Size());
83*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(xz.MemoryUsage(), xz.Size());
84*eb293b8fSAndroid Build Coastguard Worker   VerifyContent(xz, 0, expected_content_->Size());
85*eb293b8fSAndroid Build Coastguard Worker }
86*eb293b8fSAndroid Build Coastguard Worker 
87*eb293b8fSAndroid Build Coastguard Worker // Test fallback (non-power-of-2 block size).
TEST_F(MemoryXzTest,DecompressNonPower)88*eb293b8fSAndroid Build Coastguard Worker TEST_F(MemoryXzTest, DecompressNonPower) {
89*eb293b8fSAndroid Build Coastguard Worker   auto compressed = ReadFile("boot_arm.oat.gnu_debugdata.xz.non-power");
90*eb293b8fSAndroid Build Coastguard Worker   MemoryXz xz(compressed.get(), 0, compressed->Size(), "boot_arm.oat");
91*eb293b8fSAndroid Build Coastguard Worker   EXPECT_TRUE(xz.Init());
92*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(xz.BlockCount(), 1u);
93*eb293b8fSAndroid Build Coastguard Worker   EXPECT_GT(xz.BlockSize(), xz.Size());
94*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(xz.MemoryUsage(), xz.Size());
95*eb293b8fSAndroid Build Coastguard Worker   VerifyContent(xz, 0, expected_content_->Size());
96*eb293b8fSAndroid Build Coastguard Worker }
97*eb293b8fSAndroid Build Coastguard Worker 
98*eb293b8fSAndroid Build Coastguard Worker // Read first byte of some blocks.
TEST_F(MemoryXzTest,ReadFirstByte)99*eb293b8fSAndroid Build Coastguard Worker TEST_F(MemoryXzTest, ReadFirstByte) {
100*eb293b8fSAndroid Build Coastguard Worker   auto compressed = ReadFile("boot_arm.oat.gnu_debugdata.xz");
101*eb293b8fSAndroid Build Coastguard Worker   MemoryXz xz(compressed.get(), 0, compressed->Size(), "boot_arm.oat");
102*eb293b8fSAndroid Build Coastguard Worker   EXPECT_TRUE(xz.Init());
103*eb293b8fSAndroid Build Coastguard Worker   EXPECT_GT(xz.BlockCount(), 1u);
104*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(xz.BlockSize(), 16 * 1024u);
105*eb293b8fSAndroid Build Coastguard Worker   for (size_t i = 0; i < xz.BlockCount(); i += 3) {
106*eb293b8fSAndroid Build Coastguard Worker     VerifyContent(xz, i * xz.BlockSize(), 1);
107*eb293b8fSAndroid Build Coastguard Worker   }
108*eb293b8fSAndroid Build Coastguard Worker   EXPECT_LT(xz.MemoryUsage(), xz.Size());  // We didn't decompress all blocks.
109*eb293b8fSAndroid Build Coastguard Worker }
110*eb293b8fSAndroid Build Coastguard Worker 
111*eb293b8fSAndroid Build Coastguard Worker // Read last byte of some blocks.
TEST_F(MemoryXzTest,ReadLastByte)112*eb293b8fSAndroid Build Coastguard Worker TEST_F(MemoryXzTest, ReadLastByte) {
113*eb293b8fSAndroid Build Coastguard Worker   auto compressed = ReadFile("boot_arm.oat.gnu_debugdata.xz");
114*eb293b8fSAndroid Build Coastguard Worker   MemoryXz xz(compressed.get(), 0, compressed->Size(), "boot_arm.oat");
115*eb293b8fSAndroid Build Coastguard Worker   EXPECT_TRUE(xz.Init());
116*eb293b8fSAndroid Build Coastguard Worker   EXPECT_GT(xz.BlockCount(), 1u);
117*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(xz.BlockSize(), 16 * 1024u);
118*eb293b8fSAndroid Build Coastguard Worker   for (size_t i = 1; i < xz.BlockCount(); i += 3) {
119*eb293b8fSAndroid Build Coastguard Worker     VerifyContent(xz, i * xz.BlockSize() - 1, 1);
120*eb293b8fSAndroid Build Coastguard Worker   }
121*eb293b8fSAndroid Build Coastguard Worker   EXPECT_LT(xz.MemoryUsage(), xz.Size());  // We didn't decompress all blocks.
122*eb293b8fSAndroid Build Coastguard Worker }
123*eb293b8fSAndroid Build Coastguard Worker 
124*eb293b8fSAndroid Build Coastguard Worker // Read across boundary of blocks.
TEST_F(MemoryXzTest,ReadBoundary)125*eb293b8fSAndroid Build Coastguard Worker TEST_F(MemoryXzTest, ReadBoundary) {
126*eb293b8fSAndroid Build Coastguard Worker   auto compressed = ReadFile("boot_arm.oat.gnu_debugdata.xz");
127*eb293b8fSAndroid Build Coastguard Worker   MemoryXz xz(compressed.get(), 0, compressed->Size(), "boot_arm.oat");
128*eb293b8fSAndroid Build Coastguard Worker   EXPECT_TRUE(xz.Init());
129*eb293b8fSAndroid Build Coastguard Worker   EXPECT_GT(xz.BlockCount(), 1u);
130*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(xz.BlockSize(), 16 * 1024u);
131*eb293b8fSAndroid Build Coastguard Worker   for (size_t i = 1; i < xz.BlockCount(); i += 3) {
132*eb293b8fSAndroid Build Coastguard Worker     VerifyContent(xz, i * xz.BlockSize() - 1, 2);
133*eb293b8fSAndroid Build Coastguard Worker   }
134*eb293b8fSAndroid Build Coastguard Worker   EXPECT_LT(xz.MemoryUsage(), xz.Size());  // We didn't decompress all blocks.
135*eb293b8fSAndroid Build Coastguard Worker }
136*eb293b8fSAndroid Build Coastguard Worker 
137*eb293b8fSAndroid Build Coastguard Worker }  // namespace unwindstack
138