|
1 | 1 | from async_substrate_interface.types import ScaleObj, Runtime, RuntimeCache |
| 2 | +from async_substrate_interface.async_substrate import DiskCachedAsyncSubstrateInterface |
| 3 | +from async_substrate_interface.utils import cache |
| 4 | + |
| 5 | +import sqlite3 |
| 6 | +import os |
| 7 | +import pickle |
| 8 | +import pytest |
| 9 | +from unittest.mock import patch |
2 | 10 |
|
3 | 11 |
|
4 | 12 | def test_scale_object(): |
@@ -84,3 +92,71 @@ def test_runtime_cache(): |
84 | 92 | assert runtime_cache.retrieve(newer_fake_block) is not None |
85 | 93 | assert runtime_cache.retrieve(fake_block, block_hash=new_fake_hash) is not None |
86 | 94 | assert runtime_cache.retrieve(block_hash=new_fake_hash) is not None |
| 95 | + |
| 96 | + |
| 97 | +@pytest.mark.asyncio |
| 98 | +async def test_runtime_cache_from_disk(): |
| 99 | + test_db_location = "/tmp/async-substrate-interface-test-cache" |
| 100 | + fake_chain = "ws://fake.com" |
| 101 | + fake_block = 1 |
| 102 | + fake_hash = "0xignore" |
| 103 | + new_fake_block = 2 |
| 104 | + new_fake_hash = "0xnewfakehash" |
| 105 | + |
| 106 | + if os.path.exists(test_db_location): |
| 107 | + os.remove(test_db_location) |
| 108 | + with patch.object(cache, "CACHE_LOCATION", test_db_location): |
| 109 | + substrate = DiskCachedAsyncSubstrateInterface(fake_chain, _mock=True) |
| 110 | + # Needed to avoid trying to initialize on the network during `substrate.initialize()` |
| 111 | + substrate.initialized = True |
| 112 | + |
| 113 | + # runtime cache should be completely empty |
| 114 | + assert substrate.runtime_cache.block_hashes == {} |
| 115 | + assert substrate.runtime_cache.blocks == {} |
| 116 | + assert substrate.runtime_cache.versions == {} |
| 117 | + await substrate.initialize() |
| 118 | + |
| 119 | + # after initialization, runtime cache should still be completely empty |
| 120 | + assert substrate.runtime_cache.block_hashes == {} |
| 121 | + assert substrate.runtime_cache.blocks == {} |
| 122 | + assert substrate.runtime_cache.versions == {} |
| 123 | + await substrate.close() |
| 124 | + |
| 125 | + # ensure we have created the SQLite DB during initialize() |
| 126 | + assert os.path.exists(test_db_location) |
| 127 | + |
| 128 | + # insert some fake data into our DB |
| 129 | + conn = sqlite3.connect(test_db_location) |
| 130 | + conn.execute( |
| 131 | + "INSERT INTO RuntimeCache_blocks (key, value, chain) VALUES (?, ?, ?)", |
| 132 | + (fake_block, pickle.dumps(fake_hash), fake_chain), |
| 133 | + ) |
| 134 | + conn.commit() |
| 135 | + conn.close() |
| 136 | + |
| 137 | + substrate.initialized = True |
| 138 | + await substrate.initialize() |
| 139 | + assert substrate.runtime_cache.blocks == {fake_block: fake_hash} |
| 140 | + # add an item to the cache |
| 141 | + substrate.runtime_cache.add_item( |
| 142 | + runtime=None, block_hash=new_fake_hash, block=new_fake_block |
| 143 | + ) |
| 144 | + await substrate.close() |
| 145 | + |
| 146 | + # verify that our added item is now in the DB |
| 147 | + conn = sqlite3.connect(test_db_location) |
| 148 | + cursor = conn.cursor() |
| 149 | + cursor.execute("SELECT key, value, chain FROM RuntimeCache_blocks") |
| 150 | + query = cursor.fetchall() |
| 151 | + cursor.close() |
| 152 | + conn.close() |
| 153 | + |
| 154 | + first_row = query[0] |
| 155 | + assert first_row[0] == fake_block |
| 156 | + assert pickle.loads(first_row[1]) == fake_hash |
| 157 | + assert first_row[2] == fake_chain |
| 158 | + |
| 159 | + second_row = query[1] |
| 160 | + assert second_row[0] == new_fake_block |
| 161 | + assert pickle.loads(second_row[1]) == new_fake_hash |
| 162 | + assert second_row[2] == fake_chain |
0 commit comments