You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

87 lines
2.7 KiB

  1. """
  2. Checks that every .c and .h file in an implementation is present as a
  3. dependency of that scheme's Makefile.
  4. """
  5. import os
  6. import pqclean
  7. import helpers
  8. import glob
  9. import datetime
  10. import unittest
  11. def _skipped_test(*args, **kwargs):
  12. """Used to indicate skipped tests"""
  13. raise unittest.SkipTest("Skipped makefile dependencies test")
  14. def test_makefile_dependencies():
  15. for scheme in pqclean.Scheme.all_schemes():
  16. for implementation in scheme.implementations:
  17. if not helpers.permit_test(
  18. 'makefile_dependencies', implementation):
  19. yield _skipped_test, implementation
  20. continue
  21. # initial build - want to have *all* files in place at beginning
  22. helpers.make('clean', working_dir=implementation.path())
  23. helpers.make(working_dir=implementation.path())
  24. # test case for each candidate file
  25. cfiles = glob.glob(os.path.join(implementation.path(), '*.c'))
  26. hfiles = glob.glob(os.path.join(implementation.path(), '*.h'))
  27. for file in (cfiles + hfiles):
  28. yield (check_makefile_dependencies, implementation, file)
  29. def touch(time, *files):
  30. for path in files:
  31. times = (time.timestamp(), time.timestamp())
  32. os.utime(path, times)
  33. def make_check(path, expect_error=False):
  34. makeflag = '-q' if os.name != 'nt' else '/Q'
  35. expected_returncode = 0
  36. if expect_error:
  37. expected_returncode = 1 if os.name != 'nt' else 255
  38. helpers.make(makeflag, working_dir=path,
  39. expected_returncode=expected_returncode)
  40. def check_makefile_dependencies(implementation, file):
  41. cfiles = implementation.cfiles()
  42. hfiles = implementation.hfiles()
  43. ofiles = implementation.ofiles()
  44. libfile = os.path.join(implementation.path(), implementation.libname())
  45. # modification time-based calculations is tricky on a sub-second basis
  46. # so we reset all the modification times to a known and "sensible" order
  47. now = datetime.datetime.now() - datetime.timedelta(seconds=10)
  48. ago15 = now - datetime.timedelta(minutes=15)
  49. ago10 = now - datetime.timedelta(minutes=10)
  50. ago5 = now - datetime.timedelta(minutes=5)
  51. touch(ago15, *cfiles, *hfiles)
  52. touch(ago10, *ofiles)
  53. touch(ago5, libfile)
  54. # Sanity check: the scheme is up to date
  55. make_check(implementation.path())
  56. # touch the candidate .c / .h file
  57. touch(now, file)
  58. # check if it needs to be rebuilt using make -q
  59. make_check(implementation.path(), expect_error=True)
  60. if __name__ == '__main__':
  61. try:
  62. import nose2
  63. nose2.main()
  64. except ImportError:
  65. import nose
  66. nose.runmodule()