| // | |
| // 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 |