forked from hashicorp/raft
-
Notifications
You must be signed in to change notification settings - Fork 0
/
log_cache_test.go
148 lines (130 loc) · 2.7 KB
/
log_cache_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
package raft
import (
"errors"
"strings"
"sync"
"testing"
)
func TestLogCache(t *testing.T) {
store := NewInmemStore()
c, _ := NewLogCache(16, store)
// Insert into the in-mem store
for i := 0; i < 32; i++ {
log := &Log{Index: uint64(i) + 1}
store.StoreLog(log)
}
// Check the indexes
if idx, _ := c.FirstIndex(); idx != 1 {
t.Fatalf("bad: %d", idx)
}
if idx, _ := c.LastIndex(); idx != 32 {
t.Fatalf("bad: %d", idx)
}
// Try get log with a miss
var out Log
err := c.GetLog(1, &out)
if err != nil {
t.Fatalf("err: %v", err)
}
if out.Index != 1 {
t.Fatalf("bad: %#v", out)
}
// Store logs
l1 := &Log{Index: 33}
l2 := &Log{Index: 34}
err = c.StoreLogs([]*Log{l1, l2})
if err != nil {
t.Fatalf("err: %v", err)
}
if idx, _ := c.LastIndex(); idx != 34 {
t.Fatalf("bad: %d", idx)
}
// Check that it wrote-through
err = store.GetLog(33, &out)
if err != nil {
t.Fatalf("err: %v", err)
}
err = store.GetLog(34, &out)
if err != nil {
t.Fatalf("err: %v", err)
}
// Delete in the backend
err = store.DeleteRange(33, 34)
if err != nil {
t.Fatalf("err: %v", err)
}
// Should be in the ring buffer
err = c.GetLog(33, &out)
if err != nil {
t.Fatalf("err: %v", err)
}
err = c.GetLog(34, &out)
if err != nil {
t.Fatalf("err: %v", err)
}
// Purge the ring buffer
err = c.DeleteRange(33, 34)
if err != nil {
t.Fatalf("err: %v", err)
}
// Should not be in the ring buffer
err = c.GetLog(33, &out)
if err != ErrLogNotFound {
t.Fatalf("err: %v", err)
}
err = c.GetLog(34, &out)
if err != ErrLogNotFound {
t.Fatalf("err: %v", err)
}
}
type errorStore struct {
LogStore
mu sync.Mutex
fail bool
failed int
failMax int
}
func (e *errorStore) StoreLogs(logs []*Log) error {
e.mu.Lock()
defer e.mu.Unlock()
if e.fail {
e.failed++
if e.failed <= e.failMax {
return errors.New("some error")
}
e.fail = false
}
return e.LogStore.StoreLogs(logs)
}
func (e *errorStore) failNext(count int) {
e.mu.Lock()
e.fail = true
e.failMax = count
e.mu.Unlock()
}
func TestLogCacheWithBackendStoreError(t *testing.T) {
var err error
store := NewInmemStore()
errStore := &errorStore{LogStore: store}
c, _ := NewLogCache(16, errStore)
for i := 0; i < 4; i++ {
log := &Log{Index: uint64(i) + 1}
store.StoreLog(log)
}
errStore.failNext(1)
log := &Log{Index: 5}
err = c.StoreLog(log)
if !strings.Contains(err.Error(), "some error") {
t.Fatalf("wanted: some error, got err=%v", err)
}
var out Log
for i := 1; i < 5; i++ {
if err := c.GetLog(uint64(i), &out); err != nil {
t.Fatalf("err: %v", err)
}
}
out = Log{}
if err = c.GetLog(5, &out); err != ErrLogNotFound {
t.Fatalf("Should have returned not found, got err=%v out=%+v", err, out)
}
}