mirror of
https://github.com/clearlinux/autospec.git
synced 2026-08-28 21:35:42 +00:00
4befc85602
Improve rust/cargo support by: 1) Better handling only toplevel Cargo configuration files for dependency lookup. 2) Adding runtime requirements for buildreq packages in order to get dependencies from non directly dependent packages resolved. 3) Add cargo as a buildreq for rust packages to handle the rustc/cargo split. 4) Add cargo detection from failed_commands. 5) Fix rust source directory destination to not append version in case the package name already had version information in it. 6) Get name and version information from crates.io package files.
390 lines
15 KiB
Python
390 lines
15 KiB
Python
import unittest
|
|
import tempfile
|
|
import os
|
|
from unittest.mock import mock_open, patch
|
|
import buildreq
|
|
|
|
|
|
class TestBuildreq(unittest.TestCase):
|
|
|
|
@classmethod
|
|
def setUpClass(self):
|
|
"""
|
|
Class setup method to configure necessary modules
|
|
"""
|
|
buildreq.banned_buildreqs.add('bannedreq')
|
|
buildreq.config.setup_patterns()
|
|
|
|
def setUp(self):
|
|
"""
|
|
Test setup method to reset the buildreq module
|
|
"""
|
|
buildreq.banned_requires = set()
|
|
buildreq.buildreqs = set()
|
|
buildreq.requires = set()
|
|
buildreq.verbose = False
|
|
buildreq.cargo_bin = False
|
|
buildreq.config.config_opts['32bit'] = False
|
|
buildreq.config.os_packages = set()
|
|
buildreq.buildpattern.pattern_strength = 0
|
|
|
|
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(buildreq.add_buildreq('testreq'))
|
|
self.assertIn('testreq', buildreq.buildreqs)
|
|
self.assertFalse(buildreq.add_buildreq('testreq'))
|
|
|
|
def test_add_buildreq_banned(self):
|
|
"""
|
|
Test add_buildreq with banned new req
|
|
"""
|
|
self.assertFalse(buildreq.add_buildreq('bannedreq'))
|
|
self.assertNotIn('bannedreq', buildreq.buildreqs)
|
|
|
|
def test_add_requires(self):
|
|
"""
|
|
Test add_requires with unbanned new req already present in
|
|
buildreqs but not yet present in requires
|
|
"""
|
|
buildreq.add_buildreq('testreq')
|
|
self.assertTrue(buildreq.add_requires('testreq'))
|
|
self.assertIn('testreq', buildreq.requires)
|
|
|
|
def test_add_requires_not_in_buildreqs(self):
|
|
"""
|
|
Test add_requires with unbanned new req not present in buildreqs.
|
|
"""
|
|
self.assertFalse(buildreq.add_requires('testreq'))
|
|
self.assertNotIn('testreq', buildreq.requires)
|
|
|
|
def test_add_pkgconfig_buildreq(self):
|
|
"""
|
|
Test add_pkgconfig_buildreq with config_opts['32bit'] set to False
|
|
"""
|
|
self.assertTrue(buildreq.add_pkgconfig_buildreq('testreq'))
|
|
self.assertIn('pkgconfig(testreq)', buildreq.buildreqs)
|
|
|
|
def test_add_pkgconfig_buildreq_32bit(self):
|
|
"""
|
|
Test add_pkgconfig_buildreq with config_opts['32bit'] set to True
|
|
"""
|
|
buildreq.config.config_opts['32bit'] = True
|
|
self.assertTrue(buildreq.add_pkgconfig_buildreq('testreq'))
|
|
self.assertIn('pkgconfig(testreq)', buildreq.buildreqs)
|
|
self.assertIn('pkgconfig(32testreq)', buildreq.buildreqs)
|
|
|
|
def test_configure_ac_line(self):
|
|
"""
|
|
Test configure_ac_line with standard pattern
|
|
"""
|
|
buildreq.configure_ac_line('AC_CHECK_FUNC\([tgetent])')
|
|
self.assertIn('ncurses-devel', buildreq.buildreqs)
|
|
|
|
def test_configure_ac_line_comment(self):
|
|
"""
|
|
Test configure_ac_line with commented line
|
|
"""
|
|
buildreq.configure_ac_line('# AC_CHECK_FUNC\([tgetent])')
|
|
self.assertEqual(buildreq.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.
|
|
"""
|
|
buildreq.configure_ac_line(
|
|
'PKG_CHECK_MODULES(prefix, '
|
|
'[module > 2 module2 < 2], '
|
|
'action-if-found, action-if-not-found)')
|
|
self.assertEqual(buildreq.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
|
|
"""
|
|
buildreq.configure_ac_line(
|
|
'XDT_CHECK_PACKAGE(prefix, '
|
|
'[module = 2 module2 > 9], '
|
|
'action-if-found, action-if-not-found)')
|
|
self.assertEqual(buildreq.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
|
|
"""
|
|
buildreq.configure_ac_line('PKG_CHECK_EXISTS([module1 > 1 module2], '
|
|
'action-if-found, '
|
|
'action-if-not-found)')
|
|
self.assertEqual(buildreq.buildreqs,
|
|
set(['pkgconfig(module1)', 'pkgconfig(module2)']))
|
|
|
|
def test_parse_configure_ac(self):
|
|
"""
|
|
Test parse_configure_ac with changing () depths and package
|
|
requirements
|
|
"""
|
|
open_name = 'buildreq.open'
|
|
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)
|
|
buildreq.parse_configure_ac(os.path.join(tmpd, 'fname'))
|
|
|
|
self.assertEqual(buildreq.buildpattern.default_pattern, 'configure_ac')
|
|
self.assertEqual(buildreq.buildreqs,
|
|
set(['gettext',
|
|
'perl(XML::Parser)',
|
|
'pkgconfig(module2)',
|
|
'pkgconfig(module)',
|
|
'intltool',
|
|
'sed']))
|
|
|
|
def test_parse_cargo_toml(self):
|
|
"""
|
|
Test parse_cargo_toml
|
|
"""
|
|
def mock_loads(loadstr):
|
|
return {'dependencies': ['dep1', 'dep2', 'dep3'], 'bin': True}
|
|
|
|
def mock_exists(path):
|
|
return True
|
|
|
|
exists_backup = buildreq.os.path.exists
|
|
loads_backup = buildreq.toml.loads
|
|
|
|
buildreq.os.path.exists = mock_exists
|
|
buildreq.toml.loads = mock_loads
|
|
|
|
open_name = 'buildreq.open'
|
|
content = 'does not matter, let us mock'
|
|
m_open = mock_open(read_data=content)
|
|
with patch(open_name, m_open, create=True):
|
|
buildreq.parse_cargo_toml('filename')
|
|
|
|
buildreq.os.path.exists = exists_backup
|
|
buildreq.toml.loads = loads_backup
|
|
|
|
self.assertEqual(buildreq.buildreqs,
|
|
set(['cargo', 'rustc', 'dep1', 'dep2', 'dep3']))
|
|
self.assertTrue(buildreq.cargo_bin)
|
|
self.assertEqual(buildreq.buildpattern.default_pattern, 'cargo')
|
|
|
|
def test_set_build_req_maven(self):
|
|
"""
|
|
Test set_build_req with buildpattern.default_pattern set to maven.
|
|
This is just a simple test for the inclusion of a single package, in
|
|
case the overall package list changes in the future.
|
|
"""
|
|
buildreq.buildpattern.default_pattern = 'maven'
|
|
buildreq.set_build_req()
|
|
self.assertIn('apache-maven', buildreq.buildreqs)
|
|
|
|
def test_set_build_req_ruby(self):
|
|
"""
|
|
Test set_build_req with buildpattern.default_pattern set to ruby.
|
|
This is just a simple test for the inclusion of a single package, in
|
|
case the overall package list changes in the future.
|
|
"""
|
|
buildreq.buildpattern.default_pattern = 'ruby'
|
|
buildreq.set_build_req()
|
|
self.assertIn('ruby', buildreq.buildreqs)
|
|
|
|
def test_set_build_req_cargo(self):
|
|
"""
|
|
Test set_build_req with buildpattern.default_pattern set to cargo.
|
|
This is just a simple test for the inclusion of a single package, in
|
|
case the overall package list changes in the future.
|
|
"""
|
|
buildreq.buildpattern.default_pattern = 'cargo'
|
|
buildreq.set_build_req()
|
|
self.assertIn('rustc', buildreq.buildreqs)
|
|
|
|
def test_rakefile(self):
|
|
"""
|
|
Test rakefile parsing with both configured gems and unconfigured gems
|
|
"""
|
|
open_name = 'buildreq.open'
|
|
content = "line1\nrequire 'bundler/gem_tasks'\nline3\nrequire 'nope'"
|
|
m_open = mock_open(read_data=content)
|
|
with patch(open_name, m_open, create=True):
|
|
buildreq.rakefile('filename')
|
|
|
|
self.assertEqual(buildreq.buildreqs, set(['rubygem-rubygems-tasks']))
|
|
|
|
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')
|
|
|
|
def test_clean_python_req_comment(self):
|
|
"""
|
|
Test clean_python_req with a comment
|
|
"""
|
|
self.assertEqual(buildreq.clean_python_req('# hello'), '')
|
|
|
|
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')
|
|
|
|
def test_grab_python_requirements(self):
|
|
"""
|
|
Test grab_python_requirements with a reasonable requirements file
|
|
"""
|
|
# buildreqs must include the requires also
|
|
buildreq.buildreqs = set(['req1', 'req2', 'req7'])
|
|
open_name = 'buildreq.open'
|
|
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):
|
|
buildreq.grab_python_requirements('filename')
|
|
|
|
self.assertEqual(buildreq.requires, set(['req1', 'req2', 'req7']))
|
|
|
|
def test_grab_python_requirements_strange_file(self):
|
|
"""
|
|
Test grab_python_requirements with a poorly written file
|
|
"""
|
|
# buildreqs must include the requires also
|
|
buildreq.buildreqs = set(['req1', 'req2', 'req7'])
|
|
open_name = 'buildreq.open'
|
|
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):
|
|
buildreq.grab_python_requirements('filename')
|
|
|
|
self.assertEqual(buildreq.requires, set(['req1', 'req2', 'req7']))
|
|
|
|
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.open'
|
|
content = "install_requires=['req1']\n" \
|
|
"setup_requires=['req2']"
|
|
m_open = mock_open(read_data=content)
|
|
with patch(open_name, m_open, create=True):
|
|
buildreq.add_setup_py_requires('filename')
|
|
|
|
self.assertEqual(buildreq.buildreqs, set(['req1', 'req2']))
|
|
self.assertEqual(buildreq.requires, set(['req1']))
|
|
|
|
def test_add_setup_py_requires_multiline(self):
|
|
"""
|
|
Test add_setup_py_requires with a multiline item in install_requires
|
|
"""
|
|
open_name = 'buildreq.open'
|
|
content = "install_requires=['req1',\n" \
|
|
"'req2',\n" \
|
|
"'req3']\n"
|
|
m_open = mock_open(read_data=content)
|
|
with patch(open_name, m_open, create=True):
|
|
buildreq.add_setup_py_requires('filename')
|
|
|
|
self.assertEqual(buildreq.buildreqs, set(['req1', 'req2', 'req3']))
|
|
self.assertEqual(buildreq.requires, set(['req1', 'req2', 'req3']))
|
|
|
|
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.open'
|
|
content = "install_requires=[\n " \
|
|
"'req1',\n" \
|
|
"'req2',\n" \
|
|
"'req3',\n" \
|
|
"]\n"
|
|
m_open = mock_open(read_data=content)
|
|
with patch(open_name, m_open, create=True):
|
|
buildreq.add_setup_py_requires('filename')
|
|
|
|
self.assertEqual(buildreq.buildreqs, set(['req1', 'req2', 'req3']))
|
|
self.assertEqual(buildreq.requires, set(['req1', 'req2', 'req3']))
|
|
|
|
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.open'
|
|
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):
|
|
buildreq.add_setup_py_requires('filename')
|
|
|
|
self.assertEqual(buildreq.buildreqs, set(['req1', 'req2']))
|
|
self.assertEqual(buildreq.requires, set(['req1', 'req2']))
|
|
|
|
def test_add_setup_py_requires_variable(self):
|
|
"""
|
|
Test add_setup_py_requires that contains a non-literal object.
|
|
"""
|
|
open_name = 'buildreq.open'
|
|
content = "install_requires=[reqname, 'req1', 'req2']\n"
|
|
m_open = mock_open(read_data=content)
|
|
with patch(open_name, m_open, create=True):
|
|
buildreq.add_setup_py_requires('filename')
|
|
|
|
self.assertEqual(buildreq.buildreqs, set(['req1', 'req2']))
|
|
self.assertEqual(buildreq.requires, set(['req1', 'req2']))
|
|
|
|
def test_add_setup_py_requires_single_variable(self):
|
|
"""
|
|
Test add_setup_py_requires with a single non-literal object
|
|
"""
|
|
open_name = 'buildreq.open'
|
|
content = "install_requires=reqname"
|
|
m_open = mock_open(read_data=content)
|
|
with patch(open_name, m_open, create=True):
|
|
buildreq.add_setup_py_requires('filename')
|
|
|
|
self.assertEqual(buildreq.buildreqs, set())
|
|
self.assertEqual(buildreq.requires, set())
|
|
|
|
def test_scan_for_configure(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.
|
|
"""
|
|
with tempfile.TemporaryDirectory() as tmpd:
|
|
os.mkdir(os.path.join(tmpd, 'subdir'))
|
|
open(os.path.join(tmpd, 'subdir', 'test.go'), 'w').close()
|
|
open(os.path.join(tmpd, 'CMakeLists.txt'), 'w').close()
|
|
open(os.path.join(tmpd, 'SConstruct'), 'w').close()
|
|
|
|
buildreq.scan_for_configure(tmpd)
|
|
|
|
self.assertEqual(buildreq.buildreqs,
|
|
set(['go', 'cmake', 'scons', 'python-dev']))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main(buffer=True)
|