subseed.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. #!/usr/bin/env python3
  2. """
  3. test.modtest_d.subseed: subseed unit tests for the MMGen suite
  4. """
  5. from mmgen.util import msg
  6. from mmgen.seed import Seed
  7. from mmgen.subseed import SubSeedList, SubSeedIdxRange
  8. from ..include.common import cfg, vmsg
  9. nSubseeds = SubSeedList.dfl_len
  10. class unit_tests:
  11. def ops(self, name, ut, desc='basic ops...'):
  12. for a, b, c, d, e, f, h in (
  13. (8, '4710FBF0', '0C1B0615', '803B165C', '2669AC64', 256, '10L'),
  14. (6, '9D07ABBD', 'EBA9C33F', '20787E6A', '192E2AA2', 192, '10L'),
  15. (4, '43670520', '04A4CCB3', 'B5F21D7B', 'C1934CFF', 128, '10L'),
  16. ):
  17. seed_bin = bytes.fromhex('deadbeef' * a)
  18. seed = Seed(cfg, seed_bin=seed_bin)
  19. assert seed.sid == b, seed.sid
  20. subseed = seed.subseed('2s')
  21. assert subseed.sid == c, subseed.sid
  22. subseed = seed.subseed('3')
  23. assert subseed.sid == d, subseed.sid
  24. subseed = seed.subseed_by_seed_id(e)
  25. assert subseed.bitlen == f, subseed.bitlen
  26. assert subseed.sid == e, subseed.sid
  27. assert subseed.idx == 10, subseed.idx
  28. assert subseed.ss_idx == h, subseed.ss_idx
  29. seed2 = Seed(cfg, seed_bin=seed_bin)
  30. ss2_list = seed2.subseeds
  31. seed2.subseeds._generate(1)
  32. assert len(ss2_list) == 1, len(ss2_list)
  33. seed2.subseeds._generate(1) # do nothing
  34. seed2.subseeds._generate(2) # append one item
  35. seed2.subseeds._generate(5)
  36. assert len(ss2_list) == 5, len(ss2_list)
  37. seed2.subseeds._generate(3) # do nothing
  38. assert len(ss2_list) == 5, len(ss2_list)
  39. seed2.subseeds._generate(10)
  40. assert len(ss2_list) == 10, len(ss2_list)
  41. assert seed.pfmt() == seed2.pfmt()
  42. assert seed.subseeds.pfmt() == seed2.subseeds.pfmt()
  43. s = seed.subseeds.format(1, nSubseeds)
  44. s_lines = s.strip().split('\n')
  45. assert len(s_lines) == nSubseeds + 4, s
  46. a = seed.subseed('2L').sid
  47. b = [e for e in s_lines if ' 2L:' in e][0].strip().split()[1]
  48. assert a == b, b
  49. c = seed.subseed('2').sid
  50. assert c == a, c
  51. a = seed.subseed('5S').sid
  52. b = [e for e in s_lines if ' 5S:' in e][0].strip().split()[3]
  53. assert a == b, b
  54. s = seed.subseeds.format(nSubseeds+1, nSubseeds+2)
  55. s_lines = s.strip().split('\n')
  56. assert len(s_lines) == 6, s
  57. ss_idx = str(nSubseeds+2) + 'S'
  58. a = seed.subseed(ss_idx).sid
  59. b = [e for e in s_lines if f' {ss_idx}:' in e][0].strip().split()[3]
  60. assert a == b, b
  61. s = seed.subseeds.format(1, 10)
  62. s_lines = s.strip().split('\n')
  63. assert len(s_lines) == 14, s
  64. vmsg(f'{s}')
  65. return True
  66. def limits(self, name, ut, desc='limits and ranges'):
  67. seed_bin = bytes.fromhex('deadbeef' * 8)
  68. vmsg('Testing limits')
  69. seed = Seed(cfg, seed_bin=seed_bin, nSubseeds=11)
  70. seed.subseeds._generate()
  71. ss = seed.subseeds
  72. assert len(ss.data['long']) == len(ss.data['short']), len(ss.data['short'])
  73. assert len(ss) == 11, len(ss)
  74. seed = Seed(cfg, seed_bin=seed_bin)
  75. seed.subseeds._generate()
  76. ss = seed.subseeds
  77. assert len(ss.data['long']) == len(ss.data['short']), len(ss.data['short'])
  78. assert len(ss) == nSubseeds, len(ss)
  79. seed = Seed(cfg, seed_bin=seed_bin)
  80. seed.subseed_by_seed_id('EEEEEEEE')
  81. ss = seed.subseeds
  82. assert len(ss.data['long']) == len(ss.data['short']), len(ss.data['short'])
  83. assert len(ss) == nSubseeds, len(ss)
  84. seed = Seed(cfg, seed_bin=seed_bin)
  85. subseed = seed.subseed_by_seed_id('803B165C')
  86. assert len(ss.data['long']) == len(ss.data['short']), len(ss.data['short'])
  87. assert subseed.sid == '803B165C', subseed.sid
  88. assert subseed.idx == 3, subseed.idx
  89. seed = Seed(cfg, seed_bin=seed_bin)
  90. subseed = seed.subseed_by_seed_id('803B165C', last_idx=1)
  91. assert len(ss.data['long']) == len(ss.data['short']), len(ss.data['short'])
  92. assert subseed is None, subseed
  93. vmsg('Testing SubSeedIdxRange()')
  94. r = SubSeedIdxRange('1-5')
  95. r2 = SubSeedIdxRange(1, 5)
  96. assert r2 == r, r2
  97. assert r == (r.first, r.last), r
  98. assert r.first == 1, r.first
  99. assert r.last == 5, r.last
  100. assert r.items == [1, 2, 3, 4, 5], r.items
  101. assert list(r.iterate()) == r.items, list(r.iterate())
  102. r = SubSeedIdxRange('22')
  103. r2 = SubSeedIdxRange(22, 22)
  104. assert r2 == r, r2
  105. assert r == (r.first, r.last), r
  106. assert r.first == 22, r.first
  107. assert r.last == 22, r.last
  108. assert r.items == [22], r
  109. assert list(r.iterate()) == r.items, list(r.iterate())
  110. r = SubSeedIdxRange('3-3')
  111. assert r.items == [3], r.items
  112. r = SubSeedIdxRange(f'{nSubseeds-1}-{nSubseeds}')
  113. assert r.items == [nSubseeds-1, nSubseeds], r.items
  114. for n, e in enumerate(SubSeedIdxRange('1-5').iterate(), 1):
  115. assert n == e, e
  116. assert n == 5, n
  117. return True
  118. def collisions(self, name, ut, desc='Seed ID collisions'):
  119. ss_count, ltr, last_sid, collisions_chk, mode_desc = (
  120. (SubSeedIdxRange.max_idx, 'S', '2788F26B', 470, 'normal'),
  121. (49509, 'L', '8D1FE500', 2, 'fast')
  122. )[bool(cfg.fast)]
  123. last_idx = str(ss_count) + ltr
  124. vmsg(f'Using {ss_count} subseed pairs ({mode_desc} mode)')
  125. seed_bin = bytes.fromhex('12abcdef' * 8) # 95B3D78D
  126. seed = Seed(cfg, seed_bin=seed_bin)
  127. seed.subseeds._generate(ss_count)
  128. ss = seed.subseeds
  129. assert seed.subseed(last_idx).sid == last_sid, seed.subseed(last_idx).sid
  130. for sid in ss.data['long']:
  131. # msg(sid)
  132. assert sid not in ss.data['short']
  133. collisions = 0
  134. for k in ('short', 'long'):
  135. for sid in ss.data[k]:
  136. collisions += ss.data[k][sid][1]
  137. assert collisions == collisions_chk, collisions
  138. vmsg(f'{collisions} collisions, last_sid {last_sid}')
  139. return True