Reference implementations of PQC
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

86 lines
3.1 KiB

  1. """
  2. Checks that files duplicated across schemes/implementations are consistent.
  3. """
  4. import difflib
  5. import os
  6. import sys
  7. import yaml
  8. import helpers
  9. import pqclean
  10. sys.tracebacklimit = 0
  11. def pytest_generate_tests(metafunc):
  12. ids = []
  13. argvalues = []
  14. if 'duplicate_consistency' not in os.environ.get('PQCLEAN_SKIP_TESTS', '').split(','):
  15. for scheme in pqclean.Scheme.all_schemes():
  16. for implementation in scheme.implementations:
  17. if os.path.isfile(
  18. os.path.join(
  19. 'duplicate_consistency',
  20. '{}_{}.yml'.format(scheme.name, implementation.name))):
  21. metafile = os.path.join(
  22. 'duplicate_consistency',
  23. '{}_{}.yml'.format(scheme.name, implementation.name))
  24. with open(metafile, encoding='utf-8') as f:
  25. metadata = yaml.safe_load(f.read())
  26. for group in metadata['consistency_checks']:
  27. source = pqclean.Implementation.by_name(
  28. group['source']['scheme'],
  29. group['source']['implementation'])
  30. argvalues.append(
  31. (implementation, source, group['files']))
  32. ids.append(
  33. "{metafile}: {scheme.name} {implementation.name}"
  34. .format(scheme=scheme,
  35. implementation=implementation,
  36. metafile=metafile))
  37. else:
  38. # Placeholders so we don't crash
  39. ids = ['dummy']
  40. argvalues = [('dummy', 'dummy', 'dummy')]
  41. metafunc.parametrize(('implementation', 'source', 'files'),
  42. argvalues,
  43. ids=ids)
  44. def file_get_contents(filename):
  45. with open(filename) as file:
  46. return file.read()
  47. @helpers.filtered_test
  48. def test_duplicate_consistency(implementation, source, files):
  49. """Test sets of files to be identical modulo namespacing"""
  50. messages = []
  51. for file in files:
  52. target_path = os.path.join(source.path(), file)
  53. this_path = os.path.join(implementation.path(), file)
  54. target_src = file_get_contents(target_path)\
  55. .replace(source.namespace_prefix(), '')\
  56. .replace(' ', '')
  57. this_src = file_get_contents(this_path)\
  58. .replace(implementation.namespace_prefix(), '')\
  59. .replace(' ', '')
  60. if not this_src == target_src:
  61. diff = difflib.unified_diff(
  62. this_src.splitlines(keepends=True),
  63. target_src.splitlines(keepends=True),
  64. fromfile=this_path,
  65. tofile=target_path)
  66. messages.append("{} differed:\n{}".format(file, ''.join(diff)))
  67. if messages:
  68. raise AssertionError("Files differed:\n{}".format('\n'.join(messages)))
  69. if __name__ == '__main__':
  70. import pytest
  71. pytest.main(sys.argv)