/
githubmirror
/
julia
Обзор
Документация
Войти
/
githubmirror
/
julia
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
test/binaryplatforms.jl
527 строк
25 KB
Keno Fischer
binaryplatforms: Also perform compatibility transform on mutation (#62207)
25 июн 2026, 22:11
Не верифицирован
25 июн 2026, 22:11
ef6e9f9
Код
Авторство
О чём код?
# This file is a part of Julia. License is MIT: https://julialang.org/license using Test, Base.BinaryPlatforms, Base.BinaryPlatforms.CPUID @testset "CPUID" begin @test CPUID.cpu_isa() isa CPUID.ISA # x86_64 tiers form a strict subset chain get_x86_64(n) = (CPUID.ISAs_by_family["x86_64"][n].second) @test get_x86_64(2) < get_x86_64(4) @test get_x86_64(5) <= get_x86_64(5) @test get_x86_64(3) >= get_x86_64(3) @test get_x86_64(7) >= get_x86_64(1) @test sort([get_x86_64(6), get_x86_64(4), get_x86_64(2), get_x86_64(4)]) == [get_x86_64(2), get_x86_64(4), get_x86_64(4), get_x86_64(6)] # Cross-arch queries return real feature data @test length(CPUID._cross_lookup_cpu("x86_64", "haswell").features) > 10 @test length(CPUID._cross_lookup_cpu("aarch64", "cortex-a78").features) > 10 @test length(CPUID._cross_lookup_cpu("riscv64", "sifive-u74").features) > 0 @test isempty(CPUID._cross_lookup_cpu("x86_64", "nonexistent").features) @test isempty(CPUID._cross_lookup_cpu("badarch", "haswell").features) # Apple M-series aliases resolve to their A-series equivalents let m1 = CPUID._cross_lookup_cpu("aarch64", "apple-m1"), a14 = CPUID._cross_lookup_cpu("aarch64", "apple-a14") @test m1.features == a14.features end @test !isempty(CPUID._cross_lookup_cpu("aarch64", "apple-m2").features) # Arch name normalization (i686 → x86_64, arm64 → aarch64) @test CPUID._cross_lookup_cpu("i686", "haswell").features == CPUID._cross_lookup_cpu("x86_64", "haswell").features @test CPUID._cross_lookup_cpu("arm64", "cortex-a78").features == CPUID._cross_lookup_cpu("aarch64", "cortex-a78").features # All families have non-empty ISA data (cross-arch works) for (arch, isas) in CPUID.ISAs_by_family @test length(isas) >= 1 end # feature_names(arch, cpu) — query by CPU name hsw = CPUID.feature_names("x86_64", "haswell") @test "avx2" in hsw @test "fma" in hsw @test "sse4.2" in hsw @test !("avx512f" in hsw) # haswell doesn't have avx512 skx = CPUID.feature_names("x86_64", "skylake-avx512") @test "avx512f" in skx @test "avx512bw" in skx # aarch64 cross-arch feature names a78 = CPUID.feature_names("aarch64", "cortex-a78") @test "lse" in a78 @test "neon" in a78 x925 = CPUID.feature_names("aarch64", "cortex-x925") @test "sve2" in x925 @test "bf16" in x925 @test "dotprod" in x925 # Architecture version features present for ARM cores @test "v8.1a" in x925 @test "v9a" in x925 # Unknown CPU returns empty @test isempty(CPUID.feature_names("x86_64", "nonexistent")) # feature_names(arch, isa) — query by ISA struct names_from_isa = CPUID.feature_names("x86_64", get_x86_64(5)) @test "avx" in names_from_isa @test "sse4.2" in names_from_isa # feature_names(isa) — host arch default host_names = CPUID.feature_names(CPUID.cpu_isa()) @test length(host_names) > 5 # feature_names() — full default (host arch + host ISA) default_names = CPUID.feature_names() @test default_names == host_names # _build_bit_to_name returns a non-empty mapping with known features mapping = CPUID._build_bit_to_name("x86_64") @test length(mapping) > 50 @test "avx2" in values(mapping) @test "sse4.2" in values(mapping) mapping_aarch64 = CPUID._build_bit_to_name("aarch64") @test length(mapping_aarch64) > 50 @test "neon" in values(mapping_aarch64) @test "sve" in values(mapping_aarch64) end # Helper constructor to create a Platform with `validate_strict` set to `true`. P(args...; kwargs...) = Platform(args...; validate_strict=true, kwargs...) # Ensure the platform type constructors are well behaved @testset "Platform validation" begin for os_name in ("Linux", "linux", "FREEBSD", "wiNDows", "MacOS") p = P("x86_64", os_name) @test isa(p, Platform) @test os(p) == lowercase(os_name) end for arch_name in ("x86_64", "ARMv7l", "armv6l", "I686", "pOWerpc64le") p = P(arch_name, "linux") @test isa(p, Platform) @test arch(p) == lowercase(arch_name) end # Test some normalization @test arch(P("amd64", "freebsd")) == "x86_64" @test arch(P("ARM", "linux")) == "armv7l" @test arch(P("ppc64le", "linux")) == "powerpc64le" # test some error cases @test_throws ArgumentError P("x64_86", "linux") @test_throws ArgumentError P("x86_64", "not_an_os") @test_throws ArgumentError P("x86_64", "linux"; libc="crazy_libc") @test_throws ArgumentError P("x86_64", "linux"; libc="glibc", call_abi="crazy_abi") @test_throws ArgumentError P("x86_64", "linux"; libc="glibc", call_abi="eabihf") @test_throws ArgumentError P("i686", "linux"; libc="musl", call_abi="eabi") @test_throws ArgumentError P("arm", "linux"; call_abi="") @test_throws ArgumentError P("armv7l", "linux"; call_abi="kekeke") @test_throws ArgumentError P("armv6l", "linux"; call_abi="kekeke") @test_throws ArgumentError P("armv6l", "linux"; libgfortran_version="lel") @test_throws ArgumentError P("x86_64", "linux"; cxxstring_abi="lel") @test_throws ArgumentError P("x86_64", "windows"; cxxlib_version="lel") @test_throws ArgumentError P("x86_64", "windows"; cxxlib="other") @test_throws ArgumentError P("x86_64", "windows"; cxxlib="libcxx", cxxstring_abi="cxx11") @test_throws ArgumentError P("i686", "macos") @test_throws ArgumentError P("x86_64", "macos"; libc="glibc") @test_throws ArgumentError P("x86_64", "macos"; call_abi="eabihf") @test_throws ArgumentError P("powerpc64le", "windows") @test_throws ArgumentError P("x86_64", "windows"; call_abi="eabihf") @test_throws ArgumentError P("x86_64", "freebsd"; libc="crazy_libc") @test_throws ArgumentError P("x86_64", "freebsd"; call_abi="crazy_abi") @test_throws ArgumentError P("x86_64", "freebsd"; call_abi="eabihf") @test_throws ArgumentError P("x86_64", "linux"; arch="i686") @test_throws ArgumentError P("x86_64", "linux"; ARCH="i686") @test_throws ArgumentError P("x86_64", "linux"; os="windows") end @testset "Platform properties" begin # Test that `platform_name()` works platforms = ("Linux", "macOS", "Windows", "FreeBSD") for platform in platforms @test platform_name(P("x86_64", platform)) == platform end # Test `arch()` arch_names = ("x86_64", "i686", "powerpc64le", "armv7l", "armv6l", "aarch64") for arch_name in arch_names @test arch(P(arch_name, "linux")) == arch_name end # Test that if we aren't using strict validation, we can actually use new names too: @test arch(Platform("jpu", "linux")) == "jpu" # platform_dlext() @test platform_dlext(P("x86_64", "linux")) == "so" @test platform_dlext(P("armv7l", "windows")) == "dll" @test platform_dlext(P("x86_64", "freebsd")) == "so" @test platform_dlext(P("aarch64", "macos")) == "dylib" @test platform_dlext() == platform_dlext(HostPlatform()) # wordsize() @test wordsize(P("i686", "linux")) == wordsize(P("armv7l", "windows")) == 32 @test wordsize(P("aarch64", "macos")) == wordsize(P("x86_64", "freebsd")) == 64 @test wordsize(P("x86_64", "windows")) == wordsize(P("powerpc64le", "linux")) == 64 # call_abi() for platform in platforms @test call_abi(P("x86_64", platform)) === nothing end @test call_abi(P("armv7l", "linux")) == "eabihf" @test call_abi(P("armv7l", "linux"; call_abi="eabihf")) == "eabihf" @test call_abi(P("armv7l", "linux"; call_abi="eabi")) == "eabi" @test call_abi(P("armv6l", "linux")) == "eabihf" # Test that we can at least set an `eabi` call ABI, not that Julia actually supports it... @test call_abi(P("armv7l", "linux"; call_abi="eabi")) == "eabi" # Test some different OS's and libc/call ABIs @test triplet(P("i686", "Windows")) == "i686-w64-mingw32" @test triplet(P("x86_64", "linux"; libc="musl")) == "x86_64-linux-musl" @test triplet(P("armv7l", "linux"; libc="musl")) == "armv7l-linux-musleabihf" @test triplet(P("armv6l", "linux"; libc="musl", call_abi="eabihf")) == "armv6l-linux-musleabihf" @test triplet(P("armv6l", "linux"; call_abi="eabi")) == "armv6l-linux-gnueabi" @test triplet(P("x86_64", "linux")) == "x86_64-linux-gnu" @test triplet(P("armv6l", "linux")) == "armv6l-linux-gnueabihf" @test triplet(P("x86_64", "macos")) == "x86_64-apple-darwin" @test triplet(P("x86_64", "macos"; os_version=v"16")) == "x86_64-apple-darwin16" @test triplet(P("x86_64", "freebsd")) == "x86_64-unknown-freebsd" @test triplet(P("i686", "freebsd")) == "i686-unknown-freebsd" # Now test libgfortran/cxxstring ABIs @test triplet(P("x86_64", "linux"; libgfortran_version=v"3", cxxstring_abi="cxx11")) == "x86_64-linux-gnu-libgfortran3-cxx11" @test triplet(P("armv7l", "linux"; libc="musl", cxxstring_abi="cxx03")) == "armv7l-linux-musleabihf-cxx03" @test triplet(P("x86_64", "windows"; libc="ucrt")) == "x86_64-w64-ucrt-mingw32" @test triplet(P("x86_64", "linux"; cxxlib="libstdcxx", cxxlib_version=v"3.4.26")) == "x86_64-linux-gnu-libstdcxx26" libcxx_platform = P("x86_64", "linux"; cxxlib="libcxx", cxxlib_version=v"18") libcxx_triplet = triplet(libcxx_platform) @test startswith(libcxx_triplet, "x86_64-linux-gnu") @test occursin("-cxxlib+libcxx", libcxx_triplet) @test occursin("-cxxlib_version+18.0.0", libcxx_triplet) @test parse(Platform, libcxx_triplet; validate_strict=true) == libcxx_platform @test libstdcxx_version(P("x86_64", "linux"; cxxlib="libstdcxx", cxxlib_version=v"3.4.26")) == v"3.4.26" @test libstdcxx_version(libcxx_platform) === nothing if !isnothing(detect_libgfortran_version()) # When `libgfortran` can be detected at runtime, make sure # `HostPlatform` has the appropriate key. @test tags(HostPlatform())["libgfortran_version"] == string(detect_libgfortran_version()) end # Test tags() t = tags(P("x86_64", "linux")) @test all(haskey.(Ref(t), ("arch", "os", "libc"))) @test haskey(tags(P("x86_64", "linux"; customtag="foo")), "customtag") @test tags(HostPlatform())["julia_version"] == string(VERSION.major, ".", VERSION.minor, ".", VERSION.patch) # Test that we can modify tags at will using the dict-like interface: p = P("x86_64", "linux") p["foo"] = "bar" @test tags(p)["foo"] == "bar" @test p["foo"] == "bar" @test p["os"] == "linux" p["os"] = "JuliaOS" @test p["os"] == "juliaos" # Test that dict-like mutation uses the same compatibility aliases as constructors. p = P("x86_64", "linux") p["cxxstring_abi"] = "cxx11" @test p == P("x86_64", "linux"; cxxstring_abi="cxx11") @test triplet(p) == "x86_64-linux-gnu-cxx11" p = P("x86_64", "linux") p["libstdcxx_version"] = "3.4.26" @test p == P("x86_64", "linux"; libstdcxx_version=v"3.4.26") @test libstdcxx_version(p) == v"3.4.26" @test triplet(p) == "x86_64-linux-gnu-libstdcxx26" # Test that trying to set illegal tags fails @test_throws ArgumentError p["os"] = "a+b" # Test that our `hash()` is stable @test hash(HostPlatform()) == hash(HostPlatform()) # Test that round-tripping through `triplet` for a platform does not # maintain equality, as we end up losing the `compare_strategies`: p = Platform("x86_64", "linux"; cuda = v"11") Base.BinaryPlatforms.set_compare_strategy!(p, "cuda", Base.BinaryPlatforms.compare_version_cap) q = parse(Platform, triplet(p)) @test q != p end @testset "Triplet parsing" begin # Make sure the Platform() with explicit triplet works R(str) = parse(Platform, str; validate_strict=true) @test R("x86_64-linux-gnu") == P("x86_64", "linux") @test R("x86_64-linux-musl") == P("x86_64", "linux"; libc="musl") @test R("i686-unknown-linux-gnu") == P("i686", "linux") @test R("x86_64-apple-darwin") == P("x86_64", "macos") @test R("x86_64-apple-darwin14") == P("x86_64", "macos"; os_version="14") @test R("x86_64-apple-darwin17.0.0") == P("x86_64", "macos"; os_version="17") @test R("armv7l-pc-linux-gnueabihf") == P("armv7l", "linux") @test R("armv7l-linux-musleabihf") == P("armv7l", "linux"; libc="musl") @test R("armv6l-linux-gnueabi") == P("armv6l", "linux"; call_abi="eabi") # Test that the short name "arm" goes to `armv7l` @test R("arm-linux-gnueabihf") == P("armv7l", "linux") @test R("aarch64-unknown-linux-gnu") == P("aarch64", "linux") @test R("powerpc64le-linux-gnu") == P("powerpc64le", "linux") @test R("ppc64le-linux-gnu") == P("powerpc64le", "linux") @test R("x86_64-w64-mingw32") == P("x86_64", "windows") @test R("x86_64-w64-ucrt-mingw32") == P("x86_64", "windows"; libc="ucrt") @test R("i686-w64-mingw32") == P("i686", "windows") # FreeBSD has lots of arch names that don't match elsewhere @test R("x86_64-unknown-freebsd11.1") == P("x86_64", "freebsd"; os_version=v"11.1") @test R("i686-unknown-freebsd11.1") == P("i686", "freebsd"; os_version=v"11.1") @test R("amd64-unknown-freebsd12.0") == P("x86_64", "freebsd"; os_version=v"12.0") @test R("i386-unknown-freebsd10.3") == P("i686", "freebsd"; os_version=v"10.3") @test R("aarch64-apple-darwin18.7") == P("aarch64", "macos"; os_version=v"18.7") @test R("arm64-apple-darwin20") == P("aarch64", "macos"; os_version=v"20") # Test inclusion of ABI stuff, both old-style and new-style @test R("x86_64-linux-gnu-gcc7") == P("x86_64", "linux"; libgfortran_version=v"4") @test R("x86_64-linux-gnu-gcc4-cxx11") == P("x86_64", "linux"; libgfortran_version=v"3", cxxstring_abi="cxx11") @test R("x86_64-linux-gnu-cxx11") == P("x86_64", "linux"; cxxstring_abi="cxx11") @test R("x86_64-linux-gnu-libgfortran3-cxx03") == P("x86_64", "linux"; libgfortran_version=v"3", cxxstring_abi="cxx03") @test R("x86_64-linux-gnu-libstdcxx26") == P("x86_64", "linux"; cxxlib="libstdcxx", cxxlib_version=v"3.4.26") @test_throws ArgumentError R("totally FREEFORM text!!1!!!1!") @test_throws ArgumentError R("invalid-triplet-here") @test parse(Platform, "aarch64-linux-gnueabihf") == Platform("aarch64", "linux"; call_abi="eabihf") @test_throws ArgumentError R("aarch64-linux-gnueabihf") @test_throws ArgumentError R("x86_64-w32-mingw64") # Test extended attributes @test R("x86_64-linux-gnu-march+avx2") == P("x86_64", "linux"; march="avx2") @test R("x86_64-linux-gnu-march+x86_64-cuda+10.1") == P("x86_64", "linux"; march="x86_64", cuda="10.1") # Round-trip our little homie through `triplet()`, with some bending # of the rules for MacOS and FreeBSD, who have incomplete `os_version` # numbers embedded within their triplets. p = Platform("x86_64", "linux") @test parse(Platform, triplet(p)) == p # Also test round-tripping through `repr()`: p = Platform("aarch64", "macos"; os_version=v"20", march="armv8_4_crypto_sve") @test eval(Meta.parse(repr(p))) == p end @testset "platforms_match()" begin # Just do a quick combinatorial sweep for completeness' sake for platform matching linux = P("x86_64", "linux") for libgfortran_version in (nothing, v"3", v"5"), cxxlib in ("libstdcxx",), cxxlib_version in (nothing, v"3.4.18", v"3.4.26"), cxxstring_abi in (nothing, :cxx03, :cxx11) p = P("x86_64", "linux"; libgfortran_version, cxxlib, cxxlib_version, cxxstring_abi) @test platforms_match(linux, p) @test platforms_match(p, linux) # Also test auto-string-parsing @test platforms_match(triplet(linux), p) @test platforms_match(linux, triplet(p)) end # Test that Julia version is matched only on major.minor by default @test platforms_match(P("x86_64", "linux"; julia_version=v"1.5.0"), P("x86_64", "linux"; julia_version=v"1.5.1")) @test !platforms_match(P("x86_64", "linux"; julia_version=v"1.5.0"), P("x86_64", "linux"; julia_version=v"1.6.0")) # Ensure many of these things do NOT match @test !platforms_match(linux, P("i686", "linux")) @test !platforms_match(linux, P("x86_64", "windows")) @test !platforms_match(linux, P("x86_64", "macos")) # Make some explicitly non-matching compiler ABI platforms host = P("x86_64", "linux"; libgfortran_version=v"5", cxxstring_abi="cxx11") for arch in ("x86_64", "i686", "aarch64", "armv6l", "armv7l", "powerpc64le"), kwargs in ((:libgfortran_version => v"3",), (:cxxstring_abi => "cxx03",), (:libgfortran_version => v"4", :cxxstring_abi => "cxx11"), (:libgfortran_version => v"3", :cxxstring_abi => "cxx03")) a = P(arch, "linux"; libgfortran_version=v"5", cxxstring_abi="cxx11") b = P(arch, "linux"; kwargs...) @test !platforms_match(a, b) end # Test version bounds with HostPlatform() host = HostPlatform(P("x86_64", "macos"; os_version="14", libstdcxx_version=v"3.4.26")) @test platforms_match(host, P("x86_64", "macos")) @test platforms_match(host, P("x86_64", "macos"; os_version="14")) @test platforms_match(host, P("x86_64", "macos"; os_version="13")) @test !platforms_match(host, P("x86_64", "macos"; os_version="15")) @test platforms_match(host, P("x86_64", "macos"; libstdcxx_version="3.4.18")) @test platforms_match(host, P("x86_64", "macos"; os_version=v"10", libstdcxx_version="3.4.18")) @test !platforms_match(host, P("x86_64", "macos"; os_version=v"10", libstdcxx_version="3.4.27")) @test !platforms_match(host, P("x86_64", "macos"; os_version=v"14", libstdcxx_version=v"4")) end @testset "DL name/version parsing" begin # Make sure our version parsing code is working @test parse_dl_name_version("libgfortran.so", "linux") == ("libgfortran", nothing) @test parse_dl_name_version("libgfortran.so.3", "linux") == ("libgfortran", v"3") @test parse_dl_name_version("libgfortran.so.3.4", "linux") == ("libgfortran", v"3.4") @test_throws ArgumentError parse_dl_name_version("libgfortran.so.3.4a", "linux") @test_throws ArgumentError parse_dl_name_version("libgfortran", "linux") @test_throws ArgumentError parse_dl_name_version("libgfortranso", "linux") @test parse_dl_name_version("libgfortran.so", "freebsd") == ("libgfortran", nothing) @test parse_dl_name_version("libgfortran.so.3", "freebsd") == ("libgfortran", v"3") @test parse_dl_name_version("libgfortran.so.3.4", "freebsd") == ("libgfortran", v"3.4") @test_throws ArgumentError parse_dl_name_version("libgfortran.so.3.4a", "freebsd") @test_throws ArgumentError parse_dl_name_version("libgfortran", "freebsd") @test_throws ArgumentError parse_dl_name_version("libgfortranso", "freebsd") @test parse_dl_name_version("libgfortran.dylib", "macos") == ("libgfortran", nothing) @test parse_dl_name_version("libgfortran.3.dylib", "macos") == ("libgfortran", v"3") @test parse_dl_name_version("libgfortran.3.4.dylib", "macos") == ("libgfortran", v"3.4") @test parse_dl_name_version("libgfortran.3.4a.dylib", "macos") == ("libgfortran.3.4a", nothing) @test_throws ArgumentError parse_dl_name_version("libgfortran", "macos") @test_throws ArgumentError parse_dl_name_version("libgfortrandylib", "macos") @test parse_dl_name_version("libgfortran.dll", "windows") == ("libgfortran", nothing) @test parse_dl_name_version("libgfortran-3.dll", "windows") == ("libgfortran", v"3") @test parse_dl_name_version("libgfortran-3.4.dll", "windows") == ("libgfortran", v"3.4") @test parse_dl_name_version("libgfortran-3.4a.dll", "windows") == ("libgfortran-3.4a", nothing) @test_throws ArgumentError parse_dl_name_version("libgfortran", "windows") @test_throws ArgumentError parse_dl_name_version("libgfortrandll", "windows") end @testset "Sys.is* overloading" begin # Test that we can indeed ask if something is linux or windows, etc... @test Sys.islinux(P("aarch64", "linux")) @test !Sys.islinux(P("x86_64", "windows")) @test Sys.iswindows(P("i686", "windows")) @test !Sys.iswindows(P("powerpc64le", "linux")) @test Sys.isapple(P("x86_64", "macos")) @test !Sys.isapple(P("armv7l", "windows")) @test Sys.isbsd(P("aarch64", "macos")) @test Sys.isbsd(P("x86_64", "freebsd")) @test !Sys.isbsd(P("x86_64", "linux"; libc="musl")) end @testset "Compiler ABI detection" begin # Let's check and ensure that we can autodetect the currently-running Julia process @test detect_libgfortran_version() !== nothing # We run these to get coverage, but we can't test anything, because we could be built # with `clang`, which wouldn't have any `libstdc++` constraints at all detect_libstdcxx_version() detect_cxxstring_abi() end @testset "select_platform" begin platforms = Dict( # Typical binning test P("x86_64", "linux"; libgfortran_version=v"3") => "linux4", P("x86_64", "linux"; libgfortran_version=v"4") => "linux7", P("x86_64", "linux"; libgfortran_version=v"5") => "linux8", # Ambiguity test P("aarch64", "linux"; libgfortran_version=v"3") => "linux3", P("aarch64", "linux"; libgfortran_version=v"3", libstdcxx_version=v"3.4.18") => "linux5", P("aarch64", "linux"; libgfortran_version=v"3", libstdcxx_version=v"3.4.18", foo="bar") => "linux9", # OS test P("x86_64", "macos"; libgfortran_version=v"3") => "mac4", P("x86_64", "windows"; cxxstring_abi=:cxx11) => "win", ) @test select_platform(platforms, P("x86_64", "linux")) == "linux8" @test select_platform(platforms, P("x86_64", "linux"; libgfortran_version=v"4")) == "linux7" # Ambiguity test @test select_platform(platforms, P("aarch64", "linux")) == "linux3" @test select_platform(platforms, P("aarch64", "linux"; libgfortran_version=v"3")) == "linux3" @test select_platform(platforms, P("aarch64", "linux"; libgfortran_version=v"3", libstdcxx_version=v"3.4.18")) === "linux5" @test select_platform(platforms, P("aarch64", "linux"; libgfortran_version=v"4")) === nothing @test select_platform(platforms, P("x86_64", "macos")) == "mac4" @test select_platform(platforms, P("x86_64", "macos"; libgfortran_version=v"4")) === nothing @test select_platform(platforms, P("x86_64", "windows"; cxxstring_abi="cxx11")) == "win" @test select_platform(platforms, P("x86_64", "windows"; cxxstring_abi="cxx03")) === nothing # Sorry, Alex. ;) @test select_platform(platforms, P("x86_64", "freebsd")) === nothing # The new "most complete match" algorithm deals with ambiguities as follows: platforms = Dict( P("x86_64", "linux") => "normal", P("x86_64", "linux"; sanitize="memory") => "sanitized", ) @test select_platform(platforms, P("x86_64", "linux")) == "normal" @test select_platform(platforms, P("x86_64", "linux"; sanitize="memory")) == "sanitized" # Ties are broken by reverse-sorting by triplet: platforms = Dict( P("x86_64", "linux"; libgfortran_version=v"3") => "libgfortran3", P("x86_64", "linux"; libgfortran_version=v"4") => "libgfortran4", ) @test select_platform(platforms, P("x86_64", "linux")) == "libgfortran4" @test select_platform(platforms, P("x86_64", "linux"; libgfortran_version=v"3")) == "libgfortran3" end @testset "Custom comparators" begin # We're going to define here some custom comparators for Platform objects to ensure they work. # First, a symmetric one, which doesn't care which `Platform` object requested this comparison: function matches_oddness(a::String, b::String, a_requested::Bool, b_requested::Bool) return (parse(Int, a) % 2) == (parse(Int, b) % 2) end comp_strat = Dict("vally" => matches_oddness) # First, test that these two do not match, because it's using equality to test the `vally` tag a = Platform("x86_64", "linux"; vally="2") b = Platform("x86_64", "linux"; vally="4") @test !platforms_match(a, b) # Now, test that setting one or both `Platform`'s to use the `matches_oddness()` comparator works: ac = Platform("x86_64", "linux"; vally="2", compare_strategies=comp_strat) bc = Platform("x86_64", "linux"; vally="4", compare_strategies=comp_strat) @test platforms_match(ac, b) @test platforms_match(a, bc) @test platforms_match(ac, bc) # Test that even with the comparison strat, we don't match if they're not both even: bfc = Platform("x86_64", "linux"; vally="3", compare_strategies=comp_strat) @test !platforms_match(ac, bfc) # Next, an asymmetric comparison strategy. We'll create a "less than or equal to" constraint # that uses the `{a,b}_requested` parameters to determine which number represents the limit. function less_than_constraint(a::String, b::String, a_requested::Bool, b_requested::Bool) a = parse(Int, a) b = parse(Int, b) if a_requested && !b_requested return b < a end if b_requested && !a_requested return a < b end # If two constraints have been requested, return true if they are the same constraint. return a == b end comp_strat = Dict("vally" => less_than_constraint) a = Platform("x86_64", "linux"; vally="2") b = Platform("x86_64", "linux"; vally="4") ac = Platform("x86_64", "linux"; vally="2", compare_strategies=comp_strat) bc = Platform("x86_64", "linux"; vally="4", compare_strategies=comp_strat) # Vanilla comparison doesn't work @test !platforms_match(a, b) # a and bc match, but not ac and b. Also test reciprocity. @test platforms_match(a, bc) @test platforms_match(bc, a) @test !platforms_match(ac, b) @test !platforms_match(b, ac) # ac and bc do not match, but ac and ac do @test !platforms_match(ac, bc) @test platforms_match(ac, ac) @test platforms_match(bc, bc) end