test_dht_storage.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import time
  2. from hivemind.dht.routing import get_dht_time
  3. from hivemind.dht.storage import DHTLocalStorage, DHTID, DictionaryDHTValue
  4. from hivemind.utils.serializer import MSGPackSerializer
  5. def test_store():
  6. d = DHTLocalStorage()
  7. d.store(DHTID.generate("key"), b"val", get_dht_time() + 0.5)
  8. assert d.get(DHTID.generate("key"))[0] == b"val", "Wrong value"
  9. print("Test store passed")
  10. def test_get_expired():
  11. d = DHTLocalStorage()
  12. d.store(DHTID.generate("key"), b"val", get_dht_time() + 0.1)
  13. time.sleep(0.5)
  14. assert d.get(DHTID.generate("key")) is None, "Expired value must be deleted"
  15. print("Test get expired passed")
  16. def test_get_empty():
  17. d = DHTLocalStorage()
  18. assert d.get(DHTID.generate(source="key")) is None, "DHTLocalStorage returned non-existent value"
  19. print("Test get expired passed")
  20. def test_change_expiration_time():
  21. d = DHTLocalStorage()
  22. d.store(DHTID.generate("key"), b"val1", get_dht_time() + 1)
  23. assert d.get(DHTID.generate("key"))[0] == b"val1", "Wrong value"
  24. d.store(DHTID.generate("key"), b"val2", get_dht_time() + 200)
  25. time.sleep(1)
  26. assert d.get(DHTID.generate("key"))[0] == b"val2", "Value must be changed, but still kept in table"
  27. print("Test change expiration time passed")
  28. def test_maxsize_cache():
  29. d = DHTLocalStorage(maxsize=2)
  30. d.store(DHTID.generate("key1a"), b"val1a", get_dht_time() + 1)
  31. d.store(DHTID.generate("key1b"), b"val1b", get_dht_time() + 1)
  32. d.store(DHTID.generate("key1a"), b"val1a2", get_dht_time() + 2)
  33. d.store(DHTID.generate("key2"), b"val2", get_dht_time() + 200)
  34. assert d.get(DHTID.generate("key2"))[0] == b"val2", "Value with bigger exp. time must be kept"
  35. assert d.get(DHTID.generate("key1a"))[0] == b"val1a2", "Value with bigger exp. time must be kept"
  36. assert d.get(DHTID.generate("key1b")) is None, "Value with less exp time, must be deleted"
  37. def test_localstorage_top():
  38. d = DHTLocalStorage(maxsize=3)
  39. d.store(DHTID.generate("key1"), b"val1", get_dht_time() + 1)
  40. d.store(DHTID.generate("key2"), b"val2", get_dht_time() + 2)
  41. d.store(DHTID.generate("key3"), b"val3", get_dht_time() + 4)
  42. assert d.top()[0] == DHTID.generate("key1") and d.top()[1].value == b"val1"
  43. d.store(DHTID.generate("key1"), b"val1_new", get_dht_time() + 3)
  44. assert d.top()[0] == DHTID.generate("key2") and d.top()[1].value == b"val2"
  45. del d[DHTID.generate('key2')]
  46. assert d.top()[0] == DHTID.generate("key1") and d.top()[1].value == b"val1_new"
  47. d.store(DHTID.generate("key2"), b"val2_new", get_dht_time() + 5)
  48. d.store(DHTID.generate("key4"), b"val4", get_dht_time() + 6) # key4 will push out key1 due to maxsize
  49. assert d.top()[0] == DHTID.generate("key3") and d.top()[1].value == b"val3"
  50. def test_localstorage_nested():
  51. time = get_dht_time()
  52. d1 = DHTLocalStorage()
  53. d2 = DictionaryDHTValue()
  54. d2.store('subkey1', b'value1', time + 2)
  55. d2.store('subkey2', b'value2', time + 3)
  56. d2.store('subkey3', b'value3', time + 1)
  57. assert d2.latest_expiration_time == time + 3
  58. for subkey, (subvalue, subexpiration) in d2.items():
  59. assert d1.store_subkey(DHTID.generate('foo'), subkey, subvalue, subexpiration)
  60. assert d1.store(DHTID.generate('bar'), b'456', time + 2)
  61. assert d1.get(DHTID.generate('foo'))[0].data == d2.data
  62. assert d1.get(DHTID.generate('foo'))[1] == d2.latest_expiration_time
  63. assert d1.get(DHTID.generate('foo'))[0].get('subkey1') == (b'value1', time + 2)
  64. assert len(d1.get(DHTID.generate('foo'))[0]) == 3
  65. assert d1.store_subkey(DHTID.generate('foo'), 'subkey4', b'value4', time + 4)
  66. assert len(d1.get(DHTID.generate('foo'))[0]) == 4
  67. assert d1.store_subkey(DHTID.generate('bar'), 'subkeyA', b'valueA', time + 1) is False # prev has better expiration
  68. assert d1.store_subkey(DHTID.generate('bar'), 'subkeyA', b'valueA', time + 3) # new value has better expiration
  69. assert d1.store_subkey(DHTID.generate('bar'), 'subkeyB', b'valueB', time + 4) # new value has better expiration
  70. assert d1.store_subkey(DHTID.generate('bar'), 'subkeyA', b'valueA+', time + 5) # overwrite subkeyA under key bar
  71. assert all(subkey in d1.get(DHTID.generate('bar'))[0] for subkey in ('subkeyA', 'subkeyB'))
  72. assert len(d1.get(DHTID.generate('bar'))[0]) == 2 and d1.get(DHTID.generate('bar'))[1] == time + 5
  73. assert d1.store(DHTID.generate('foo'), b'nothing', time + 3.5) is False # previous value has better expiration
  74. assert d1.get(DHTID.generate('foo'))[0].get('subkey2') == (b'value2', time + 3)
  75. assert d1.store(DHTID.generate('foo'), b'nothing', time + 5) is True # new value has better expiraiton
  76. assert d1.get(DHTID.generate('foo')) == (b'nothing', time + 5) # value should be replaced
  77. def test_localstorage_freeze():
  78. d = DHTLocalStorage(maxsize=2)
  79. with d.freeze():
  80. d.store(DHTID.generate("key1"), b"val1", get_dht_time() + 0.01)
  81. assert DHTID.generate("key1") in d
  82. time.sleep(0.03)
  83. assert DHTID.generate("key1") in d
  84. assert DHTID.generate("key1") not in d
  85. with d.freeze():
  86. d.store(DHTID.generate("key1"), b"val1", get_dht_time() + 1)
  87. d.store(DHTID.generate("key2"), b"val2", get_dht_time() + 2)
  88. d.store(DHTID.generate("key3"), b"val3", get_dht_time() + 3) # key3 will push key1 out due to maxsize
  89. assert DHTID.generate("key1") in d
  90. assert DHTID.generate("key1") not in d
  91. def test_localstorage_serialize():
  92. d1 = DictionaryDHTValue()
  93. d2 = DictionaryDHTValue()
  94. now = get_dht_time()
  95. d1.store('key1', b'ololo', now + 1)
  96. d2.store('key2', b'pysh', now + 1)
  97. d2.store('key3', b'pyshpysh', now + 2)
  98. data = MSGPackSerializer.dumps([d1, d2, 123321])
  99. assert isinstance(data, bytes)
  100. new_d1, new_d2, new_value = MSGPackSerializer.loads(data)
  101. assert isinstance(new_d1, DictionaryDHTValue) and isinstance(new_d2, DictionaryDHTValue) and new_value == 123321
  102. assert 'key1' in new_d1 and len(new_d1) == 1
  103. assert 'key1' not in new_d2 and len(new_d2) == 2 and new_d2.get('key3') == (b'pyshpysh', now + 2)