xref: /aosp_15_r20/external/angle/src/libANGLE/Decompress_unittest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2024 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // Decompress_unittest.cpp: Unit tests for the |(Compress/Decompress)*Blob| functions.
7 
8 #include <gtest/gtest.h>
9 
10 #include "libANGLE/angletypes.h"
11 
12 namespace angle
13 {
14 namespace
15 {
16 class DecompressTest : public ::testing::Test
17 {
18   protected:
SetUp()19     void SetUp() override
20     {
21         constexpr size_t kTestDataSize = 100'000;
22 
23         mTestData.resize(kTestDataSize);
24         for (size_t i = 0; i < kTestDataSize; ++i)
25         {
26             mTestData[i] = static_cast<uint8_t>(i);
27         }
28 
29         ASSERT_TRUE(CompressBlob(mTestData.size(), mTestData.data(), &mCompressedData));
30     }
31 
setCompressedDataLastDWord(uint32_t value)32     void setCompressedDataLastDWord(uint32_t value)
33     {
34         ASSERT(IsLittleEndian());
35         ASSERT(mCompressedData.size() > sizeof(value));
36         memcpy(mCompressedData.data() + mCompressedData.size() - sizeof(value), &value,
37                sizeof(value));
38     }
39 
decompress(size_t compressedSize,size_t maxUncompressedDataSize)40     bool decompress(size_t compressedSize, size_t maxUncompressedDataSize)
41     {
42         return DecompressBlob(mCompressedData.data(), compressedSize, maxUncompressedDataSize,
43                               &mUncompressedData);
44     }
45 
checkUncompressedData()46     bool checkUncompressedData()
47     {
48         return (mTestData.size() == mUncompressedData.size()) &&
49                (memcmp(mTestData.data(), mUncompressedData.data(), mTestData.size()) == 0);
50     }
51 
52     std::vector<uint8_t> mTestData;
53     MemoryBuffer mCompressedData;
54     MemoryBuffer mUncompressedData;
55 };
56 
57 // Tests that decompressing full data has no errors.
TEST_F(DecompressTest,FullData)58 TEST_F(DecompressTest, FullData)
59 {
60     EXPECT_TRUE(decompress(mCompressedData.size(), mTestData.size()));
61     EXPECT_TRUE(checkUncompressedData());
62 }
63 
64 // Tests expected failure if |maxUncompressedDataSize| is less than actual uncompressed size.
TEST_F(DecompressTest,InsufficientMaxUncompressedDataSize)65 TEST_F(DecompressTest, InsufficientMaxUncompressedDataSize)
66 {
67     EXPECT_FALSE(decompress(mCompressedData.size(), mTestData.size() - 1));
68 }
69 
70 // Tests expected failure if try to decompress partial compressed data.
TEST_F(DecompressTest,UnexpectedPartialData)71 TEST_F(DecompressTest, UnexpectedPartialData)
72 {
73     // Use this to avoid |maxUncompressedDataSize| affecting the test.
74     constexpr size_t kMaxUncompressedDataSize = std::numeric_limits<size_t>::max();
75 
76     EXPECT_FALSE(decompress(mCompressedData.size() - 1, kMaxUncompressedDataSize));
77 }
78 
79 // Tests expected failure if try to decompress corrupted data.
TEST_F(DecompressTest,CorruptedData)80 TEST_F(DecompressTest, CorruptedData)
81 {
82     // Corrupt the compressed data.
83     const size_t corruptIndex = mCompressedData.size() / 2;
84     mCompressedData[corruptIndex] ^= 255;
85 
86     EXPECT_FALSE(decompress(mCompressedData.size(), mTestData.size()));
87 }
88 
89 // Tests expected failures if try to decompress data with the corrupted last dword.
TEST_F(DecompressTest,CorruptedLastDWord)90 TEST_F(DecompressTest, CorruptedLastDWord)
91 {
92     // Last dword stores decompressed data size and not the actual compressed data. This dword must
93     // match the decompressed size. Decompress should fail if it is not the case.
94 
95     // Use this to avoid |maxUncompressedDataSize| affecting the test.
96     constexpr size_t kMaxUncompressedDataSize = std::numeric_limits<size_t>::max();
97 
98     // Try to decompress with decreased size in the last dword.
99     setCompressedDataLastDWord(static_cast<uint32_t>(mTestData.size() - 1));
100     EXPECT_FALSE(decompress(mCompressedData.size(), kMaxUncompressedDataSize));
101 
102     // Try to decompress with increased size in the last dword.
103     setCompressedDataLastDWord(static_cast<uint32_t>(mTestData.size() + 1));
104     EXPECT_FALSE(decompress(mCompressedData.size(), kMaxUncompressedDataSize));
105 
106     // Try to decompress with the last dword set to 0.
107     setCompressedDataLastDWord(0);
108     EXPECT_FALSE(decompress(mCompressedData.size(), kMaxUncompressedDataSize));
109 
110     // Decompress with the last dword set to the correct size should succeed.
111     setCompressedDataLastDWord(static_cast<uint32_t>(mTestData.size()));
112     EXPECT_TRUE(decompress(mCompressedData.size(), kMaxUncompressedDataSize));
113     EXPECT_TRUE(checkUncompressedData());
114 }
115 
116 }  // anonymous namespace
117 }  // namespace angle
118