-
Notifications
You must be signed in to change notification settings - Fork 0
/
blob_test.go
154 lines (124 loc) · 3.36 KB
/
blob_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// Copyright Chrono Technologies LLC
// SPDX-License-Identifier: MIT
package arc
import (
"bytes"
"testing"
)
func TestBlobStorePut(t *testing.T) {
store := blobStore{}
tests := []struct {
value []byte
expectedBlobID blobID
expectedRefCount int
}{
{[]byte("apple"), makeBlobID([]byte("apple")), 1},
{[]byte("apple"), makeBlobID([]byte("apple")), 2},
{[]byte("apple"), makeBlobID([]byte("apple")), 3},
}
for _, test := range tests {
blobID := store.put(test.value)
if !bytes.Equal(blobID.Slice(), test.expectedBlobID.Slice()) {
t.Errorf("unexpected blobID: got:%q, want:%q", blobID, test.expectedBlobID)
}
value := store.get(blobID[:])
if !bytes.Equal(value, test.value) {
t.Errorf("unexpected blob: got:%q, want:%q", value, test.value)
}
if got := store[blobID].refCount; got != test.expectedRefCount {
t.Errorf("unexpected refCount: got:%d, want:%d", got, test.expectedRefCount)
}
}
}
func TestBlobThreshold(t *testing.T) {
arc := New()
testCases := []struct {
name string
key []byte
want []byte
}{
{"smaller than threshold", []byte("small"), []byte("small value")},
{"larger than threshold", []byte("large"), bytes.Repeat([]byte("x"), 64)},
{"exactly at the threshold", []byte("exact"), bytes.Repeat([]byte("x"), 32)},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
if err := arc.Put(tc.key, tc.want); err != nil {
t.Fatalf("unexpected put() error: %v", err)
}
got, err := arc.Get(tc.key)
if err != nil {
t.Fatalf("unexpected get() error: %v", err)
}
if !bytes.Equal(got, tc.want) {
t.Errorf("incorrect value: key:%q, got:%q, want:%q", tc.key, got, tc.want)
}
})
}
if len(arc.blobs) != 1 {
t.Errorf("unexpected blob count: got:%d, want:%d", len(arc.blobs), 1)
}
}
func TestBlobRefCountAfterPut(t *testing.T) {
testCases := []struct {
name string
keys [][]byte
value []byte
want int
}{
{
name: "with identical keys",
keys: [][]byte{[]byte("a"), []byte("a"), []byte("a"), []byte("a")},
value: blobValueX(),
want: 1,
},
{
name: "with mixed keys",
keys: [][]byte{[]byte("a"), []byte("b"), []byte("c"), []byte("d")},
value: blobValueX(),
want: 4,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
arc := New()
for _, key := range tc.keys {
arc.Put(key, tc.value)
}
blob := arc.blobs[makeBlobID(tc.value)]
if !bytes.Equal(blob.value, tc.value) {
t.Fatalf("unexpected blob value: got:%q, want:%q", blob.value, tc.value)
}
if blob.refCount != tc.want {
t.Errorf("unexpected refCount: got:%d, want:%d", blob.refCount, tc.want)
}
})
}
}
func TestBlobStoreRelease(t *testing.T) {
store := blobStore{}
value := []byte("pineapple")
refCount := 20
var blobID blobID
for i := 0; i < refCount; i++ {
blobID = store.put(value)
}
for i := refCount; i > 0; i-- {
store.release(blobID.Slice())
expectedRefCount := i - 1
if expectedRefCount == 0 {
if _, found := store[blobID]; found {
t.Error("expected blob to be removed")
}
} else {
if store[blobID].refCount != expectedRefCount {
t.Errorf("unexpected refCount: got:%d, want:%d", store[blobID].refCount, expectedRefCount)
}
}
}
// Test that the store does not panic with an unknown key.
store.release([]byte("bogus"))
if len(store) != 0 {
t.Error("store should be empty")
}
}