github.com/zuoyebang/bitalostable@v1.0.1-0.20240229032404-e3b99a834294/flush_test.go (about) 1 // Copyright 2018 The LevelDB-Go and Pebble and Bitalostored Authors. All rights reserved. Use 2 // of this source code is governed by a BSD-style license that can be found in 3 // the LICENSE file. 4 5 package bitalostable 6 7 import ( 8 "fmt" 9 "testing" 10 "time" 11 12 "github.com/cockroachdb/errors" 13 "github.com/stretchr/testify/require" 14 "github.com/zuoyebang/bitalostable/internal/datadriven" 15 "github.com/zuoyebang/bitalostable/vfs" 16 ) 17 18 func TestManualFlush(t *testing.T) { 19 getOptions := func() *Options { 20 opts := &Options{ 21 FS: vfs.NewMem(), 22 L0CompactionThreshold: 10, 23 } 24 opts.DisableAutomaticCompactions = true 25 return opts 26 } 27 d, err := Open("", getOptions()) 28 require.NoError(t, err) 29 defer func() { 30 require.NoError(t, d.Close()) 31 }() 32 33 datadriven.RunTest(t, "testdata/manual_flush", func(td *datadriven.TestData) string { 34 switch td.Cmd { 35 case "batch": 36 b := d.NewBatch() 37 if err := runBatchDefineCmd(td, b); err != nil { 38 return err.Error() 39 } 40 b.Commit(nil) 41 return "" 42 43 case "flush": 44 if err := d.Flush(); err != nil { 45 return err.Error() 46 } 47 48 d.mu.Lock() 49 s := d.mu.versions.currentVersion().String() 50 d.mu.Unlock() 51 return s 52 53 case "async-flush": 54 d.mu.Lock() 55 cur := d.mu.versions.currentVersion() 56 d.mu.Unlock() 57 58 if _, err := d.AsyncFlush(); err != nil { 59 return err.Error() 60 } 61 62 err := try(100*time.Microsecond, 20*time.Second, func() error { 63 d.mu.Lock() 64 defer d.mu.Unlock() 65 if cur == d.mu.versions.currentVersion() { 66 return errors.New("flush has not occurred") 67 } 68 return nil 69 }) 70 if err != nil { 71 return err.Error() 72 } 73 74 d.mu.Lock() 75 s := d.mu.versions.currentVersion().String() 76 d.mu.Unlock() 77 return s 78 79 case "acquire-cleaning-turn": 80 d.mu.Lock() 81 d.acquireCleaningTurn(false) 82 d.mu.Unlock() 83 return "" 84 85 case "release-cleaning-turn": 86 d.mu.Lock() 87 d.releaseCleaningTurn() 88 d.mu.Unlock() 89 return "" 90 91 case "reset": 92 if err := d.Close(); err != nil { 93 return err.Error() 94 } 95 d, err = Open("", getOptions()) 96 if err != nil { 97 return err.Error() 98 } 99 return "" 100 101 default: 102 return fmt.Sprintf("unknown command: %s", td.Cmd) 103 } 104 }) 105 } 106 107 // TestFlushDelRangeEmptyKey tests flushing a range tombstone that begins with 108 // an empty key. The empty key is a valid key but can be confused with nil. 109 func TestFlushDelRangeEmptyKey(t *testing.T) { 110 d, err := Open("", &Options{FS: vfs.NewMem()}) 111 require.NoError(t, err) 112 require.NoError(t, d.DeleteRange([]byte{}, []byte("z"), nil)) 113 require.NoError(t, d.Flush()) 114 require.NoError(t, d.Close()) 115 } 116 117 // TestFlushEmptyKey tests that flushing an empty key does not trigger that key 118 // order invariant assertions. 119 func TestFlushEmptyKey(t *testing.T) { 120 d, err := Open("", &Options{FS: vfs.NewMem()}) 121 require.NoError(t, err) 122 require.NoError(t, d.Set(nil, []byte("hello"), nil)) 123 require.NoError(t, d.Flush()) 124 val, closer, err := d.Get(nil) 125 require.NoError(t, err) 126 require.Equal(t, val, []byte("hello")) 127 require.NoError(t, closer.Close()) 128 require.NoError(t, d.Close()) 129 }