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  }