diff options
| author | skallweitNV <64953474+skallweitNV@users.noreply.github.com> | 2022-12-02 16:34:53 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-12-02 16:34:53 +0100 |
| commit | e9b7c66a541636e72659fbfcc9a3f20a85f2bee8 (patch) | |
| tree | b65942799ff6267ebe29c8b64056819461621be7 /tools | |
| parent | 92ae4949fe1af28ef31331fd4116c8111c057420 (diff) | |
Cleanup crypto utilities (#2549)
* Consolidate crypto functions into single module
* Migrate rest of code to new crypto module
* Fix name conflict
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/gfx-unit-test/shader-cache-tests.cpp | 1 | ||||
| -rw-r--r-- | tools/gfx/persistent-shader-cache.cpp | 31 | ||||
| -rw-r--r-- | tools/gfx/persistent-shader-cache.h | 15 | ||||
| -rw-r--r-- | tools/gfx/renderer-shared.cpp | 11 | ||||
| -rw-r--r-- | tools/slang-unit-test/unit-test-crypto.cpp | 173 | ||||
| -rw-r--r-- | tools/slang-unit-test/unit-test-digest-builder.cpp | 72 | ||||
| -rw-r--r-- | tools/slang-unit-test/unit-test-digest-utils.cpp | 58 | ||||
| -rw-r--r-- | tools/slang-unit-test/unit-test-md5.cpp | 47 |
8 files changed, 203 insertions, 205 deletions
diff --git a/tools/gfx-unit-test/shader-cache-tests.cpp b/tools/gfx-unit-test/shader-cache-tests.cpp index c1d058d70..486b59cda 100644 --- a/tools/gfx-unit-test/shader-cache-tests.cpp +++ b/tools/gfx-unit-test/shader-cache-tests.cpp @@ -5,7 +5,6 @@ #include "tools/gfx-util/shader-cursor.h" #include "source/core/slang-basic.h" #include "source/core/slang-string-util.h" -#include "source/core/slang-digest-util.h" #include "source/core/slang-memory-file-system.h" #include "source/core/slang-file-system.h" diff --git a/tools/gfx/persistent-shader-cache.cpp b/tools/gfx/persistent-shader-cache.cpp index 54c46f9dc..7dc64632b 100644 --- a/tools/gfx/persistent-shader-cache.cpp +++ b/tools/gfx/persistent-shader-cache.cpp @@ -1,7 +1,6 @@ // slang-shader-cache-index.cpp #include "persistent-shader-cache.h" -#include "../../source/core/slang-digest-util.h" #include "../../source/core/slang-io.h" #include "../../source/core/slang-string-util.h" #include "../../source/core/slang-file-system.h" @@ -128,7 +127,7 @@ void PersistentShaderCache::loadCacheFromFile() } } -ShaderCacheEntry* PersistentShaderCache::findEntry(const slang::Digest& key, ISlangBlob** outCompiledCode) +ShaderCacheEntry* PersistentShaderCache::findEntry(const DigestType& key, ISlangBlob** outCompiledCode) { LinkedNode<Index>* entryIndexNode; if (!keyToEntry.TryGetValue(key, entryIndexNode)) @@ -140,7 +139,7 @@ ShaderCacheEntry* PersistentShaderCache::findEntry(const slang::Digest& key, ISl // If the key is found, load the stored contents from disk. We then move the corresponding // entry to the front of the linked list and update the cache file on disk - desc.shaderCacheFileSystem->loadFile(DigestUtil::toString(key).getBuffer(), outCompiledCode); + desc.shaderCacheFileSystem->loadFile(key.toString().getBuffer(), outCompiledCode); auto index = entryIndexNode->Value; entries[index].lastAccessedTime = (double)high_resolution_clock::now().time_since_epoch().count(); if (orderedEntries.FirstNode() != entryIndexNode) @@ -150,7 +149,7 @@ ShaderCacheEntry* PersistentShaderCache::findEntry(const slang::Digest& key, ISl if (mutableShaderCacheFileSystem && !isMemoryFileSystem) { auto offset = index * sizeof(ShaderCacheEntry); - indexStream.seek(SeekOrigin::Start, offset + 2 * sizeof(slang::Digest)); + indexStream.seek(SeekOrigin::Start, offset + 2 * sizeof(DigestType)); indexStream.write(&entries[index].lastAccessedTime, sizeof(double)); indexStream.flush(); } @@ -158,7 +157,7 @@ ShaderCacheEntry* PersistentShaderCache::findEntry(const slang::Digest& key, ISl return &entries[index]; } -void PersistentShaderCache::addEntry(const slang::Digest& dependencyDigest, const slang::Digest& contentsDigest, ISlangBlob* compiledCode) +void PersistentShaderCache::addEntry(const DigestType& dependencyDigest, const DigestType& contentsDigest, ISlangBlob* compiledCode) { if (!mutableShaderCacheFileSystem) { @@ -197,7 +196,7 @@ void PersistentShaderCache::addEntry(const slang::Digest& dependencyDigest, cons } keyToEntry.Add(dependencyDigest, entryNode); - mutableShaderCacheFileSystem->saveFileBlob(DigestUtil::toString(dependencyDigest).getBuffer(), compiledCode); + mutableShaderCacheFileSystem->saveFileBlob(dependencyDigest.toString().getBuffer(), compiledCode); if (!isMemoryFileSystem) { @@ -208,8 +207,8 @@ void PersistentShaderCache::addEntry(const slang::Digest& dependencyDigest, cons } void PersistentShaderCache::updateEntry( - const slang::Digest& dependencyDigest, - const slang::Digest& contentsDigest, + const DigestType& dependencyDigest, + const DigestType& contentsDigest, ISlangBlob* updatedCode) { if (!mutableShaderCacheFileSystem) @@ -224,13 +223,13 @@ void PersistentShaderCache::updateEntry( auto entryIndexNode = *keyToEntry.TryGetValue(dependencyDigest); auto index = entryIndexNode->Value; entries[index].contentsBasedDigest = contentsDigest; - mutableShaderCacheFileSystem->saveFileBlob(DigestUtil::toString(dependencyDigest).getBuffer(), updatedCode); + mutableShaderCacheFileSystem->saveFileBlob(dependencyDigest.toString().getBuffer(), updatedCode); if (!isMemoryFileSystem) { auto offset = index * sizeof(ShaderCacheEntry); - indexStream.seek(SeekOrigin::Start, offset + sizeof(slang::Digest)); - indexStream.write(&contentsDigest, sizeof(slang::Digest)); + indexStream.seek(SeekOrigin::Start, offset + sizeof(DigestType)); + indexStream.write(&contentsDigest, sizeof(DigestType)); indexStream.flush(); } } @@ -250,7 +249,7 @@ Index PersistentShaderCache::deleteLRUEntry() auto shaderKey = entries[index].dependencyBasedDigest; keyToEntry.Remove(shaderKey); - mutableShaderCacheFileSystem->remove(DigestUtil::toString(shaderKey).getBuffer()); + mutableShaderCacheFileSystem->remove(shaderKey.toString().getBuffer()); orderedEntries.Delete(lruEntry); return index; @@ -286,8 +285,8 @@ void PersistentShaderCache::loadCacheFromMemory() continue; ShaderCacheEntry entry; - entry.dependencyBasedDigest = DigestUtil::fromString(entryFields[0]); - entry.contentsBasedDigest = DigestUtil::fromString(entryFields[1]); + entry.dependencyBasedDigest = DigestType(entryFields[0]); + entry.contentsBasedDigest = DigestType(entryFields[1]); entry.lastAccessedTime = 0; auto entryNode = orderedEntries.AddLast(entries.getCount()); @@ -305,9 +304,9 @@ void PersistentShaderCache::saveCacheToMemory() for (auto& entryIndex : orderedEntries) { auto entry = entries[entryIndex]; - indexSb << entry.dependencyBasedDigest; + indexSb << entry.dependencyBasedDigest.toString(); indexSb << " "; - indexSb << entry.contentsBasedDigest; + indexSb << entry.contentsBasedDigest.toString(); indexSb << "\n"; } diff --git a/tools/gfx/persistent-shader-cache.h b/tools/gfx/persistent-shader-cache.h index 8e05eddf6..530d50a58 100644 --- a/tools/gfx/persistent-shader-cache.h +++ b/tools/gfx/persistent-shader-cache.h @@ -8,16 +8,19 @@ #include "../../source/core/slang-dictionary.h" #include "../../source/core/slang-linked-list.h" #include "../../source/core/slang-stream.h" +#include "../../source/core/slang-crypto.h" namespace gfx { using namespace Slang; +using DigestType = MD5::Digest; + struct ShaderCacheEntry { - slang::Digest dependencyBasedDigest; - slang::Digest contentsBasedDigest; + DigestType dependencyBasedDigest; + DigestType contentsBasedDigest; double lastAccessedTime; bool operator==(const ShaderCacheEntry& rhs) @@ -42,16 +45,16 @@ public: // Fetch the cache entry corresponding to the provided key. If found, move the entry to // the front of entries and return the entry and the corresponding compiled code in // outCompiledCode. Else, return nullptr. - ShaderCacheEntry* findEntry(const slang::Digest& key, ISlangBlob** outCompiledCode); + ShaderCacheEntry* findEntry(const DigestType& key, ISlangBlob** outCompiledCode); // Add an entry to the cache with the provided key and contents hashes. If // adding an entry causes the cache to exceed size limitations, this will also // delete the least recently used entry. - void addEntry(const slang::Digest& dependencyDigest, const slang::Digest& contentsDigest, ISlangBlob* compiledCode); + void addEntry(const DigestType& dependencyDigest, const DigestType& contentsDigest, ISlangBlob* compiledCode); // Update the contents hash for the specified entry in the cache and update the // corresponding file on disk. - void updateEntry(const slang::Digest& dependencyDigest, const slang::Digest& contentsDigest, ISlangBlob* updatedCode); + void updateEntry(const DigestType& dependencyDigest, const DigestType& contentsDigest, ISlangBlob* updatedCode); private: // Load a previous cache index saved to disk. If not found, create a new cache index @@ -82,7 +85,7 @@ private: // Dictionary mapping each shader's key to its corresponding node (entry) in the // linked list 'orderedEntries'. - Dictionary<slang::Digest, LinkedNode<Index>*> keyToEntry; + Dictionary<DigestType, LinkedNode<Index>*> keyToEntry; // Linked list containing the corresponding indices in 'entries' for entries in the // shader cache ordered from most to least recently used. diff --git a/tools/gfx/renderer-shared.cpp b/tools/gfx/renderer-shared.cpp index 3dcdb324c..3397b325e 100644 --- a/tools/gfx/renderer-shared.cpp +++ b/tools/gfx/renderer-shared.cpp @@ -6,7 +6,6 @@ #include "../../source/core/slang-file-system.h" #include "../../slang.h" -#include "../../source/core/slang-digest-util.h" using namespace Slang; @@ -349,13 +348,15 @@ Result RendererBase::getEntryPointCodeFromShaderCache( ComPtr<slang::ISession> session; getSlangSession(session.writeRef()); - slang::Digest shaderKey; - program->computeDependencyBasedHash(entryPointIndex, targetIndex, &shaderKey); + ComPtr<ISlangBlob> shaderKeyBlob; + program->computeDependencyBasedHash(entryPointIndex, targetIndex, shaderKeyBlob.writeRef()); + DigestType shaderKey(shaderKeyBlob); // Produce a hash using the AST for this program - This is needed to check whether a cache entry is effectively dirty, // or to save along with the compiled code into an entry so the entry can be checked if fetched later on. - slang::Digest contentsHash; - program->computeContentsBasedHash(&contentsHash); + ComPtr<ISlangBlob> contentsHashBlob; + program->computeContentsBasedHash(contentsHashBlob.writeRef()); + DigestType contentsHash(contentsHashBlob); ComPtr<ISlangBlob> codeBlob; diff --git a/tools/slang-unit-test/unit-test-crypto.cpp b/tools/slang-unit-test/unit-test-crypto.cpp new file mode 100644 index 000000000..adb7b2218 --- /dev/null +++ b/tools/slang-unit-test/unit-test-crypto.cpp @@ -0,0 +1,173 @@ +// unit-test-sha1.cpp +#include "tools/unit-test/slang-unit-test.h" + +#include "../../source/core/slang-crypto.h" + +using namespace Slang; + +SLANG_UNIT_TEST(crypto) +{ + // HashDigest + { + using Digest = HashDigest<8>; + Digest empty; + SLANG_CHECK(empty.data[0] == 0 && empty.data[1] == 0); + SLANG_CHECK(empty.toString() == "0000000000000000"); + + Digest all = Digest("ffffffffffffffff"); + SLANG_CHECK(all.data[0] == 0xffffffff && all.data[1] == 0xffffffff); + SLANG_CHECK(all.toString() == "ffffffffffffffff"); + + SLANG_CHECK(empty == Digest("0000000000000000")); + SLANG_CHECK(all == Digest("ffffffffffffffff")); + SLANG_CHECK(empty != all); + + SLANG_CHECK(Digest("invalid") == empty); + SLANG_CHECK(Digest("X000000000000000") == empty); + SLANG_CHECK(Digest(" 000000000000000") == empty); + + SLANG_CHECK(Digest("0123456789abcdef").toString() == "0123456789abcdef"); + + Slang::ComPtr<ISlangBlob> blob = Digest("0123456789abcdef").toBlob(); + const uint8_t check[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; + SLANG_CHECK(blob->getBufferSize() == 8); + SLANG_CHECK(::memcmp(blob->getBufferPointer(), check, 8) == 0); + + SLANG_CHECK(Digest(blob) == Digest("0123456789abcdef")); + } + + // MD5 + + // Empty string + { + MD5 sha1; + auto digest = sha1.finalize(); + SLANG_CHECK(digest.toString() == "d41d8cd98f00b204e9800998ecf8427e"); + } + + // One call to update() + { + MD5 sha1; + const String str("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."); + sha1.update(str.getBuffer(), str.getLength()); + auto digest = sha1.finalize(); + SLANG_CHECK(digest.toString() == "818c6e601a24f72750da0f6c9b8ebe28"); + } + + // Two calls to update() + { + MD5 sha1; + const String str1("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."); + const String str2("Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."); + sha1.update(str1.getBuffer(), str1.getLength()); + sha1.update(str2.getBuffer(), str2.getLength()); + auto digest = sha1.finalize(); + SLANG_CHECK(digest.toString() == "87d3caecb0ab82faae84d60fde994aca"); + } + + // compute() + { + SLANG_CHECK(MD5::compute(nullptr, 0).toString() == "d41d8cd98f00b204e9800998ecf8427e"); + const String str("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."); + SLANG_CHECK(MD5::compute(str.getBuffer(), str.getLength()).toString() == "818c6e601a24f72750da0f6c9b8ebe28"); + } + + // SHA1 + + // Empty string + { + SHA1 sha1; + auto digest = sha1.finalize(); + SLANG_CHECK(digest.toString() == "da39a3ee5e6b4b0d3255bfef95601890afd80709"); + } + + // One call to update() + { + SHA1 sha1; + const String str("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."); + sha1.update(str.getBuffer(), str.getLength()); + auto digest = sha1.finalize(); + SLANG_CHECK(digest.toString() == "cca0871ecbe200379f0a1e4b46de177e2d62e655"); + } + + // Two calls to update() + { + SHA1 sha1; + const String str1("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."); + const String str2("Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."); + sha1.update(str1.getBuffer(), str1.getLength()); + sha1.update(str2.getBuffer(), str2.getLength()); + auto digest = sha1.finalize(); + SLANG_CHECK(digest.toString() == "7a8213edf9976d2e693f27bbc7dc41546bcfcc97"); + } + + // compute() + { + SLANG_CHECK(SHA1::compute(nullptr, 0).toString() == "da39a3ee5e6b4b0d3255bfef95601890afd80709"); + const String str("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."); + SLANG_CHECK(SHA1::compute(str.getBuffer(), str.getLength()).toString() == "cca0871ecbe200379f0a1e4b46de177e2d62e655"); + } + + // DigestBuider + + // Raw numerical values, etc. + { + DigestBuilder<MD5> builder; + + int64_t valueA = -1; + uint64_t valueB = 1; + builder.append(valueA); + builder.append(valueB); + + auto digest = builder.finalize(); + SLANG_CHECK(digest.toString() == "5ba171e20898bdd205639013746f2679"); + } + + // List + { + DigestBuilder<MD5> builder; + + List<int64_t> listA; + listA.add(1); + listA.add(2); + listA.add(3); + listA.add(4); + builder.append(listA); + + auto digest = builder.finalize(); + SLANG_CHECK(digest.toString() == "9f66c130786a1a05e4731f71a3c5f172"); + } + + // UnownedStringSlice + { + DigestBuilder<MD5> builder; + + UnownedStringSlice stringSlice = UnownedStringSlice("String Slice Test"); + builder.append(stringSlice); + + auto digest = builder.finalize(); + SLANG_CHECK(digest.toString() == "5d6cc58e1824a4dfd0cf57395b603316"); + } + + // String + { + DigestBuilder<MD5> builder; + + String str = String("String Test"); + builder.append(str); + + auto digest = builder.finalize(); + SLANG_CHECK(digest.toString() == "df5a79cc2170c7401cf0a506ceb0ce24"); + } + + // Digest + { + DigestBuilder<MD5> builder; + + MD5::Digest hash; + builder.append(hash); + + auto digest = builder.finalize(); + SLANG_CHECK(digest.toString() == "4ae71336e44bf9bf79d2752e234818a5"); + } +} diff --git a/tools/slang-unit-test/unit-test-digest-builder.cpp b/tools/slang-unit-test/unit-test-digest-builder.cpp deleted file mode 100644 index b89b31a7b..000000000 --- a/tools/slang-unit-test/unit-test-digest-builder.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// unit-test-digest-utils.cpp - -#include "tools/unit-test/slang-unit-test.h" - -#include "../../source/core/slang-digest-builder.h" -#include "../../source/core/slang-digest-util.h" - -using namespace Slang; - -SLANG_UNIT_TEST(digestBuilder) -{ - // Raw numerical values, etc. - { - DigestBuilder builder; - - int64_t valueA = -1; - uint64_t valueB = 1; - builder.append(valueA); - builder.append(valueB); - - slang::Digest digest = builder.finalize(); - SLANG_CHECK(DigestUtil::toString(digest) == "5BA171E20898BDD205639013746F2679"); - } - - // List - { - DigestBuilder builder; - - List<int64_t> listA; - listA.add(1); - listA.add(2); - listA.add(3); - listA.add(4); - builder.append(listA); - - slang::Digest digest = builder.finalize(); - SLANG_CHECK(DigestUtil::toString(digest) == "9F66C130786A1A05E4731F71A3C5F172"); - } - - // UnownedStringSlice - { - DigestBuilder builder; - - UnownedStringSlice stringSlice = UnownedStringSlice("String Slice Test"); - builder.append(stringSlice); - - slang::Digest digest = builder.finalize(); - SLANG_CHECK(DigestUtil::toString(digest) == "5D6CC58E1824A4DFD0CF57395B603316"); - } - - // String - { - DigestBuilder builder; - - String str = String("String Test"); - builder.append(str); - - slang::Digest digest = builder.finalize(); - SLANG_CHECK(DigestUtil::toString(digest) == "DF5A79CC2170C7401CF0A506CEB0CE24"); - } - - // Digest - { - DigestBuilder builder; - - slang::Digest hash; - builder.append(hash); - - slang::Digest digest = builder.finalize(); - SLANG_CHECK(DigestUtil::toString(digest) == "4AE71336E44BF9BF79D2752E234818A5"); - } -} diff --git a/tools/slang-unit-test/unit-test-digest-utils.cpp b/tools/slang-unit-test/unit-test-digest-utils.cpp deleted file mode 100644 index a463fe07f..000000000 --- a/tools/slang-unit-test/unit-test-digest-utils.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// unit-test-digest-utils.cpp - -#include "tools/unit-test/slang-unit-test.h" - -#include "../../source/core/slang-digest-util.h" - -using namespace Slang; - -SLANG_UNIT_TEST(digestUtils) -{ - { - slang::Digest testA; - testA.values[0] = 1; - testA.values[1] = 2; - testA.values[2] = 3; - testA.values[3] = 4; - - String testAString = DigestUtil::toString(testA); - SLANG_CHECK(testAString.equals(String("01000000020000000300000004000000"))); - } - - { - slang::Digest testC; - testC.values[0] = 0x11111111; - testC.values[1] = 0x22222222; - testC.values[2] = 0x33333333; - testC.values[3] = 0x44444444; - - String testCString = DigestUtil::toString(testC); - SLANG_CHECK(testCString.equals(String("11111111222222223333333344444444"))); - } - - { - auto digestString = UnownedStringSlice("5D6CC58E1824A4DFD0CF57395B603316"); - slang::Digest digest = DigestUtil::fromString(digestString); - auto resultString = DigestUtil::toString(digest); - SLANG_CHECK(resultString == digestString); - } - - { - auto digestString = UnownedStringSlice("01000000020000000300000004000000"); - slang::Digest digest = DigestUtil::fromString(digestString); - auto resultString = DigestUtil::toString(digest); - SLANG_CHECK(resultString == digestString); - } - - { - slang::Digest testD; - testD.values[0] = 1; - testD.values[1] = 2; - testD.values[2] = 3; - testD.values[3] = 4; - - StringBuilder testDSb; - testDSb << testD; - SLANG_CHECK(testDSb.equals(String("01000000020000000300000004000000"))); - } -} diff --git a/tools/slang-unit-test/unit-test-md5.cpp b/tools/slang-unit-test/unit-test-md5.cpp deleted file mode 100644 index 1297d4f17..000000000 --- a/tools/slang-unit-test/unit-test-md5.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// unit-test-md5.cpp -#include "tools/unit-test/slang-unit-test.h" - -#include "../../source/core/slang-md5.h" -#include "../../source/core/slang-string.h" -#include "../../source/core/slang-digest-util.h" - -using namespace Slang; - -SLANG_UNIT_TEST(md5hash) -{ - // Empty string - { - MD5Context ctx; - MD5HashGen gen; - gen.init(&ctx); - slang::Digest digest; - gen.finalize(&ctx, &digest); - SLANG_CHECK(DigestUtil::toString(digest) == "D41D8CD98F00B204E9800998ECF8427E"); - } - - // One call to update() - { - MD5Context ctx; - MD5HashGen gen; - gen.init(&ctx); - const String str("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."); - gen.update(&ctx, str.getBuffer(), str.getLength()); - slang::Digest digest; - gen.finalize(&ctx, &digest); - SLANG_CHECK(DigestUtil::toString(digest) == "818C6E601A24F72750DA0F6C9B8EBE28"); - } - - // Two calls to update() - { - MD5Context ctx; - MD5HashGen gen; - gen.init(&ctx); - const String str1("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."); - const String str2("Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."); - gen.update(&ctx, str1.getBuffer(), str1.getLength()); - gen.update(&ctx, str2.getBuffer(), str2.getLength()); - slang::Digest digest; - gen.finalize(&ctx, &digest); - SLANG_CHECK(DigestUtil::toString(digest) == "87D3CAECB0AB82FAAE84D60FDE994ACA"); - } -} |
