github.com/flower-corp/rosedb@v1.1.2-0.20230117132829-21dc4f7b319a/logfile/log_file_test.go (about) 1 package logfile 2 3 import ( 4 "fmt" 5 "reflect" 6 "sync/atomic" 7 "testing" 8 9 "github.com/stretchr/testify/assert" 10 ) 11 12 func TestOpenLogFile(t *testing.T) { 13 t.Run("fileio", func(t *testing.T) { 14 testOpenLogFile(t, FileIO) 15 }) 16 17 t.Run("mmap", func(t *testing.T) { 18 testOpenLogFile(t, MMap) 19 }) 20 } 21 22 func testOpenLogFile(t *testing.T, ioType IOType) { 23 type args struct { 24 path string 25 fid uint32 26 fsize int64 27 ftype FileType 28 ioType IOType 29 } 30 tests := []struct { 31 name string 32 args args 33 wantErr bool 34 }{ 35 { 36 "zero-size", args{"/tmp", 0, 0, List, ioType}, true, 37 }, 38 { 39 "normal-size", args{"/tmp", 1, 100, List, ioType}, false, 40 }, 41 { 42 "big-size", args{"/tmp", 2, 1024 << 20, List, ioType}, false, 43 }, 44 } 45 for _, tt := range tests { 46 t.Run(tt.name, func(t *testing.T) { 47 gotLf, err := OpenLogFile(tt.args.path, tt.args.fid, tt.args.fsize, tt.args.ftype, tt.args.ioType) 48 defer func() { 49 if gotLf != nil && gotLf.IoSelector != nil { 50 _ = gotLf.Delete() 51 } 52 }() 53 54 if (err != nil) != tt.wantErr { 55 t.Errorf("OpenLogFile() error = %v, wantErr %v", err, tt.wantErr) 56 return 57 } 58 if !tt.wantErr && gotLf == nil { 59 t.Errorf("OpenLogFile() gotLf =nil, want not nil") 60 } 61 }) 62 } 63 } 64 65 func TestLogFile_Write(t *testing.T) { 66 t.Run("fileio", func(t *testing.T) { 67 testLogFileWrite(t, FileIO) 68 }) 69 70 t.Run("mmap", func(t *testing.T) { 71 testLogFileWrite(t, MMap) 72 }) 73 } 74 75 func testLogFileWrite(t *testing.T, ioType IOType) { 76 lf, err := OpenLogFile("/tmp", 1, 1<<20, List, ioType) 77 assert.Nil(t, err) 78 defer func() { 79 if lf != nil { 80 _ = lf.Delete() 81 } 82 }() 83 84 type fields struct { 85 lf *LogFile 86 } 87 type args struct { 88 buf []byte 89 } 90 tests := []struct { 91 name string 92 fields fields 93 args args 94 wantErr bool 95 }{ 96 { 97 "nil", fields{lf: lf}, args{buf: nil}, false, 98 }, 99 { 100 "no-value", fields{lf: lf}, args{buf: []byte{}}, false, 101 }, 102 { 103 "normal-1", fields{lf: lf}, args{buf: []byte("lotusdb")}, false, 104 }, 105 { 106 "normal-2", fields{lf: lf}, args{buf: []byte("some data")}, false, 107 }, 108 } 109 for _, tt := range tests { 110 t.Run(tt.name, func(t *testing.T) { 111 if err := tt.fields.lf.Write(tt.args.buf); (err != nil) != tt.wantErr { 112 t.Errorf("Write() error = %v, wantErr %v", err, tt.wantErr) 113 } 114 }) 115 } 116 } 117 118 func TestLogFile_Read(t *testing.T) { 119 t.Run("fileio", func(t *testing.T) { 120 testLogFileRead(t, FileIO) 121 }) 122 123 t.Run("mmap", func(t *testing.T) { 124 testLogFileRead(t, MMap) 125 }) 126 } 127 128 func testLogFileRead(t *testing.T, ioType IOType) { 129 lf, err := OpenLogFile("/tmp", 1, 1<<20, List, ioType) 130 assert.Nil(t, err) 131 defer func() { 132 if lf != nil { 133 _ = lf.Delete() 134 } 135 }() 136 137 data := [][]byte{ 138 []byte("0"), 139 []byte("some data"), 140 []byte("some data 1"), 141 []byte("some data 2"), 142 []byte("some data 3"), 143 []byte("lotusdb"), 144 } 145 offset := writeSomeData(lf, data) 146 147 type fields struct { 148 lf *LogFile 149 } 150 type args struct { 151 offset int64 152 size uint32 153 } 154 tests := []struct { 155 name string 156 fields fields 157 args args 158 want []byte 159 wantErr bool 160 }{ 161 { 162 "read-0", fields{lf: lf}, args{offset[0], uint32(len(data[0]))}, data[0], false, 163 }, 164 { 165 "read-1", fields{lf: lf}, args{offset[1], uint32(len(data[1]))}, data[1], false, 166 }, 167 { 168 "read-2", fields{lf: lf}, args{offset[2], uint32(len(data[2]))}, data[2], false, 169 }, 170 { 171 "read-3", fields{lf: lf}, args{offset[3], uint32(len(data[3]))}, data[3], false, 172 }, 173 { 174 "read-4", fields{lf: lf}, args{offset[4], uint32(len(data[4]))}, data[4], false, 175 }, 176 { 177 "read-5", fields{lf: lf}, args{offset[5], uint32(len(data[5]))}, data[5], false, 178 }, 179 } 180 181 for _, tt := range tests { 182 t.Run(tt.name, func(t *testing.T) { 183 got, err := tt.fields.lf.Read(tt.args.offset, tt.args.size) 184 if (err != nil) != tt.wantErr { 185 t.Errorf("Read() error = %v, wantErr %v", err, tt.wantErr) 186 return 187 } 188 if !reflect.DeepEqual(got, tt.want) { 189 t.Errorf("Read() got = %v, want %v", got, tt.want) 190 } 191 }) 192 } 193 } 194 195 func writeSomeData(lf *LogFile, data [][]byte) []int64 { 196 var offset []int64 197 for _, v := range data { 198 off := atomic.LoadInt64(&lf.WriteAt) 199 offset = append(offset, off) 200 if err := lf.Write(v); err != nil { 201 panic(fmt.Sprintf("write data err.%+v", err)) 202 } 203 } 204 return offset 205 } 206 207 func TestLogFile_ReadLogEntry(t *testing.T) { 208 t.Run("fileio", func(t *testing.T) { 209 testLogFileReadLogEntry(t, FileIO) 210 }) 211 212 t.Run("mmap", func(t *testing.T) { 213 testLogFileReadLogEntry(t, MMap) 214 }) 215 } 216 217 func testLogFileReadLogEntry(t *testing.T, ioType IOType) { 218 lf, err := OpenLogFile("/tmp", 1, 1<<20, Strs, ioType) 219 assert.Nil(t, err) 220 defer func() { 221 if lf != nil { 222 _ = lf.Delete() 223 } 224 }() 225 226 // write some entries. 227 entries := []*LogEntry{ 228 {ExpiredAt: 123332, Type: 0}, 229 {ExpiredAt: 123332, Type: TypeDelete}, 230 {Key: []byte(""), Value: []byte(""), ExpiredAt: 994332343, Type: TypeDelete}, 231 {Key: []byte("k1"), Value: nil, ExpiredAt: 7844332343}, 232 {Key: nil, Value: []byte("lotusdb"), ExpiredAt: 99400542343}, 233 {Key: []byte("k2"), Value: []byte("lotusdb"), ExpiredAt: 8847333912}, 234 {Key: []byte("k3"), Value: []byte("some data"), ExpiredAt: 8847333912, Type: TypeDelete}, 235 } 236 var vals [][]byte 237 for _, e := range entries { 238 v, _ := EncodeEntry(e) 239 vals = append(vals, v) 240 } 241 offsets := writeSomeData(lf, vals) 242 243 type fields struct { 244 lf *LogFile 245 } 246 type args struct { 247 offset int64 248 } 249 tests := []struct { 250 name string 251 fields fields 252 args args 253 want *LogEntry 254 want1 int64 255 wantErr bool 256 }{ 257 { 258 "read-entry-0", fields{lf: lf}, args{offset: offsets[0]}, entries[0], int64(len(vals[0])), false, 259 }, 260 { 261 "read-entry-1", fields{lf: lf}, args{offset: offsets[1]}, entries[1], int64(len(vals[1])), false, 262 }, 263 { 264 "read-entry-2", fields{lf: lf}, args{offset: offsets[2]}, &LogEntry{ExpiredAt: 994332343, Type: TypeDelete}, int64(len(vals[2])), false, 265 }, 266 { 267 "read-entry-3", fields{lf: lf}, args{offset: offsets[3]}, &LogEntry{Key: []byte("k1"), Value: []byte{}, ExpiredAt: 7844332343}, int64(len(vals[3])), false, 268 }, 269 { 270 "read-entry-4", fields{lf: lf}, args{offset: offsets[4]}, &LogEntry{Key: []byte{}, Value: []byte("lotusdb"), ExpiredAt: 99400542343}, int64(len(vals[4])), false, 271 }, 272 { 273 "read-entry-5", fields{lf: lf}, args{offset: offsets[5]}, entries[5], int64(len(vals[5])), false, 274 }, 275 { 276 "read-entry-6", fields{lf: lf}, args{offset: offsets[6]}, entries[6], int64(len(vals[6])), false, 277 }, 278 } 279 for _, tt := range tests { 280 t.Run(tt.name, func(t *testing.T) { 281 got, got1, err := tt.fields.lf.ReadLogEntry(tt.args.offset) 282 if (err != nil) != tt.wantErr { 283 t.Errorf("ReadLogEntry() error = %v, wantErr %v", err, tt.wantErr) 284 return 285 } 286 if !reflect.DeepEqual(got, tt.want) { 287 t.Errorf("ReadLogEntry() got = %v, want %v", got, tt.want) 288 } 289 if got1 != tt.want1 { 290 t.Errorf("ReadLogEntry() got1 = %v, want %v", got1, tt.want1) 291 } 292 }) 293 } 294 } 295 296 func TestLogFile_Sync(t *testing.T) { 297 sync := func(ioType IOType) { 298 file, err := OpenLogFile("/tmp", 0, 100, Hash, ioType) 299 assert.Nil(t, err) 300 defer func() { 301 if file != nil { 302 _ = file.Delete() 303 } 304 }() 305 err = file.Sync() 306 assert.Nil(t, err) 307 } 308 309 t.Run("fileio", func(t *testing.T) { 310 sync(FileIO) 311 }) 312 313 t.Run("mmap", func(t *testing.T) { 314 sync(MMap) 315 }) 316 } 317 318 func TestLogFile_Close(t *testing.T) { 319 var fid uint32 = 0 320 321 closeLf := func(ioType IOType) { 322 file, err := OpenLogFile("/tmp", fid, 100, Sets, ioType) 323 assert.Nil(t, err) 324 325 err = file.Delete() 326 assert.Nil(t, err) 327 } 328 329 t.Run("fileio", func(t *testing.T) { 330 closeLf(FileIO) 331 }) 332 333 t.Run("mmap", func(t *testing.T) { 334 closeLf(MMap) 335 }) 336 } 337 338 func TestLogFile_Delete(t *testing.T) { 339 deleteLf := func(ioType IOType) { 340 file, err := OpenLogFile("/tmp", 0, 100, ZSet, ioType) 341 assert.Nil(t, err) 342 err = file.Delete() 343 assert.Nil(t, err) 344 } 345 346 t.Run("fileio", func(t *testing.T) { 347 deleteLf(FileIO) 348 }) 349 350 t.Run("mmap", func(t *testing.T) { 351 deleteLf(MMap) 352 }) 353 }