// // 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 #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(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 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::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::max(); // Try to decompress with decreased size in the last dword. setCompressedDataLastDWord(static_cast(mTestData.size() - 1)); EXPECT_FALSE(decompress(mCompressedData.size(), kMaxUncompressedDataSize)); // Try to decompress with increased size in the last dword. setCompressedDataLastDWord(static_cast(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(mTestData.size())); EXPECT_TRUE(decompress(mCompressedData.size(), kMaxUncompressedDataSize)); EXPECT_TRUE(checkUncompressedData()); } } // anonymous namespace } // namespace angle