mirror of
https://github.com/clearlinux/autospec.git
synced 2026-04-28 19:13:45 +00:00
Given more packages are using ninja as the build system of choice instead of make, add flag to enable ninja usage. Signed-off-by: William Douglas <william.douglas@intel.com>
862 lines
34 KiB
Python
862 lines
34 KiB
Python
import unittest
|
|
import tempfile
|
|
import os
|
|
from unittest.mock import MagicMock, mock_open, patch
|
|
import json
|
|
import io
|
|
import buildreq
|
|
import config
|
|
import pypidata
|
|
|
|
bak_get_pypi_name = pypidata.get_pypi_name
|
|
def get_pypi_name_wrapper(name, miss=None):
|
|
"""Ignore missing packags in pypi"""
|
|
return bak_get_pypi_name(name)
|
|
|
|
|
|
class TestBuildreq(unittest.TestCase):
|
|
|
|
def setUp(self):
|
|
"""
|
|
Test setup method to reset the buildreq module
|
|
"""
|
|
self.reqs = buildreq.Requirements("")
|
|
self.reqs.banned_buildreqs.add('bannedreq')
|
|
|
|
def test_add_buildreq(self):
|
|
"""
|
|
Test add_buildreq with unbanned new req. Follow up by asserting that
|
|
trying to add the same req a second time results in a False return.
|
|
"""
|
|
self.assertTrue(self.reqs.add_buildreq('testreq'))
|
|
self.assertIn('testreq', self.reqs.buildreqs)
|
|
self.assertFalse(self.reqs.add_buildreq('testreq'))
|
|
|
|
def test_add_buildreq_banned(self):
|
|
"""
|
|
Test add_buildreq with banned new req
|
|
"""
|
|
self.assertFalse(self.reqs.add_buildreq('bannedreq'))
|
|
self.assertNotIn('bannedreq', self.reqs.buildreqs)
|
|
|
|
def test_ban_requires(self):
|
|
"""
|
|
Test ban_requires with req already present in requires
|
|
"""
|
|
self.reqs.requires[None] = set(['testreq'])
|
|
self.reqs.ban_requires('testreq')
|
|
self.assertNotIn('testreq', self.reqs.requires[None])
|
|
|
|
def test_ban_requires_subpkg(self):
|
|
"""
|
|
Test ban_requires on a subpkg with req already present in requires
|
|
"""
|
|
self.reqs.requires['subpkg'] = set(['testreq'])
|
|
self.reqs.ban_requires('testreq', subpkg='subpkg')
|
|
self.assertNotIn('testreq', self.reqs.requires['subpkg'])
|
|
|
|
def test_add_requires(self):
|
|
"""
|
|
Test add_requires with unbanned new req already present in
|
|
buildreqs but not yet present in requires
|
|
"""
|
|
self.reqs.add_buildreq('testreq')
|
|
self.assertTrue(self.reqs.add_requires('testreq', ['testreq']))
|
|
self.assertIn('testreq', self.reqs.requires[None])
|
|
|
|
def test_add_requires_subpkg(self):
|
|
"""
|
|
Test add_requires on a subpkg with unbanned new req already present in
|
|
buildreqs but not yet present in requires
|
|
"""
|
|
self.reqs.add_buildreq('testreq')
|
|
self.assertTrue(self.reqs.add_requires('testreq', ['testreq'], subpkg='subpkg'))
|
|
self.assertIn('testreq', self.reqs.requires['subpkg'])
|
|
|
|
def test_add_requires_not_in_buildreqs(self):
|
|
"""
|
|
Test add_requires with unbanned new req not present in buildreqs.
|
|
"""
|
|
self.assertFalse(self.reqs.add_requires('testreq', []))
|
|
self.assertNotIn('testreq', self.reqs.requires[None])
|
|
|
|
def test_add_banned_requires(self):
|
|
"""
|
|
Test add_requires with banned new req (override buildreq).
|
|
"""
|
|
self.assertFalse(self.reqs.add_requires('pypi(nose)', [], override=True))
|
|
self.assertNotIn('testreq', self.reqs.requires[None])
|
|
|
|
def test_ban_provides(self):
|
|
"""
|
|
Test ban_provides with prov already present in provides
|
|
"""
|
|
self.reqs.provides[None] = set(['testreq'])
|
|
self.reqs.ban_provides('testreq')
|
|
self.assertNotIn('testreq', self.reqs.provides[None])
|
|
|
|
def test_ban_provides_subpkg(self):
|
|
"""
|
|
Test ban_provides on a subpkg with prov already present in provides
|
|
"""
|
|
self.reqs.provides['subpkg'] = set(['testreq'])
|
|
self.reqs.ban_provides('testreq', subpkg='subpkg')
|
|
self.assertNotIn('testreq', self.reqs.provides['subpkg'])
|
|
|
|
def test_add_provides(self):
|
|
"""
|
|
Test add_provides with unbanned new prov
|
|
"""
|
|
self.assertTrue(self.reqs.add_provides('testreq'))
|
|
self.assertIn('testreq', self.reqs.provides[None])
|
|
|
|
def test_add_provides_subpkg(self):
|
|
"""
|
|
Test add_provides on a subpkg with unbanned new prov
|
|
"""
|
|
self.assertTrue(self.reqs.add_provides('testreq', subpkg='subpkg'))
|
|
self.assertIn('testreq', self.reqs.provides['subpkg'])
|
|
|
|
def test_add_pkgconfig_buildreq(self):
|
|
"""
|
|
Test add_pkgconfig_buildreq with config_opts['32bit'] set to False
|
|
"""
|
|
self.assertTrue(self.reqs.add_pkgconfig_buildreq('testreq', False))
|
|
self.assertIn('pkgconfig(testreq)', self.reqs.buildreqs)
|
|
|
|
def test_add_pkgconfig_buildreq_32bit(self):
|
|
"""
|
|
Test add_pkgconfig_buildreq with config_opts['32bit'] set to True
|
|
"""
|
|
self.assertTrue(self.reqs.add_pkgconfig_buildreq('testreq', True))
|
|
self.assertIn('pkgconfig(testreq)', self.reqs.buildreqs)
|
|
self.assertIn('pkgconfig(32testreq)', self.reqs.buildreqs)
|
|
|
|
def test_configure_ac_line(self):
|
|
"""
|
|
Test configure_ac_line with standard pattern
|
|
"""
|
|
self.reqs.configure_ac_line('AC_CHECK_FUNC([tgetent])', False)
|
|
self.assertIn('ncurses-devel', self.reqs.buildreqs)
|
|
|
|
def test_configure_ac_line_comment(self):
|
|
"""
|
|
Test configure_ac_line with commented line
|
|
"""
|
|
self.reqs.configure_ac_line('# AC_CHECK_FUNC([tgetent])', False)
|
|
self.assertEqual(self.reqs.buildreqs, set())
|
|
|
|
def test_configure_ac_line_pkg_check_modules(self):
|
|
"""
|
|
Test the somewhat complicated logic of configure_ac_line check for the
|
|
PKG_CHECK_MODULES((.*?)) line.
|
|
"""
|
|
self.reqs.configure_ac_line(
|
|
'PKG_CHECK_MODULES(prefix, '
|
|
'[module > 2 module2 < 2], '
|
|
'action-if-found, action-if-not-found)', False)
|
|
self.assertEqual(self.reqs.buildreqs,
|
|
set(['pkgconfig(module)', 'pkgconfig(module2)']))
|
|
|
|
def test_configure_ac_line_xdt_check_package(self):
|
|
"""
|
|
Test configure_ac_line for the XFCE version of PKG_CHECK_MODULES
|
|
"""
|
|
self.reqs.configure_ac_line(
|
|
'XDT_CHECK_PACKAGE(prefix, '
|
|
'[module = 2 module2 > 9], '
|
|
'action-if-found, action-if-not-found)', False)
|
|
self.assertEqual(self.reqs.buildreqs,
|
|
set(['pkgconfig(module)', 'pkgconfig(module2)']))
|
|
|
|
def test_configure_ac_line_pkg_check_exists(self):
|
|
"""
|
|
Test configure_ac_line for the PKG_CHECK_EXISTS macro
|
|
"""
|
|
self.reqs.configure_ac_line('PKG_CHECK_EXISTS([module1 > 1 module2], '
|
|
'action-if-found, '
|
|
'action-if-not-found)', False)
|
|
self.assertEqual(self.reqs.buildreqs,
|
|
set(['pkgconfig(module1)', 'pkgconfig(module2)']))
|
|
|
|
def test_parse_configure_ac(self):
|
|
"""
|
|
Test parse_configure_ac with changing () depths and package
|
|
requirements
|
|
"""
|
|
conf = config.Config("")
|
|
content = 'AC_CHECK_FUNC([tgetent])\n' \
|
|
'XDT_CHECK_PACKAGE(prefix, ' \
|
|
'[module = 2 module2 > 9], ' \
|
|
'action-if-found, action-if-not-found)\n' \
|
|
'next two lines should be read in batch ( \n' \
|
|
'PROG_INTLTOOL\n' \
|
|
'AC_PROG_SED)\n' \
|
|
'GETTEXT_PACKAGE'
|
|
with tempfile.TemporaryDirectory() as tmpd:
|
|
with open(os.path.join(tmpd, 'fname'), 'w') as f:
|
|
f.write(content)
|
|
self.reqs.parse_configure_ac(os.path.join(tmpd, 'fname'), conf)
|
|
|
|
self.assertEqual(self.reqs.buildreqs,
|
|
set(['gettext',
|
|
'ncurses-devel',
|
|
'perl(XML::Parser)',
|
|
'pkgconfig(module2)',
|
|
'pkgconfig(module)',
|
|
'intltool',
|
|
'sed']))
|
|
|
|
@patch('buildreq.pypidata.get_pypi_name', get_pypi_name_wrapper)
|
|
def test_clean_python_req(self):
|
|
"""
|
|
Test clean_python_req with a common python requirements string
|
|
"""
|
|
self.assertEqual(buildreq.clean_python_req('requirement >= 1.1.2'),
|
|
'requirement')
|
|
self.assertEqual(buildreq.clean_python_req('requirement ; python_version > 1.1.2'),
|
|
'requirement')
|
|
self.assertEqual(buildreq.clean_python_req('requirement ; python_version < 1.1.2'),
|
|
'')
|
|
self.assertEqual(buildreq.clean_python_req('requirement <= 1.1.2'),
|
|
'requirement')
|
|
self.assertEqual(buildreq.clean_python_req('requirement = 1.1.2'),
|
|
'requirement')
|
|
self.assertEqual(buildreq.clean_python_req('requirement \n ; rsa>= 1.1.2'),
|
|
'requirement')
|
|
self.assertEqual(buildreq.clean_python_req('requirement != 1.1.2'),
|
|
'requirement')
|
|
self.assertEqual(buildreq.clean_python_req('[:python > 2]'),
|
|
'')
|
|
self.assertEqual(buildreq.clean_python_req('requirement ~= 1.1.2'),
|
|
'requirement')
|
|
|
|
@patch('buildreq.pypidata.get_pypi_name', get_pypi_name_wrapper)
|
|
def test_clean_python_req_comment(self):
|
|
"""
|
|
Test clean_python_req with a comment
|
|
"""
|
|
self.assertEqual(buildreq.clean_python_req('# hello'), '')
|
|
|
|
@patch('buildreq.pypidata.get_pypi_name', get_pypi_name_wrapper)
|
|
def test_clean_python_req_whitespace(self):
|
|
"""
|
|
Test clean_python_req with strange whitespaced string
|
|
"""
|
|
self.assertEqual(buildreq.clean_python_req(' requirement < 1.1'),
|
|
'requirement')
|
|
|
|
@patch('buildreq.pypidata.get_pypi_name', get_pypi_name_wrapper)
|
|
def test_grab_python_requirements(self):
|
|
"""
|
|
Test grab_python_requirements with a reasonable requirements file
|
|
"""
|
|
# buildreqs must include the requires also
|
|
open_name = 'buildreq.util.open_auto'
|
|
content = 'req1 <= 1.2.3\n' \
|
|
'req2 >= 1.55\n' \
|
|
'req7 == 3.3.3\n'
|
|
m_open = mock_open(read_data=content)
|
|
with patch(open_name, m_open, create=True):
|
|
self.reqs.grab_python_requirements('filename', [])
|
|
|
|
self.assertEqual(self.reqs.requires["python3"], set(['pypi(req1)', 'pypi(req2)', 'pypi(req7)']))
|
|
|
|
@patch('buildreq.pypidata.get_pypi_name', get_pypi_name_wrapper)
|
|
def test_grab_python_requirements_strange_file(self):
|
|
"""
|
|
Test grab_python_requirements with a poorly written file
|
|
"""
|
|
# buildreqs must include the requires also
|
|
open_name = 'buildreq.util.open_auto'
|
|
content = ' req1 <= 1.2.3\n ' \
|
|
'req2 >= 1.55 \n' \
|
|
' req7 == 3.3.3\n '
|
|
m_open = mock_open(read_data=content)
|
|
with patch(open_name, m_open, create=True):
|
|
self.reqs.grab_python_requirements('filename', [])
|
|
|
|
self.assertEqual(self.reqs.requires["python3"], set(['pypi(req1)', 'pypi(req2)', 'pypi(req7)']))
|
|
|
|
@patch('buildreq.pypidata.get_pypi_name', get_pypi_name_wrapper)
|
|
def test_add_setup_py_requires(self):
|
|
"""
|
|
Test add_setup_py_requires with a single item in install_requires and
|
|
setup_requires
|
|
"""
|
|
open_name = 'buildreq.util.open_auto'
|
|
content = "install_requires=['req1']\n" \
|
|
"setup_requires=['req2']"
|
|
m_open = mock_open(read_data=content)
|
|
with patch(open_name, m_open, create=True):
|
|
self.reqs.add_setup_py_requires('filename', [])
|
|
|
|
self.assertEqual(self.reqs.buildreqs, set(['pypi(req1)', 'pypi(req2)']))
|
|
self.assertEqual(self.reqs.requires["python3"], set(['pypi(req1)']))
|
|
|
|
@patch('buildreq.pypidata.get_pypi_name', get_pypi_name_wrapper)
|
|
def test_add_setup_py_requires_multiline(self):
|
|
"""
|
|
Test add_setup_py_requires with a multiline item in install_requires
|
|
"""
|
|
open_name = 'buildreq.util.open_auto'
|
|
content = "install_requires=['req1',\n" \
|
|
"'req2',\n" \
|
|
"'req7']\n"
|
|
m_open = mock_open(read_data=content)
|
|
with patch(open_name, m_open, create=True):
|
|
self.reqs.add_setup_py_requires('filename', [])
|
|
|
|
self.assertEqual(self.reqs.buildreqs, set(['pypi(req1)', 'pypi(req2)', 'pypi(req7)']))
|
|
self.assertEqual(self.reqs.requires["python3"], set(['pypi(req1)', 'pypi(req2)', 'pypi(req7)']))
|
|
|
|
@patch('buildreq.pypidata.get_pypi_name', get_pypi_name_wrapper)
|
|
def test_add_setup_py_requires_multiline_formatted(self):
|
|
"""
|
|
Test add_setup_py_requires with a multiline item in install_requires
|
|
with brackets on their own lines.
|
|
"""
|
|
open_name = 'buildreq.util.open_auto'
|
|
content = "install_requires=[\n " \
|
|
"'req1',\n" \
|
|
"'req2',\n" \
|
|
"'req7',\n" \
|
|
"]\n"
|
|
m_open = mock_open(read_data=content)
|
|
with patch(open_name, m_open, create=True):
|
|
self.reqs.add_setup_py_requires('filename', [])
|
|
|
|
self.assertEqual(self.reqs.buildreqs, set(['pypi(req1)', 'pypi(req2)', 'pypi(req7)']))
|
|
self.assertEqual(self.reqs.requires["python3"], set(['pypi(req1)', 'pypi(req2)', 'pypi(req7)']))
|
|
|
|
@patch('buildreq.pypidata.get_pypi_name', get_pypi_name_wrapper)
|
|
def test_add_setup_py_requires_multiline_variable(self):
|
|
"""
|
|
Test add_setup_py_requires with multiline item in install_requires that
|
|
contains a non-literal object.
|
|
"""
|
|
open_name = 'buildreq.util.open_auto'
|
|
content = "install_requires=[\n" \
|
|
"reqvar,\n" \
|
|
"'req1',\n" \
|
|
"'req2'" \
|
|
"]\n"
|
|
m_open = mock_open(read_data=content)
|
|
with patch(open_name, m_open, create=True):
|
|
self.reqs.add_setup_py_requires('filename', [])
|
|
|
|
self.assertEqual(self.reqs.buildreqs, set(['pypi(req1)', 'pypi(req2)']))
|
|
self.assertEqual(self.reqs.requires["python3"], set(['pypi(req1)', 'pypi(req2)']))
|
|
|
|
@patch('buildreq.pypidata.get_pypi_name', get_pypi_name_wrapper)
|
|
def test_add_setup_py_requires_multiline_install_requires_variable(self):
|
|
"""
|
|
Test add_setup_py_requires with multiline item in install_requires that
|
|
contains an extra bit of content that shouldn't be parsed as install_requires.
|
|
"""
|
|
open_name = 'buildreq.util.open_auto'
|
|
content = "install_requires=[\n" \
|
|
"'req1',\n" \
|
|
"'req2'" \
|
|
"] + install_requires\n" \
|
|
"'bad']\n"
|
|
m_open = mock_open(read_data=content)
|
|
with patch(open_name, m_open, create=True):
|
|
self.reqs.add_setup_py_requires('filename', [])
|
|
|
|
self.assertEqual(self.reqs.buildreqs, set(['pypi(req1)', 'pypi(req2)']))
|
|
self.assertEqual(self.reqs.requires["python3"], set(['pypi(req1)', 'pypi(req2)']))
|
|
|
|
@patch('buildreq.pypidata.get_pypi_name', get_pypi_name_wrapper)
|
|
def test_add_setup_py_requires_variable(self):
|
|
"""
|
|
Test add_setup_py_requires that contains a non-literal object.
|
|
"""
|
|
open_name = 'buildreq.util.open_auto'
|
|
content = "install_requires=[reqname, 'req1', 'req2']\n"
|
|
m_open = mock_open(read_data=content)
|
|
with patch(open_name, m_open, create=True):
|
|
self.reqs.add_setup_py_requires('filename', [])
|
|
|
|
self.assertEqual(self.reqs.buildreqs, set(['pypi(req1)', 'pypi(req2)']))
|
|
self.assertEqual(self.reqs.requires["python3"], set(['pypi(req1)', 'pypi(req2)']))
|
|
|
|
@patch('buildreq.pypidata.get_pypi_name', get_pypi_name_wrapper)
|
|
def test_add_setup_py_requires_single_variable(self):
|
|
"""
|
|
Test add_setup_py_requires with a single non-literal object
|
|
"""
|
|
open_name = 'buildreq.util.open_auto'
|
|
content = "install_requires='reqname'"
|
|
m_open = mock_open(read_data=content)
|
|
with patch(open_name, m_open, create=True):
|
|
self.reqs.add_setup_py_requires('filename', [])
|
|
|
|
self.assertEqual(self.reqs.buildreqs, set(['pypi(reqname)']))
|
|
self.assertEqual(self.reqs.requires['python3'], set(['pypi(reqname)']))
|
|
|
|
def test_scan_for_configure_setup(self):
|
|
"""
|
|
Test scan_for_configure with a mocked package structure. There is so
|
|
much to test here that uses the same logic, a representative test
|
|
should be sufficient.
|
|
"""
|
|
conf = config.Config("")
|
|
conf.config_opts['use_ninja'] = False
|
|
with tempfile.TemporaryDirectory() as tmpd:
|
|
os.mkdir(os.path.join(tmpd, 'subdir'))
|
|
open(os.path.join(tmpd, 'setup.py'), 'w').close()
|
|
|
|
self.reqs.scan_for_configure(tmpd, "", conf)
|
|
|
|
self.assertEqual(self.reqs.buildreqs,
|
|
set(['buildreq-distutils3']))
|
|
|
|
def test_scan_for_configure_cmake(self):
|
|
"""
|
|
Test scan_for_configure with a mocked package structure. There is so
|
|
much to test here that uses the same logic, a representative test
|
|
should be sufficient.
|
|
"""
|
|
conf = config.Config("")
|
|
conf.config_opts['use_ninja'] = False
|
|
with tempfile.TemporaryDirectory() as tmpd:
|
|
os.mkdir(os.path.join(tmpd, 'subdir'))
|
|
open(os.path.join(tmpd, 'CMakeLists.txt'), 'w').close()
|
|
|
|
self.reqs.scan_for_configure(tmpd, "", conf)
|
|
|
|
self.assertEqual(self.reqs.buildreqs,
|
|
set(['buildreq-cmake']))
|
|
|
|
def test_scan_for_configure_scons(self):
|
|
"""
|
|
Test scan_for_configure with a mocked package structure. There is so
|
|
much to test here that uses the same logic, a representative test
|
|
should be sufficient.
|
|
"""
|
|
conf = config.Config("")
|
|
conf.config_opts['use_ninja'] = False
|
|
with tempfile.TemporaryDirectory() as tmpd:
|
|
os.mkdir(os.path.join(tmpd, 'subdir'))
|
|
open(os.path.join(tmpd, 'SConstruct'), 'w').close()
|
|
|
|
self.reqs.scan_for_configure(tmpd, "", conf)
|
|
|
|
self.assertEqual(self.reqs.buildreqs,
|
|
set(['buildreq-scons']))
|
|
|
|
def test_scan_for_configure_meson(self):
|
|
"""
|
|
Test scan_for_configure with a mocked package structure. There is so
|
|
much to test here that uses the same logic, a representative test
|
|
should be sufficient.
|
|
"""
|
|
conf = config.Config("")
|
|
conf.config_opts['use_ninja'] = False
|
|
with tempfile.TemporaryDirectory() as tmpd:
|
|
os.mkdir(os.path.join(tmpd, 'subdir'))
|
|
open(os.path.join(tmpd, 'meson.build'), 'w').close()
|
|
|
|
self.reqs.scan_for_configure(tmpd, "", conf)
|
|
|
|
self.assertEqual(self.reqs.buildreqs,
|
|
set(['buildreq-meson']))
|
|
|
|
def test_scan_for_configure_pypi(self):
|
|
"""
|
|
Test scan_for_configure when distutils is being used for the build
|
|
pattern to test pypi metadata handling.
|
|
"""
|
|
orig_summary = buildreq.specdescription.default_summary
|
|
orig_sscore = buildreq.specdescription.default_summary_score
|
|
orig_pypi_name = buildreq.pypidata.get_pypi_name
|
|
orig_pypi_meta = buildreq.pypidata.get_pypi_metadata
|
|
name = "name"
|
|
requires = ["abc",
|
|
"def"]
|
|
pypi_requires = set(f"pypi({x})" for x in requires)
|
|
summary = "summary"
|
|
content = json.dumps({"name": name,
|
|
"summary": summary,
|
|
"requires": requires})
|
|
buildreq.pypidata.get_pypi_name = MagicMock(return_value=True)
|
|
buildreq.pypidata.get_pypi_metadata = MagicMock(return_value=content)
|
|
with tempfile.TemporaryDirectory() as tmpd:
|
|
conf = config.Config(tmpd)
|
|
conf.config_opts['use_ninja'] = False
|
|
os.mkdir(os.path.join(tmpd, 'subdir'))
|
|
open(os.path.join(tmpd, 'subdir', 'pyproject.toml'), 'w').close()
|
|
self.reqs.scan_for_configure(os.path.join(tmpd, 'subdir'), "", conf)
|
|
|
|
ssummary = buildreq.specdescription.default_summary
|
|
buildreq.specdescription.default_summary = orig_summary
|
|
buildreq.specdescription.default_summary_score = orig_sscore
|
|
buildreq.pypidata.get_pypi_name = orig_pypi_name
|
|
buildreq.pypidata.get_pypi_metadata = orig_pypi_meta
|
|
|
|
self.assertEqual(self.reqs.pypi_provides, name)
|
|
self.assertEqual(self.reqs.requires['python3'], pypi_requires)
|
|
self.assertEqual(ssummary, summary)
|
|
|
|
def test_scan_for_configure_pypi_override(self):
|
|
"""
|
|
Test scan_for_configure when distutils is being used for the build
|
|
pattern to test pypi metadata file override handling.
|
|
"""
|
|
open_name = 'buildreq.open'
|
|
orig_summary = buildreq.specdescription.default_summary
|
|
orig_sscore = buildreq.specdescription.default_summary_score
|
|
name = "name"
|
|
summary = "summary"
|
|
requires = ["req"]
|
|
pypi_requires = set(f"pypi({x})" for x in requires)
|
|
content = json.dumps({"name": name,
|
|
"summary": summary,
|
|
"requires": requires})
|
|
m_open = mock_open(read_data=content)
|
|
with tempfile.TemporaryDirectory() as tmpd:
|
|
conf = config.Config(tmpd)
|
|
conf.config_opts['use_ninja'] = False
|
|
os.mkdir(os.path.join(tmpd, 'subdir'))
|
|
open(os.path.join(tmpd, 'subdir', 'pyproject.toml'), 'w').close()
|
|
open(os.path.join(tmpd, 'pypi.json'), 'w').close()
|
|
with patch(open_name, m_open, create=True):
|
|
self.reqs.scan_for_configure(os.path.join(tmpd, 'subdir'), "", conf)
|
|
|
|
ssummary = buildreq.specdescription.default_summary
|
|
buildreq.specdescription.default_summary = orig_summary
|
|
buildreq.specdescription.default_summary_score = orig_sscore
|
|
|
|
self.assertEqual(self.reqs.pypi_provides, name)
|
|
self.assertEqual(self.reqs.requires['python3'], pypi_requires)
|
|
self.assertEqual(ssummary, summary)
|
|
|
|
def test_scan_for_configure_setup_with_requires(self):
|
|
"""
|
|
Test scan_for_configure when distutils is being used for the build
|
|
pattern to test requires.txt handling.
|
|
"""
|
|
self.reqs.add_pyproject_requires = MagicMock()
|
|
self.reqs.add_setup_py_requires = MagicMock()
|
|
self.reqs.grab_python_requirements = MagicMock()
|
|
|
|
with tempfile.TemporaryDirectory() as tmpd:
|
|
conf = config.Config(tmpd)
|
|
conf.config_opts['use_ninja'] = False
|
|
os.mkdir(os.path.join(tmpd, 'subdir'))
|
|
open(os.path.join(tmpd, 'subdir', 'setup.py'), 'w').close()
|
|
open(os.path.join(tmpd, 'subdir', 'requires.txt'), 'w').close()
|
|
self.reqs.scan_for_configure(os.path.join(tmpd, 'subdir'), "", conf)
|
|
|
|
self.reqs.add_pyproject_requires.assert_not_called()
|
|
self.reqs.add_setup_py_requires.assert_called_once()
|
|
self.reqs.grab_python_requirements.assert_called_once()
|
|
|
|
def test_scan_for_configure_ninja(self):
|
|
"""
|
|
Test scan_for_configure when ninja is enabled.
|
|
"""
|
|
conf = config.Config("")
|
|
conf.config_opts['use_ninja'] = True
|
|
with tempfile.TemporaryDirectory() as tmpd:
|
|
os.mkdir(os.path.join(tmpd, 'subdir'))
|
|
open(os.path.join(tmpd, 'setup.py'), 'w').close()
|
|
|
|
self.reqs.scan_for_configure(tmpd, "", conf)
|
|
|
|
self.assertEqual(self.reqs.buildreqs,
|
|
set(['buildreq-distutils3', 'ninja']))
|
|
|
|
def test_parse_cmake_pkg_check_modules(self):
|
|
"""
|
|
Test parse_cmake to ensure accurate detection of versioned and
|
|
unversioned pkgconfig modules.
|
|
"""
|
|
conf = config.Config("")
|
|
conf.setup_patterns()
|
|
content = 'pkg_check_modules(GLIB gio-unix-2.0>=2.46.0 glib-2.0 REQUIRED)'
|
|
with tempfile.TemporaryDirectory() as tmpd:
|
|
with open(os.path.join(tmpd, 'fname'), 'w') as f:
|
|
f.write(content)
|
|
self.reqs.parse_cmake(os.path.join(tmpd, 'fname'), conf.cmake_modules, False)
|
|
|
|
self.assertEqual(self.reqs.buildreqs,
|
|
set(['pkgconfig(gio-unix-2.0)', 'pkgconfig(glib-2.0)']))
|
|
|
|
def test_parse_cmake_pkg_check_modules_whitespace(self):
|
|
"""
|
|
Test parse_cmake to ensure accurate handling of versioned
|
|
pkgconfig modules with whitespace.
|
|
"""
|
|
conf = config.Config("")
|
|
conf.setup_patterns()
|
|
content = 'pkg_check_modules(GLIB gio-unix-2.0 >= 2.46.0 glib-2.0 REQUIRED)'
|
|
with tempfile.TemporaryDirectory() as tmpd:
|
|
with open(os.path.join(tmpd, 'fname'), 'w') as f:
|
|
f.write(content)
|
|
self.reqs.parse_cmake(os.path.join(tmpd, 'fname'), conf.cmake_modules, False)
|
|
|
|
self.assertEqual(self.reqs.buildreqs,
|
|
set(['pkgconfig(gio-unix-2.0)', 'pkgconfig(glib-2.0)']))
|
|
|
|
def test_parse_cmake_pkg_check_modules_in_a_comment(self):
|
|
"""
|
|
Test parse_cmake to ensure it ignores pkg_check_modules in comments.
|
|
"""
|
|
conf = config.Config("")
|
|
conf.setup_patterns()
|
|
content = '''
|
|
# For example, consider the following patch to some CMakeLists.txt.
|
|
# - pkg_check_modules(FOO REQUIRED foo>=1.0)
|
|
# + pkg_check_modules(FOO REQUIRED foo>=2.0)
|
|
'''
|
|
with tempfile.TemporaryDirectory() as tmpd:
|
|
with open(os.path.join(tmpd, 'fname'), 'w') as f:
|
|
f.write(content)
|
|
self.reqs.parse_cmake(os.path.join(tmpd, 'fname'), conf.cmake_modules, False)
|
|
|
|
self.assertEqual(self.reqs.buildreqs,
|
|
set([]))
|
|
|
|
def test_parse_cmake_pkg_check_modules_variables(self):
|
|
"""
|
|
Test parse_cmake to ensure accurate handling of versioned
|
|
pkgconfig modules with variable version strings.
|
|
"""
|
|
conf = config.Config("")
|
|
conf.setup_patterns()
|
|
content = 'pkg_check_modules(AVCODEC libavcodec${_avcodec_ver} libavutil$_avutil_ver)'
|
|
with tempfile.TemporaryDirectory() as tmpd:
|
|
with open(os.path.join(tmpd, 'fname'), 'w') as f:
|
|
f.write(content)
|
|
self.reqs.parse_cmake(os.path.join(tmpd, 'fname'), conf.cmake_modules, False)
|
|
|
|
self.assertEqual(self.reqs.buildreqs,
|
|
set(['pkgconfig(libavcodec)', 'pkgconfig(libavutil)']))
|
|
|
|
def test_parse_cmake_find_package(self):
|
|
"""
|
|
Test parse_cmake to ensure accurate handling of find_package.
|
|
"""
|
|
cmake_modules = {
|
|
"valid": "valid",
|
|
"valid_but_commented": "valid_but_commented",
|
|
"different_name": "another_name",
|
|
"qt6.module1": "qt6module1",
|
|
"qt6.module2": "qt6module2",
|
|
"kf6.module3": "kf6module3",
|
|
"kf6.module4": "kf6module4",
|
|
".module5": "namodule5",
|
|
".module6": "namodule6"
|
|
}
|
|
content = '''
|
|
find_package(valid)
|
|
#find_package(foo)
|
|
# find_package(valid_but_commented)
|
|
find_package(different_name)
|
|
find_package(Qt6 stuff
|
|
module1
|
|
module2)
|
|
find_package(KF6 stuff
|
|
module3
|
|
module4
|
|
)
|
|
find_package(NOT_HANDLED_NAMESPACE stuff
|
|
module5
|
|
|
|
module6
|
|
)
|
|
'''
|
|
with tempfile.TemporaryDirectory() as tmpd:
|
|
with open(os.path.join(tmpd, 'fname'), 'w') as f:
|
|
f.write(content)
|
|
self.reqs.parse_cmake(os.path.join(tmpd, 'fname'), cmake_modules, False)
|
|
|
|
self.assertEqual(self.reqs.buildreqs,
|
|
set(['valid',
|
|
'another_name',
|
|
'qt6module1',
|
|
'qt6module2',
|
|
'kf6module3',
|
|
'kf6module4',
|
|
'namodule5',
|
|
'namodule6']))
|
|
|
|
def test_r_desc_field_begin(self):
|
|
"""Test parsing of the first R description field."""
|
|
lines = [
|
|
"Field1: foo",
|
|
"Field2: bar",
|
|
"Field3: baz",
|
|
]
|
|
result = buildreq._get_desc_field("Field1", "\n".join(lines))
|
|
self.assertEqual(result, ["foo"])
|
|
|
|
def test_r_desc_field_middle(self):
|
|
"""Test parsing of an R description field with surrounding fields."""
|
|
lines = [
|
|
"Field1: foo",
|
|
"Field2: bar",
|
|
"Field3: baz",
|
|
]
|
|
result = buildreq._get_desc_field("Field2", "\n".join(lines))
|
|
self.assertEqual(result, ["bar"])
|
|
|
|
def test_r_desc_field_end(self):
|
|
"""Test parsing of the last R description field."""
|
|
lines = [
|
|
"Field1: foo",
|
|
"Field2: bar",
|
|
"Field3: baz",
|
|
]
|
|
result = buildreq._get_desc_field("Field3", "\n".join(lines))
|
|
self.assertEqual(result, ["baz"])
|
|
|
|
def test_r_desc_field_middle_multiple_lines(self):
|
|
"""Test parsing of a multi-line R description field, with surrounding fields."""
|
|
lines = [
|
|
"Field1: foo",
|
|
"Field2: bar1, bar2,",
|
|
" bar3, bar4",
|
|
"Field3: baz",
|
|
]
|
|
result = buildreq._get_desc_field("Field2", "\n".join(lines))
|
|
self.assertEqual(result, ["bar1", "bar2", "bar3", "bar4"])
|
|
|
|
def test_r_desc_field_end_multiple_lines(self):
|
|
"""Test parsing of the last R description field, consisting of multiple lines."""
|
|
lines = [
|
|
"Field1: foo",
|
|
"Field2: bar",
|
|
"Field3: baz1,",
|
|
" baz2",
|
|
]
|
|
result = buildreq._get_desc_field("Field3", "\n".join(lines))
|
|
self.assertEqual(result, ["baz1", "baz2"])
|
|
|
|
def test_r_desc_field_middle_one_per_line(self):
|
|
"""Test parsing of an R description field with one entry per line."""
|
|
lines = [
|
|
"Field1: foo",
|
|
"Field2:",
|
|
"bar1,",
|
|
"bar2",
|
|
"Field3: baz",
|
|
]
|
|
result = buildreq._get_desc_field("Field2", "\n".join(lines))
|
|
self.assertEqual(result, ["bar1", "bar2"])
|
|
|
|
def test_r_desc_field_trailing_whitespace(self):
|
|
"""Test parsing of an R description field with trailing whitespace."""
|
|
lines = [
|
|
"Field1: foo1, foo2 ",
|
|
]
|
|
result = buildreq._get_desc_field("Field1", "\n".join(lines))
|
|
self.assertEqual(result, ["foo1", "foo2"])
|
|
|
|
def test_r_desc_field_trailing_comma(self):
|
|
"""Test parsing of an R description field with trailing comma."""
|
|
lines = [
|
|
"Field1: foo1, foo2,",
|
|
]
|
|
result = buildreq._get_desc_field("Field1", "\n".join(lines))
|
|
self.assertEqual(result, ["foo1", "foo2"])
|
|
|
|
def test_r_desc_field_empty(self):
|
|
"""Test parsing of an R description field with an empty value."""
|
|
lines = [
|
|
"Field1:",
|
|
]
|
|
result = buildreq._get_desc_field("Field1", "\n".join(lines))
|
|
self.assertEqual(result, [])
|
|
|
|
def test_r_desc_field_missing(self):
|
|
"""Test parsing of an R description field that is missing."""
|
|
lines = [
|
|
"Field1: foo, bar",
|
|
]
|
|
result = buildreq._get_desc_field("Field2", "\n".join(lines))
|
|
self.assertEqual(result, [])
|
|
|
|
def test_parse_r_desc_depends(self):
|
|
"""Test parsing of R description Depends field."""
|
|
pkgs = ['R-pkg1']
|
|
open_name = 'buildreq.util.open_auto'
|
|
content = 'Depends: pkg1'
|
|
m_open = mock_open(read_data=content)
|
|
with patch(open_name, m_open):
|
|
self.reqs.parse_r_description('filename', pkgs)
|
|
self.assertTrue('R-pkg1' in self.reqs.buildreqs)
|
|
|
|
def test_parse_r_desc_imports(self):
|
|
"""Test parsing of an R description Imports field."""
|
|
pkgs = ['R-pkg2']
|
|
open_name = 'buildreq.util.open_auto'
|
|
content = 'Imports: pkg2'
|
|
m_open = mock_open(read_data=content)
|
|
with patch(open_name, m_open):
|
|
self.reqs.parse_r_description('filename', pkgs)
|
|
self.assertTrue('R-pkg2' in self.reqs.buildreqs)
|
|
|
|
def test_parse_r_desc_linkingto(self):
|
|
"""Test parsing of an R description LinkingTo field."""
|
|
pkgs = ['R-pkg3']
|
|
open_name = 'buildreq.util.open_auto'
|
|
content = 'LinkingTo: pkg3'
|
|
m_open = mock_open(read_data=content)
|
|
with patch(open_name, m_open):
|
|
self.reqs.parse_r_description('filename', pkgs)
|
|
self.assertTrue('R-pkg3' in self.reqs.buildreqs)
|
|
|
|
def test_parse_r_desc_multiple(self):
|
|
"""Test parsing of an R description file that captures multiple fields."""
|
|
pkgs = [
|
|
'R-pkg1',
|
|
'R-pkg2',
|
|
'R-pkg3',
|
|
'R-pkg4',
|
|
]
|
|
open_name = 'buildreq.util.open_auto'
|
|
content = [
|
|
'Field1: foo',
|
|
'Imports: pkg1, pkg2,',
|
|
' pkg3 ',
|
|
'LinkingTo: pkg4',
|
|
'FieldFoo: bar',
|
|
]
|
|
m_open = mock_open(read_data='\n'.join(content))
|
|
with patch(open_name, m_open):
|
|
self.reqs.parse_r_description('filename', pkgs)
|
|
self.assertFalse('R-foo' in self.reqs.buildreqs)
|
|
self.assertFalse('R-bar' in self.reqs.buildreqs)
|
|
self.assertTrue('R-pkg1' in self.reqs.buildreqs)
|
|
self.assertTrue('R-pkg2' in self.reqs.buildreqs)
|
|
self.assertTrue('R-pkg3' in self.reqs.buildreqs)
|
|
self.assertTrue('R-pkg4' in self.reqs.buildreqs)
|
|
|
|
def test_parse_r_desc_not_in_os(self):
|
|
"""Test parsing of an R description file with some non-OS packages."""
|
|
pkgs = [
|
|
'R-pkg1',
|
|
]
|
|
open_name = 'buildreq.util.open_auto'
|
|
content = [
|
|
'Imports: pkg1, pkg2',
|
|
'Depends: pkg3',
|
|
]
|
|
m_open = mock_open(read_data='\n'.join(content))
|
|
with patch(open_name, m_open):
|
|
self.reqs.parse_r_description('filename', pkgs)
|
|
self.assertTrue('R-pkg1' in self.reqs.buildreqs)
|
|
self.assertTrue('R-pkg1' in self.reqs.requires[None])
|
|
# Names absent from the os-packages list are also added, because the
|
|
# DESCRIPTION file is considered authoritative.
|
|
for pkg in ['R-pkg2', 'R-pkg3']:
|
|
self.assertTrue(pkg in self.reqs.buildreqs)
|
|
self.assertTrue(pkg in self.reqs.requires[None])
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main(buffer=True)
|