|
48 | 48 | @test (model′.x, model′.y, model′.z) == (1, 4, 3) |
49 | 49 | end |
50 | 50 |
|
51 | | -@testset "cache" begin |
| 51 | +@testset "Sharing" begin |
52 | 52 | shared = [1,2,3] |
53 | 53 | m1 = Foo(shared, Foo([1,2,3], Foo(shared, [1,2,3]))) |
54 | 54 | m1f = fmap(float, m1) |
55 | 55 | @test m1f.x === m1f.y.y.x |
56 | 56 | @test m1f.x !== m1f.y.x |
57 | 57 | m1p = fmapstructure(identity, m1; prune = nothing) |
58 | 58 | @test m1p == (x = [1, 2, 3], y = (x = [1, 2, 3], y = (x = nothing, y = [1, 2, 3]))) |
| 59 | + m1no = fmap(float, m1; cache = nothing) # disable the cache by hand |
| 60 | + @test m1no.x !== m1no.y.y.x |
59 | 61 |
|
60 | | - # The cache applies only to leaf nodes, so that "4" is not shared: |
| 62 | + # Here "4" is not shared, because Foo isn't leaf: |
61 | 63 | m2 = Foo(Foo(shared, 4), Foo(shared, 4)) |
62 | 64 | @test m2.x === m2.y |
63 | 65 | m2f = fmap(float, m2) |
|
72 | 74 | @test m3p.y.x == 1:3 |
73 | 75 |
|
74 | 76 | # All-isbits trees need not create a cache at all: |
75 | | - @test isbits(fmap(float, (x=1, y=(2, 3), z=4:5))) |
76 | | - @test_skip 0 == @allocated fmap(float, (x=1, y=(2, 3), z=4:5)) |
| 77 | + m4 = (x=1, y=(2, 3), z=4:5) |
| 78 | + @test isbits(fmap(float, m4)) |
| 79 | + @test_skip 0 == @allocated fmap(float, m4) # true, but fails in tests |
| 80 | + |
| 81 | + # Shared mutable containers are preserved, even if all children are isbits: |
| 82 | + ref = Ref(1) |
| 83 | + m5 = (x = ref, y = ref, z = Ref(1)) |
| 84 | + m5f = fmap(x -> x/2, m5) |
| 85 | + @test m5f.x === m5f.y |
| 86 | + @test m5f.x !== m5f.z |
77 | 87 |
|
78 | 88 | @testset "usecache" begin |
79 | | - # Leaf types: |
80 | | - @test usecache([1,2]) |
81 | | - @test !usecache(4.0) |
82 | | - @test usecache(NoChild([1,2])) |
83 | | - @test !usecache(NoChild((3,4))) |
| 89 | + d = IdDict() |
84 | 90 |
|
85 | | - # Not leaf by default, but `exclude` can change that: |
86 | | - @test usecache(Ref(3)) |
87 | | - @test !usecache((5, 6.0)) |
88 | | - @test !usecache((a = 2pi, b = missing)) |
89 | | - |
90 | | - @test usecache((x = [1,2,3], y = 4)) |
| 91 | + # Leaf types: |
| 92 | + @test usecache(d, [1,2]) |
| 93 | + @test !usecache(d, 4.0) |
| 94 | + @test usecache(d, NoChild([1,2])) |
| 95 | + @test !usecache(d, NoChild((3,4))) |
| 96 | + |
| 97 | + # Not leaf: |
| 98 | + @test usecache(d, Ref(3)) # mutable container |
| 99 | + @test !usecache(d, (5, 6.0)) |
| 100 | + @test !usecache(d, (a = 2pi, b = missing)) |
| 101 | + |
| 102 | + @test !usecache(d, (5, [6.0]')) # contains mutable |
| 103 | + @test !usecache(d, (x = [1,2,3], y = 4)) |
| 104 | + |
| 105 | + usecache(d, OneChild3([1,2], 3, nothing)) # mutable isn't a child, do we care? |
| 106 | + |
| 107 | + # No dictionary: |
| 108 | + @test !usecache(nothing, [1,2]) |
| 109 | + @test !usecache(nothing, 3) |
91 | 110 | end |
92 | 111 | end |
93 | 112 |
|
|
0 commit comments