| // |
| // Copyright 2024 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // Decompress_unittest.cpp: Unit tests for the |(Compress/Decompress)*Blob| functions. |
| |
| #include <gtest/gtest.h> |
| |
| #include "libANGLE/angletypes.h" |
| |
| namespace angle |
| { |
| namespace |
| { |
| class DecompressTest : public ::testing::Test |
| { |
| protected: |
| void SetUp() override |
| { |
| constexpr size_t kTestDataSize = 100'000; |
| |
| mTestData.resize(kTestDataSize); |
| for (size_t i = 0; i < kTestDataSize; ++i) |
| { |
| mTestData[i] = static_cast<uint8_t>(i); |
| } |
| |
| ASSERT_TRUE(CompressBlob(mTestData.size(), mTestData.data(), &mCompressedData)); |
| } |
| |
| void setCompressedDataLastDWord(uint32_t value) |
| { |
| ASSERT(IsLittleEndian()); |
| ASSERT(mCompressedData.size() > sizeof(value)); |
| memcpy(mCompressedData.data() + mCompressedData.size() - sizeof(value), &value, |
| sizeof(value)); |
| } |
| |
| bool decompress(size_t compressedSize, size_t maxUncompressedDataSize) |
| { |
| return DecompressBlob(mCompressedData.data(), compressedSize, maxUncompressedDataSize, |
| &mUncompressedData); |
| } |
| |
| bool checkUncompressedData() |
| { |
| return (mTestData.size() == mUncompressedData.size()) && |
| (memcmp(mTestData.data(), mUncompressedData.data(), mTestData.size()) == 0); |
| } |
| |
| std::vector<uint8_t> mTestData; |
| MemoryBuffer mCompressedData; |
| MemoryBuffer mUncompressedData; |
| }; |
| |
| // Tests that decompressing full data has no errors. |
| TEST_F(DecompressTest, FullData) |
| { |
| EXPECT_TRUE(decompress(mCompressedData.size(), mTestData.size())); |
| EXPECT_TRUE(checkUncompressedData()); |
| } |
| |
| // Tests expected failure if |maxUncompressedDataSize| is less than actual uncompressed size. |
| TEST_F(DecompressTest, InsufficientMaxUncompressedDataSize) |
| { |
| EXPECT_FALSE(decompress(mCompressedData.size(), mTestData.size() - 1)); |
| } |
| |
| // Tests expected failure if try to decompress partial compressed data. |
| TEST_F(DecompressTest, UnexpectedPartialData) |
| { |
| // Use this to avoid |maxUncompressedDataSize| affecting the test. |
| constexpr size_t kMaxUncompressedDataSize = std::numeric_limits<size_t>::max(); |
| |
| EXPECT_FALSE(decompress(mCompressedData.size() - 1, kMaxUncompressedDataSize)); |
| } |
| |
| // Tests expected failure if try to decompress corrupted data. |
| TEST_F(DecompressTest, CorruptedData) |
| { |
| // Corrupt the compressed data. |
| const size_t corruptIndex = mCompressedData.size() / 2; |
| mCompressedData[corruptIndex] ^= 255; |
| |
| EXPECT_FALSE(decompress(mCompressedData.size(), mTestData.size())); |
| } |
| |
| // Tests expected failures if try to decompress data with the corrupted last dword. |
| TEST_F(DecompressTest, CorruptedLastDWord) |
| { |
| // Last dword stores decompressed data size and not the actual compressed data. This dword must |
| // match the decompressed size. Decompress should fail if it is not the case. |
| |
| // Use this to avoid |maxUncompressedDataSize| affecting the test. |
| constexpr size_t kMaxUncompressedDataSize = std::numeric_limits<size_t>::max(); |
| |
| // Try to decompress with decreased size in the last dword. |
| setCompressedDataLastDWord(static_cast<uint32_t>(mTestData.size() - 1)); |
| EXPECT_FALSE(decompress(mCompressedData.size(), kMaxUncompressedDataSize)); |
| |
| // Try to decompress with increased size in the last dword. |
| setCompressedDataLastDWord(static_cast<uint32_t>(mTestData.size() + 1)); |
| EXPECT_FALSE(decompress(mCompressedData.size(), kMaxUncompressedDataSize)); |
| |
| // Try to decompress with the last dword set to 0. |
| setCompressedDataLastDWord(0); |
| EXPECT_FALSE(decompress(mCompressedData.size(), kMaxUncompressedDataSize)); |
| |
| // Decompress with the last dword set to the correct size should succeed. |
| setCompressedDataLastDWord(static_cast<uint32_t>(mTestData.size())); |
| EXPECT_TRUE(decompress(mCompressedData.size(), kMaxUncompressedDataSize)); |
| EXPECT_TRUE(checkUncompressedData()); |
| } |
| |
| } // anonymous namespace |
| } // namespace angle |