/tests/proto/loop_prevention.py

http://github.com/rawler/bithorde
Python | 93 lines | 62 code | 17 blank | 14 comment | 4 complexity | a763c884325ad06a88ad52d05500166b MD5 | raw file
  1. #!/usr/bin/env python2
  2. from bithordetest import message, BithordeD, TestConnection
  3. from random import randint
  4. ASSET_IDS = [message.Identifier(type=message.TREE_TIGER, id='GIS3CRGMSBT7CKRBLQFXFAL3K4YIO5P5E3AMC2A')]
  5. INITIAL_REQUEST = randint(0,(2**64)-1)
  6. if __name__ == '__main__':
  7. bithorded = BithordeD(config={
  8. 'friend.upstream1.addr': '',
  9. 'friend.upstream2.addr': '',
  10. })
  11. upstream1 = TestConnection(bithorded, name='upstream1')
  12. upstream2 = TestConnection(bithorded, name='upstream2')
  13. downstream1 = TestConnection(bithorded, name='downstream1')
  14. downstream2 = TestConnection(bithorded, name='downstream2')
  15. # Request an asset-session
  16. downstream1.send(message.BindRead(handle=1, ids=ASSET_IDS, timeout=500, requesters=[INITIAL_REQUEST]))
  17. req1 = upstream1.expect(message.BindRead)
  18. assert len(req1.requesters) > 1
  19. assert INITIAL_REQUEST in req1.requesters
  20. assert INITIAL_REQUEST == req1.requesters[-1] # Try to keep backwards compatibility
  21. server_id = next(x for x in req1.requesters if x != INITIAL_REQUEST)
  22. # Let upstream1 join as server
  23. upstream1.send(message.AssetStatus(handle=req1.handle, status=message.SUCCESS, ids=ASSET_IDS, servers=[99998888], size=15))
  24. resp = downstream1.expect(message.AssetStatus)
  25. assert len(resp.servers) > 1
  26. assert 99998888 in resp.servers
  27. assert server_id in resp.servers
  28. # Let upstream2 join as server
  29. req2 = upstream2.expect(message.BindRead)
  30. upstream2.send(message.AssetStatus(handle=req2.handle, status=message.SUCCESS, ids=ASSET_IDS, servers=[12345], size=15))
  31. resp = downstream1.expect(message.AssetStatus)
  32. assert 99998888 in resp.servers
  33. assert server_id in resp.servers
  34. assert 12345 in resp.servers
  35. # Let upstream1 leave
  36. upstream1.send(message.AssetStatus(handle=req2.handle, status=message.NOTFOUND))
  37. resp = downstream1.expect(message.AssetStatus)
  38. assert 99998888 not in resp.servers
  39. assert server_id in resp.servers
  40. assert 12345 in resp.servers
  41. # Add another downstream
  42. downstream2.send(message.BindRead(handle=1, ids=ASSET_IDS, timeout=500, requesters=[9873474]))
  43. req2 = upstream2.expect(message.BindRead)
  44. assert len(req2.requesters) > 2
  45. assert INITIAL_REQUEST in req2.requesters
  46. assert 9873474 in req2.requesters
  47. resp2 = downstream2.expect(message.AssetStatus(status=message.SUCCESS))
  48. # Simulate loop on client1
  49. downstream1.send(message.BindRead(handle=1, ids=ASSET_IDS, timeout=500, requesters=[9873474, 12345]))
  50. resp1 = downstream1.expect(message.AssetStatus(status=message.WOULD_LOOP))
  51. # Simulate redundantly connected downstream on downstream1
  52. downstream1.send(message.BindRead(handle=1, ids=ASSET_IDS, timeout=500, requesters=[9873474]))
  53. resp1 = downstream1.expect(message.AssetStatus(status=message.SUCCESS))
  54. # Close both downstreams
  55. downstream1.send(message.BindRead(handle=1, ids=[]))
  56. downstream1.expect(message.AssetStatus(handle=1, status=message.NOTFOUND))
  57. downstream2.send(message.BindRead(handle=1, ids=[]))
  58. downstream2.expect(message.AssetStatus(handle=1, status=message.NOTFOUND))
  59. # Simulate late loop
  60. downstream1.send(message.BindRead(handle=1, ids=ASSET_IDS, timeout=500, requesters=req2.requesters))
  61. downstream1.expect(message.AssetStatus(status=message.WOULD_LOOP))
  62. # Reset
  63. for x in (upstream1, upstream2, downstream1, downstream2):
  64. x.close()
  65. upstream1 = TestConnection(bithorded, name='upstream1')
  66. downstream1 = TestConnection(bithorded, name='downstream1')
  67. # Test concurrent-request race-condition
  68. downstream1.send(message.BindRead(handle=1, ids=ASSET_IDS, timeout=500, requesters=[123124]))
  69. req = upstream1.expect(message.BindRead(handle=1, ids=ASSET_IDS))
  70. assert 123124 in req.requesters
  71. # Assume upstream1 had already sent this, unknowing that server would ask too.
  72. upstream1.send(message.BindRead(handle=1, ids=ASSET_IDS, timeout=500, requesters=[123124, 421321]))
  73. upstream1.send(message.AssetStatus(handle=req.handle, status=message.SUCCESS, ids=ASSET_IDS, size=15, servers=[1018,421321]))
  74. # Server is now assumed to reject upstream1, since the same node appear as requester and server
  75. upstream1.expect(message.BindRead(handle=1, ids=[]))
  76. downstream1.expect(message.AssetStatus(handle=1, status=message.NOTFOUND))