Repository: JuliaLang/julia
File: stdlib/Random/test/runtests.jl (Julia)

Code before:
    rng = MersenneTwister(123)
    a = (reshape(1:(4*5), 4, 5) .<= 2) # 4x5 BitMatrix whose first two elements are true, rest are false
    m = sum(1:50_000) do _
        shuffle!(rng, a)
    end/50_000 # mean result of shuffle!-ing a 50_000 times. If the shuffle! is uniform, then each index has a
    # 10% chance of having a true in it, so each value should converge to 0.1.
    @test minimum(m) >= 0.094
    @test maximum(m) <= 0.106
end

@testset "`shuffle(::NTuple)`" begin
    @testset "sorted" begin
        for n ∈ 0:20
            tup = ntuple(identity, n)
            @test tup === sort(@inferred shuffle(tup))
        end
    end
    @testset "not identity" begin
        function is_not_identity_at_least_once()
            function f(::Any)
                tup = ntuple(identity, 9)
                tup !== shuffle(tup)
            end
            @test any(f, 1:1000000)
        end
        is_not_identity_at_least_once()
    end
end

# issue #42752
# test that running finalizers that launch tasks doesn't change RNG stream
function f42752(do_gc::Bool, cell = (()->Any[[]])())
    a = rand()
    if do_gc
        finalizer(cell[1]) do _
            @async nothing
        end
        cell[1] = nothing
        GC.gc()
    end
    b = rand()
    (a, b)
end
guardseed() do
    for _ in 1:4
        Random.seed!(1)
        val = f42752(false)
        Random.seed!(1)
        @test f42752(true) === val
    end
end

Review comment (suggestion):
I'm confused... is the goal to clarify what the test ("check not identity at least once") does ? What about
```suggestion
        # shuffle should not be the identity at least once
        tup = ntuple(identity, 9)
        @test any(1:1000000) do _ 
            tup != shuffle(tup)
        end
```

Code after:
    x = rand(s) # should use precision of s
    @test precision(x) == 100
    x = BigFloat()
    @test_throws ArgumentError rand!(rng, x, s) # incompatible precision
end

@testset "shuffle! for BitArray" begin
    # Test that shuffle! is uniformly random on BitArrays
    rng = MersenneTwister(123)
    a = (reshape(1:(4*5), 4, 5) .<= 2) # 4x5 BitMatrix whose first two elements are true, rest are false
    m = sum(1:50_000) do _
        shuffle!(rng, a)
    end/50_000 # mean result of shuffle!-ing a 50_000 times. If the shuffle! is uniform, then each index has a
    # 10% chance of having a true in it, so each value should converge to 0.1.
    @test minimum(m) >= 0.094
    @test maximum(m) <= 0.106
end

@testset "`shuffle(::NTuple)`" begin
    @testset "sorted" begin
        for n ∈ 0:20
            tup = ntuple(identity, n)
            @test tup === sort(@inferred shuffle(tup))
        end
    end
    @testset "not identity" begin
        function shuffle_is_identity()
            tup = ntuple(identity, 9)
            tup === shuffle(tup)
        end
        # shuffling may behave as the identity sometimes, but if it doesn't manage to actually reorder some of the elements at least once, something is wrong
        @test any((_ -> !shuffle_is_identity()), 1:1000000)
    end
end

# issue #42752
# test that running finalizers that launch tasks doesn't change RNG stream
function f42752(do_gc::Bool, cell = (()->Any[[]])())
    a = rand()
    if do_gc
        finalizer(cell[1]) do _
            @async nothing
        end
        cell[1] = nothing
        GC.gc()
    end
    b = rand()
    (a, b)
end
guardseed() do
    for _ in 1:4