|
| 1 | +using DataDrivenDiffEq |
| 2 | +using JET |
| 3 | +using Test |
| 4 | + |
| 5 | +# Note: JET analysis on symbolic packages can be slow and may report many |
| 6 | +# false positives from the underlying symbolic infrastructure (Symbolics.jl, |
| 7 | +# ModelingToolkit.jl). This test file focuses on core DataDrivenDiffEq |
| 8 | +# functionality with concrete types to catch actual type stability issues. |
| 9 | +# |
| 10 | +# We use @test_opt with target_modules to only check DataDrivenDiffEq code, |
| 11 | +# and we use broken=true for tests that detect expected polymorphic behavior |
| 12 | +# (like problem type dispatch) rather than actual bugs. |
| 13 | + |
| 14 | +@testset "JET Static Analysis" begin |
| 15 | + @testset "Basis generator type stability" begin |
| 16 | + # Test basis generators with concrete types |
| 17 | + # These should be fully type-stable as they don't involve symbolic computation |
| 18 | + @test_opt target_modules = (DataDrivenDiffEq,) DataDrivenDiffEq.polynomial_basis( |
| 19 | + 2, 3 |
| 20 | + ) |
| 21 | + @test_opt target_modules = (DataDrivenDiffEq,) DataDrivenDiffEq.monomial_basis(2, 3) |
| 22 | + @test_opt target_modules = (DataDrivenDiffEq,) DataDrivenDiffEq.chebyshev_basis(2, 3) |
| 23 | + @test_opt target_modules = (DataDrivenDiffEq,) DataDrivenDiffEq.sin_basis(2, 3) |
| 24 | + @test_opt target_modules = (DataDrivenDiffEq,) DataDrivenDiffEq.cos_basis(2, 3) |
| 25 | + @test_opt target_modules = (DataDrivenDiffEq,) DataDrivenDiffEq.fourier_basis(2, 3) |
| 26 | + end |
| 27 | + |
| 28 | + @testset "Problem accessor type stability" begin |
| 29 | + X = rand(2, 10) |
| 30 | + t = collect(1.0:10.0) |
| 31 | + DX = rand(2, 10) |
| 32 | + |
| 33 | + prob = ContinuousDataDrivenProblem(X, t, DX) |
| 34 | + |
| 35 | + # Test simple accessor functions that should be type-stable |
| 36 | + # These accessors only check type parameters, not field values |
| 37 | + @test_opt target_modules = (DataDrivenDiffEq,) DataDrivenDiffEq.is_autonomous(prob) |
| 38 | + @test_opt target_modules = (DataDrivenDiffEq,) DataDrivenDiffEq.is_discrete(prob) |
| 39 | + @test_opt target_modules = (DataDrivenDiffEq,) DataDrivenDiffEq.is_continuous(prob) |
| 40 | + @test_opt target_modules = (DataDrivenDiffEq,) DataDrivenDiffEq.is_direct(prob) |
| 41 | + # Note: has_timepoints checks isempty on AbstractVector field, which has |
| 42 | + # expected runtime dispatch due to the abstract field type design choice |
| 43 | + end |
| 44 | + |
| 45 | + @testset "Internal constructor type stability" begin |
| 46 | + # Test the internal type-stable constructor directly |
| 47 | + X = rand(2, 10) |
| 48 | + t = collect(1.0:10.0) |
| 49 | + DX = rand(2, 10) |
| 50 | + Y = Matrix{Float64}(undef, 0, 0) |
| 51 | + U = Matrix{Float64}(undef, 0, 0) |
| 52 | + p = Float64[] |
| 53 | + |
| 54 | + # The internal constructor has runtime dispatch in _promote on Julia lts |
| 55 | + # due to broadcasting with abstract element types. Fixed in Julia 1.11+. |
| 56 | + @test_opt broken = (VERSION < v"1.11") target_modules = (DataDrivenDiffEq,) DataDrivenDiffEq._construct_datadrivenproblem( |
| 57 | + Val(false), |
| 58 | + Val(DataDrivenDiffEq.DDProbType(3)), |
| 59 | + Float64, |
| 60 | + X, |
| 61 | + t, |
| 62 | + DX, |
| 63 | + Y, |
| 64 | + U, |
| 65 | + p, |
| 66 | + :test |
| 67 | + ) |
| 68 | + end |
| 69 | +end |
0 commit comments