| // |
| // Copyright 2018 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. |
| // |
| // BlobCache_unittest.h: Unit tests for the blob cache. |
| |
| #include <gtest/gtest.h> |
| |
| #include "libANGLE/BlobCache.h" |
| |
| namespace egl |
| { |
| |
| // Note: this is fairly similar to SizedMRUCache_unittest, and makes sure the |
| // BlobCache usage of SizedMRUCache is not broken. |
| |
| using BlobPut = angle::MemoryBuffer; |
| using Blob = BlobCache::Value; |
| using Key = BlobCache::Key; |
| |
| template <typename T> |
| void MakeSequence(T &seq, uint8_t start) |
| { |
| for (uint8_t i = 0; i < seq.size(); ++i) |
| { |
| seq[i] = i + start; |
| } |
| } |
| |
| BlobPut MakeBlob(size_t size, uint8_t start = 0) |
| { |
| BlobPut blob; |
| EXPECT_TRUE(blob.resize(size)); |
| MakeSequence(blob, start); |
| return blob; |
| } |
| |
| Key MakeKey(uint8_t start = 0) |
| { |
| Key key; |
| MakeSequence(key, start); |
| return key; |
| } |
| |
| // Test a cache with a value that takes up maximum size. |
| TEST(BlobCacheTest, MaxSizedValue) |
| { |
| constexpr size_t kSize = 32; |
| BlobCache blobCache(kSize); |
| |
| blobCache.populate(MakeKey(0), MakeBlob(kSize)); |
| EXPECT_EQ(32u, blobCache.size()); |
| EXPECT_FALSE(blobCache.empty()); |
| |
| blobCache.populate(MakeKey(1), MakeBlob(kSize)); |
| EXPECT_EQ(32u, blobCache.size()); |
| EXPECT_FALSE(blobCache.empty()); |
| |
| Blob blob; |
| size_t blobSize; |
| EXPECT_FALSE(blobCache.get(nullptr, MakeKey(0), &blob, &blobSize)); |
| |
| blobCache.clear(); |
| EXPECT_TRUE(blobCache.empty()); |
| } |
| |
| // Test a cache with many small values, that it can handle unlimited inserts. |
| TEST(BlobCacheTest, ManySmallValues) |
| { |
| constexpr size_t kSize = 32; |
| BlobCache blobCache(kSize); |
| |
| for (size_t value = 0; value < kSize; ++value) |
| { |
| blobCache.populate(MakeKey(value), MakeBlob(1, value)); |
| |
| Blob qvalue; |
| size_t blobSize; |
| EXPECT_TRUE(blobCache.get(nullptr, MakeKey(value), &qvalue, &blobSize)); |
| if (qvalue.size() > 0) |
| { |
| EXPECT_EQ(value, qvalue[0]); |
| } |
| } |
| |
| EXPECT_EQ(32u, blobCache.size()); |
| EXPECT_FALSE(blobCache.empty()); |
| |
| // Putting one element evicts the first element. |
| blobCache.populate(MakeKey(kSize), MakeBlob(1, kSize)); |
| |
| Blob qvalue; |
| size_t blobSize; |
| EXPECT_FALSE(blobCache.get(nullptr, MakeKey(0), &qvalue, &blobSize)); |
| |
| // Putting one large element cleans out the whole stack. |
| blobCache.populate(MakeKey(kSize + 1), MakeBlob(kSize, kSize + 1)); |
| EXPECT_EQ(32u, blobCache.size()); |
| EXPECT_FALSE(blobCache.empty()); |
| |
| for (size_t value = 0; value <= kSize; ++value) |
| { |
| EXPECT_FALSE(blobCache.get(nullptr, MakeKey(value), &qvalue, &blobSize)); |
| } |
| EXPECT_TRUE(blobCache.get(nullptr, MakeKey(kSize + 1), &qvalue, &blobSize)); |
| if (qvalue.size() > 0) |
| { |
| EXPECT_EQ(kSize + 1, qvalue[0]); |
| } |
| |
| // Put a bunch of items in the cache sequentially. |
| for (size_t value = 0; value < kSize * 10; ++value) |
| { |
| blobCache.populate(MakeKey(value), MakeBlob(1, value)); |
| } |
| |
| EXPECT_EQ(32u, blobCache.size()); |
| } |
| |
| // Tests putting an oversize element. |
| TEST(BlobCacheTest, OversizeValue) |
| { |
| constexpr size_t kSize = 32; |
| BlobCache blobCache(kSize); |
| |
| blobCache.populate(MakeKey(5), MakeBlob(100)); |
| |
| Blob qvalue; |
| size_t blobSize; |
| EXPECT_FALSE(blobCache.get(nullptr, MakeKey(5), &qvalue, &blobSize)); |
| } |
| |
| } // namespace egl |