github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/flush_test.go (about)

     1  // Copyright 2018 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  	"testing"
    10  	"time"
    11  
    12  	"github.com/cockroachdb/datadriven"
    13  	"github.com/cockroachdb/errors"
    14  	"github.com/cockroachdb/pebble/vfs"
    15  	"github.com/stretchr/testify/require"
    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(t *testing.T, 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 "reset":
    80  			if err := d.Close(); err != nil {
    81  				return err.Error()
    82  			}
    83  			d, err = Open("", getOptions())
    84  			if err != nil {
    85  				return err.Error()
    86  			}
    87  			return ""
    88  
    89  		default:
    90  			return fmt.Sprintf("unknown command: %s", td.Cmd)
    91  		}
    92  	})
    93  }
    94  
    95  // TestFlushDelRangeEmptyKey tests flushing a range tombstone that begins with
    96  // an empty key. The empty key is a valid key but can be confused with nil.
    97  func TestFlushDelRangeEmptyKey(t *testing.T) {
    98  	d, err := Open("", &Options{FS: vfs.NewMem()})
    99  	require.NoError(t, err)
   100  	require.NoError(t, d.DeleteRange([]byte{}, []byte("z"), nil))
   101  	require.NoError(t, d.Flush())
   102  	require.NoError(t, d.Close())
   103  }
   104  
   105  // TestFlushEmptyKey tests that flushing an empty key does not trigger that key
   106  // order invariant assertions.
   107  func TestFlushEmptyKey(t *testing.T) {
   108  	d, err := Open("", &Options{FS: vfs.NewMem()})
   109  	require.NoError(t, err)
   110  	require.NoError(t, d.Set(nil, []byte("hello"), nil))
   111  	require.NoError(t, d.Flush())
   112  	val, closer, err := d.Get(nil)
   113  	require.NoError(t, err)
   114  	require.Equal(t, val, []byte("hello"))
   115  	require.NoError(t, closer.Close())
   116  	require.NoError(t, d.Close())
   117  }