@@ -1004,7 +1004,6 @@ end
1004
1004
A simple fallback test set that throws immediately on a failure.
1005
1005
"""
1006
1006
struct FallbackTestSet <: AbstractTestSet end
1007
- fallback_testset = FallbackTestSet ()
1008
1007
1009
1008
struct FallbackTestSetException <: Exception
1010
1009
msg:: String
@@ -1074,9 +1073,9 @@ mutable struct DefaultTestSet <: AbstractTestSet
1074
1073
end
1075
1074
function DefaultTestSet (desc:: AbstractString ; verbose:: Bool = false , showtiming:: Bool = true , failfast:: Union{Nothing,Bool} = nothing , source = nothing )
1076
1075
if isnothing (failfast)
1077
- # pass failfast state into child testsets
1078
- parent_ts = get_testset ()
1079
- if parent_ts isa DefaultTestSet
1076
+ # pass failfast state into child testsets
1077
+ if get_testset_depth () != 0
1078
+ parent_ts = get_testset ()
1080
1079
failfast = parent_ts. failfast
1081
1080
else
1082
1081
failfast = false
@@ -1230,9 +1229,8 @@ function finish(ts::DefaultTestSet; print_results::Bool=TESTSET_PRINT_ENABLE[])
1230
1229
ts. time_end = time ()
1231
1230
# If we are a nested test set, do not print a full summary
1232
1231
# now - let the parent test set do the printing
1233
- if get_testset_depth () != 0
1234
- # Attach this test set to the parent test set
1235
- parent_ts = get_testset ()
1232
+ parent_ts = get_testset ()
1233
+ if ! (parent_ts isa FallbackTestSet)
1236
1234
record (parent_ts, ts)
1237
1235
return ts
1238
1236
end
@@ -1639,22 +1637,11 @@ function testset_context(args, ex, source)
1639
1637
else
1640
1638
error (" Malformed `let` expression is given" )
1641
1639
end
1642
- reverse! (contexts)
1643
-
1644
- test_ex = ex. args[2 ]
1645
-
1646
- ex. args[2 ] = quote
1647
- $ (map (contexts) do context
1648
- :($ push_testset ($ (ContextTestSet)($ (QuoteNode (context)), $ context; $ options... )))
1649
- end ... )
1650
- try
1651
- $ (test_ex)
1652
- finally
1653
- $ (map (_-> :($ pop_testset ()), contexts)... )
1654
- end
1640
+ test_ex = esc (ex. args[2 ])
1641
+ for context in reverse (contexts)
1642
+ test_ex = :(@with_testset (ContextTestSet ($ (QuoteNode (context)), $ (esc (context)); $ (esc (options)). .. ), $ test_ex))
1655
1643
end
1656
-
1657
- return esc (ex)
1644
+ return test_ex
1658
1645
end
1659
1646
1660
1647
"""
@@ -1672,7 +1659,7 @@ function testset_beginend_call(args, tests, source)
1672
1659
# If we're at the top level we'll default to DefaultTestSet. Otherwise
1673
1660
# default to the type of the parent testset
1674
1661
if testsettype === nothing
1675
- testsettype = :(get_testset_depth () == 0 ? DefaultTestSet : typeof (get_testset ()))
1662
+ testsettype = :(new_testset_type (get_testset ()))
1676
1663
end
1677
1664
1678
1665
# Generate a block of code that initializes a new testset, adds
@@ -1687,35 +1674,34 @@ function testset_beginend_call(args, tests, source)
1687
1674
else
1688
1675
$ (testsettype)($ desc; $ options... )
1689
1676
end
1690
- push_testset (ts)
1691
- # we reproduce the logic of guardseed, but this function
1692
- # cannot be used as it changes slightly the semantic of @testset,
1693
- # by wrapping the body in a function
1694
- local default_rng_orig = copy (default_rng ())
1695
- local tls_seed_orig = copy (Random. get_tls_seed ())
1696
- try
1697
- # default RNG is reset to its state from last `seed!()` to ease reproduce a failed test
1698
- copy! (Random. default_rng (), tls_seed_orig)
1699
- let
1700
- $ (esc (tests))
1701
- end
1702
- catch err
1703
- err isa InterruptException && rethrow ()
1704
- # something in the test block threw an error. Count that as an
1705
- # error in this test set
1706
- trigger_test_failure_break (err)
1707
- if err isa FailFastError
1708
- get_testset_depth () > 1 ? rethrow () : failfast_print ()
1709
- else
1710
- record (ts, Error (:nontest_error , Expr (:tuple ), err, Base. current_exceptions (), $ (QuoteNode (source))))
1677
+ @with_testset ts begin
1678
+ # we reproduce the logic of guardseed, but this function
1679
+ # cannot be used as it changes slightly the semantic of @testset,
1680
+ # by wrapping the body in a function
1681
+ local default_rng_orig = copy (default_rng ())
1682
+ local tls_seed_orig = copy (Random. get_tls_seed ())
1683
+ try
1684
+ # default RNG is reset to its state from last `seed!()` to ease reproduce a failed test
1685
+ copy! (Random. default_rng (), tls_seed_orig)
1686
+ let
1687
+ $ (esc (tests))
1688
+ end
1689
+ catch err
1690
+ err isa InterruptException && rethrow ()
1691
+ # something in the test block threw an error. Count that as an
1692
+ # error in this test set
1693
+ trigger_test_failure_break (err)
1694
+ if err isa FailFastError
1695
+ get_testset_depth () > 1 ? rethrow () : failfast_print ()
1696
+ else
1697
+ record (ts, Error (:nontest_error , Expr (:tuple ), err, Base. current_exceptions (), $ (QuoteNode (source))))
1698
+ end
1699
+ finally
1700
+ copy! (default_rng (), default_rng_orig)
1701
+ copy! (Random. get_tls_seed (), tls_seed_orig)
1711
1702
end
1712
- finally
1713
- copy! (default_rng (), default_rng_orig)
1714
- copy! (Random. get_tls_seed (), tls_seed_orig)
1715
- pop_testset ()
1716
- ret = finish (ts)
1717
1703
end
1718
- ret
1704
+ ts
1719
1705
end
1720
1706
# preserve outer location if possible
1721
1707
if tests isa Expr && tests. head === :block && ! isempty (tests. args) && tests. args[1 ] isa LineNumberNode
@@ -1761,7 +1747,7 @@ function testset_forloop(args, testloop, source)
1761
1747
end
1762
1748
1763
1749
if testsettype === nothing
1764
- testsettype = :(get_testset_depth () == 0 ? DefaultTestSet : typeof (get_testset ()))
1750
+ testsettype = :(new_testset_type (get_testset ()))
1765
1751
end
1766
1752
1767
1753
# Uses a similar block as for `@testset`, except that it is
@@ -1771,52 +1757,38 @@ function testset_forloop(args, testloop, source)
1771
1757
_check_testset ($ testsettype, $ (QuoteNode (testsettype. args[1 ])))
1772
1758
# Trick to handle `break` and `continue` in the test code before
1773
1759
# they can be handled properly by `finally` lowering.
1774
- if ! first_iteration
1775
- pop_testset ()
1776
- finish_errored = true
1777
- push! (arr, finish (ts))
1778
- finish_errored = false
1779
- copy! (default_rng (), tls_seed_orig)
1780
- end
1781
1760
ts = if ($ testsettype === $ DefaultTestSet) && $ (isa (source, LineNumberNode))
1782
1761
$ (testsettype)($ desc; source= $ (QuoteNode (source. file)), $ options... )
1783
1762
else
1784
1763
$ (testsettype)($ desc; $ options... )
1785
1764
end
1786
- push_testset (ts)
1787
- first_iteration = false
1788
- try
1789
- $ (esc (tests))
1790
- catch err
1791
- err isa InterruptException && rethrow ()
1792
- # Something in the test block threw an error. Count that as an
1793
- # error in this test set
1794
- trigger_test_failure_break (err)
1795
- if ! isa (err, FailFastError)
1796
- record (ts, Error (:nontest_error , Expr (:tuple ), err, Base. current_exceptions (), $ (QuoteNode (source))))
1765
+ @with_testset ts begin
1766
+ try
1767
+ # default RNG is reset to its state from last `seed!()` to ease reproduce a failed test
1768
+ copy! (Random. default_rng (), tls_seed_orig)
1769
+ $ (esc (tests))
1770
+ catch err
1771
+ err isa InterruptException && rethrow ()
1772
+ # Something in the test block threw an error. Count that as an
1773
+ # error in this test set
1774
+ trigger_test_failure_break (err)
1775
+ if ! isa (err, FailFastError)
1776
+ record (ts, Error (:nontest_error , Expr (:tuple ), err, Base. current_exceptions (), $ (QuoteNode (source))))
1777
+ end
1778
+ finally
1779
+ copy! (default_rng (), default_rng_orig)
1780
+ copy! (Random. get_tls_seed (), tls_seed_orig)
1781
+ push! (arr, ts)
1797
1782
end
1798
1783
end
1799
1784
end
1800
1785
quote
1801
1786
local arr = Vector {Any} ()
1802
- local first_iteration = true
1803
- local ts
1804
- local finish_errored = false
1805
1787
local default_rng_orig = copy (default_rng ())
1806
1788
local tls_seed_orig = copy (Random. get_tls_seed ())
1807
- copy! (Random. default_rng (), tls_seed_orig)
1808
- try
1809
- let
1810
- $ (Expr (:for , Expr (:block , [esc (v) for v in loopvars]. .. ), blk))
1811
- end
1812
- finally
1813
- # Handle `return` in test body
1814
- if ! first_iteration && ! finish_errored
1815
- pop_testset ()
1816
- push! (arr, finish (ts))
1817
- end
1818
- copy! (default_rng (), default_rng_orig)
1819
- copy! (Random. get_tls_seed (), tls_seed_orig)
1789
+ local ts
1790
+ let
1791
+ $ (Expr (:for , Expr (:block , [esc (v) for v in loopvars]. .. ), blk))
1820
1792
end
1821
1793
arr
1822
1794
end
@@ -1855,50 +1827,42 @@ end
1855
1827
# -----------------------------------------------------------------------
1856
1828
# Various helper methods for test sets
1857
1829
1830
+ const CURRENT_TESTSET = ScopedValue {AbstractTestSet} (FallbackTestSet ())
1831
+ const TESTSET_DEPTH = ScopedValue {Int} (0 )
1832
+
1833
+ macro with_testset (ts, expr)
1834
+ quote
1835
+ ts = $ (esc (ts))
1836
+ Expr (:tryfinally ,
1837
+ @with (CURRENT_TESTSET => ts, TESTSET_DEPTH => get_testset_depth () + 1 , $ (esc (expr))),
1838
+ finish (ts)
1839
+ )
1840
+ end
1841
+ end
1842
+
1858
1843
"""
1859
1844
get_testset()
1860
1845
1861
1846
Retrieve the active test set from the task's local storage. If no
1862
1847
test set is active, use the fallback default test set.
1863
1848
"""
1864
1849
function get_testset ()
1865
- testsets = get (task_local_storage (), :__BASETESTNEXT__ , AbstractTestSet[])
1866
- return isempty (testsets) ? fallback_testset : testsets[end ]
1850
+ something (Base. ScopedValues. get (CURRENT_TESTSET))
1867
1851
end
1868
1852
1869
1853
"""
1870
- push_testset(ts::AbstractTestSet )
1854
+ get_testset_depth( )
1871
1855
1872
- Adds the test set to the `task_local_storage`.
1856
+ Return the number of active test sets, not including the default test set
1873
1857
"""
1874
- function push_testset (ts:: AbstractTestSet )
1875
- testsets = get (task_local_storage (), :__BASETESTNEXT__ , AbstractTestSet[])
1876
- push! (testsets, ts)
1877
- setindex! (task_local_storage (), testsets, :__BASETESTNEXT__ )
1858
+ function get_testset_depth ()
1859
+ something (Base. ScopedValues. get (TESTSET_DEPTH))
1878
1860
end
1879
1861
1880
- """
1881
- pop_testset()
1882
1862
1883
- Pops the last test set added to the `task_local_storage`. If there are no
1884
- active test sets, returns the fallback default test set.
1885
- """
1886
- function pop_testset ()
1887
- testsets = get (task_local_storage (), :__BASETESTNEXT__ , AbstractTestSet[])
1888
- ret = isempty (testsets) ? fallback_testset : pop! (testsets)
1889
- setindex! (task_local_storage (), testsets, :__BASETESTNEXT__ )
1890
- return ret
1891
- end
1863
+ new_testset_type (:: AbstractTestSet ) = DefaultTestSet
1892
1864
1893
- """
1894
- get_testset_depth()
1895
1865
1896
- Return the number of active test sets, not including the default test set
1897
- """
1898
- function get_testset_depth ()
1899
- testsets = get (task_local_storage (), :__BASETESTNEXT__ , AbstractTestSet[])
1900
- return length (testsets)
1901
- end
1902
1866
1903
1867
_args_and_call (args... ; kwargs... ) = (args[1 : end - 1 ], kwargs, args[end ](args[1 : end - 1 ]. .. ; kwargs... ))
1904
1868
_materialize_broadcasted (f, args... ) = Broadcast. materialize (Broadcast. broadcasted (f, args... ))
0 commit comments