diff --git a/codecov.yml b/codecov.yml index 561bf760e25..f418c3d13dc 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1 +1,3 @@ comment: false # Disable codecov PR comments -> leave only the checks +ignore: + - "test/performance" diff --git a/conan/test/assets/__init__.py b/conan/test/assets/__init__.py index c7f40f86eee..e69de29bb2d 100644 --- a/conan/test/assets/__init__.py +++ b/conan/test/assets/__init__.py @@ -1,16 +0,0 @@ -import os -import shutil - - -def copy_assets(src_folder, dst_folder, assets=None): - assets_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "files") - if src_folder: - src_folder = os.path.join(assets_path, src_folder) - assets = assets or os.listdir(src_folder) - for asset in assets: - s = os.path.join(src_folder, asset) - d = os.path.join(dst_folder, asset) - if os.path.isdir(s): - shutil.copytree(s, d) - else: - shutil.copy2(s, d) diff --git a/conan/test/assets/visual_project_files.py b/conan/test/assets/visual_project_files.py index 5db7b7cecdf..9b9f5ceb587 100644 --- a/conan/test/assets/visual_project_files.py +++ b/conan/test/assets/visual_project_files.py @@ -245,47 +245,9 @@ } ''' -main_file_17_2015 = ''' -//available in 2015 with c++17 -#include - -namespace test::mytest { -struct mystruct {}; -}; -int main(){ -test::mytest::mystruct t; -} -''' - - -main_file_17_2017 = ''' -//only available in visual 2017 with c++17 -#include - -auto hello(){ - return 2; -} - -int main() -{ - if constexpr(true) - std::cout << "Hello World!" << std::endl; - return 0; -} -''' - - -def get_vs_project_files(std=False): - if not std: - main = main_file - elif std == "cpp17_2015": - main = main_file_17_2015 - elif std == "cpp17_2017": - main = main_file_17_2017 - else: - raise Exception("Incorrect std") +def get_vs_project_files(): return {"MyProject.sln": sln_file, "MyProject/MyProject.vcxproj": vcxproj_file, "MyProject/MyProject.vcxproj.filters": filters_file, - "MyProject/main.cpp": main} + "MyProject/main.cpp": main_file} diff --git a/conan/test/utils/mocks.py b/conan/test/utils/mocks.py index 9638b4ad877..cd4e9f45eab 100644 --- a/conan/test/utils/mocks.py +++ b/conan/test/utils/mocks.py @@ -9,25 +9,6 @@ from conan.internal.model.options import Options -class LocalDBMock(object): - - def __init__(self, user=None, access_token=None, refresh_token=None): - self.user = user - self.access_token = access_token - self.refresh_token = refresh_token - - def get_login(self, _): - return self.user, self.access_token, self.refresh_token - - def get_username(self, _): - return self.user - - def store(self, user, access_token, refresh_token, _): - self.user = user - self.access_token = access_token - self.refresh_token = refresh_token - - class RedirectedInputStream: """ Mock for testing. If get_username or get_password is requested will raise @@ -67,19 +48,6 @@ def possible_values(self): return defaultdict(lambda: []) -class MockCppInfo(object): - def __init__(self): - self.bin_paths = [] - self.lib_paths = [] - self.include_paths = [] - self.libs = [] - self.cflags = [] - self.cxxflags = [] - self.defines = [] - self.frameworks = [] - self.framework_paths = [] - - class ConanFileMock(ConanFile): def __init__(self, settings=None, options=None, runner=None, display_name=""): self.display_name = display_name diff --git a/conan/test/utils/tools.py b/conan/test/utils/tools.py index b143a7502f7..d0c44a9eac2 100644 --- a/conan/test/utils/tools.py +++ b/conan/test/utils/tools.py @@ -41,7 +41,6 @@ from conan.internal.model.profile import Profile from conan.api.model import RecipeReference from conan.internal.model.settings import Settings -from conan.test.assets import copy_assets from conan.test.assets.genconanfile import GenConanfile from conan.test.utils.artifactory import ArtifactoryServer from conan.test.utils.mocks import RedirectedInputStream @@ -661,9 +660,6 @@ def save(self, files, path=None, clean_first=False): def save_home(self, files): self.save(files, path=self.cache_folder) - def copy_assets(self, origin_folder, assets=None): - copy_assets(origin_folder, self.current_folder, assets) - # Higher level operations def remove_all(self): self.run("remove '*' -c") diff --git a/conans/client/rest/rest_client_v2.py b/conans/client/rest/rest_client_v2.py index 97ff280153a..45ca3f1927f 100644 --- a/conans/client/rest/rest_client_v2.py +++ b/conans/client/rest/rest_client_v2.py @@ -277,27 +277,6 @@ def get_package(self, pref, dest_folder, metadata, only_metadata): result.update({fn: os.path.join(dest_folder, fn) for fn in files}) return result - @staticmethod - def _is_dir(path, files): - if path == ".": - return True - for the_file in files["files"]: - if path == the_file: - return False - elif the_file.startswith(path): - return True - raise NotFoundException("The specified path doesn't exist") - - @staticmethod - def _list_dir_contents(path, files): - ret = [] - for the_file in files["files"]: - if path == "." or the_file.startswith(path): - tmp = the_file[len(path) - 1:].split("/", 1)[0] - if tmp not in ret: - ret.append(tmp) - return sorted(ret) - def _upload_files(self, files, urls, ref): failed = [] uploader = FileUploader(self.requester, self.verify_ssl, self._config) diff --git a/conans/client/rest/rest_routes.py b/conans/client/rest/rest_routes.py index 7dab1f0779a..b2059162deb 100644 --- a/conans/client/rest/rest_routes.py +++ b/conans/client/rest/rest_routes.py @@ -31,22 +31,10 @@ def recipe_revisions(self): def recipe_revision_file(self): return '%s/files/{path}' % self.recipe_revision - @property - def packages(self): - return '%s/packages' % self.recipe - @property def packages_revision(self): return '%s/packages' % self.recipe_revision - @property - def package(self): - return '%s/{package_id}' % self.packages - - @property - def package_files(self): - return '%s/files' % self.package - @property def package_recipe_revision(self): """Route for a package specifying the recipe revision but not the package revision""" diff --git a/test/functional/toolchains/microsoft/test_msbuild.py b/test/functional/toolchains/microsoft/test_msbuild.py index c476e07c0ae..0754e2e33fa 100644 --- a/test/functional/toolchains/microsoft/test_msbuild.py +++ b/test/functional/toolchains/microsoft/test_msbuild.py @@ -488,12 +488,12 @@ def check_toolchain_win(self, compiler, version, runtime, cppstd, ide_version): check_vs_runtime("Release/MyApp.exe", client, ide_version, build_type="Release", static_runtime=static_runtime) - @pytest.mark.tool("cmake") - @pytest.mark.tool("visual_studio", "16") + @pytest.mark.tool("cmake", "3.23") + @pytest.mark.tool("visual_studio", "17") def test_toolchain_win_debug(self): client = TestClient(path_with_spaces=False) settings = [("compiler", "msvc"), - ("compiler.version", "192"), + ("compiler.version", "193"), ("compiler.runtime", "dynamic"), ("build_type", "Debug"), ("arch", "x86_64")] @@ -514,27 +514,27 @@ def test_toolchain_win_debug(self): # Run the configure corresponding to this test case client.run("build . %s" % (settings, )) assert "conanfile.py: MSBuildToolchain created conantoolchain_debug_x64.props" in client.out - assert f"conanvcvars.bat: Activating environment Visual Studio 16" in client.out + assert f"conanvcvars.bat: Activating environment Visual Studio 17" in client.out assert "[vcvarsall.bat] Environment initialized for: 'x64'" in client.out self._run_app(client, "x64", "Debug") assert "Hello World Debug" in client.out - check_exe_run(client.out, "main", "msvc", "192", "Debug", "x86_64", "14", + check_exe_run(client.out, "main", "msvc", "19", "Debug", "x86_64", "14", {"DEFINITIONS_BOTH": 'True', "DEFINITIONS_BOTH2": "True", "DEFINITIONS_BOTH_INT": "123", "DEFINITIONS_CONFIG": 'Debug', "DEFINITIONS_CONFIG2": 'Debug', "DEFINITIONS_CONFIG_INT": "234"}) - check_vs_runtime("x64/Debug/MyApp.exe", client, "16", build_type="Debug") + check_vs_runtime("x64/Debug/MyApp.exe", client, "17", build_type="Debug") - @pytest.mark.tool("cmake") - @pytest.mark.tool("visual_studio", "16") + @pytest.mark.tool("cmake", "3.23") + @pytest.mark.tool("visual_studio", "17") def test_toolchain_win_multi(self): - ide_version = "16" + ide_version = "17" client = TestClient(path_with_spaces=False) settings = [("compiler", "msvc"), - ("compiler.version", "192"), + ("compiler.version", "193"), ("compiler.cppstd", "17"), ("compiler.runtime", "static")] @@ -582,7 +582,7 @@ def test_toolchain_win_multi(self): assert "[vcvarsall.bat] Environment initialized for: 'x64'" in client.out self._run_app(client, arch, build_type, shared) - check_exe_run(client.out, "main", "msvc", "192", build_type, arch, "17", + check_exe_run(client.out, "main", "msvc", "19", build_type, arch, "17", {"DEFINITIONS_BOTH": "True", "DEFINITIONS_CONFIG": build_type}) diff --git a/test/integration/conanfile/runner_test.py b/test/integration/conanfile/runner_test.py index add79668766..28ce9c9b99b 100644 --- a/test/integration/conanfile/runner_test.py +++ b/test/integration/conanfile/runner_test.py @@ -1,20 +1,9 @@ -import os import textwrap -import unittest from conan.test.utils.tools import TestClient -class RunnerTest(unittest.TestCase): - - def _install_and_build(self, client, conanfile_text): - files = {"conanfile.py": conanfile_text} - test_folder = os.path.join(client.current_folder, "test_folder") - self.assertFalse(os.path.exists(test_folder)) - client.save(files) - client.run("install .") - client.run("build .") - return client +class TestRunner: def test_ignore_error(self): conanfile = """from conan import ConanFile @@ -26,7 +15,7 @@ def source(self): client = TestClient() client.save({"conanfile.py": conanfile}) client.run("source .") - self.assertIn("RETCODE True", client.out) + assert "RETCODE True" in client.out def test_runner_capture_output(self): conanfile = textwrap.dedent(""" @@ -38,7 +27,7 @@ def source(self): client = TestClient() client.save({"conanfile.py": conanfile}) client.run("source .") - self.assertIn("hello Conan!", client.out) + assert "hello Conan!" in client.out def test_custom_stream_error(self): # https://github.com/conan-io/conan/issues/7888 @@ -54,7 +43,7 @@ def source(self): client = TestClient() client.save({"conanfile.py": conanfile}) client.run("source .") - self.assertIn('conanfile.py: Buffer got msgs Hello', client.out) + assert 'conanfile.py: Buffer got msgs Hello' in client.out def test_custom_stream_stderr(self): conanfile = textwrap.dedent(""" @@ -69,4 +58,4 @@ def source(self): client = TestClient() client.save({"conanfile.py": conanfile}) client.run("source .") - self.assertIn('conanfile.py: Buffer got stderr msgs Hello', client.out) + assert 'conanfile.py: Buffer got stderr msgs Hello' in client.out diff --git a/test/integration/environment/test_env.py b/test/integration/environment/test_env.py index a3b506ee6d6..293371d284d 100644 --- a/test/integration/environment/test_env.py +++ b/test/integration/environment/test_env.py @@ -110,14 +110,14 @@ def build(self): client.run("install . -s:b os=Windows -s:h os=Linux --build=missing") # Run the BUILD environment if platform.system() == "Windows": - cmd = environment_wrap_command(ConanFileMock(),"conanbuildenv", client.current_folder, "mycmake.bat") + cmd = environment_wrap_command(ConanFileMock(), "conanbuildenv", client.current_folder, "mycmake.bat") client.run_command(cmd) assert "MYCMAKE=Windows!!" in client.out assert "MYOPENSSL=Windows!!" in client.out # Run the RUN environment if platform.system() != "Windows": - cmd = environment_wrap_command(ConanFileMock(),"conanrunenv", client.current_folder, + cmd = environment_wrap_command(ConanFileMock(), "conanrunenv", client.current_folder, "mygtest.sh && .{}myrunner.sh".format(os.sep)) client.run_command(cmd, assert_error=not gtest_run_true) if gtest_run_true: @@ -210,7 +210,7 @@ def generate(self): client.run("install . -pr=myprofile") # Run the BUILD environment ext = "bat" if platform.system() == "Windows" else "sh" # TODO: Decide on logic .bat vs .sh - cmd = environment_wrap_command(ConanFileMock(),"conanbuildenv", client.current_folder, + cmd = environment_wrap_command(ConanFileMock(), "conanbuildenv", client.current_folder, "mycompiler.{}".format(ext)) client.run_command(cmd) assert "MYCOMPILER!!" in client.out @@ -621,14 +621,13 @@ class Pkg(ConanFile): assert os.path.isfile(os.path.join(client.current_folder, "conanrunenv.ps1")) assert not os.path.isfile(os.path.join(client.current_folder, "conanrunenv.bat")) for i in range(num_deps): - cmd = environment_wrap_command(ConanFileMock(),"conanrunenv", client.current_folder, + cmd = environment_wrap_command(ConanFileMock(), "conanrunenv", client.current_folder, "mycompiler{}.bat".format(i)) - if num_deps > 50: # to be safe if we change the "num_deps" number - client.run_command(cmd, assert_error=True) - assert "is not recognized as an internal" in client.out - else: - client.run_command(cmd) - assert "MYTOOL {}!!".format(i) in client.out + # if num_deps > 50: # to be safe if we change the "num_deps" number + # client.run_command(cmd, assert_error=True) + # assert "is not recognized as an internal" in client.out + client.run_command(cmd) + assert "MYTOOL {}!!".format(i) in client.out # Test .bats now client.save({"conanfile.py": conanfile}, clean_first=True) @@ -636,14 +635,14 @@ class Pkg(ConanFile): assert not os.path.isfile(os.path.join(client.current_folder, "conanrunenv.ps1")) assert os.path.isfile(os.path.join(client.current_folder, "conanrunenv.bat")) for i in range(num_deps): - cmd = environment_wrap_command(ConanFileMock(),"conanrunenv", client.current_folder, + cmd = environment_wrap_command(ConanFileMock(), "conanrunenv", client.current_folder, "mycompiler{}.bat".format(i)) - if num_deps > 50: # to be safe if we change the "num_deps" number - client.run_command(cmd, assert_error=True) - # This also fails, but without an error message (in my terminal, it kills the terminal!) - else: - client.run_command(cmd) - assert "MYTOOL {}!!".format(i) in client.out + # if num_deps > 50: # to be safe if we change the "num_deps" number + # client.run_command(cmd, assert_error=True) + # # This also fails, but without an error message (in my terminal, it kills the terminal!) + # else: + client.run_command(cmd) + assert "MYTOOL {}!!".format(i) in client.out def test_profile_build_env_spaces(): diff --git a/test/integration/graph/core/graph_manager_base.py b/test/integration/graph/core/graph_manager_base.py index 97d85b96f49..23dcdd9dfd6 100644 --- a/test/integration/graph/core/graph_manager_base.py +++ b/test/integration/graph/core/graph_manager_base.py @@ -67,7 +67,7 @@ class Alias(ConanFile): self._cache_recipe(ref, conanfile) @staticmethod - def recipe_consumer(reference=None, requires=None, build_requires=None, tool_requires=None): + def recipe_consumer(reference=None, requires=None, build_requires=None): path = temp_folder() path = os.path.join(path, "conanfile.py") conanfile = GenConanfile() @@ -80,9 +80,6 @@ def recipe_consumer(reference=None, requires=None, build_requires=None, tool_req if build_requires: for r in build_requires: conanfile.with_build_requires(r) - if tool_requires: - for r in tool_requires: - conanfile.with_tool_requires(r) save(path, str(conanfile)) return path diff --git a/test/integration/graph/core/graph_manager_test.py b/test/integration/graph/core/graph_manager_test.py index 095dfcc707a..4e226b7bbb0 100644 --- a/test/integration/graph/core/graph_manager_test.py +++ b/test/integration/graph/core/graph_manager_test.py @@ -1,7 +1,6 @@ import pytest from parameterized import parameterized -from conans.client.graph.graph import BINARY_SKIP from conans.client.graph.graph_error import GraphMissingError, GraphLoopError, GraphConflictError from conan.errors import ConanException from test.integration.graph.core.graph_manager_base import GraphManagerTest @@ -11,24 +10,17 @@ def _check_transitive(node, transitive_deps): values = list(node.transitive_deps.values()) - if len(values) != len(transitive_deps): - values = [r.require.ref for r in values] - raise Exception("{}: Number of deps don't match \n{}!=\n{}".format(node, values, - transitive_deps)) + assert len(values) == len(transitive_deps), f"{node}: Number of deps don't match " \ + f"\n{[r.require.ref for r in values]}" \ + f"!=\n{transitive_deps}" for v1, v2 in zip(values, transitive_deps): - if v1.node is not v2[0]: - raise Exception(f"{v1.node}!={v2[0]}") - if v1.require.headers is not v2[1]: - raise Exception(f"{v1.node}!={v2[0]} headers") - if v1.require.libs is not v2[2]: - raise Exception(f"{v1.node}!={v2[0]} libs") - if v1.require.build is not v2[3]: - raise Exception(f"{v1.node}!={v2[0]} build") - if v1.require.run is not v2[4]: - raise Exception(f"{v1.node}!={v2[0]} run") - if len(v2) > 5: - assert v1.require.package_id_mode is v2[5] + assert v1.node is v2[0], f"{v1.node}!={v2[0]}" + assert v1.require.headers is v2[1], f"{v1.node}!={v2[0]} headers" + assert v1.require.libs is v2[2], f"{v1.node}!={v2[0]} libs" + assert v1.require.build is v2[3], f"{v1.node}!={v2[0]} build" + assert v1.require.run is v2[4], f"{v1.node}!={v2[0]} run" + assert len(v2) <= 5 class TestLinear(GraphManagerTest): diff --git a/test/integration/remote/auth_bearer_test.py b/test/integration/remote/auth_bearer_test.py index b5d05e531fa..19008a2c939 100644 --- a/test/integration/remote/auth_bearer_test.py +++ b/test/integration/remote/auth_bearer_test.py @@ -1,20 +1,10 @@ -import unittest - from bottle import request +from conan.test.assets.genconanfile import GenConanfile from conan.test.utils.tools import TestClient, TestServer -conanfile = """ -from conan import ConanFile - -class OpenSSLConan(ConanFile): - name = "hello" - version = "0.1" -""" - - -class AuthorizationHeaderSpy(object): +class AuthorizationHeaderSpy: """ Generic plugin to handle Authorization header. Must be extended and implement some abstract methods in subclasses""" @@ -24,50 +14,32 @@ class AuthorizationHeaderSpy(object): def __init__(self): self.auths = [] - def apply(self, callback, context): # @UnusedVariable + def apply(self, callback, context): # noqa auth = request.headers.get("Authorization") name = callback.__name__ self.auths.append((name, auth)) return callback -class ReturnHandlerPlugin(object): - - name = 'ReturnHandlerPluginSpy' - api = 2 - - def apply(self, callback, _): - """Apply plugin""" - def wrapper(*args, **kwargs): - """Capture possible exceptions to manage the return""" - result = callback(*args, **kwargs) - if isinstance(result, dict): - for k, v in result.items(): - result[k] = v.split("?signature=")[0] - return result - return wrapper - - -class AuthorizeBearerTest(unittest.TestCase): +class TestAuthorizeBearer: def test_basic(self): auth = AuthorizationHeaderSpy() server = TestServer(plugins=[auth]) - servers = {"default": server} - client = TestClient(servers=servers, inputs=["admin", "password"]) - client.save({"conanfile.py": conanfile}) + client = TestClient(servers={"default": server}, inputs=["admin", "password"]) + client.save({"conanfile.py": GenConanfile("hello", "0.1")}) client.run("export . --user=lasote --channel=stable") errors = client.run("upload hello/0.1@lasote/stable -r default --only-recipe") - self.assertFalse(errors) + assert not errors expected_calls = [('get_recipe_revisions_references', None), ('check_credentials', None), ('authenticate', 'Basic'), ('upload_recipe_file', 'Bearer')] - self.assertEqual(len(expected_calls), len(auth.auths)) + assert len(expected_calls) == len(auth.auths) for i, (method, auth_type) in enumerate(expected_calls): real_call = auth.auths[i] - self.assertEqual(method, real_call[0]) + assert method == real_call[0] if auth_type: - self.assertIn(auth_type, real_call[1]) + assert auth_type in real_call[1] diff --git a/test/unittests/tools/files/test_downloads.py b/test/unittests/tools/files/test_downloads.py index 165001b46d2..25019d08a2e 100644 --- a/test/unittests/tools/files/test_downloads.py +++ b/test/unittests/tools/files/test_downloads.py @@ -1,5 +1,6 @@ import os import shutil +from unittest import mock import pytest @@ -13,27 +14,31 @@ from conans.util.files import save, load, chdir, mkdir -@pytest.mark.skip(reason="This causes more troubles than benefits, external ftp download is testing " - "very little conan code, mostly python") +@mock.patch('ftplib.FTP', autospec=True) class TestFTP: - def test_ftp_auth(self): - filename = "/pub/example/readme.txt" - conanfile = ConanFileMock() - ftp_download(conanfile, "test.rebex.net", filename, "demo", "password") - assert os.path.exists(os.path.basename(filename)) - - def test_ftp_invalid_path(self): + def test_ftp_auth(self, ftp_mock): + ftp_object = ftp_mock.return_value + filename = "/pub/example/readme2.txt" + with chdir(temp_folder()): # To not pollute the project + ftp_download(None, "test.rebex.net", filename, "demo", "password") + ftp_mock.assert_called_with('test.rebex.net') + assert ftp_object.login.called + ftp_object.cwd.assert_called_with('/pub/example') + + def test_ftp_invalid_path(self, ftp_mock): + ftp_object = ftp_mock.return_value + ftp_object.cwd.side_effect = Exception("550 The system cannot find the file specified.") with pytest.raises(ConanException) as exc: - conanfile = ConanFileMock() - ftp_download(conanfile, "test.rebex.net", "invalid-file", "demo", "password") + ftp_download(None, "test.rebex.net", "/path/invalid-file", "demo", "password") assert "550 The system cannot find the file specified." in str(exc.value) assert not os.path.exists("invalid-file") - def test_ftp_invalid_auth(self): + def test_ftp_invalid_auth(self, ftp_mock): + ftp_object = ftp_mock.return_value + ftp_object.login.side_effect = Exception("530 User cannot log in.") with pytest.raises(ConanException) as exc: - conanfile = ConanFileMock() - ftp_download(conanfile, "test.rebex.net", "readme.txt", "demo", "invalid") + ftp_download(None, "test.rebex.net", "readme.txt", "demo", "invalid") assert "530 User cannot log in." in str(exc.value) assert not os.path.exists("readme.txt") diff --git a/test/unittests/tools/gnu/autotoolschain_test.py b/test/unittests/tools/gnu/autotoolschain_test.py index eec8d7cce0e..43d79fc4319 100644 --- a/test/unittests/tools/gnu/autotoolschain_test.py +++ b/test/unittests/tools/gnu/autotoolschain_test.py @@ -126,9 +126,8 @@ def test_get_gnu_triplet_for_cross_building_raise_error(): conanfile.settings_build = MockSettings({"os": "Solaris", "arch": "x86"}) with pytest.raises(ConanException) as conan_error: AutotoolsToolchain(conanfile) - msg = "'compiler' parameter for 'get_gnu_triplet()' is not specified and " \ - "needed for os=Windows" - assert msg == str(conan_error.value) + msg = "'compiler' parameter for 'get_gnu_triplet()' is not specified and needed for os=Windows" + assert msg == str(conan_error.value) def test_compilers_mapping(): diff --git a/test/unittests/tools/gnu/test_gnutoolchain.py b/test/unittests/tools/gnu/test_gnutoolchain.py index 48fffbe9420..b18e2119f6f 100644 --- a/test/unittests/tools/gnu/test_gnutoolchain.py +++ b/test/unittests/tools/gnu/test_gnutoolchain.py @@ -124,9 +124,8 @@ def test_get_gnu_triplet_for_cross_building_raise_error(): conanfile.settings_build = MockSettings({"os": "Solaris", "arch": "x86"}) with pytest.raises(ConanException) as conan_error: GnuToolchain(conanfile) - msg = "'compiler' parameter for 'get_gnu_triplet()' is not specified and " \ - "needed for os=Windows" - assert msg == str(conan_error.value) + msg = "'compiler' parameter for 'get_gnu_triplet()' is not specified and needed for os=Windows" + assert msg == str(conan_error.value) def test_compilers_mapping():