LCOV - code coverage report
Current view: top level - pebble/internal/randvar - flag.go (source / functions) Hit Total Coverage
Test: 2024-05-14 08:16Z 8e556e81 - meta test only.lcov Lines: 0 98 0.0 %
Date: 2024-05-14 08:17:01 Functions: 0 0 -

          Line data    Source code
       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 randvar
       6             : 
       7             : import (
       8             :         "encoding/binary"
       9             :         "regexp"
      10             :         "strconv"
      11             :         "strings"
      12             : 
      13             :         "github.com/cockroachdb/errors"
      14             :         "golang.org/x/exp/rand"
      15             : )
      16             : 
      17             : var randVarRE = regexp.MustCompile(`^(?:(latest|uniform|zipf):)?(\d+)(?:-(\d+))?$`)
      18             : 
      19             : // Flag provides a command line flag interface for specifying static random
      20             : // variables.
      21             : type Flag struct {
      22             :         Static
      23             :         spec string
      24             : }
      25             : 
      26             : // NewFlag creates a new Flag initialized with the specified spec.
      27           0 : func NewFlag(spec string) *Flag {
      28           0 :         f := &Flag{}
      29           0 :         if err := f.Set(spec); err != nil {
      30           0 :                 panic(err)
      31             :         }
      32           0 :         return f
      33             : }
      34             : 
      35           0 : func (f *Flag) String() string {
      36           0 :         return f.spec
      37           0 : }
      38             : 
      39             : // Type implements the Flag.Value interface.
      40           0 : func (f *Flag) Type() string {
      41           0 :         return "randvar"
      42           0 : }
      43             : 
      44             : // Set implements the Flag.Value interface.
      45           0 : func (f *Flag) Set(spec string) error {
      46           0 :         m := randVarRE.FindStringSubmatch(spec)
      47           0 :         if m == nil {
      48           0 :                 return errors.Errorf("invalid random var spec: %s", errors.Safe(spec))
      49           0 :         }
      50             : 
      51           0 :         min, err := strconv.Atoi(m[2])
      52           0 :         if err != nil {
      53           0 :                 return err
      54           0 :         }
      55           0 :         max := min
      56           0 :         if m[3] != "" {
      57           0 :                 max, err = strconv.Atoi(m[3])
      58           0 :                 if err != nil {
      59           0 :                         return err
      60           0 :                 }
      61             :         }
      62             : 
      63           0 :         switch strings.ToLower(m[1]) {
      64           0 :         case "", "uniform":
      65           0 :                 f.Static = NewUniform(uint64(min), uint64(max))
      66           0 :         case "latest":
      67           0 :                 f.Static, err = NewSkewedLatest(uint64(min), uint64(max), 0.99)
      68           0 :                 if err != nil {
      69           0 :                         return err
      70           0 :                 }
      71           0 :         case "zipf":
      72           0 :                 var err error
      73           0 :                 f.Static, err = NewZipf(uint64(min), uint64(max), 0.99)
      74           0 :                 if err != nil {
      75           0 :                         return err
      76           0 :                 }
      77           0 :         default:
      78           0 :                 return errors.Errorf("unknown random var distribution: %s", errors.Safe(m[1]))
      79             :         }
      80           0 :         f.spec = spec
      81           0 :         return nil
      82             : }
      83             : 
      84             : // BytesFlag provides a command line flag interface for specifying random
      85             : // bytes. The specification provides for both the length of the random bytes
      86             : // and a target compression ratio.
      87             : type BytesFlag struct {
      88             :         sizeFlag          Flag
      89             :         targetCompression float64
      90             :         spec              string
      91             : }
      92             : 
      93             : // NewBytesFlag creates a new BytesFlag initialized with the specified spec.
      94           0 : func NewBytesFlag(spec string) *BytesFlag {
      95           0 :         f := &BytesFlag{}
      96           0 :         if err := f.Set(spec); err != nil {
      97           0 :                 panic(err)
      98             :         }
      99           0 :         return f
     100             : }
     101             : 
     102           0 : func (f *BytesFlag) String() string {
     103           0 :         return f.spec
     104           0 : }
     105             : 
     106             : // Type implements the Flag.Value interface.
     107           0 : func (f *BytesFlag) Type() string {
     108           0 :         return "randbytes"
     109           0 : }
     110             : 
     111             : // Set implements the Flag.Value interface.
     112           0 : func (f *BytesFlag) Set(spec string) error {
     113           0 :         parts := strings.Split(spec, "/")
     114           0 :         if len(parts) == 0 || len(parts) > 2 {
     115           0 :                 return errors.Errorf("invalid randbytes spec: %s", errors.Safe(spec))
     116           0 :         }
     117           0 :         if err := f.sizeFlag.Set(parts[0]); err != nil {
     118           0 :                 return err
     119           0 :         }
     120           0 :         f.targetCompression = 1.0
     121           0 :         if len(parts) == 2 {
     122           0 :                 var err error
     123           0 :                 f.targetCompression, err = strconv.ParseFloat(parts[1], 64)
     124           0 :                 if err != nil {
     125           0 :                         return err
     126           0 :                 }
     127             :         }
     128           0 :         f.spec = spec
     129           0 :         return nil
     130             : }
     131             : 
     132             : // Bytes returns random bytes. The length of the random bytes comes from the
     133             : // internal sizeFlag.
     134           0 : func (f *BytesFlag) Bytes(r *rand.Rand, buf []byte) []byte {
     135           0 :         size := int(f.sizeFlag.Uint64(r))
     136           0 :         uniqueSize := int(float64(size) / f.targetCompression)
     137           0 :         if uniqueSize < 1 {
     138           0 :                 uniqueSize = 1
     139           0 :         }
     140           0 :         if cap(buf) < size {
     141           0 :                 buf = make([]byte, size)
     142           0 :         }
     143           0 :         data := buf[:size]
     144           0 :         offset := 0
     145           0 :         for offset+8 <= uniqueSize {
     146           0 :                 binary.LittleEndian.PutUint64(data[offset:], r.Uint64())
     147           0 :                 offset += 8
     148           0 :         }
     149           0 :         word := r.Uint64()
     150           0 :         for offset < uniqueSize {
     151           0 :                 data[offset] = byte(word)
     152           0 :                 word >>= 8
     153           0 :                 offset++
     154           0 :         }
     155           0 :         for offset < size {
     156           0 :                 data[offset] = data[offset-uniqueSize]
     157           0 :                 offset++
     158           0 :         }
     159           0 :         return data
     160             : }

Generated by: LCOV version 1.14