diff --git a/.circleci/config.yml b/.circleci/config.yml index 810608fa..17f13e49 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,7 +10,7 @@ version: 2 - run: name: Run the tests in a container command: | - docker run --rm -v `pwd`:`pwd` -w `pwd` "pqclean/ci-container:$ARCH" /bin/bash -c " + docker run -e CI=true --rm -v `pwd`:`pwd` -w `pwd` "pqclean/ci-container:$ARCH" /bin/bash -c " uname -a && export CC=${CC} && cd test && python3 -m nose --rednose --verbose" diff --git a/appveyor.yml b/appveyor.yml index 41bc098f..956ad13d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,14 +12,16 @@ environment: init: - call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars%BITS%.bat" - - set PATH="C:\\Python37";"C:\\Python37\Scripts";"C:\\tmp\\tools";%PATH% - - mkdir "C:\tmp\tools" # Download AStyle 3.1: first enable strong crypto in Invoke-WebRequest - ps: Set-ItemProperty -Path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319" -Name 'SchUseStrongCrypto' -Value '1' -Type DWord - ps: Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319" -Name "SchUseStrongCrypto" -Value '1' -Type DWord - - ps: Invoke-WebRequest -OutFile "C:\tmp\tools\AStyle.exe" "https://rded.nl/pqclean/AStyle.exe" + # Add Python to PATH + - set PATH="C:\\Python37";"C:\\Python37\Scripts";%PATH% build_script: - python -m pip install -r requirements.txt - cd test + # 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" + # Run tests - python -m nose -v --rednose diff --git a/test/Makefile.Microsoft_nmake b/test/Makefile.Microsoft_nmake index e0e057fb..21afb364 100644 --- a/test/Makefile.Microsoft_nmake +++ b/test/Makefile.Microsoft_nmake @@ -39,7 +39,7 @@ $(DEST_DIR)\functest_$(SCHEME)_$(IMPLEMENTATION).exe: build-scheme $(COMMON_OBJE -MKDIR $(DEST_DIR) -DEL functest.obj $(CC) /c crypto_$(TYPE)\functest.c $(CFLAGS) /I $(SCHEME_DIR) /DPQCLEAN_NAMESPACE=PQCLEAN_$(SCHEME_UPPERCASE)_$(IMPLEMENTATION_UPPERCASE) - LINK.EXE /OUT:$@ functest.obj $(COMMON_OBJECTS_NOPATH) notrandombytes.obj $(SCHEME_DIR)\lib$(SCHEME)_$(IMPLEMENTATION).lib Advapi32.lib + LINK.EXE /OUT:$@ functest.obj $(COMMON_OBJECTS_NOPATH) randombytes.obj $(SCHEME_DIR)\lib$(SCHEME)_$(IMPLEMENTATION).lib Advapi32.lib $(DEST_DIR)\testvectors_$(SCHEME)_$(IMPLEMENTATION).exe: build-scheme $(COMMON_OBJECTS) $(COMMON_DIR)\notrandombytes.obj -MKDIR $(DEST_DIR) diff --git a/test/helpers.py b/test/helpers.py index 0f043691..238e234c 100644 --- a/test/helpers.py +++ b/test/helpers.py @@ -2,6 +2,8 @@ import functools import os import subprocess import unittest +import shutil +import sys def run_subprocess(command, working_dir='.', env=None, expected_returncode=0): @@ -44,7 +46,8 @@ def make(*args, working_dir='.', env=None, expected_returncode=0, **kwargs): # we need SCHEME_UPPERCASE and IMPLEMENTATION_UPPERCASE with nmake for envvar in ['IMPLEMENTATION', 'SCHEME']: if envvar in kwargs: - kwargs['{}_UPPERCASE'.format(envvar)] = kwargs[envvar].upper().replace('-', '') + kwargs['{}_UPPERCASE'.format(envvar)] = ( + kwargs[envvar].upper().replace('-', '')) else: make_command = ['make'] @@ -69,4 +72,29 @@ def skip_windows(message="This test is not supported on Windows"): return skip_windows else: return f - return wrapper \ No newline at end of file + return wrapper + + +def ensure_available(executable): + """ + Checks if a command is available. + + If a command MUST be available, because we are in a CI environment, + raises an AssertionError. + + In the docker containers, on Travis and on Windows, CI=true is set. + """ + path = shutil.which(executable) + if path: + print("Found", path) + return path + + # Installing clang-tidy on LLVM will be too much of a mess. + if ((executable == 'clang-tidy' and sys.platform == 'darwin') + or 'CI' not in os.environ): + raise unittest.SkipTest( + "{} is not available on PATH. Install it to run this test.{}" + .format(executable, "" if not os.name == 'nt' + else "On Windows, make sure to add it to PATH") + ) + raise AssertionError("{} not available on CI".format(executable)) diff --git a/test/test_format.py b/test/test_format.py index e94e3deb..09cc61fd 100644 --- a/test/test_format.py +++ b/test/test_format.py @@ -1,8 +1,5 @@ -import shutil -import unittest - import pqclean -from helpers import run_subprocess +from helpers import run_subprocess, ensure_available def test_formatting(): @@ -12,8 +9,7 @@ def test_formatting(): def check_format(implementation: pqclean.Implementation): - if shutil.which('astyle') is None: - raise unittest.SkipTest("AStyle is not installed") + ensure_available('astyle') cfiles = implementation.cfiles() hfiles = implementation.hfiles() run_subprocess(['astyle', diff --git a/test/test_functest.py b/test/test_functest.py index 465b639a..01807e75 100644 --- a/test/test_functest.py +++ b/test/test_functest.py @@ -24,7 +24,7 @@ def test_functest_sanitizers(): def check_functest(implementation): - helpers.make(#'functest', + helpers.make('functest', TYPE=implementation.scheme.type, SCHEME=implementation.scheme.name, IMPLEMENTATION=implementation.name, @@ -48,6 +48,8 @@ def check_functest_sanitizers(implementation): env = {'ASAN_OPTIONS': 'detect_leaks=0'} else: print("Supported platform: {}".format(platform.machine())) + + helpers.ensure_available('valgrind') helpers.make('clean-scheme', 'functest', TYPE=implementation.scheme.type, SCHEME=implementation.scheme.name, diff --git a/test/test_linter.py b/test/test_linter.py index 8d6b6839..33563f8b 100644 --- a/test/test_linter.py +++ b/test/test_linter.py @@ -1,10 +1,8 @@ import os from glob import glob -import shutil -import unittest import pqclean -from helpers import run_subprocess +from helpers import run_subprocess, ensure_available def test_clang_tidy(): @@ -14,8 +12,7 @@ def test_clang_tidy(): def check_tidy(implementation: pqclean.Implementation): - if shutil.which('clang-tidy') is None: - raise unittest.SkipTest("clang-tidy unavailable in PATH") + ensure_available('clang-tidy') cfiles = glob(os.path.join(implementation.path(), '*.c')) common_files = glob(os.path.join('..', 'common', '*.c')) run_subprocess(['clang-tidy',