Parcourir la source

Add support for specifying architecture and feature limits (#224)

* Add support for specifying architecture and feature limits

* cpuinfo not supported on ppc

* Detect 32-bit python interpreter on 64-bit CPU

* Fix bugs in isolated tests

* Also support restricting operating system
master
Thom Wiggers il y a 5 ans
committed by Matthias J. Kannwischer
Parent
révision
2eaf382689
15 fichiers modifiés avec 117 ajouts et 21 suppressions
  1. +1
    -0
      requirements.txt
  2. +1
    -1
      test/Makefile
  3. +54
    -0
      test/pqclean.py
  4. +2
    -2
      test/test_compile_lib.py
  5. +2
    -2
      test/test_dynamic_memory.py
  6. +4
    -4
      test/test_functest.py
  7. +1
    -1
      test/test_linter.py
  8. +2
    -2
      test/test_makefile_dependencies.py
  9. +15
    -2
      test/test_makefiles_present.py
  10. +25
    -0
      test/test_metadata.py
  11. +1
    -1
      test/test_metadata_sizes.py
  12. +2
    -2
      test/test_nistkat.py
  13. +2
    -2
      test/test_symbol_namespace.py
  14. +3
    -0
      test/test_testvectors.py
  15. +2
    -2
      test/test_valgrind.py

+ 1
- 0
requirements.txt Voir le fichier

@@ -2,3 +2,4 @@ PyYAML
pytest
pytest-xdist
pycparser
py-cpuinfo

+ 1
- 1
test/Makefile Voir le fichier

@@ -69,7 +69,7 @@ $(DEST_DIR)/testvectors_$(SCHEME)_$(IMPLEMENTATION): build-scheme crypto_$(TYPE)
mkdir -p $(DEST_DIR)
$(CC) $(CFLAGS) -DPQCLEAN_NAMESPACE=PQCLEAN_$(SCHEME_UPPERCASE)_$(IMPLEMENTATION_UPPERCASE) -I$(SCHEME_DIR) crypto_$(TYPE)/testvectors.c $(COMMON_FILES) $(TEST_COMMON_DIR)/notrandombytes.c -o $@ -L$(SCHEME_DIR) -l$(SCHEME)_$(IMPLEMENTATION)

$(DEST_DIR)/printparams_$(SCHEME)_$(IMPLEMENTATION): build-scheme crypto_$(TYPE)/printparams.c
$(DEST_DIR)/printparams_$(SCHEME)_$(IMPLEMENTATION): crypto_$(TYPE)/printparams.c
mkdir -p $(DEST_DIR)
$(CC) $(CFLAGS) -DPQCLEAN_NAMESPACE=PQCLEAN_$(SCHEME_UPPERCASE)_$(IMPLEMENTATION_UPPERCASE) -I$(SCHEME_DIR) crypto_$(TYPE)/printparams.c -o $@



+ 54
- 0
test/pqclean.py Voir le fichier

@@ -1,7 +1,9 @@
import glob
import os
from typing import Optional

import yaml
import platform


class Scheme:
@@ -37,6 +39,11 @@ class Scheme:
implementations.extend(scheme.implementations)
return implementations

@staticmethod
def all_supported_implementations():
return [impl for impl in Scheme.all_implementations()
if impl.supported_on_current_platform()]

@staticmethod
def all_schemes_of_type(type: str) -> list:
schemes = []
@@ -111,10 +118,57 @@ class Implementation:
implementations.append(Implementation(scheme, d))
return implementations

@staticmethod
def all_supported_implementations(scheme: Scheme) -> list:
return [impl for impl in Implementation.all_implementations(scheme)
if impl.supported_on_current_platform()]

def namespace_prefix(self):
return '{}{}_'.format(self.scheme.namespace_prefix(),
self.name.upper()).replace('-', '')

def supported_on_os(self, os: Optional[str] = None) -> bool:
"""Check if we support the OS

If no OS is specified, then we run on the current OS
"""
if os is None:
os = platform.system()

for platform_ in self.metadata().get('supported_platforms', []):
if 'operating_systems' in platform_:
if os not in platform_['operating_systems']:
return False

return True

def supported_on_current_platform(self) -> bool:
if 'supported_platforms' not in self.metadata():
return True

if platform.machine() == 'ppc':
return False

if not self.supported_on_os():
return False

if not hasattr(Implementation, 'CPUINFO'):
import cpuinfo
Implementation.CPUINFO = cpuinfo.get_cpu_info()

CPUINFO = Implementation.CPUINFO

for platform_ in self.metadata()['supported_platforms']:
if platform_['architecture'] == CPUINFO['arch'].lower():
# Detect actually running on emulated i386
if (platform_['architecture'] == 'x86_64' and
platform.architecture()[0] == '32bit'):
continue
if all([flag in CPUINFO['flags']
for flag in platform_['required_flags']]):
return True
return False

def __str__(self):
return "{} implementation of {}".format(self.name, self.scheme.name)



+ 2
- 2
test/test_compile_lib.py Voir le fichier

@@ -11,8 +11,8 @@ import pqclean
@pytest.mark.parametrize(
'implementation,test_dir,impl_dir, init, destr',
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
for impl in pqclean.Scheme.all_implementations()],
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
for impl in pqclean.Scheme.all_supported_implementations()],
ids=[str(impl) for impl in pqclean.Scheme.all_supported_implementations()],
)
@helpers.filtered_test
def test_compile_lib(implementation, test_dir, impl_dir, init, destr):


+ 2
- 2
test/test_dynamic_memory.py Voir le fichier

@@ -11,8 +11,8 @@ import pqclean
@pytest.mark.parametrize(
'implementation,test_dir,impl_path, init, destr',
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
for impl in pqclean.Scheme.all_implementations()],
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
for impl in pqclean.Scheme.all_supported_implementations()],
ids=[str(impl) for impl in pqclean.Scheme.all_supported_implementations()],
)
@helpers.skip_windows()
@helpers.filtered_test


+ 4
- 4
test/test_functest.py Voir le fichier

@@ -16,8 +16,8 @@ import pqclean
@pytest.mark.parametrize(
'implementation,test_dir,impl_path, init, destr',
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
for impl in pqclean.Scheme.all_implementations()],
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
for impl in pqclean.Scheme.all_supported_implementations()],
ids=[str(impl) for impl in pqclean.Scheme.all_supported_implementations()],
)
@helpers.filtered_test
def test_functest(implementation, impl_path, test_dir,
@@ -45,8 +45,8 @@ def test_functest(implementation, impl_path, test_dir,
'implementation,test_dir,impl_path, init, destr',
[(impl,
*helpers.isolate_test_files(impl.path(), 'test_functest_sanitizers_'))
for impl in pqclean.Scheme.all_implementations()],
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
for impl in pqclean.Scheme.all_supported_implementations()],
ids=[str(impl) for impl in pqclean.Scheme.all_supported_implementations()],
)
@helpers.skip_windows()
@helpers.filtered_test


+ 1
- 1
test/test_linter.py Voir le fichier

@@ -13,7 +13,7 @@ additional_flags = [] #['-fix-errors']

@pytest.mark.parametrize(
'implementation',
pqclean.Scheme.all_implementations(),
pqclean.Scheme.all_supported_implementations(),
ids=str,
)
@helpers.skip_windows()


+ 2
- 2
test/test_makefile_dependencies.py Voir le fichier

@@ -17,8 +17,8 @@ import pqclean
'implementation,test_dir,impl_path, init, destr',
[(impl,
*helpers.isolate_test_files(impl.path(), 'test_makefile_deps_'))
for impl in pqclean.Scheme.all_implementations()],
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
for impl in pqclean.Scheme.all_supported_implementations()],
ids=[str(impl) for impl in pqclean.Scheme.all_supported_implementations()],
)
@helpers.filtered_test
def test_makefile_dependencies(implementation, impl_path, test_dir,


+ 15
- 2
test/test_makefiles_present.py Voir le fichier

@@ -17,10 +17,23 @@ import pqclean
ids=str,
)
@helpers.filtered_test
def test_makefiles_present(implementation):
def test_makefile_present(implementation):
p1 = os.path.join(implementation.path(), 'Makefile')
assert os.path.isfile(p1)


@pytest.mark.parametrize(
'implementation',
pqclean.Scheme.all_implementations(),
ids=str,
)
@helpers.filtered_test
def test_microsoft_nmakefile_present(implementation):
p2 = os.path.join(implementation.path(), 'Makefile.Microsoft_nmake')
assert(os.path.isfile(p1) and os.path.isfile(p2))
if implementation.supported_on_os(os='Windows'):
assert os.path.isfile(p2)
else:
assert not os.path.isfile(p2), "Should not have an NMake file"


if __name__ == '__main__':


+ 25
- 0
test/test_metadata.py Voir le fichier

@@ -61,6 +61,31 @@ EXPECTED_FIELDS = {
'spec': {
'name': {'type': str},
'version': {'type': str},
'supported_platforms': {
'type': list,
'optional': True,
'elements': {
'type': dict,
'spec': {
'architecture': {
'type': str,
'values': ['x86', 'x86_64', 'aarch64']},
'required_flags': {
'type': list,
'optional': True,
'elements': {'type': str},
},
'operating_systems': {
'type': list,
'optional': True,
'elements': {
'type': str,
'values': ['Linux', 'Windows', 'Darwin'],
},
},
},
},
},
},
},
},


+ 1
- 1
test/test_metadata_sizes.py Voir le fichier

@@ -9,7 +9,7 @@ import pqclean

@pytest.mark.parametrize(
'implementation,test_dir,impl_path, init, destr',
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
[(impl, *helpers.isolate_test_files(impl.path(), 'test_printparams_'))
for impl in pqclean.Scheme.all_implementations()],
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
)


+ 2
- 2
test/test_nistkat.py Voir le fichier

@@ -20,8 +20,8 @@ import pqclean
@pytest.mark.parametrize(
'implementation,test_dir,impl_path, init, destr',
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
for impl in pqclean.Scheme.all_implementations()],
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
for impl in pqclean.Scheme.all_supported_implementations()],
ids=[str(impl) for impl in pqclean.Scheme.all_supported_implementations()],
)
@helpers.filtered_test
def test_nistkat(implementation, impl_path, test_dir, init, destr):


+ 2
- 2
test/test_symbol_namespace.py Voir le fichier

@@ -16,8 +16,8 @@ import pqclean
'implementation,test_dir,impl_path,init,destr',
[(impl,
*helpers.isolate_test_files(impl.path(), 'test_symbol_ns_'))
for impl in pqclean.Scheme.all_implementations()],
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
for impl in pqclean.Scheme.all_supported_implementations()],
ids=[str(impl) for impl in pqclean.Scheme.all_supported_implementations()],
)
@helpers.filtered_test
def test_symbol_namespaces(implementation, impl_path, test_dir, init, destr):


+ 3
- 0
test/test_testvectors.py Voir le fichier

@@ -5,6 +5,7 @@ the one provided in the META file for every scheme/implementation.

import hashlib
import os
import unittest

import pytest

@@ -22,6 +23,8 @@ import pqclean
)
@helpers.filtered_test
def test_testvectors(implementation, impl_path, test_dir, init, destr):
if not implementation.supported_on_current_platform():
raise unittest.SkipTest("Not supported on current platform")
init()
dest_dir = os.path.join(test_dir, 'bin')
helpers.make('testvectors',


+ 2
- 2
test/test_valgrind.py Voir le fichier

@@ -27,8 +27,8 @@ def valgrind_supports_exit_early():
@pytest.mark.parametrize(
'implementation,test_dir,impl_path, init, destr',
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
for impl in pqclean.Scheme.all_implementations()],
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
for impl in pqclean.Scheme.all_supported_implementations()],
ids=[str(impl) for impl in pqclean.Scheme.all_supported_implementations()],
)
@helpers.slow_test
@helpers.filtered_test


Chargement…
Annuler
Enregistrer