mirror of
https://github.com/henrydcase/pqc.git
synced 2024-11-22 23:48:58 +00:00
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
This commit is contained in:
parent
aa46b5239d
commit
2eaf382689
@ -2,3 +2,4 @@ PyYAML
|
|||||||
pytest
|
pytest
|
||||||
pytest-xdist
|
pytest-xdist
|
||||||
pycparser
|
pycparser
|
||||||
|
py-cpuinfo
|
||||||
|
@ -69,7 +69,7 @@ $(DEST_DIR)/testvectors_$(SCHEME)_$(IMPLEMENTATION): build-scheme crypto_$(TYPE)
|
|||||||
mkdir -p $(DEST_DIR)
|
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)
|
$(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)
|
mkdir -p $(DEST_DIR)
|
||||||
$(CC) $(CFLAGS) -DPQCLEAN_NAMESPACE=PQCLEAN_$(SCHEME_UPPERCASE)_$(IMPLEMENTATION_UPPERCASE) -I$(SCHEME_DIR) crypto_$(TYPE)/printparams.c -o $@
|
$(CC) $(CFLAGS) -DPQCLEAN_NAMESPACE=PQCLEAN_$(SCHEME_UPPERCASE)_$(IMPLEMENTATION_UPPERCASE) -I$(SCHEME_DIR) crypto_$(TYPE)/printparams.c -o $@
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
import platform
|
||||||
|
|
||||||
|
|
||||||
class Scheme:
|
class Scheme:
|
||||||
@ -37,6 +39,11 @@ class Scheme:
|
|||||||
implementations.extend(scheme.implementations)
|
implementations.extend(scheme.implementations)
|
||||||
return implementations
|
return implementations
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def all_supported_implementations():
|
||||||
|
return [impl for impl in Scheme.all_implementations()
|
||||||
|
if impl.supported_on_current_platform()]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def all_schemes_of_type(type: str) -> list:
|
def all_schemes_of_type(type: str) -> list:
|
||||||
schemes = []
|
schemes = []
|
||||||
@ -111,10 +118,57 @@ class Implementation:
|
|||||||
implementations.append(Implementation(scheme, d))
|
implementations.append(Implementation(scheme, d))
|
||||||
return implementations
|
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):
|
def namespace_prefix(self):
|
||||||
return '{}{}_'.format(self.scheme.namespace_prefix(),
|
return '{}{}_'.format(self.scheme.namespace_prefix(),
|
||||||
self.name.upper()).replace('-', '')
|
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):
|
def __str__(self):
|
||||||
return "{} implementation of {}".format(self.name, self.scheme.name)
|
return "{} implementation of {}".format(self.name, self.scheme.name)
|
||||||
|
|
||||||
|
@ -11,8 +11,8 @@ import pqclean
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'implementation,test_dir,impl_dir, init, destr',
|
'implementation,test_dir,impl_dir, init, destr',
|
||||||
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
|
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
|
||||||
for impl in pqclean.Scheme.all_implementations()],
|
for impl in pqclean.Scheme.all_supported_implementations()],
|
||||||
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
|
ids=[str(impl) for impl in pqclean.Scheme.all_supported_implementations()],
|
||||||
)
|
)
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
def test_compile_lib(implementation, test_dir, impl_dir, init, destr):
|
def test_compile_lib(implementation, test_dir, impl_dir, init, destr):
|
||||||
|
@ -11,8 +11,8 @@ import pqclean
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'implementation,test_dir,impl_path, init, destr',
|
'implementation,test_dir,impl_path, init, destr',
|
||||||
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
|
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
|
||||||
for impl in pqclean.Scheme.all_implementations()],
|
for impl in pqclean.Scheme.all_supported_implementations()],
|
||||||
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
|
ids=[str(impl) for impl in pqclean.Scheme.all_supported_implementations()],
|
||||||
)
|
)
|
||||||
@helpers.skip_windows()
|
@helpers.skip_windows()
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
|
@ -16,8 +16,8 @@ import pqclean
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'implementation,test_dir,impl_path, init, destr',
|
'implementation,test_dir,impl_path, init, destr',
|
||||||
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
|
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
|
||||||
for impl in pqclean.Scheme.all_implementations()],
|
for impl in pqclean.Scheme.all_supported_implementations()],
|
||||||
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
|
ids=[str(impl) for impl in pqclean.Scheme.all_supported_implementations()],
|
||||||
)
|
)
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
def test_functest(implementation, impl_path, test_dir,
|
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',
|
'implementation,test_dir,impl_path, init, destr',
|
||||||
[(impl,
|
[(impl,
|
||||||
*helpers.isolate_test_files(impl.path(), 'test_functest_sanitizers_'))
|
*helpers.isolate_test_files(impl.path(), 'test_functest_sanitizers_'))
|
||||||
for impl in pqclean.Scheme.all_implementations()],
|
for impl in pqclean.Scheme.all_supported_implementations()],
|
||||||
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
|
ids=[str(impl) for impl in pqclean.Scheme.all_supported_implementations()],
|
||||||
)
|
)
|
||||||
@helpers.skip_windows()
|
@helpers.skip_windows()
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
|
@ -13,7 +13,7 @@ additional_flags = [] #['-fix-errors']
|
|||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'implementation',
|
'implementation',
|
||||||
pqclean.Scheme.all_implementations(),
|
pqclean.Scheme.all_supported_implementations(),
|
||||||
ids=str,
|
ids=str,
|
||||||
)
|
)
|
||||||
@helpers.skip_windows()
|
@helpers.skip_windows()
|
||||||
|
@ -17,8 +17,8 @@ import pqclean
|
|||||||
'implementation,test_dir,impl_path, init, destr',
|
'implementation,test_dir,impl_path, init, destr',
|
||||||
[(impl,
|
[(impl,
|
||||||
*helpers.isolate_test_files(impl.path(), 'test_makefile_deps_'))
|
*helpers.isolate_test_files(impl.path(), 'test_makefile_deps_'))
|
||||||
for impl in pqclean.Scheme.all_implementations()],
|
for impl in pqclean.Scheme.all_supported_implementations()],
|
||||||
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
|
ids=[str(impl) for impl in pqclean.Scheme.all_supported_implementations()],
|
||||||
)
|
)
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
def test_makefile_dependencies(implementation, impl_path, test_dir,
|
def test_makefile_dependencies(implementation, impl_path, test_dir,
|
||||||
|
@ -17,10 +17,23 @@ import pqclean
|
|||||||
ids=str,
|
ids=str,
|
||||||
)
|
)
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
def test_makefiles_present(implementation):
|
def test_makefile_present(implementation):
|
||||||
p1 = os.path.join(implementation.path(), 'Makefile')
|
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')
|
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__':
|
if __name__ == '__main__':
|
||||||
|
@ -61,6 +61,31 @@ EXPECTED_FIELDS = {
|
|||||||
'spec': {
|
'spec': {
|
||||||
'name': {'type': str},
|
'name': {'type': str},
|
||||||
'version': {'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'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -9,7 +9,7 @@ import pqclean
|
|||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'implementation,test_dir,impl_path, init, destr',
|
'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()],
|
for impl in pqclean.Scheme.all_implementations()],
|
||||||
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
|
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
|
||||||
)
|
)
|
||||||
|
@ -20,8 +20,8 @@ import pqclean
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'implementation,test_dir,impl_path, init, destr',
|
'implementation,test_dir,impl_path, init, destr',
|
||||||
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
|
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
|
||||||
for impl in pqclean.Scheme.all_implementations()],
|
for impl in pqclean.Scheme.all_supported_implementations()],
|
||||||
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
|
ids=[str(impl) for impl in pqclean.Scheme.all_supported_implementations()],
|
||||||
)
|
)
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
def test_nistkat(implementation, impl_path, test_dir, init, destr):
|
def test_nistkat(implementation, impl_path, test_dir, init, destr):
|
||||||
|
@ -16,8 +16,8 @@ import pqclean
|
|||||||
'implementation,test_dir,impl_path,init,destr',
|
'implementation,test_dir,impl_path,init,destr',
|
||||||
[(impl,
|
[(impl,
|
||||||
*helpers.isolate_test_files(impl.path(), 'test_symbol_ns_'))
|
*helpers.isolate_test_files(impl.path(), 'test_symbol_ns_'))
|
||||||
for impl in pqclean.Scheme.all_implementations()],
|
for impl in pqclean.Scheme.all_supported_implementations()],
|
||||||
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
|
ids=[str(impl) for impl in pqclean.Scheme.all_supported_implementations()],
|
||||||
)
|
)
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
def test_symbol_namespaces(implementation, impl_path, test_dir, init, destr):
|
def test_symbol_namespaces(implementation, impl_path, test_dir, init, destr):
|
||||||
|
@ -5,6 +5,7 @@ the one provided in the META file for every scheme/implementation.
|
|||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import os
|
import os
|
||||||
|
import unittest
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@ -22,6 +23,8 @@ import pqclean
|
|||||||
)
|
)
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
def test_testvectors(implementation, impl_path, test_dir, init, destr):
|
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()
|
init()
|
||||||
dest_dir = os.path.join(test_dir, 'bin')
|
dest_dir = os.path.join(test_dir, 'bin')
|
||||||
helpers.make('testvectors',
|
helpers.make('testvectors',
|
||||||
|
@ -27,8 +27,8 @@ def valgrind_supports_exit_early():
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'implementation,test_dir,impl_path, init, destr',
|
'implementation,test_dir,impl_path, init, destr',
|
||||||
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
|
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
|
||||||
for impl in pqclean.Scheme.all_implementations()],
|
for impl in pqclean.Scheme.all_supported_implementations()],
|
||||||
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
|
ids=[str(impl) for impl in pqclean.Scheme.all_supported_implementations()],
|
||||||
)
|
)
|
||||||
@helpers.slow_test
|
@helpers.slow_test
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
|
Loading…
Reference in New Issue
Block a user