@testsnippet TreeMesh3DAdvection begin
    EXAMPLES_DIR = joinpath(examples_dir(), "tree_3d_dgsem")
end

@testitem "TreeMesh3D Advection: elixir_advection_basic.jl" setup=[
    Setup,
    TreeMesh3DAdvection
] tags=[:tree_part4] begin
    @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"),
                        l2=[0.00016263963870641478],
                        linf=[0.0014537194925779984])
    # Ensure that we do not have excessive memory allocations
    # (e.g., from type instabilities)
    @test_allocations(Trixi.rhs_hyperbolic!, semi, sol, 1000)
end

@testitem "TreeMesh3D Advection: elixir_advection_convergence_fvO2.jl" setup=[
    Setup,
    TreeMesh3DAdvection
] tags=[:tree_part4] begin
    @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_convergence_fvO2.jl"),
                        l2=[0.023417734889807557], linf=[0.0713577997489736])
    # Ensure that we do not have excessive memory allocations
    # (e.g., from type instabilities)
    @test_allocations(Trixi.rhs_hyperbolic!, semi, sol, 1000)
end

@testitem "TreeMesh3D Advection: elixir_advection_restart.jl" setup=[
    Setup,
    TreeMesh3DAdvection
] tags=[:tree_part4] begin
    @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"),
                        l2=[0.00016017848135651983],
                        linf=[0.0014175368788298393])
    # Ensure that we do not have excessive memory allocations
    # (e.g., from type instabilities)
    @test_allocations(Trixi.rhs_hyperbolic!, semi, sol, 1000)
end

@testitem "TreeMesh3D Advection: elixir_advection_extended.jl with initial_condition_sin" setup=[
    Setup,
    TreeMesh3DAdvection
] tags=[:tree_part4] begin
    @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"),
                        l2=[0.002647730309275237],
                        linf=[0.02114324070353557],
                        initial_condition=Trixi.initial_condition_sin)
    # Ensure that we do not have excessive memory allocations
    # (e.g., from type instabilities)
    @test_allocations(Trixi.rhs_hyperbolic!, semi, sol, 1000)
end

@testitem "TreeMesh3D Advection: elixir_advection_extended.jl with initial_condition_constant" setup=[
    Setup,
    TreeMesh3DAdvection
] tags=[:tree_part4] begin
    @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"),
                        l2=[7.728011630010656e-16],
                        linf=[3.9968028886505635e-15],
                        initial_condition=initial_condition_constant)
    # Ensure that we do not have excessive memory allocations
    # (e.g., from type instabilities)
    @test_allocations(Trixi.rhs_hyperbolic!, semi, sol, 1000)
end

@testitem "TreeMesh3D Advection: elixir_advection_extended.jl with initial_condition_linear_z and periodicity=false" setup=[
    Setup,
    TreeMesh3DAdvection
] tags=[:tree_part4] begin
    @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"),
                        l2=[3.007995700405795e-16],
                        linf=[2.886579864025407e-15],
                        initial_condition=Trixi.initial_condition_linear_z,
                        boundary_conditions=Trixi.boundary_condition_linear_z,
                        periodicity=false)
    # Ensure that we do not have excessive memory allocations
    # (e.g., from type instabilities)
    @test_allocations(Trixi.rhs_hyperbolic!, semi, sol, 1000)
end

@testitem "TreeMesh3D Advection: elixir_advection_mortar.jl" setup=[
    Setup,
    TreeMesh3DAdvection
] tags=[:tree_part4] begin
    @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_mortar.jl"),
                        l2=[0.001810141301577316],
                        linf=[0.017848192256602058])

    # Ensure that we do not have excessive memory allocations
    # (e.g., from type instabilities)
    @test_allocations(Trixi.rhs_hyperbolic!, semi, sol, 1000)
end

@testitem "TreeMesh3D Advection: elixir_advection_amr.jl" setup=[Setup, TreeMesh3DAdvection] tags=[:tree_part4] begin
    @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr.jl"),
                        l2=[9.773852895157622e-6],
                        linf=[0.0005853874124926162])

    # Ensure that we do not have excessive memory allocations
    # (e.g., from type instabilities)
    @test_allocations(Trixi.rhs_hyperbolic!, semi, sol, 1000)
end

@testitem "TreeMesh3D Advection: elixir_advection_limiter_liu_zhang.jl" setup=[
    Setup,
    TreeMesh3DAdvection
] tags=[:tree_part4] begin
    @test_trixi_include(joinpath(EXAMPLES_DIR,
                                 "elixir_advection_limiter_liu_zhang.jl"),
                        l2=[0.39212005674820044],
                        linf=[1.3569114615249689])
    u = Trixi.wrap_array_native(sol.u[end], semi)
    # matches thresholds = (1e-3,) up to a tolerance
    @test minimum(u) > 1e-3 - 10 * eps()
    @test_allocations(Trixi.rhs_hyperbolic!, semi, sol, 1000)
end

@testitem "TreeMesh3D Advection: elixir_advection_er.jl" setup=[Setup, TreeMesh3DAdvection] tags=[:tree_part4] begin
    @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_er.jl"),
                        l2=[0.005193350046445726], linf=[0.025986449692943836])

    # Larger values for allowed allocations due to usage of custom
    # integrator which are not *recorded* for the methods from
    # OrdinaryDiffEq.jl
    # Corresponding issue: https://github.com/trixi-framework/Trixi.jl/issues/1877
    @test_allocations(Trixi.rhs_hyperbolic!, semi, sol, 15_000)
end
