mirror of
https://github.com/henrydcase/pqc.git
synced 2024-11-26 01:11:25 +00:00
Parallel tests (#206)
* Do tests with pytest to run them in parallel * attempt to handle merge commits better for PR test path Similar to how we solved this for travis * Clean up imports * don't run valgrind if not specified slow_test * Fix functest after initializer rename * upload tests results as junit * Upload test-common files since #200 got merged * Catch test results upload failure
This commit is contained in:
parent
133a38b890
commit
78a65d6ec9
@ -22,7 +22,8 @@ version: 2.1
|
|||||||
export CC=${CC} &&
|
export CC=${CC} &&
|
||||||
pip3 install -r requirements.txt &&
|
pip3 install -r requirements.txt &&
|
||||||
mkdir test-results &&
|
mkdir test-results &&
|
||||||
cd test && python3 -m nose --rednose --verbose --with-xunit --xunit-file=../test-results/nosetests.xml"
|
cd test && python3 -m pytest --verbose --junitxml=test-results/pytest/results.xml --numprocesses=auto"
|
||||||
|
no_output_timeout: 2h
|
||||||
- store_test_results:
|
- store_test_results:
|
||||||
path: test-results
|
path: test-results
|
||||||
|
|
||||||
@ -42,7 +43,8 @@ version: 2.1
|
|||||||
pip3 install -r requirements.txt
|
pip3 install -r requirements.txt
|
||||||
mkdir test-results
|
mkdir test-results
|
||||||
cd test
|
cd test
|
||||||
python3 -m nose --rednose --verbose --with-xunit --xunit-file=../test-results/nosetests.xml
|
python3 -m pytest --verbose --junitxml=test-results/pytest/results.xml --numprocesses=auto
|
||||||
|
no_output_timeout: 2h
|
||||||
- store_test_results:
|
- store_test_results:
|
||||||
path: test-results
|
path: test-results
|
||||||
|
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -10,3 +10,4 @@ bin/
|
|||||||
*.obj
|
*.obj
|
||||||
|
|
||||||
__pycache__
|
__pycache__
|
||||||
|
testcases/
|
||||||
|
@ -16,7 +16,7 @@ matrix:
|
|||||||
- git reset --hard $COMMIT
|
- git reset --hard $COMMIT
|
||||||
script:
|
script:
|
||||||
# Use travis-wait to allow slower tests to run
|
# Use travis-wait to allow slower tests to run
|
||||||
- "cd test && travis_wait 60 python3 -m nose --rednose --verbose"
|
- "cd test && travis_wait 60 python3 -m pytest --numprocesses=auto"
|
||||||
env:
|
env:
|
||||||
PQCLEAN_ONLY_DIFF: 1
|
PQCLEAN_ONLY_DIFF: 1
|
||||||
PQCLEAN_SKIP_SCHEMES: sphincs-haraka-128f-robust,sphincs-haraka-192s-robust,sphincs-sha256-128f-robust,sphincs-sha256-192s-robust,sphincs-shake256-128f-robust,sphincs-shake256-192s-robust,sphincs-haraka-128f-simple,sphincs-haraka-192s-simple,sphincs-sha256-128f-simple,sphincs-sha256-192s-simple,sphincs-shake256-128f-simple,sphincs-shake256-192s-simple,sphincs-haraka-128s-robust,sphincs-haraka-256f-robust,sphincs-sha256-128s-robust,sphincs-sha256-256f-robust,sphincs-shake256-128s-robust,sphincs-shake256-256f-robust,sphincs-haraka-128s-simple,sphincs-haraka-256f-simple,sphincs-sha256-128s-simple,sphincs-sha256-256f-simple,sphincs-shake256-128s-simple,sphincs-shake256-256f-simple,sphincs-haraka-192f-robust,sphincs-haraka-256s-robust,sphincs-sha256-192f-robust,sphincs-sha256-256s-robust,sphincs-shake256-192f-robust,sphincs-shake256-256s-robust,sphincs-haraka-192f-simple,sphincs-haraka-256s-simple,sphincs-sha256-192f-simple,sphincs-sha256-256s-simple,sphincs-shake256-192f-simple,sphincs-shake256-256s-simple
|
PQCLEAN_SKIP_SCHEMES: sphincs-haraka-128f-robust,sphincs-haraka-192s-robust,sphincs-sha256-128f-robust,sphincs-sha256-192s-robust,sphincs-shake256-128f-robust,sphincs-shake256-192s-robust,sphincs-haraka-128f-simple,sphincs-haraka-192s-simple,sphincs-sha256-128f-simple,sphincs-sha256-192s-simple,sphincs-shake256-128f-simple,sphincs-shake256-192s-simple,sphincs-haraka-128s-robust,sphincs-haraka-256f-robust,sphincs-sha256-128s-robust,sphincs-sha256-256f-robust,sphincs-shake256-128s-robust,sphincs-shake256-256f-robust,sphincs-haraka-128s-simple,sphincs-haraka-256f-simple,sphincs-sha256-128s-simple,sphincs-sha256-256f-simple,sphincs-shake256-128s-simple,sphincs-shake256-256f-simple,sphincs-haraka-192f-robust,sphincs-haraka-256s-robust,sphincs-sha256-192f-robust,sphincs-sha256-256s-robust,sphincs-shake256-192f-robust,sphincs-shake256-256s-robust,sphincs-haraka-192f-simple,sphincs-haraka-256s-simple,sphincs-sha256-192f-simple,sphincs-sha256-256s-simple,sphincs-shake256-192f-simple,sphincs-shake256-256s-simple
|
||||||
@ -49,7 +49,7 @@ matrix:
|
|||||||
- gcc --version
|
- gcc --version
|
||||||
script:
|
script:
|
||||||
# Use travis-wait to allow slower tests to run
|
# Use travis-wait to allow slower tests to run
|
||||||
- "cd test && travis_wait 60 python3 -m nose --rednose --verbose"
|
- "cd test && travis_wait 60 python3 -m pytest --numprocesses=auto"
|
||||||
|
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
|
@ -146,7 +146,9 @@ While we run extensive automatic testing on [Circle CI][circleci-pqc] (Linux bui
|
|||||||
To do this, make sure the following is installed:
|
To do this, make sure the following is installed:
|
||||||
|
|
||||||
* Python 3.5+
|
* Python 3.5+
|
||||||
* `nosetests` or `nose2` (either for Python 3)
|
* `pytest` for python 3.
|
||||||
|
|
||||||
|
We also recommend installing ``pytest-xdist`` to allow running tests in parallel.
|
||||||
|
|
||||||
You will also need to make sure the submodules are initialized by running:
|
You will also need to make sure the submodules are initialized by running:
|
||||||
|
|
||||||
@ -154,8 +156,7 @@ You will also need to make sure the submodules are initialized by running:
|
|||||||
git submodule update --init
|
git submodule update --init
|
||||||
```
|
```
|
||||||
|
|
||||||
Run the Python-based tests by going into the `test` directory and running `nosetests -v` or `nose2 -B -v`, depending on what you installed.
|
Run the Python-based tests by going into the `test` directory and running `pytest -v` or (recommended) `pytest -n=auto` for parallel testing.
|
||||||
If you have the `rednose` plugin for `nosetests` installed, run `nosetests --rednose` to get colored output.
|
|
||||||
|
|
||||||
You may also run `python3 <testmodule>` where `<testmodule>` is any of the files starting with `test_` in the `test/` folder.
|
You may also run `python3 <testmodule>` where `<testmodule>` is any of the files starting with `test_` in the `test/` folder.
|
||||||
|
|
||||||
|
17
appveyor.yml
17
appveyor.yml
@ -25,12 +25,23 @@ init:
|
|||||||
build_script:
|
build_script:
|
||||||
- git config --replace-all remote.origin.fetch +refs/heads/*:refs/remotes/origin/*
|
- git config --replace-all remote.origin.fetch +refs/heads/*:refs/remotes/origin/*
|
||||||
- git fetch --all
|
- git fetch --all
|
||||||
- git checkout %APPVEYOR_REPO_BRANCH%
|
- sh: |
|
||||||
- git reset --hard %APPVEYOR_REPO_COMMIT%
|
COMMIT=$(git rev-parse HEAD)
|
||||||
|
git checkout $APPVEYOR_REPO_BRANCH
|
||||||
|
git reset --hard $COMMIT
|
||||||
- git diff --name-only origin/master
|
- git diff --name-only origin/master
|
||||||
- python -m pip install -r requirements.txt
|
- python -m pip install -r requirements.txt
|
||||||
- cd test
|
- cd test
|
||||||
# Download Astyle to local folder because putting it in PATH doesn't work
|
# Download Astyle to local folder because putting it in PATH doesn't work
|
||||||
- ps: Invoke-WebRequest -OutFile "astyle.exe" "https://rded.nl/pqclean/AStyle.exe"
|
- ps: Invoke-WebRequest -OutFile "astyle.exe" "https://rded.nl/pqclean/AStyle.exe"
|
||||||
# Run tests
|
# Run tests
|
||||||
- python -m nose -v --rednose
|
- python -m pytest --verbose --numprocesses=auto --junitxml=results.xml
|
||||||
|
|
||||||
|
on_finish:
|
||||||
|
- ps: |
|
||||||
|
Try {
|
||||||
|
$wc = New-Object 'System.Net.WebClient'
|
||||||
|
$wc.UploadFile("https://ci.appveyor.com/api/testresults/junit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\results.xml))
|
||||||
|
} Catch {
|
||||||
|
Write-Warning "$($error[0])"
|
||||||
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
PyYAML
|
PyYAML
|
||||||
nose
|
pytest
|
||||||
rednose
|
pytest-xdist
|
||||||
pycparser
|
pycparser
|
||||||
|
@ -1,13 +1,79 @@
|
|||||||
|
import atexit
|
||||||
import functools
|
import functools
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import subprocess
|
|
||||||
import unittest
|
|
||||||
import shutil
|
import shutil
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import tempfile
|
||||||
|
import unittest
|
||||||
|
|
||||||
import pqclean
|
import pqclean
|
||||||
|
|
||||||
import logging
|
|
||||||
|
@atexit.register
|
||||||
|
def cleanup_testcases():
|
||||||
|
"""Clean up any remaining isolated test dirs"""
|
||||||
|
print("Cleaning up testcases directory",
|
||||||
|
file=sys.stderr)
|
||||||
|
for dir_ in TEST_TEMPDIRS:
|
||||||
|
shutil.rmtree(dir_, ignore_errors=True)
|
||||||
|
|
||||||
|
|
||||||
|
TEST_TEMPDIRS = []
|
||||||
|
|
||||||
|
|
||||||
|
def isolate_test_files(impl_path, test_prefix,
|
||||||
|
dir=os.path.join('..', 'testcases')):
|
||||||
|
"""Isolates the test files in a separate directory, to help parallelise.
|
||||||
|
|
||||||
|
Especially Windows is problematic and needs isolation of all test files:
|
||||||
|
its build process will create .obj files EVERYWHERE.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
os.mkdir(dir)
|
||||||
|
except FileExistsError:
|
||||||
|
pass
|
||||||
|
test_dir = tempfile.mkdtemp(prefix=test_prefix, dir=dir)
|
||||||
|
test_dir = os.path.abspath(test_dir)
|
||||||
|
TEST_TEMPDIRS.append(test_dir)
|
||||||
|
|
||||||
|
# Create layers in folder structure
|
||||||
|
nested_dir = os.path.join(test_dir, 'crypto_bla')
|
||||||
|
os.mkdir(nested_dir)
|
||||||
|
nested_dir = os.path.join(nested_dir, 'scheme')
|
||||||
|
os.mkdir(nested_dir)
|
||||||
|
|
||||||
|
# Create test dependencies structure
|
||||||
|
os.mkdir(os.path.join(test_dir, 'test'))
|
||||||
|
|
||||||
|
# the implementation will go here.
|
||||||
|
new_impl_dir = os.path.abspath(os.path.join(nested_dir, 'impl'))
|
||||||
|
|
||||||
|
def initializer():
|
||||||
|
"""Isolate the files to be tested"""
|
||||||
|
# Copy common files (randombytes.c, aes.c, ...)
|
||||||
|
shutil.copytree(
|
||||||
|
os.path.join('..', 'common'), os.path.join(test_dir, 'common'))
|
||||||
|
# Copy makefiles
|
||||||
|
shutil.copy(os.path.join('..', 'test', 'Makefile'),
|
||||||
|
os.path.join(test_dir, 'test', 'Makefile'))
|
||||||
|
shutil.copy(os.path.join('..', 'test', 'Makefile.Microsoft_nmake'),
|
||||||
|
os.path.join(test_dir, 'test', 'Makefile.Microsoft_nmake'))
|
||||||
|
# Copy directories with support files
|
||||||
|
for d in ['common', 'test_common', 'crypto_sign', 'crypto_kem']:
|
||||||
|
shutil.copytree(
|
||||||
|
os.path.join('..', 'test', d),
|
||||||
|
os.path.join(test_dir, 'test', d)
|
||||||
|
)
|
||||||
|
|
||||||
|
shutil.copytree(impl_path, new_impl_dir)
|
||||||
|
|
||||||
|
def destructor():
|
||||||
|
"""Clean up the isolated files"""
|
||||||
|
shutil.rmtree(test_dir)
|
||||||
|
|
||||||
|
return (test_dir, new_impl_dir, initializer, destructor)
|
||||||
|
|
||||||
|
|
||||||
def run_subprocess(command, working_dir='.', env=None, expected_returncode=0):
|
def run_subprocess(command, working_dir='.', env=None, expected_returncode=0):
|
||||||
@ -21,7 +87,7 @@ def run_subprocess(command, working_dir='.', env=None, expected_returncode=0):
|
|||||||
env = env_
|
env = env_
|
||||||
|
|
||||||
# Note we need to capture stdout/stderr from the subprocess,
|
# Note we need to capture stdout/stderr from the subprocess,
|
||||||
# then print it, which nose/unittest will then capture and
|
# then print it, which the unittest will then capture and
|
||||||
# buffer appropriately
|
# buffer appropriately
|
||||||
print(working_dir + " > " + " ".join(command))
|
print(working_dir + " > " + " ".join(command))
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
@ -116,7 +182,12 @@ def ensure_available(executable):
|
|||||||
raise AssertionError("{} not available on CI".format(executable))
|
raise AssertionError("{} not available on CI".format(executable))
|
||||||
|
|
||||||
|
|
||||||
def permit_test(testname, thing, *args, **kwargs):
|
def permit_test(testname, *args, **kwargs):
|
||||||
|
if len(args) == 0:
|
||||||
|
thing = list(kwargs.values())[0]
|
||||||
|
else:
|
||||||
|
thing = args[0]
|
||||||
|
|
||||||
if 'PQCLEAN_ONLY_TESTS' in os.environ:
|
if 'PQCLEAN_ONLY_TESTS' in os.environ:
|
||||||
if not(testname.lower() in os.environ['PQCLEAN_ONLY_TESTS'].lower().split(',')):
|
if not(testname.lower() in os.environ['PQCLEAN_ONLY_TESTS'].lower().split(',')):
|
||||||
return False
|
return False
|
||||||
@ -192,7 +263,7 @@ def permit_test(testname, thing, *args, **kwargs):
|
|||||||
|
|
||||||
|
|
||||||
def filtered_test(func):
|
def filtered_test(func):
|
||||||
funcname = func.__name__[len("check_"):]
|
funcname = func.__name__[len("test_"):]
|
||||||
|
|
||||||
@functools.wraps(func)
|
@functools.wraps(func)
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import os
|
|
||||||
import glob
|
import glob
|
||||||
|
import os
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
|
||||||
@ -31,9 +32,9 @@ class Scheme:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def all_implementations():
|
def all_implementations():
|
||||||
implementations = dict()
|
implementations = []
|
||||||
for scheme in Scheme.all_schemes().values():
|
for scheme in Scheme.all_schemes():
|
||||||
implementations.extend(scheme.all_implementations())
|
implementations.extend(scheme.implementations)
|
||||||
return implementations
|
return implementations
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -142,4 +143,4 @@ class Signature(Scheme):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def all_sigs():
|
def all_sigs():
|
||||||
return Scheme.all_schemes_of_type('sig')
|
return Scheme.all_schemes_of_type('sign')
|
||||||
|
3
test/pytest.ini
Normal file
3
test/pytest.ini
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[pytest]
|
||||||
|
norecursedirs = .git *
|
||||||
|
empty_parameter_set_mark = fail_at_collect
|
@ -1,24 +1,26 @@
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
import helpers
|
import helpers
|
||||||
import pqclean
|
import pqclean
|
||||||
|
|
||||||
|
pattern = re.compile(r'^\s*#include\s*"')
|
||||||
def test_api_h():
|
|
||||||
for scheme in pqclean.Scheme.all_schemes():
|
|
||||||
for implementation in scheme.implementations:
|
|
||||||
yield check_api_h, implementation
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'implementation',
|
||||||
|
pqclean.Scheme.all_implementations(),
|
||||||
|
ids=str,
|
||||||
|
)
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
def check_api_h(implementation: pqclean.Implementation):
|
def test_api_h(implementation: pqclean.Implementation):
|
||||||
apipath = os.path.join(implementation.path(), 'api.h')
|
apipath = os.path.join(implementation.path(), 'api.h')
|
||||||
errors = []
|
errors = []
|
||||||
p = re.compile(r'^\s*#include\s*"')
|
|
||||||
with open(apipath) as f:
|
with open(apipath) as f:
|
||||||
for i, line in enumerate(f):
|
for i, line in enumerate(f):
|
||||||
if p.match(line):
|
if pattern.match(line):
|
||||||
errors.append("\n at {}:{}".format(apipath, i+1))
|
errors.append("\n at {}:{}".format(apipath, i+1))
|
||||||
if errors:
|
if errors:
|
||||||
raise AssertionError(
|
raise AssertionError(
|
||||||
@ -26,10 +28,6 @@ def check_api_h(implementation: pqclean.Implementation):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == '__main__':
|
||||||
try:
|
import sys
|
||||||
import nose2
|
pytest.main(sys.argv)
|
||||||
nose2.main()
|
|
||||||
except ImportError:
|
|
||||||
import nose
|
|
||||||
nose.runmodule()
|
|
||||||
|
@ -4,20 +4,18 @@ Checks that the implementation does not make use of the `char` type.
|
|||||||
This is ambiguous; compilers can freely choose `signed` or `unsigned` char.
|
This is ambiguous; compilers can freely choose `signed` or `unsigned` char.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import helpers
|
||||||
import pqclean
|
import pqclean
|
||||||
import pycparser
|
import pycparser
|
||||||
import os
|
|
||||||
import helpers
|
|
||||||
|
|
||||||
|
|
||||||
def test_char():
|
def setup_module():
|
||||||
if not(os.path.exists(os.path.join('pycparser', '.git'))):
|
if not(os.path.exists(os.path.join('pycparser', '.git'))):
|
||||||
helpers.run_subprocess(
|
print("Please run `git submodule update --init`")
|
||||||
['git', 'submodule', 'update', '--init']
|
|
||||||
)
|
|
||||||
for scheme in pqclean.Scheme.all_schemes():
|
|
||||||
for implementation in scheme.implementations:
|
|
||||||
yield check_char, implementation
|
|
||||||
|
|
||||||
|
|
||||||
def walk_tree(ast):
|
def walk_tree(ast):
|
||||||
@ -29,9 +27,14 @@ def walk_tree(ast):
|
|||||||
yield from walk_tree(child) # recursively yield prohibited nodes
|
yield from walk_tree(child) # recursively yield prohibited nodes
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'implementation',
|
||||||
|
pqclean.Scheme.all_implementations(),
|
||||||
|
ids=str,
|
||||||
|
)
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
@helpers.skip_windows()
|
@helpers.skip_windows()
|
||||||
def check_char(implementation):
|
def test_char(implementation):
|
||||||
errors = []
|
errors = []
|
||||||
for fname in os.listdir(implementation.path()):
|
for fname in os.listdir(implementation.path()):
|
||||||
if not fname.endswith(".c"):
|
if not fname.endswith(".c"):
|
||||||
@ -63,10 +66,6 @@ def check_char(implementation):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
try:
|
import sys
|
||||||
import nose2
|
pytest.main(sys.argv)
|
||||||
nose2.main()
|
|
||||||
except ImportError:
|
|
||||||
import nose
|
|
||||||
nose.runmodule()
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
Runs functional tests for common crypto functions (e.g., fips202, sha2, aes).
|
Runs functional tests for common crypto functions (e.g., fips202, sha2, aes).
|
||||||
|
|
||||||
|
Doesn't currently need isolation for parallelisation
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@ -8,24 +10,23 @@ import re
|
|||||||
import helpers
|
import helpers
|
||||||
|
|
||||||
|
|
||||||
@helpers.skip_windows()
|
def pytest_generate_tests(metafunc):
|
||||||
def test_common():
|
argvalues = []
|
||||||
for d in os.listdir('test_common'):
|
for d in os.listdir('test_common'):
|
||||||
primitive = re.sub(r"\.c$", "", d)
|
primitive = re.sub(r"\.c$", "", d)
|
||||||
if helpers.permit_test('common', None):
|
argvalues.append(primitive)
|
||||||
yield check_common, primitive
|
metafunc.parametrize('primitive', argvalues)
|
||||||
|
|
||||||
|
|
||||||
def check_common(primitive):
|
@helpers.skip_windows()
|
||||||
|
@helpers.filtered_test
|
||||||
|
def test_common(primitive):
|
||||||
binname = os.path.join('..', 'bin', 'test_common_'+primitive)
|
binname = os.path.join('..', 'bin', 'test_common_'+primitive)
|
||||||
helpers.make(binname)
|
helpers.make(binname)
|
||||||
helpers.run_subprocess([binname])
|
helpers.run_subprocess([binname])
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
import pytest
|
||||||
import nose2
|
import sys
|
||||||
nose2.main()
|
pytest.main(sys.argv)
|
||||||
except ImportError:
|
|
||||||
import nose
|
|
||||||
nose.runmodule()
|
|
||||||
|
@ -2,27 +2,26 @@
|
|||||||
Checks that the archive library can be successfully built for every
|
Checks that the archive library can be successfully built for every
|
||||||
scheme/implementation.
|
scheme/implementation.
|
||||||
"""
|
"""
|
||||||
|
import pytest
|
||||||
|
|
||||||
import pqclean
|
|
||||||
import helpers
|
import helpers
|
||||||
|
import pqclean
|
||||||
|
|
||||||
|
|
||||||
def test_compile_lib():
|
@pytest.mark.parametrize(
|
||||||
for scheme in pqclean.Scheme.all_schemes():
|
'implementation,test_dir,impl_dir, init, destr',
|
||||||
for implementation in scheme.implementations:
|
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
|
||||||
yield check_compile_lib, implementation
|
for impl in pqclean.Scheme.all_implementations()],
|
||||||
|
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
|
||||||
|
)
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
def check_compile_lib(implementation):
|
def test_compile_lib(implementation, test_dir, impl_dir, init, destr):
|
||||||
helpers.make('clean', working_dir=implementation.path())
|
init()
|
||||||
helpers.make(working_dir=implementation.path())
|
helpers.make('clean', working_dir=impl_dir)
|
||||||
|
helpers.make(working_dir=impl_dir)
|
||||||
|
destr()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
import sys
|
||||||
import nose2
|
pytest.main(sys.argv)
|
||||||
nose2.main()
|
|
||||||
except ImportError:
|
|
||||||
import nose
|
|
||||||
nose.runmodule()
|
|
||||||
|
@ -3,24 +3,18 @@ Checks that files duplicated across schemes/implementations are consistent.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import pqclean
|
|
||||||
import helpers
|
|
||||||
import unittest
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
import helpers
|
||||||
def _skipped_test(*args, **kwargs):
|
import pqclean
|
||||||
raise unittest.SkipTest("Skipped consistency check")
|
|
||||||
|
|
||||||
|
|
||||||
def test_duplicate_consistency():
|
def pytest_generate_tests(metafunc):
|
||||||
|
ids = []
|
||||||
|
argvalues = []
|
||||||
for scheme in pqclean.Scheme.all_schemes():
|
for scheme in pqclean.Scheme.all_schemes():
|
||||||
for implementation in scheme.implementations:
|
for implementation in scheme.implementations:
|
||||||
if not helpers.permit_test('duplicate_consistency',
|
|
||||||
implementation):
|
|
||||||
yield _skipped_test, implementation
|
|
||||||
continue
|
|
||||||
|
|
||||||
if os.path.isfile(
|
if os.path.isfile(
|
||||||
os.path.join(
|
os.path.join(
|
||||||
'duplicate_consistency',
|
'duplicate_consistency',
|
||||||
@ -35,8 +29,14 @@ def test_duplicate_consistency():
|
|||||||
group['source']['scheme'],
|
group['source']['scheme'],
|
||||||
group['source']['implementation'])
|
group['source']['implementation'])
|
||||||
for file in group['files']:
|
for file in group['files']:
|
||||||
yield (check_duplicate_consistency, implementation,
|
argvalues.append((implementation, source, file))
|
||||||
source, file)
|
ids.append(
|
||||||
|
"{scheme.name}-{source.scheme.name}: {file}"
|
||||||
|
.format(scheme=scheme, source=source,
|
||||||
|
file=file))
|
||||||
|
metafunc.parametrize(('implementation', 'source', 'file'),
|
||||||
|
argvalues,
|
||||||
|
ids=ids)
|
||||||
|
|
||||||
|
|
||||||
def file_get_contents(filename):
|
def file_get_contents(filename):
|
||||||
@ -45,7 +45,8 @@ def file_get_contents(filename):
|
|||||||
|
|
||||||
|
|
||||||
@helpers.skip_windows()
|
@helpers.skip_windows()
|
||||||
def check_duplicate_consistency(implementation, source, file):
|
@helpers.filtered_test
|
||||||
|
def test_duplicate_consistency(implementation, source, file):
|
||||||
transformed_src = helpers.run_subprocess(
|
transformed_src = helpers.run_subprocess(
|
||||||
['sed', '-e', 's/{}/{}/g'.format(source.namespace_prefix(),
|
['sed', '-e', 's/{}/{}/g'.format(source.namespace_prefix(),
|
||||||
implementation.namespace_prefix()), os.path.join(source.path(), file)]
|
implementation.namespace_prefix()), os.path.join(source.path(), file)]
|
||||||
@ -57,9 +58,6 @@ def check_duplicate_consistency(implementation, source, file):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
import pytest
|
||||||
import nose2
|
import sys
|
||||||
nose2.main()
|
pytest.main(sys.argv)
|
||||||
except ImportError:
|
|
||||||
import nose
|
|
||||||
nose.runmodule()
|
|
||||||
|
@ -2,41 +2,42 @@
|
|||||||
Checks that no dynamic memory functions are used
|
Checks that no dynamic memory functions are used
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import pqclean
|
import pytest
|
||||||
|
|
||||||
import helpers
|
import helpers
|
||||||
|
import pqclean
|
||||||
|
|
||||||
|
|
||||||
def test_dynamic_memory():
|
@pytest.mark.parametrize(
|
||||||
for scheme in pqclean.Scheme.all_schemes():
|
'implementation,test_dir,impl_path, init, destr',
|
||||||
for implementation in scheme.implementations:
|
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
|
||||||
# Keep this loop outside, to allow multiple assertions
|
for impl in pqclean.Scheme.all_implementations()],
|
||||||
for function in ['malloc', 'free', 'realloc', 'calloc']:
|
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
|
||||||
yield (check_dynamic_memory, implementation, function)
|
)
|
||||||
|
|
||||||
|
|
||||||
@helpers.filtered_test
|
|
||||||
@helpers.skip_windows()
|
@helpers.skip_windows()
|
||||||
def check_dynamic_memory(implementation, function):
|
@helpers.filtered_test
|
||||||
|
def test_dynamic_memory(implementation, test_dir, impl_path, init, destr):
|
||||||
|
init()
|
||||||
# 'make' will take care of not rebuilding existing library files
|
# 'make' will take care of not rebuilding existing library files
|
||||||
helpers.make(working_dir=implementation.path())
|
helpers.make(working_dir=impl_path)
|
||||||
scheme_name = implementation.scheme.name
|
scheme_name = implementation.scheme.name
|
||||||
out = helpers.run_subprocess(
|
out = helpers.run_subprocess(
|
||||||
['nm', '-g', 'lib{}_{}.a'.format(scheme_name, implementation.name)],
|
['nm', '-g', 'lib{}_{}.a'.format(scheme_name, implementation.name)],
|
||||||
implementation.path()
|
impl_path,
|
||||||
)
|
)
|
||||||
|
|
||||||
lines = out.strip().split("\n")
|
lines = out.strip().split("\n")
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
|
for function in ['malloc', 'free', 'realloc', 'calloc']:
|
||||||
if line.endswith('U {}'.format(function)):
|
if line.endswith('U {}'.format(function)):
|
||||||
raise AssertionError(
|
raise AssertionError(
|
||||||
"Illegal use of dynamic memory function '{}'".format(function))
|
"Illegal use of dynamic memory function "
|
||||||
|
"'{function}'".format(function=function))
|
||||||
|
|
||||||
|
destr()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
import sys
|
||||||
import nose2
|
pytest.main(sys.argv)
|
||||||
nose2.main()
|
|
||||||
except ImportError:
|
|
||||||
import nose
|
|
||||||
nose.runmodule()
|
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
import helpers
|
import helpers
|
||||||
import pqclean
|
import pqclean
|
||||||
|
|
||||||
|
|
||||||
def test_formatting():
|
@pytest.mark.parametrize(
|
||||||
for scheme in pqclean.Scheme.all_schemes():
|
'implementation',
|
||||||
for implementation in scheme.implementations:
|
pqclean.Scheme.all_implementations(),
|
||||||
yield check_format, implementation
|
ids=str,
|
||||||
|
)
|
||||||
|
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
def check_format(implementation: pqclean.Implementation):
|
def test_format(implementation: pqclean.Implementation):
|
||||||
helpers.ensure_available('astyle')
|
helpers.ensure_available('astyle')
|
||||||
cfiles = implementation.cfiles()
|
cfiles = implementation.cfiles()
|
||||||
hfiles = implementation.hfiles()
|
hfiles = implementation.hfiles()
|
||||||
@ -19,13 +20,9 @@ def check_format(implementation: pqclean.Implementation):
|
|||||||
'--options=../.astylerc',
|
'--options=../.astylerc',
|
||||||
*cfiles,
|
*cfiles,
|
||||||
*hfiles])
|
*hfiles])
|
||||||
assert(not('Formatted' in result))
|
assert 'Formatted' not in result
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == '__main__':
|
||||||
try:
|
import sys
|
||||||
import nose2
|
pytest.main(sys.argv)
|
||||||
nose2.main()
|
|
||||||
except ImportError:
|
|
||||||
import nose
|
|
||||||
nose.runmodule()
|
|
||||||
|
@ -7,85 +7,85 @@ import os
|
|||||||
import platform
|
import platform
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import pqclean
|
import pytest
|
||||||
|
|
||||||
import helpers
|
import helpers
|
||||||
|
import pqclean
|
||||||
|
|
||||||
|
|
||||||
def test_functest():
|
@pytest.mark.parametrize(
|
||||||
for scheme in pqclean.Scheme.all_schemes():
|
'implementation,test_dir,impl_path, init, destr',
|
||||||
for implementation in scheme.implementations:
|
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
|
||||||
yield check_functest, implementation
|
for impl in pqclean.Scheme.all_implementations()],
|
||||||
|
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
|
||||||
|
)
|
||||||
def test_functest_sanitizers():
|
|
||||||
for scheme in pqclean.Scheme.all_schemes():
|
|
||||||
for implementation in scheme.implementations:
|
|
||||||
yield check_functest_sanitizers, implementation
|
|
||||||
|
|
||||||
|
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
def check_functest(implementation):
|
def test_functest(implementation, impl_path, test_dir,
|
||||||
|
init, destr):
|
||||||
|
init()
|
||||||
|
dest_dir = os.path.join(test_dir, 'bin')
|
||||||
helpers.make('functest',
|
helpers.make('functest',
|
||||||
TYPE=implementation.scheme.type,
|
TYPE=implementation.scheme.type,
|
||||||
SCHEME=implementation.scheme.name,
|
SCHEME=implementation.scheme.name,
|
||||||
IMPLEMENTATION=implementation.name,
|
IMPLEMENTATION=implementation.name,
|
||||||
working_dir=os.path.join('..', 'test'))
|
SCHEME_DIR=impl_path,
|
||||||
|
DEST_DIR=dest_dir,
|
||||||
|
working_dir=os.path.join(test_dir, 'test'))
|
||||||
helpers.run_subprocess(
|
helpers.run_subprocess(
|
||||||
[os.path.join('..', 'bin', 'functest_{}_{}{}'.format(
|
[os.path.join(dest_dir, 'functest_{}_{}{}'.format(
|
||||||
implementation.scheme.name,
|
implementation.scheme.name,
|
||||||
implementation.name,
|
implementation.name,
|
||||||
'.exe' if os.name == 'nt' else ''
|
'.exe' if os.name == 'nt' else ''
|
||||||
))],
|
))],
|
||||||
os.path.join('..', 'bin'),
|
|
||||||
)
|
)
|
||||||
|
destr()
|
||||||
|
|
||||||
|
|
||||||
@helpers.filtered_test
|
@pytest.mark.parametrize(
|
||||||
|
'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()],
|
||||||
|
)
|
||||||
@helpers.skip_windows()
|
@helpers.skip_windows()
|
||||||
|
@helpers.filtered_test
|
||||||
@helpers.slow_test
|
@helpers.slow_test
|
||||||
def check_functest_sanitizers(implementation):
|
def test_functest_sanitizers(implementation, impl_path, test_dir,
|
||||||
|
init, destr):
|
||||||
|
dest_dir = os.path.join(test_dir, 'bin')
|
||||||
env = None
|
env = None
|
||||||
if platform.machine() == 'ppc' and os.environ.get('CC', 'gcc') == 'clang':
|
if platform.machine() == 'ppc' and os.environ.get('CC', 'gcc') == 'clang':
|
||||||
raise unittest.SkipTest("Clang does not support ASAN on ppc")
|
raise unittest.SkipTest("Clang does not support ASAN on ppc")
|
||||||
elif platform.machine() in ['armv7l', 'aarch64']:
|
elif platform.machine() in ['armv7l', 'aarch64']:
|
||||||
env = {'ASAN_OPTIONS': 'detect_leaks=0'}
|
env = {'ASAN_OPTIONS': 'detect_leaks=0'}
|
||||||
elif platform.system() == 'Darwin':
|
elif platform.system() == 'Darwin':
|
||||||
raise unittest.SkipTest('valgrind is not reliable on OSX')
|
raise unittest.SkipTest('ASAN is not reliable on OSX')
|
||||||
else:
|
else:
|
||||||
print("Supported platform: {}".format(platform.machine()))
|
print("Supported platform: {}".format(platform.machine()))
|
||||||
|
|
||||||
|
init()
|
||||||
|
|
||||||
helpers.make('clean-scheme', 'functest',
|
helpers.make('clean-scheme', 'functest',
|
||||||
TYPE=implementation.scheme.type,
|
TYPE=implementation.scheme.type,
|
||||||
SCHEME=implementation.scheme.name,
|
SCHEME=implementation.scheme.name,
|
||||||
IMPLEMENTATION=implementation.name,
|
IMPLEMENTATION=implementation.name,
|
||||||
EXTRAFLAGS='-g -fsanitize=address,undefined',
|
EXTRAFLAGS='-g -fsanitize=address,undefined',
|
||||||
working_dir=os.path.join('..', 'test'),
|
SCHEME_DIR=impl_path,
|
||||||
|
DEST_DIR=dest_dir,
|
||||||
|
working_dir=os.path.join(test_dir, 'test'),
|
||||||
env=env)
|
env=env)
|
||||||
try:
|
|
||||||
helpers.run_subprocess(
|
helpers.run_subprocess(
|
||||||
[os.path.join('..', 'bin', 'functest_{}_{}{}'.format(
|
[os.path.join(dest_dir, 'functest_{}_{}{}'.format(
|
||||||
implementation.scheme.name,
|
implementation.scheme.name,
|
||||||
implementation.name,
|
implementation.name,
|
||||||
'.exe' if os.name == 'nt' else ''
|
'.exe' if os.name == 'nt' else ''
|
||||||
))],
|
))],
|
||||||
os.path.join('..', 'bin'),
|
|
||||||
env=env,
|
env=env,
|
||||||
)
|
)
|
||||||
except AssertionError as e:
|
destr()
|
||||||
raise e
|
|
||||||
finally:
|
|
||||||
# Remove files with ASAN library compiled in
|
|
||||||
helpers.make('clean-scheme',
|
|
||||||
TYPE=implementation.scheme.type,
|
|
||||||
SCHEME=implementation.scheme.name,
|
|
||||||
IMPLEMENTATION=implementation.name,
|
|
||||||
working_dir=os.path.join('..', 'test'))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
import sys
|
||||||
import nose2
|
pytest.main(sys.argv)
|
||||||
nose2.main()
|
|
||||||
except ImportError:
|
|
||||||
import nose
|
|
||||||
nose.runmodule()
|
|
||||||
|
@ -4,27 +4,25 @@ implementation of the specified scheme.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import pqclean
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
import helpers
|
import helpers
|
||||||
|
import pqclean
|
||||||
|
|
||||||
|
|
||||||
def test_license():
|
@pytest.mark.parametrize(
|
||||||
for scheme in pqclean.Scheme.all_schemes():
|
'implementation',
|
||||||
for implementation in scheme.implementations:
|
pqclean.Scheme.all_implementations(),
|
||||||
yield check_license, implementation
|
ids=str,
|
||||||
|
)
|
||||||
|
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
def check_license(implementation):
|
def test_license(implementation):
|
||||||
p1 = os.path.join(implementation.path(), 'LICENSE')
|
p1 = os.path.join(implementation.path(), 'LICENSE')
|
||||||
p2 = os.path.join(implementation.path(), 'LICENSE.txt')
|
p2 = os.path.join(implementation.path(), 'LICENSE.txt')
|
||||||
assert(os.path.isfile(p1) or os.path.isfile(p2))
|
assert(os.path.isfile(p1) or os.path.isfile(p2))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
import sys
|
||||||
import nose2
|
pytest.main(sys.argv)
|
||||||
nose2.main()
|
|
||||||
except ImportError:
|
|
||||||
import nose
|
|
||||||
nose.runmodule()
|
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
import os
|
import os
|
||||||
from glob import glob
|
|
||||||
import sys
|
|
||||||
import unittest
|
import unittest
|
||||||
|
from glob import glob
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
import pqclean
|
|
||||||
import helpers
|
import helpers
|
||||||
|
import pqclean
|
||||||
|
|
||||||
additional_flags = []
|
additional_flags = []
|
||||||
|
|
||||||
|
|
||||||
def test_clang_tidy():
|
@pytest.mark.parametrize(
|
||||||
for scheme in pqclean.Scheme.all_schemes():
|
'implementation',
|
||||||
for implementation in scheme.implementations:
|
pqclean.Scheme.all_implementations(),
|
||||||
yield check_tidy, implementation
|
ids=str,
|
||||||
|
)
|
||||||
|
|
||||||
@helpers.filtered_test
|
|
||||||
@helpers.skip_windows()
|
@helpers.skip_windows()
|
||||||
def check_tidy(implementation: pqclean.Implementation):
|
@helpers.filtered_test
|
||||||
|
def test_clang_tidy(implementation: pqclean.Implementation):
|
||||||
helpers.ensure_available('clang-tidy')
|
helpers.ensure_available('clang-tidy')
|
||||||
cfiles = implementation.cfiles()
|
cfiles = implementation.cfiles()
|
||||||
common_files = glob(os.path.join('..', 'common', '*.c'))
|
common_files = glob(os.path.join('..', 'common', '*.c'))
|
||||||
@ -37,18 +37,15 @@ def check_tidy(implementation: pqclean.Implementation):
|
|||||||
# Detect and gracefully avoid segfaults
|
# Detect and gracefully avoid segfaults
|
||||||
if returncode == -11:
|
if returncode == -11:
|
||||||
raise unittest.SkipTest("clang-tidy segfaulted")
|
raise unittest.SkipTest("clang-tidy segfaulted")
|
||||||
else:
|
|
||||||
assert returncode == 0, "Clang-tidy returned %d" % returncode
|
assert returncode == 0, "Clang-tidy returned %d" % returncode
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
# allow a user to specify --fix-errors, to immediately fix errors
|
# allow a user to specify --fix-errors, to immediately fix errors
|
||||||
if len(sys.argv) >= 2 and sys.argv[1] == '-fix-errors':
|
if len(sys.argv) >= 2 and sys.argv[1] == '-fix-errors':
|
||||||
additional_flags = ['-fix-errors']
|
additional_flags = ['-fix-errors']
|
||||||
sys.argv = sys.argv[0:1] + sys.argv[2:]
|
del sys.argv[1]
|
||||||
try:
|
|
||||||
import nose2
|
pytest.main(sys.argv)
|
||||||
nose2.main()
|
|
||||||
except ImportError:
|
|
||||||
import nose
|
|
||||||
nose.runmodule()
|
|
||||||
|
@ -3,35 +3,36 @@ Checks that every .c and .h file in an implementation is present as a
|
|||||||
dependency of that scheme's Makefile.
|
dependency of that scheme's Makefile.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
import pqclean
|
|
||||||
import helpers
|
|
||||||
import glob
|
|
||||||
import datetime
|
import datetime
|
||||||
import unittest
|
import glob
|
||||||
|
import os
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import helpers
|
||||||
|
import pqclean
|
||||||
|
|
||||||
|
|
||||||
def _skipped_test(*args, **kwargs):
|
@pytest.mark.parametrize(
|
||||||
"""Used to indicate skipped tests"""
|
'implementation,test_dir,impl_path, init, destr',
|
||||||
raise unittest.SkipTest("Skipped makefile dependencies test")
|
[(impl,
|
||||||
|
*helpers.isolate_test_files(impl.path(), 'test_makefile_deps_'))
|
||||||
|
for impl in pqclean.Scheme.all_implementations()],
|
||||||
def test_makefile_dependencies():
|
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
|
||||||
for scheme in pqclean.Scheme.all_schemes():
|
)
|
||||||
for implementation in scheme.implementations:
|
@helpers.filtered_test
|
||||||
if not helpers.permit_test(
|
def test_makefile_dependencies(implementation, impl_path, test_dir,
|
||||||
'makefile_dependencies', implementation):
|
init, destr):
|
||||||
yield _skipped_test, implementation
|
init()
|
||||||
continue
|
|
||||||
|
|
||||||
# initial build - want to have *all* files in place at beginning
|
# initial build - want to have *all* files in place at beginning
|
||||||
helpers.make('clean', working_dir=implementation.path())
|
helpers.make('clean', working_dir=impl_path)
|
||||||
helpers.make(working_dir=implementation.path())
|
helpers.make(working_dir=impl_path)
|
||||||
# test case for each candidate file
|
# test case for each candidate file
|
||||||
cfiles = glob.glob(os.path.join(implementation.path(), '*.c'))
|
cfiles = glob.glob(os.path.join(impl_path, '*.c'))
|
||||||
hfiles = glob.glob(os.path.join(implementation.path(), '*.h'))
|
hfiles = glob.glob(os.path.join(impl_path, '*.h'))
|
||||||
for file in (cfiles + hfiles):
|
for file in (cfiles + hfiles):
|
||||||
yield (check_makefile_dependencies, implementation, file)
|
check_makefile_dependencies(implementation, impl_path, file)
|
||||||
|
destr()
|
||||||
|
|
||||||
|
|
||||||
def touch(time, *files):
|
def touch(time, *files):
|
||||||
@ -49,12 +50,14 @@ def make_check(path, expect_error=False):
|
|||||||
expected_returncode=expected_returncode)
|
expected_returncode=expected_returncode)
|
||||||
|
|
||||||
|
|
||||||
def check_makefile_dependencies(implementation, file):
|
def check_makefile_dependencies(implementation, impl_path, file):
|
||||||
cfiles = implementation.cfiles()
|
cfiles = glob.glob(os.path.join(impl_path, '*.c'))
|
||||||
hfiles = implementation.hfiles()
|
hfiles = glob.glob(os.path.join(impl_path, '*.h'))
|
||||||
ofiles = implementation.ofiles()
|
ofiles = glob.glob(
|
||||||
|
os.path.join(impl_path,
|
||||||
|
'*.o' if os.name != 'nt' else '*.obj'))
|
||||||
|
|
||||||
libfile = os.path.join(implementation.path(), implementation.libname())
|
libfile = os.path.join(impl_path, implementation.libname())
|
||||||
|
|
||||||
# modification time-based calculations is tricky on a sub-second basis
|
# modification time-based calculations is tricky on a sub-second basis
|
||||||
# so we reset all the modification times to a known and "sensible" order
|
# so we reset all the modification times to a known and "sensible" order
|
||||||
@ -68,19 +71,15 @@ def check_makefile_dependencies(implementation, file):
|
|||||||
touch(ago5, libfile)
|
touch(ago5, libfile)
|
||||||
|
|
||||||
# Sanity check: the scheme is up to date
|
# Sanity check: the scheme is up to date
|
||||||
make_check(implementation.path())
|
make_check(impl_path)
|
||||||
|
|
||||||
# touch the candidate .c / .h file
|
# touch the candidate .c / .h file
|
||||||
touch(now, file)
|
touch(now, file)
|
||||||
|
|
||||||
# check if it needs to be rebuilt using make -q
|
# check if it needs to be rebuilt using make -q
|
||||||
make_check(implementation.path(), expect_error=True)
|
make_check(impl_path, expect_error=True)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
import sys
|
||||||
import nose2
|
pytest.main(sys.argv)
|
||||||
nose2.main()
|
|
||||||
except ImportError:
|
|
||||||
import nose
|
|
||||||
nose.runmodule()
|
|
||||||
|
@ -4,27 +4,25 @@ implementation of the specified scheme.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import pqclean
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
import helpers
|
import helpers
|
||||||
|
import pqclean
|
||||||
|
|
||||||
|
|
||||||
def test_makefiles():
|
@pytest.mark.parametrize(
|
||||||
for scheme in pqclean.Scheme.all_schemes():
|
'implementation',
|
||||||
for implementation in scheme.implementations:
|
pqclean.Scheme.all_implementations(),
|
||||||
yield check_makefiles, implementation
|
ids=str,
|
||||||
|
)
|
||||||
|
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
def check_makefiles(implementation):
|
def test_makefiles_present(implementation):
|
||||||
p1 = os.path.join(implementation.path(), 'Makefile')
|
p1 = os.path.join(implementation.path(), 'Makefile')
|
||||||
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))
|
assert(os.path.isfile(p1) and os.path.isfile(p2))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
import sys
|
||||||
import nose2
|
pytest.main(sys.argv)
|
||||||
nose2.main()
|
|
||||||
except ImportError:
|
|
||||||
import nose
|
|
||||||
nose.runmodule()
|
|
||||||
|
@ -3,18 +3,21 @@ Verify the metadata specified in the META.yml files.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import helpers
|
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import helpers
|
||||||
import pqclean
|
import pqclean
|
||||||
|
|
||||||
|
|
||||||
def test_metadata():
|
@pytest.mark.parametrize(
|
||||||
for scheme in pqclean.Scheme.all_schemes():
|
'scheme',
|
||||||
yield check_metadata, scheme
|
pqclean.Scheme.all_schemes(),
|
||||||
|
ids=str,
|
||||||
|
)
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
def check_metadata(scheme):
|
def test_metadata(scheme):
|
||||||
metadata = scheme.metadata()
|
metadata = scheme.metadata()
|
||||||
|
|
||||||
specification = EXPECTED_FIELDS.items()
|
specification = EXPECTED_FIELDS.items()
|
||||||
@ -49,7 +52,8 @@ EXPECTED_FIELDS = {
|
|||||||
'length-secret-key': {'type': int, 'min': 1},
|
'length-secret-key': {'type': int, 'min': 1},
|
||||||
'nistkat-sha256': {'type': str, 'length': 64},
|
'nistkat-sha256': {'type': str, 'length': 64},
|
||||||
'principal-submitters': {'type': list, 'elements': {'type': str}},
|
'principal-submitters': {'type': list, 'elements': {'type': str}},
|
||||||
'auxiliary-submitters': {'type': list, 'elements': {'type': str}, 'optional' : True},
|
'auxiliary-submitters': {
|
||||||
|
'type': list, 'elements': {'type': str}, 'optional': True},
|
||||||
'implementations': {
|
'implementations': {
|
||||||
'type': list,
|
'type': list,
|
||||||
'elements': {
|
'elements': {
|
||||||
@ -63,7 +67,7 @@ EXPECTED_FIELDS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
KEM_FIELDS = {
|
KEM_FIELDS = {
|
||||||
'claimed-security' : {'type' : str, 'values' : ['IND-CPA', 'IND-CCA2'] },
|
'claimed-security': {'type': str, 'values': ['IND-CPA', 'IND-CCA2']},
|
||||||
'length-ciphertext': {'type': int, 'min': 1},
|
'length-ciphertext': {'type': int, 'min': 1},
|
||||||
'length-shared-secret': {'type': int, 'min': 1},
|
'length-shared-secret': {'type': int, 'min': 1},
|
||||||
}
|
}
|
||||||
@ -128,7 +132,6 @@ def check_element(field, element, props):
|
|||||||
raise ValueError("'{}' should be in {}"
|
raise ValueError("'{}' should be in {}"
|
||||||
.format(element, props['values']))
|
.format(element, props['values']))
|
||||||
|
|
||||||
|
|
||||||
if type_ == list: # recursively check the elements
|
if type_ == list: # recursively check the elements
|
||||||
for el in element:
|
for el in element:
|
||||||
check_element('element of {}'.format(field), el, props['elements'])
|
check_element('element of {}'.format(field), el, props['elements'])
|
||||||
@ -138,9 +141,5 @@ def check_element(field, element, props):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
import sys
|
||||||
import nose2
|
pytest.main(sys.argv)
|
||||||
nose2.main()
|
|
||||||
except ImportError:
|
|
||||||
import nose
|
|
||||||
nose.runmodule()
|
|
||||||
|
@ -1,25 +1,27 @@
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import pqclean
|
import pytest
|
||||||
|
|
||||||
import helpers
|
import helpers
|
||||||
|
import pqclean
|
||||||
|
|
||||||
|
|
||||||
def test_metadata_sizes():
|
@pytest.mark.parametrize(
|
||||||
for scheme in pqclean.Scheme.all_schemes():
|
'implementation,test_dir,impl_path, init, destr',
|
||||||
for implementation in scheme.implementations:
|
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
|
||||||
yield check_metadata_sizes, implementation
|
for impl in pqclean.Scheme.all_implementations()],
|
||||||
|
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
|
||||||
|
)
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
def check_metadata_sizes(implementation):
|
def test_metadata_sizes(implementation, impl_path, test_dir, init, destr):
|
||||||
|
init()
|
||||||
metadata = implementation.scheme.metadata()
|
metadata = implementation.scheme.metadata()
|
||||||
impl_meta = next((impl for impl in metadata['implementations']
|
|
||||||
if impl['name'] == implementation.name), None)
|
|
||||||
helpers.make('printparams',
|
helpers.make('printparams',
|
||||||
TYPE=implementation.scheme.type,
|
TYPE=implementation.scheme.type,
|
||||||
SCHEME=implementation.scheme.name,
|
SCHEME=implementation.scheme.name,
|
||||||
IMPLEMENTATION=implementation.name,
|
IMPLEMENTATION=implementation.name,
|
||||||
|
SCHEME_DIR=impl_path,
|
||||||
working_dir=os.path.join('..', 'test'))
|
working_dir=os.path.join('..', 'test'))
|
||||||
|
|
||||||
out = helpers.run_subprocess(
|
out = helpers.run_subprocess(
|
||||||
@ -42,12 +44,9 @@ def check_metadata_sizes(implementation):
|
|||||||
assert parsed['CRYPTO_BYTES'] == metadata['length-shared-secret']
|
assert parsed['CRYPTO_BYTES'] == metadata['length-shared-secret']
|
||||||
else:
|
else:
|
||||||
assert parsed['CRYPTO_BYTES'] == metadata['length-signature']
|
assert parsed['CRYPTO_BYTES'] == metadata['length-signature']
|
||||||
|
destr()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
import sys
|
||||||
import nose2
|
pytest.main(sys.argv)
|
||||||
nose2.main()
|
|
||||||
except ImportError:
|
|
||||||
import nose
|
|
||||||
nose.runmodule()
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
Checks that (hash of the) KATs (in NIST format) produced on this platform matches
|
Checks that (hash of the) KATs (in NIST format) produced on this platform match
|
||||||
the one provided in the META file for every scheme/implementation.
|
the one provided in the META file for every scheme/implementation.
|
||||||
|
|
||||||
Note that this only uses the first test case from the NIST-format KAT files.
|
Note that this only uses the first test case from the NIST-format KAT files.
|
||||||
@ -10,40 +10,42 @@ using the command:
|
|||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import os
|
import os
|
||||||
import pqclean
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
import helpers
|
import helpers
|
||||||
import unittest
|
import pqclean
|
||||||
|
|
||||||
|
|
||||||
def test_nistkat():
|
|
||||||
for scheme in pqclean.Scheme.all_schemes():
|
|
||||||
for implementation in scheme.implementations:
|
|
||||||
yield check_nistkat, implementation
|
|
||||||
|
|
||||||
|
|
||||||
|
@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()],
|
||||||
|
)
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
def check_nistkat(implementation):
|
def test_nistkat(implementation, impl_path, test_dir, init, destr):
|
||||||
|
init()
|
||||||
|
dest_path = os.path.join(test_dir, 'bin')
|
||||||
helpers.make('nistkat',
|
helpers.make('nistkat',
|
||||||
TYPE=implementation.scheme.type,
|
TYPE=implementation.scheme.type,
|
||||||
SCHEME=implementation.scheme.name,
|
SCHEME=implementation.scheme.name,
|
||||||
IMPLEMENTATION=implementation.name,
|
IMPLEMENTATION=implementation.name,
|
||||||
working_dir=os.path.join('..', 'test'))
|
SCHEME_DIR=impl_path,
|
||||||
|
DEST_DIR=dest_path,
|
||||||
|
working_dir=os.path.join(test_dir, 'test'))
|
||||||
out = helpers.run_subprocess(
|
out = helpers.run_subprocess(
|
||||||
[os.path.join('..', 'bin', 'nistkat_{}_{}{}'.format(
|
[os.path.join(dest_path, 'nistkat_{}_{}{}'.format(
|
||||||
implementation.scheme.name,
|
implementation.scheme.name,
|
||||||
implementation.name,
|
implementation.name,
|
||||||
'.exe' if os.name == 'nt' else ''
|
'.exe' if os.name == 'nt' else ''
|
||||||
))],
|
))],
|
||||||
os.path.join('..', 'bin'),
|
|
||||||
).replace('\r', '')
|
).replace('\r', '')
|
||||||
assert(implementation.scheme.metadata()['nistkat-sha256'].lower()
|
assert(implementation.scheme.metadata()['nistkat-sha256'].lower()
|
||||||
== hashlib.sha256(out.encode('utf-8')).hexdigest().lower())
|
== hashlib.sha256(out.encode('utf-8')).hexdigest().lower())
|
||||||
|
destr()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
import sys
|
||||||
import nose2
|
pytest.main(sys.argv)
|
||||||
nose2.main()
|
|
||||||
except ImportError:
|
|
||||||
import nose
|
|
||||||
nose.runmodule()
|
|
||||||
|
@ -3,18 +3,20 @@ Checks that no implementation makes use of symbolic links.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import pqclean
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
import helpers
|
import helpers
|
||||||
|
import pqclean
|
||||||
|
|
||||||
|
|
||||||
def test_no_symlinks():
|
@pytest.mark.parametrize(
|
||||||
for scheme in pqclean.Scheme.all_schemes():
|
'implementation',
|
||||||
for implementation in scheme.implementations:
|
pqclean.Scheme.all_implementations(),
|
||||||
yield check_no_symlinks, implementation
|
ids=str,
|
||||||
|
)
|
||||||
|
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
def check_no_symlinks(implementation):
|
def test_no_symlinks(implementation):
|
||||||
for file in os.listdir(implementation.path()):
|
for file in os.listdir(implementation.path()):
|
||||||
fpath = os.path.join(implementation.path(), file)
|
fpath = os.path.join(implementation.path(), file)
|
||||||
if os.path.islink(fpath):
|
if os.path.islink(fpath):
|
||||||
@ -22,9 +24,5 @@ def check_no_symlinks(implementation):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
import sys
|
||||||
import nose2
|
pytest.main(sys.argv)
|
||||||
nose2.main()
|
|
||||||
except ImportError:
|
|
||||||
import nose
|
|
||||||
nose.runmodule()
|
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import pqclean
|
import pytest
|
||||||
|
|
||||||
import helpers
|
import helpers
|
||||||
|
import pqclean
|
||||||
|
|
||||||
|
|
||||||
def test_preprocessor():
|
@pytest.mark.parametrize(
|
||||||
for scheme in pqclean.Scheme.all_schemes():
|
'implementation',
|
||||||
for implementation in scheme.implementations:
|
pqclean.Scheme.all_implementations(),
|
||||||
yield check_preprocessor, implementation
|
ids=str,
|
||||||
|
)
|
||||||
|
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
def check_preprocessor(implementation: pqclean.Implementation):
|
def test_preprocessor(implementation: pqclean.Implementation):
|
||||||
cfiles = implementation.cfiles()
|
cfiles = implementation.cfiles()
|
||||||
hfiles = implementation.hfiles()
|
hfiles = implementation.hfiles()
|
||||||
errors = []
|
errors = []
|
||||||
@ -27,10 +28,6 @@ def check_preprocessor(implementation: pqclean.Implementation):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == '__main__':
|
||||||
try:
|
import sys
|
||||||
import nose2
|
pytest.main(sys.argv)
|
||||||
nose2.main()
|
|
||||||
except ImportError:
|
|
||||||
import nose
|
|
||||||
nose.runmodule()
|
|
||||||
|
@ -3,26 +3,31 @@ Checks that the all exported symbols are properly namespaced, i.e., all
|
|||||||
start with "PQCLEAN_SCHEMENAME_".
|
start with "PQCLEAN_SCHEMENAME_".
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import pqclean
|
|
||||||
import helpers
|
|
||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
def test_symbol_namespace():
|
import helpers
|
||||||
for scheme in pqclean.Scheme.all_schemes():
|
import pqclean
|
||||||
for implementation in scheme.implementations:
|
|
||||||
yield check_symbol_namespace, implementation
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'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()],
|
||||||
|
)
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
def check_symbol_namespace(implementation):
|
def test_symbol_namespaces(implementation, impl_path, test_dir, init, destr):
|
||||||
if sys.platform not in ['linux', 'darwin']:
|
if sys.platform not in ['linux', 'darwin']:
|
||||||
raise unittest.SkipTest("Unsupported platform")
|
raise unittest.SkipTest("Unsupported platform")
|
||||||
helpers.make(working_dir=implementation.path())
|
init()
|
||||||
|
helpers.make(working_dir=impl_path)
|
||||||
out = helpers.run_subprocess(
|
out = helpers.run_subprocess(
|
||||||
['nm', '-g', implementation.libname()],
|
['nm', '-g', implementation.libname()],
|
||||||
implementation.path()
|
impl_path,
|
||||||
)
|
)
|
||||||
|
|
||||||
lines = out.strip().split("\n")
|
lines = out.strip().split("\n")
|
||||||
@ -46,13 +51,10 @@ def check_symbol_namespace(implementation):
|
|||||||
print("Missing namespace literal {}".format(namespace))
|
print("Missing namespace literal {}".format(namespace))
|
||||||
for symbol in non_namespaced:
|
for symbol in non_namespaced:
|
||||||
print("\ttype: {}, symbol: {}".format(symtype, symbol))
|
print("\ttype: {}, symbol: {}".format(symtype, symbol))
|
||||||
assert(False)
|
|
||||||
|
assert not non_namespaced, "Literals with missing namespaces"
|
||||||
|
destr()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
pytest.main(sys.argv)
|
||||||
import nose2
|
|
||||||
nose2.main()
|
|
||||||
except ImportError:
|
|
||||||
import nose
|
|
||||||
nose.runmodule()
|
|
||||||
|
@ -5,38 +5,44 @@ the one provided in the META file for every scheme/implementation.
|
|||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import os
|
import os
|
||||||
import pqclean
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
import helpers
|
import helpers
|
||||||
|
import pqclean
|
||||||
|
|
||||||
|
|
||||||
def test_testvectors():
|
@pytest.mark.parametrize(
|
||||||
@helpers.filtered_test
|
'implementation,test_dir,impl_path,init,destr',
|
||||||
def check_testvectors(implementation):
|
[(impl, *helpers.isolate_test_files(impl.path(), 'test_testvectors_'))
|
||||||
|
for sig in pqclean.Signature.all_sigs()
|
||||||
|
for impl in sig.implementations],
|
||||||
|
ids=[str(impl) for sig in pqclean.Signature.all_sigs()
|
||||||
|
for impl in sig.implementations],
|
||||||
|
)
|
||||||
|
@helpers.filtered_test
|
||||||
|
def test_testvectors(implementation, impl_path, test_dir, init, destr):
|
||||||
|
init()
|
||||||
|
dest_dir = os.path.join(test_dir, 'bin')
|
||||||
helpers.make('testvectors',
|
helpers.make('testvectors',
|
||||||
TYPE=implementation.scheme.type,
|
TYPE=implementation.scheme.type,
|
||||||
SCHEME=implementation.scheme.name,
|
SCHEME=implementation.scheme.name,
|
||||||
|
SCHEME_DIR=impl_path,
|
||||||
IMPLEMENTATION=implementation.name,
|
IMPLEMENTATION=implementation.name,
|
||||||
working_dir=os.path.join('..', 'test'))
|
DEST_DIR=dest_dir,
|
||||||
|
working_dir=os.path.join(test_dir, 'test'))
|
||||||
out = helpers.run_subprocess(
|
out = helpers.run_subprocess(
|
||||||
[os.path.join('..', 'bin', 'testvectors_{}_{}{}'.format(
|
[os.path.join(dest_dir, 'testvectors_{}_{}{}'.format(
|
||||||
implementation.scheme.name,
|
implementation.scheme.name,
|
||||||
implementation.name,
|
implementation.name,
|
||||||
'.exe' if os.name == 'nt' else ''
|
'.exe' if os.name == 'nt' else ''
|
||||||
))],
|
))],
|
||||||
os.path.join('..', 'bin'),
|
|
||||||
).replace('\r', '')
|
).replace('\r', '')
|
||||||
assert(implementation.scheme.metadata()['testvectors-sha256'].lower()
|
assert(implementation.scheme.metadata()['testvectors-sha256'].lower()
|
||||||
== hashlib.sha256(out.encode('utf-8')).hexdigest().lower())
|
== hashlib.sha256(out.encode('utf-8')).hexdigest().lower())
|
||||||
|
destr()
|
||||||
for scheme in pqclean.Scheme.all_schemes_of_type('sign'):
|
|
||||||
for implementation in scheme.implementations:
|
|
||||||
yield check_testvectors, implementation
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
import sys
|
||||||
import nose2
|
pytest.main(sys.argv)
|
||||||
nose2.main()
|
|
||||||
except ImportError:
|
|
||||||
import nose
|
|
||||||
nose.runmodule()
|
|
||||||
|
@ -6,37 +6,41 @@ import os
|
|||||||
import platform
|
import platform
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import pqclean
|
import pytest
|
||||||
|
|
||||||
import helpers
|
import helpers
|
||||||
|
import pqclean
|
||||||
|
|
||||||
|
|
||||||
def test_functest():
|
@pytest.mark.parametrize(
|
||||||
for scheme in pqclean.Scheme.all_schemes():
|
'implementation,test_dir,impl_path, init, destr',
|
||||||
for implementation in scheme.implementations:
|
[(impl, *helpers.isolate_test_files(impl.path(), 'test_functest_'))
|
||||||
yield check_valgrind, implementation
|
for impl in pqclean.Scheme.all_implementations()],
|
||||||
|
ids=[str(impl) for impl in pqclean.Scheme.all_implementations()],
|
||||||
|
)
|
||||||
@helpers.slow_test
|
@helpers.slow_test
|
||||||
@helpers.filtered_test
|
@helpers.filtered_test
|
||||||
def check_valgrind(implementation: pqclean.Implementation):
|
def test_valgrind(implementation: pqclean.Implementation, impl_path, test_dir,
|
||||||
|
init, destr):
|
||||||
if (platform.machine() not in ('i386', 'x86_64') or
|
if (platform.machine() not in ('i386', 'x86_64') or
|
||||||
platform.system() != 'Linux'):
|
platform.system() != 'Linux'):
|
||||||
raise unittest.SkipTest()
|
raise unittest.SkipTest()
|
||||||
|
init()
|
||||||
|
|
||||||
|
dest_dir = os.path.join(test_dir, 'bin')
|
||||||
|
|
||||||
helpers.make(TYPE=implementation.scheme.type,
|
helpers.make(TYPE=implementation.scheme.type,
|
||||||
SCHEME=implementation.scheme.name,
|
SCHEME=implementation.scheme.name,
|
||||||
|
SCHEME_DIR=os.path.abspath(impl_path),
|
||||||
IMPLEMENTATION=implementation.name,
|
IMPLEMENTATION=implementation.name,
|
||||||
working_dir=os.path.join('..', 'test'))
|
DEST_DIR=dest_dir,
|
||||||
|
working_dir=os.path.join(test_dir, 'test'))
|
||||||
functest_name = './functest_{}_{}'.format(implementation.scheme.name,
|
functest_name = './functest_{}_{}'.format(implementation.scheme.name,
|
||||||
implementation.name)
|
implementation.name)
|
||||||
helpers.run_subprocess(['valgrind', functest_name],
|
helpers.run_subprocess(['valgrind', functest_name], dest_dir)
|
||||||
os.path.join('..', 'bin'))
|
destr()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
import sys
|
||||||
import nose2
|
pytest.main(sys.argv)
|
||||||
nose2.main()
|
|
||||||
except ImportError:
|
|
||||||
import nose
|
|
||||||
nose.runmodule()
|
|
||||||
|
Loading…
Reference in New Issue
Block a user