Exemplo n.º 1
0
def test_webkit_cached_deps():
    # regression test for a bug in caching deps
    config = copy.copy(global_config)
    config.skip_sdk = True
    config.include_toolchain_dependencies = False
    config.include_dependencies = True
    webkit_native = target_manager.get_target_raw("qtwebkit-native").project_class
    webkit_cheri = target_manager.get_target_raw("qtwebkit-mips64-purecap").project_class
    webkit_mips = target_manager.get_target_raw("qtwebkit-mips64-hybrid").project_class
    # Check that the deps are not cached yet
    _check_deps_not_cached((webkit_native, webkit_cheri, webkit_mips))
    assert inspect.getattr_static(webkit_native, "dependencies") == ["qtbase", "icu4c", "libxml2", "sqlite"]
    assert inspect.getattr_static(webkit_cheri, "dependencies") == ["qtbase", "icu4c", "libxml2", "sqlite"]
    assert inspect.getattr_static(webkit_mips, "dependencies") == ["qtbase", "icu4c", "libxml2", "sqlite"]

    cheri_target_names = list(sorted(webkit_cheri.all_dependency_names(config)))
    assert cheri_target_names == ["cheribsd-mips64-purecap", "icu4c-mips64-purecap", "icu4c-native",
                                  "libxml2-mips64-purecap", "llvm-native", "qtbase-mips64-purecap",
                                  "sqlite-mips64-purecap"]
    _check_deps_not_cached([webkit_native, webkit_mips])
    _check_deps_cached([webkit_cheri])
    mips_target_names = list(sorted(webkit_mips.all_dependency_names(config)))
    assert mips_target_names == ["cheribsd-mips64-hybrid", "icu4c-mips64-hybrid", "icu4c-native",
                                 "libxml2-mips64-hybrid", "llvm-native", "qtbase-mips64-hybrid", "sqlite-mips64-hybrid"]
    _check_deps_cached([webkit_cheri, webkit_mips])
    _check_deps_not_cached([webkit_native])

    native_target_names = list(sorted(webkit_native.all_dependency_names(config)))
    assert native_target_names == ["icu4c-native", "libxml2-native", "qtbase-native", "sqlite-native"]
    _check_deps_cached([webkit_cheri, webkit_mips, webkit_native])
    assert inspect.getattr_static(webkit_native, "dependencies") == ["qtbase", "icu4c", "libxml2", "sqlite"]
    assert inspect.getattr_static(webkit_cheri, "dependencies") == ["qtbase", "icu4c", "libxml2", "sqlite"]
    assert inspect.getattr_static(webkit_mips, "dependencies") == ["qtbase", "icu4c", "libxml2", "sqlite"]
def test_cheri_mips_purecap_alias():
    # # For other targets we currently keep -cheri suffixed aliases for the -mips-purecap versions
    config = _parse_config_file_and_args(
        b'{"qtbase-mips-purecap/build-directory": "/some/build/dir"}')
    # Check that cheribsd-cheri is a (deprecated) target alias for cheribsd-mips-cheri
    # We should load config options for that target from
    qtbase_cheri = target_manager.get_target_raw(
        "qtbase-mips-purecap").get_or_create_project(None, config)  # type:
    # BuildCHERIBSD
    assert str(qtbase_cheri.build_dir) == "/some/build/dir"
    qtbase_mips_purecap = target_manager.get_target_raw(
        "qtbase-mips-purecap").get_or_create_project(None, config)  # type:
    # BuildCHERIBSD
    assert str(qtbase_mips_purecap.build_dir) == "/some/build/dir"
def test_disk_image_path(target, expected_name):
    config = _parse_arguments([])
    project = target_manager.get_target_raw(target).get_or_create_project(
        None, config)
    assert isinstance(project, _BuildDiskImageBase)
    assert str(project.disk_image_path) == str(config.output_root /
                                               expected_name)
def test_target_aliases_default_target(target_name, resolved_target):
    # Check that only some targets (e.g. llvm) have a default target and that we have to explicitly
    # specify the target name for e.g. cheribsd-* run-*, etc
    if resolved_target is None:
        # The target should not exist in the list of targets accepted on the command line
        assert target_name not in target_manager.target_names
        # However, if we use get_target_raw we should get the TargetAlias
        assert isinstance(target_manager.get_target_raw(target_name), MultiArchTargetAlias)
        assert target_manager.get_target_raw(target_name).project_class.default_architecture is None
    else:
        assert target_name in target_manager.target_names
        raw_target = target_manager.get_target_raw(target_name)
        assert isinstance(raw_target, MultiArchTargetAlias) or raw_target.name == resolved_target
        target = target_manager.get_target(target_name, None, _parse_arguments([]),
                                           caller="test_target_aliases_default_target")
        assert target.name == resolved_target
def test_kernconf():
    # Parse args once to ensure target_manager is initialized
    # check default values
    config = _parse_arguments([])
    cheribsd_cheri = target_manager.get_target_raw(
        "cheribsd-cheri").get_or_create_project(None, config)  # type:
    # BuildCHERIBSD
    cheribsd_mips = target_manager.get_target_raw(
        "cheribsd-mips-nocheri").get_or_create_project(None, config)  # type:
    # BuildCHERIBSD
    freebsd_mips = target_manager.get_target_raw(
        "freebsd-mips").get_or_create_project(None,
                                              config)  # type: BuildFreeBSD
    freebsd_native = target_manager.get_target_raw(
        "freebsd-amd64").get_or_create_project(None,
                                               config)  # type: BuildFreeBSD
    assert config.freebsd_kernconf is None
    assert freebsd_mips.kernel_config == "MALTA64"
    assert cheribsd_cheri.kernel_config == "CHERI_MALTA64"
    assert freebsd_native.kernel_config == "GENERIC"

    # Check that --kernconf is used as the fallback
    config = _parse_arguments(
        ["--kernconf=LINT", "--freebsd-mips/kernel-config=NOTMALTA64"])
    assert config.freebsd_kernconf == "LINT"
    attr = inspect.getattr_static(freebsd_mips, "kernel_config")
    # previously we would replace the command line attribute with a string -> check this is no longer true
    assert isinstance(attr, JsonAndCommandLineConfigOption)
    assert freebsd_mips.kernel_config == "NOTMALTA64"
    assert cheribsd_cheri.kernel_config == "LINT"
    assert freebsd_native.kernel_config == "LINT"

    config = _parse_arguments(
        ["--kernconf=LINT", "--cheribsd-cheri/kernel-config=SOMETHING"])
    assert config.freebsd_kernconf == "LINT"
    assert freebsd_mips.kernel_config == "LINT"
    assert cheribsd_cheri.kernel_config == "SOMETHING"
    assert freebsd_native.kernel_config == "LINT"

    config = _parse_arguments(
        ["--kernconf=GENERIC", "--cheribsd/kernel-config=SOMETHING_ELSE"])
    assert config.freebsd_kernconf == "GENERIC"
    assert cheribsd_cheri.kernel_config == "SOMETHING_ELSE"
    assert cheribsd_mips.kernel_config == "SOMETHING_ELSE"
    assert freebsd_mips.kernel_config == "GENERIC"
    assert freebsd_native.kernel_config == "GENERIC"
def test_target_alias():
    config = _parse_config_file_and_args(
        b'{"cheribsd-cheri/mfs-root-image": "/some/image"}')
    # Check that cheribsd-cheri is a (deprecated) target alias for cheribsd-mips-cheri
    # We should load config options for that target from
    cheribsd_cheri = target_manager.get_target_raw(
        "cheribsd-cheri").get_or_create_project(None, config)  # type:
    # BuildCHERIBSD
    assert str(cheribsd_cheri.mfs_root_image) == "/some/image"
    cheribsd_mips_hybrid = target_manager.get_target_raw(
        "cheribsd-mips-hybrid").get_or_create_project(None, config)  #
    # type: BuildCHERIBSD
    assert str(cheribsd_mips_hybrid.mfs_root_image) == "/some/image"
    # Try again with the other key:
    config = _parse_config_file_and_args(
        b'{"cheribsd-mips-hybrid/mfs-root-image": "/some/image"}')
    # Check that cheribsd-cheri is a (deprecated) target alias for cheribsd-mips-cheri
    # We should load config options for that target from
    cheribsd_cheri = target_manager.get_target_raw(
        "cheribsd-cheri").get_or_create_project(None, config)  # type:
    # BuildCHERIBSD
    assert str(cheribsd_cheri.mfs_root_image) == "/some/image"
    cheribsd_mips_hybrid = target_manager.get_target_raw(
        "cheribsd-mips-hybrid").get_or_create_project(None, config)  #
    # type: BuildCHERIBSD
    assert str(cheribsd_mips_hybrid.mfs_root_image) == "/some/image"

    # Check command line aliases:
    config = _parse_config_file_and_args(
        b'{"cheribsd-cheri/mfs-root-image": "/json/value"}',
        "--cheribsd-cheri/mfs-root-image=/command/line/value")
    # Check that cheribsd-cheri is a (deprecated) target alias for cheribsd-mips-cheri
    # We should load config options for that target from
    cheribsd_cheri = target_manager.get_target_raw(
        "cheribsd-cheri").get_or_create_project(None, config)  # type:
    # BuildCHERIBSD
    assert str(cheribsd_cheri.mfs_root_image) == "/command/line/value"
    cheribsd_mips_hybrid = target_manager.get_target_raw(
        "cheribsd-mips-hybrid").get_or_create_project(None, config)  #
    # type: BuildCHERIBSD
    assert str(cheribsd_mips_hybrid.mfs_root_image) == "/command/line/value"

    config = _parse_config_file_and_args(
        b'{"cheribsd-cheri/mfs-root-image": "/json/value"}',
        "--cheribsd-mips-hybrid/mfs-root-image=/command/line/value")
    # Check that cheribsd-cheri is a (deprecated) target alias for cheribsd-mips-cheri
    # We should load config options for that target from
    cheribsd_cheri = target_manager.get_target_raw(
        "cheribsd-cheri").get_or_create_project(None,
                                                config)  # type: BuildCHERIBSD
    assert str(cheribsd_cheri.mfs_root_image) == "/command/line/value"
    cheribsd_mips_hybrid = target_manager.get_target_raw(
        "cheribsd-mips-hybrid").get_or_create_project(
            None, config)  # type: BuildCHERIBSD
    assert str(cheribsd_mips_hybrid.mfs_root_image) == "/command/line/value"
 def check_libunwind_path(path, target_name):
     tgt = target_manager.get_target_raw(target_name).get_or_create_project(
         None, config)
     for i in tgt.configure_args:
         if i.startswith("-DLIBUNWIND_PATH="):
             assert i == ("-DLIBUNWIND_PATH=" +
                          str(path)), tgt.configure_args
             return
     assert False, "Should have found -DLIBUNWIND_PATH= in " + str(
         tgt.configure_args)
Exemplo n.º 8
0
def test_webkit_cached_deps():
    # regression test for a bug in caching deps
    config = copy.copy(global_config)
    config.skip_sdk = True
    webkit_native = target_manager.get_target_raw(
        "qtwebkit-native").project_class
    webkit_cheri = target_manager.get_target_raw(
        "qtwebkit-mips-purecap").project_class
    webkit_mips = target_manager.get_target_raw(
        "qtwebkit-mips-hybrid").project_class
    # Check that the deps are not cached yet
    _check_deps_not_cached((webkit_native, webkit_cheri, webkit_mips))

    cheri_target_names = list(sorted(
        webkit_cheri.all_dependency_names(config)))
    assert cheri_target_names == [
        "icu4c-mips-purecap", "icu4c-native", "libxml2-mips-purecap",
        "qtbase-mips-purecap", "sqlite-mips-purecap"
    ]
    _check_deps_not_cached([webkit_native, webkit_mips])
    _check_deps_cached([webkit_cheri])

    mips_target_names = list(sorted(webkit_mips.all_dependency_names(config)))
    assert mips_target_names == [
        "icu4c-mips-hybrid", "icu4c-native", "libxml2-mips-hybrid",
        "qtbase-mips-hybrid", "sqlite-mips-hybrid"
    ]
    _check_deps_cached([webkit_cheri, webkit_mips])
    _check_deps_not_cached([webkit_native])

    native_target_names = list(
        sorted(webkit_native.all_dependency_names(config)))
    assert native_target_names == [
        "icu4c-native", "libxml2-native", "qtbase-native", "sqlite-native"
    ]
    _check_deps_cached([webkit_cheri, webkit_mips, webkit_native])
def test_freebsd_toolchains(target, expected_path, kind: FreeBSDToolchainKind,
                            extra_args):
    args = ["--" + target + "/toolchain", kind.value]
    args.extend(extra_args)
    config = _parse_arguments(args)
    expected_path = expected_path.replace("$OUTPUT$", str(config.output_root))
    project = target_manager.get_target_raw(target).get_or_create_project(
        None, config)
    assert isinstance(project, BuildFreeBSD)
    assert str(project.CC) == str(expected_path)
    if kind == FreeBSDToolchainKind.BOOTSTRAP:
        assert "XCC" not in project.buildworld_args.env_vars
        assert "XCC=" not in project.kernel_make_args_for_config(
            "GENERIC", None).env_vars
    else:
        assert project.buildworld_args.env_vars.get("XCC",
                                                    None) == expected_path
        assert project.kernel_make_args_for_config(
            "GENERIC", None).env_vars.get("XCC", None) == expected_path
def test_config_file_include():
    with tempfile.TemporaryDirectory() as d:
        config_dir = Path(d)
        (config_dir /
         "128-common.json").write_bytes(b'{ "output-root": "/output128" }')
        (config_dir /
         "256-common.json").write_bytes(b'{ "output-root": "/output256" }')
        (config_dir / "common.json"
         ).write_bytes(b'{ "source-root": "/this/is/a/unit/test" }')

        # Check that the config file is parsed:
        result = _get_config_with_include(config_dir,
                                          b'{ "#include": "common.json"}')
        assert "/this/is/a/unit/test" == str(result.source_root)

        # Check that the current file always has precendence
        result = _get_config_with_include(
            config_dir,
            b'{ "#include": "256-common.json", "output-root": "/output128"}')
        assert "/output128" == str(result.output_root)
        result = _get_config_with_include(
            config_dir,
            b'{ "#include": "128-common.json", "output-root": "/output256"}')
        assert "/output256" == str(result.output_root)
        # order doesn't matter since the #include is only evaluated after the whole file has been parsed:
        result = _get_config_with_include(
            config_dir,
            b'{ "output-root": "/output128", "#include": "256-common.json"}')
        assert "/output128" == str(result.output_root)
        result = _get_config_with_include(
            config_dir,
            b'{ "output-root": "/output256", "#include": "128-common.json"}')
        assert "/output256" == str(result.output_root)

        # TODO: handled nested cases: the level closest to the initial file wins
        (config_dir / "change-source-root.json").write_bytes(
            b'{ "source-root": "/source/root/override", "#include": "common.json" }'
        )
        result = _get_config_with_include(
            config_dir, b'{ "#include": "change-source-root.json"}')
        assert "/source/root/override" == str(result.source_root)
        # And again the root file wins:
        result = _get_config_with_include(
            config_dir,
            b'{ "source-root": "/override/twice", "#include": "change-source-root.json"}'
        )
        assert "/override/twice" == str(result.source_root)
        # no matter in which order it is written:
        result = _get_config_with_include(
            config_dir,
            b'{ "#include": "change-source-root.json", "source-root": "/override/again"}'
        )
        assert "/override/again" == str(result.source_root)

        # Test merging of objects:
        (config_dir / "change-smb-dir.json").write_bytes(
            b'{ "run": { "smb-host-directory": "/some/path" }, "#include": "common.json" }'
        )
        result = _get_config_with_include(
            config_dir,
            b'{ "run": { "ssh-forwarding-port": 12345 }, "#include": '
            b'"change-smb-dir.json" }')
        run_project = target_manager.get_target_raw(
            "run").get_or_create_project(None, result)
        assert run_project.custom_qemu_smb_mount == Path("/some/path")
        assert run_project.ssh_forwarding_port == 12345

        with tempfile.TemporaryDirectory() as d2:
            # Check that relative paths work
            relpath = b"../" + str(Path(d).relative_to(
                Path(d2).parent)).encode("utf-8")
            result = _get_config_with_include(config_dir,
                                              b'{ "#include": "' + relpath +
                                              b'/common.json" }',
                                              workdir=Path(d2))
            assert "/this/is/a/unit/test" == str(result.source_root)

            # Check that absolute paths work as expected:
            abspath = b"" + str(Path(d)).encode("utf-8")
            result = _get_config_with_include(config_dir,
                                              b'{ "#include": "' + abspath +
                                              b'/common.json" }',
                                              workdir=Path(d2))
            assert "/this/is/a/unit/test" == str(result.source_root)

        # Nonexistant paths should raise an error
        with pytest.raises(FileNotFoundError) as excinfo:
            _get_config_with_include(config_dir,
                                     b'{ "#include": "bad-path.json"}')
            assert re.search("No such file or directory", str(excinfo.value))

        # Currently only one #include per config file is allowed
        # TODO: this could be supported but it might be better to accept a list instead?
        with pytest.raises(SyntaxError) as excinfo:
            _get_config_with_include(
                config_dir,
                b'{ "#include": "128-common.json", "foo": "bar", "#include": "256-common.json"}'
            )
            assert re.search("duplicate key: '#include'", str(excinfo.value))
def test_cheribsd_purecap_inherits_config_from_cheribsd():
    # Parse args once to ensure target_manager is initialized
    config = _parse_arguments(["--skip-configure"])
    cheribsd_class = target_manager.get_target_raw("cheribsd").project_class
    cheribsd_default_tgt = target_manager.get_target_raw(
        "cheribsd").get_or_create_project(None, config)  # type:
    # BuildCHERIBSD
    assert cheribsd_default_tgt.target == "cheribsd-mips-hybrid"
    cheribsd_mips = target_manager.get_target_raw(
        "cheribsd-mips-nocheri").get_or_create_project(None, config)  # type:
    # BuildCHERIBSD
    cheribsd_cheri = target_manager.get_target_raw(
        "cheribsd-mips-hybrid").get_or_create_project(None, config)  # type:
    # BuildCHERIBSD
    cheribsd_purecap = target_manager.get_target_raw(
        "cheribsd-mips-purecap").get_or_create_project(None, config)  # type:
    # BuildCHERIBSD

    # Check that project name is the same:
    assert cheribsd_mips.project_name == cheribsd_cheri.project_name
    assert cheribsd_cheri.project_name == cheribsd_purecap.project_name

    # cheribsd-cheri is a synthetic class, but cheribsd-purecap inst:
    assert cheribsd_cheri.synthetic_base == cheribsd_class
    assert hasattr(cheribsd_purecap, "synthetic_base")

    _parse_arguments(["--cheribsd-mips-nocheri/debug-kernel"])
    assert not cheribsd_purecap.debug_kernel, "cheribsd-purecap debug-kernel should default to false"
    assert not cheribsd_cheri.debug_kernel, "cheribsd-mips-hybrid debug-kernel should default to false"
    assert cheribsd_mips.debug_kernel, "cheribsd-mips-nocheri debug-kernel should be set on cmdline"
    _parse_arguments(["--cheribsd-purecap/debug-kernel"])
    assert cheribsd_purecap.debug_kernel, "cheribsd-purecap debug-kernel should be set on cmdline"
    assert not cheribsd_cheri.debug_kernel, "cheribsd-mips-hybrid debug-kernel should default to false"
    assert not cheribsd_mips.debug_kernel, "cheribsd-mips-nocheri debug-kernel should default to false"
    _parse_arguments(["--cheribsd-cheri/debug-kernel"])
    assert not cheribsd_purecap.debug_kernel, "cheribsd-purecap debug-kernel should default to false"
    assert cheribsd_cheri.debug_kernel, "cheribsd-cheri debug-kernel should be set on cmdline"
    assert not cheribsd_mips.debug_kernel, "cheribsd-mips-nocheri debug-kernel should default to false"

    # If the base cheribsd option is set but no per-target one use both cheribsd-cheri and cheribsd-purecap should
    # inherit basic one:
    _parse_arguments(["--cheribsd/debug-kernel"])
    assert cheribsd_cheri.debug_kernel, "cheribsd-cheri should inherit debug-kernel from cheribsd(default)"
    assert cheribsd_purecap.debug_kernel, "cheribsd-purecap should inherit debug-kernel from cheribsd(default)"

    # But target-specific ones should override
    _parse_arguments(
        ["--cheribsd/debug-kernel", "--cheribsd-purecap/no-debug-kernel"])
    assert cheribsd_cheri.debug_kernel, "cheribsd-cheri should inherit debug-kernel from cheribsd(default)"
    assert not cheribsd_purecap.debug_kernel, "cheribsd-purecap should have a false override for debug-kernel"

    _parse_arguments(
        ["--cheribsd/debug-kernel", "--cheribsd-cheri/no-debug-kernel"])
    assert cheribsd_purecap.debug_kernel, "cheribsd-purecap should inherit debug-kernel from cheribsd(default)"
    assert not cheribsd_cheri.debug_kernel, "cheribsd-cheri should have a false override for debug-kernel"

    # Check that we hav ethe same behaviour when loading from json:
    _parse_config_file_and_args(b'{"cheribsd/debug-kernel": true }')
    assert cheribsd_purecap.debug_kernel, "cheribsd-purecap should inherit debug-kernel from cheribsd(default)"
    assert cheribsd_cheri.debug_kernel, "cheribsd-cheri should inherit debug-kernel from cheribsd(default)"
    assert cheribsd_mips.debug_kernel, "cheribsd-mips should inherit debug-kernel from cheribsd(default)"

    # But target-specific ones should override
    _parse_config_file_and_args(
        b'{"cheribsd/debug-kernel": true, "cheribsd-cheri/debug-kernel": false }'
    )
    assert cheribsd_mips.debug_kernel, "cheribsd-mips debug-kernel should be inherited on cmdline"
    assert cheribsd_purecap.debug_kernel, "cheribsd-purecap should inherit debug-kernel from cheribsd(default)"
    assert not cheribsd_cheri.debug_kernel, "cheribsd-cheri should have a false override for debug-kernel"

    # And that cmdline still overrides JSON:
    _parse_config_file_and_args(b'{"cheribsd/debug-kernel": true }',
                                "--cheribsd-cheri/no-debug-kernel")
    assert cheribsd_purecap.debug_kernel, "cheribsd-purecap should inherit debug-kernel from cheribsd(default)"
    assert cheribsd_mips.debug_kernel, "cheribsd-mips debug-kernel should be inherited from cheribsd(default)"
    assert not cheribsd_cheri.debug_kernel, "cheribsd-cheri should have a false override for debug-kernel"
    # But if a per-target option is set in the json that still overrides the default set on the cmdline
    _parse_config_file_and_args(b'{"cheribsd-cheri/debug-kernel": false }',
                                "--cheribsd/debug-kernel")
    assert cheribsd_purecap.debug_kernel, "cheribsd-purecap should inherit debug-kernel from cheribsd(default)"
    assert cheribsd_mips.debug_kernel, "cheribsd-mips debug-kernel should be inherited from cheribsd(default)"
    assert not cheribsd_cheri.debug_kernel, "cheribsd-cheri should have a JSON false override for debug-kernel"

    # However, don't inherit for build_dir since that doesn't make sense:
    def assert_build_dirs_different():
        assert cheribsd_cheri.build_dir != cheribsd_purecap.build_dir
        assert cheribsd_cheri.build_dir != cheribsd_mips.build_dir
        assert cheribsd_cheri.build_dir == cheribsd_default_tgt.build_dir

    assert_build_dirs_different()
    # overriding native build dir is fine:
    _parse_arguments(["--cheribsd-purecap/build-directory=/foo/bar"])
    assert cheribsd_purecap.build_dir == Path("/foo/bar")
    assert_build_dirs_different()
    _parse_config_file_and_args(
        b'{"cheribsd-purecap/build-directory": "/foo/bar"}')
    assert cheribsd_purecap.build_dir == Path("/foo/bar")
    assert_build_dirs_different()
    # cheribsd-cheri should inherit from the default one, but not cheribsd-purecap:
    _parse_arguments(["--cheribsd/build-directory=/foo/bar"])
    assert cheribsd_cheri.build_dir == Path("/foo/bar")
    assert cheribsd_purecap.build_dir != Path("/foo/bar")
    assert_build_dirs_different()
    _parse_config_file_and_args(b'{"cheribsd/build-directory": "/foo/bar"}')
    assert cheribsd_cheri.build_dir == Path("/foo/bar")
    assert cheribsd_purecap.build_dir != Path("/foo/bar")
    assert_build_dirs_different()

    # cheribsd-cheri/builddir should have higher prirority:
    _parse_arguments([
        "--cheribsd/build-directory=/foo/bar",
        "--cheribsd-cheri/build-directory=/bar/foo"
    ])
    assert cheribsd_cheri.build_dir == Path("/bar/foo")
    assert_build_dirs_different()
    _parse_config_file_and_args(
        b'{"cheribsd/build-directory": "/foo/bar",'
        b' "cheribsd-cheri/build-directory": "/bar/foo"}')
    assert cheribsd_cheri.build_dir == Path("/bar/foo")
    assert_build_dirs_different()
def test_cross_compile_project_inherits():
    # Parse args once to ensure target_manager is initialized
    config = _parse_arguments(["--skip-configure"])
    qtbase_class = target_manager.get_target_raw("qtbase").project_class
    qtbase_default = target_manager.get_target_raw(
        "qtbase").get_or_create_project(None, config)  # type: BuildQtBase
    qtbase_native = target_manager.get_target_raw(
        "qtbase-native").get_or_create_project(None,
                                               config)  # type: BuildQtBase
    qtbase_mips = target_manager.get_target_raw(
        "qtbase-mips-hybrid").get_or_create_project(
            None, config)  # type: BuildQtBase

    # Check that project name is the same:
    assert qtbase_default.project_name == qtbase_native.project_name
    assert qtbase_mips.project_name == qtbase_native.project_name
    # These classes were generated:
    # noinspection PyUnresolvedReferences
    assert qtbase_native.synthetic_base == qtbase_class
    # noinspection PyUnresolvedReferences
    assert qtbase_mips.synthetic_base == qtbase_class
    assert not hasattr(qtbase_class, "synthetic_base")

    # Now check a property that should be inherited:
    _parse_arguments(["--qtbase-native/build-tests"])
    assert not qtbase_default.build_tests, "qtbase-default build-tests should default to false"
    assert qtbase_native.build_tests, "qtbase-native build-tests should be set on cmdline"
    assert not qtbase_mips.build_tests, "qtbase-mips build-tests should default to false"
    # If the base qtbase option is set but no per-target one use the basic one:
    _parse_arguments(["--qtbase/build-tests"])
    assert qtbase_default.build_tests, "qtbase(default) build-tests should be set on cmdline"
    assert qtbase_native.build_tests, "qtbase-native should inherit build-tests from qtbase(default)"
    assert qtbase_mips.build_tests, "qtbase-mips should inherit build-tests from qtbase(default)"

    # But target-specific ones should override
    _parse_arguments(
        ["--qtbase/build-tests", "--qtbase-mips-hybrid/no-build-tests"])
    assert qtbase_default.build_tests, "qtbase(default) build-tests should be set on cmdline"
    assert qtbase_native.build_tests, "qtbase-native should inherit build-tests from qtbase(default)"
    assert not qtbase_mips.build_tests, "qtbase-mips should have a false override for build-tests"

    # Check that we hav ethe same behaviour when loading from json:
    _parse_config_file_and_args(b'{"qtbase-native/build-tests": true }')
    assert not qtbase_default.build_tests, "qtbase-default build-tests should default to false"
    assert qtbase_native.build_tests, "qtbase-native build-tests should be set on cmdline"
    assert not qtbase_mips.build_tests, "qtbase-mips build-tests should default to false"
    # If the base qtbase option is set but no per-target one use the basic one:
    _parse_config_file_and_args(b'{"qtbase/build-tests": true }')
    assert qtbase_default.build_tests, "qtbase(default) build-tests should be set on cmdline"
    assert qtbase_native.build_tests, "qtbase-native should inherit build-tests from qtbase(default)"
    assert qtbase_mips.build_tests, "qtbase-mips should inherit build-tests from qtbase(default)"

    # But target-specific ones should override
    _parse_config_file_and_args(
        b'{"qtbase/build-tests": true, "qtbase-mips-hybrid/build-tests": false }'
    )
    assert qtbase_default.build_tests, "qtbase(default) build-tests should be set on cmdline"
    assert qtbase_native.build_tests, "qtbase-native should inherit build-tests from qtbase(default)"
    assert not qtbase_mips.build_tests, "qtbase-mips should have a false override for build-tests"

    # And that cmdline still overrides JSON:
    _parse_config_file_and_args(b'{"qtbase/build-tests": true }',
                                "--qtbase-mips-hybrid/no-build-tests")
    assert qtbase_default.build_tests, "qtbase(default) build-tests should be set on cmdline"
    assert qtbase_native.build_tests, "qtbase-native should inherit build-tests from qtbase(default)"
    assert not qtbase_mips.build_tests, "qtbase-mips should have a false override for build-tests"
    # But if a per-target option is set in the json that still overrides the default set on the cmdline
    _parse_config_file_and_args(b'{"qtbase-mips-hybrid/build-tests": false }',
                                "--qtbase/build-tests")
    assert qtbase_default.build_tests, "qtbase(default) build-tests should be set on cmdline"
    assert qtbase_native.build_tests, "qtbase-native should inherit build-tests from qtbase(default)"
    assert not qtbase_mips.build_tests, "qtbase-mips should have a JSON false override for build-tests"

    # However, don't inherit for build_dir since that doesn't make sense:
    def assert_build_dirs_different():
        # Default should be CHERI purecap
        # print("Default build dir:", qtbase_default.build_dir)
        # print("Native build dir:", qtbase_native.build_dir)
        # print("Mips build dir:", qtbase_mips.build_dir)
        assert qtbase_default.build_dir != qtbase_native.build_dir
        assert qtbase_default.build_dir != qtbase_mips.build_dir
        assert qtbase_mips.build_dir != qtbase_native.build_dir

    assert_build_dirs_different()
    # overriding native build dir is fine:
    _parse_arguments(["--qtbase-native/build-directory=/foo/bar"])
    assert_build_dirs_different()
    _parse_config_file_and_args(
        b'{"qtbase-native/build-directory": "/foo/bar"}')
    assert_build_dirs_different()
    # Should not inherit from the default one:
    _parse_arguments(["--qtbase/build-directory=/foo/bar"])
    assert_build_dirs_different()
    _parse_config_file_and_args(b'{"qtbase/build-directory": "/foo/bar"}')
    assert_build_dirs_different()

    # Should not inherit from the default one:
    _parse_arguments([
        "--qtbase/build-directory=/foo/bar",
        "--qtbase-mips-hybrid/build-directory=/bar/foo"
    ])
    assert_build_dirs_different()
    _parse_config_file_and_args(
        b'{"qtbase/build-directory": "/foo/bar",'
        b' "qtbase-mips-hybrid/build-directory": "/bar/foo"}')
    assert_build_dirs_different()
def _get_target_instance(target_name: str, config, cls: typing.Type[T] = SimpleProject) -> T:
    result = target_manager.get_target_raw(target_name).get_or_create_project(None, config)
    assert isinstance(result, cls)
    return result
def test_cheribsd_purecap_inherits_config_from_cheribsd():
    # Parse args once to ensure target_manager is initialized
    config = _parse_arguments(["--skip-configure"])
    cheribsd_class = target_manager.get_target_raw("cheribsd").project_class
    cheribsd_mips = _get_cheribsd_instance("cheribsd-mips64", config)
    cheribsd_mips_hybrid = _get_cheribsd_instance("cheribsd-mips64-hybrid", config)
    cheribsd_mips_purecap = _get_cheribsd_instance("cheribsd-mips64-purecap", config)

    # Check that project name is the same:
    assert cheribsd_mips.project_name == cheribsd_mips_hybrid.project_name
    assert cheribsd_mips_hybrid.project_name == cheribsd_mips_purecap.project_name

    # noinspection PyUnresolvedReferences
    assert cheribsd_mips_hybrid.synthetic_base == cheribsd_class
    # noinspection PyUnresolvedReferences
    assert cheribsd_mips_purecap.synthetic_base == cheribsd_class

    _parse_arguments(["--cheribsd-mips64/debug-kernel"])
    assert not cheribsd_mips_purecap.debug_kernel, "cheribsd-purecap debug-kernel should default to false"
    assert not cheribsd_mips_hybrid.debug_kernel, "cheribsd-mips-hybrid debug-kernel should default to false"
    assert cheribsd_mips.debug_kernel, "cheribsd-mips64 debug-kernel should be set on cmdline"
    _parse_arguments(["--cheribsd-mips64-purecap/debug-kernel"])
    assert cheribsd_mips_purecap.debug_kernel, "cheribsd-purecap debug-kernel should be set on cmdline"
    assert not cheribsd_mips_hybrid.debug_kernel, "cheribsd-mips-hybrid debug-kernel should default to false"
    assert not cheribsd_mips.debug_kernel, "cheribsd-mips64 debug-kernel should default to false"
    _parse_arguments(["--cheribsd-mips64-hybrid/debug-kernel"])
    assert not cheribsd_mips_purecap.debug_kernel, "cheribsd-purecap debug-kernel should default to false"
    assert cheribsd_mips_hybrid.debug_kernel, "cheribsd-mips64-hybrid debug-kernel should be set on cmdline"
    assert not cheribsd_mips.debug_kernel, "cheribsd-mips64 debug-kernel should default to false"

    # If the base cheribsd option is set but no per-target one use both cheribsd-mips64-hybrid and cheribsd-purecap
    # should    # inherit basic one:
    _parse_arguments(["--cheribsd/debug-kernel"])
    assert cheribsd_mips_hybrid.debug_kernel, "mips64-hybrid should inherit debug-kernel from cheribsd(default)"
    assert cheribsd_mips_purecap.debug_kernel, "cheribsd-purecap should inherit debug-kernel from cheribsd(default)"

    # But target-specific ones should override
    _parse_arguments(["--cheribsd/debug-kernel", "--cheribsd-mips64-purecap/no-debug-kernel"])
    assert cheribsd_mips_hybrid.debug_kernel, "mips64-hybrid should inherit debug-kernel from cheribsd(default)"
    assert not cheribsd_mips_purecap.debug_kernel, "cheribsd-purecap should have a false override for debug-kernel"

    _parse_arguments(["--cheribsd/debug-kernel", "--cheribsd-mips64-hybrid/no-debug-kernel"])
    assert cheribsd_mips_purecap.debug_kernel, "cheribsd-purecap should inherit debug-kernel from cheribsd(default)"
    assert not cheribsd_mips_hybrid.debug_kernel, "mips64-hybrid should have a false override for debug-kernel"

    # Check that we hav ethe same behaviour when loading from json:
    _parse_config_file_and_args(b'{"cheribsd/debug-kernel": true }')
    assert cheribsd_mips_purecap.debug_kernel, "cheribsd-purecap should inherit debug-kernel from cheribsd(default)"
    assert cheribsd_mips_hybrid.debug_kernel, "mips64-hybrid should inherit debug-kernel from cheribsd(default)"
    assert cheribsd_mips.debug_kernel, "cheribsd-mips should inherit debug-kernel from cheribsd(default)"

    # But target-specific ones should override
    _parse_config_file_and_args(b'{"cheribsd/debug-kernel": true, "cheribsd-mips64-hybrid/debug-kernel": false }')
    assert cheribsd_mips.debug_kernel, "cheribsd-mips debug-kernel should be inherited on cmdline"
    assert cheribsd_mips_purecap.debug_kernel, "cheribsd-purecap should inherit debug-kernel from cheribsd(default)"
    assert not cheribsd_mips_hybrid.debug_kernel, "mips64-hybrid should have a false override for debug-kernel"

    # And that cmdline still overrides JSON:
    _parse_config_file_and_args(b'{"cheribsd/debug-kernel": true }', "--cheribsd-mips64-hybrid/no-debug-kernel")
    assert cheribsd_mips_purecap.debug_kernel, "cheribsd-purecap should inherit debug-kernel from cheribsd(default)"
    assert cheribsd_mips.debug_kernel, "cheribsd-mips debug-kernel should be inherited from cheribsd(default)"
    assert not cheribsd_mips_hybrid.debug_kernel, "mips64-hybrid should have a false override for debug-kernel"
    # But if a per-target option is set in the json that still overrides the default set on the cmdline
    _parse_config_file_and_args(b'{"cheribsd-mips64-hybrid/debug-kernel": false }', "--cheribsd/debug-kernel")
    assert cheribsd_mips_purecap.debug_kernel, "cheribsd-purecap should inherit debug-kernel from cheribsd(default)"
    assert cheribsd_mips.debug_kernel, "cheribsd-mips debug-kernel should be inherited from cheribsd(default)"
    assert not cheribsd_mips_hybrid.debug_kernel, "mips64-hybrid should have a JSON false override for debug-kernel"

    # However, don't inherit for build_dir since that doesn't make sense:
    def assert_build_dirs_different():
        assert cheribsd_mips_hybrid.build_dir != cheribsd_mips_purecap.build_dir
        assert cheribsd_mips_hybrid.build_dir != cheribsd_mips.build_dir

    assert_build_dirs_different()
    # overriding native build dir is fine:
    _parse_arguments(["--cheribsd-mips64-purecap/build-directory=/foo/bar"])
    assert cheribsd_mips_purecap.build_dir == Path("/foo/bar")
    assert_build_dirs_different()
    _parse_config_file_and_args(b'{"cheribsd-mips64-purecap/build-directory": "/foo/bar"}')
    assert cheribsd_mips_purecap.build_dir == Path("/foo/bar")
    assert_build_dirs_different()
    _parse_arguments(["--cheribsd-mips64-hybrid/build-directory=/foo/bar"])
    assert cheribsd_mips_hybrid.build_dir == Path("/foo/bar")
    assert cheribsd_mips_purecap.build_dir != Path("/foo/bar")
    assert_build_dirs_different()
    _parse_config_file_and_args(b'{"cheribsd-mips-hybrid/build-directory": "/foo/bar"}')
    assert cheribsd_mips_hybrid.build_dir == Path("/foo/bar")
    assert cheribsd_mips_purecap.build_dir != Path("/foo/bar")
    assert_build_dirs_different()

    # cheribsd-mips64-hybrid/builddir should have higher prirority:
    _parse_arguments(["--cheribsd/build-directory=/foo/bar", "--cheribsd-mips64-hybrid/build-directory=/bar/foo"])
    assert cheribsd_mips_hybrid.build_dir == Path("/bar/foo")
    assert_build_dirs_different()
    _parse_config_file_and_args(b'{"cheribsd/build-directory": "/foo/bar",'
                                b' "cheribsd-mips64-hybrid/build-directory": "/bar/foo"}')
    assert cheribsd_mips_hybrid.build_dir == Path("/bar/foo")
    assert_build_dirs_different()