github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/cleaner_test.go (about) 1 // Copyright 2019 The LevelDB-Go and Pebble 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 pebble 6 7 import ( 8 "fmt" 9 "sort" 10 "strings" 11 "testing" 12 13 "github.com/cockroachdb/datadriven" 14 "github.com/cockroachdb/pebble/internal/base" 15 "github.com/cockroachdb/pebble/vfs" 16 "github.com/stretchr/testify/require" 17 ) 18 19 func TestCleaner(t *testing.T) { 20 dbs := make(map[string]*DB) 21 defer func() { 22 for _, db := range dbs { 23 require.NoError(t, db.Close()) 24 } 25 }() 26 27 mem := vfs.NewMem() 28 var memLog base.InMemLogger 29 fs := vfs.WithLogging(mem, memLog.Infof) 30 datadriven.RunTest(t, "testdata/cleaner", func(t *testing.T, td *datadriven.TestData) string { 31 memLog.Reset() 32 switch td.Cmd { 33 case "batch": 34 if len(td.CmdArgs) != 1 { 35 return "batch <db>" 36 } 37 d := dbs[td.CmdArgs[0].String()] 38 b := d.NewBatch() 39 if err := runBatchDefineCmd(td, b); err != nil { 40 return err.Error() 41 } 42 if err := b.Commit(Sync); err != nil { 43 return err.Error() 44 } 45 return memLog.String() 46 47 case "compact": 48 if len(td.CmdArgs) != 1 { 49 return "compact <db>" 50 } 51 d := dbs[td.CmdArgs[0].String()] 52 if err := d.Compact(nil, []byte("\xff"), false); err != nil { 53 return err.Error() 54 } 55 return memLog.String() 56 57 case "flush": 58 if len(td.CmdArgs) != 1 { 59 return "flush <db>" 60 } 61 d := dbs[td.CmdArgs[0].String()] 62 if err := d.Flush(); err != nil { 63 return err.Error() 64 } 65 return memLog.String() 66 67 case "close": 68 if len(td.CmdArgs) != 1 { 69 return "close <db>" 70 } 71 dbDir := td.CmdArgs[0].String() 72 d := dbs[dbDir] 73 if err := d.Close(); err != nil { 74 return err.Error() 75 } 76 delete(dbs, dbDir) 77 return memLog.String() 78 79 case "list": 80 if len(td.CmdArgs) != 1 { 81 return "list <dir>" 82 } 83 paths, err := mem.List(td.CmdArgs[0].String()) 84 if err != nil { 85 return err.Error() 86 } 87 sort.Strings(paths) 88 return fmt.Sprintf("%s\n", strings.Join(paths, "\n")) 89 90 case "open": 91 if len(td.CmdArgs) < 1 || len(td.CmdArgs) > 3 { 92 return "open <dir> [archive] [readonly]" 93 } 94 dir := td.CmdArgs[0].String() 95 opts := (&Options{ 96 FS: fs, 97 WALDir: dir + "_wal", 98 }).WithFSDefaults() 99 100 for i := 1; i < len(td.CmdArgs); i++ { 101 switch td.CmdArgs[i].String() { 102 case "readonly": 103 opts.ReadOnly = true 104 case "archive": 105 opts.Cleaner = ArchiveCleaner{} 106 default: 107 return "open <dir> [archive] [readonly]" 108 } 109 } 110 // Asynchronous table stats retrieval makes the output flaky. 111 opts.private.disableTableStats = true 112 opts.private.testingAlwaysWaitForCleanup = true 113 d, err := Open(dir, opts) 114 if err != nil { 115 return err.Error() 116 } 117 d.TestOnlyWaitForCleaning() 118 dbs[dir] = d 119 return memLog.String() 120 121 case "create-bogus-file": 122 if len(td.CmdArgs) != 1 { 123 return "create-bogus-file <db/file>" 124 } 125 dst, err := fs.Create(td.CmdArgs[0].String()) 126 require.NoError(t, err) 127 _, err = dst.Write([]byte("bogus data")) 128 require.NoError(t, err) 129 require.NoError(t, dst.Sync()) 130 require.NoError(t, dst.Close()) 131 return memLog.String() 132 133 default: 134 return fmt.Sprintf("unknown command: %s", td.Cmd) 135 } 136 }) 137 }