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