github.com/projecteru2/core@v0.0.0-20240321043226-06bcc1c23f58/wal/hydro_test.go (about) 1 package wal 2 3 import ( 4 "context" 5 "fmt" 6 "path" 7 "testing" 8 "time" 9 10 "github.com/projecteru2/core/wal/kv" 11 12 "github.com/stretchr/testify/assert" 13 ) 14 15 func TestLogFailedAsNoSuchHandler(t *testing.T) { 16 hydro, _ := NewHydro(path.Join(t.TempDir(), "1"), time.Second) 17 commit, err := hydro.Log("create", struct{}{}) 18 assert.Error(t, err) 19 assert.Nil(t, commit) 20 } 21 22 func TestLogFailedAsEncodeError(t *testing.T) { 23 var checked, handled, encoded, decoded bool 24 eventype := "create" 25 handler := newTestEventHandler(eventype, &checked, &handled, &encoded, &decoded) 26 handler.encode = func(interface{}) ([]byte, error) { return nil, fmt.Errorf("encode error") } 27 28 hydro, _ := NewHydro(path.Join(t.TempDir(), "1"), time.Second) 29 hydro.store = kv.NewMockedKV() 30 hydro.Register(handler) 31 32 commit, err := hydro.Log(eventype, struct{}{}) 33 assert.Error(t, err) 34 assert.Nil(t, commit) 35 assert.False(t, encoded) 36 assert.False(t, checked) 37 assert.False(t, decoded) 38 assert.False(t, handled) 39 } 40 41 func TestLogWithCommitEvent(t *testing.T) { 42 var checked, handled, encoded, decoded bool 43 eventype := "create" 44 handler := newTestEventHandler(eventype, &checked, &handled, &encoded, &decoded) 45 46 hydro, _ := NewHydro(path.Join(t.TempDir(), "1"), time.Second) 47 hydro.store = kv.NewMockedKV() 48 hydro.Register(handler) 49 50 commit, err := hydro.Log(eventype, struct{}{}) 51 assert.NoError(t, err) 52 assert.NotNil(t, commit) 53 54 assert.NoError(t, commit()) 55 assert.True(t, encoded) 56 assert.False(t, decoded) 57 assert.False(t, checked) 58 assert.False(t, handled) 59 } 60 61 func TestRecoverFailedAsNoSuchHandler(t *testing.T) { 62 var checked, handled, encoded, decoded bool 63 eventype := "create" 64 handler := newTestEventHandler(eventype, &checked, &handled, &encoded, &decoded) 65 66 hydro, _ := NewHydro(path.Join(t.TempDir(), "1"), time.Second) 67 hydro.store = kv.NewMockedKV() 68 hydro.Register(handler) 69 70 commit, err := hydro.Log(eventype, struct{}{}) 71 assert.NoError(t, err) 72 assert.NotNil(t, commit) 73 74 hydro.Del(eventype) 75 76 hydro.Recover(context.Background()) 77 assert.True(t, encoded) 78 assert.False(t, decoded) 79 assert.False(t, checked) 80 assert.False(t, handled) 81 } 82 83 func TestRecoverFailedAsCheckError(t *testing.T) { 84 var checked, handled, encoded, decoded bool 85 eventype := "create" 86 handler := newTestEventHandler(eventype, &checked, &handled, &encoded, &decoded) 87 handler.check = func(interface{}) (bool, error) { 88 checked = true 89 return false, fmt.Errorf("check error") 90 } 91 92 hydro, _ := NewHydro(path.Join(t.TempDir(), "1"), time.Second) 93 hydro.store = kv.NewMockedKV() 94 hydro.Register(handler) 95 96 commit, err := hydro.Log(eventype, struct{}{}) 97 assert.NoError(t, err) 98 assert.NotNil(t, commit) 99 100 hydro.Recover(context.Background()) 101 assert.True(t, encoded) 102 assert.True(t, decoded) 103 assert.True(t, checked) 104 assert.False(t, handled) 105 } 106 107 func TestDecodeEventFailedAsDecodeEntryError(t *testing.T) { 108 hydro, _ := NewHydro(path.Join(t.TempDir(), "1"), time.Second) 109 ent := kv.MockedScanEntry{Value: []byte("x")} 110 _, err := hydro.decodeEvent(ent) 111 assert.Error(t, err) 112 } 113 114 func TestDecodeEventFailedAsInvalidEventID(t *testing.T) { 115 hydro, _ := NewHydro(path.Join(t.TempDir(), "1"), time.Second) 116 ent := kv.MockedScanEntry{Key: "/events/x", Value: []byte("{}")} 117 _, err := hydro.decodeEvent(ent) 118 assert.Error(t, err) 119 } 120 121 func TestDecodeEventFailedAsEntryError(t *testing.T) { 122 hydro, _ := NewHydro(path.Join(t.TempDir(), "1"), time.Second) 123 expErr := fmt.Errorf("expects an error") 124 ent := kv.MockedScanEntry{Err: expErr} 125 _, err := hydro.decodeEvent(ent) 126 assert.Error(t, err) 127 assert.Equal(t, expErr.Error(), err.Error()) 128 } 129 130 func TestRecoverFailedAsDecodeLogError(t *testing.T) { 131 var checked, handled, encoded, decoded bool 132 eventype := "create" 133 handler := newTestEventHandler(eventype, &checked, &handled, &encoded, &decoded) 134 handler.decode = func([]byte) (interface{}, error) { 135 decoded = true 136 return nil, fmt.Errorf("decode error") 137 } 138 139 hydro, _ := NewHydro(path.Join(t.TempDir(), "1"), time.Second) 140 hydro.store = kv.NewMockedKV() 141 hydro.Register(handler) 142 143 commit, err := hydro.Log(eventype, struct{}{}) 144 assert.NoError(t, err) 145 assert.NotNil(t, commit) 146 147 hydro.Recover(context.Background()) 148 assert.True(t, encoded) 149 assert.True(t, decoded) 150 assert.False(t, checked) 151 assert.False(t, handled) 152 } 153 154 func TestHydroRecoverDiscardNoNeedEvent(t *testing.T) { 155 var checked, handled, encoded, decoded bool 156 check := func(interface{}) (need bool, err error) { 157 checked = true 158 return 159 } 160 161 eventype := "create" 162 handler := newTestEventHandler(eventype, &checked, &handled, &encoded, &decoded) 163 handler.check = check 164 165 hydro, _ := NewHydro(path.Join(t.TempDir(), "1"), time.Second) 166 hydro.store = kv.NewMockedKV() 167 hydro.Register(handler) 168 169 commit, err := hydro.Log(eventype, struct{}{}) 170 assert.NoError(t, err) 171 assert.NotNil(t, commit) 172 173 hydro.Recover(context.Background()) 174 assert.True(t, encoded) 175 assert.True(t, decoded) 176 assert.True(t, checked) 177 assert.False(t, handled) 178 } 179 180 func TestHydroRecover(t *testing.T) { 181 var checked, handled, encoded, decoded bool 182 eventype := "create" 183 handler := newTestEventHandler(eventype, &checked, &handled, &encoded, &decoded) 184 185 hydro, _ := NewHydro(path.Join(t.TempDir(), "1"), time.Second) 186 hydro.store = kv.NewMockedKV() 187 hydro.Register(handler) 188 189 commit, err := hydro.Log(eventype, struct{}{}) 190 assert.NoError(t, err) 191 assert.NotNil(t, commit) 192 193 hydro.Recover(context.Background()) 194 assert.True(t, encoded) 195 assert.True(t, decoded) 196 assert.True(t, checked) 197 assert.True(t, handled) 198 199 // The handled events should be removed. 200 ch, _ := hydro.store.Scan([]byte(eventPrefix)) 201 select { 202 case <-ch: 203 assert.Fail(t, "the events should be deleted") 204 default: 205 } 206 } 207 208 func TestHydroEventKeyMustPadZero(t *testing.T) { 209 event := HydroEvent{ID: 15} 210 assert.Equal(t, "/events/000000000000000f", string(event.Key())) 211 } 212 213 func TestHydroEventParseIDShouldRemovePadding(t *testing.T) { 214 id, err := parseHydroEventID([]byte("/events/00000000000000000000000000f")) 215 assert.NoError(t, err) 216 assert.Equal(t, uint64(15), id) 217 } 218 219 func TestHydroRecoverWithRealLithium(t *testing.T) { 220 p := path.Join(t.TempDir(), "temp.wal") 221 hydro, err := NewHydro(p, time.Second) 222 assert.NoError(t, err) 223 224 handler := simpleEventHandler{ 225 event: "create", 226 encode: func(interface{}) ([]byte, error) { return []byte("{}"), nil }, 227 decode: func([]byte) (interface{}, error) { return struct{}{}, nil }, 228 check: func(interface{}) (bool, error) { return true, nil }, 229 handle: func(interface{}) error { return nil }, 230 } 231 hydro.Register(handler) 232 233 hydro.Log(handler.event, struct{}{}) 234 hydro.Log(handler.event, struct{}{}) 235 hydro.Log(handler.event, struct{}{}) 236 237 hydro.Recover(context.Background()) 238 239 ch, _ := hydro.store.Scan([]byte(eventPrefix)) 240 select { 241 case <-ch: 242 assert.FailNow(t, "expects no data") 243 default: 244 } 245 } 246 247 func newTestEventHandler(eventype string, checked, handled, encoded, decoded *bool) simpleEventHandler { 248 check := func(interface{}) (bool, error) { 249 *checked = true 250 return true, nil 251 } 252 253 handle := func(interface{}) (err error) { 254 *handled = true 255 return 256 } 257 258 encode := func(interface{}) (bs []byte, err error) { 259 *encoded = true 260 return 261 } 262 263 decode := func([]byte) (item interface{}, err error) { 264 *decoded = true 265 return 266 } 267 268 return simpleEventHandler{ 269 event: eventype, 270 encode: encode, 271 decode: decode, 272 check: check, 273 handle: handle, 274 } 275 }