| # SPDX-License-Identifier: Apache-2.0 |
| # Copyright © 2022-2023 Intel Corporation |
| |
| from __future__ import annotations |
| import unittest |
| import os |
| import tempfile |
| import textwrap |
| import typing as T |
| |
| from mesonbuild.cargo import builder, cfg, load_wraps |
| from mesonbuild.cargo.cfg import TokenType |
| from mesonbuild.cargo.version import convert |
| |
| |
| class CargoVersionTest(unittest.TestCase): |
| |
| def test_cargo_to_meson(self) -> None: |
| cases: T.List[T.Tuple[str, T.List[str]]] = [ |
| # Basic requirements |
| ('>= 1', ['>= 1']), |
| ('> 1', ['> 1']), |
| ('= 1', ['= 1']), |
| ('< 1', ['< 1']), |
| ('<= 1', ['<= 1']), |
| |
| # tilde tests |
| ('~1', ['>= 1', '< 2']), |
| ('~1.1', ['>= 1.1', '< 1.2']), |
| ('~1.1.2', ['>= 1.1.2', '< 1.2.0']), |
| |
| # Wildcards |
| ('*', []), |
| ('1.*', ['>= 1', '< 2']), |
| ('2.3.*', ['>= 2.3', '< 2.4']), |
| |
| # Unqualified |
| ('2', ['>= 2', '< 3']), |
| ('2.4', ['>= 2.4', '< 3']), |
| ('2.4.5', ['>= 2.4.5', '< 3']), |
| ('0.0.0', ['< 1']), |
| ('0.0', ['< 1']), |
| ('0', ['< 1']), |
| ('0.0.5', ['>= 0.0.5', '< 0.0.6']), |
| ('0.5.0', ['>= 0.5.0', '< 0.6']), |
| ('0.5', ['>= 0.5', '< 0.6']), |
| ('1.0.45', ['>= 1.0.45', '< 2']), |
| |
| # Caret (Which is the same as unqualified) |
| ('^2', ['>= 2', '< 3']), |
| ('^2.4', ['>= 2.4', '< 3']), |
| ('^2.4.5', ['>= 2.4.5', '< 3']), |
| ('^0.0.0', ['< 1']), |
| ('^0.0', ['< 1']), |
| ('^0', ['< 1']), |
| ('^0.0.5', ['>= 0.0.5', '< 0.0.6']), |
| ('^0.5.0', ['>= 0.5.0', '< 0.6']), |
| ('^0.5', ['>= 0.5', '< 0.6']), |
| |
| # Multiple requirements |
| ('>= 1.2.3, < 1.4.7', ['>= 1.2.3', '< 1.4.7']), |
| ] |
| |
| for (data, expected) in cases: |
| with self.subTest(): |
| self.assertListEqual(convert(data), expected) |
| |
| |
| class CargoCfgTest(unittest.TestCase): |
| |
| def test_lex(self) -> None: |
| cases: T.List[T.Tuple[str, T.List[T.Tuple[TokenType, T.Optional[str]]]]] = [ |
| ('"unix"', [(TokenType.STRING, 'unix')]), |
| ('unix', [(TokenType.IDENTIFIER, 'unix')]), |
| ('not(unix)', [ |
| (TokenType.NOT, None), |
| (TokenType.LPAREN, None), |
| (TokenType.IDENTIFIER, 'unix'), |
| (TokenType.RPAREN, None), |
| ]), |
| ('any(unix, windows)', [ |
| (TokenType.ANY, None), |
| (TokenType.LPAREN, None), |
| (TokenType.IDENTIFIER, 'unix'), |
| (TokenType.COMMA, None), |
| (TokenType.IDENTIFIER, 'windows'), |
| (TokenType.RPAREN, None), |
| ]), |
| ('target_arch = "x86_64"', [ |
| (TokenType.IDENTIFIER, 'target_arch'), |
| (TokenType.EQUAL, None), |
| (TokenType.STRING, 'x86_64'), |
| ]), |
| ('all(target_arch = "x86_64", unix)', [ |
| (TokenType.ALL, None), |
| (TokenType.LPAREN, None), |
| (TokenType.IDENTIFIER, 'target_arch'), |
| (TokenType.EQUAL, None), |
| (TokenType.STRING, 'x86_64'), |
| (TokenType.COMMA, None), |
| (TokenType.IDENTIFIER, 'unix'), |
| (TokenType.RPAREN, None), |
| ]), |
| ] |
| for data, expected in cases: |
| with self.subTest(): |
| self.assertListEqual(list(cfg.lexer(data)), expected) |
| |
| def test_parse(self) -> None: |
| cases = [ |
| ('target_os = "windows"', cfg.Equal(cfg.Identifier("target_os"), cfg.String("windows"))), |
| ('target_arch = "x86"', cfg.Equal(cfg.Identifier("target_arch"), cfg.String("x86"))), |
| ('target_family = "unix"', cfg.Equal(cfg.Identifier("target_family"), cfg.String("unix"))), |
| ('any(target_arch = "x86", target_arch = "x86_64")', |
| cfg.Any( |
| [ |
| cfg.Equal(cfg.Identifier("target_arch"), cfg.String("x86")), |
| cfg.Equal(cfg.Identifier("target_arch"), cfg.String("x86_64")), |
| ])), |
| ('all(target_arch = "x86", target_os = "linux")', |
| cfg.All( |
| [ |
| cfg.Equal(cfg.Identifier("target_arch"), cfg.String("x86")), |
| cfg.Equal(cfg.Identifier("target_os"), cfg.String("linux")), |
| ])), |
| ('not(all(target_arch = "x86", target_os = "linux"))', |
| cfg.Not( |
| cfg.All( |
| [ |
| cfg.Equal(cfg.Identifier("target_arch"), cfg.String("x86")), |
| cfg.Equal(cfg.Identifier("target_os"), cfg.String("linux")), |
| ]))), |
| ] |
| for data, expected in cases: |
| with self.subTest(): |
| self.assertEqual(cfg.parse(iter(cfg.lexer(data))), expected) |
| |
| def test_ir_to_meson(self) -> None: |
| build = builder.Builder('') |
| HOST_MACHINE = build.identifier('host_machine') |
| |
| cases = [ |
| ('target_os = "windows"', |
| build.equal(build.method('system', HOST_MACHINE), |
| build.string('windows'))), |
| ('target_arch = "x86"', |
| build.equal(build.method('cpu_family', HOST_MACHINE), |
| build.string('x86'))), |
| ('target_family = "unix"', |
| build.equal(build.method('system', HOST_MACHINE), |
| build.string('unix'))), |
| ('not(target_arch = "x86")', |
| build.not_(build.equal( |
| build.method('cpu_family', HOST_MACHINE), |
| build.string('x86')))), |
| ('any(target_arch = "x86", target_arch = "x86_64")', |
| build.or_( |
| build.equal(build.method('cpu_family', HOST_MACHINE), |
| build.string('x86')), |
| build.equal(build.method('cpu_family', HOST_MACHINE), |
| build.string('x86_64')))), |
| ('any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")', |
| build.or_( |
| build.equal(build.method('cpu_family', HOST_MACHINE), |
| build.string('x86')), |
| build.or_( |
| build.equal(build.method('cpu_family', HOST_MACHINE), |
| build.string('x86_64')), |
| build.equal(build.method('cpu_family', HOST_MACHINE), |
| build.string('aarch64'))))), |
| ('all(target_arch = "x86", target_arch = "x86_64")', |
| build.and_( |
| build.equal(build.method('cpu_family', HOST_MACHINE), |
| build.string('x86')), |
| build.equal(build.method('cpu_family', HOST_MACHINE), |
| build.string('x86_64')))), |
| ('all(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")', |
| build.and_( |
| build.equal(build.method('cpu_family', HOST_MACHINE), |
| build.string('x86')), |
| build.and_( |
| build.equal(build.method('cpu_family', HOST_MACHINE), |
| build.string('x86_64')), |
| build.equal(build.method('cpu_family', HOST_MACHINE), |
| build.string('aarch64'))))), |
| ] |
| for data, expected in cases: |
| with self.subTest(): |
| value = cfg.ir_to_meson(cfg.parse(iter(cfg.lexer(data))), build) |
| self.assertEqual(value, expected) |
| |
| class CargoLockTest(unittest.TestCase): |
| def test_cargo_lock(self) -> None: |
| with tempfile.TemporaryDirectory() as tmpdir: |
| with open(os.path.join(tmpdir, 'Cargo.lock'), 'w', encoding='utf-8') as f: |
| f.write(textwrap.dedent('''\ |
| version = 3 |
| [[package]] |
| name = "foo" |
| version = "0.1" |
| source = "registry+https://github.com/rust-lang/crates.io-index" |
| checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" |
| [[package]] |
| name = "bar" |
| version = "0.1" |
| source = "git+https://github.com/gtk-rs/gtk-rs-core?branch=0.19#23c5599424cc75ec66618891c915d9f490f6e4c2" |
| ''')) |
| wraps = load_wraps(tmpdir, 'subprojects') |
| self.assertEqual(len(wraps), 2) |
| self.assertEqual(wraps[0].name, 'foo-0.1-rs') |
| self.assertEqual(wraps[0].directory, 'foo-0.1') |
| self.assertEqual(wraps[0].type, 'file') |
| self.assertEqual(wraps[0].get('method'), 'cargo') |
| self.assertEqual(wraps[0].get('source_url'), 'https://crates.io/api/v1/crates/foo/0.1/download') |
| self.assertEqual(wraps[0].get('source_hash'), '8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb') |
| self.assertEqual(wraps[1].name, 'bar-0.1-rs') |
| self.assertEqual(wraps[1].directory, 'bar') |
| self.assertEqual(wraps[1].type, 'git') |
| self.assertEqual(wraps[1].get('method'), 'cargo') |
| self.assertEqual(wraps[1].get('url'), 'https://github.com/gtk-rs/gtk-rs-core') |
| self.assertEqual(wraps[1].get('revision'), '23c5599424cc75ec66618891c915d9f490f6e4c2') |