4
4
# Use of this source code is governed by an MIT-style license that can be found
5
5
# in the LICENSE.md file or at https://opensource.org/licenses/MIT.
6
6
7
+ # !!! info "COV_EXCL_LINE"
8
+ #
9
+ # The Julia coverage check is not perfect, particularly when it comes to
10
+ # macros that produce code that is not executed. To work around
11
+ # false-negatives, some lines in this file are excluded from coverage with
12
+ # `# COV_EXCL_LINE`. (In most of the excluded cases, the default is for the
13
+ # tests to pass, so the failure case of the testset macro is not executed,
14
+ # and so no code is executed that can be tied back to the excluded lines.
15
+
7
16
module Bridges
8
17
9
18
import MathOptInterface as MOI
@@ -153,15 +162,21 @@ function _test_structural_identical(
153
162
# the variables are added in the same order to both models.
154
163
a_x = MOI. get (a, MOI. ListOfVariableIndices ())
155
164
b_x = MOI. get (b, MOI. ListOfVariableIndices ())
156
- attr = MOI. NumberOfVariables ()
157
- Test. @test MOI. get (a, attr) == MOI. get (b, attr)
158
- Test. @test length (a_x) == length (b_x)
165
+ Test. @testset " Test NumberOfVariables" begin # COV_EXCL_LINE
166
+ Test. @test MOI. get (a, MOI. NumberOfVariables ()) ==
167
+ MOI. get (b, MOI. NumberOfVariables ())
168
+ end
169
+ Test. @testset " Test length ListOfVariableIndices" begin # COV_EXCL_LINE
170
+ Test. @test length (a_x) == length (b_x)
171
+ end
159
172
# A dictionary that maps things from `b`-space to `a`-space.
160
173
x_map = Dict (bx => a_x[i] for (i, bx) in enumerate (b_x))
161
174
# To check that the constraints, we need to first cache all of the
162
175
# constraints in `a`.
163
176
constraints = Dict {Any,Any} ()
164
- for (F, S) in MOI. get (a, MOI. ListOfConstraintTypesPresent ())
177
+ a_constraint_types = MOI. get (a, MOI. ListOfConstraintTypesPresent ())
178
+ b_constraint_types = MOI. get (b, MOI. ListOfConstraintTypesPresent ())
179
+ Test. @testset " get $F and $S " for (F, S) in a_constraint_types
165
180
Test. @test MOI. supports_constraint (a, F, S)
166
181
constraints[(F, S)] =
167
182
map (MOI. get (a, MOI. ListOfConstraintIndices {F,S} ())) do ci
@@ -170,20 +185,16 @@ function _test_structural_identical(
170
185
MOI. get (a, MOI. ConstraintSet (), ci),
171
186
)
172
187
end
173
- end
174
- # Now compare the constraints in `b` with the cache in `constraints`.
175
- b_constraint_types = MOI. get (b, MOI. ListOfConstraintTypesPresent ())
176
- # There may be constraint types reported in `a` that are not in `b`, but
177
- # have zero constraints in `a`.
178
- for (F, S) in keys (constraints)
179
- attr = MOI. NumberOfConstraints {F,S} ()
180
- Test. @test (F, S) in b_constraint_types || MOI. get (a, attr) == 0
181
- end
182
- for (F, S) in b_constraint_types
188
+ # There may be constraint types reported in `a` that are not in `b`, but
189
+ # have zero constraints in `a`.
190
+ Test. @test (F, S) in b_constraint_types ||
191
+ MOI. get (a, MOI. NumberOfConstraints {F,S} ()) == 0
192
+ end # COV_EXCL_LINE
193
+ Test. @testset " $F -in-$S " for (F, S) in b_constraint_types
183
194
Test. @test haskey (constraints, (F, S))
184
195
# Check that the same number of constraints are present
185
- attr = MOI. NumberOfConstraints {F,S} ()
186
- Test . @test MOI . get (a, attr) == MOI. get (b, attr )
196
+ Test . @test MOI . get (a, MOI. NumberOfConstraints {F,S} ()) ==
197
+ MOI. get (b, MOI . NumberOfConstraints {F,S} () )
187
198
# Check that supports_constraint is implemented
188
199
Test. @test MOI. supports_constraint (b, F, S)
189
200
# Check that each function in `b` matches a function in `a`
@@ -202,12 +213,14 @@ function _test_structural_identical(
202
213
return s_b == s && isapprox (f, f_b) && typeof (f) == typeof (f_b)
203
214
end
204
215
end
205
- end
216
+ end # COV_EXCL_LINE
206
217
# Test model attributes are set, like ObjectiveSense and ObjectiveFunction.
207
218
a_attrs = MOI. get (a, MOI. ListOfModelAttributesSet ())
208
219
b_attrs = MOI. get (b, MOI. ListOfModelAttributesSet ())
209
- Test. @test length (a_attrs) == length (b_attrs)
210
- for attr in b_attrs
220
+ Test. @testset " Test length ListOfModelAttributesSet" begin # COV_EXCL_LINE
221
+ Test. @test length (a_attrs) == length (b_attrs)
222
+ end
223
+ Test. @testset " $attr " for attr in b_attrs
211
224
Test. @test attr in a_attrs
212
225
if attr == MOI. ObjectiveSense ()
213
226
# map_indices isn't defined for `OptimizationSense`
@@ -216,7 +229,7 @@ function _test_structural_identical(
216
229
attr_b = MOI. Utilities. map_indices (x_map, MOI. get (b, attr))
217
230
Test. @test isapprox (MOI. get (a, attr), attr_b)
218
231
end
219
- end
232
+ end # COV_EXCL_LINE
220
233
return
221
234
end
222
235
@@ -259,7 +272,7 @@ and [`MOI.ConstraintPrimalStart`](@ref) to throw [`MOI.GetAttributeNotAllowed`](
259
272
260
273
## Example
261
274
262
- ```jldoctest; setup=:(import MathOptInterface as MOI)
275
+ ```jldoctest; setup=:(import MathOptInterface as MOI), filter=r"[0-9.]+s"
263
276
julia> MOI.Bridges.runtests(
264
277
MOI.Bridges.Constraint.ZeroOneBridge,
265
278
model -> MOI.add_constrained_variable(model, MOI.ZeroOne()),
@@ -268,9 +281,18 @@ julia> MOI.Bridges.runtests(
268
281
MOI.add_constraint(model, 1.0 * x, MOI.Interval(0.0, 1.0))
269
282
end,
270
283
)
284
+ Test Summary: | Pass Total Time
285
+ Bridges.runtests | 32 32 0.8s
271
286
```
272
287
"""
273
- function runtests (
288
+ function runtests (args... ; kwargs... )
289
+ Test. @testset " Bridges.runtests" begin
290
+ _runtests (args... ; kwargs... )
291
+ end
292
+ return
293
+ end
294
+
295
+ function _runtests (
274
296
Bridge:: Type{<:AbstractBridge} ,
275
297
input_fn:: Function ,
276
298
output_fn:: Function ;
@@ -290,50 +312,61 @@ function runtests(
290
312
if print_inner_model
291
313
print (inner)
292
314
end
293
- # Load a non-bridged input model, and check that getters are the same.
294
- test = MOI. Utilities. UniversalFallback (MOI. Utilities. Model {eltype} ())
295
- input_fn (test)
296
- _test_structural_identical (test, model; cannot_unbridge = cannot_unbridge)
297
- # Load a bridged target model, and check that getters are the same.
298
- target = MOI. Utilities. UniversalFallback (MOI. Utilities. Model {eltype} ())
299
- output_fn (target)
300
- _test_structural_identical (target, inner)
301
- # Test VariablePrimalStart
302
- attr = MOI. VariablePrimalStart ()
303
- bridge_supported = all (values (Variable. bridges (model))) do bridge
304
- return MOI. supports (model, attr, typeof (bridge))
315
+ Test. @testset " Test outer bridged model appears like the input" begin # COV_EXCL_LINE
316
+ test = MOI. Utilities. UniversalFallback (MOI. Utilities. Model {eltype} ())
317
+ input_fn (test)
318
+ _test_structural_identical (
319
+ test,
320
+ model;
321
+ cannot_unbridge = cannot_unbridge,
322
+ )
305
323
end
306
- if MOI. supports (model, attr, MOI. VariableIndex) && bridge_supported
307
- x = MOI. get (model, MOI. ListOfVariableIndices ())
308
- MOI. set (model, attr, x, fill (nothing , length (x)))
309
- Test. @test all (isnothing, MOI. get (model, attr, x))
310
- primal_start = fill (variable_start, length (x))
311
- MOI. set (model, attr, x, primal_start)
312
- if ! isempty (x)
313
- # ≈ does not work if x is empty because the return of get is Any[]
314
- Test. @test MOI. get (model, attr, x) ≈ primal_start
315
- end
324
+ Test. @testset " Test inner bridged model appears like the target" begin # COV_EXCL_LINE
325
+ target = MOI. Utilities. UniversalFallback (MOI. Utilities. Model {eltype} ())
326
+ output_fn (target)
327
+ _test_structural_identical (target, inner)
316
328
end
317
- # Test ConstraintPrimalStart and ConstraintDualStart
318
- for (F, S) in MOI. get (model, MOI. ListOfConstraintTypesPresent ())
319
- for ci in MOI. get (model, MOI. ListOfConstraintIndices {F,S} ())
320
- set = try
321
- MOI. get (model, MOI. ConstraintSet (), ci)
322
- catch err
323
- _runtests_error_handler (err, cannot_unbridge)
324
- continue
329
+ Test. @testset " Test MOI.VariablePrimalStart" begin # COV_EXCL_LINE
330
+ attr = MOI. VariablePrimalStart ()
331
+ bridge_supported = all (values (Variable. bridges (model))) do bridge
332
+ return MOI. supports (model, attr, typeof (bridge))
333
+ end
334
+ if MOI. supports (model, attr, MOI. VariableIndex) && bridge_supported
335
+ x = MOI. get (model, MOI. ListOfVariableIndices ())
336
+ MOI. set (model, attr, x, fill (nothing , length (x)))
337
+ Test. @test all (isnothing, MOI. get (model, attr, x))
338
+ primal_start = fill (variable_start, length (x))
339
+ MOI. set (model, attr, x, primal_start)
340
+ if ! isempty (x)
341
+ # ≈ does not work if x is empty because the return of get is Any[]
342
+ Test. @test MOI. get (model, attr, x) ≈ primal_start
325
343
end
326
- for attr in (MOI. ConstraintPrimalStart (), MOI. ConstraintDualStart ())
327
- if MOI. supports (model, attr, MOI. ConstraintIndex{F,S})
344
+ end
345
+ end
346
+ Test. @testset " Test ConstraintPrimalStart and ConstraintDualStart" begin # COV_EXCL_LINE
347
+ list_of_constraints = MOI. get (model, MOI. ListOfConstraintTypesPresent ())
348
+ Test. @testset " $F -in-$S " for (F, S) in list_of_constraints
349
+ for ci in MOI. get (model, MOI. ListOfConstraintIndices {F,S} ())
350
+ set = try
351
+ MOI. get (model, MOI. ConstraintSet (), ci)
352
+ catch err
353
+ _runtests_error_handler (err, cannot_unbridge)
354
+ continue
355
+ end
356
+ attrs = (MOI. ConstraintPrimalStart (), MOI. ConstraintDualStart ())
357
+ Test. @testset " $attr " for attr in attrs
358
+ if ! MOI. supports (model, attr, MOI. ConstraintIndex{F,S})
359
+ continue
360
+ end
328
361
MOI. set (model, attr, ci, nothing )
329
362
Test. @test MOI. get (model, attr, ci) === nothing
330
363
start = _fake_start (constraint_start, set)
331
364
MOI. set (model, attr, ci, start)
332
365
returned_start = try
333
366
MOI. get (model, attr, ci)
334
367
catch err
335
- # For a Constraint bridge for which the map is not invertible, the constraint primal cannot
336
- # be inverted
368
+ # For a Constraint bridge for which the map is not
369
+ # invertible, the constraint primal cannot be inverted
337
370
_runtests_error_handler (
338
371
err,
339
372
Bridge <: MOI.Bridges.Constraint.AbstractBridge &&
@@ -342,21 +375,30 @@ function runtests(
342
375
continue
343
376
end
344
377
Test. @test returned_start ≈ start
345
- end
378
+ end # COV_EXCL_LINE
346
379
end
347
- end
348
- end
349
- # Test other bridge functions
350
- for b in values (Constraint. bridges (model))
351
- _general_bridge_tests (something (b))
380
+ end # COV_EXCL_LINE
352
381
end
353
- for b in values (Objective. bridges (model))
354
- _general_bridge_tests (something (b))
382
+ Test. @testset " Test general bridge tests" begin # COV_EXCL_LINE
383
+ Test. @testset " Constraint" begin # COV_EXCL_LINE
384
+ for b in values (Constraint. bridges (model))
385
+ _general_bridge_tests (something (b))
386
+ end
387
+ end
388
+ Test. @testset " Objective" begin # COV_EXCL_LINE
389
+ for b in values (Objective. bridges (model))
390
+ _general_bridge_tests (something (b))
391
+ end
392
+ end
393
+ Test. @testset " Variable" begin # COV_EXCL_LINE
394
+ for b in values (Variable. bridges (model))
395
+ _general_bridge_tests (something (b))
396
+ end
397
+ end
355
398
end
356
- for b in values (Variable . bridges (model))
357
- _general_bridge_tests ( something (b) )
399
+ Test . @testset " Test delete " begin # COV_EXCL_LINE
400
+ _test_delete (Bridge, model, inner )
358
401
end
359
- _test_delete (Bridge, model, inner)
360
402
return
361
403
end
362
404
@@ -377,7 +419,7 @@ Run a series of tests that check the correctness of `Bridge`.
377
419
378
420
## Example
379
421
380
- ```jldoctest; setup=:(import MathOptInterface as MOI)
422
+ ```jldoctest; setup=:(import MathOptInterface as MOI), filter=r"[0-9.]+s"
381
423
julia> MOI.Bridges.runtests(
382
424
MOI.Bridges.Constraint.ZeroOneBridge,
383
425
\"\"\"
@@ -390,6 +432,8 @@ julia> MOI.Bridges.runtests(
390
432
1.0 * x in Interval(0.0, 1.0)
391
433
\"\"\" ,
392
434
)
435
+ Test Summary: | Pass Total Time
436
+ Bridges.runtests | 32 32 0.0s
393
437
```
394
438
"""
395
439
function runtests (
0 commit comments