|
| 1 | +@testsnippet defs_cablepos begin |
| 2 | + using Test |
| 3 | + using LineCableModels |
| 4 | + const DM = LineCableModels.DataModel |
| 5 | + const MAT = LineCableModels.Materials |
| 6 | + using Measurements |
| 7 | + |
| 8 | + # ---- helpers ---------------------------------------------------------- |
| 9 | + |
| 10 | + # Minimal Float64 design with matching interface radii |
| 11 | + function _make_design_F64() |
| 12 | + mC = MAT.Material(1e-8, 1.0, 1.0, 20.0, 0.0) |
| 13 | + mI = MAT.Material(1e12, 2.5, 1.0, 20.0, 0.0) |
| 14 | + |
| 15 | + cg = DM.ConductorGroup(DM.Tubular(0.010, 0.012, mC)) |
| 16 | + ig = DM.InsulatorGroup(DM.Insulator(0.012, 0.016, mI)) |
| 17 | + |
| 18 | + cc = DM.CableComponent("core", cg, ig) |
| 19 | + return DM.CableDesign("CAB", cc) |
| 20 | + end |
| 21 | + |
| 22 | + # Outermost radius of the last component (for placement checks) |
| 23 | + _out_radius(des) = max( |
| 24 | + des.components[end].conductor_group.radius_ext, |
| 25 | + des.components[end].insulator_group.radius_ext, |
| 26 | + ) |
| 27 | +end |
| 28 | + |
| 29 | +@testitem "DataModel(CablePosition): constructor unit tests" setup = [defaults, defs_cablepos] begin |
| 30 | + @testset "Basic construction (Float64)" begin |
| 31 | + des = _make_design_F64() |
| 32 | + rmax = _out_radius(des) |
| 33 | + pos = DM.CablePosition(des, 1.0, rmax + 0.10) # default mapping |
| 34 | + |
| 35 | + @test pos isa DM.CablePosition |
| 36 | + @test DM.eltype(pos) == Float64 |
| 37 | + @test pos.design_data === des # no promotion → same object |
| 38 | + @test pos.horz == 1.0 |
| 39 | + @test pos.vert == rmax + 0.10 |
| 40 | + @test length(pos.conn) == length(des.components) |
| 41 | + @test any(!iszero, pos.conn) # at least one non-grounded |
| 42 | + end |
| 43 | + |
| 44 | + @testset "Phase mapping (Dict-based)" begin |
| 45 | + des = _make_design_F64() |
| 46 | + rmax = _out_radius(des) |
| 47 | + |
| 48 | + # map by component id (unknown ids are rejected, missing ids default to 0) |
| 49 | + conn = Dict(des.components[1].id => 1) |
| 50 | + pos = DM.CablePosition(des, 0.0, rmax + 0.05, conn) |
| 51 | + |
| 52 | + @test pos.conn[1] == 1 |
| 53 | + @test all(i == 1 ? pos.conn[i] == 1 : pos.conn[i] == 0 for i in 1:length(pos.conn)) |
| 54 | + |
| 55 | + bad = Dict("does-not-exist" => 1) |
| 56 | + @test_throws ArgumentError DM.CablePosition(des, 0.0, rmax + 0.05, bad) |
| 57 | + end |
| 58 | + |
| 59 | + @testset "Geometry validation" begin |
| 60 | + des = _make_design_F64() |
| 61 | + rmax = _out_radius(des) |
| 62 | + |
| 63 | + # exactly at z=0 is forbidden |
| 64 | + @test_throws ArgumentError DM.CablePosition(des, 0.0, 0.0) |
| 65 | + |
| 66 | + # inside outer radius (crossing interface) is forbidden |
| 67 | + @test_throws ArgumentError DM.CablePosition(des, 0.0, rmax * 0.5) |
| 68 | + end |
| 69 | + |
| 70 | + @testset "Type stability & promotion" begin |
| 71 | + desF = _make_design_F64() |
| 72 | + rmax = _out_radius(desF) |
| 73 | + vertM = measurement(rmax + 0.10, 1e-6) |
| 74 | + |
| 75 | + posM = DM.CablePosition(desF, 0.0, vertM) |
| 76 | + |
| 77 | + @test DM.eltype(posM) <: Measurement |
| 78 | + @test DM.eltype(posM.design_data) <: Measurement # design promoted with position |
| 79 | + @test posM.vert === vertM # identity preserved |
| 80 | + @test typeof(posM.horz) <: Measurement # coerced to same scalar type |
| 81 | + @test DM.coerce_to_T(posM, DM.eltype(posM)) === posM |
| 82 | + end |
| 83 | +end |
0 commit comments