@@ -65,13 +65,13 @@ mutable struct TestsetExpr
65
65
mod:: Module # enclosing module
66
66
desc:: Union{String,Expr}
67
67
options:: Options
68
+ marks:: Marks
68
69
# loops: the original loop expression, if any, but where each `x=...` is
69
70
# pulled out into a vector
70
71
loops:: Maybe{Vector{Expr}}
71
72
parent:: Maybe{TestsetExpr}
72
73
children:: Vector{TestsetExpr}
73
74
strings:: Vector{Union{String,Missing}}
74
- marks:: Marks
75
75
# loopvalues & loopiters: when successful in evaluating loop values in resolve!,
76
76
# we "flatten" the nested for loops into a single loop, with loopvalues
77
77
# containing tuples of values, and loopiters the tuples of variables to which the
@@ -85,9 +85,8 @@ mutable struct TestsetExpr
85
85
descwidth:: Int # max width of self and children shown descriptions
86
86
body:: Expr
87
87
88
- TestsetExpr (source, mod, desc, options, loops, parent, children= TestsetExpr[]) =
89
- new (0 , source, mod, desc, options, loops, parent, children, String[],
90
- Marks ())
88
+ TestsetExpr (source, mod, desc, options, marks, loops, parent, children= TestsetExpr[]) =
89
+ new (0 , source, mod, desc, options, marks, loops, parent, children, String[])
91
90
end
92
91
93
92
isfor (ts:: TestsetExpr ) = ts. loops != = nothing
@@ -156,9 +155,16 @@ function parse_ts(source::LineNumberNode, mod::Module, args::Tuple, parent=nothi
156
155
157
156
local desc
158
157
options = Options ()
158
+ marks = Marks ()
159
+ if parent != = nothing
160
+ append! (marks. hard, parent. marks. hard) # copy! not available in Julia 1.0
161
+ end
159
162
for arg in args[1 : end - 1 ]
160
163
if arg isa String || Meta. isexpr (arg, :string )
161
164
desc = arg
165
+ elseif arg isa QuoteNode && arg. value isa Symbol
166
+ # TODO : support non-literal symbols?
167
+ push! (marks. hard, arg. value)
162
168
elseif Meta. isexpr (arg, :(= ))
163
169
arg. args[1 ] in fieldnames (Options) ||
164
170
return tserror (" unsupported @testset option" )
@@ -200,7 +206,7 @@ function parse_ts(source::LineNumberNode, mod::Module, args::Tuple, parent=nothi
200
206
return tserror (" expected begin/end block or for loop as argument to @testset" )
201
207
end
202
208
203
- ts = TestsetExpr (source, mod, desc, options, loops, parent)
209
+ ts = TestsetExpr (source, mod, desc, options, marks, loops, parent)
204
210
ts. body, ts. hasbroken = replace_ts (source, mod, tsbody, ts)
205
211
ts, false # hasbroken counts only "proper" @test_broken, not recursive ones
206
212
end
@@ -723,14 +729,15 @@ function retest(@nospecialize(args::ArgType...);
723
729
maxidw[] = id ? maxidw[] : 0
724
730
725
731
if tag isa Symbol || tag isa Not && tag. x isa Symbol
726
- tag = [tag]
727
- elseif ! (tag isa Vector{<: Union{Symbol,Not} })
728
- tag = vec (collect (Union{Symbol,Not}, tag))
732
+ tag = Pair[tag => false ]
733
+ else
734
+ tag = vec (Pair[t => false for t in tag])
735
+ # values indicate whether a warning was already issued for this tag
729
736
end
730
737
if ! dry && ! isempty (tag)
731
738
@warn " tag keyword: labels can be added only in dry mode"
732
739
end
733
- for t in tag
740
+ for (t, _) in tag
734
741
label:: Symbol = t isa Symbol ? t : t. x
735
742
startswith (String (label), ' _' ) &&
736
743
throw (ArgumentError (" tag keyword: labels can't start with an underscore" ))
@@ -1461,16 +1468,19 @@ function dryrun(mod::Module, ts::TestsetExpr, pat::Pattern, align::Int=0,
1461
1468
res = pastresult (ts. marks, subject)
1462
1469
if clear && res != = nothing
1463
1470
delmark! (ts. marks, subject, res ? _pass : _fail)
1464
- # should we set res=nothing here ? not doing it might be confusing,
1465
- # but it gives an idea about which marks are being deleted
1471
+ # TODO : should we set res=nothing here ? not doing it might be confusing,
1472
+ # but it gives an idea about which marks are being deleted;
1466
1473
end
1467
1474
if subject != = missing
1468
- for mark= tag
1475
+ for (ith, ( mark, warned)) in enumerate ( tag)
1469
1476
if ismatch
1470
1477
if mark isa Symbol
1471
1478
addmark! (ts. marks, subject, mark)
1472
1479
else
1473
- delmark! (ts. marks, subject, mark. x)
1480
+ justwarned = delmark! (ts. marks, subject, mark. x, warned)
1481
+ if justwarned > warned
1482
+ tag[ith] = mark => justwarned
1483
+ end
1474
1484
end
1475
1485
end
1476
1486
end
@@ -1562,13 +1572,12 @@ function dryrun(mod::Module, ts::TestsetExpr, pat::Pattern, align::Int=0,
1562
1572
end
1563
1573
end
1564
1574
end
1565
- beginend = TestsetExpr (ts. source, ts. mod, descx, ts. options, nothing ,
1575
+ beginend = TestsetExpr (ts. source, ts. mod, descx, ts. options, ts . marks, nothing ,
1566
1576
ts. parent, ts. children)
1567
1577
beginend. run = true
1568
1578
beginend. id = ts. id
1569
1579
beginend. iter = iter
1570
1580
ts. iter = iter # necessary when reachable is used
1571
- beginend. marks = ts. marks
1572
1581
dryrun (mod, beginend, pat, align, parentsubj; evaldesc= false ,
1573
1582
repeated= repeated, maxidw= maxidw, marks= marks, tag= tag,
1574
1583
clear= clear, show= show)
0 commit comments