Added some new tests: TestAllocationAlgorithmsCorrectness
diff --git a/src/Tests.cpp b/src/Tests.cpp
index 94a326e..b7bdb2f 100644
--- a/src/Tests.cpp
+++ b/src/Tests.cpp
@@ -3981,6 +3981,191 @@
     vmaDestroyPool(g_hAllocator, pool);
 }
 
+static void TestAllocationAlgorithmsCorrectness()
+{
+    wprintf(L"Test allocation algorithm correctness\n");
+
+    constexpr uint32_t LEVEL_COUNT = 12;
+    RandomNumberGenerator rand{2342435};
+
+    for(uint32_t isVirtual = 0; isVirtual < 3; ++isVirtual)
+    {
+        // isVirtual == 0: Use VmaPool, unit is 64 KB.
+        // isVirtual == 1: Use VmaVirtualBlock, unit is 64 KB.
+        // isVirtual == 2: Use VmaVirtualBlock, unit is 1 B.
+        const VkDeviceSize sizeUnit = isVirtual == 2 ? 1 : 0x10000;
+        const VkDeviceSize blockSize = (1llu << (LEVEL_COUNT - 1)) * sizeUnit;
+
+        for(uint32_t algorithmIndex = 0; algorithmIndex < 2; ++algorithmIndex)
+        {
+            VmaPool pool = VK_NULL_HANDLE;
+            VmaVirtualBlock virtualBlock = VK_NULL_HANDLE;
+
+            if(isVirtual)
+            {
+                VmaVirtualBlockCreateInfo blockCreateInfo = {};
+                blockCreateInfo.pAllocationCallbacks = g_Allocs;
+                blockCreateInfo.flags = algorithmIndex ? VMA_VIRTUAL_BLOCK_CREATE_TLSF_ALGORITHM_BIT : 0;
+                blockCreateInfo.size = blockSize;
+                TEST(vmaCreateVirtualBlock(&blockCreateInfo, &virtualBlock) == VK_SUCCESS);
+            }
+            else
+            {
+                VmaPoolCreateInfo poolCreateInfo = {};
+                poolCreateInfo.blockSize = blockSize;
+                poolCreateInfo.flags = algorithmIndex ? VMA_POOL_CREATE_TLSF_ALGORITHM_BIT : 0;
+                poolCreateInfo.minBlockCount = poolCreateInfo.maxBlockCount = 1;
+
+                VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+                bufCreateInfo.size = 0x10000; // Doesn't matter.
+                bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+                VmaAllocationCreateInfo allocCreateInfo = {};
+                TEST(vmaFindMemoryTypeIndexForBufferInfo(g_hAllocator, &bufCreateInfo, &allocCreateInfo, &poolCreateInfo.memoryTypeIndex) == VK_SUCCESS);
+
+                TEST(vmaCreatePool(g_hAllocator, &poolCreateInfo, &pool) == VK_SUCCESS);
+            }
+
+            for(uint32_t strategyIndex = 0; strategyIndex < 3; ++strategyIndex)
+            {
+                struct AllocData
+                {
+                    VmaAllocation alloc = VK_NULL_HANDLE;
+                    VkBuffer buf = VK_NULL_HANDLE;
+                    VmaVirtualAllocation virtualAlloc = VK_NULL_HANDLE;
+                };
+                std::vector<AllocData> allocationsPerLevel[LEVEL_COUNT];
+
+                auto createAllocation = [&](uint32_t level) -> void
+                {
+                    AllocData allocData;
+                    const VkDeviceSize allocSize = (1llu << level) * sizeUnit;
+                    if(isVirtual)
+                    {
+                        VmaVirtualAllocationCreateInfo allocCreateInfo = {};
+                        allocCreateInfo.size = allocSize;
+                        switch(strategyIndex)
+                        {
+                        case 1: allocCreateInfo.flags = VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT; break;
+                        case 2: allocCreateInfo.flags = VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT; break;
+                        }
+                        TEST(vmaVirtualAllocate(virtualBlock, &allocCreateInfo, &allocData.virtualAlloc, nullptr) == VK_SUCCESS);
+                    }
+                    else
+                    {
+                        VmaAllocationCreateInfo allocCreateInfo = {};
+                        allocCreateInfo.pool = pool;
+                        switch(strategyIndex)
+                        {
+                        case 1: allocCreateInfo.flags = VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT; break;
+                        case 2: allocCreateInfo.flags = VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT; break;
+                        }
+                        VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+                        bufCreateInfo.size = allocSize;
+                        bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+                        TEST(vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo, &allocData.buf, &allocData.alloc, nullptr) == VK_SUCCESS);
+                    }
+                    allocationsPerLevel[level].push_back(allocData);
+                };
+
+                auto destroyAllocation = [&](uint32_t level, size_t index) -> void
+                {
+                    const AllocData& allocData = allocationsPerLevel[level][index];
+                    if(isVirtual)
+                        vmaVirtualFree(virtualBlock, allocData.virtualAlloc);
+                    else
+                        vmaDestroyBuffer(g_hAllocator, allocData.buf, allocData.alloc);
+                    allocationsPerLevel[level].erase(allocationsPerLevel[level].begin() + index);
+                };
+
+                // Fill entire block with one big allocation.
+                createAllocation(LEVEL_COUNT - 1);
+
+                // For each level, remove one allocation and refill it with 2 allocations at lower level.
+                for(uint32_t level = LEVEL_COUNT; level-- > 1; )
+                {
+                    size_t indexToDestroy = rand.Generate() % allocationsPerLevel[level].size();
+                    destroyAllocation(level, indexToDestroy);
+                    createAllocation(level - 1);
+                    createAllocation(level - 1);
+                }
+
+                // Test statistics.
+                {
+                    uint32_t actualAllocCount = 0, statAllocCount = 0;
+                    VkDeviceSize actualAllocSize = 0, statAllocSize = 0;
+                    // Calculate actual statistics.
+                    for(uint32_t level = 0; level < LEVEL_COUNT; ++level)
+                    {
+                        for(size_t index = allocationsPerLevel[level].size(); index--; )
+                        {
+                            if(isVirtual)
+                            {
+                                VmaVirtualAllocationInfo allocInfo = {};
+                                vmaGetVirtualAllocationInfo(virtualBlock, allocationsPerLevel[level][index].virtualAlloc, &allocInfo);
+                                actualAllocSize += allocInfo.size;
+                            }
+                            else
+                            {
+                                VmaAllocationInfo allocInfo = {};
+                                vmaGetAllocationInfo(g_hAllocator, allocationsPerLevel[level][index].alloc, &allocInfo);
+                                actualAllocSize += allocInfo.size;
+                            }
+                        }
+                        actualAllocCount += (uint32_t)allocationsPerLevel[level].size();
+                    }
+                    // Fetch reported statistics.
+                    if(isVirtual)
+                    {
+                        VmaStatInfo info = {};
+                        vmaCalculateVirtualBlockStats(virtualBlock, &info);
+                        statAllocCount = info.allocationCount;
+                        statAllocSize = info.usedBytes;
+                        TEST(info.blockCount == 1);
+                        TEST(info.usedBytes + info.unusedBytes == blockSize);
+                    }
+                    else
+                    {
+                        VmaPoolStats stats = {};
+                        vmaGetPoolStats(g_hAllocator, pool, &stats);
+                        statAllocCount = (uint32_t)stats.allocationCount;
+                        statAllocSize = stats.size - stats.unusedSize;
+                        TEST(stats.blockCount == 1);
+                        TEST(stats.size == blockSize);
+                    }
+                    // Compare them.
+                    TEST(actualAllocCount == statAllocCount);
+                    TEST(actualAllocSize == statAllocSize);
+                }
+
+                // Test JSON dump - for manual inspection.
+                {
+                    char* json = nullptr;
+                    if(isVirtual)
+                    {
+                        vmaBuildVirtualBlockStatsString(virtualBlock, &json, VK_TRUE);
+                        int I = 1; // Put breakpoint here to inspect `json`.
+                        vmaFreeVirtualBlockStatsString(virtualBlock, json);
+                    }
+                    else
+                    {
+                        vmaBuildStatsString(g_hAllocator, &json, VK_TRUE);
+                        int I = 1; // Put breakpoint here to inspect `json`.
+                        vmaFreeStatsString(g_hAllocator, json);
+                    }
+                }
+
+                // Free all remaining allocations
+                for(uint32_t level = 0; level < LEVEL_COUNT; ++level)
+                    for(size_t index = allocationsPerLevel[level].size(); index--; )
+                        destroyAllocation(level, index);
+            }
+
+            vmaDestroyVirtualBlock(virtualBlock);
+            vmaDestroyPool(g_hAllocator, pool);
+        }
+    }
+}
+
 static void ManuallyTestLinearAllocator()
 {
     VmaStats origStats;
@@ -7081,6 +7266,7 @@
     TestLinearAllocator();
     ManuallyTestLinearAllocator();
     TestLinearAllocatorMultiBlock();
+    TestAllocationAlgorithmsCorrectness();
 
     BasicTestTLSF();
     BasicTestBuddyAllocator();