johnsonjh/jleveldb

View on GitHub
leveldb/testutil/util.go

Summary

Maintainability
A
35 mins
Test Coverage
// Copyright © 2014, Suryandaru Triandana <syndtr@gmail.com>
// Copyright © 2021, Jeffrey H. Johnson <trnsz@pobox.com>
//
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package testutil

import (
    "bytes"
    "flag"
    "math/rand"
    "reflect"
    "sync"

    "github.com/onsi/ginkgo/config"

    "github.com/johnsonjh/jleveldb/leveldb/comparer"
)

var (
    runfn = make(map[string][]func())
    runmu sync.Mutex
)

func Defer(args ...interface{}) bool {
    var (
        group string
        fn    func()
    )
    for _, arg := range args {
        v := reflect.ValueOf(arg)
        switch v.Kind() {
        case reflect.String:
            group = v.String()
        case reflect.Func:
            r := reflect.ValueOf(&fn).Elem()
            r.Set(v)
        }
    }
    if fn != nil {
        runmu.Lock()
        runfn[group] = append(runfn[group], fn)
        runmu.Unlock()
    }
    return true
}

func RunDefer(groups ...string) bool {
    if len(groups) == 0 {
        groups = append(groups, "")
    }
    runmu.Lock()
    var runfn_ []func()
    for _, group := range groups {
        runfn_ = append(runfn_, runfn[group]...)
        delete(runfn, group)
    }
    runmu.Unlock()
    for _, fn := range runfn_ {
        fn()
    }
    return runfn_ != nil
}

func RandomSeed() int64 {
    if !flag.Parsed() {
        panic("random seed not initialized")
    }
    return config.GinkgoConfig.RandomSeed
}

func NewRand() *rand.Rand {
    return rand.New(rand.NewSource(RandomSeed()))
}

var cmp = comparer.DefaultComparer

func BytesSeparator(a, b []byte) []byte {
    if bytes.Equal(a, b) {
        return b
    }
    i, n := 0, len(a)
    if n > len(b) {
        n = len(b)
    }
    for ; i < n && (a[i] == b[i]); i++ {
    }
    x := append([]byte{}, a[:i]...)
    if i < n {
        if c := a[i] + 1; c < b[i] {
            return append(x, c)
        }
        x = append(x, a[i])
        i++
    }
    for ; i < len(a); i++ {
        if c := a[i]; c < 0xff {
            return append(x, c+1)
        } else {
            x = append(x, c)
        }
    }
    if len(b) > i && b[i] > 0 {
        return append(x, b[i]-1)
    }
    return append(x, 'x')
}

func BytesAfter(b []byte) []byte {
    var x []byte
    for _, c := range b {
        if c < 0xff {
            return append(x, c+1)
        } else {
            x = append(x, c)
        }
    }
    return append(x, 'x')
}

func RandomIndex(rnd *rand.Rand, n, round int, fn func(i int)) {
    if rnd == nil {
        rnd = NewRand()
    }
    for x := 0; x < round; x++ {
        fn(rnd.Intn(n))
    }
}

func ShuffledIndex(rnd *rand.Rand, n, round int, fn func(i int)) {
    if rnd == nil {
        rnd = NewRand()
    }
    for x := 0; x < round; x++ {
        for _, i := range rnd.Perm(n) {
            fn(i)
        }
    }
}

func RandomRange(rnd *rand.Rand, n, round int, fn func(start, limit int)) {
    if rnd == nil {
        rnd = NewRand()
    }
    for x := 0; x < round; x++ {
        start := rnd.Intn(n)
        length := 0
        if j := n - start; j > 0 {
            length = rnd.Intn(j)
        }
        fn(start, start+length)
    }
}

func Max(x, y int) int {
    if x > y {
        return x
    }
    return y
}

func Min(x, y int) int {
    if x < y {
        return x
    }
    return y
}