github.com/zuoyebang/bitalostable@v1.0.1-0.20240229032404-e3b99a834294/pacer_test.go (about)

     1  // Copyright 2019 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  	"bytes"
     9  	"fmt"
    10  	"strconv"
    11  	"strings"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/zuoyebang/bitalostable/internal/datadriven"
    16  )
    17  
    18  type mockPrintLimiter struct {
    19  	buf   bytes.Buffer
    20  	burst int
    21  }
    22  
    23  func (m *mockPrintLimiter) DelayN(now time.Time, n int) time.Duration {
    24  	fmt.Fprintf(&m.buf, "wait: %d\n", n)
    25  	return 0
    26  }
    27  
    28  func (m *mockPrintLimiter) AllowN(now time.Time, n int) bool {
    29  	fmt.Fprintf(&m.buf, "allow: %d\n", n)
    30  	return true
    31  }
    32  
    33  func (m *mockPrintLimiter) Burst() int {
    34  	return m.burst
    35  }
    36  
    37  func TestCompactionPacerMaybeThrottle(t *testing.T) {
    38  	datadriven.RunTest(t, "testdata/compaction_pacer_maybe_throttle",
    39  		func(d *datadriven.TestData) string {
    40  			switch d.Cmd {
    41  			case "init":
    42  				if len(d.CmdArgs) != 1 {
    43  					return fmt.Sprintf("%s expects 1 argument", d.Cmd)
    44  				}
    45  
    46  				burst := uint64(1)
    47  				var bytesIterated uint64
    48  				var slowdownThreshold uint64
    49  				var freeBytes, liveBytes, obsoleteBytes uint64
    50  				if len(d.Input) > 0 {
    51  					for _, data := range strings.Split(d.Input, "\n") {
    52  						parts := strings.Split(data, ":")
    53  						if len(parts) != 2 {
    54  							return fmt.Sprintf("malformed test:\n%s", d.Input)
    55  						}
    56  						varKey := parts[0]
    57  						varValue, err := strconv.ParseUint(strings.TrimSpace(parts[1]), 10, 64)
    58  						if err != nil {
    59  							return err.Error()
    60  						}
    61  
    62  						switch varKey {
    63  						case "burst":
    64  							burst = varValue
    65  						case "bytesIterated":
    66  							bytesIterated = varValue
    67  						case "slowdownThreshold":
    68  							slowdownThreshold = varValue
    69  						case "freeBytes":
    70  							freeBytes = varValue
    71  						case "liveBytes":
    72  							liveBytes = varValue
    73  						case "obsoleteBytes":
    74  							obsoleteBytes = varValue
    75  						default:
    76  							return fmt.Sprintf("unknown command: %s", varKey)
    77  						}
    78  					}
    79  				}
    80  
    81  				mockLimiter := mockPrintLimiter{burst: int(burst)}
    82  				switch d.CmdArgs[0].Key {
    83  				case "deletion":
    84  					getInfo := func() deletionPacerInfo {
    85  						return deletionPacerInfo{
    86  							freeBytes:     freeBytes,
    87  							liveBytes:     liveBytes,
    88  							obsoleteBytes: obsoleteBytes,
    89  						}
    90  					}
    91  					deletionPacer := newDeletionPacer(&mockLimiter, getInfo)
    92  					deletionPacer.freeSpaceThreshold = slowdownThreshold
    93  					err := deletionPacer.maybeThrottle(bytesIterated)
    94  					if err != nil {
    95  						return err.Error()
    96  					}
    97  
    98  					return mockLimiter.buf.String()
    99  				default:
   100  					return fmt.Sprintf("unknown command: %s", d.Cmd)
   101  				}
   102  
   103  			default:
   104  				return fmt.Sprintf("unknown command: %s", d.Cmd)
   105  			}
   106  		})
   107  }