github.com/Kintar/etxt@v0.0.0-20221224033739-2fc69f000137/ecache/cache_test.go (about) 1 //go:build gtxt 2 3 package ecache 4 5 import "time" 6 import "image" 7 import "sync/atomic" 8 9 import "testing" 10 11 import "github.com/Kintar/etxt/emask" 12 13 import "golang.org/x/image/math/fixed" 14 15 func TestDefaultCache(t *testing.T) { 16 masks := make([]GlyphMask, 10) 17 18 rect := image.Rect(0, 0, 10, 10) 19 for i := 0; i < 10; i++ { 20 masks[i] = GlyphMask(image.NewAlpha(rect)) 21 masks[i].Pix[i] = 1 22 } 23 refSize := GlyphMaskByteSize(masks[0]) 24 25 cache, err := NewDefaultCache(int(refSize * 8)) 26 if err != nil { 27 panic(err) 28 } 29 30 gotSize := cache.ApproxByteSize() 31 if gotSize != 0 { 32 t.Fatalf("expected %d, got %d", 0, gotSize) 33 } 34 35 gotSize = cache.PeakSize() 36 if gotSize != 0 { 37 t.Fatalf("expected %d, got %d", 0, gotSize) 38 } 39 40 mask, found := cache.GetMask([3]uint64{0, 0, 1}) 41 if found { 42 t.Fatal("didn't expect to find mask") 43 } 44 if mask != nil { 45 t.Fatal("expected nil mask") 46 } 47 48 cache.PassMask([3]uint64{0, 0, 2}, masks[2]) 49 _, found = cache.GetMask([3]uint64{0, 0, 1}) 50 if found { 51 t.Fatal("didn't expect to find mask") 52 } 53 54 mask, found = cache.GetMask([3]uint64{0, 0, 2}) 55 if !found { 56 t.Fatal("expected to find mask") 57 } 58 if mask.Pix[2] != 1 { 59 t.Fatal("absurd test") 60 } 61 62 for i := 3; i < 10; i++ { 63 if i <= 5 { 64 time.Sleep(200 * time.Millisecond) 65 } // keep mask additions appart 66 cache.PassMask([3]uint64{0, 0, uint64(i)}, masks[i]) 67 } 68 69 for i := 3; i < 10; i++ { 70 mask, found = cache.GetMask([3]uint64{0, 0, uint64(i)}) 71 if !found { 72 t.Fatal("expected to find mask") 73 } 74 if mask.Pix[i-1] != 0 || mask.Pix[i] != 1 { 75 t.Fatal("wrong mask") 76 } 77 } 78 79 gotSize = cache.ApproxByteSize() 80 expectSize := int(refSize) * 8 81 if gotSize != expectSize { 82 t.Fatalf("expected %d, got %d", expectSize, gotSize) 83 } 84 gotSize = cache.PeakSize() 85 if gotSize != expectSize { 86 t.Fatalf("expected %d, got %d", expectSize, gotSize) 87 } 88 89 time.Sleep(200 * time.Millisecond) 90 cache.PassMask([3]uint64{0, 0, 0}, masks[0]) 91 mask, found = cache.GetMask([3]uint64{0, 0, 0}) 92 if !found { 93 t.Fatal("expected mask to be added") 94 } 95 96 mask, found = cache.GetMask([3]uint64{0, 0, 2}) 97 if found { 98 t.Fatal("expected mask to be evicted") 99 } 100 101 gotSize = cache.ApproxByteSize() 102 if gotSize != expectSize { 103 t.Fatalf("expected %d, got %d", expectSize, gotSize) 104 } 105 gotSize = cache.PeakSize() 106 if gotSize != expectSize { 107 t.Fatalf("expected %d, got %d", expectSize, gotSize) 108 } 109 110 for i := 3; i < 10; i++ { 111 mask, found = cache.GetMask([3]uint64{0, 0, uint64(i)}) 112 if !found { 113 t.Fatal("expected to find mask") 114 } 115 if mask.Pix[i-1] != 0 || mask.Pix[i] != 1 { 116 t.Fatal("wrong mask") 117 } 118 } 119 120 // cooldown for recently accessed masks 121 time.Sleep(200 * time.Millisecond) 122 123 biggerMask := GlyphMask(image.NewAlpha(image.Rect(0, 0, 12, 12))) 124 cache.PassMask([3]uint64{999, 999, 999}, biggerMask) 125 _, found = cache.GetMask([3]uint64{0, 0, 3}) 126 if found { 127 t.Fatal("expected mask to be evicted") 128 } 129 _, found = cache.GetMask([3]uint64{0, 0, 4}) 130 if found { 131 t.Fatal("expected mask to be evicted") 132 } 133 _, found = cache.GetMask([3]uint64{0, 0, 1}) 134 if found { 135 t.Fatal("this mask hasn't been ever passed to cache") 136 } 137 _, found = cache.GetMask([3]uint64{0, 0, 5}) 138 if !found { 139 t.Fatal("expected mask to be present") 140 } 141 _, found = cache.GetMask([3]uint64{0, 0, 0}) 142 if !found { 143 t.Fatal("expected mask to be present") 144 } 145 146 gotSize = cache.PeakSize() 147 if gotSize != expectSize { 148 t.Fatalf("expected %d, got %d", expectSize, gotSize) 149 } 150 expectSize = expectSize - int(refSize*2) + int(GlyphMaskByteSize(biggerMask)) 151 gotSize = cache.ApproxByteSize() 152 if gotSize != expectSize { 153 t.Fatalf("expected %d, got %d", expectSize, gotSize) 154 } 155 } 156 157 func TestDefaultHandler(t *testing.T) { 158 cache, err := NewDefaultCache(16 * 1024 * 1024) 159 if err != nil { 160 panic(err) 161 } 162 163 rast := emask.DefaultRasterizer{} 164 rast.SetHighByte(0x77) 165 166 handler := cache.NewHandler() 167 handler.NotifyFontChange(nil) 168 handler.NotifyRasterizerChange(&rast) 169 handler.NotifySizeChange(12 << 6) 170 handler.NotifyFractChange(fixed.Point26_6{1, 1}) 171 172 if handler.ApproxCacheByteSize() != 0 { 173 t.Fatal("no mask yet size != 0") 174 } 175 176 if GlyphMaskByteSize(nil) != constMaskSizeFactor { 177 t.Fatal("assumptions") 178 } 179 180 _, found := handler.GetMask(9) 181 if found { 182 t.Fatal("no mask in the cache") 183 } 184 handler.PassMask(9, nil) 185 mask, found := handler.GetMask(9) 186 if !found { 187 t.Fatal("expected mask in cache") 188 } 189 if mask != nil { 190 t.Fatal("expected nil mask") 191 } 192 193 gotSize := handler.PeakCacheSize() 194 if gotSize != constMaskSizeFactor { 195 t.Fatalf("expected %d bytes, got %d", constMaskSizeFactor, gotSize) 196 } 197 198 mask, found = cache.GetMask([3]uint64{0, 0x7700000000000000, 0x0000030000410009}) 199 if !found { 200 t.Fatal("expected mask at the given key") 201 } 202 if mask != nil { 203 t.Fatal("expected nil mask") 204 } 205 206 freed := cache.removeRandEntry(100000, CacheEntryInstant()) 207 if freed != constMaskSizeFactor { 208 t.Fatalf("expected %d freed bytes, got %d", constMaskSizeFactor, freed) 209 } 210 atomic.AddUint32(&cache.spaceBytesLeft, constMaskSizeFactor) 211 212 freed = cache.removeRandEntry(100000, CacheEntryInstant()) 213 if freed != 0 { 214 t.Fatalf("expected 0 freed bytes, got %d", freed) 215 } 216 217 gotSize = handler.ApproxCacheByteSize() 218 if gotSize != 0 { 219 t.Fatalf("expected 0 bytes, got %d", gotSize) 220 } 221 222 gotSize = handler.PeakCacheSize() 223 if gotSize != constMaskSizeFactor { 224 t.Fatalf("expected %d bytes, got %d", constMaskSizeFactor, gotSize) 225 } 226 }