diff options
Diffstat (limited to 'libs/hwui/tests/unit/ShaderCacheTests.cpp')
-rw-r--r-- | libs/hwui/tests/unit/ShaderCacheTests.cpp | 143 |
1 files changed, 127 insertions, 16 deletions
diff --git a/libs/hwui/tests/unit/ShaderCacheTests.cpp b/libs/hwui/tests/unit/ShaderCacheTests.cpp index 43080a9460b3..1433aa0349f4 100644 --- a/libs/hwui/tests/unit/ShaderCacheTests.cpp +++ b/libs/hwui/tests/unit/ShaderCacheTests.cpp @@ -48,11 +48,18 @@ public: */ static void terminate(ShaderCache& cache, bool saveContent) { std::lock_guard<std::mutex> lock(cache.mMutex); - if (cache.mInitialized && cache.mBlobCache && saveContent) { - cache.mBlobCache->writeToFile(); - } + cache.mSavePending = saveContent; + cache.saveToDiskLocked(); cache.mBlobCache = NULL; } + + /** + * + */ + template <typename T> + static bool validateCache(ShaderCache& cache, std::vector<T> hash) { + return cache.validateCache(hash.data(), hash.size() * sizeof(T)); + } }; } /* namespace skiapipeline */ @@ -75,26 +82,39 @@ bool folderExist(const std::string& folderName) { return false; } -bool checkShader(const sk_sp<SkData>& shader, const char* program) { +inline bool +checkShader(const sk_sp<SkData>& shader1, const sk_sp<SkData>& shader2) { + return nullptr != shader1 && nullptr != shader2 && shader1->size() == shader2->size() + && 0 == memcmp(shader1->data(), shader2->data(), shader1->size()); +} + +inline bool +checkShader(const sk_sp<SkData>& shader, const char* program) { sk_sp<SkData> shader2 = SkData::MakeWithCString(program); - return shader->size() == shader2->size() - && 0 == memcmp(shader->data(), shader2->data(), shader->size()); + return checkShader(shader, shader2); } -bool checkShader(const sk_sp<SkData>& shader, std::vector<char>& program) { - sk_sp<SkData> shader2 = SkData::MakeWithCopy(program.data(), program.size()); - return shader->size() == shader2->size() - && 0 == memcmp(shader->data(), shader2->data(), shader->size()); +template <typename T> +bool checkShader(const sk_sp<SkData>& shader, std::vector<T>& program) { + sk_sp<SkData> shader2 = SkData::MakeWithCopy(program.data(), program.size() * sizeof(T)); + return checkShader(shader, shader2); } void setShader(sk_sp<SkData>& shader, const char* program) { shader = SkData::MakeWithCString(program); } -void setShader(sk_sp<SkData>& shader, std::vector<char>& program) { - shader = SkData::MakeWithCopy(program.data(), program.size()); +template <typename T> +void setShader(sk_sp<SkData>& shader, std::vector<T>& buffer) { + shader = SkData::MakeWithCopy(buffer.data(), buffer.size() * sizeof(T)); } +template <typename T> +void genRandomData(std::vector<T>& buffer) { + for (auto& data : buffer) { + data = T(std::rand()); + } +} #define GrProgramDescTest(a) (*SkData::MakeWithCString(#a).get()) @@ -110,6 +130,7 @@ TEST(ShaderCacheTest, testWriteAndRead) { //remove any test files from previous test run int deleteFile = remove(cacheFile1.c_str()); ASSERT_TRUE(0 == deleteFile || ENOENT == errno); + std::srand(0); //read the cache from a file that does not exist ShaderCache::get().setFilename(cacheFile1.c_str()); @@ -158,10 +179,8 @@ TEST(ShaderCacheTest, testWriteAndRead) { //write and read big data chunk (50K) size_t dataSize = 50*1024; - std::vector<char> dataBuffer(dataSize); - for (size_t i = 0; i < dataSize; i++) { - dataBuffer[0] = dataSize % 256; - } + std::vector<uint8_t> dataBuffer(dataSize); + genRandomData(dataBuffer); setShader(inVS, dataBuffer); ShaderCache::get().store(GrProgramDescTest(432), *inVS.get()); ShaderCacheTestUtils::terminate(ShaderCache::get(), true); @@ -173,4 +192,96 @@ TEST(ShaderCacheTest, testWriteAndRead) { remove(cacheFile1.c_str()); } +TEST(ShaderCacheTest, testCacheValidation) { + if (!folderExist(getExternalStorageFolder())) { + //don't run the test if external storage folder is not available + return; + } + std::string cacheFile1 = getExternalStorageFolder() + "/shaderCacheTest1"; + std::string cacheFile2 = getExternalStorageFolder() + "/shaderCacheTest2"; + + //remove any test files from previous test run + int deleteFile = remove(cacheFile1.c_str()); + ASSERT_TRUE(0 == deleteFile || ENOENT == errno); + std::srand(0); + + //generate identity and read the cache from a file that does not exist + ShaderCache::get().setFilename(cacheFile1.c_str()); + ShaderCacheTestUtils::setSaveDelay(ShaderCache::get(), 0); //disable deferred save + std::vector<uint8_t> identity(1024); + genRandomData(identity); + ShaderCache::get().initShaderDiskCache(identity.data(), identity.size() * + sizeof(decltype(identity)::value_type)); + + // generate random content in cache and store to disk + constexpr size_t numBlob(10); + constexpr size_t keySize(1024); + constexpr size_t dataSize(50 * 1024); + + std::vector< std::pair<sk_sp<SkData>, sk_sp<SkData>> > blobVec(numBlob); + for (auto& blob : blobVec) { + std::vector<uint8_t> keyBuffer(keySize); + std::vector<uint8_t> dataBuffer(dataSize); + genRandomData(keyBuffer); + genRandomData(dataBuffer); + + sk_sp<SkData> key, data; + setShader(key, keyBuffer); + setShader(data, dataBuffer); + + blob = std::make_pair(key, data); + ShaderCache::get().store(*key.get(), *data.get()); + } + ShaderCacheTestUtils::terminate(ShaderCache::get(), true); + + // change to a file that does not exist and verify validation fails + ShaderCache::get().setFilename(cacheFile2.c_str()); + ShaderCache::get().initShaderDiskCache(); + ASSERT_FALSE( ShaderCacheTestUtils::validateCache(ShaderCache::get(), identity) ); + ShaderCacheTestUtils::terminate(ShaderCache::get(), false); + + // restore the original file and verify validation succeeds + ShaderCache::get().setFilename(cacheFile1.c_str()); + ShaderCache::get().initShaderDiskCache(identity.data(), identity.size() * + sizeof(decltype(identity)::value_type)); + ASSERT_TRUE( ShaderCacheTestUtils::validateCache(ShaderCache::get(), identity) ); + for (const auto& blob : blobVec) { + auto outVS = ShaderCache::get().load(*blob.first.get()); + ASSERT_TRUE( checkShader(outVS, blob.second) ); + } + + // generate error identity and verify load fails + ShaderCache::get().initShaderDiskCache(identity.data(), -1); + for (const auto& blob : blobVec) { + ASSERT_EQ( ShaderCache::get().load(*blob.first.get()), sk_sp<SkData>() ); + } + ShaderCache::get().initShaderDiskCache(nullptr, identity.size() * + sizeof(decltype(identity)::value_type)); + for (const auto& blob : blobVec) { + ASSERT_EQ( ShaderCache::get().load(*blob.first.get()), sk_sp<SkData>() ); + } + + // verify the cache validation again after load fails + ShaderCache::get().initShaderDiskCache(identity.data(), identity.size() * + sizeof(decltype(identity)::value_type)); + ASSERT_TRUE( ShaderCacheTestUtils::validateCache(ShaderCache::get(), identity) ); + for (const auto& blob : blobVec) { + auto outVS = ShaderCache::get().load(*blob.first.get()); + ASSERT_TRUE( checkShader(outVS, blob.second) ); + } + + // generate another identity and verify load fails + for (auto& data : identity) { + data += std::rand(); + } + ShaderCache::get().initShaderDiskCache(identity.data(), identity.size() * + sizeof(decltype(identity)::value_type)); + for (const auto& blob : blobVec) { + ASSERT_EQ( ShaderCache::get().load(*blob.first.get()), sk_sp<SkData>() ); + } + + ShaderCacheTestUtils::terminate(ShaderCache::get(), false); + remove(cacheFile1.c_str()); +} + } // namespace |